Pydantic AI

Pydantic AI is a Python agent framework from the creators of Pydantic. It provides a type-safe way to build agents with tools, structured outputs, and multi-model support. Respan gives you full observability over every agent run, model call, and tool invocation — and gateway routing through the OpenAI-compatible Respan endpoint.

Create an account at platform.respan.ai and grab an API key. For gateway, also add credits or a provider key.

Run npx @respan/cli setup to set up with your coding agent.

Setup

1

Install packages

$pip install respan-ai respan-instrumentation-pydantic-ai pydantic-ai
2

Set environment variables

$export OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
$export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"

This example uses the OpenAI provider directly. OPENAI_API_KEY is used for model requests, and RESPAN_API_KEY is used to export traces to Respan.

3

Initialize and run

Python
1from pydantic_ai import Agent
2from respan import Respan
3from respan_instrumentation_pydantic_ai import PydanticAIInstrumentor
4
5respan = Respan(
6 instrumentations=[PydanticAIInstrumentor()],
7)
8
9agent = Agent(
10 model="openai:gpt-4o",
11 system_prompt="You are a helpful assistant.",
12)
13
14result = agent.run_sync("What is the capital of France?")
15print(result.output)
16respan.flush()
4

View your trace

Open the Traces page to see your agent run with model spans, tool calls, tokens, and cost.

Configuration

ParameterTypeDefaultDescription
api_keystr | NoneNoneFalls back to RESPAN_API_KEY env var.
base_urlstr | NoneNoneFalls back to RESPAN_BASE_URL env var.
instrumentationslist[]Plugin instrumentations to activate (e.g. PydanticAIInstrumentor()).
customer_identifierstr | NoneNoneDefault customer identifier for all spans.
metadatadict | NoneNoneDefault metadata attached to all spans.
environmentstr | NoneNoneEnvironment tag (e.g. "production").

PydanticAIInstrumentor options

ParameterTypeDefaultDescription
agentAgent | NoneNoneInstrument a single agent. If None, all agents are instrumented globally.
include_contentboolTrueInclude message content in telemetry.
include_binary_contentboolTrueInclude binary content in telemetry.

Instrument a single agent

By default, PydanticAIInstrumentor() instruments all Pydantic AI agents globally. To instrument only one agent:

1from pydantic_ai import Agent
2from respan import Respan
3from respan_instrumentation_pydantic_ai import PydanticAIInstrumentor
4
5agent = Agent(model="openai:gpt-4o")
6
7respan = Respan(
8 instrumentations=[PydanticAIInstrumentor(agent=agent)],
9)

Attributes

In Respan()

Set defaults at initialization — these apply to all spans.

Python
1from respan import Respan
2from respan_instrumentation_pydantic_ai import PydanticAIInstrumentor
3
4respan = Respan(
5 instrumentations=[PydanticAIInstrumentor()],
6 customer_identifier="user_123",
7 metadata={"service": "assistant-api", "version": "1.0.0"},
8)

With propagate_attributes

Override per-request using a context scope.

Python
1from pydantic_ai import Agent
2from respan import Respan, propagate_attributes
3from respan_instrumentation_pydantic_ai import PydanticAIInstrumentor
4
5respan = Respan(
6 instrumentations=[PydanticAIInstrumentor()],
7)
8
9agent = Agent(
10 model="openai:gpt-4o",
11 system_prompt="You are a helpful assistant.",
12)
13
14def handle_request(user_id: str, message: str):
15 with propagate_attributes(
16 customer_identifier=user_id,
17 thread_identifier="conv_abc_123",
18 metadata={"plan": "pro"},
19 ):
20 result = agent.run_sync(message)
21 print(result.output)
AttributeTypeDescription
customer_identifierstrIdentifies the end user in Respan analytics.
thread_identifierstrGroups related messages into a conversation.
metadatadictCustom key-value pairs. Merged with default metadata.

Decorators (optional)

Decorators are not required. Pydantic AI model spans and tool calls are auto-traced by the instrumentor. Use @workflow and @task when you want to add structure around one or more agent runs.

1from pydantic_ai import Agent
2from respan import Respan, workflow, task
3from respan_instrumentation_pydantic_ai import PydanticAIInstrumentor
4
5respan = Respan(
6 instrumentations=[PydanticAIInstrumentor()],
7)
8
9agent = Agent(
10 model="openai:gpt-4o",
11 system_prompt="You are a helpful travel assistant.",
12)
13
14@task(name="fetch_destination_info")
15def fetch_destination_info(destination: str) -> str:
16 result = agent.run_sync(f"Give me a one-sentence summary of {destination}.")
17 return result.output
18
19@workflow(name="travel_planning_workflow")
20def travel_planning_workflow(destination: str) -> str:
21 return fetch_destination_info(destination)
22
23print(travel_planning_workflow("Paris"))
24respan.flush()

Examples

Tool calls

Tool calls are automatically captured as spans with inputs, outputs, and timing.

1from pydantic_ai import Agent
2
3agent = Agent(
4 model="openai:gpt-4o",
5 system_prompt=(
6 "You are a calculator assistant. You must use the provided tools for any arithmetic. "
7 "Never compute numbers yourself; always call the add tool when asked to add numbers."
8 ),
9)
10
11@agent.tool_plain
12def add(a: int, b: int) -> int:
13 return a + b
14
15result = agent.run_sync(
16 "Use your add tool to compute 15 + 27, then reply with the result."
17)
18print(result.output)

Structured output

Structured outputs are traced the same way as normal agent runs.

1from pydantic import BaseModel
2from pydantic_ai import Agent
3
4class TravelAnswer(BaseModel):
5 city: str
6 summary: str
7
8agent = Agent(
9 model="openai:gpt-4o",
10 system_prompt="You are a helpful travel assistant.",
11 output_type=TravelAnswer,
12)
13
14result = agent.run_sync("Recommend a weekend trip to Paris.")
15print(result.output)