Agent.bx

Die eine erforderliche Datei - eine Klasse, die bx-ais eigenes AiAgent erweitert, sodass sie DER Agent IST.

On this page

Agent.bx

Agent.bx ist die einzige erforderliche Datei in einem BX-Agents-Projekt. Sie erweitert bx-ais eigenes AiAgent, sie ist also der Agent - der Build instanziiert sie, statt eine aus einer Konfigurationsstruktur neu aufzubauen, sodass das, was geschrieben wird, auch läuft. Erben und hinzufügen, was gebraucht wird: private Hilfsmethoden, überschriebene Methoden, im Code registrierte Tools. Weil es sich um eine echte Klasse statt um einen struct-zurückgebenden Deskriptor handelt, kann eine IDE sie wie jede andere BoxLang-Klasse introspizieren - Sprung zur Definition, Autovervollständigung auf geerbten Methoden, alles.

class extends="bxModules.bxai.models.runnables.AiAgent" {

	function init() {
		super.init(
			name        : "my-agent",
			description : "A helpful assistant",
			instructions: "You are a helpful assistant.",
			model       : aiModel( provider: "openai", params: { model: "gpt-5" } )
		)
		return this
	}

}

bxAgents new erzeugt genau diese Form als Gerüst. instructions.md ist optional - instructions direkt in super.init() setzen, oder die Datei neben Agent.bx ablegen und sie vom Build einbinden lassen (siehe Tabelle unten).

Was der Build über die Klasse legt

Die Regel: eine explizit deklarierte Konvention gewinnt; ansonsten hat die Klasse das letzte Wort.

Ein Agent, der alles in seiner eigenen init() setzt, bekommt also nichts aufgezwungen, während einer, der nur das Minimum setzt, trotzdem die Konventionen übernimmt, für die er nichts erklärt hat. Alles Folgende ist optional - eine configure() deklarieren, die einen dieser Schlüssel zurückgibt, um zu überschreiben, was die Klasse selbst gesetzt hat, oder den passenden Konventionsordner instructions.md/tools//subagents/:

Was deklariert wirdWas der Build erzeugtWenn nicht deklariert
instructions.mdwithInstructions( fileRead( ... ) )die eigenen Instruktionen der Klasse bleiben bestehen
model in configure()setModel( aiModel( ... ) )das eigene Modell der Klasse bleibt bestehen
name / description in configure()setName() / setDescription()die eigenen Werte der Klasse bleiben bestehen
memory in configure()setMemory( ... )der eigene Wert der Klasse bleibt bestehen
(nichts zu deklarieren)withTools( aiToolRegistry().getAll() )immer - withTools() hängt an in bx-ai statt zu ersetzen, sodass von der Klasse selbst registrierte Tools erhalten bleiben und die entdeckten tools/ hinzugefügt werden
subAgents an der Klasse, oder subagents/ auf der PlatteaddSubAgent( ... ) pro Kindwird auf dieselbe Weise angehängt
checkpointer in configure()withCheckpointer( ... )wird trotzdem eingesetzt, falls die Klasse keinen gesetzt hat - siehe unten
Info

Der Checkpointer ist das Einzige, das der Build ungefragt einsetzt. Ein von einem Gateway aus erreichbarer Agent ohne Checkpointer hat stillschweigend kaputtes Human-in-the-Loop, also erhält eine Klasse, die keinen gesetzt hat, trotzdem den cache-Standard. Eine Klasse, die einen eigenen setzt, wird unangetastet gelassen.

Warning

Bewusst nicht implementiert durch den Vergleich der eigenen Instanz mit bx-ais DEFAULT_AGENT_*-Werten. "Wollte die Autorin das so, oder ist das nur der Standardwert?" ist unbeantwortbar, und eine Autorin, die tatsächlich den Standardnamen wollte, würde ihn stillschweigend ersetzt vorfinden. Das Vorhandensein einer externen Deklaration ist eine Tatsache; die Absicht hinter einem Standardwert ist es nicht.

