AIAgent / init_agent
Verantwortung
init_agent ist die «Aufbauwerkstatt» des Agenten: Provider (provider), Toolsets (toolsets), Kompressionsschwellen (compression thresholds), Custom-Provider-extra_body, Gedächtnis- und Lernkomponenten werden in die Agent-Instanz injiziert, sodass sie alle Abhängigkeiten besitzt, um eine Dialogrunde (turn) zu drehen. Die AIAgent-Klasse selbst ist nur die dünne Hülle über diesem Produkt.
Designmotiv
Konfiguration und Runtime zu trennen, hält den Codepfad für «eine Dialogrunde drehen» so zustandslos wie möglich. init_agent macht einmalig alle Start-Entscheidungen fest (Provider-Wahl, Kompressionsstrategie, Toolset-Schalter, extra_body-Merge); danach tritt run_conversation in den Rhythmus «Nachricht füttern → Schleife drehen» ein, ohne die Konfiguration nochmal anzufassen. Direkter Gewinn: run_conversation darf gefahrlos parallel laufen — wird dieselbe Agent-Instanz von mehreren eingehenden Nachrichten gleichzeitig angetrieben, gibt es kein «Konfiguration wird gerade geändert»-Race.
Dass die Kompressionsschwelle zur Startzeit aufgelöst wird statt erst beim Kompressionstrigger, hat einen zweiten Grund: Die 272K-Fenster der Codex-gpt-5.x-Familie brauchen eine «automatisch angehobene» Schwelle, um das Fenster voll zu nutzen — und diese Anhebung will man dem Nutzer einmal mitteilen. Zur Laufzeit jedes Mal berechnet, würde die Mitteilung entweder dauernd wiederholt oder vergessen. Startzeit einmal berechnet, Marker-Datei schreiben, später nur noch den Marker lesen.
Schlüsseldateien
class AIAgent:400-497— Klassendefinition, Felder = Konfiguration__init__ Weiterleitung:497-560—from agent.agent_init import init_agent; init_agent(...)def init_agent:276— Assembly-HauptfunktionseinstiegCustom-Provider-extra_body-Hilfe:183-275—_normalized_custom_base_url/_custom_provider_model_matches/_merge_custom_provider_extra_body_resolve_compression_threshold:93-127— Auflösung der KompressionsschwelleHilfsfunktionen-Bereich:62-91—_ra, Autoraise-Hinweis usw.
Datenfluss
AIAgent.__init__(run_agent.py:423) sammelt die Konstruktionsparameter unverändert.- Aufruf von
init_agent:276, nacheinander:- Provider-Name und base_url auflösen (
agent/agent_init.py:183) extra_bodydes Custom-Providers mergen (agent/agent_init.py:257)- Kompressionsschwelle auflösen (
agent/agent_init.py:93) - Toolsets, Memory-Manager, Lern-Graph usw. injizieren
- Provider-Name und base_url auflösen (
- Der fertige Agent stellt die Methode
run_conversation(run_agent.py:6350) zur Verfügung, die an die modulweiteagent/conversation_loop.py:588weiterleitet. - Das Gateway (gateway)
GatewayRunner(gateway/run.py:3029) hält den zusammengebauten Agenten und übergeben ihm eingehende Nachrichten.
Der Provider-Name wird in init_agent auf Kleinbuchstaben normalisiert, Whitespace abgeschnitten; provider dient sowohl als Routing-Hinweis als auch als Basis für den api_mode-Schluss:
agent.base_url = base_url or ""
provider_name = provider.strip().lower() if isinstance(provider, str) and provider.strip() else None
agent.provider = provider_name or ""
...
if api_mode in {"chat_completions", "codex_responses", "anthropic_messages", "bedrock_converse", "codex_app_server"}:
agent.api_mode = api_mode
elif agent.provider == "openai-codex":
agent.api_mode = "codex_responses"
elif agent.provider in {"xai", "xai-oauth"}:
agent.api_mode = "codex_responses"Die Auflösung der Kompressionsschwelle liegt in _resolve_compression_threshold. Codex-Autoraise ist einseitig — sie kann die Schwelle nur anheben, nicht senken, was der Nutzer bereits höher gesetzt hat:
if model_cthresh is None:
return global_threshold, None
if is_codex_autoraise:
if model_cthresh <= global_threshold + 1e-9:
# Autoraise never lowers; keep the user's higher/equal threshold.
return global_threshold, None
return model_cthresh, {
"model": model,
"from": global_threshold,
"to": model_cthresh,
}
return model_cthresh, NoneDer Merge des extra_body für Custom-Provider matcht konfigurierte Einträge an base_url + model und merged extra_body in request_overrides; bereits vorhandene Schlüssel des Nutzers haben Vorrang:
merged_extra_body = dict(extra_body)
existing_extra_body = overrides.get("extra_body")
if isinstance(existing_extra_body, dict):
merged_extra_body.update(existing_extra_body)
overrides["extra_body"] = merged_extra_body
agent.request_overrides = overridesDie Richtung von update ist «extra_body aus der Konfiguration als Boden, darüber der bereits vorhandene extra_body des Nutzers» — zur Laufzeit in request_overrides["extra_body"] gesteckte Felder werden nicht von der Startkonfiguration überschrieben.
Grenzen und Fehler
- Provider-Name lässt sich nicht zu
api_modeauflösen: Gibt der Nutzerprovider="foobar"an, wirdapi_modenicht geschlossen und fällt auf den Standard-Pfadchat_completions. Unterstütztfoobartatsächlich nurcodex_responses, kommt bei der ersten Nachricht eine 400.init_agentvalidiert nicht, ob der Provider auf einer Whitelist steht; es normalisiert nur Groß-/Kleinschreibung. - Custom-
extra_body-Merge-Konflikt: Sind für dieselbe base_url mehrere Einträge konfiguriert und matchen alle dasselbe Modell, gewinnt in_custom_provider_extra_body_for_agentder «erste mit explizitem Modell-Match»; die folgenden werden ignoriert. Ein Eintrag ohnemodel-Feld gilt als Fallback (fallback) und greift nur, wenn kein expliziter Modell-Match vorhanden ist. Hat der Nutzer die Konfiguration geändert, ohne den Agenten neu zu starten, denkt er, das neueextra_bodysei aktiv, aber tatsächlich läuft noch der alte Fallback. - Kompressionsschwelle mit unzulässigem Wert: Ist
global_thresholdNoneoder negativ, macht_resolve_compression_thresholdkeine Bereichsvalidierung und reicht den Wert durch. Negativ schaltet die Kompression dauerhaft ab;Nonewirft beim Vergleich einenTypeError. Die Konfigurationsschicht (hermes config) hat eine Bereichsprüfung, aberinit_agentvalidiert nicht doppelt, sondern vertraut dem Konfigurationsprodukt. - Autoraise-Marker schreiben fehlgeschlagen: Ist
$HERMES_HOMEread-only oder die Platte voll, überspringt_record_codex_gpt55_autoraise_noticestillschweigend; der Preis ist, dass beim nächsten init die Mitteilung nochmal erscheint. Das ist ein bewusster Trade-off: Ein gescheiterter Marker-Schreiben darf den Agenten nicht am Start hindern. - Lazy Import von
_ra(): Hilfsfunktionen ininit_agentholen dasrun_agent-Modul über_ra()statt über einen Top-Level-Import, damit Testsrun_agent.OpenAIund andere Attribute monkeypatchen können, bevor sieinit_agentaufrufen. Kosten: ein zusätzlicher Import beim ersten Aufruf; ist der Patch-Zeitpunkt zu spät, sind bereits gebundene Attribute nicht mehr durch den neuen Patch überdeckt.
Zusammenfassung
init_agent ist die Übersetzungsschicht von Konfiguration → Runtime; alle Start-Entscheidungen (Provider-Wahl, Kompressionsstrategie, Toolset-Schalter) fallen hier einmalig. Danach tritt der Agent in den zustandslosen Rhythmus «Nachricht füttern → Schleife drehen» ein, ohne die Konfiguration weiter zu verändern.