今更だけど"AIエージェント"を作ってみた

Published

はじめに

ClaudeCodeやCodexのようなコーディングエージェントをはじめ,日常的に"エージェント"という言葉を耳にしたり使ったりするようになりました.みなさんは「AIエージェントって何?普通のAIと何が違うの?」と聞かれた時に,どう答えるでしょうか?自分は,「なんか自律的にいろいろやってくれるやつ」くらいの解像度しかありません.

そこで,AIエージェントとは何かを説明できること,AIエージェントを実際に作って動かしてみること,を目的としてこのブログを書いてみます.

環境を認識し,意思決定し,行動する

“artificial entities that sense their environment, make decisions, and take actions”


Xi, Zhiheng, et al. "The rise and potential of large language model based agents: A survey." Science China information sciences 68.2 (2025): 121101.

(引用元: https://arxiv.org/abs/2309.07864)

Xiらによれば,「環境を認識し,意思決定し,行動する」と定義されていました.ClaudeCodeでコーディングを行った場合にあてはめると,環境の認識(プロンプトの解釈やファイルの確認),意思決定(実装方針の決定),行動(ファイルの編集)という定義ができそうです.

AIエージェントの基礎となる概念にReActというものがあります(このまえ研究室のゼミで初めて知りました...).Web開発をやっている人間が聞くとJavaScriptのライブラリが思い浮かぶのですが,ここではReasoning + ActingでReActとなっているようです.

Yao, Shunyu, et al. "React: Synergizing reasoning and acting in language models." arXiv preprint arXiv:2210.03629 (2022).

(引用元: https://arxiv.org/abs/2210.03629)

図のようにThought→Action→Observationをループさせることで,より精度の高い結果を得ることができています.ActionではSearchやLookupといった行動をしていますが,前者が指定したエンティティのWikipediaページを検索する操作を行い,後者が開いているWikipediaページの中から,特定の文字列を探す操作を行なっているようです.シンプルな構造ですけど,合理的で強力な仕組みだなと感じています.わかりやすくてめっちゃ好きです.MCPは,この論文におけるActionの自由度をあげて,外部ツールと接続できる形になっているのだなと納得しました.だいぶエージェントの解像度が上がってきましたね.

簡単なエージェントを作ってみる

langchainを使えば,簡単にエージェントを作れます.今回はOllamaで構築したローカルLLMを使ってエージェントを構築したいと思います.

ライブラリのインストール

!pip install langchain langchain-ollama

LLMを定義する

今回はqwen3.8:27bというモデルを使ってみます.日本語能力にも長けていて,めちゃくちゃ賢いです.

from langchain_ollama import ChatOllama
from langchain.agents import create_agent

llm = ChatOllama(
    model="qwen3.8:27b",
    base_url="{Ollamaのエンドポイント}",
)

通常のLLMを実行してみる

まずは比較のために,シンプルなLLMで質問をしてみます.

for chunk in llm.stream(
    "福岡と東京の気温を調べて,どちらが暑いか教えて"
):
  print(chunk.content, end="", flush=True)

だいぶ賢いですね...適当なこと言ってハルシネーションを起こして欲しかったのですが,情報が不確実なことを考慮しつつ,確からしい回答をしている気がします.しかしながら,学習済みのデータから一般的な答えを出力しただけで,推論の域を出ません.

エージェントを定義する

次に,エージェントがActionを行うためのToolをまず定義して,エージェントを定義していきます.今回のToolは都市名を入力してハードコードで書いた気温を返すだけのシンプルな関数を使います.

# Tool
def get_weather(city: str) -> str:
    """指定した都市の現在の気温を取得する"""

    weather = {
        "福岡": 30,
        "東京": 27,
        "大阪": 29,
        "札幌": 22,
    }

    return f"{city}の気温は{weather[city]}℃です"

# Agent
agent = create_agent(
    llm,
    tools=[get_weather],
)

エージェントを実行する

それではエージェントを実行して,結果がどう変わるのかをみてみます.

for chunk in agent.stream(
    {"messages": [("user", "福岡と東京の気温を調べて,どちらが暑いか教えて")]},
    stream_mode="updates",
):
    for value in chunk.values():
        for message in value["messages"]:
            print(message.content)

ちゃんと気温を調べて(get_weatherの出力を見て)具体的な回答をしてくれました.LLMが出力を得るために考え,気温を調べ,調べた結果を観察するという過程を踏んでいます.

おわりに

エージェントを思考→行動→観察の繰り返しという構造に分解できることがわかりました.これから複雑な課題のソリューションとしてエージェントを用いる機会があると思いますが,今回のブログを通して,思考・行動・観察の判断基準をあらかじめ決めておけば,エージェントをうまく使いこなせそうだなと感じました.ここからハーネスエンジニアリングという考え方に繋がっていくのだと思います.判断基準を決めるために(AIをうまく使うために),まだまだ人間の知識と経験は必要になりそうですね.