Skip to content

Bus Inspector: a debug surface for agentSession.bus + AG-UI event streams #202

@runyaga

Description

@runyaga

Motivation

Debugging session state today means reading agent logs and inferring what happened. There's no in-app way to see:

  • What's being written to the per-thread StateBus and by whom
  • The raw AG-UI event stream that drives those writes
  • The relationship between an event arriving and the bus commit it produced

This makes it hard to verify projections, diagnose stuck UI state, or understand the order of activity events vs state events for a given thread.

Proposal

A new in-app debug surface, Bus Inspector, mounted next to the existing Network Inspector under the diagnostics module. It records:

  • Every per-thread StateBus commit (with ThreadKey context, the resolved tag, and a frozen snapshot)
  • Every raw AG-UI BaseEvent processed by any session

Renders both in a unified, time-ordered timeline distinguished by bus/event row badges. Per-thread sidebar lets you scope to one thread; a small filter mini-language (thread:, room:, tag:, path:, kind:, with autocomplete chips) drills further.

Pure additive at the soliplex_client / soliplex_agent layer: two new observer hooks (StateBus.addObserver, AgentRuntime.busObserver/eventObserver) that the diagnostics module subscribes to. The agent layer stays free of any inspector-specific code; the diagnostics module owns all tagging and rendering.

Design notes

Tag taxonomy:

  • Bus commits: agui.snapshot, agui.delta, agui.run-state (inferred by the inspector by correlating with the most recent state event on the thread), or seed.initial/seed.history (set explicitly at the seed paths).
  • Event records: agui.<eventclassname-lowercased>, e.g. agui.activitysnapshot, agui.activitydelta, agui.textmessagestart. So tag:agui.activity* lights up activity events without any extra grammar.

Memory bound: each queue caps at 1000 entries; oldest dropped on overflow.

Implementation: 4 stacked PRs

  1. feat(client): StateBus observer + tag API — additive addObserver hook + optional tag: arg on setAgentState/update. Pure client-package addition.
  2. feat(agent): bus + event observers on AgentRuntimeThreadBusObserver + ThreadEventObserver typedefs + ctor params, wiring through AgentSession._bridgeBaseEvent, seed tagging.
  3. feat(diagnostics): Bus Inspector module — recorder, filter parser, snapshot differ, screen. Self-contained under lib/src/modules/diagnostics/.
  4. feat: wire Bus Inspector into shell/diagnostics/bus route, sidebar button next to "Network Inspector", standard() flavor wiring.

Out of scope (for this stack)

  • Persisting recorded events across runs
  • Exporting timeline to JSON
  • A separate dart_monty Bridge inspector — distinct surface, separate work
  • A registry inspector for ClientTools / code block builders — separate work

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions