0Pricing
AI Agents · レッスン

ツールエラーの検出と復旧

ツールが500エラーを返したとき、クラッシュさせず別の方法を試せるよう、エラーをモデルに返します。

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

ツールは失敗します。対策を用意しましょう

実際のツールはどれも、ときどき失敗します:

  • ネットワークのタイムアウト
  • レート制限
  • モデルからの不正な引数
  • 外部サービスの停止
  • 認証情報の無効化

本番環境のエージェントは、適切に復旧できなければなりません。

常に返し、決して raise しない

エージェントのループ内では、すべてのツールエラーを捕捉してコンテンツとして返します。例外によってループを停止させてはいけません:

def safe_dispatch(tool_call):
    try:
        args = json.loads(tool_call.function.arguments)
        return TOOLS[tool_call.function.name](**args)
    except json.JSONDecodeError:
        return {'error': 'Arguments are not valid JSON.'}
    except KeyError:
        return {'error': f'Unknown tool: {tool_call.function.name}'}
    except Exception as e:
        return {'error': f'{type(e).__name__}: {e}'}

構造化されたエラー形式

モデルがエラーを認識できるように、一貫した形式を使います:

error = {'ok': False, 'error_type': 'TimeoutError', 'error_message': 'Tavily timed out after 10s', 'retryable': True}
print(error)

リトライ可能なエラーと恒久的なエラーを区別する

タイムアウトのようにリトライすべきエラーもあれば、404 のようにリトライすべきでないエラーもあります。モデルに次のように伝えます:

if isinstance(e, requests.Timeout):
    return {'ok': False, 'retryable': True, 'error': str(e)}
if isinstance(e, ValueError):
    return {'ok': False, 'retryable': False, 'error': str(e)}

一時的なエラーを自動的にリトライする

ネットワーク呼び出しでは、指数バックオフを使ってリトライします:

from tenacity import retry, wait_exponential, stop_after_attempt, retry_if_exception_type

@retry(
    wait=wait_exponential(multiplier=1, max=10),
    stop=stop_after_attempt(3),
    retry=retry_if_exception_type((requests.Timeout, requests.ConnectionError))
)
def web_search(query):
    return requests.get('https://api.tavily.com/search', ...).json()

引数の検証

ツールを呼び出す前に、Pydantic モデルで引数を検証します:

from pydantic import BaseModel, ValidationError

class SearchArgs(BaseModel):
    query: str
    k: int = 5

try:
    args = SearchArgs.model_validate_json(tool_call.function.arguments)
except ValidationError as e:
    return {'error': f'Bad arguments: {e}'}

モデルにエラーを示す

エラーをツールの結果として追加し、もう一度モデルを呼び出します。モデルが自力で修正することはよくあります:

messages.append({
    'role': 'tool',
    'tool_call_id': tc.id,
    'content': json.dumps({'error': 'Argument k must be an integer'})
})
# Next model call: 'Sorry, let me retry with k=5...'

無限エラーループを避ける

エラーを示されると、同じ壊れた呼び出しをリトライするモデルもあります。ループに上限を設け、繰り返しを検出します:

recent_calls = []
for tc in msg.tool_calls:
    key = (tc.function.name, tc.function.arguments)
    if recent_calls.count(key) >= 3:
        return 'Agent stuck in retry loop, aborting.'
    recent_calls.append(key)

ツールごとの復旧

不安定さが既知のツールでは、リトライ処理をループの中ではなく、ツールの内部に実装します。

def search_with_fallback(query):
    try:
        return tavily_search(query)
    except Exception:
        return bing_search(query)   # secondary provider

すべての呼び出しにタイムアウトを設定

すべての外部呼び出しにタイムアウトが必要です。設定しないと、1つの遅いサービスによってエージェント全体が停止してしまいます。

import requests
response = requests.get(url, timeout=10)  # 10s

# For LLM calls:
from openai import OpenAI
client = OpenAI(timeout=30.0)

サーキットブレーカー

ツールが繰り返し失敗した場合は、サーキットを「開」にして、一定時間そのツールをスキップします。

import time

class CircuitOpen(Exception):
    pass

def circuit(failure_threshold=5, recovery_timeout=60):
    def decorator(func):
        state = {'failures': 0, 'open_until': 0}
        def wrapper(*args, **kwargs):
            if time.time() < state['open_until']:
                raise CircuitOpen('circuit is open')
            try:
                result = func(*args, **kwargs)
                state['failures'] = 0
                return result
            except Exception:
                state['failures'] += 1
                if state['failures'] >= failure_threshold:
                    state['open_until'] = time.time() + recovery_timeout
                raise
        return wrapper
    return decorator

@circuit(failure_threshold=3, recovery_timeout=1)
def fragile_tool(x):
    if x < 0:
        raise ValueError('bad input')
    return x * 2

for x in [1, -1, -1, -1, -1]:
    try:
        print('ok', fragile_tool(x))
    except CircuitOpen as e:
        print('blocked:', e)
    except ValueError as e:
        print('failed:', e)

コンテキスト付きでエラーをログに記録

後からデバッグできるだけの情報を記録します。ツール名、引数、エラーの種類、スタックトレース、リクエストID、ユーザーID、トレースIDを含めます。使用しているオブザーバビリティツールに送信します。

グレースフルデグラデーション

重要なツールが停止している場合は、エージェントが成功したかのように振る舞わず、ユーザーに正直に伝えます。

if all_search_tools_failed:
    return 'I was unable to search the web right now. Please try again in a few minutes.'

ツールエラーのパターン

エージェントのループ内でツールの例外を処理する最も安全な方法は何でしょうか。

まとめ

ツールは失敗します。例外を捕捉して分類し、構造化したコンテンツとして扱い、エージェントが復旧できるようにします。本番環境で信頼性を確保するために、タイムアウト、リトライ、サーキットブレーカーを追加します。

よくある質問

「ツールエラーの検出と復旧」レッスンは無料ですか?

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

「ツールエラーの検出と復旧」で何を学びますか?

ツールが500エラーを返したとき、クラッシュさせず別の方法を試せるよう、エラーをモデルに返します。 ブラウザで直接実行するハンズオンコードでAI Agentsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「ツールエラーの検出と復旧」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

  1. ReAct:Reason + Actパターン
  2. ReActをゼロから実装する
  3. 一般的なツールセット(Web、計算機、RAG)
  4. ツールエラーの検出と復旧
← AI Agentsに戻る