0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ローカル LLM を OpenAI Agents SDK で Agent として動かす

0
Last updated at Posted at 2026-08-23

はじめに

今回は 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・実行処理を一つのプログラムとして確認できた
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?