Skip to content

Add onAgentActivityChanged SDK hook #681

@willwashburn

Description

@willwashburn

Add a first-class SDK hook named onAgentActivityChanged so app clients do not need to infer “thinking” from raw broker events themselves.

Goal:

  • Add onAgentActivityChanged to the high-level AgentRelay API in the SDK.
  • This should be an SDK-level derived signal built from existing broker events.
  • Prefer not to add any new broker protocol events unless you conclude the existing events are insufficient. If you do change protocol, explain why.

Why:

  • Today clients have to combine delivery_*, relay_inbound, and agent_idle to show a simple “agent is active/thinking” badge.
  • That logic belongs in the SDK, not in each app.

Relevant files:

  • packages/sdk/src/relay.ts
  • packages/sdk/src/protocol.ts
  • src/pty_worker.rs

Current event context:

  • AgentRelay already has hooks like onMessageReceived, onMessageSent, onDeliveryUpdate, onAgentIdle, and onWorkerOutput.
  • Broker events already include:
    • delivery_queued
    • delivery_injected
    • delivery_active
    • delivery_ack
    • delivery_failed
    • relay_inbound
    • agent_idle
    • agent_exited
    • agent_released

Requested API:

  • Add a new hook on AgentRelay, something like:

    interface AgentActivityChange {
    name: string;
    active: boolean;
    pendingDeliveries: number;
    reason:
    | 'delivery_queued'
    | 'delivery_injected'
    | 'delivery_active'
    | 'delivery_ack'
    | 'delivery_failed'
    | 'relay_inbound'
    | 'agent_idle'
    | 'agent_exited'
    | 'agent_released';
    eventId?: string;
    }

    onAgentActivityChanged: EventHook = null;

Semantics:

  • This is an “activity” signal, not a literal cognition signal.
  • active=true should mean: the SDK has seen an in-flight delivery for the agent that has not yet been closed out.
  • Mark an agent active when a delivery enters activity:
    • delivery_queued
    • delivery_injected
    • delivery_active
    • delivery_ack
  • Mark an agent inactive when activity is closed out:
    • relay_inbound from that agent
    • agent_idle
    • delivery_failed when no pending deliveries remain
    • agent_exited
    • agent_released
  • Maintain per-agent pending delivery state so concurrent deliveries behave correctly.
  • Do not emit duplicate callbacks when the derived active state has not changed.

Notes:

  • delivery_ack is not proof the model is actively reasoning; it is still useful as part of the broader “activity” signal.
  • If you think a different state shape is better, keep the API simple and app-facing.

Tests:

  • Add focused SDK tests covering:
    • emits active on first delivery event
    • does not emit repeated active transitions while already active
    • emits inactive on relay_inbound
    • emits inactive on agent_idle
    • concurrent deliveries do not flip inactive too early
    • emits inactive on exit/release
    • delivery_failed only clears activity when the last pending delivery is gone

Docs:

  • Add a short SDK example showing how a UI could render a “thinking” badge from onAgentActivityChanged.

Output:

  • Implement the change
  • Run relevant tests
  • Summarize semantics/tradeoffs
  • List changed files

This keeps the change SDK-side and avoids pushing relay/broker event inference into each app.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions