0Pricing
AI Agents · レッスン

エージェント検索向けTavilyとSerpAPI

Web検索ツールのAPI設定、クエリ構築、結果解析を学びます。

「エージェント検索向けTavilyとSerpAPI」はCoddyKit上の無料AI Agentsレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Agents学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Agentsコースには全4レッスンが含まれています。

エージェントにウェブ検索が必要な理由

LLMには知識カットオフ日があります。現在の出来事、リアルタイムの価格、最新ニュース、または急速に変化するトピックに関する質問では、モデルの学習データは古くなっています。

TavilyやSerpApiなどのウェブ検索ツールは、エージェントにインターネットへのリアルタイムアクセスを提供し、静的な学習データと現在の現実との隔たりを埋めます。

AIエージェント専用のTavily

Tavilyは、AIエージェント専用に設計された検索APIです。一般的なウェブスクレイピングとは異なり、コンテンツを事前に抽出したクリーンで構造化された結果を返すため、HTMLのパースは必要ありません。

pip install tavily-pythonでインストールします。APIキーはtavily.comで取得してください。

from tavily import TavilyClient
import os

client = TavilyClient(api_key=os.getenv('TAVILY_API_KEY'))

results = client.search(
    query='latest OpenAI GPT-5 release date',
    max_results=5
)

for r in results['results']:
    print(r['title'])
    print(r['url'])
    print(r['content'][:200])
    print('---')

Tavily検索のパラメーター

Tavilyには、検索動作を制御する複数のパラメーターがあります。エージェントにとって特に便利なのは、max_results、search_depth、include_domains / exclude_domainsです。

# Basic search
results = client.search(
    query='Python async best practices 2024',
    max_results=5,
    search_depth='basic'  # 'basic' (fast) or 'advanced' (slower, deeper)
)

# Domain-filtered search
results = client.search(
    query='machine learning papers',
    max_results=5,
    include_domains=['arxiv.org', 'papers.nips.cc', 'openreview.net']
)

# Exclude low-quality domains
results = client.search(
    query='stock market today',
    max_results=5,
    exclude_domains=['pinterest.com', 'quora.com']
)

Tavilyの結果構造

Tavilyの各結果には、title、url、content(抽出されたテキスト)、score(関連性)、そして任意でpublished_dateが含まれます。contentフィールドはクリーンなテキストで、HTMLタグは含まれません。

results = client.search('Claude AI pricing 2024', max_results=3)

for r in results['results']:
    print(f"Title:   {r['title']}")
    print(f"URL:     {r['url']}")
    print(f"Score:   {r.get('score', 'N/A')}")
    print(f"Date:    {r.get('published_date', 'unknown')}")
    print(f"Content: {r['content'][:300]}")
    print()

# Tavily also returns 'answer' — a direct answer synthesized from results
if results.get('answer'):
    print('Direct answer:', results['answer'])

SerpApi:Google検索へのプログラムによるアクセス

SerpApiは、Google、Bing、YouTubeなどの検索エンジンに構造化された形でアクセスできます。オーガニック検索結果、ナレッジパネル、強調スニペット、ショッピング結果などを含む、豊富なデータを返します。

pip install google-search-resultsでインストールします。

from serpapi import GoogleSearch
import os

params = {
    'q': 'best Python web frameworks 2024',
    'api_key': os.getenv('SERPAPI_KEY'),
    'num': 5,              # number of results
    'hl': 'en',            # language
    'gl': 'us',            # country
    'safe': 'active'       # safe search
}

search = GoogleSearch(params)
results = search.get_dict()

for r in results.get('organic_results', []):
    print(r['title'])
    print(r['link'])
    print(r.get('snippet', ''))
    print()

SerpApiの結果構造

SerpApiは、Tavilyよりも豊富な構造化データを返します。organic_resultsの主なフィールドは、title、link、snippet、positionです。強調スニペットはanswer_boxの下に別途表示されます。

def extract_serp_results(serp_data, max_results=5):
    results = []

    # Featured snippet / answer box (highest priority)
    if 'answer_box' in serp_data:
        box = serp_data['answer_box']
        results.append({
            'title': box.get('title', 'Featured Snippet'),
            'url':   box.get('link', ''),
            'snippet': box.get('answer') or box.get('snippet', ''),
            'is_featured': True
        })

    # Organic results
    for r in serp_data.get('organic_results', [])[:max_results]:
        results.append({
            'title':   r.get('title', ''),
            'url':     r.get('link', ''),
            'snippet': r.get('snippet', ''),
            'position': r.get('position', 0),
            'is_featured': False
        })

    return results

if __name__ == '__main__':
    demo_serp = {
        'answer_box': {'title': 'Python version', 'link': 'https://python.org', 'answer': '3.13'},
        'organic_results': [
            {'title': 'Python Docs', 'link': 'https://docs.python.org', 'snippet': 'Official docs', 'position': 1},
        ],
    }
    for r in extract_serp_results(demo_serp):
        print(f"{'[FEATURED] ' if r['is_featured'] else ''}{r['title']} - {r['url']}")

最新性オプションと日付フィルタリング

時間に敏感なクエリでは、公開日で結果をフィルタリングしてください。Tavilyはdaysパラメーターを、SerpApiはtbs(時間ベース検索)パラメーターをサポートしています。

# Tavily: results from last 7 days
recent_results = client.search(
    query='AI news',
    max_results=5,
    days=7  # only results published in last 7 days
)

# SerpApi: results from last month
params = {
    'q': 'AI news',
    'api_key': os.getenv('SERPAPI_KEY'),
    'tbs': 'qdr:m',   # qdr:d=day, qdr:w=week, qdr:m=month, qdr:y=year
    'num': 5
}
search = GoogleSearch(params)
results = search.get_dict()

