How do you analyze your coding sessions with OpenTelemetry traces from Claude Code? A developer on the AGNT5 team enabled Claude Code's OpenTelemetry tracing, backed by a self-hosted Jaeger instance, to inspect what happens between prompts during coding sessions. The traces revealed Claude was repeatedly querying package versions from the shell because their skill file cited a version number without saying whether to trust it; adding one line instructing Claude to use the skill's versions eliminated the lookups. The writeup documents the Jaeger and settings.json setup, the span and attribute schema, and eight Python-based questions teams can ask of their own session traces. We use Claude Code every day to build AGNT5 https://agnt5.com , a platform for running AI agents and workflows. When a session was slow, or the result wasn't what we expected, we couldn't see why. We could read the conversation, but not what happened in between: which commands ran, what the tools returned, whether our skill loaded. A skill is a folder of instructions that Claude Code loads when a task needs it. Ours teaches it how to work with AGNT5. So we turned on Claude Code's OpenTelemetry tracing, which records every prompt, model call and tool call. One of the first things it showed us was something we could fix on our side. Claude was checking package versions online from the shell: tool Bash 62ms ls -la; pip index versions agnt5 | head -2; which agnt5 uv tool Bash 51ms uv pip index versions agnt5 | head -1 || curl -s https://pypi.org/pypi/agnt5/json | … tool Bash 292ms curl -s https://pypi.org/pypi/agnt5/json | …; agnt5 --version That was a sensible thing for it to do. Our skill mentioned a version number and didn't say whether to trust it. We added one line telling Claude to use the versions in the skill, and the lookups stopped. We wouldn't have found this from the conversation, or from counting web searches: there were only 2 in three days. This article shows how to set up the same tracing, how to read a trace, and eight questions you can answer about your own sessions, each with a few lines of Python and the output from ours. Each prompt you send becomes one trace. It's a tree of spans: claude code.interaction ← your prompt → Claude's answer ├── claude code.llm request ← each model call └── claude code.tool ← each tool call: Bash, Read, MCP, Skill… ├── tool.blocked on user ← time waiting for a permission decision └── tool.execution ← time actually running, success true/false Each span carries attributes. These are the ones this article uses: | Span | Attributes | |---|---| | interaction | user prompt | | llm request | model , query source why the call was made , input tokens , output tokens , cache read tokens , ttft ms time to first token , stop reason | | tool | tool name , tool input the command, file path or arguments , skill name | | tool.blocked on user | decision accept or reject , source your settings or you | | tool.execution | success , error | MCP calls are tool spans named mcp