pydantic_ai の承認付きツール登録
🧑 User
2026-11-08T14:04:02.809414Z
pydantic_ai.Agent を使って、agent = Agent(instructions=INSTRUCTIONS, output_type=[str, DeferredToolRequests]) で初期化した agent に、requires_approval=True をつけて agent.tool_plain() で関数をツールとして登録するにはどうコーディングしますか?
🤖 Claude
2026-11-08T14:04:14.752687Z
@agent.tool_plain にデコレータ引数として requires_approval=True を渡します。
from pydantic_ai import (
Agent,
DeferredToolRequests,
DeferredToolResults,
ToolDenied,
)
INSTRUCTIONS = "あなたは運用自動化アシスタントです。"
agent = Agent(
"openai:gpt-5", # 使用するモデルに置き換える
instructions=INSTRUCTIONS,
output_type=[str, DeferredToolRequests],
)
@agent.tool_plain(requires_approval=True)
def restart_service(service_name: str) -> str:
"""指定したサービスを再起動する(承認必須)。"""
# 実際の処理
return f"{service_name} を再起動しました"
承認が必要なツールをモデルが呼ぶと、そのツールは実行されません。代わりに result.output が DeferredToolRequests で返ってくるので、承認結果を渡して再実行します。
result = agent.run_sync("web-api を再起動して")
messages = result.all_messages()
if isinstance(result.output, DeferredToolRequests):
results = DeferredToolResults()
for call in result.output.approvals: # 承認待ちのツール呼び出し
print(call.tool_name, call.args)
if input("承認しますか? [y/N] ").lower() == "y":
results.approvals[call.tool_call_id] = True
else:
results.approvals[call.tool_call_id] = ToolDenied("ユーザーが拒否しました")
# 新しいプロンプトは渡さず、履歴と承認結果だけで再開する
result = agent.run_sync(
message_history=messages,
deferred_tool_results=results,
)
print(result.output)
補足です。
- 非同期版:
await agent.run(...)でも同じ流れです。 - 引数の上書き:
Trueの代わりにToolApproved(override_args={"service_name": "..."})を使うと、承認時に引数を書き換えられます。 - 条件付き承認: 状況によって承認の要否を変えたい場合は、
tool_plainではなく@agent.toolでRunContextを受け取ります。関数内でif not ctx.tool_call_approved: raise ApprovalRequiredとします。 - 必須の指定:
requires_approval=Trueを使う agent はoutput_typeにDeferredToolRequestsを含める必要があります。ご提示の初期化はこの条件を満たしています。
私の知識に基づく回答で、公式ドキュメントの最新版とは照合していません。インポート名やバージョン差が気になる場合は、Pydantic AI の "Deferred Tools" のページで確認してください。