# Pydantic AI

> Capture traces from Pydantic AI by pointing Logfire at Voxmith

## Choose a setup method

| Method | Use it when |
| - | - |
| **Voxmith skill** | You want your coding agent to inspect the app, make the change, and verify it. |
| **Voxmith SDK** | You want explicit control over the interaction boundaries and fields. |
| **OpenTelemetry** | The framework already emits useful spans or you operate an OTel pipeline. |

Start with one method for a call path. Combining SDK tracking with framework
OpenTelemetry on the same call can create duplicate interactions.

## Recommended: Voxmith skill

<Note>
  **Recommended.** Choose this path when you want your coding agent to inspect the
  project, select a supported transport, make the smallest instrumentation change,
  send a test event, and verify that it reached Voxmith.
</Note>

Install the skill once in your coding-agent environment:

```bash theme={null}
npx skills add Voxmith/skills --skill voxmith
```

Run the framework-specific prompt below from the application root. Review the
resulting diff before deploying it.

```text theme={null}
Use the voxmith skill to add Voxmith analytics to this Pydantic AI application.
Org ID: your-org-id
Instrument the real agent.run_sync() or agent.run() path and verify one fresh interaction.
```

## Manual setup: Voxmith SDK

```bash theme={null}
pip install voxmith
```

```python theme={null}
import voxmith

voxmith.init("your-org-id")
interaction = voxmith.begin(user_id="u-42", agent_name="pydantic-support", input=prompt)
try:
    result = agent.run_sync(prompt)
    interaction.end(output=str(result.output))
except Exception as exc:
    interaction.end(output=str(exc), success=False)
    raise
finally:
    voxmith.shutdown()
```

## Manual setup: OpenTelemetry

Pydantic AI uses Logfire for instrumentation. Point Logfire's OTLP exporter at Voxmith and disable its hosted backend.

### Install

```bash theme={null}
pip install pydantic-ai logfire
```

### Setup

```python theme={null}
import os, logfire
from pydantic_ai import Agent
from opentelemetry import trace

os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://otel.voxmith.com"
os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = "X-Voxmith-Org-ID=<your-org-id>"

logfire.configure(send_to_logfire=False)  # required: don't dual-send to Logfire
logfire.instrument_pydantic_ai()

agent = Agent("anthropic:claude-sonnet-4-5", system_prompt="...")

tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("chat-turn") as span:
    span.set_attribute("gen_ai.conversation.id", "sess-123")
    span.set_attribute("user.id", "u-42")
    agent.run_sync("Hello")
```

Spans use OTel GenAI semconv (`gen_ai.input.messages`, `gen_ai.output.messages`, `gen_ai.tool.call.arguments`, `gen_ai.usage.*`) plus `pydantic_ai.all_messages`. `gen_ai.conversation.id` is emitted natively when message history is provided to the agent.

### Caveats

Do **not** set `LOGFIRE_TOKEN`: that re-enables the hosted backend.

### Verify

Run one `agent.run_sync` call, then open **Events** in Voxmith. Confirm `gen_ai.*` and `pydantic_ai.*` attributes are present.

### Troubleshooting

* Keep `send_to_logfire=False` if you do not want dual-send to Logfire.
* Do not set `LOGFIRE_TOKEN` unless you explicitly want hosted Logfire enabled.
* Confirm `OTEL_EXPORTER_OTLP_HEADERS` contains `X-Voxmith-Org-ID=<your-org-id>`.

### References

* [Enable OpenTelemetry export](https://pydantic.dev/docs/ai/integrations/logfire/#otel-without-logfire)
* [Add custom metadata](https://pydantic.dev/docs/ai/integrations/logfire/#adding-custom-metadata)

## Next steps

* [Conversations](/using-conversations): review the complete Pydantic AI interaction.
* [Events](/using-events): inspect agent, model, and tool activity.
* [Intents](/using-intents): organize production conversations by what users wanted.