LangChain用検索ツールの構築

LangChainエージェント内でTavilyまたはSerpApiを使用するには、検索関数をToolとしてラップします。エージェントは、指定した説明に基づいて、他のツールと同じようにそれを呼び出せるようになります。

from langchain.tools import Tool
from tavily import TavilyClient
import os

tavily = TavilyClient(api_key=os.getenv('TAVILY_API_KEY'))

def tavily_search(query: str) -> str:
    results = tavily.search(query=query, max_results=3, search_depth='basic')
    output = []
    for r in results['results']:
        output.append(f"Title: {r['title']}\nURL: {r['url']}\nContent: {r['content'][:500]}")
    return '\n\n'.join(output)

web_search_tool = Tool(
    name='web_search',
    func=tavily_search,
    description='Search the web for current information. Input: a search query string. Returns top results with title, URL, and content.'
)

品質管理のためのドメインフィルタリング

すべての検索結果が信頼できるとは限りません。ドメインフィルタリングを使うと、信頼できるソース(調査用)に検索対象を限定したり、一般的なクエリでスパムの多いドメインを除外したりできます。

TRUSTED_DOMAINS = {
    'medical':  ['nih.gov', 'who.int', 'mayoclinic.org', 'pubmed.ncbi.nlm.nih.gov'],
    'legal':    ['law.cornell.edu', 'supreme.justia.com', 'congress.gov'],
    'tech':     ['docs.python.org', 'developer.mozilla.org', 'stackoverflow.com'],
    'finance':  ['sec.gov', 'federalreserve.gov', 'bloomberg.com']
}

SPAM_DOMAINS = ['pinterest.com', 'quora.com', 'answers.yahoo.com', 'wikihow.com']

def domain_aware_search(query, domain_category=None):
    kwargs = {'query': query, 'max_results': 5, 'exclude_domains': SPAM_DOMAINS}
    if domain_category and domain_category in TRUSTED_DOMAINS:
        kwargs['include_domains'] = TRUSTED_DOMAINS[domain_category]
    return client.search(**kwargs)

検索エラーとレート制限への対処

TavilyとSerpApiにはいずれもレート制限があります。指数バックオフによるリトライロジックを実装し、検索結果がない場合も適切に処理してください。

import time

def robust_search(query, max_retries=3):
    for attempt in range(max_retries):
        try:
            results = client.search(query=query, max_results=5)
            if results and results.get('results'):
                return results['results']
            print(f'No results for: {query}')
            return []
        except Exception as e:
            if '429' in str(e) or 'rate' in str(e).lower():
                wait = 2 ** attempt  # 1s, 2s, 4s
                print(f'Rate limited. Waiting {wait}s...')
                time.sleep(wait)
            else:
                print(f'Search error: {e}')
                return []
    return []

スニペット長の正規化

結果のスニペットの長さには大きなばらつきがあります。50文字のものもあれば、2000文字のものもあります。スニペットの長さを正規化すると、LLMのコンテキスト内で各ソースを均等に扱えます。

MAX_SNIPPET_CHARS = 600
MIN_SNIPPET_CHARS = 100

def normalize_snippets(results):
    normalized = []
    for r in results:
        content = r.get('content') or r.get('snippet', '')
        # Truncate long snippets at sentence boundary
        if len(content) > MAX_SNIPPET_CHARS:
            # Find last sentence end before limit
            cutoff = content.rfind('. ', 0, MAX_SNIPPET_CHARS)
            content = content[:cutoff + 1] if cutoff > 0 else content[:MAX_SNIPPET_CHARS]
        # Skip very short snippets
        if len(content) < MIN_SNIPPET_CHARS:
            continue
        normalized.append({**r, 'content': content})
    return normalized

if __name__ == '__main__':
    demo_results = [
        {'content': 'Short.'},
        {'content': 'A' * 200 + '. ' + 'B' * 500},
    ]
    for r in normalize_snippets(demo_results):
        print(f"Length {len(r['content'])}: {r['content'][:60]}...")

理解度チェック

AIエージェントにとって、一般的なウェブスクレイピングの手法と比べたTavilyの主な利点は何ですか?

まとめ:エージェント検索のためのTavilyとSerpApi

ウェブ検索APIにより、エージェントは学習カットオフ以降の最新情報にアクセスできます。TavilyはAIエージェント向けに特化しており、クリーンなコンテンツ抽出を提供します。一方、SerpApiは、強調スニペットやナレッジパネルなどを含む、より豊富なGoogleの構造化データを提供します。

主な実践方法は、品質管理にドメインフィルタリングを使用し、時間依存のクエリには最新性フィルターを適用し、スニペットの長さを正規化し、レート制限に対処するためバックオフ付きのリトライロジックを実装することです。

よくある質問

「エージェント検索向けTavilyとSerpAPI」レッスンは無料ですか?

はい。「エージェント検索向けTavilyとSerpAPI」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Agentsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Agentsコースには全4レッスンが含まれています。

「エージェント検索向けTavilyとSerpAPI」で何を学びますか?

Web検索ツールのAPI設定、クエリ構築、結果解析を学びます。 ブラウザで直接実行するハンズオンコードでAI Agentsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

AI Agentsを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAI Agentsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「エージェント検索向けTavilyとSerpAPI」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAI Agentsレッスンでコードを書いて実行できますか?

はい。すべてのAI Agentsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. エージェント検索向けTavilyとSerpAPI
  2. 検索結果のランキングとフィルタリング
  3. ディープリサーチループのパターン
  4. Web検索とRAGの組み合わせ
← AI Agentsに戻る