mcpField
P
pydantic-ai-common-pitfalls

pydantic-ai-common-pitfalls

github.com/existential-birdsエージェントワークフロー85220 回インストール11 週間前に更新
リポジトリ

pydantic-ai-common-pitfalls について

PydanticAI を使う開発者向けのデバッグ資料です。ツール定義、依存関係の受け渡し、出力検証、モデル設定、ストリーミングの誤りと、実行メッセージやトレースによる調査方法を扱います。

主な機能

  1. 01ツールデコレーターの使い方
  2. 02依存関係と型チェックの確認
  3. 03構造化出力のトラブルシューティング
  4. 04モデル設定とストリーミングの注意点
  5. 05メッセージ取得とトレースの例

活用シーン

  1. 01RunContext 引数の誤りを診断
  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"}

デバッグのヒント

ゲート(原因が曖昧な失敗)

エージェントが想定どおりに動作しないものの、スタックトレースやエラー文字列から原因がわからない場合は、次の手順を順番に実施し、先に進んで手順を飛ばさないでください。

  1. 証拠を取得する — capture_run_messages() を使って再実行するか、run/run_sync の実行後に result.all_messages() を調べます(またはメッセージ型を順番に出力します)。合格条件: 失敗を説明するメッセージパートの型と内容を1行で示せること(例: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 in messages検証に失敗したoutput_type を確認し、リトライ回数を増やす

コメント