pydantic-ai-common-pitfalls by existential-birds/beagle
npx skills add https://github.com/existential-birds/beagle --skill pydantic-ai-common-pitfalls# 错误:tool_plain 中不允许使用 RunContext
@agent.tool_plain
async def bad_tool(ctx: RunContext[MyDeps]) -> str:
return "oops"
# UserError: RunContext 注解只能用于需要上下文的工具
修复方法:如果需要上下文,请使用 @agent.tool:
@agent.tool
async def good_tool(ctx: RunContext[MyDeps]) -> str:
return "works"
# 错误:第一个参数必须是 RunContext
@agent.tool
def bad_tool(user_id: int) -> str:
return "oops"
# UserError: 需要上下文的工具的第一个参数必须使用 RunContext[...] 注解
修复方法:将 RunContext 添加为第一个参数:
@agent.tool
def good_tool(ctx: RunContext[MyDeps], user_id: int) -> str:
return "works"
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
# 错误:RunContext 必须是第一个参数
@agent.tool
def bad_tool(user_id: int, ctx: RunContext[MyDeps]) -> str:
return "oops"
修复方法:RunContext 必须始终是第一个参数。
以下模式是有效的,并且 pydantic-ai 支持:
from pydantic_ai import Agent, RunContext
async def search_db(ctx: RunContext[MyDeps], query: str) -> list[dict]:
"""搜索数据库。"""
return await ctx.deps.db.search(query)
async def get_user(ctx: RunContext[MyDeps], user_id: int) -> dict:
"""根据 ID 获取用户。"""
return await ctx.deps.db.get_user(user_id)
# 有效:将原始函数传递给 Agent(tools=[...])
agent = Agent(
'openai:gpt-4o',
deps_type=MyDeps,
tools=[search_db, get_user] # 从函数签名中检测到 RunContext
)
为什么这有效:PydanticAI 会检查函数签名。如果第一个参数是 RunContext[T],则将其视为上下文感知工具。无需装饰器。
请勿标记将带有 RunContext 签名的函数传递给 Agent(tools=[...]) 的代码。这等同于使用 @agent.tool,并且有明确文档说明。
agent = Agent('openai:gpt-4o', deps_type=MyDeps)
# 错误:需要依赖项但未提供
result = agent.run_sync('Hello') # 缺少依赖项!
修复方法:设置 deps_type 时始终提供依赖项:
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)
# 类型错误: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')
# 如果 LLM 返回错误的结构,可能会失败
修复方法:增加重试次数或改进提示:
agent = Agent(
'openai:gpt-4o',
output_type=Response,
retries=3, # 更多尝试次数
instructions='返回包含 count(整数)和 items(字符串列表)的 JSON。'
)
# 某些模型可能导致模式问题
class Complex(BaseModel):
nested: dict[str, list[tuple[int, str]]]
修复方法:简化或使用中间模型:
class Item(BaseModel):
id: int
name: str
class Simple(BaseModel):
items: list[Item]
# 错误:无法在同步函数中等待
def handler():
result = await agent.run('Hello') # 语法错误!
修复方法:使用 run_sync 或将处理程序设为异步:
def handler():
result = agent.run_sync('Hello')
# 或者
async def handler():
result = await agent.run('Hello')
@agent.tool
async def slow_tool(ctx: RunContext[Deps]) -> str:
time.sleep(5) # 错误:阻塞事件循环!
return "done"
修复方法:使用异步 I/O:
@agent.tool
async def slow_tool(ctx: RunContext[Deps]) -> str:
await asyncio.sleep(5) # 正确
return "done"
# 错误:未设置 OPENAI_API_KEY
agent = Agent('openai:gpt-4o')
result = agent.run_sync('Hello')
# ModelAPIError: 身份验证失败
修复方法:设置环境变量或使用 defer_model_check:
# 用于测试
agent = Agent('openai:gpt-4o', defer_model_check=True)
with agent.override(model=TestModel()):
result = agent.run_sync('Hello')
# 错误:未知提供者
agent = Agent('unknown:model')
# ValueError: 未知模型提供者
修复方法:使用有效的 provider:model 格式。
async with agent.run_stream('Hello') as response:
# 在流式传输完成前不要访问 .output
print(response.output) # 可能不完整!
# 正确:在上下文管理器之后访问
print(response.output) # 完整结果
async with agent.run_stream('Hello') as response:
pass # 从未消费!
# 流从未被读取 - 输出可能不完整
修复方法:始终消费流:
async 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() # 无法序列化!
修复方法:返回可序列化的类型(str、dict、Pydantic 模型):
@agent.tool_plain
def good_return() -> dict:
return {"key": "value"}
import logfire
logfire.configure()
logfire.instrument_pydantic_ai()
# 或者按代理启用
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()) # 完整的消息历史
print(result.response) # 最后的模型响应
print(result.usage()) # 令牌使用情况
| 错误 | 原因 | 修复方法 |
|---|---|---|
First parameter... RunContext | @agent.tool 缺少 ctx | 添加 ctx: RunContext[...] |
RunContext... only... context | @agent.tool_plain 包含 ctx | 移除 ctx 或使用 @agent.tool |
Unknown model provider | 无效的模型字符串 | 使用有效的 provider:model |
ModelAPIError | API 身份验证/配额 | 检查 API 密钥、限制 |
RetryPromptPart 在消息中 | 验证失败 | 检查 output_type,增加重试次数 |
每周安装量
139
代码仓库
GitHub 星标数
40
首次出现
2026年1月20日
安全审计
安装于
opencode118
gemini-cli115
codex114
github-copilot108
cursor101
claude-code95
# 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
Fix : Use @agent.tool if you need context:
@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[...]
Fix : Add RunContext as first parameter:
@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"
Fix : RunContext must always be the first parameter.
The following pattern IS valid and supported by pydantic-ai:
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
)
Why this works: PydanticAI inspects function signatures. If the first parameter is RunContext[T], it's treated as a context-aware tool. No decorator required.
Reference: https://ai.pydantic.dev/agents/#registering-tools-via-the-tools-argument
Do NOT flag code that passes functions with RunContext signatures to Agent(tools=[...]). This is equivalent to using @agent.tool and is explicitly documented.
agent = Agent('openai:gpt-4o', deps_type=MyDeps)
# ERROR: deps required but not provided
result = agent.run_sync('Hello') # Missing deps!
Fix : Always provide deps when deps_type is set:
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 structure
Fix : Increase retries or improve prompt:
agent = 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]]]
Fix : Simplify or use intermediate models:
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!
Fix : Use run_sync or make handler async:
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"
Fix : Use async I/O:
@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
Fix : Set environment variable or use defer_model_check:
# 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 provider
Fix : Use valid provider:model format.
async 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 result
async with agent.run_stream('Hello') as response:
pass # Never consumed!
# Stream was never read - output may be incomplete
Fix : Always consume the stream:
async 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!
Fix : Return serializable types (str, dict, Pydantic model):
@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 |
|---|---|---|
First parameter... RunContext | @agent.tool missing ctx | Add ctx: RunContext[...] |
RunContext... only... context | @agent.tool_plain has ctx | Remove ctx or use @agent.tool |
Unknown model provider | Invalid model string | Use valid provider:model |
ModelAPIError |
Weekly Installs
139
Repository
GitHub Stars
40
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode118
gemini-cli115
codex114
github-copilot108
cursor101
claude-code95
超能力技能使用指南:AI助手技能调用优先级与工作流程详解
47,800 周安装
TanStack Table 模式指南:使用 Meta 字段优化 React 表格性能与类型安全
137 周安装
iOS系统集成开发指南:Siri、小组件、相机、应用内购买等完整解决方案
137 周安装
iOS/macOS 构建调试指南:解决 Xcode SPM/CocoaPods 依赖项与编译错误
137 周安装
STRING 数据库 API 技能:蛋白质相互作用网络查询与功能富集分析
137 周安装
视觉质量检查工具:AI自动化UI审查,发现间距、对齐、颜色、响应式设计问题
137 周安装
Encore.ts 入门指南:快速上手 TypeScript 微服务开发与部署
137 周安装
| API auth/quota |
| Check API key, limits |
RetryPromptPart in messages | Validation failed | Check output_type, increase retries |