Hauptagent → (session_id, None)
Der Hauptagent trägt kein agent_id-Feld. Genau diese Abwesenheit macht ihn erkennbar — er bekommt seine eigene Top-Lane.
agent-observatory ist ein Echtzeit-Kontrollraum für Claude-Code-Sessions und ihre Subagenten. Hook-Events laufen über einen lokalen FastAPI-Server in SQLite und erscheinen im Browser als Live-Swimlanes — eine Spur pro Session, eine pro Subagent, jeder Tool-Aufruf ein eigener Chip. Was vorher nur in fragmentierten Terminal-Logs sichtbar war, wird zum nachvollziehbaren, replaybaren Ereignisstrom.
agent-observatory — Live-Kontrollraum für Multi-Agent-Sessions.
Für die Rolle: belegt Observability- und Tooling-Engineering für Multi-Agent-Systeme — eine vollständige Event-Pipeline (Hook-Capture → Ingest → Persistenz → Live-Visualisierung), gebaut stdlib-nah und fail-soft, damit das Beobachten den beobachteten Agenten nie ausbremst. Relevant für AI-Infrastruktur-, Developer-Tooling- und Observability-Rollen.
Reine Lab-Arbeit, lokal. Der Code läuft nur auf 127.0.0.1 — kein öffentliches Repository, keine Live-URL. Mechanik und Stand sind hier dokumentiert, ein Walkthrough ist auf Anfrage möglich.
Subagenten und Hook-Aktivität tauchen normalerweise nur verstreut in Terminal-Logs auf: man sieht, dass etwas passiert, aber nicht das Wer/Wann/Womit als zusammenhängenden Strom. Erfasst werden die ohnehin gefeuerten Hook-Typen — PreToolUse, PostToolUse, SubagentStop, UserPromptSubmit, Stop und SessionStart.
agent-observatory baut daraus einen einzigen lokalen Ereignisstrom: welche Session welches Tool nutzte, welche Subagenten parallel liefen, wann ein Aufruf begann und endete. Eine Lane je Session bzw. Subagent, und alles wird persistiert — für eine spätere Analyse oder einen Replay.
Und ehrlich eingeordnet: das Ganze ist bewusst klein und lokal gehalten. Kein externer Dienst, kein Deployment — ein Diagnose- und Erzählwerkzeug, das Agentenarbeit aus der Black Box holt, nicht ein Produkt.
So sieht ein Lauf aus: oben die Hauptsession, darunter die Subagenten — auf jeder Spur laufen Tool-Chips zeitlich versetzt ein. Ein Chip pulsiert, solange der Aufruf läuft (PreToolUse), und schließt, sobald er fertig ist (PostToolUse). Die Demo unten nutzt ausschließlich synthetische, anonymisierte Events.
Rein synthetische, anonymisierte Events · keine echten Hook-Daten, IDs redigiert · Chips zeigen nur Tool-Namen
Bewusst klein und lokal: ein stdlib-only Hook-Sender liest die Payload von stdin, kürzt sie, leitet die Lane ab und schickt sie per HTTP an einen FastAPI-Server. Der normalisiert, schreibt nach SQLite und broadcastet live über WebSocket. Das Dashboard ist rein clientseitig. Kein externer Dienst, kein Auth, nur 127.0.0.1.
Der nicht offensichtliche Teil: alle Events eines Session-Baums teilen dieselbe session_id. Der einzige Diskriminator für einen Subagenten ist das Feld agent_id (beim Hauptagenten abwesend), agent_type liefert das lesbare Label. Der naive Default 'eine Lane pro session_id' hätte alle Subagenten in eine Spur kollabiert. Empirisch verifiziert an echten Capture-Payloads.
Der Hauptagent trägt kein agent_id-Feld. Genau diese Abwesenheit macht ihn erkennbar — er bekommt seine eigene Top-Lane.
Beim Subagenten ist agent_id der einzige Diskriminator, agent_type liefert das lesbare Label. Die geteilte session_id wird zum Parent.
derive_lane ist die einzige Stelle für Lane-Anpassungen — kalibriert gegen die offizielle Hooks-Dokumentation, nicht gegen Vermutungen.
Ein realer general-purpose-Subagent wurde gespawnt; agent_id und agent_type erschienen in PreToolUse UND SubagentStop. Der Capture-Hook fing nebenbei alle parallel laufenden Sessions ein.
Ein Observability-Tool, das den überwachten Agenten blockieren oder crashen kann, ist schlimmer als keins. Der Hook-Sender ist deshalb durchgehend fail-soft ausgelegt: läuft der Server nicht, arbeitet Claude Code einfach weiter. Diese Entscheidungen sind die eigentliche Engineering-Substanz.
Kein raise, kein stdout — bei jedem Fehler beendet der Sender mit exit 0. Der beobachtete Agent merkt nichts.
Der Sender wartet nie lange auf den Server. Läuft der nicht, arbeitet Claude Code einfach weiter.
Strings >500 Zeichen, Dicts >20 Keys und Listen >20 Items werden gekürzt — Schutz vor riesigen Payloads.
Der Hook hat keine externen Dependencies und kann in jeder Claude-Umgebung laufen, ohne etwas zu installieren.
conftest.py lenkt AGENT_OBS_DATA_DIR auf eine Temp-DB; ein Poison-Guard prüft nach jedem Test gegen die echte data/events.db.
Das System läuft lokal auf 127.0.0.1:7171, mit grünen Tests und empirisch verifizierter Lane-Logik. Es ist bewusst Lab-Arbeit: rein lokal, kein öffentliches Repository, keine Live-URL. Was läuft, läuft echt; was offen ist, steht hier offen.
Tests grün — Hook-Sender, Ingest, DB, Hub, Stream, Lane-Logik, Poison-Guard
Latenz, bis ein neuer Tool-Call im Dashboard erscheint
Hook-Timeout — fire-and-forget, exit 0 bei Fehler
Events im In-Memory-Ring-Buffer (Snapshot für neue Verbindungen)
Port — gebunden ausschließlich an 127.0.0.1, kein Public-Zugang
empirisch abgeschlossen — derive_lane gegen echte Subagent-Payloads verifiziert
Kein Repo-Link, keine Live-URL. Anders als dual-bridge ist dieser Code nicht öffentlich. Ein Walkthrough ist auf Anfrage möglich.
Die Hook-Pipeline, die Lane-Logik, der fail-soft Sender — wenn dich ein Mechanismus interessiert, schreib mir. Der Code ist lokal, ein Walkthrough ist jederzeit möglich.