Aviary
Reference

Diagnostics events

The aviary:agent:* diagnostics_channel events published by @dudousxd/nestjs-agent-core, with exact payload shapes.

@dudousxd/nestjs-agent-core publishes lifecycle events on the aviary:agent:* node:diagnostics_channel namespace via @dudousxd/nestjs-diagnostics' emit('agent', <event>, payload). Both the dashboard's live feed and the -telescope "Agent" tab subscribe to the same channel — see Governance and packages/telescope.

Events

EventPayload fieldsPublisher
run.startedrunId: string; threadId: string; actorId: string; agentName?: stringpublishAgentRunStarted
messagerunId: string; threadId: string; role: 'user' | 'assistant'; textLength: numberpublishAgentMessage
tool-callrunId: string; toolName: string; toolType: 'read' | 'action'; status: string; durationMs?: numberpublishAgentToolCall
quota.exceededactorId: string; usedTokens: number; limitTokens: numberpublishAgentQuotaExceeded
run.failedrunId: string; code: string; message: stringpublishAgentRunFailed
run.finishedrunId: string; threadId: string; steps: number; inputTokens: number; outputTokens: numberpublishAgentRunFinished
delegatedrunId: string; fromAgent?: string; toAgent: stringpublishAgentDelegated
retrievedrunId: string; query: string; count: numberpublishAgentRetrieved

These 8 are the point events, exported as a stable, compile-time-checked AGENT_DIAGNOSTIC_EVENTS array with a matching agentDiagnosticKey(event) helper that composes the telescope bridge's agent:<event> key — pass those keys to nestjsDiagnosticsTelescope({ exclude: [...] }) to mute a channel already recorded elsewhere (the generic bridge now records all 8, including run.failed, delegated, and retrieved, which used to be silently dropped).

tool-call's toolType is narrower than ToolKind

AgentToolCallEvent.toolType is 'read' | 'action' — it does not include the 'agent' kind that ToolSpec.kind supports for delegation. Delegation gets its own delegated event instead.

Trace spans (traceId = runId)

Every run also emits four span-only events — never as point events on the base channel, only via trace() on the :start/:end/:asyncStart/:asyncEnd/:error sub-channels, correlated by traceId = runId. This is what lets the Telescope TRACES tab render a turn as a nested waterfall (llm calls, tool executions, retrieval, follow-ups) with durations and error phases. They're emitted from inside the checkpointed step bodies, so a replayed (cached) step never re-emits — and, for dispatched turns (see Inline → durable), from whichever worker actually executes the step.

Span eventSTART payload fields
llm.turnrunId: string; step: number (zero-based model-call index)
tool.executionrunId: string; toolCallId: string; toolName: string; toolType: 'read' | 'action'
retrievalrunId: string; queryLength: number; topK: number
follow-upsrunId: string; step: number; count: number

Payloads are metadata-only — model id, token counts, tool name/type, step index, query length — never prompt or output text. traceLlmTurn/traceToolExecution are exported for remote execution sites that need to emit the same span shape.

Spans need the span-aware bridge

Rendering these as a waterfall requires @dudousxd/nestjs-diagnostics-telescope 0.7+ and @dudousxd/nestjs-telescope 1.17+ (explicit RecordInput.traceId). Without them the spans are still emitted but unobserved — zero cost, since the phase envelopes are gated on subscriber presence. Span events are deliberately excluded from AGENT_DIAGNOSTIC_EVENTS: the point-event watcher has nothing to subscribe to on their base channels.

How to subscribe

Directly, via node:diagnostics_channel:

import { subscribe } from 'node:diagnostics_channel';
import { channelName } from '@dudousxd/nestjs-diagnostics';

subscribe(channelName('agent', 'tool-call'), (message) => {
  // message: DiagnosticEvent<AgentToolCallEvent>
  //   { v?, ts: number, lib: 'agent', event: 'tool-call', traceId?, payload: AgentToolCallEvent }
});

Or via the telescope extension, which wires the same channel into a navigable entry type and dashboard page without any manual subscribe calls — see packages/telescope.

The dashboard's GET /ai-gateway/api/stream SSE endpoint forwards these same events flattened to LiveAgentEvent ({ event, ts, payload }) for browser clients — see Endpoints.

On this page