Die Klasse wird in die generierte App nach agent/classes/ kopiert und dort über ihren eigenen absoluten Dateipfad instanziiert (nie eine relative Lookup, die von einer registrierten Zuordnung abhängen würde), genau wie tools/, skills/ und mcp/ kopiert werden - sodass eine paketierte .bxa sie mitführt, und chat/invoke/serve sie alle auf dieselbe Weise instanziieren, egal ob ein echter ColdBox-Container bootet oder nicht.

configure() (optional) - überschreibt, was die Klasse gesetzt hat

Eine configure()-Methode ist vollständig optional. Sie nur deklarieren, um bestimmte Felder von außerhalb der Klasse zu überschreiben - nützlich, um deploymentspezifische Werte (z. B. ein anderes Modell pro Umgebung) aus dem Klassenkörper selbst herauszuhalten:

class extends="bxModules.bxai.models.runnables.AiAgent" {

	function init() {
		super.init(
			name  : "with-mcp-servers-agent",
			model : aiModel( provider: "openai", params: { model: "gpt-5" } )
		)
		return this
	}

	function configure() {
		return {
			mcpServers : [
				"https://example.com/mcp",
				{ url : "https://other.com/mcp", name : "other" }
			]
		};
	}

}
FeldTypHinweise
namestringWird zur Build-Zeit auch zum Bindungsschlüssel dieses Agenten in config/WireBox.bx (getInstance( name )) - siehe schedules/ - muss also im gesamten Projekt eindeutig sein (Root + jeder Subagent); build schlägt fehl, falls zwei Agenten sich einen Namen teilen.
modelstringEin provider/model-Slug, ein bloßer Provider-Name, oder ein Name, der zu einem models/-Eintrag passt. Siehe unten.
descriptionstringOptional.
subAgentsarray of stringsNamen von Geschwister-Ordnern unter dem subagents/ des Root-Projekts. Siehe subagents/.
mcpServersarrayRemote-MCP-Server - jeder Eintrag ein URL-String oder { url, name }. Siehe mcp/.
securitystructWird unverändert in die bxai-Moduleinstellungen der generierten App weitergereicht; bx-ais eigener SecurityDirector macht daraus Guardrail-Middleware. Nur Durchreichung - BX Agents hat keine eigene Guardrails-Konvention.
memorystring oder structDas Konversationsgedächtnis des Agenten. Ein bloßer String ist eine Kurzform für den Typ ("cache"); eine Struktur ist { type, ...config } und wird unverändert an aiMemory() weitergereicht - z. B. { type: "cache", maxMessages: 50 }, oder mit summaryProvider/summaryModel/summaryThreshold, damit /compact in der Web-UI funktioniert. Gilt pro Knoten, ein Subagent kann also einen eigenen deklarieren.
checkpointerstruct{ type: "cache"\|"file"\|"jdbc", ...config }. Fällt bei Weglassen auf { type: "cache" } zurück. Immer angewendet - ohne einen scheitern Human-in-the-Loop-Genehmigungsabläufe über jedes Gateway außer cli vollständig.
gatewaySessionstruct{ policy, maxQueueDepth }, beide optional (Standard "queue" / 50). Nur relevant, falls das Projekt mindestens einen Push-Style-Gateway-Eintrag hat - steuert die Richtlinie der generierten GatewaySession für eine zweite eingehende Nachricht, die auf einem Thread eintrifft, auf dem bereits ein Turn läuft. policy muss reject/queue/steer/interrupt sein.
jeder andere SchlüsselanyWird gemergt und ist in der aufgelösten Konfigurationsstruktur verfügbar, wird aber von BX Agents selbst nicht interpretiert.

The model slug

model ist BX Agents' eigene Konvention - bx-ai selbst nimmt provider und model als zwei separate Argumente an aiModel(). BX Agents teilt den Slug nur am ersten /, sodass ein Provider, der selbst einen Schrägstrich enthält (wie OpenRouters openrouter/anthropic/claude-x), trotzdem korrekt geparst wird:

model-Wertprovidermodel
openai/gpt-5openaigpt-5
openrouter/anthropic/claude-xopenrouteranthropic/claude-x
mock/mock-modelmockmock-model

Hat model überhaupt keinen /, muss es entweder ein bekannter Core-Provider-Name sein oder zum Namen eines models/-Eintrags passen - die Validierung lehnt alles andere ab. Die erkannten Core-Provider sind: bedrock, claude, cohere, deepseek, docker, elevenlabs, gemini, grok, groq, huggingface, minimax, mistral, mock, ollama, openai, openai-compatible, openrouter, perplexity, voyage (mit bx-ais eigenem CORE_PROVIDERS synchron gehalten). mock ist ein echter Provider, nützlich für Tests und CI - er macht nie einen Netzwerkaufruf.

Diese Slug-Aufteilungskonvention durchläuft ein per configure() deklarierter model-String - super.init()s eigenes model-Argument nimmt hingegen direkt eine echte AiModel-Instanz (aiModel( provider: "...", params: { model: "..." } )), da die Klasse bereits bx-ais eigene API spricht.

Umgebungs-Overrides

Agent.bx kann eine nach einer Umgebung benannte Methode deklarieren (z. B. production(), development(), oder ein beliebiger eigener Name), die eine Struktur von Overrides zurückgibt - das funktioniert unabhängig davon, ob die Klasse auch eine configure() deklariert:

class extends="bxModules.bxai.models.runnables.AiAgent" {

	function init() {
		super.init(
			name        : "override-agent",
			description : "An agent with an environment override",
			model       : aiModel( provider: "openai", params: { model: "gpt-5" } )
		)
		return this
	}

	function production() {
		return {
			model : "openai/gpt-5-mini"
		};
	}

}

Die aktive Umgebung wird nach dieser Rangfolge aufgelöst (höchste gewinnt):

  1. --environment-CLI-Flag (bxAgents build --environment=production)
  2. Umgebungsvariable BX_AGENTS_ENV
  3. "development" (Standard)

Das ist eine reine Build-Zeit-Entscheidung, unabhängig von ColdBoxs eigener Laufzeit-Umgebungserkennung (die generierte App liest getSetting("environment") selbst, gemäß ColdBoxs environments-Konvention) - diese Rangfolge entscheidet nur, welche environment()-Override-Methode an Agent.bx, und welche boxlang-{env}.json/miniserver-{env}.json-Dateien, die Build-Pipeline anwendet.

Existiert keine zur aktiven Umgebung passende Methode, wird kein Override angewendet.

Merge-Semantik

Die vollständige Auflösungsreihenfolge (niedrigste zu höchste Priorität) ist:

  1. configure() (optional)
  2. die passende Umgebungs-Override-Methode, falls vorhanden
  3. boxlang.json
  4. boxlang-{environment}.json
  5. miniserver.json
  6. miniserver-{environment}.json

Struct-Schlüssel werden rekursiv gemergt - eine verschachtelte Struktur aus einer höher priorisierten Quelle überschreibt nur die Schlüssel, die sie tatsächlich setzt, und lässt Geschwisterschlüssel aus einer niedriger priorisierten Quelle unangetastet. Arrays und alle skalaren Werte werden vollständig ersetzt, nie angehängt oder verkettet.

boxlang.json/boxlang-{env}.json/miniserver.json/miniserver-{env}.json sind allesamt optionale JSON-Dateien im Projekt-Root, nützlich für Konfiguration, die sich leichter als Daten denn als BoxLang-Code ausdrücken lässt (z. B. Modell-Standardwerte):

// boxlang.json
{
	"modelDefaults": { "temperature": 0.7, "maxTokens": 1000 }
}
// boxlang-production.json
{
	"modelDefaults": { "temperature": 0.2 }
}

Ein Build mit --environment=production ergibt hier modelDefaults: { temperature: 0.2, maxTokens: 1000 } - das rekursive Merge behielt maxTokens aus der Basisdatei, da boxlang-production.json es nie erwähnte.

Warning

Secrets (API-Schlüssel, Tokens) werden von BX Agents zur Build-Zeit nie gelesen oder gemergt - sie bleiben extern (eine OS-Umgebungsvariable, .env, ein Plattform-Secret-Manager) und werden von bx-ai selbst live zur Laufzeit aufgelöst. Siehe Deployment & Secrets.

Edit this page Download Markdown Last updated Aug 21, 2026, 6:33:28 PM