Loading...
Loading...
Avoid common mistakes and debug issues in PydanticAI agents. Use when encountering errors, unexpected behavior, or when reviewing agent implementations.
npx skill4agent add existential-birds/beagle pydantic-ai-common-pitfalls# ERROR: RunContext not allowed in tool_plain
@agent.tool_plain
async def bad_tool(ctx: RunContext[MyDeps]) -> str:
return "oops"
# UserError: RunContext annotations can only be used with tools that take context@agent.tool@agent.tool
async def good_tool(ctx: RunContext[MyDeps]) -> str:
return "works"# ERROR: First param must be RunContext
@agent.tool
def bad_tool(user_id: int) -> str:
return "oops"
# UserError: First parameter of tools that take context must be annotated with RunContext[...]@agent.tool
def good_tool(ctx: RunContext[MyDeps], user_id: int) -> str:
return "works"# ERROR: RunContext must be first parameter
@agent.tool
def bad_tool(user_id: int, ctx: RunContext[MyDeps]) -> str:
return "oops"from pydantic_ai import Agent, RunContext
async def search_db(ctx: RunContext[MyDeps], query: str) -> list[dict]:
"""Search the database."""
return await ctx.deps.db.search(query)
async def get_user(ctx: RunContext[MyDeps], user_id: int) -> dict:
"""Get user by ID."""
return await ctx.deps.db.get_user(user_id)
# Valid: Pass raw functions to Agent(tools=[...])
agent = Agent(
'openai:gpt-4o',
deps_type=MyDeps,
tools=[search_db, get_user] # RunContext detected from signature
)RunContext[T]RunContextAgent(tools=[...])@agent.toolagent = Agent('openai:gpt-4o', deps_type=MyDeps)
# ERROR: deps required but not provided
result = agent.run_sync('Hello') # Missing deps!result = agent.run_sync('Hello', deps=MyDeps(...))@dataclass
class AppDeps:
db: Database
@dataclass
class WrongDeps:
api: ApiClient
agent = Agent('openai:gpt-4o', deps_type=AppDeps)
# Type error: WrongDeps != AppDeps
result = agent.run_sync('Hello', deps=WrongDeps(...))class Response(BaseModel):
count: int
items: list[str]
agent = Agent('openai:gpt-4o', output_type=Response)
result = agent.run_sync('List items')
# May fail if LLM returns wrong structureagent = Agent(
'openai:gpt-4o',
output_type=Response,
retries=3, # More attempts
instructions='Return JSON with count (int) and items (list of strings).'
)# May cause schema issues with some models
class Complex(BaseModel):
nested: dict[str, list[tuple[int, str]]]class Item(BaseModel):
id: int
name: str
class Simple(BaseModel):
items: list[Item]# ERROR: Can't await in sync function
def handler():
result = await agent.run('Hello') # SyntaxError!def handler():
result = agent.run_sync('Hello')
# Or
async def handler():
result = await agent.run('Hello')@agent.tool
async def slow_tool(ctx: RunContext[Deps]) -> str:
time.sleep(5) # WRONG: Blocks event loop!
return "done"@agent.tool
async def slow_tool(ctx: RunContext[Deps]) -> str:
await asyncio.sleep(5) # Correct
return "done"# ERROR: OPENAI_API_KEY not set
agent = Agent('openai:gpt-4o')
result = agent.run_sync('Hello')
# ModelAPIError: Authentication failed# For testing
agent = Agent('openai:gpt-4o', defer_model_check=True)
with agent.override(model=TestModel()):
result = agent.run_sync('Hello')# ERROR: Unknown provider
agent = Agent('unknown:model')
# ValueError: Unknown model providerasync with agent.run_stream('Hello') as response:
# DON'T access .output before streaming completes
print(response.output) # May be incomplete!
# Correct: access after context manager
print(response.output) # Complete resultasync with agent.run_stream('Hello') as response:
pass # Never consumed!
# Stream was never read - output may be incompleteasync with agent.run_stream('Hello') as response:
async for chunk in response.stream_output():
print(chunk, end='')@agent.tool_plain
def bad_return() -> object:
return CustomObject() # Can't serialize!@agent.tool_plain
def good_return() -> dict:
return {"key": "value"}import logfire
logfire.configure()
logfire.instrument_pydantic_ai()
# Or per-agent
agent = Agent('openai:gpt-4o', instrument=True)from pydantic_ai import capture_run_messages
with capture_run_messages() as messages:
result = agent.run_sync('Hello')
for msg in messages:
print(type(msg).__name__, msg)result = agent.run_sync('Hello')
print(result.all_messages()) # Full message history
print(result.response) # Last model response
print(result.usage()) # Token usage| Error | Cause | Fix |
|---|---|---|
| @agent.tool missing ctx | Add |
| @agent.tool_plain has ctx | Remove ctx or use @agent.tool |
| Invalid model string | Use valid |
| API auth/quota | Check API key, limits |
| Validation failed | Check output_type, increase retries |