OpenAI / Claude エージェントにリアルタイム Web 検索を 4 ステップで追加する

Sarah Choy公開: 2026年5月2日更新: 2026年5月3日読了 7 分
OpenAI / Claude エージェントにリアルタイム Web 検索を 4 ステップで追加する

エージェントの回答を最新情報で裏付けたい?必要なのは 2 つ:LLM 向けスニペットを返す検索 API と、モデルが呼べるツール定義。本記事はこれを 4 ステップで実装する。

要点

  • Step 1:API キーを発行(無料)して curl でエンドポイントを叩く。
  • Step 2:OpenAI / Claude の tool schema を API から取得 — JSON は手書きしない。
  • Step 3:エージェント(OpenAI Assistants、Anthropic Messages、LangChain、n8n)にツール登録。
  • Step 4:tool ハンドラで /api/search/web を呼び、結果をモデルに返す。

なぜこの記事が短いか

「LLM に Web 検索を足す」チュートリアルが長くなるのは、検索 API の SDK や重量級エージェントフレームワークの解説になるから。本記事は違う。仕事は:エンドポイントを選ぶ → ツール登録 → 5 行のハンドラを書く、それだけ。

1無料の API キーを取得してエンドポイントを叩く

apipick.com/dashboard/api-keys でサインアップ。新規アカウントは 100 クレジット無料、クレカ不要。キーを作って:

curl -X POST https://www.apipick.com/api/search/web \
  -H "x-api-key: pk_yourkey" \
  -H "Content-Type: application/json" \
  -d '{"query": "what is retrieval augmented generation"}'

整理された ranked リスト(title、URL、snippet)が返る。curl で動くと確認すれば後のデバッグ時間が大幅に減る。

2tool schema を取得(手書きしない)

API Pick は GET /api/search/web/tool-schema でコピペ用 tool schema を提供。OpenAI 関数定義と Claude tool use 定義の両方。

curl https://www.apipick.com/api/search/web/tool-schema

結果はキャッシュしてよい — 頻繁には変わらない。関数 schema の手書きはエージェントコードで最もバグりやすい場所(型違い、required 違い、description 欠如)。

3エージェントにツールを登録

OpenAI Assistants

from openai import OpenAI
import requests

client = OpenAI()
schema = requests.get("https://www.apipick.com/api/search/web/tool-schema").json()

assistant = client.beta.assistants.create(
    name="Research Agent",
    model="gpt-4o",
    instructions="Use web_search whenever the user asks about current events or anything that changes after your training cutoff.",
    tools=[{"type": "function", "function": schema["openai"]}],
)

Anthropic Claude

import anthropic
import requests

schema = requests.get("https://www.apipick.com/api/search/web/tool-schema").json()
client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    tools=[schema["claude"]],
    messages=[{"role": "user", "content": "Summarise this week's RAG research."}],
)

LangChain

from langchain.tools import tool
import requests

@tool
def web_search(query: str) -> dict:
    """Real-time web search. Use for any question that needs current information."""
    return requests.post(
        "https://www.apipick.com/api/search/web",
        headers={"x-api-key": "pk_yourkey"},
        json={"query": query},
    ).json()

n8n

HTTP Request ノードを追加:method POST、URL https://www.apipick.com/api/search/web、ヘッダ x-api-key: pk_yourkey、JSON ボディ {"query": "{{ $json.query }}"}。エージェントノードや LLM Chain ノードに繋ぐ。SDK 不要。

4ツール呼び出しを処理

OpenAI Assistants の run が requires_action で止まったら、検索を実行して結果を提出:

import json, time, requests
from openai import OpenAI

client = OpenAI()
KEY = "pk_yourkey"

def run_with_tool(thread_id: str, assistant_id: str):
    run = client.beta.threads.runs.create(thread_id=thread_id, assistant_id=assistant_id)
    while True:
        run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id)
        if run.status == "requires_action":
            outputs = []
            for call in run.required_action.submit_tool_outputs.tool_calls:
                if call.function.name == "web_search":
                    args = json.loads(call.function.arguments)
                    result = requests.post(
                        "https://www.apipick.com/api/search/web",
                        headers={"x-api-key": KEY},
                        json=args,
                    ).json()
                    outputs.append({"tool_call_id": call.id, "output": json.dumps(result)})
            client.beta.threads.runs.submit_tool_outputs(
                thread_id=thread_id, run_id=run.id, tool_outputs=outputs,
            )
        elif run.status in ("completed", "failed", "cancelled", "expired"):
            return run
        time.sleep(0.5)

Anthropic Messages のループも同様 — レスポンスに tool_use ブロックが現れたら API を呼び、次のターンで tool_result ブロックとして返す。

ループを安定させる

  • tool description はモデル視点で:「Use this when the user asks about current events, breaking news, or anything that may have changed after your training cutoff.」と書く。「これは Web 検索 API です」とは書かない。
  • 同じ会話で同じ query が繰り返されたらハンドラでキャッシュ。検索結果は分単位で安定、同じ会話で 2 回 15 credits 払う必要はない。
  • 鮮度が重要なら start_date を付ける。「今週のニュース」は日付フィルターなしだと去年の見出しが返ることが多い。

次の一歩

エージェントが検索できるようになったら、次は記事を読ませる。URL 内容抽出 API を 2 つ目のツールとして登録 — 同じ認証、同じ JSON 形式、1 回最大 25 URL。「検索 + 抽出」が最小実用のリサーチエージェント。

よくある質問

Assistants ではなく OpenAI Responses API でも使える?

使える。同じ tool schema を client.responses.create()tools=[{...}] に渡すだけ。ハンドラの形は同じ:tool_calls をパース、POST /api/search/web を呼び、JSON を返す。

結果をモデルに返す前に整形が必要?

不要。POST /api/search/web は ranked の title + URL + LLM 向け snippet を返す。生 JSON をそのままツール結果として返せばよい。モデルが snippet を引用し URL をリンクする。

エージェントターン 1 回あたりのコストは?

Web 検索 1 回 15 credits($5 / 5,000 で約 $0.015)。1 回ツールを呼ぶ典型的なターンの検索コストは 1 セント未満。コストの大部分は LLM トークン。

モデルがツールを呼ばない場合は?

tool description を具体的に。「Use this for any question that requires current or post-training information」は「web search」よりずっと効く。モデルは「このツールが何をするか」を理解できれば自発的に使う。

国や日付範囲で絞れる?

可。country_code(ISO 3166-1 alpha-2)、start_date / end_date(YYYY-MM-DD)を渡す。モデルに選ばせるなら tool schema にパラメータとして含める、エージェントが固定 locale や鮮度要件を持つならハンドラで直書きでよい。

この記事で使われている API

執筆
Sarah Choy
CEO, API Pick

API Pick の CEO。AI エージェントと LLM ワークフロー向けの本番運用可能な API について執筆。