Conventional monitoring watches for crashes, error rates and latency. LLM and agent systems add failures that all of those can miss: a 200 OK carrying a wrong or incomplete answer, a tool loop that burns tokens, a subagent that quietly covered half the scope. Agents also make dynamic decisions and can behave differently across runs with the same prompt, so you cannot reproduce a bad run by re-sending the input. Observability here means recording enough at run time to reconstruct what happened, at a cost and privacy footprint you can defend. Ongoing quality monitoring and alerting belong to Lesson 3.6; this lesson is about what to instrument and how.
What to capture, layer by layer
| Layer | Capture | Why it matters |
|---|---|---|
| Request | Anthropic request-id, model, key parameters (effort, max_tokens, tool_choice), token usage, latency (time to first token and total), stop_reason, error type | The request ID is what support needs; usage and latency drive cost and SLOs; stop reasons expose truncation and tool-use turns |
| Tool | Tool name, redacted arguments, duration, success or error, result size, permission decision | Shows loops, slow dependencies and what the agent was actually allowed to do |
| Agent trace | One trace per user task linking model calls, tool calls and subagent runs | The only view that explains a multi-step outcome |
| Outcome | Task success, user feedback, escalation, linked to the trace ID | Turns telemetry into quality signal |
| Cost and usage | Aggregates by model, workspace, key | Budgeting, chargeback, anomaly detection |
Details worth knowing. Every API response carries a request-id header, repeated as request_id in error bodies, and the SDKs expose it (for example _request_id in Python). Log it on every call. For streaming, an error can arrive after the API has already returned a 200, so status-code monitoring alone misses mid-stream failures; log the stream's error events too. The Usage and Cost Admin API reports token and cost data by model, workspace, API key and service tier in minute, hour or day buckets, typically within about five minutes, and needs an Admin credential. It is the right source for spend and chargeback, but it is aggregated: it cannot tell you why one request failed.
Traces are the unit for agents
Claude Code and the Agent SDK show the target shape. They export OpenTelemetry metrics, log events and (in beta, behind CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1) traces: a claude_code.interaction span per prompt, with claude_code.llm_request and claude_code.tool child spans. When an agent spawns a subagent, the subagent's spans nest under the parent's tool span, so the whole delegation chain reads as one trace. The SDK also propagates W3C trace context (TRACEPARENT), so an agent run appears inside your application's own trace rather than as an orphan. Resource attributes such as OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES let you tag agent name, version, environment and, if you percent-encode them, the end user on whose behalf it acted.
If you build orchestration on the Messages API instead, reproduce the pattern deliberately. Subagents receive only what you pass them, so correlation does not happen by itself: create the trace ID in the coordinator, attach it to every model call, tool call and subagent invocation through your own span context, and record parent-child links. A per-subagent view that cannot be joined back to the coordinator's decomposition hides the failures Lesson 2.4 warns about.
Sampling, volume and cardinality at scale
- Aggregate metrics are cheap and unsampled; traces and content are the expensive part. Sampling them uniformly (say 1%) is simple but drops precisely the rare failures you want. A common engineering pattern is tail-based: decide after the trace completes and keep all errors, slow traces, high-cost traces and low-feedback outcomes, sampling the healthy remainder. This is an engineering practice, not an Anthropic requirement.
- Cardinality. Session IDs, user IDs and prompt hashes as metric labels multiply your time series. Keep them on traces and events. Claude Code exposes switches such as
OTEL_METRICS_INCLUDE_SESSION_IDfor this reason. - Body size. Full request and response bodies contain the whole conversation history. Claude Code's raw-body export is opt-in and truncates inline bodies at 60 KB by default, with an option to write full bodies to files. Decide deliberately what is worth storing.
- Export reliability. Telemetry export must never block the agent. The Claude Code CLI drops data silently on export errors unless you enable diagnostics, and short-lived processes can lose buffered spans if killed before a flush, so shorten export intervals for short tasks and verify data actually arrives.
Key concept: metadata by default, content by exception
Model, tokens, latency, tool names, stop reasons, IDs and outcomes are usually safe to keep broadly. Prompt text, tool arguments, file contents and raw bodies are data-handling decisions. Claude Code follows this: by default it exports only structural metadata, and content requires explicit opt-in variables (OTEL_LOG_USER_PROMPTS, OTEL_LOG_TOOL_DETAILS, OTEL_LOG_TOOL_CONTENT, OTEL_LOG_RAW_API_BODIES).
Privacy of what you log
Logs of prompts and tool results can hold customer data, credentials pasted by users and confidential documents, and a log store is often more widely readable than the source system. Design for it: capture content only in environments and for cohorts where you have approval, redact identifiers before writing, give content a shorter retention and tighter access than metadata, and hold sampled failure traces behind a break-glass access path. Anthropic's write-up of its own multi-agent research system describes monitoring high-level interaction patterns without inspecting individual conversation content. Anthropic-side retention is a separate question from your own logs; feature pages state whether zero data retention applies. This is architecture guidance, not legal advice; regulatory obligations are covered in Lesson 4.4.
Common exam distractor
"Log every prompt and response in full so any incident can be replayed" sounds thorough but is a privacy and cost failure. "Status codes and latency dashboards are enough" misses wrong answers behind a 200 and mid-stream errors. "Use the Usage and Cost API to trace a failing request" confuses aggregate billing data with request-level traces. The strong answer correlates a trace across agents and keeps content behind explicit, governed opt-ins.