Appearance
Traces
The trace format the agent platform uses everywhere is the activity frame — a small structured record emitted on every cognitive step of an agent loop. Frames stream from AgentActor to its activityTo sinks (Director, Chat, observability) and are also persisted on the session for replay.
ActivityFrame shape
From IAgentSessionStore.ts:85-103:
ts
interface ActivityFrame {
requestId: string;
seq: number; // monotonic per request
ts: number; // epoch-ms
source: string; // emitting mount (e.g. system.agents.<target>)
traceId?: string;
spanId?: string;
parentSpanId?: string;
sessionId?: string;
resumeId?: string;
principalId?: string;
kind: string; // see "Kinds" below
phase: string; // 'start' | 'progress' | 'complete' | 'error'
summary?: string; // short human label
target?: string; // for tool frames: the invoked mount
op?: string; // for tool frames: the invoked op
data?: unknown; // kind-specific payload
durationMs?: number;
}Frames are normalized: regardless of whether the underlying event came from the internal oracle, a Claude Code worker, or a Codex worker, the consumer sees the same envelope.
Kinds (canonical set)
From NormalizedActivityEvent.ts (NormalizedActivityKind):
prompt.in— the user/caller prompt arrivedinference.start/inference.token/inference.complete— model call lifecyclethinking— extended-thinking output (Anthropic) / reasoning summary (Codex)tool.call— model requested a tooltool.result— tool returnedapproval.required— model needs human approval (paired withapproval.granted/approval.denied)response.partial/response.final— streamed and final assistant texterror— terminal failuresession.bootstrap— session created or resumed
NormalizedActivityPhase is start | progress | complete | error.
Where frames come from
| Runtime | Normalizer | Notes |
|---|---|---|
Internal oracle (InternalOracleRuntimeAdapter) | emits frames directly via OracleSink callbacks | the executeActorOracle → sink → frame path |
| Claude Code worker | ClaudeEventNormalizer (activity/ClaudeEventNormalizer.ts) | maps Anthropic SDK event types to frames |
| Codex worker | CodexEventNormalizer (activity/CodexEventNormalizer.ts) | maps Codex SDK event types to frames |
Where frames go
Three sinks are wired today:
- Caller mount. Every frame is published to
activityTo[]mounts on the bus. Director and Chat subscribe. - Session store.
IAgentSessionStore.appendActivityFrames(sessionId, requestId, frames)persists each request's frames. Two backends:FileAgentSessionStore(filesystem under<host-home>/sessions/) andRecordBackedSessionStore(observability record store). $traceQuery.AgentsRoot.$traceQueryis the read accept that returns activity frames for a given session/request — this is the same surface a future Director timeline UI would call.
Trace IDs
Frames carry OpenTelemetry-aligned IDs (traceId, spanId, parentSpanId). When system.agents is called from another agent (delegated agency), the parentSpanId chains the trace across the bus boundary so a single user prompt that fans out to multiple agents can be reconstructed end-to-end.
See also
Source:
projects/matrix-3/packages/agents/src/IAgentSessionStore.ts:85-103,projects/matrix-3/packages/agents/src/activity/NormalizedActivityEvent.ts, normalizers underprojects/matrix-3/packages/agents/src/activity/.