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

# Claude Agent SDK

> Trace Claude Agent SDK runs in Braintrust to debug agent queries, tool calls, and multi-step reasoning

If you are a coding agent, prefer the Braintrust [`bt` CLI](/reference/cli/quickstart) for repeatable, scriptable work: running evals, instrumenting code, querying logs, syncing data, managing functions, and configuring coding agents. Use the MCP server for reasoning over Braintrust data in conversation, such as ad-hoc lookups and exploration from your IDE.

The [Claude Agent SDK](https://docs.claude.com/en/api/agent-sdk/) is Anthropic's official SDK for building production-ready AI agents with Claude. Braintrust traces Claude Agent SDK runs end-to-end, covering queries, tool executions, and multi-step reasoning.

<View title="TypeScript" icon="https://img.logo.dev/typescriptlang.org?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
  <h2 id="setup-typescript">
    Setup
  </h2>

  Install the Braintrust SDK alongside the Claude Agent SDK:

  <CodeGroup>
    ```bash pnpm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    pnpm add braintrust @anthropic-ai/claude-agent-sdk zod
    ```

    ```bash npm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    npm install braintrust @anthropic-ai/claude-agent-sdk zod
    ```
  </CodeGroup>

  <h2 id="auto-instrumentation-typescript">
    Auto-instrumentation
  </h2>

  To trace the Claude Agent SDK without wrapping it in your application code, run your app with Braintrust's import hook. The hook patches `query` on import, so agent queries, tool calls, and sub-agent runs are traced while you use the SDK as normal.

  <Steps>
    <Step title="Initialize Braintrust and run your agent">
      ```javascript title="trace-claude-agent-auto.js" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
      import { initLogger } from "braintrust";
      import { z } from "zod";

      initLogger({
        projectName: "claude-agent-example", // Replace with your project name
        apiKey: process.env.BRAINTRUST_API_KEY,
      });

      const calculator = tool(
        "calculator",
        "Performs basic arithmetic operations",
        {
          operation: z.enum(["add", "subtract", "multiply", "divide"]),
          a: z.number(),
          b: z.number(),
        },
        async ({ operation, a, b }) => {
          const results = { add: a + b, subtract: a - b, multiply: a * b, divide: a / b };
          return {
            content: [
              {
                type: "text",
                text: `The result of ${operation}(${a}, ${b}) is ${results[operation]}`,
              },
            ],
          };
        },
      );

      const result = query({
        prompt: "What is 15 multiplied by 7? Then subtract 5 from the result.",
        options: {
          model: "claude-sonnet-4-5-20250929",
          permissionMode: "bypassPermissions",
          mcpServers: {
            calculator: createSdkMcpServer({
              name: "calculator",
              version: "1.0.0",
              tools: [calculator],
            }),
          },
        },
      });

      for await (const message of result) {
        console.log(message);
      }
      ```
    </Step>

    <Step title="Run with the import hook">
      ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      node --import braintrust/hook.mjs trace-claude-agent-auto.js
      ```

      The auto-instrumentation example uses plain JavaScript so `node --import` can run the file directly. The Braintrust APIs work the same in TypeScript projects — compile your TypeScript to JavaScript, then run the compiled file with the import hook.

      <Note>
        If you're using a bundler, see [Trace LLM calls](/instrument/trace-llm-calls#auto-instrumentation) for plugin and loader setup.
      </Note>
    </Step>
  </Steps>

  <h2 id="manual-instrumentation-typescript">
    Manual instrumentation
  </h2>

  To trace the Claude Agent SDK explicitly, wrap the SDK module with `wrapClaudeAgentSDK` and use the returned `query`, `tool`, and `createSdkMcpServer` functions. This example creates a calculator tool and traces a multi-step agent query.

  <CodeGroup>
    ```typescript title="claude-agent.ts" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import { initLogger, wrapClaudeAgentSDK } from "braintrust";
    import * as claudeSDK from "@anthropic-ai/claude-agent-sdk";
    import { z } from "zod";

    // Initialize Braintrust logging
    initLogger({
      projectName: "claude-agent-example",
      apiKey: process.env.BRAINTRUST_API_KEY,
    });

    // Wrap the Claude SDK with Braintrust tracing
    const { query, tool, createSdkMcpServer } = wrapClaudeAgentSDK(claudeSDK);

    // Create a calculator tool
    const calculator = tool(
      "calculator",
      "Performs basic arithmetic operations",
      {
        operation: z.enum(["add", "subtract", "multiply", "divide"]),
        a: z.number(),
        b: z.number(),
      },
      async (args: { operation: string; a: number; b: number }) => {
        console.log(`[Tool] Calculating: ${args.a} ${args.operation} ${args.b}`);

        let result = 0;
        switch (args.operation) {
          case "add":
            result = args.a + args.b;
            break;
          case "subtract":
            result = args.a - args.b;
            break;
          case "multiply":
            result = args.a * args.b;
            break;
          case "divide":
            if (args.b === 0) {
              return {
                content: [
                  {
                    type: "text",
                    text: "Error: Division by zero",
                  },
                ],
                isError: true,
              };
            }
            result = args.a / args.b;
            break;
        }

        return {
          content: [
            {
              type: "text",
              text: `The result of ${args.operation}(${args.a}, ${args.b}) is ${result}`,
            },
          ],
        };
      },
    );

    async function main() {
      console.log("Starting Claude Agent SDK example with Braintrust tracing...\n");

      try {
        // Query with mcp server for tool calls
        const result = query({
          prompt: "What is 15 multiplied by 7? Then subtract 5 from the result.",
          options: {
            model: "claude-sonnet-4-5-20250929",
            permissionMode: "bypassPermissions",
            mcpServers: {
              calculator: createSdkMcpServer({
                name: "calculator",
                version: "1.0.0",
                tools: [calculator],
              }),
            },
          },
        });

        // Stream the results
        for await (const message of result) {
          console.log(message);
        }

        console.log("\n\n✓ Example completed! Check Braintrust for tracing data.");
      } catch (error) {
        console.error("Error:", error);
        process.exit(1);
      }
    }

    main();
    ```
  </CodeGroup>

  <h3 id="nested-agents-typescript">
    Trace nested agent operations
  </h3>

  To organize agent calls into parent-child traces, wrap coordinating functions with `wrapTraced`. Braintrust captures the hierarchical relationships, making multi-step workflows easy to follow in your logs.

  ```typescript title="nested-agents.ts" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import { initLogger, wrapClaudeAgentSDK, wrapTraced } from "braintrust";
  import * as claudeSDK from "@anthropic-ai/claude-agent-sdk";

  initLogger({
    projectName: "nested-agents-example",
    apiKey: process.env.BRAINTRUST_API_KEY,
  });

  const { query } = wrapClaudeAgentSDK(claudeSDK);

  // Wrapped function creates a child trace
  const analyzeData = wrapTraced(
    async (data: string) => {
      const result = query({
        prompt: `Analyze this data and identify key patterns: ${data}`,
        options: {
          model: "claude-sonnet-4-5-20250929",
          permissionMode: "bypassPermissions",
        },
      });

      // Collect and return the analysis
      let analysis = "";
      for await (const message of result) {
        if (message.type === "result") {
          analysis = message.result;
        }
      }
      return analysis;
    },
    { name: "data-analyzer" },
  );

  // Parent function coordinates multiple operations
  async function coordinatorWorkflow() {
    // This call creates a child trace under the parent
    const analysis = await analyzeData("Sales data: Q1=100k, Q2=150k, Q3=180k, Q4=200k");

    console.log("Analysis complete:", analysis);

    // In Braintrust logs, you'll see both operations
    // linked in a parent-child relationship
  }

  coordinatorWorkflow();
  ```

  <h2 id="what-traced-typescript">
    What Braintrust traces
  </h2>

  Braintrust captures the Claude Agent SDK span tree for each query:

  * Agent run spans (`Claude Agent`), with the prompt as input and the query options as metadata.
  * Model call spans (`anthropic.messages.create`), with input messages, model, and assistant output; token metrics including prompt, completion, and cache read and creation tokens.
  * Tool call spans (named by the tool, such as `calculator`), with tool input and output, tool name, tool call ID, and MCP server.
  * Sub-agent spans (named by the sub-agent), with sub-agent metadata and token usage.
  * Parent-child nesting under any enclosing Braintrust span.

  <h2 id="resources-typescript">
    Resources
  </h2>

  * [Claude Agent SDK documentation](https://docs.claude.com/en/api/agent-sdk/)
  * [Anthropic API documentation](https://docs.anthropic.com/)
</View>

<View title="Python" icon="https://img.logo.dev/python.org?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
  <h2 id="setup-python">
    Setup
  </h2>

  Install the Braintrust SDK alongside the Claude Agent SDK:

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  pip install braintrust claude-agent-sdk
  ```

  <h2 id="auto-instrumentation-python">
    Auto-instrumentation
  </h2>

  To trace the Claude Agent SDK alongside Braintrust's other supported libraries, call `braintrust.auto_instrument()` before importing the SDK, then use `claude_agent_sdk` as normal. Because auto-instrumentation patches the SDK on import, call it first.

  <CodeGroup>
    ```python title="claude_agent_auto.py" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import asyncio
    import os

    import braintrust

    braintrust.auto_instrument()
    braintrust.init_logger(
        project="claude-agent-example",  # Replace with your project name
        api_key=os.environ.get("BRAINTRUST_API_KEY"),
    )

    # Import after auto_instrument() so the patched SDK is used
    from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient


    async def main() -> None:
        options = ClaudeAgentOptions(model="claude-sonnet-4-5-20250929")

        async with ClaudeSDKClient(options=options) as client:
            await client.query("What is 15 multiplied by 7? Then subtract 5 from the result.")
            async for message in client.receive_response():
                print(message)


    asyncio.run(main())
    ```
  </CodeGroup>

  <Accordion title="Instrument only Claude Agent SDK">
    To trace the Claude Agent SDK without auto-instrumenting other libraries, call `setup_claude_agent_sdk` instead. It patches the SDK's client, query, and MCP tool APIs, and initializes a logger for you. This example creates a calculator tool and traces a multi-step agent query.

    <CodeGroup>
      ```python title="claude_agent.py" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      #!/usr/bin/env python3

      import asyncio
      import os
      from typing import Any

      from braintrust.wrappers.claude_agent_sdk import setup_claude_agent_sdk
      from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient, create_sdk_mcp_server, tool

      # Setup claude_agent_sdk with braintrust tracing
      setup_claude_agent_sdk(
          project="claude-agent-example",
          api_key=os.environ.get("BRAINTRUST_API_KEY"),
      )

      # Create a calculator tool
      @tool(
          "calculator",
          "Performs basic arithmetic operations",
          {
              "operation": str,
              "a": float,
              "b": float,
          },
      )
      async def calculator(args: dict[str, Any]) -> dict[str, Any]:
          operation = args["operation"]
          a = float(args["a"])
          b = float(args["b"])

          print(f"[Tool] Calculating: {a} {operation} {b}")

          if operation == "add":
              result = a + b
          elif operation == "subtract":
              result = a - b
          elif operation == "multiply":
              result = a * b
          elif operation == "divide":
              if b == 0:
                  return {"content": [{"type": "text", "text": "Error: Division by zero"}], "is_error": True}
              result = a / b
          else:
              result = 0

          return {"content": [{"type": "text", "text": f"The result of {operation}({a}, {b}) is {result}"}]}

      async def main():
          print("Starting Claude Agent SDK example with Braintrust tracing...\n")

          try:
              # Create SDK MCP server with the calculator tool
              calculator_server = create_sdk_mcp_server(
                  name="calculator",
                  version="1.0.0",
                  tools=[calculator],
              )

              options = ClaudeAgentOptions(
                  model="claude-sonnet-4-5-20250929",
                  permission_mode="bypassPermissions",
                  mcp_servers={"calculator": calculator_server},
                  allowed_tools=["mcp__calculator__calculator"],
              )

              # Use a persistent client session to enable custom MCP tools
              async with ClaudeSDKClient(options=options) as client:
                  await client.query("What is 15 multiplied by 7? Then subtract 5 from the result.")
                  async for message in client.receive_response():
                      print(message)

              print("\n\n✓ Example completed! Check Braintrust for tracing data.")
          except Exception as error:
              print(f"Error: {error}")

      asyncio.run(main())
      ```
    </CodeGroup>
  </Accordion>

  <h2 id="what-traced-python">
    What Braintrust traces
  </h2>

  Braintrust mirrors the Claude Agent SDK span tree for each run:

  * Agent run spans (`Claude Agent`), with the conversation input and final result, plus run summary metadata (turn count, session ID, stop reason, cost, and duration).
  * Sub-agent task spans (named by the task description or type), with task metadata (task ID, session ID, status, and usage) and task output.
  * Model call spans (`anthropic.messages.create`), with the model, assistant output, token usage, and time-to-first-token.
  * Tool call spans (named by the tool, such as `calculator`), with tool input and output, tool name, tool call ID, and MCP server.
  * Hook spans (such as `PreToolUse hook`), with the hook event name, callback name, and output.
  * Parent-child nesting under any enclosing Braintrust span.

  <h2 id="resources-python">
    Resources
  </h2>

  * [Claude Agent SDK documentation](https://docs.claude.com/en/api/agent-sdk/)
  * [Anthropic API documentation](https://docs.anthropic.com/)
</View>
