integrate-arcjet-guard-openai-agents-py について
公式 OpenAI Agents SDK の独自 FunctionTool に Arcjet Guard を適用する Python スキルです。ツールのコピーに入力ガードレールを加え、呼び出し側が管理する相関 ID を読み取ります。ホスト型ツールや MCP などは対象外です。
主な機能
- 01独自の FunctionTool を保護
- 02ツール入力ガードレールで拒否を処理
- 03呼び出し側管理の相関 ID を読み取り
- 04Guard ルールとツールのレート制限に対応
活用シーン
- 01リスクのある独自 FunctionTool の呼び出しを遮断
- 02Guard の判定をセッション ID に関連付け
- 03ツール呼び出しに制限を適用
MCP 対応
MCP ツールはこの統合の対象外です。MCP サーバーや MCP クライアントの機能も説明していません。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ arcjet/ skills --skill integrate-arcjet-guard-openai-agents-pyインストール後、Claude Code で/integrate-arcjet-guard-openai-agents-pyを入力して読み込まれたか確認します。
詳細
Python OpenAI Agents に Arcjet Guard を統合する
arcjet.guard.openai_agents は、エージェントが既存の Arcjet クライアントをラップします。Arcjet API と直接通信することはありません。Guard の共通の基礎(クライアント、ルール、ラベル、判定、キャプチャ、登録)については、
../arcjet/references/guards_python.md を参照してください。OpenAI Agents 固有ではない内容については、このリファレンスを読み込んでください。
公式の openai-agents>=0.19.0,<1 のみが対象です。JS の @openai/agents アダプター(@arcjet/guard/openai-agents/v0、ドキュメント
https://docs.arcjet.com/guards/openai-agents/)や、コミュニティ製フォークは対象外です。
arcjet.guard.openai_agents をインポートしても LangChain は読み込まれません。
エクスポート:guard_tool、openai_agents_context。作成者が定義した FunctionTool /
@function_tool のみが対象です。ホスト型ツール、MCP、Computer / Shell /
ApplyPatch、ハンドオフ、Agent.as_tool() は対象外です。
2 つのインターフェースで、判定ルールは 1 つです。
- 作成者が定義した
FunctionTool→guard_tool。ゲートにはFunctionTool.tool_input_guardrails+reject_content(ArcjetDenialResultの JSON)を使います。例外を発生させないでください。 - 相関付け →
openai_agents_contextは呼び出し側が所有するセッション / 会話 ID を読み取ります。ID を新たに生成することはありません。trace_idは読み取りません。
ドキュメント:https://docs.arcjet.com/guards/openai-agents/。
ゲートには tool_input_guardrails + reject_content を使います
guard_tool はコピーを返し、入力ガードレールの先頭に Arcjet を配置します。そのため、DENY(またはデフォルトの on_guard_error="deny" による未評価の Guard)の場合、on_invoke_tool は実行されません。拒否は
ToolGuardrailFunctionOutput.reject_content に ArcjetDenialResult の JSON({ arcjetDenied: true, … })を設定して表します。例外を発生させないでください。
raise_exception() はトリップワイヤーによる停止であり、on_invoke_tool で発生した例外は default_tool_error_function によって握りつぶされます。#196 と同じフェイルクローズのデフォルトです。
"allow" の場合に限りフェイルオープンし、DENY は常にブロックします。コアの guard() は引き続きフェイルオープンします(has_failed_open())。
needs_approval はポリシーゲートではありません
needs_approval はヒューマン・イン・ザ・ループの仕組みです(state.approve / state.reject)。
JS OpenAI Agents の needsApproval、LangGraph の interrupt()、Genkit の interrupt() と同じ落とし穴があります。インバウンド用ヘルパーも承認用ヘルパーもありません。
RunConfig.tool_execution.pre_approval_tool_input_guardrails=True はアプリケーション側で明示的に有効にするものです。このヘルパーでは設定しません。
Runner.run の前にインバウンドをスクリーニングする
インバウンド用のヘルパーはありません。SDK の input_guardrails / output_guardrails
/ ツール出力ガードレールは SDK 独自のトリップワイヤーであり、Arcjet のものではありません。アプリケーションで aj.guard(...) を呼び出し、判定に応じて処理してください。コアの
guard() はフェイルオープンします。ALLOW はルールが実行された証明にはなりません。この呼び出し箇所でフェイルクローズが必要な場合は、decision.has_failed_open() を条件にしてください。
guard_tool はすでにデフォルトでそのように動作します。
まず人に確認する質問
コードから推測できないことだけを質問し、デフォルトも提案してください。
- どのツールがリスクを伴いますか(外部への副作用、取り消し不能、費用の発生、メッセージの送信など)?対象のツールには
guard_toolを使います。ホスト型 / MCP / ハンドオフ /as_toolは対象外です。 - どのような制限が必要ですか?(例:「ユーザーごとに 1 分あたり 10 回の検索」→
TokenBucket。) - メタデータに使うユーザーは誰ですか。不透明なユーザー / テナント ID(PII は使用しません)ですか?
デフォルト:なし。すでに持っている会話 / セッション ID を、
Runner.runに渡すアプリケーションコンテキストに設定してください。その ID は相関 ID であり、ユーザーではありません。 - Arcjet の障害は許容できませんか?すべてのヘルパーはデフォルトで
on_guard_error="deny"です。Runner.run前のインバウンドスクリーニングについては、明示的に確認してください。そこでフェイルクローズにするとエージェントが実行されなくなるため、その呼び出し箇所に限って"allow"を選ぶことは一般的で、妥当な選択です。
読者が誤解しやすい点
- これは JS アダプターではありません。
@arcjet/guard/openai-agents/v0をインポートしないでください。 - 受信リクエスト用のヘルパーはありません。 SDK のガードレールは Arcjet ではありません。
Runner.runの前にコアのguard()でスクリーニングしてください。 needs_approvalは HITL であり、ポリシーではありません。- 拒否されるのは
reject_contentのみです。 例外を発生させるとトリップワイヤーによる停止になるか、default_tool_error_functionによって握りつぶされます。 - 相関 ID は読み取るだけで、生成しません。
trace_idは使わないでください。OpenAIConversationsSession()を構築しないでください。 - レート制限はモデルが指定した注文 ID ではなく、認証済みの呼び出し元をキーにしてください。
guard_toolが返すコピーをエージェントに渡してください。元のツールはガードされないままです。 - すべてのツールを生の
guard()で個別にラップしないでください。 inputs=は受け付けられます。 判定がないことは拒否を意味しません。Console/CLI で確認してください。
ステップ 1:ガードクライアントをインストールして取得する
このモジュールは PyPI の arcjet 1.0.0 に含まれています。
pip install "arcjet[openai-agents]"
エージェントにガードクライアントがまだない場合は、モジュールスコープで 一度だけ 起動してください。
import os
from arcjet.guard import launch_arcjet
aj = launch_arcjet(key=os.environ["ARCJET_KEY"])
ステップ 2:作成したツールをゲートする — guard_tool
from agents import Agent, Runner, function_tool
from arcjet.guard import DetectPromptInjection, TokenBucket, launch_arcjet
from arcjet.guard.openai_agents import guard_tool, openai_agents_context
aj = launch_arcjet(key=os.environ["ARCJET_KEY"])
lookup_limit = TokenBucket(
label="order.looked-up",
bucket="lookups",
refill_rate=10,
interval_seconds=60,
max_tokens=10,
)
user_id = authenticated_user_id
@function_tool # needs_approval=... is HITL — not this policy gate
def lookup_order(order_number: str) -> dict:
"""Look up an order by number."""
return {"order_number": order_number, "status": "shipped"}
lookup_order = guard_tool(
guard=aj,
tool=lookup_order,
action="order.looked-up",
rules=[lookup_limit(key=user_id, requested=1)],
on_guard_error="deny",
)
agent = Agent(
name="support-agent",
instructions="Help the user.",
tools=[lookup_order],
)
guard_tool では action と rules を使用してください。
ステップ 3:Runner.run の前に受信リクエストをスクリーニングする
inbound = DetectPromptInjection()
app_context = {"session_id": conversation_id}
derived = openai_agents_context(app_context)
decision = await aj.guard(
label="message.received",
rules=[inbound(user_text)],
correlation_id=derived.correlation_id,
)
if decision.conclusion == "DENY":
raise Exception("message blocked")
if decision.has_failed_open():
raise Exception("inbound guard unavailable")
await Runner.run(agent, user_text, context=app_context)
受信リクエスト用のヘルパーはありません。
ステップ 4:相関
openai_agents_context は、呼び出し元が所有する ID を読み取ります。優先順位は、runContext.context/アプリオブジェクトそのものにあるフィールド(correlation_id、次に session_id、次に conversation_id、次に group_id。スネークケースまたはキャメルケース)、次にエンベロープ上の同じ名前、次に correlation_id=/session_id= キーワード引数、最後に外側の arcjet_sequence です。OpenAIAgentsContext を返すため、.correlation_id を guard() に渡してください。ID を生成することはありません。trace_id を読み取ることもありません。OpenAIConversationsSession() を構築することもありません。ターンごとに相関 ID を新たに作らないでください。
統合を検証する
python -m py_compile(またはプロジェクトの型チェック)が成功することを確認します。- 受信 PI(
Runner.runの前)、ツールの拒否(例外ではなくreject_content)、レート制限、フェイルクローズ(到達不能なガード)をテストします。needs_approvalがゲートとして扱われないことを確認します。 - Arcjet Console/CLI で、判定が
trace_idではなく、呼び出し元が所有するセッション ID/会話 ID を共有していることを確認します。 - 実際の
ARCJET_KEYを使用した手動 E2E は、実行するまで未検証です。
例の fastapi-openai-agents-guard は Runtime に置いたままにしてください。新しい例の名前を考案しないでください。この skills リポジトリに例を追加しないでください。