Pydantic AI v3+ tool spans show blank input/output in Conversation: map gen_ai.tool.call.arguments/result
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 39.9k
- Forks
- 3.4k
- Avg merge
- 7h 27m
- Merged PRs (30d)
- 222
Description
Bug Description
Summary
- Pydantic AI tool spans are successfully ingested by PostHog, but their input and output are blank in the Conversation tab.
- The span’s Raw tab contains the current OpenTelemetry GenAI tool attributes:
gen_ai.tool.call.argumentsgen_ai.tool.call.result
However, Conversation displays which affects tool spans only. Model-generation spans in the same trace displaytheir input and output normally.
- Input:
No input - Output:
No output
Trace link: https://eu.posthog.com/project/27465/ai-observability/traces/80ce134e484d6cdfbf8c44e25b5e960c?timestamp=2026-09-04T09%3A33%3A43Z&event=01a06bc9-1a86-71c2-93a8-38fb451d4deb
Expected behavior
For Pydantic AI v3+ tool spans, PostHog should normalize:
gen_ai.tool.call.arguments→$ai_input_stategen_ai.tool.call.result→$ai_output_state
The existing Conversation view should then render the tool arguments and tool result.
Legacy Pydantic AI v2 fields should continue to work:
tool_argumentstool_response
Actual behavior
PostHog receives the dotted Pydantic AI / OpenTelemetry fields and leaves them visible in Raw, but does not create $ai_input_state or $ai_output_state.
The Conversation view reads those normalized state properties for $ai_span events, so it shows No input and No output.
Why this appears to be a compatibility gap
Pydantic AI defaults to instrumentation format v5. v3+ emits the current
OpenTelemetry-style names:
gen_ai.tool.call.argumentsgen_ai.tool.call.result
The Pydantic AI OTel middleware currently handles only the older flat
Pydantic v2 keys:
tool_argumentstool_response
Relevant PostHog source:
- https://github.com/PostHog/posthog/blob/master/nodejs/src/ingestion/pipelines/ai/otel/middleware/pydantic-ai.ts
- https://github.com/PostHog/posthog/blob/master/products/ai_observability/frontend/ConversationDisplay/ConversationDisplay.tsx
How to reproduce
- Configure Pydantic AI instrumentation with a PostHog OpenTelemetry exporter. Do not set
InstrumentationSettings.version, so Pydantic AI uses its default instrumentation format v5. - Run an agent that calls a function tool with content capture enabled.
- Open the resulting trace in PostHog AI Observability.
- Select the tool span.
- In the Raw tab, observe both:
gen_ai.tool.call.argumentsgen_ai.tool.call.result
- Switch to the Conversation tab.
- Observe that the span shows:
- Input:
No input - Output:
No output
- Input:
Additional context
The raw attributes prove this is not an exporter or include_content problem:
the tool arguments and result have already reached PostHog.
Suggested mapper behavior:
const rawArgs =
props['gen_ai.tool.call.arguments'] ?? props['tool_arguments']
const rawResult =
props['gen_ai.tool.call.result'] ?? props['tool_response']
PostHog should preserve its existing JSON parsing and write the resolved values to $ai_input_state and $ai_output_state.
Suggested regression coverage:
- Legacy Pydantic AI v2:
tool_arguments/tool_response - Current Pydantic AI v3+ and default v5:
gen_ai.tool.call.arguments/gen_ai.tool.call.result - JSON-string arguments, JSON-string results, and plain-text results.
I did not find an existing public PostHog issue for this exact tool-span mapping problem.
Debug info
- [x] PostHog Cloud, region and project ID: EU, project ID: <fill in your project ID>
- [ ] PostHog Hobby self-hosted with `docker compose`, version/commit: N/A
- [ ] You’re self-hosted with Kubernetes: N/A
Client environment:
- posthog-python: 7.45.1
- pydantic-ai: 2.36.0
- opentelemetry-sdk: 1.44.0
- Pydantic AI instrumentation format: v5 default
- Event transport: OpenTelemetry to PostHog AI endpoint
- Tool arguments/results are visible in the PostHog Raw tab
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in nodejs/src/ingestion/pipelines/ai/otel/middleware/pydantic-ai.ts and inspect how tool_arguments and tool_response are mapped into normalized AI state properties. Add regression coverage for legacy and gen_ai.tool.call.arguments/result attributes, including JSON-string and plain-text values, then run the relevant middleware tests and confirm Conversation displays the tool input and output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, typescript
- Domain
- ai, backend, observability
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100