Die Build-Pipeline
Die feste Phasenabfolge, die ein Projekt in eine ColdBox-Anwendung verwandelt.
On this page
Die Build-Pipeline
bxAgents build durchläuft einmal eine feste Abfolge von Phasen und erzeugt dabei eine einfache ColdBox-Anwendung. Nichts davon läuft zur Request-Zeit erneut - genau darum geht es bei der Build-Zeit-Zusammensetzung. Diese Seite geht die Phasen in exakt der Reihenfolge durch, in der BuildPipeline.bx sie ausführt.
flowchart TD
A["1 · Config auflösen<br/><small>AgentConfigResolver</small>"] --> B["2 · Discovery<br/><small>ProjectDiscoverer</small>"]
B --> C{"3 · Validierung<br/><small>ProjectValidator</small>"}
C -->|"irgendein Fehler"| X["Build wirft einen Fehler.<br/>.build/app wird nie geschrieben oder angefasst"]
C -->|"sauber<br/><small>Warnungen blockieren nie</small>"| D["4 · Generierung"]
D --> D1["1 Interceptors"] --> D2["2 Gateways"] --> D3["3 MCP"] --> D4["4 Router"]
D4 --> D5["5 Web-UI"] --> D6["6 Kern-App-Skelett"] --> D7["7 Tools/Skills kopieren"] --> D8["8 Scheduler"]
D8 --> E["5 · Normalisieren + schreiben<br/><small>ManifestNormalizer</small>"]
E --> F[".build/manifest.json<br/>+ .build/app - eine einfache ColdBox-Anwendung"]
style C fill:#fff3cd,stroke:#856404
style X fill:#f8d7da,stroke:#721c24
style F fill:#d4edda,stroke:#155724
Die Validierung ist das Tor: Sie sammelt jeden Fehler, statt beim ersten abzubrechen, und es wird nichts generiert, bevor sie sauber zurückkommt.
(Das Paketieren in eine .bxa ist ein bewusst separater Schritt - siehe Deployment & Secrets - sodass eine schnelle Schleife aus build → prüfen → erneut build nie die Kosten des Paketierens trägt, die sie nicht braucht.)
1. Config auflösen
AgentConfigResolver lädt Agent.bx, ruft configure() und die Override-Methode der aktiven Umgebung auf und merged dann tief boxlang.json/boxlang-{env}.json/miniserver.json/miniserver-{env}.json, falls vorhanden. Ergebnis ist die eine aufgelöste Konfigurationsstruktur, aus der jede spätere Phase liest.
2. Discovery
ProjectDiscoverer durchläuft das Projekt-Root und erfasst jeden Konventionsordner (models/, tools/, skills/, subagents/, gateways/, mcp/, interceptors/, modules/) als rohe { name, path, type }-Einträge. schedules/ ist die eine Ausnahme - kein Liste von Einträgen, sondern nur ein einzelnes hasScheduler/schedulerPath-Paar, da es eine echte ColdBox-Scheduler-Datei enthält statt einer Menge von BX-Agents-definierten Konfigurationseinträgen. Reine Discovery - eine Interpretation der Dateiinhalte findet hier noch nicht statt.
3. Validierung
ProjectValidator führt jeden Validator aus und sammelt jeden Fehler (nie Fail-Fast) plus alle Warnungen: doppelte Tool-/Skill-/Modell-/Subagenten-Namen, doppelte Agenten-names über den gesamten Subagenten-Baum hinweg (siehe subagents/), zirkuläre Subagenten-/Modul-Referenzen, die zwei Gateway-Eintragsformen, Vollständigkeit der Remote-MCP-Konfiguration und Gültigkeit von Modell/Provider. Wurden Fehler gesammelt, wirft der Build hier sofort einen Fehler - .build/app wird nicht geschrieben oder angefasst. Warnungen (z. B. ein schedules/-Ordner ohne Scheduler.bx darin) blockieren den Build nie.
4. Generierung
Wird nur erreicht, wenn die Validierung sauber ist. In dieser Reihenfolge:
- Interceptors -
InterceptorSplitterkopiert Interceptors mitagent-Scope nach.build/app/interceptors, solche mitruntime-Scope in ein separates Verzeichnis.build/runtime-interceptors. - Gateways -
GatewayGeneratorerzeugtaiGatewayRegistry().register(...)-Anweisungen für Channel-Adapter-Einträge und schreibt (falls welchetype: "http"sind).build/app/handlers/Gateway.bx. Ist ein Eintrag ein Push-Style-Gateway (z. B.type: "telegram"), schreibt es zusätzlich.build/app/interceptors/GatewaySessionBootstrap.bx, das eine einzige bx-ai-GatewaySession(die jedes Push-Style-Gateway bündelt) mit dem Root-Agenten des Projekts verdrahtet. - MCP -
McpGeneratorkopiert lokalemcp/*-Server nach.build/app/mcpund erzeugt derenmcpServer(...).registerTool(...)-Registrierungsanweisungen. - Router -
RouterGeneratorschreibt.build/app/config/Router.bx: eineroute(path).toAi(...)/toMCP(...)-Zeile pro Exposure-Eintrag, plus die 3 festen Gateway-Webhook-Routen, falls ein Channel-Gateway vom Typhttpexistiert. - Web-UI -
WebUiGeneratorläuft für jedenexposes: "webui"-Eintrag und schreibt das statische<path>/index.html,handlers/ChatUi.bx(die zwanzig Actions umfassende API),models/ChatDb.bx(den SQLite-Store und seine nur vorwärts laufenden Migrationen),interceptors/WebUiSchema.bx(migriert beim Start statt bei welchem Request auch immer zuerst die Datenbank berührt) und - nur wennapiKeyEnvVargesetzt ist -interceptors/WebUiAuthGate.bx. Es liefert die aufgelöste Datenbankkonfiguration zurück, die der nächste Schritt braucht. - Kern-App-Skelett -
ColdBoxAppGeneratorschreibtApplication.bx,config/ColdBox.bx,config/WireBox.bx,agent/GeneratedAgentFactory.bxundindex.bxmund flicht dabei jede zuvor gesammelte Anweisung (Gateway-Registrierungen, MCP-Registrierungen und - fallstools/Dateien enthält - einen bloßenaiToolRegistry().scan("tools")-Aufruf) inApplication.bxsonApplicationStart()ein, sowie (Phase 1sGatewaySessionBootstrap.bx, falls generiert) in dieinterceptors-Liste, auf dieconfig/ColdBox.bxverweist. Jeder generierte Agent erhält nun außerdem immer einen Checkpointer (withCheckpointer(...), standardmäßig einecache-gestützteaiMemory(), falls das Projekt keinecheckpointer-Konfiguration deklariert und die Klasse keine eigene gesetzt hat) - ohne einen solchen scheitern Human-in-the-Loop-Genehmigungsabläufe über jedes Gateway außerclivollständig.config/WireBox.bxbindet jeden Agenten im Baum (Root + jeder Subagent) unter seinem eigenen deklariertenname, nicht nur unter dem festen Root-Alias"GeneratedAgent"- siehe schedules/. Für ein Projekt mit einerwebui-Exposure aktiviert es außerdem die Session-Verwaltung, registriert die SQLite-Datenquelle (benennt sie überthis.datasourceals App-Standard), legt inonApplicationStart()das übergeordnete Verzeichnis der Datenbank an - SQLite erzeugt die Datei, aber nie den Ordner, der sie enthält - und pinnt qbs Grammatik inconfig/ColdBox.bx. - Tools/Skills kopieren -
ToolsSkillsCopierlöscht.build/app/toolsund.build/app/skillsund schreibt sie eins zu eins aus den eigenen Ordnern des Projekts neu. - Scheduler -
SchedulerGeneratorkopiertschedules/Scheduler.bx, falls vorhanden, unverändert nach.build/app/config/Scheduler.bx- keine Generierung, es ist echter ColdBox-Code, den man selbst geschrieben hat.
5. Manifest normalisieren und schreiben
ManifestNormalizer erzeugt das kanonische, hash-gestempelte interne Manifest aus den Discovery- und den aufgelösten Konfigurationsdaten, und die Pipeline schreibt es nach .build/manifest.json.
Idempotenz
Ein unverändertes Projekt neu zu bauen erzeugt eine bytegleiche Ausgabe, bis hinunter zu den Datei-Inhalts-Hashes pro Datei im Manifest - genau darum geht es dabei, die Kosten der Zusammensetzung einmal, zur Build-Zeit, zu tragen, statt einen Teil dieser Arbeit in die Request-Verarbeitung zu verschieben.