mcpField
P
pydantic-ai-common-pitfalls

pydantic-ai-common-pitfalls

github.com/existential-birdsAgent 工作流85220 次安装11 周前更新
代码仓库

关于 pydantic-ai-common-pitfalls

面向使用 PydanticAI 的开发者,整理工具定义、依赖传递、输出校验、模型配置与流式调用中的常见错误及排查步骤。还提供消息捕获和追踪示例,帮助依据运行证据定位问题。

主要功能

  1. 01工具装饰器使用规范
  2. 02依赖与类型检查建议
  3. 03结构化输出故障排查
  4. 04模型配置与流式调用提示
  5. 05消息捕获和追踪示例

适用场景

  1. 01排查 RunContext 参数错误
  2. 02诊断依赖未传入的问题
  3. 03定位输出类型校验失败
  4. 04检查流式结果是否完整

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/existential-birds/beagle --skill pydantic-ai-common-pitfalls

安装后在 Claude Code 中输入/pydantic-ai-common-pitfalls确认已加载。

详细介绍

PydanticAI 常见陷阱与调试

工具装饰器错误

错误:在 tool_plain 中使用 RunContext
# 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"
错误:在 tool 中缺少 RunContext
# 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[...]

修复方法:将 RunContext 添加为第一个参数:

@agent.tool
def good_tool(ctx: RunContext[MyDeps], user_id: int) -> str:
    return "works"
错误:RunContext 不是第一个参数
# ERROR: RunContext must be first parameter
@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]:
    """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
)

为何有效: PydanticAI 会检查函数签名。如果第一个参数是 RunContext[T],就会将其视为可访问上下文的工具。无需装饰器。

参考: https://ai.pydantic.dev/agents/#registering-tools-via-the-tools-argument

不要将传入带有 RunContext 签名的函数并调用 Agent(tools=[...]) 的代码标记为错误。这与使用 @agent.tool 等效,并且有明确文档说明。

依赖类型不匹配

错误:运行时缺少 deps
agent = Agent('openai:gpt-4o', deps_type=MyDeps)

# ERROR: deps required but not provided
result = agent.run_sync('Hello')  # Missing deps!

修复方法:设置 deps_type 后,务必提供 deps:

result = agent.run_sync('Hello', deps=MyDeps(...))
错误:deps 类型错误
@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(...))

输出类型问题

Pydantic 验证失败
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

修复方法:增加重试次数或改进提示词:

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]]]

修复方法:简化类型或使用中间模型:

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!

修复方法:使用 run_sync,或将处理函数改为异步:

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"

修复方法:使用异步 I/O:

@agent.tool
async def slow_tool(ctx: RunContext[Deps]) -> str:
    await asyncio.sleep(5)  # Correct
    return "done"

模型配置错误

缺少 API 密钥
# ERROR: OPENAI_API_KEY not set
agent = Agent('openai:gpt-4o')
result = agent.run_sync('Hello')
# ModelAPIError: Authentication failed

修复方法:设置环境变量或使用 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

修复方法:使用有效的 provider:model 格式。

流式处理问题

错误:流尚未完成就使用结果
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

修复方法:务必读取完整个流:

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!

修复方法:返回可序列化的类型(str、dict、Pydantic 模型):

@agent.tool_plain
def good_return() -> dict:
    return {"key": "value"}

调试提示

关卡(失败原因不明确)

当 Agent 行为异常,但堆栈跟踪或错误字符串不明确时,请按顺序执行以下步骤;不要跳过。

  1. 收集证据 — 使用 capture_run_messages() 重新运行,或在 run/run_sync 后检查 result.all_messages()(或按顺序打印消息类型)。**通过标准:**你能说出消息部分类型,并指出一行解释失败原因的内容(例如 RetryPromptPart、工具返回值、模型文本)。
  2. 区分模型问题与架构问题 — 如果出现验证错误或 RetryPromptPart,请将模型的最后一条消息与 output_type 的字段和类型进行比较。**通过标准:**在单纯增加 retries 或更换模型之前,你已找出具体不匹配之处(缺少字段、类型错误、拒绝回答)。
  3. 确认每条路径上的 deps — 如果工具或 deps 出错,请确认每个调用点(run、run_sync、run_stream)在设置了 deps_type 时都提供了 deps=...。**通过标准:**使用显式 deps 的最小复现能确认或排除 deps 传递错误。
启用跟踪
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

常见错误消息

错误原因修复方法
First parameter... RunContext@agent.tool 缺少 ctx添加 ctx: RunContext[...]
RunContext... only... context@agent.tool_plain 带有 ctx移除 ctx 或使用 @agent.tool
Unknown model provider模型字符串无效使用有效的 provider:model
ModelAPIErrorAPI 身份验证/配额问题检查 API 密钥和限额
消息中出现 RetryPromptPart验证失败检查 output_type,增加重试次数

评论

支持 Markdown