Skip to main content
The Claude Agent SDK (claude-agent-sdk) runs a tool-use loop against the Claude Code engine. It exposes no global callback system, so DecimalAI traces it by wrapping the message stream: every message passes through to your code unchanged while the SDK accumulates one trace per query() run — model turns, tool calls with inputs and results, token usage, and cost. This page also covers Claude Code as a skill runtime: skills reach it via disk install, not the live router.

Install

Trace every run

The flag form monkeypatches claude_agent_sdk.query. Call init() before binding query by name (from claude_agent_sdk import query), or call it off the module (claude_agent_sdk.query(...)), so you get the patched symbol.

Explicit form — wrap a stream you already have

No monkeypatch; useful when you only want some runs traced or you’re using ClaudeSDKClient.receive_response():
There’s also traced_query(prompt=..., options=..., agent_name=...) — a convenience that calls query() and wraps it in one step.

What gets captured

  • One trace per query() run: every assistant turn as an LLM call, tool calls matched to their results (with latency and per-tool error status)
  • Cumulative token usage and cost from the final ResultMessage, including cache-read/creation input tokens
  • Auto-detected manifest from ClaudeAgentOptions + the init message: model, system prompt, allowed tools (names), and subagents
  • Run status: a failed tool doesn’t fail the run — the ResultMessage is authoritative
The wrapper is observability-only: it never alters or swallows messages, and an ingest failure never breaks your run.

Skills: disk install, no live router

Claude Code loads skills from disk (.claude/skills/), not from a hosted menu. Install registry skills into it with:
There is no hosted-routing path on this integration. Skill selection happens inside Claude Code itself, so router-side effectiveness data (offered/delivered counts, activation rates) isn’t collected for skills used this way. A disk install counts as delivered on the usage ladder — what the runtime does with it after that isn’t measurable from the SDK side.
install() also writes for other disk-loading runtimes (agents=["claude-code", "cursor"], scope "project" or "global"). SDK-routed runtimes don’t need it — fork() alone puts the skill in your workspace.

Caveats

  • DECIMAL_AUTO_TRACE has no claude-agent-sdk value — use init(claude_agent_sdk=True) in code.
  • Tool schema depth in the manifest is names only (allowed_tools is a name list). Use register_manifest() if you need schema-aware regression checks.
  • Per-turn token usage isn’t exposed in the stream; the run’s cumulative usage attaches to the final LLM call.
  • This adapter is distinct from decimalai.anthropic (the raw Messages-API skill-injection adapter) and from init(anthropic=True) (raw provider tracing). The Claude Agent SDK is Anthropic-native; pair it with the anthropic provider only.
Checkpoint: run one query() to completion. Startup logs show DecimalAI Claude Agent SDK tracing installed globally, and the run appears in Traces with one LLM call per assistant turn and your tool calls matched to results.

What’s next

Skills

The offered → delivered → activated ladder and what disk installs count as.

Manifests

Register a manifest explicitly to capture tool schemas.