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 from disk, through its own skill loader, not through the live router.
Install
Trace every run
query() returns an async iterator, so consuming it takes async for — and async for is only legal inside an async def. At module level it is a SyntaxError, not a runtime error: the file will not even import. asyncio.run() is the shortest way to get that function; from inside an event loop you already have (a notebook cell, a FastAPI handler) await main() instead.
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 usingClaudeSDKClient.receive_response():
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
ResultMessageis authoritative - Skills Claude Code loads from your installed skills, as activations with their version (SDK 0.16.0+; see Skills)
Skills: Claude Code loads them from disk
Claude Code reads skills from disk itself, so a registry skill reaches it as files. Install it into the project (SDK 0.15.0+):Load installed skills as a Claude Code plugin
decimalai skills keeps .agents/ as a Claude Code plugin named decimalai-skills, with the installed skills in its skills/ folder. Pass that folder to the Agent SDK as a local plugin with skills_plugin() (SDK 0.16.0+):
skills="all" also offers the model Claude Code’s own built-in skills alongside yours. To offer only your installed skills, list them by their plugin-qualified names instead, skills=["decimalai-skills:acme-refund-policy", ...] (the folder names under .agents/skills/). A list has to be updated when you add a skill: one left off is hidden from the model, and nothing reports it.
Interactively, the same plugin loads with:
--plugin-dir started from a subdirectory loads nothing and shows no error. skills_plugin() returns an absolute one from anywhere in the project.
- Each load is an activation (SDK 0.16.0+). With the stream traced (
init(claude_agent_sdk=True)ortrace_stream), each skill body the CLI hands the model is recorded as an activation carrying its version, and the DecimalAI skills in the CLI’s skill catalog as offered. The frontmatter never reaches your process, so the version comes from the lock, by the hash of the delivered body. Afterdecimalai skills update, Claude Code serves the new version. - Skill names carry the plugin’s prefix. Claude Code lists the skills as
decimalai-skills:acme-refund-policy. The plugin is not calleddecimalaibecause the marketplace plugin already has that name, and two plugins with one name replace each other. - Only skills your org wrote pre-approve tools. While a skill is active, Claude Code runs the tools its
allowed-toolslists without asking. The registry keeps that list whole only for a skill your org wrote itself; for any other, a fork or an import included, it keeps onlyRead,GrepandGlob, so running that skill’s scripts needs your permission. - On-demand skills stay on demand. A skill the registry marks on-demand carries
disable-model-invocation: true. Claude Code lists it but runs it only when you invoke it; of the native loaders, only Claude Code and the Pydantic AI harness honour that key.
There is no hosted-routing path on this integration. Skill selection happens inside Claude Code itself, so there is no DecimalAI skill router here to step aside and no routing decision on the trace. Installing a skill to disk is counted separately, as a fetch, and earns no use. What a run does with a skill is on its trace: the
Skill tool call with its input, and from SDK 0.16.0 the load itself as an activation on the usage ladder. See Native skill loaders for how the version is decided and how the other frameworks compare.decimalai skills update moves the project’s skills to their newest version, and decimalai skills install --frozen reproduces the locked files in CI. See Skills on disk. SDK-routed runtimes don’t need any of this: router.use() (or router.fork(), for an editable copy) puts the skill in your workspace, and the router serves it to the agents it reaches: use() to every agent unless you name some, and fork() to the agents you add it to (SDK 0.25.1+). router.install() is deprecated, and from SDK 0.15.0 it no longer forks. See Vocabulary.
Caveats
DECIMAL_AUTO_TRACEhas noclaude-agent-sdkvalue — useinit(claude_agent_sdk=True)in code.- Tool schema depth in the manifest is names only (
allowed_toolsis a name list). Useregister_manifest()if you need schema-aware regression checks. - This adapter is distinct from
decimalai.anthropic(agent_config()for the raw Messages API) and frominit(anthropic=True)(raw provider tracing). The Claude Agent SDK is Anthropic-native; pair it with theanthropicprovider 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
Installing skills to disk, native loaders, and the offered → delivered → activated ladder.
Manifests
Register a manifest explicitly to capture tool schemas.