> ## Documentation Index
> Fetch the complete documentation index at: https://tracevell.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Claude Agent SDK observability

> Trace agents built on the Claude Agent SDK in TypeScript and Python, including subagent runs, tool calls, token usage, and cost.

## Overview

Tracevell is an open-source, OpenTelemetry-native observability platform for the Claude Agent SDK. Trace, debug, and monitor every agent turn, tool call, and subagent spawned by `ClaudeSDKClient.query` and the module-level `query` function. Self-host via Helm or use managed cloud.

[Claude Agent SDK](https://docs.claude.com/en/api/agent-sdk/overview) (formerly Claude Code SDK) lets you call the same agent that powers Claude Code from your own code. It handles process management, tool execution, and model calls, and exposes a `query` function (TypeScript) and `ClaudeSDKClient` (Python) for driving a session.

Tracevell captures the full structure of each run: the root call, every model turn, each tool call, and every subagent spawned via the `Agent` tool. Nested subagents show up as child spans under the invocation that spawned them, so you can read the whole agent tree in one trace.

What Tracevell captures:

* The root call (`ClaudeSDKClient.query` / module-level `query`) with the prompt you sent.
* Every model turn with prompts, responses, token counts, latency, and cost.
* Tool calls (`Read`, `Write`, `Edit`, `Bash`, `Glob`, `Grep`, `WebSearch`, custom MCP tools) with arguments and results.
* Subagents spawned via the `Agent` tool as nested spans under the parent turn.

## Getting started

> [tab] TypeScript
>
> **1. Install**
>
> Ensure you are using `@lmnr-ai/lmnr` version `0.7.10` or higher.
>
> ```bash theme={null}
> npm install @lmnr-ai/lmnr@latest @anthropic-ai/claude-agent-sdk@latest
> # or
> pnpm add @lmnr-ai/lmnr@latest @anthropic-ai/claude-agent-sdk@latest
> ```
>
> **2. Set environment variables**
>
> ```bash theme={null}
> export LMNR_PROJECT_API_KEY=your-tracevell-project-api-key
> export ANTHROPIC_API_KEY=your-anthropic-api-key
> ```
>
> **3. Wrap the query function**
>
> ```typescript {2,5,8} theme={null}
> import { query as origQuery } from '@anthropic-ai/claude-agent-sdk';
> import { Tracevell } from '@lmnr-ai/lmnr';
>
> Laminar.initialize();
>
> // Wrap the original query function to capture every turn, tool call, and subagent.
> const query = Laminar.wrapClaudeAgentQuery(origQuery);
>
> async function run() {
>   for await (const message of query({
>     prompt: "Scan the current directory for TODOs and create a summary markdown file.",
>   })) {
>     // Messages stream in; Tracevell records the full span tree.
>   }
> }
> run();
> ```
>
> > [!NOTE]
> >
> > `query` is an async generator. You must iterate it (or collect it) for the agent to run to completion. If you need the return value before initialization, the module-level `instrumentClaudeAgentQuery(originalQuery)` export is equivalent to `Laminar.wrapClaudeAgentQuery`.

> [tab] Python
>
> **1. Install**
>
> ```bash theme={null}
> pip install -U lmnr claude-agent-sdk
> ```
>
> **2. Set environment variables**
>
> ```bash theme={null}
> export LMNR_PROJECT_API_KEY=your-tracevell-project-api-key
> export ANTHROPIC_API_KEY=your-anthropic-api-key
> ```
>
> **3. Initialize Tracevell**
>
> `Laminar.initialize()` auto-instruments `claude-agent-sdk` when the package is importable. No wrapping call is needed.
>
> ```python {4-6} theme={null}
> import asyncio
>
> from claude_agent_sdk import ClaudeSDKClient
> from lmnr import Tracevell, observe
>
> Laminar.initialize()
>
> @observe()
> async def main():
>     async with ClaudeSDKClient() as client:
>         await client.query(
>             "Explain with examples how memoization speeds up recursive calls, "
>             "using Fibonacci as the example."
>         )
>         async for msg in client.receive_response():
>             print(msg)
>
> if __name__ == "__main__":
>     asyncio.run(main())
> ```
>
> > [!NOTE]
> >
> > Wrapping your entry point in `@observe()` is optional but recommended: it creates a root span that captures inputs and outputs and makes the trace easy to find in the UI.

## Running on Amazon Bedrock

The Claude Agent SDK supports Claude models hosted on Amazon Bedrock. Tracevell traces work out of the box: follow Anthropic's [Amazon Bedrock guide](https://code.claude.com/docs/en/amazon-bedrock) to configure your AWS credentials and the SDK environment variables, and additionally set `AWS_REGION` to the region you're targeting.

```bash theme={null}
export CLAUDE_CODE_USE_BEDROCK=1
export AWS_REGION=us-west-2
# plus the AWS credentials from the Anthropic Bedrock guide
```

> [!NOTE]
>
> `AWS_REGION` is required for Tracevell tracing to work correctly on Bedrock.

Initialize Tracevell exactly as shown in [Getting started](#getting-started); no other code changes are needed.

## See what happened in a trace

Open the trace in Tracevell and you land on the transcript view: each turn reads as a conversation, with the prompt, the model's response, tool calls inline with their inputs and outputs, and any subagents collapsed to their final output. A tree of span names tells you the shape of the run; the transcript tells you what actually happened.

![Claude Agent SDK trace in Tracevell, transcript view](https://mintcdn.com/laminarai/RPYdoMdfsv6y-QUL/images/traces/claude-agent-sdk.png?fit=max\&auto=format\&n=RPYdoMdfsv6y-QUL\&q=85\&s=72c527d4e2588d86babd44762e0c71cc)

Transcript view: the user prompt, tool calls, and model responses read as a dialogue. Expand any span to see its full input and output.

More on the trace UX: [Viewing traces](https://tracevell.com/docs/platform/viewing-traces.md).

## Multi-agent runs

The Claude Agent SDK lets you define subagents programmatically with the `agents` option. Each subagent gets its own system prompt and tool allowlist, and the orchestrator invokes them via the `Agent` tool (formerly `Task`). In Tracevell, every subagent invocation becomes a child span of the turn that spawned it, with its own LLM calls and tool calls nested underneath.

> [tab] TypeScript
>
> ```typescript theme={null}
> import { query as origQuery } from '@anthropic-ai/claude-agent-sdk';
> import { Tracevell } from '@lmnr-ai/lmnr';
>
> Laminar.initialize();
> const query = Laminar.wrapClaudeAgentQuery(origQuery);
>
> for await (const _ of query({
>   prompt: `Review fizzbuzz.py. Kick off three subagents in parallel:
> 1. researcher: summarize what the code does.
> 2. reviewer: flag bugs, naming, and missing edge cases.
> 3. test-runner: propose 3-5 unit tests.
> Combine their findings into a short report.`,
>   options: {
>     allowedTools: ['Read', 'Glob', 'Grep', 'Agent'],
>     agents: {
>       researcher: {
>         description: 'Summarizes what code does. Use for investigation and overview.',
>         prompt: 'Read the code and describe in 3-5 bullets what it does, its inputs, and outputs.',
>         tools: ['Read', 'Glob', 'Grep'],
>       },
>       reviewer: {
>         description: 'Reviews code for quality, bugs, and maintainability.',
>         prompt: 'Identify bugs, unclear naming, missing edge cases, and style issues. Respond with a numbered list.',
>         tools: ['Read', 'Glob', 'Grep'],
>       },
>       'test-runner': {
>         description: 'Designs unit tests. Use for test planning.',
>         prompt: 'Propose 3-5 unit tests covering happy path and edge cases.',
>         tools: ['Read', 'Glob', 'Grep'],
>       },
>     },
>   },
> })) {
>   // stream through messages
> }
> ```

> [tab] Python
>
> ```python theme={null}
> import asyncio
> from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
> from lmnr import Tracevell, observe
>
> Laminar.initialize()
>
> @observe(name="multi-agent-code-review")
> async def main():
>     options = ClaudeAgentOptions(
>         allowed_tools=["Read", "Glob", "Grep", "Agent"],
>         agents={
>             "researcher": AgentDefinition(
>                 description="Summarizes what code does. Use for investigation and overview.",
>                 prompt="Read the code and describe in 3-5 bullets what it does, its inputs, and outputs.",
>                 tools=["Read", "Glob", "Grep"],
>             ),
>             "reviewer": AgentDefinition(
>                 description="Reviews code for quality, bugs, and maintainability.",
>                 prompt="Identify bugs, unclear naming, missing edge cases, and style issues. Respond with a numbered list.",
>                 tools=["Read", "Glob", "Grep"],
>             ),
>             "test-runner": AgentDefinition(
>                 description="Designs unit tests. Use for test planning.",
>                 prompt="Propose 3-5 unit tests covering happy path and edge cases.",
>                 tools=["Read", "Glob", "Grep"],
>             ),
>         },
>     )
>
>     prompt = (
>         "Review fizzbuzz.py. Kick off three subagents in parallel (researcher, reviewer, "
>         "test-runner) and combine their findings into a short report."
>     )
>     async for _ in query(prompt=prompt, options=options):
>         pass
>
> asyncio.run(main())
> ```

> [!NOTE]
>
> Subagents are only invoked when `Agent` is in `allowedTools` / `allowed_tools`. Without it, the orchestrator cannot delegate and you'll see a single-threaded trace.

The resulting trace renders each subagent as a branch under the turn that spawned it. Switch to tree view when you want to see the hierarchy at a glance:

![Claude Agent SDK multi-agent trace in Tracevell](https://mintcdn.com/laminarai/RPYdoMdfsv6y-QUL/images/traces/claude-agent-sdk-multi-agent.png?fit=max\&auto=format\&n=RPYdoMdfsv6y-QUL\&q=85\&s=307d366ce222354f6a377263c2a150bc)

Tree view of a multi-agent run: the ClaudeSDKClient.query root contains the orchestrator turn and three Agent-tool subagents, each with its own LLM and tool calls nested underneath.

## Track outcomes with Signals

Traces answer *what happened on this run*. **[Signals](https://tracevell.com/docs/signals/introduction.md) answer the cross-trace question**: *how often does the agent edit a file it wasn't asked to, when does a subagent exceed five tool calls, which reviewers miss null-check bugs*. A Signal pairs a plain-language instruction with a JSON output schema. Tracevell runs it live on new traces (Triggers) or backfills it across history (Jobs) and records a structured event every time it matches. From there you [query](https://tracevell.com/docs/platform/sql-editor.md), [cluster](https://tracevell.com/docs/signals/clusters.md), and [alert](https://tracevell.com/docs/signals/alerts.md) on events across every trace.

> [!NOTE]
>
> Every new project ships with a **Failure Detector** Signal that categorizes issues on any trace over 1000 tokens. Open it from the Signals sidebar to see events as soon as your Claude Agent SDK traces arrive.

## Query across traces

* **[SQL editor](https://tracevell.com/docs/platform/sql-editor.md)** for ad-hoc queries across traces, spans, signals, and evals.
* **SQL API** for programmatic access from scripts and pipelines.
* **[CLI](https://tracevell.com/docs/platform/cli.md)** (`lmnr-cli sql query`) for terminal-driven queries and piping JSON into shell tools or coding agents.
* **[MCP server](https://tracevell.com/docs/platform/mcp.md)** to query Tracevell directly from Claude Code, Cursor, Codex, or any MCP-aware client.

## Troubleshooting

> [accordion] I don't see any traces in Tracevell
>
> * Confirm `LMNR_PROJECT_API_KEY` is set in the same process that runs the Claude Agent SDK.
> * In TypeScript, make sure you're iterating the async generator returned by `query`. The agent only runs while you consume messages.
> * In Python, `claude-agent-sdk` must be importable when `Laminar.initialize()` runs. Install it with `pip install claude-agent-sdk`.

> [accordion] Subagents aren't showing up as child spans
>
> * Add `Agent` to `allowedTools` / `allowed_tools`. Without it the orchestrator falls back to doing everything in-line.
> * Define subagents on the `agents` option; otherwise the `Agent` tool has nothing to invoke.
> * The `Agent` tool was called `Task` in earlier Claude Agent SDK versions (\< 2.1.63). Upgrade to the latest SDK to match the examples above.

> [accordion] Self-hosting Tracevell
>
> Set `LMNR_BASE_URL` and the ports of your instance before initializing. For a local OSS deployment:
>
> ```bash theme={null}
> export LMNR_BASE_URL=http://localhost
> # Python
> # Laminar.initialize(base_url="http://localhost", http_port=8000, grpc_port=8001)
> ```

## What's next

> [card] [Viewing traces](https://tracevell.com/docs/platform/viewing-traces.md)
>
> Read the transcript view, filter, and search across traces.

> [card] [Signals](https://tracevell.com/docs/signals/introduction.md)
>
> Detect behaviors and failures across every run, then query, cluster, and alert on them.

> [card] [SQL editor and MCP server](https://tracevell.com/docs/platform/sql-editor.md)
>
> Query traces programmatically from the UI, API, or your IDE.

> [card] [Tracing structure](https://tracevell.com/docs/tracing/structure/overview.md)
>
> Sessions, metadata, and tags for deeper control.

## Related integrations

> [card] [Claude Code](https://tracevell.com/docs/integrations/claude-code.md)
>
> Trace Claude Code sessions with a one-command plugin.

> [card] [OpenCode](https://tracevell.com/docs/integrations/opencode.md)
>
> Running the Claude Agent SDK alongside OpenCode? Trace both here.

> [card] [Codex](https://tracevell.com/docs/integrations/codex.md)
>
> Trace Codex CLI sessions with a one-command plugin.

> [card] [Anthropic](https://tracevell.com/docs/integrations/anthropic.md)
>
> Trace the Anthropic SDK directly in TypeScript and Python.

> [card] [OpenHands SDK](https://tracevell.com/docs/integrations/openhands-sdk.md)
>
> Trace OpenHands software agents end to end.

> [card] [All integrations](https://tracevell.com/docs/integrations.md)
>
> Browse every provider, framework, coding agent, and browser integration Tracevell supports.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.