> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zespan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pydantic AI

> Configure a Python Pydantic AI agent to export its OpenTelemetry/Logfire traces to Zespan, using an environment variable helper from the Zespan TypeScript SDK.

<Note>
  Available for: **Python** agents (configured via a **TypeScript** helper).
</Note>

<Note>
  Pydantic AI is a Python-only agent framework, but the helper for it lives in `@zespan/sdk` (TypeScript). There's no Python-side `zespan.integrations.pydantic_ai` module and no wrapper function to call from your agent code — `getPydanticAIConfig()` is a one-off config generator, not a runtime integration.
</Note>

## How this integration works

Pydantic AI instruments itself with [Logfire](https://logfire.pydantic.dev), which is OpenTelemetry-native. Instead of wrapping calls in your agent code, you point Logfire's OTel exporter at Zespan's ingest endpoint using environment variables. `getPydanticAIConfig(otlpEndpoint)` builds that exact set of environment variables for you from a single OTLP endpoint argument, so you don't have to hand-write Logfire's variable names yourself.

Because it's a config generator rather than something that runs inside your Python process, you typically call it once — from wherever you already provision the Python agent's environment (a Node/TS setup script, an internal deploy tool, a Dockerfile build stage, a CI job) — and then apply the resulting values to that process.

## Installation

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
# Wherever you generate the env vars (Node/TS tooling)
npm install @zespan/sdk

# In the Python environment that runs the Pydantic AI agent
pip install pydantic-ai logfire
```

## Usage

Call `getPydanticAIConfig()` with the OTLP endpoint you want the agent to export to. It returns a plain `Record<string, string>` — it only builds the values, it does not set them in any environment for you.

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
import { getPydanticAIConfig } from "@zespan/sdk";

const config = getPydanticAIConfig("http://localhost:4318");

console.log(config);
// {
//   OTEL_EXPORTER_OTLP_ENDPOINT: "http://localhost:4318",
//   OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf",
//   OTEL_SERVICE_NAME: "pydantic-ai-agent",
//   LOGFIRE_SEND_TO_LOGFIRE: "false",
// }
```

## What it generates

| Variable                      | Value                                   | Purpose                                                                                                   |
| ----------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | The `otlpEndpoint` argument you pass in | Where the OTLP exporter sends spans                                                                       |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | `http/protobuf`                         | Wire protocol used for the OTLP export                                                                    |
| `OTEL_SERVICE_NAME`           | `pydantic-ai-agent`                     | Service name attached to every exported span                                                              |
| `LOGFIRE_SEND_TO_LOGFIRE`     | `false`                                 | Stops Logfire from also forwarding spans to Logfire's own cloud, so Zespan is the only export destination |

## Applying the config to your Python process

`getPydanticAIConfig()` only produces the four values above — getting them into the environment the Python process reads from is a separate step. A few common ways to do that:

**Write a `.env` file the Python process loads on startup:**

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
import { writeFileSync } from "node:fs";
import { getPydanticAIConfig } from "@zespan/sdk";

const config = getPydanticAIConfig("http://localhost:4318");

const envFile = Object.entries(config)
  .map(([key, value]) => `${key}=${value}`)
  .join("\n");

writeFileSync(".env", envFile);
```

**Pass them directly when spawning the Python process:**

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
import { spawn } from "node:child_process";
import { getPydanticAIConfig } from "@zespan/sdk";

const config = getPydanticAIConfig("http://localhost:4318");

spawn("python", ["agent.py"], {
  env: { ...process.env, ...config },
});
```

**Or set them manually** in whatever mechanism configures the Python environment — these four keys are the entire contract; nothing else needs to change in your Pydantic AI code:

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_SERVICE_NAME=pydantic-ai-agent
export LOGFIRE_SEND_TO_LOGFIRE=false
```

Once those variables are set, Pydantic AI's own Logfire integration picks them up automatically:

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
import logfire
from pydantic_ai import Agent

logfire.configure(send_to_logfire=False)  # OTel export only, no Logfire cloud
logfire.instrument_pydantic_ai()

agent = Agent("openai:gpt-4o", instructions="Be concise.")

result = agent.run_sync("What is the capital of France?")
print(result.output)
```

<Note>
  There's no Python-side `zespan` package involved in this flow. Zespan's role is limited to generating the right OTel/Logfire environment variables from the TypeScript SDK — everything else is standard Pydantic AI and Logfire instrumentation.
</Note>
