エージェントループでよくある失敗
無限ループ、同じツール呼び出しの繰り返し、最終回答に到達できない問題を学びます。
「エージェントループでよくある失敗」はCoddyKit上の無料AI Agentsレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Agents学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Agentsコースには全4レッスンが含まれています。
エージェントループとその失敗モード
エージェントループは、推論 → ツールの呼び出し → 結果の観測 → 再度の推論という処理を繰り返します。このループは強力である一方、壊れやすい側面もあります。よく知られた失敗モードがいくつかあり、エージェントが抜け出せなくなったり、トークンを浪費したり、有用な出力を生成できなくなったりします。
こうした失敗を理解することが、防御策を講じるための第一歩です。
失敗1:無限ループ
エージェントが同じ引数で同じツールを繰り返し呼び出し、進展しない場合に無限ループが発生します。ツールが役に立たない結果を返し、エージェントが推論によってそこから抜け出せない場合に起こることがあります。
# Example of an agent in an infinite loop:
# Step 1: reasoning='Need to search for Python docs'
# tool='search_web', args={'query': 'Python documentation'}
# Step 2: reasoning='Search result was unhelpful, try again'
# tool='search_web', args={'query': 'Python documentation'}
# Step 3: reasoning='Search result was unhelpful, try again'
# tool='search_web', args={'query': 'Python documentation'}
# ... repeats until max_iterations or token budget is exhausted
print('Symptom: same tool + same arguments appearing repeatedly in steps')
print('Fix: detect repeated (tool, args) pairs and break the loop')失敗2:行き詰まった状態
行き詰まった状態は、無限ループをより分かりにくくしたものです。エージェントは推論や異なるツールの呼び出しを続けますが、最終回答にたどり着けません。進展がないまま、複数のアプローチの間を行き来します。
# Example of a stuck agent:
# Step 1: tool='search_web', args={'query': 'topic A'}
# Step 2: tool='search_web', args={'query': 'topic B'} # different args
# Step 3: tool='search_web', args={'query': 'topic A'} # back to first
# Step 4: tool='read_document', args={'url': '...'}
# Step 5: tool='search_web', args={'query': 'topic A'}
# ... no FINAL_ANSWER ever produced
print('Symptom: agent takes many steps but never calls FINAL_ANSWER')
print('Fix: max_iterations guard + force final answer if limit is near')失敗3:最終回答の欠落
タスクが完了したと判断しないまま、ループを続けるエージェントもあります。情報を集めるだけで、それを統合して返すために処理を終了しません。これはトークンと時間の浪費につながります。
# An agent that never concludes:
def run_agent_bad(query: str, max_steps: int = 20) -> str:
for step in range(max_steps):
action = llm_decide_action(query, history)
if action['type'] == 'tool':
result = execute_tool(action)
history.append(result)
# BUG: No check for 'final_answer' type!
# The agent loops until max_steps, returning None
return None # never actually returns an answer
# Fix: explicitly check for final_answer signal
def run_agent_good(query: str, max_steps: int = 20) -> str:
for step in range(max_steps):
action = llm_decide_action(query, history)
if action['type'] == 'final_answer':
return action['answer'] # exit cleanly
execute_tool(action)
return 'Reached step limit without a conclusion.'失敗4:ツール呼び出しの解析エラー
LLMが関数呼び出し用の不正なJSONを生成すると、ツール実行器はそれを解析できません。適切に作られていないエージェントはクラッシュしたり、そのステップをひそかにスキップしたりします。堅牢なエージェントは解析エラーを捕捉し、そのエラーをLLMに返します。
import json
def safe_parse_tool_call(arguments_str: str) -> dict:
try:
return json.loads(arguments_str)
except json.JSONDecodeError as e:
print(f'Failed to parse tool arguments: {e}')
print(f'Raw: {arguments_str}')
return None
def execute_step(tool_call) -> str:
args = safe_parse_tool_call(tool_call.function.arguments)
if args is None:
# Feed the error back to the LLM in the next step
return f'ERROR: Could not parse tool arguments. Raw: {tool_call.function.arguments}'
return run_tool(tool_call.function.name, args)失敗5:ツールが有用なデータを返さない
ツールは技術的には成功していても(例外が発生しなくても)、空のデータや役に立たないデータを返すことがあります。すべてのツール呼び出しが実行可能な情報を返すとは限らないため、エージェントはこのケースに対処する必要があります。
def run_agent_with_empty_result_handling(query: str) -> str:
for step in range(20):
action = decide_next_action(query, history)
if action['type'] == 'final_answer':
return action['answer']
result = execute_tool(action['tool'], action['args'])
# Detect empty results and provide context
if not result or result.strip() == '':
observation = f'Tool {action["tool"]} returned no data. Try a different approach or different arguments.'
elif 'error' in result.lower():
observation = f'Tool error: {result}. Consider a different tool or query.'
else:
observation = result
history.append({'tool': action['tool'], 'result': observation})
return 'Could not complete task within step limit.'失敗6:存在しないツール名の生成
LLMが存在しないツール名を生成することがあります。呼び出しを試みる前に、必ず登録済みのツールと照合してツール名を検証してください。このような場合は、エージェントにわかりやすいエラーを返してください。
REGISTERED_TOOLS = {
'search_web': search_web_function,
'get_weather': get_weather_function,
'calculate': calculate_function
}
def dispatch_tool(tool_name: str, args: dict) -> str:
if tool_name not in REGISTERED_TOOLS:
available = ', '.join(REGISTERED_TOOLS.keys())
return (
f'ERROR: Unknown tool "{tool_name}". '
f'Available tools: {available}. '
f'Please use one of the available tools.'
)
tool_fn = REGISTERED_TOOLS[tool_name]
return tool_fn(**args)失敗7:トークン予算の枯渇
ツールの完全な結果をコンテキストに保存する長時間実行のエージェントは、LLMのコンテキストウィンドウの上限に達することがあります。履歴に追加する前に、大きなツール結果を要約するか、切り詰めてください。
def truncate_tool_result(result: str, max_chars: int = 2000) -> str:
if len(result) <= max_chars:
return result
truncated = result[:max_chars]
return f'{truncated}\n... [result truncated to {max_chars} chars]'
def add_observation_to_history(history: list, tool_name: str, result: str):
safe_result = truncate_tool_result(result, max_chars=2000)
history.append({
'role': 'tool',
'content': safe_result,
'tool_name': tool_name
})
print(f'[Step] Tool={tool_name}, Result length={len(result)} (stored {len(safe_result)})')
if __name__ == '__main__':
demo_history = []
add_observation_to_history(demo_history, 'search_web', 'x' * 3000)
失敗モードをプログラムで検出する
エージェントのステップ履歴を分析し、どの失敗モードが発生したかを特定する診断関数を作成してください。これはデバッグ時に非常に役立ちます。
def diagnose_agent_failure(steps: list) -> str:
if not steps:
return 'No steps recorded'
# Check for infinite loop: same (tool, args) repeated
seen = {}
for s in steps:
key = (s.get('tool'), str(s.get('args')))
seen[key] = seen.get(key, 0) + 1
repeated = {k: v for k, v in seen.items() if v > 2}
if repeated:
return f'INFINITE_LOOP: repeated actions: {repeated}'
# Check for missing final answer
has_answer = any(s.get('type') == 'final_answer' for s in steps)
if not has_answer and len(steps) >= 15:
return 'STUCK_STATE: many steps taken but no final answer'
# Check for parse errors
errors = [s for s in steps if 'ERROR' in str(s.get('result', ''))]
if len(errors) > 2:
return f'TOOL_ERROR: {len(errors)} tool errors in pipeline'
return 'OK'
if __name__ == '__main__':
demo_steps = [{'tool': 'search_web', 'args': {'q': 'weather'}} for _ in range(3)]
print('Diagnosis:', diagnose_agent_failure(demo_steps))
シンプルなステップ数上限を実装する
本番環境のエージェントループには、必ず厳格なステップ数上限を設けてください。これは最も重要な安全機構です。LLMが何を決定しても、ループが必ず終了することを保証します。
def run_agent_with_budget(query: str, max_steps: int = 15) -> dict:
history = []
for step in range(1, max_steps + 1):
print(f'[Step {step}/{max_steps}]')
action = decide_next_action(query, history)
if action['type'] == 'final_answer':
return {
'status': 'success',
'answer': action['answer'],
'steps_taken': step
}
result = execute_tool(action['tool'], action['args'])
history.append({'step': step, 'tool': action['tool'], 'result': result})
if step == max_steps - 1:
# Warn the agent it must conclude
history.append({'role': 'system',
'content': 'You must provide a FINAL_ANSWER on the next step.'})
return {'status': 'timeout', 'answer': None, 'steps_taken': max_steps}クイックリファレンス:失敗モードと修正方法
エージェントループにおける6つの失敗モードと、その修正方法をまとめます。
- 無限ループ:繰り返される(ツール、引数)の組を検出し、エラーフィードバックを返して中断します
- 行き詰まった状態:max_iterationsガードを設け、上限に近づいたら最終回答を強制します
- 最終回答の欠落:アクションに最終回答のシグナルがあるかを明示的に確認します
- 解析エラー:JSONの解析をtry/exceptで囲み、エラーをLLMに返します
- 空のツール結果:空の文字列を検出し、「データなし」というフィードバックを提供します
- 存在しないツール名の生成:登録済みのツールと照合して検証し、エラーメッセージを返します
理解度チェック:エージェントループの失敗
エージェントループでよくある失敗モードについての理解度を確認しましょう。
振り返り:エージェントループでよくある失敗
これで、エージェントループの主な失敗モードを特定し、防御できるようになりました。
- 無限ループ、行き詰まった状態、最終回答の欠落には、いずれも最大反復回数のガードが必要です
- ツール呼び出しの解析エラーには、JSONの解析をtry/exceptで囲む必要があります
- 空のツール結果には、検出とLLMへのわかりやすいフィードバックが必要です
- 存在しないツール名の生成には、登録済みツール一覧との照合が必要です
- トークン予算の枯渇には、結果の切り詰めが必要です
堅牢なエージェントループは、これらすべての失敗モードを予測し、適切に処理します。
よくある質問
「エージェントループでよくある失敗」レッスンは無料ですか?
はい。「エージェントループでよくある失敗」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Agentsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Agentsコースには全4レッスンが含まれています。
「エージェントループでよくある失敗」で何を学びますか?
無限ループ、同じツール呼び出しの繰り返し、最終回答に到達できない問題を学びます。 ブラウザで直接実行するハンズオンコードでAI Agentsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
AI Agentsを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAI Agentsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「エージェントループでよくある失敗」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAI Agentsレッスンでコードを書いて実行できますか?
はい。すべてのAI Agentsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- エージェントループでよくある失敗
- エージェントステップのトレースログ
- 無限ループの検出と停止
- ステップ実行デバッグの手法