Observe a live Agent session
Run one incident-analysis <Agent /> with an application Tool and two <FollowUp /> turns, while AML’s built-in console tracer shows:
- the initial and follow-up turn boundaries;
- ordered ACP message, thought, Tool, plan, usage, and other update variants;
- provider session and process lifecycle;
- Agent cleanup after the final turn or a failure.
This observes what crosses AML’s ACP connection. It cannot reveal hidden vendor retries, unreported sub-agents, model internals, or Tool activity the Agent does not emit.
Prerequisites
Section titled “Prerequisites”- Node.js
>=26, ESM TypeScript/TSX,@aml-jsx/sdk, andzod; - the OpenCode executable and model credentials available to the process;
AML_OPENCODE_MODELwhen you do not want the example’sopencode-go/deepseek-v4-flashdefault;- a local terminal approved to receive prompt, Tool, thought, and response content.
Building block 1: application-owned evidence
Section titled “Building block 1: application-owned evidence”The Agent receives the incident packet through one typed Tool. This is an explicit application capability, not ambient filesystem or network access.
const ReadIncidentPacket = defineTool({ description: "Read the complete, application-owned incident packet", input: z.object({}), name: "read_incident_packet", async execute() { return INCIDENT_PACKET },})The maintained source defines a small frozen packet containing the deploy time, observed latency change, rollback status, and three span summaries.
Building block 2: the AML component tree
Section titled “Building block 2: the AML component tree”The workflow reads like the session it authors: capability first, initial instruction next, then two ordered later turns.
function IncidentReview() { return ( <Agent provider={provider} system="You are an incident analyst. Separate direct evidence, inference, and missing information." > <Tool use={ReadIncidentPacket} /> Call read_incident_packet. Form a preliminary incident hypothesis using only the returned evidence. <FollowUp> Audit the preliminary hypothesis. Identify the strongest alternative explanation and the next observation that would distinguish between them. </FollowUp> <FollowUp> Produce the final five-line incident update. Label facts, inference, uncertainty, next check, and rollback status. </FollowUp> </Agent> )}This is one Agent session and three sequential ACP prompt requests. <FollowUp /> keeps the preliminary response and audit in provider-owned conversation history. If application code must inspect or branch on an intermediate response, use separate Agent evaluations instead.
Building block 3: compose the built-in tracer
Section titled “Building block 3: compose the built-in tracer”Observability is a runtime concern, so the application composes AML’s dependency-free console tracer at its runtime boundary:
const runtime = new AmlRuntime({ maxAgentCalls: 1, maxTurnsPerAgent: 3, trace: createConsoleTracer({ captureContent: true, write: line => process.stderr.write(`${line}\n`), }),})createConsoleTracer() already understands AML’s span tree, turn correlation, event ordering, duration fields, and content policy. The workflow does not need a reporter class or a parallel ACP schema.
With content capture enabled, each acp.session.update line includes the provider’s unchanged serialized ACP update. Consumers that need a specialized dashboard may decode the ACP version they support, but that is integration code—not part of the AML workflow and not necessary for seeing the live event stream.
Main file
Section titled “Main file”The maintained .tsx file combines the imports, incident packet, Tool, IncidentReview component, provider, and runtime blocks above. Its final result boundary stays one line:
process.stdout.write(`${await runtime.evaluate(<IncidentReview />)}\n`)Trace activity goes to standard error and the final workflow result goes to standard output, so the result remains pipeable. This is an application-owned runtime example; run it with vite-node, not aml run. The CLI owns its own runtime and exposes the same tracer through --trace --capture-content.
Run it
Section titled “Run it”From the repository root:
AML_OPENCODE_MODEL=opencode-go/deepseek-v4-flash \ npx vite-node examples/src/operations/observe-agent.tsx \ > /tmp/incident-update.txtThe requested five-line update goes to /tmp/incident-update.txt. Standard error shows a trace shaped like:
▶ agent Agent ▶ agent.session provider="opencode" ▶ agent.turn index=1 kind="initial" • acp.session.update sessionUpdate="tool_call" toolName="shell" update="{...}" ✓ agent.turn 1.8s ▶ agent.turn index=2 kind="follow-up" ... ▶ agent.turn index=3 kind="follow-up" ... ▶ agent.cleanup ✓ agent.cleanup 8.1msExact ACP variants, serialized content, timings, chunk sizes, and prose depend on the Agent and model. Turn order does not: AML ends one authored turn before starting the next.
How the events map to the tree
Section titled “How the events map to the tree”- Runtime construction captures the trace sink and its content policy. The sink observes the run; it is not an Agent capability.
<Agent />opens one provider session. Its<Tool />child grants one scoped application capability.- AML starts
agent.turn index=1 kind="initial"and submits the first ACP prompt. Every ACP notification becomes one orderedacp.session.update. - AML ends the initial turn before starting each
<FollowUp />in declaration order. - The final FollowUp response becomes the workflow result. AML then closes the provider session and reports
agent.cleanupindependently.
Failure and design notes
Section titled “Failure and design notes”- A provider can emit no updates and still complete a turn. Updates are progress evidence, not a completeness guarantee.
- Trace sinks are not awaited and cannot control workflow success. Use
onTraceErrorfor sink failures; do not put business logic in telemetry. - One captured update can contain customer data even when the displayed event name looks harmless.
- For durable telemetry, keep content capture off and record span durations, turn kinds, update discriminants, stop reasons, and usage metadata.
- Use the CLI form,
aml run workflow.tsx --trace --capture-content, when the workflow should export only an AML tree and let the CLI own runtime construction.