Pydantic AI

Overview

Use respan-exporter-pydantic-ai to instrument Pydantic AI agents with Respan. Traces, spans, and metrics from agent runs (including LLM calls and tool use) are sent to Respan via OpenTelemetry and standard semantic conventions. The exporter requires respan-tracing (installed automatically).

You can route LLM calls through Respan as the gateway, so only your Respan API key is needed—no separate OpenAI key.

Setup

1. Install

$pip install pydantic-ai respan-exporter-pydantic-ai

2. Environment

Set RESPAN_API_KEY (required). Optional: RESPAN_BASE_URL (default https://api.respan.ai/api). For the gateway pattern, also set OPENAI_BASE_URL and OPENAI_API_KEY to your Respan base URL and API key so no separate OpenAI key is needed.

Examples

Each example below is a complete runnable script. Run it and open the Respan dashboard to see the trace.

Example: Hello World

Minimal instrumentation: initialize Respan, instrument Pydantic AI, run one agent call.

1import os
2
3# Route LLM calls through Respan (gateway pattern — only RESPAN_API_KEY needed)
4respan_api_key = os.environ["RESPAN_API_KEY"]
5respan_base_url = os.getenv("RESPAN_BASE_URL", "https://api.respan.ai/api")
6os.environ["OPENAI_BASE_URL"] = respan_base_url
7os.environ["OPENAI_API_KEY"] = respan_api_key
8
9from pydantic_ai import Agent
10from respan_tracing import RespanTelemetry
11from respan_exporter_pydantic_ai import instrument_pydantic_ai
12
13def main():
14 telemetry = RespanTelemetry(
15 app_name="pydantic-ai-hello-world",
16 api_key=respan_api_key,
17 base_url=respan_base_url,
18 )
19 instrument_pydantic_ai()
20
21 agent = Agent(
22 model="openai:gpt-4o",
23 system_prompt="You are a helpful assistant.",
24 )
25 result = agent.run_sync("What is the capital of France?")
26 print("Agent Output:", result.output)
27
28 telemetry.flush()
29
30if __name__ == "__main__":
31 main()

hello_world

Example: Gateway

Use Respan as the LLM gateway and control content capture with include_content and include_binary_content.

1import os
2
3respan_api_key = os.environ["RESPAN_API_KEY"]
4respan_base_url = os.getenv("RESPAN_BASE_URL", "https://api.respan.ai/api")
5os.environ["OPENAI_BASE_URL"] = respan_base_url
6os.environ["OPENAI_API_KEY"] = respan_api_key
7
8from pydantic_ai import Agent
9from respan_tracing import RespanTelemetry
10from respan_exporter_pydantic_ai import instrument_pydantic_ai
11
12def main():
13 telemetry = RespanTelemetry(
14 app_name="pydantic-ai-gateway",
15 api_key=respan_api_key,
16 base_url=respan_base_url,
17 )
18 instrument_pydantic_ai(
19 include_content=True,
20 include_binary_content=True,
21 )
22
23 agent = Agent(
24 model="openai:gpt-4o",
25 system_prompt="You are a helpful assistant.",
26 )
27 result = agent.run_sync("What is the capital of France?")
28 print("Agent Output:", result.output)
29
30 telemetry.flush()
31
32if __name__ == "__main__":
33 main()

gateway

Example: Workflows and tasks

Use @workflow and @task from respan-tracing to group spans into workflows and tasks.

1import os
2
3respan_api_key = os.environ["RESPAN_API_KEY"]
4respan_base_url = os.getenv("RESPAN_BASE_URL", "https://api.respan.ai/api")
5os.environ["OPENAI_BASE_URL"] = respan_base_url
6os.environ["OPENAI_API_KEY"] = respan_api_key
7
8from pydantic_ai import Agent
9from respan_tracing import RespanTelemetry
10from respan_tracing.decorators import workflow, task
11from respan_exporter_pydantic_ai import instrument_pydantic_ai
12
13agent = Agent("openai:gpt-4o", system_prompt="You are a helpful travel assistant.")
14
15@task(name="fetch_destination_info")
16def fetch_destination_info(destination: str) -> str:
17 result = agent.run_sync(f"Give me a one-sentence summary of {destination}.")
18 return result.output
19
20@workflow(name="travel_planning_workflow")
21def travel_planning_workflow(destination: str):
22 info = fetch_destination_info(destination)
23 return info
24
25def main():
26 telemetry = RespanTelemetry(
27 app_name="pydantic-ai-tracing",
28 api_key=respan_api_key,
29 base_url=respan_base_url,
30 )
31 instrument_pydantic_ai()
32 output = travel_planning_workflow("Paris")
33 print("Workflow Output:", output)
34 telemetry.flush()
35
36if __name__ == "__main__":
37 main()

tracing

Example: Respan params on spans

Set customer_identifier, metadata, and custom_tags on the current span with get_client().update_current_span(respan_params=...).

1import os
2
3respan_api_key = os.environ["RESPAN_API_KEY"]
4respan_base_url = os.getenv("RESPAN_BASE_URL", "https://api.respan.ai/api")
5os.environ["OPENAI_BASE_URL"] = respan_base_url
6os.environ["OPENAI_API_KEY"] = respan_api_key
7
8from pydantic_ai import Agent
9from respan_tracing import RespanTelemetry, get_client
10from respan_tracing.decorators import task
11from respan_exporter_pydantic_ai import instrument_pydantic_ai
12
13agent = Agent("openai:gpt-4o")
14
15@task(name="customer_query")
16def customer_query(query: str):
17 client = get_client()
18 if client:
19 client.update_current_span(
20 respan_params={
21 "customer_identifier": "user_12345",
22 "metadata": {"plan": "premium", "session_id": "abc-987"},
23 "custom_tags": ["pydantic-ai", "test-run"],
24 }
25 )
26 result = agent.run_sync(query)
27 return result.output
28
29def main():
30 telemetry = RespanTelemetry(
31 app_name="pydantic-ai-params",
32 api_key=respan_api_key,
33 base_url=respan_base_url,
34 )
35 instrument_pydantic_ai()
36 output = customer_query("Hello, who are you?")
37 print("Output:", output)
38 telemetry.flush()
39
40if __name__ == "__main__":
41 main()

respan_params

Example: Tool use

Agents that use tools are traced automatically; tool calls and results appear as spans.

1import os
2
3respan_api_key = os.environ["RESPAN_API_KEY"]
4respan_base_url = os.getenv("RESPAN_BASE_URL", "https://api.respan.ai/api")
5os.environ["OPENAI_BASE_URL"] = respan_base_url
6os.environ["OPENAI_API_KEY"] = respan_api_key
7
8from pydantic_ai import Agent
9from respan_tracing import RespanTelemetry
10from respan_tracing.decorators import workflow
11from respan_exporter_pydantic_ai import instrument_pydantic_ai
12
13agent = Agent(
14 "openai:gpt-4o",
15 system_prompt=(
16 "You are a calculator assistant. You must use the provided tools for any arithmetic. "
17 "Never compute numbers yourself; always call the add tool when asked to add numbers."
18 ),
19)
20
21@agent.tool_plain
22def add(a: int, b: int) -> int:
23 """Add two numbers together."""
24 return a + b
25
26@workflow(name="calculator_agent_run")
27def run_calculator_agent(prompt: str):
28 result = agent.run_sync(prompt)
29 return result.output
30
31def main():
32 telemetry = RespanTelemetry(
33 app_name="pydantic-ai-tool-use",
34 api_key=respan_api_key,
35 base_url=respan_base_url,
36 )
37 instrument_pydantic_ai()
38 output = run_calculator_agent("Use your add tool to compute 15 + 27, then reply with the result.")
39 print("Agent Output:", output)
40 telemetry.flush()
41
42if __name__ == "__main__":
43 main()

tool_use

Reference

RespanTelemetry options

ArgumentDescription
app_nameApplication name shown in Respan.
api_keyOptional if RESPAN_API_KEY is set.
base_urlOptional; overrides RESPAN_BASE_URL.
is_enabledSet to False to disable tracing.
is_batching_enabledBatch export (default: typically True); set False for immediate flush in tests.

instrument_pydantic_ai() options

ArgumentDescription
agentOptional. If provided, only that agent is instrumented; if None, all agents are instrumented globally.
include_contentInclude message content in telemetry (default: True).
include_binary_contentInclude binary content in telemetry (default: True).

Instrument a single agent

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

1agent = Agent("openai:gpt-4o")
2instrument_pydantic_ai(agent=agent)

Further reading