Skip to content

PydanticAI Agent.iter() not instrumented — missing tool execution and chat spans #5606

@dfm88

Description

@dfm88

Agent.iter() not instrumented — missing tool execution and chat spans

Problem Statement

When using pydantic-ai's Agent.iter() to control agent execution step by step, Sentry does not create any spans. This means that tool calls, model requests, and the agent invocation itself are completely invisible in the Sentry UI.

This is a problem because iter() is the recommended way to drive an agent when you need fine-grained control over each execution step — for example, in real-time streaming scenarios like WebSocket consumers, where you want to process each node (tool call, model response, final result) as it arrives.

Agent.run() and Agent.run_stream() work fine and produce the expected spans. Only iter() is missing.

How to reproduce

import asyncio
import sentry_sdk
from sentry_sdk.integrations.pydantic_ai import PydanticAIIntegration
from pydantic_ai import Agent

sentry_sdk.init(
    dsn="YOUR_DSN",
    integrations=[PydanticAIIntegration()],
    traces_sample_rate=1.0,
    send_default_pii=True,
)

agent = Agent("openai:gpt-4.1-mini", system_prompt="You are a helpful assistant.")

@agent.tool_plain
def get_weather(city: str) -> str:
    """Get the weather for a city."""
    return f"Sunny in {city}"

async def main():
    # This works — creates invoke_agent, gen_ai.chat, and gen_ai.execute_tool spans:
    result = await agent.run("What's the weather in Paris?")

    # This does NOT create any spans (the bug):
    async with agent.iter("What's the weather in London?") as agent_run:
        async for node in agent_run:
            pass  # each node is processed but nothing shows up in Sentry

asyncio.run(main())

Expected behavior

Agent.iter() should create an invoke_agent span with child gen_ai.chat and gen_ai.execute_tool spans, just like Agent.run() and Agent.run_stream() do.

Additional context

In pydantic-ai v1.x, Agent.run() and Agent.run_stream() internally delegate to Agent.iter(). This means that any patch for iter() needs passthrough detection to avoid creating duplicate invoke_agent spans when run() or run_stream() are used — otherwise you'd get two nested spans for a single agent call.

pydantic-ai >= 1.0.0 is required (that's when iter() was introduced), as from sentry docs this is the minnimum verdsion supported.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Waiting for: Product Owner

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions