AIエージェント入門

PythonでAIエージェントを自作する完全ガイド【2026年最新】

PythonでAIエージェントを自作する完全ガイド【2026年最新】

この記事の結論

PythonでAIエージェントをゼロから構築する方法を解説。OpenAI Agents SDK・LangChain・Pydantic AIの比較、ReActパターンのコード実装、ツール連携、マルチエージェント設計まで実践的に紹介します。

「AIエージェントって、実際どうやってPythonで作るの?」

AIエージェントという言葉が飛び交うなかで、多くの開発者から繰り返し届く質問がこれです。概念はわかった、でも実際に手を動かして動くものを作れる人は、まだ少ない。

実際に10社以上のAIエージェント導入支援をしてきて気づいたのは、「入門記事を読んだ後の実装の壁」が思った以上に高いということでした。使うフレームワークが多すぎて選べない。コードを書いてみてもうまく動かない。そこで止まってしまうケースを何度も見てきました。

この記事では、AIエージェントをPythonでゼロから作る方法を、コピペ可能なコード・設定例つきで全公開します。フレームワークなしのスクラッチ実装から始め、OpenAI Agents SDK・LangChainといった主要フレームワークへの移行まで、5分で試せるセットアップを起点に順を追って紹介していきます。


AIエージェントの概念・定義については、当サイトの「AIエージェントとは?仕組み・種類・活用事例」で詳しく解説しています。この記事は「実装」にフォーカスします。

まず5分で動かす——スクラッチAIエージェント3選

最初の壁を超えるために、今すぐコピペして動く実装から始めましょう。環境変数 OPENAI_API_KEY さえ設定してあれば、以下は全て動きます。

即効実装1:フレームワークなし、素のPythonエージェント(ReActパターン)

まず「エージェントとは何か」を体で理解するために、外部ライブラリなしでReActループを実装してみましょう。これを自分で書いた人は、LangChainの内部で何が起きているかが一瞬でわかるようになります。


# 動作環境: Python 3.11+, openai>=1.30.0
# pip install openai
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import os
import json
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

# ツール定義(エージェントが使える「手」)
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "指定した都市の天気を取得します",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "都市名(例: 東京、大阪)"}
                },
                "required": ["city"]
            }
        }
    }
]

def get_weather(city: str) -> str:
    """ダミーの天気API(実際はOpen-Meteo等に差し替え)"""
    weather_data = {"東京": "晴れ、気温22℃", "大阪": "曇り、気温19℃"}
    return weather_data.get(city, f"{city}の天気情報は取得できません")

def run_agent(user_message: str) -> str:
    """ReAct(Reasoning + Acting)ループの実装"""
    messages = [
        {"role": "system", "content": "ユーザーの質問に日本語で答えるアシスタントです。必要であれば天気ツールを使ってください。"},
        {"role": "user", "content": user_message}
    ]

    # ReActループ: Think → Act → Observe → 繰り返す
    for _ in range(5):  # 最大5回まで(無限ループ防止)
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=messages,
            tools=TOOLS,
            tool_choice="auto"
        )
        msg = response.choices[0].message
        messages.append(msg)

        # ツール呼び出しが必要なら実行(Actフェーズ)
        if msg.tool_calls:
            for call in msg.tool_calls:
                if call.function.name == "get_weather":
                    args = json.loads(call.function.arguments)
                    result = get_weather(args["city"])
                    messages.append({
                        "role": "tool",
                        "tool_call_id": call.id,
                        "content": result
                    })
        else:
            # ツール呼び出しなし → 最終回答
            return msg.content

    return "エラー: ループ上限に達しました"

# 実行例
if __name__ == "__main__":
    answer = run_agent("東京と大阪、今日はどっちが暖かい?")
    print(answer)

ポイント:

  • for _ in range(5) のループ上限は必ず設定する。設定しないと無限ループになるケースがある
  • tool_calls がNoneなら「エージェントが最終回答を出した」サイン
  • gpt-4o-mini を使うとコストを1/30以下に抑えながら開発できる

即効実装2:OpenAI Agents SDKで10行エージェント

スクラッチ実装の仕組みを理解したら、OpenAI公式のAgents SDKに乗り換えましょう。コードが劇的に短くなります。


# 動作環境: Python 3.11+
# pip install openai-agents
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import asyncio
from agents import Agent, Runner, function_tool

@function_tool
def get_weather(city: str) -> str:
    """指定した都市の天気を返します。"""
    weather_data = {"東京": "晴れ、気温22℃", "大阪": "曇り、気温19℃"}
    return weather_data.get(city, f"{city}の天気情報は取得できません")

agent = Agent(
    name="天気エージェント",
    instructions="ユーザーの質問に日本語で丁寧に回答してください。天気の質問にはget_weatherツールを使ってください。",
    model="gpt-4o-mini",
    tools=[get_weather],
)

async def main():
    result = await Runner.run(agent, "東京の今日の天気は?")
    print(result.final_output)

asyncio.run(main())

ポイント:

  • @function_tool デコレータでPython関数を即ツール化できる
  • スクラッチ実装で書いた30行のReActループが、SDK内部で自動実行される
  • 同期実行が必要なら Runner.run_sync() を使う

即効実装3:LangChainでツール連携エージェント

複数ツールを組み合わせた実用的なエージェントが必要なら、LangChainが安定した選択肢です。エラーハンドリングと会話メモリを含む実装例を示します。


# 動作環境: Python 3.11+
# pip install langchain langchain-openai
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import os
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain.tools import tool
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.memory import ConversationBufferWindowMemory

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0, api_key=os.environ["OPENAI_API_KEY"])

@tool
def get_weather(city: str) -> str:
    """指定した都市の天気を取得します。"""
    weather_data = {"東京": "晴れ、気温22℃", "大阪": "曇り、気温19℃"}
    return weather_data.get(city, f"{city}の天気情報は取得できません")

@tool
def calculate(expression: str) -> str:
    """数式を計算します。例: '2 + 3 * 4'"""
    try:
        # evalは本番では使わないこと(セキュリティリスク)— numexprを推奨
        result = eval(expression, {"__builtins__": {}}, {})
        return str(result)
    except Exception as e:
        return f"計算エラー: {str(e)}"

tools = [get_weather, calculate]

prompt = ChatPromptTemplate.from_messages([
    ("system", "ユーザーの質問に日本語で回答するアシスタントです。ツールを積極的に活用してください。"),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"),
])

memory = ConversationBufferWindowMemory(k=5, memory_key="chat_history", return_messages=True)

agent = create_openai_functions_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, memory=memory, verbose=True)

# 実行例(会話の連続性が保たれる)
response1 = executor.invoke({"input": "東京の天気は?"})
print(response1["output"])

response2 = executor.invoke({"input": "さっき言った都市に関係する数式、15 + 7 を計算して"})
print(response2["output"])

ポイント:

  • ConversationBufferWindowMemory(k=5) で直近5ターンの会話を記憶する
  • evaluate は本番ではセキュリティリスク。数値計算には numexpr ライブラリを使うこと
  • verbose=True にするとReActの思考過程がコンソールに出力されるため、デバッグに便利

AIエージェントの仕組みを”3つの型”で理解する

実装を始める前に、「何を作るか」を明確にしておきましょう。AIエージェントは構造によって大きく3つの型に分かれます。

構造 難易度 典型的なユースケース 参考フレームワーク
シングルエージェント LLM 1体 + ツール群 ★☆☆ 問い合わせ対応、情報収集、データ変換 OpenAI Agents SDK
マルチエージェント(逐次) 複数LLMを直列に連結 ★★☆ 文章生成→レビュー→修正の自動化 LangGraph, LangChain
マルチエージェント(並列) 複数LLMが並列で協調 ★★★ 大規模データ処理、複数タスクの同時実行 CrewAI, OpenAI Agents SDK

初めて作るなら「シングルエージェント+2〜3ツール」からスタートするのが正解です。いきなり並列マルチエージェントを構築しようとすると、デバッグで詰まってプロジェクトが止まります。

フレームワーク選定ガイド:2026年版比較表

Pythonで使える主要AIエージェントフレームワークを整理しました。2026年3月時点の情報です。

フレームワーク GitHub Stars 特徴 向いているケース 向かないケース
OpenAI Agents SDK ※注1 軽量・公式・マルチエージェント対応 OpenAIモデルを使った本番開発 マルチモデル環境(Claudeも使いたい等)
LangChain 126,000+ 700以上のインテグレーション・最大エコシステム 外部サービス連携が多いエージェント シンプルな単機能エージェント(オーバースペック)
LangGraph 24,600+ グラフ構造でワークフローを精密制御 複雑な条件分岐・ループのある処理 プロトタイプ・PoC(学習コストが高い)
Pydantic AI ※注1 型安全・モデル不依存・Pythonicな設計 型安全性が重要な本番環境 エコシステムの広さが必要なケース
スクラッチ(フレームワークなし) 完全な制御・依存関係ゼロ 学習目的・超軽量エージェント 本番開発(メンテナンスコストが高い)

料金情報(最終確認: 2026-03-18): いずれのフレームワークも本体は無料・オープンソース。APIコストはOpenAI GPT-4o-miniが入力$0.15/百万トークン・出力$0.60/百万トークン(出典: OpenAI公式料金ページ)。GitHubスター数は2026年3月時点の概算値(※注1: OpenAI Agents SDK・Pydantic AIは急成長中のためアクセス時点で変動します)。

ユースケース別実装パターン3選

フレームワークを選んだら、実際のビジネスユースケースに即した実装例を見ていきましょう。

ユースケース1:Webスクレイピング+要約エージェント

日次のニュース収集を自動化するエージェントです。「URL一覧を渡したら要約レポートを作って返す」という処理を実装します。


# 動作環境: Python 3.11+
# pip install openai-agents requests beautifulsoup4
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import os, requests
from bs4 import BeautifulSoup
from agents import Agent, Runner, function_tool

@function_tool
def fetch_page_text(url: str) -> str:
    """指定URLのページ本文テキストを取得します(最大3,000文字)。"""
    try:
        resp = requests.get(url, timeout=10, headers={"User-Agent": "Mozilla/5.0"})
        resp.raise_for_status()
        soup = BeautifulSoup(resp.text, "html.parser")
        # scriptとstyleを除去
        for tag in soup(["script", "style", "nav", "footer"]):
            tag.decompose()
        text = soup.get_text(separator="n", strip=True)
        return text[:3000]  # トークン節約のため3,000文字に制限
    except Exception as e:
        return f"ページ取得エラー: {str(e)}"

news_agent = Agent(
    name="ニュース要約エージェント",
    instructions="""
    渡されたURLのページを取得し、以下の形式でレポートを作成してください。

    フォーマット:
    ## [記事タイトル]
    - 要点1
    - 要点2
    - 要点3
    - AIエージェント開発者へのインパクト: [1文で]
    """,
    model="gpt-4o-mini",
    tools=[fetch_page_text],
)

async def summarize_urls(urls: list[str]) -> str:
    prompt = "以下のURLの記事を要約してください:n" + "n".join(f"- {u}" for u in urls)
    result = await Runner.run(news_agent, prompt)
    return result.final_output

# 実行例
if __name__ == "__main__":
    import asyncio
    urls = ["https://openai.com/blog/", "https://anthropic.com/news/"]
    report = asyncio.run(summarize_urls(urls))
    print(report)

ポイント:

  • text[:3000] でトークン上限に引っかかるリスクを下げる。長いページは重要部分だけ抽出する処理を追加するとよい
  • User-Agent を設定しないとブロックされるサイトが多い
  • スクレイピング対象サイトの利用規約を必ず確認すること

ユースケース2:データ分析+可視化エージェント

CSVデータをアップロードして「分析してグラフを作って」を自動化します。


# 動作環境: Python 3.11+
# pip install openai-agents pandas matplotlib
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import os, json
import pandas as pd
import matplotlib
matplotlib.use("Agg")  # 非GUIバックエンドを使用(サーバー環境対応)
import matplotlib.pyplot as plt
from agents import Agent, Runner, function_tool

@function_tool
def analyze_csv(csv_path: str) -> str:
    """CSVファイルを読み込み、基本統計情報を返します。"""
    try:
        df = pd.read_csv(csv_path)
        stats = {
            "行数": len(df),
            "列数": len(df.columns),
            "列名": list(df.columns),
            "数値列の統計": df.describe().to_dict()
        }
        return json.dumps(stats, ensure_ascii=False, default=str)
    except Exception as e:
        return f"CSV読み込みエラー: {str(e)}"

@function_tool
def plot_bar_chart(csv_path: str, x_column: str, y_column: str, output_path: str) -> str:
    """CSVから棒グラフを生成してファイルに保存します。"""
    try:
        df = pd.read_csv(csv_path)
        fig, ax = plt.subplots(figsize=(10, 6))
        ax.bar(df[x_column], df[y_column])
        ax.set_xlabel(x_column)
        ax.set_ylabel(y_column)
        ax.set_title(f"{x_column} × {y_column}")
        plt.xticks(rotation=45)
        plt.tight_layout()
        plt.savefig(output_path)
        plt.close()
        return f"グラフを保存しました: {output_path}"
    except Exception as e:
        return f"グラフ生成エラー: {str(e)}"

analyst_agent = Agent(
    name="データ分析エージェント",
    instructions="CSVデータを分析し、適切なグラフを生成して、洞察をわかりやすく説明してください。",
    model="gpt-4o",  # 複雑な分析はgpt-4oを推奨
    tools=[analyze_csv, plot_bar_chart],
)

ユースケース3:Slackへの自動報告エージェント

分析結果をSlackチャンネルに自動送信する実装です。定期実行のcronジョブと組み合わせると、朝のデイリーレポートを完全自動化できます。


# 動作環境: Python 3.11+
# pip install openai-agents slack-sdk
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
from agents import Agent, Runner, function_tool

slack_client = WebClient(token=os.environ["SLACK_BOT_TOKEN"])

@function_tool
def post_to_slack(channel: str, message: str) -> str:
    """Slackチャンネルにメッセージを送信します。"""
    try:
        slack_client.chat_postMessage(channel=channel, text=message)
        return f"Slackに送信しました: {channel}"
    except SlackApiError as e:
        return f"Slack送信エラー: {e.response['error']}"

reporter_agent = Agent(
    name="Slack報告エージェント",
    instructions="""
    与えられたデータを分析し、以下の形式でSlackレポートを作成して送信してください。

    チャンネル: #daily-report
    フォーマット:
    【デイリーレポート】{日付}
    ✅ 完了: [内容]
    ⚠️ 注意事項: [内容]
    📊 数値サマリー: [主要KPI]
    """,
    model="gpt-4o-mini",
    tools=[post_to_slack],
)

マルチエージェント設計:オーケストレーターとワーカーの分離

業務が複雑になってきたら、「指示役(オーケストレーター)」と「実行役(ワーカー)」を分けたマルチエージェント構成を検討しましょう。

OpenAI Agents SDKのハンドオフ機能を使った実装例です。


# 動作環境: Python 3.11+
# pip install openai-agents
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
import asyncio
from agents import Agent, Runner, function_tool, handoff

# ワーカーエージェント1:リサーチ担当
research_agent = Agent(
    name="リサーチャー",
    instructions="与えられたトピックについて調査し、重要な情報を箇条書きでまとめてください。",
    model="gpt-4o-mini",
)

# ワーカーエージェント2:ライター担当
writer_agent = Agent(
    name="ライター",
    instructions="提供された情報をもとに、ブログ記事の本文(500字程度)を書いてください。",
    model="gpt-4o",
)

# オーケストレーター:全体制御
orchestrator = Agent(
    name="オーケストレーター",
    instructions="""
    ユーザーのリクエストを分析し、適切なエージェントに作業を依頼してください。
    1. まずリサーチャーに情報収集を依頼する
    2. 収集した情報をライターに渡して記事を作成させる
    """,
    model="gpt-4o",
    handoffs=[
        handoff(research_agent),
        handoff(writer_agent),
    ]
)

async def main():
    result = await Runner.run(orchestrator, "AIエージェントの最新トレンドについての記事を作成してください")
    print(result.final_output)

asyncio.run(main())

ポイント:

  • handoff() でオーケストレーターがワーカーに会話を引き継ぎできる
  • ワーカーは専門特化することで精度が上がる(ジェネラリスト1体より専門家2体)
  • オーケストレーターにはより高性能なモデル(gpt-4o)を使い、ワーカーには軽量モデルを使ってコストを下げる設計が有効

より複雑なワークフロー制御が必要な場合は、「LangGraph・CrewAI・AutoGen徹底比較」でグラフ型のオーケストレーションパターンを詳しく解説しています。

本番運用前に必須:セキュリティと運用設計

正直に言うと、AIエージェントのセキュリティはまだ発展途上の領域です。「動くものを作れた」で止まらず、以下の対策を本番前に必ず実装してください。

リスク 対策 実装の目安
プロンプトインジェクション ユーザー入力のサニタイズ、システムプロンプトの分離 PoC段階から必須
APIキー漏洩 環境変数管理(.envやSecret Manager)、ハードコード禁止 開発開始前に設定
ツール実行の暴走 ループ回数の上限設定、ツール実行ログの保存 PoC段階から必須
コスト超過 月額上限の設定、モデルのダウングレード検討 本番移行前に設定
ハルシネーション ツール出力の優先(LLMの生成より実データを信頼) 設計時に意識

# セキュリティ実装例: APIキーの安全な管理
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

# ❌ NG: ハードコード
# client = OpenAI(api_key="sk-abc123...")

# ⭕ OK: 環境変数から取得
import os
from dotenv import load_dotenv
load_dotenv()  # .envファイルから読み込み(開発時)

api_key = os.environ.get("OPENAI_API_KEY")
if not api_key:
    raise ValueError("OPENAI_API_KEY が設定されていません")

# .envファイル(.gitignoreに必ず追加)
# OPENAI_API_KEY=sk-your-key-here

# コスト管理: OpenAIダッシュボードで月額上限を設定すること
# https://platform.openai.com/settings/organization/limits

【要注意】よくある失敗パターンと回避策

10社以上のAIエージェント導入支援を経て蓄積した「引っかかりやすいポイント」を共有します。

失敗1:ツールの説明文が曖昧すぎる

ツールの description はエージェントへの「説明書」です。ここが曖昧だと、エージェントが適切なタイミングでツールを使えなくなります。


# ❌ NG: 説明が抽象的
@function_tool
def get_data(query: str) -> str:
    """データを取得します。"""  # エージェントが使い方を判断できない
    ...

# ⭕ OK: いつ・何を・どうやって使うかを明記
@function_tool
def search_product_db(product_name: str) -> str:
    """社内製品データベースから製品情報を検索します。

    製品の仕様・価格・在庫状況を確認する際に使用してください。
    引数: product_name — 製品名(例: 'AIエージェントPro', 'DataSync v2')
    返値: JSON形式の製品情報(name, price, stock, specs)
    """
    ...

失敗2:一度に複雑なエージェントを作ろうとする

❌ 最初から10個のツールと複雑なワークフローを実装しようとする
⭕ まず1つのツールだけで動かし、1本ずつ追加していく

ツールが増えるほどエージェントの挙動が予測しにくくなります。1ツールずつ追加して「意図通りに使われているか」を確認するプロセスを省略しないことが重要です。

失敗3:会話履歴の管理を忘れる

❌ ステートレスな実装で「さっきの話を踏まえて」が機能しない
⭕ セッション単位でメッセージ履歴を保持する


# 会話履歴を維持する基本パターン
# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。
conversation_history = []  # セッション中は永続

def chat(user_message: str) -> str:
    conversation_history.append({"role": "user", "content": user_message})

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "あなたは便利なアシスタントです。"},
            *conversation_history  # 全履歴を渡す
        ],
        tools=TOOLS,
        tool_choice="auto"
    )

    assistant_msg = response.choices[0].message
    conversation_history.append(assistant_msg)  # 返答も履歴に追加
    return assistant_msg.content

失敗4:本番環境でのモニタリングを後回しにする

❌ ログを取らずに本番投入 → 問題が起きても原因特定できない
⭕ 最低限、入力・出力・ツール実行結果をログに保存する

AIエージェントはハルシネーションやツール誤用が発生します。「何をどんな順で実行したか」のトレースを残さないと、障害対応が不可能になります。LangChainなら verbose=True、OpenAI Agents SDKならトレーシング機能を活用しましょう。

PoC→本番移行の3フェーズ

AIエージェントの導入は「動いた!」で終わりではありません。本番で価値を出すまでのロードマップを示します。

フェーズ1: PoC(1〜2週間)

  • 最もシンプルなシングルエージェント+2ツールで動作確認
  • モデルはGPT-4o-miniで十分(コスト最小化)
  • エラーハンドリングは最低限。まず動くことを優先

フェーズ2: パイロット運用(1〜2ヶ月)

  • 実ユーザー10〜20人に使わせてフィードバック収集
  • ツールの説明文・システムプロンプトを継続改善
  • ログ・モニタリング体制を整備
  • コスト実績をもとにモデル選定を見直す

フェーズ3: 本番展開(3ヶ月〜)

  • セキュリティレビュー(プロンプトインジェクション・APIキー管理)
  • スケーリング設計(並列実行・レート制限対応)
  • ヒューマン・イン・ザ・ループの実装(重要判断は人間が確認)
  • コスト管理・上限アラートの設定

参考・出典

まとめ:今日から始める3つのアクション

  1. 今日やること: 「即効実装1」のスクラッチReActエージェントをコピペして動かす。自分で実装した30行のコードがLangChainの中で何をやっているかを体感する
  2. 今週中: 自分の業務で「繰り返しやっている作業」を1つ特定して、シングルエージェント+1ツールでPoC実装する
  3. 今月中: PoCの結果をチームに共有し、パイロット運用対象を決定する。フレームワーク選定はこの段階でよい

あわせて読みたい:


著者: 佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。早稲田大学法学部在学中に生成AIの可能性に魅了され、X(旧Twitter)で活用法を発信(@SuguruKun_ai、フォロワー10万人超)。100社以上の企業向けAI研修・導入支援。著書累計3万部突破。SoftBank IT連載7回執筆(NewsPicks最大1,125ピックス)。

ご質問・ご相談はお問い合わせフォームからお気軽にどうぞ。

関連記事: Agents SDKか、LangGraphか|2026年のフレームワーク選定指針

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年3月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事