はじめに
今回は OpenAI Agents SDK を使ってみます。
LLM を1回呼び出して文章を返すだけなら、通常の API クライアントで十分です。
一方で、役割ごとの Instructions、実行時の入力、必要に応じて Agent が利用する Tool などを一つの単位として扱いたくなると、呼び出し周辺のコードをアプリケーション側で管理する必要があります。
OpenAI Agents SDK を使うと、LLM と Instructions を Agent として定義し、Runner から実行できます。まずはこの最小構成を動かすことで、単純な LLM 呼び出しから Agent を構築するための土台を作ります。
ローカルで起動した LLM を OpenAI 互換 API 経由で OpenAI Agents SDK へ接続し、Instructions を持つ単一の Agent を実行します。複数行の入力、処理条件、出力形式を指定することで、Agent に渡した Instructions と実行時入力がどのように応答へ反映されるかを確認します。
集計の正確性や本番運用に耐えるデータ処理を検証するものではありません。
OpenAI Agents SDK とは
OpenAI Agents SDK は、LLM を呼び出す処理に Instructions、Tool、実行フローなどを加え、Agent の動作をコードで組み立てるための SDK です。本記事では最小構成として、次の2つだけを使います。
-
Agent: 名前、Instructions、使用するモデルを定義する -
Runner: Agent と実行時入力を受け取り、実行して最終出力を返す
今回は Tool や Agent 間の連携は追加しません。まずは、LLM の接続設定と Agent の定義・実行を分けて記述できることを確認します。
今回の題材
動作確認の例として、1件ごとの決済データから、日付・商品別の決済件数と売上金額を集計するよう Agent へ依頼します。
この題材は、入力データ、除外条件、出力形式を一度に Agent へ渡せるため、Instructions と実行時入力が応答へ反映されることを確認しやすいからです。ここでの目的は集計ロジックの正確性ではなく、Agent の定義と実行経路を確認することです。
完成イメージ
request.txt
↓
Sales Data Preparation Agent
↓
OpenAI Agents SDK
↓ OpenAI 互換 API
ローカル LLM サーバー
↓
集計済み Markdown 表
今回確認すること
- OpenAI 互換 API を公開するローカル LLM に接続できる
- Instructions を持つ
Agentを定義できる -
Runnerから実行時入力を渡し、最終出力を取得できる
前提環境
| 項目 | 必要なもの |
|---|---|
| OS | Python とローカル LLM サーバーを実行できる環境 |
| Python | OpenAI Agents SDK をインストールできるバージョン |
| LLM | OpenAI 互換 API で利用できる任意のローカルモデル |
| LLM サーバー | Chat Completions API を公開できる任意のサーバー |
ローカル LLM サーバーの API 互換性には差があります。今回のコードは Chat Completions API を使うため、サーバーが /v1/chat/completions 相当のエンドポイントを提供していることを確認してください。
プロジェクトを用意する
仮想環境を作成し、SDK をインストールする
任意のディレクトリで仮想環境を作成し、有効化してから OpenAI Agents SDK をインストールします。
python -m venv .venv
source .venv/Scripts/activate # Bash の場合
# Windows PowerShell の場合
# .venv\Scripts\Activate.ps1
python -m pip install openai-agents
ファイル構成は次のとおりです。
agent/
├─ agent.py
└─ request.txt
Agent を実装して実行する
ローカル LLM の接続情報を設定する
ローカル LLM の接続先とモデル名は環境変数から受け取るようにします。LOCAL_LLM_BASE_URL には /v1 までを含むベース URL を、LOCAL_LLM_MODEL にはモデル一覧 API で確認したモデル ID を設定してください。
agent.py を作成する
import asyncio
import os
import sys
from openai import AsyncOpenAI
from agents import (
Agent,
OpenAIChatCompletionsModel,
Runner,
set_tracing_disabled,
)
def read_request() -> str:
"""UTF-8 または CP932 の標準入力を読む。"""
raw_input = sys.stdin.buffer.read()
for encoding in ("utf-8-sig", "cp932"):
try:
return raw_input.decode(encoding).strip()
except UnicodeDecodeError:
continue
raise ValueError("標準入力を UTF-8 または CP932 として読み取れません")
set_tracing_disabled(True)
client = AsyncOpenAI(
base_url=os.environ["LOCAL_LLM_BASE_URL"],
# ローカルサーバーで認証を要求しない場合でも、クライアントには値を渡す。
api_key=os.environ.get("LOCAL_LLM_API_KEY", "not-needed"),
)
model = OpenAIChatCompletionsModel(
model=os.environ["LOCAL_LLM_MODEL"],
openai_client=client,
)
agent = Agent(
name="Sales Data Preparation Agent",
instructions=(
"あなたは売上データを分析用に準備するエージェントです。"
"入力に含まれる決済データと指示だけを使い、日本語で簡潔に答えてください。"
"指定された条件でレコードを抽出・集計し、分析担当者へ渡せるMarkdown表を返してください。"
"入力にない取引や数値を作ってはいけません。"
"必ず回答の先頭を「データ担当:」にしてください。"
),
model=model,
)
async def main() -> None:
request = read_request()
if not request:
raise SystemExit("標準入力から依頼を渡してください")
result = await Runner.run(agent, input=request)
print(result.final_output)
if __name__ == "__main__":
asyncio.run(main())
Chat Completions を明示する理由
OpenAIChatCompletionsModel を明示している点が重要です。Agents SDK は OpenAI モデルでは Responses API を既定で使いますが、OpenAI 互換 API を提供するローカル LLM サーバーでは Chat Completions API を実装している場合が多いためです。
Agents SDKではTracingがデフォルトで有効です。本記事ではローカルLLMのみを利用し、OpenAIへのトレース送信も不要なため、set_tracing_disabled(True)で無効化しています。
Agent に渡す依頼を作る
入力ファイルを用意する
次を request.txt として UTF-8 で保存します。各行は1件の決済を表します。cancelled の決済も混ぜ、Agent が条件に従って除外するかを確認します。
以下は1レコード1決済の売上データです。
- `status` が `completed` のレコードだけを対象にしてください。
- 日付・商品ごとに決済件数と売上金額を集計してください。
- 分析担当者へ渡せる Markdown 表だけを返してください。
取引ID,日付,商品,金額(円),status
P001,2026-08-01,ノート,300,completed
P002,2026-08-01,ノート,300,completed
P003,2026-08-01,ボールペン,150,completed
P004,2026-08-01,マグカップ,1800,completed
P005,2026-08-02,ノート,300,completed
P006,2026-08-02,ボールペン,150,completed
P007,2026-08-02,ボールペン,150,completed
P008,2026-08-02,マグカップ,1800,completed
P009,2026-08-03,ノート,300,completed
P010,2026-08-03,ノート,300,completed
P011,2026-08-03,ボールペン,150,completed
P012,2026-08-03,マグカップ,1800,cancelled
P013,2026-08-04,ノート,300,completed
P014,2026-08-04,ボールペン,150,completed
P015,2026-08-04,ボールペン,150,completed
P016,2026-08-04,ボールペン,150,completed
P017,2026-08-05,ノート,300,completed
P018,2026-08-05,ノート,300,completed
P019,2026-08-05,ノート,300,completed
P020,2026-08-05,マグカップ,1800,completed
P021,2026-08-06,ボールペン,150,completed
P022,2026-08-06,ボールペン,150,completed
P023,2026-08-06,マグカップ,1800,completed
P024,2026-08-07,ノート,300,completed
P025,2026-08-07,ノート,300,completed
P026,2026-08-07,ボールペン,150,completed
P027,2026-08-07,マグカップ,1800,completed
P028,2026-08-08,ノート,300,cancelled
P029,2026-08-08,ボールペン,150,completed
P030,2026-08-08,ボールペン,150,completed
P031,2026-08-08,ボールペン,150,completed
P032,2026-08-08,ボールペン,150,completed
P033,2026-08-08,マグカップ,1800,completed
実行して結果を確認する
標準入力から依頼を渡す
request.txt を標準入力から渡して実行します。
python agent.py < request.txt
実行結果
次のように、cancelled のレコードを除外した日付・商品別の集計表を取得できました。
データ担当: 集計結果です。
| 日付 | 商品 | 決済件数 | 売上金額(円) |
| :--- | :--- | :--- | :--- |
| 2026-08-01 | ノート | 2 | 600 |
| 2026-08-01 | ボールペン | 1 | 150 |
| 2026-08-01 | マグカップ | 1 | 1800 |
| 2026-08-02 | ノート | 1 | 300 |
| 2026-08-02 | ボールペン | 2 | 300 |
| 2026-08-02 | マグカップ | 1 | 1800 |
| 2026-08-03 | ノート | 2 | 600 |
| 2026-08-03 | ボールペン | 1 | 150 |
| 2026-08-04 | ノート | 1 | 300 |
| 2026-08-04 | ボールペン | 3 | 450 |
| 2026-08-05 | ノート | 3 | 900 |
| 2026-08-05 | マグカップ | 1 | 1800 |
| 2026-08-06 | ボールペン | 2 | 300 |
| 2026-08-06 | マグカップ | 1 | 1800 |
| 2026-08-07 | ノート | 2 | 600 |
| 2026-08-07 | ボールペン | 1 | 150 |
| 2026-08-07 | マグカップ | 1 | 1800 |
| 2026-08-08 | ボールペン | 4 | 600 |
| 2026-08-08 | マグカップ | 1 | 1800 |
結果から分かること
ここで確認できたのは、ローカル LLM を Agents SDK の Agent として定義し、Instructions と実行時入力に従う結果を得られることです。
一方で、これは単一 Agent の実行です。集計値を正確に扱う実運用では、Python または SQL など、決定的に計算できる処理を組み合わせることを検討します。
まとめ
- OpenAI 互換 API を公開するローカル LLM を、OpenAI Agents SDK の Agent として実行できた
-
Agentに Instructions を与え、Runnerから実行時入力を渡して最終出力を取得できた - 動作確認の題材として決済データを集計し、指定した除外条件と表形式を含む応答を得られた
- Agent の基本構成である、モデル・Instructions・実行処理を一つのプログラムとして確認できた