0Pricing
AI Engineering Academy · 课时

分类智能体故障模式

建立智能体故障分类体系:工具错误、格式错误的输出、推理循环、上下文耗尽以及外部服务不可用,并为每种故障设计恢复策略。

分类智能体故障模式 是 CoddyKit 上的免费 AI Engineering Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Engineering Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Engineering Academy 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

Why Agents Fail in Distinctive Ways

Agents fail differently from simple LLM calls. A single-turn call either returns an answer or throws an error. An agent executing a multi-step task can fail at any point — and the failure might not be obvious from the final output. Understanding the taxonomy of agent failure modes is the first step toward building agents that detect, diagnose, and recover from their own failures.

Failure Mode 1: Tool Errors

Tool errors occur when the agent calls a tool with invalid arguments, the tool raises an exception, or the tool returns an empty or malformed result. Examples include: calling a search API with a malformed query, querying a database with invalid SQL, or invoking a code executor that times out. Tool errors are the easiest to detect because they produce explicit exception signals that can be caught and handled.

class ToolError(Exception):
    def __init__(self, tool_name: str, args: dict, error: Exception):
        self.tool_name = tool_name
        self.args = args
        self.original_error = error
        super().__init__(f'Tool {tool_name} failed: {error}')

def safe_tool_call(tool_func, args: dict) -> str:
    try:
        result = tool_func(**args)
        if not result:
            return 'Tool returned empty result. Try a different approach.'
        return str(result)
    except Exception as e:
        raise ToolError(tool_func.__name__, args, e)

Failure Mode 2: Malformed Outputs

Malformed outputs happen when the agent generates text that does not match the expected format — for example, returning natural language when the next step expects JSON, or calling a tool with arguments in the wrong structure. This often happens when the agent confuses its current step with a previous one. Validate the format of every agent output before using it and re-prompt when the format is wrong.

import json

def validate_agent_output(raw_output: str, expected_format: str) -> dict:
    if expected_format == 'json':
        try:
            return json.loads(raw_output)
        except json.JSONDecodeError as e:
            return {
                'valid': False,
                'error': f'Expected JSON but got invalid JSON: {e}',
                'raw': raw_output[:200]
            }
    return {'valid': True, 'data': raw_output}

Failure Mode 3: Reasoning Loops

Reasoning loops occur when an agent repeats the same action or thought indefinitely without making progress. The agent might call the same search query 10 times in a row, getting the same empty result and not knowing what to try next. Detect loops by tracking recent actions and checking for repeats. When a loop is detected, inject a meta-prompt telling the agent to try a different approach.

from collections import Counter

class LoopDetector:
    def __init__(self, window: int = 5, threshold: int = 3):
        self.recent_actions = []
        self.window = window
        self.threshold = threshold

    def record(self, action: str) -> bool:
        self.recent_actions.append(action)
        if len(self.recent_actions) > self.window:
            self.recent_actions.pop(0)
        counts = Counter(self.recent_actions)
        most_common_count = counts.most_common(1)[0][1] if counts else 0
        return most_common_count >= self.threshold  # True = loop detected

Failure Mode 4: Context Exhaustion

Context exhaustion happens when the agent's accumulated history (tool calls, observations, thoughts) exceeds the model's context window. The model either truncates the history silently (losing critical information) or raises a token limit error. Prevent this by tracking token usage across steps and compressing the history (summarizing old steps) before it reaches the limit.

import tiktoken

CONTEXT_LIMIT = 100_000  # tokens
COMPRESS_AT = 80_000     # trigger compression with headroom

enc = tiktoken.encoding_for_model('gpt-4o')

def total_tokens(messages: list) -> int:
    return sum(len(enc.encode(str(m))) for m in messages)

def check_context(messages: list) -> str:
    tokens = total_tokens(messages)
    if tokens > COMPRESS_AT:
        return 'compress'
    if tokens > CONTEXT_LIMIT:
        return 'critical'
    return 'ok'

Failure Mode 5: External Service Unavailability

External service failures occur when a tool's underlying service is down, rate-limited, or returns unexpected errors. An agent that cannot reach the database it needs to query is stuck. Unlike reasoning loops (agent's fault), external failures are environment failures. Handle them with retry + exponential backoff, and have fallback tools that can approximate the result using different data sources.

import asyncio

async def resilient_tool_call(tool_func, args: dict, max_retries: int = 3) -> str:
    for attempt in range(max_retries):
        try:
            return await tool_func(**args)
        except (ConnectionError, TimeoutError) as e:
            if attempt == max_retries - 1:
                return f'Service unavailable after {max_retries} attempts. Error: {e}'
            wait = 2 ** attempt  # 1s, 2s, 4s
            await asyncio.sleep(wait)
    return 'Unexpected error in resilient_tool_call'

Failure Mode 6: Goal Misunderstanding

Goal misunderstanding is when the agent misinterprets the task and pursues a subtly different objective. This is the hardest failure to detect because the agent may complete successfully — just not the task the user intended. Mitigate it by asking the agent to restate the goal in its own words at the start, and by implementing a final verification step that checks whether the result actually answers the original question.

async def confirm_goal_understanding(original_task: str) -> str:
    resp = await client.chat.completions.create(
        model='gpt-4o',
        messages=[
            {'role': 'system', 'content': 'Restate the task in your own words. Be specific about what the final deliverable should be.'},
            {'role': 'user', 'content': f'Task: {original_task}'}
        ]
    )
    return resp.choices[0].message.content

# Use the restatement as the first step of the agent
# to catch misunderstandings before any tools are called

Building a Failure Classification System

Create a structured failure classifier that labels every agent exception with its type. This enables automatic routing to the appropriate recovery strategy. Store failure logs with type labels so you can analyze which failure modes are most common and prioritize which to address first. Tool errors and loops are typically most frequent and most fixable.

from enum import Enum
from dataclasses import dataclass

class FailureType(Enum):
    TOOL_ERROR = 'tool_error'
    MALFORMED_OUTPUT = 'malformed_output'
    REASONING_LOOP = 'reasoning_loop'
    CONTEXT_EXHAUSTION = 'context_exhaustion'
    EXTERNAL_SERVICE = 'external_service'
    GOAL_MISUNDERSTANDING = 'goal_misunderstanding'
    MAX_ITERATIONS = 'max_iterations'
    UNKNOWN = 'unknown'

@dataclass
class AgentFailure:
    failure_type: FailureType
    step: int
    tool_name: str | None
    error_message: str
    recoverable: bool

Mapping Failures to Recovery Actions

Each failure type has an appropriate recovery action. Tool errors warrant a retry with adjusted arguments. Loops warrant a diversity prompt telling the agent to try something new. Context exhaustion warrants compression. External service failures warrant fallback tools. Goal misunderstanding warrants a clarification request. Map these explicitly in a recovery router that the agent runtime invokes when failures occur.

RECOVERY_ACTIONS = {
    FailureType.TOOL_ERROR:           'retry_with_corrected_args',
    FailureType.MALFORMED_OUTPUT:     'reformat_output',
    FailureType.REASONING_LOOP:       'inject_diversity_prompt',
    FailureType.CONTEXT_EXHAUSTION:   'compress_history',
    FailureType.EXTERNAL_SERVICE:     'use_fallback_tool',
    FailureType.GOAL_MISUNDERSTANDING:'request_clarification',
    FailureType.MAX_ITERATIONS:       'escalate_to_human',
    FailureType.UNKNOWN:              'escalate_to_human'
}

Setting Maximum Iteration Limits

Every agent must have a maximum iteration limit as a hard safety boundary. Without it, a looping agent runs indefinitely, consuming tokens and money. Set the limit based on expected task complexity: a simple question-answering agent might cap at 5 steps, while a complex research agent might allow 20. When the limit is reached, log the failure, save the partial results, and escalate to a human or return a partial answer.

MAX_ITERATIONS = 15

async def run_agent(task: str) -> str:
    messages = [{'role': 'user', 'content': task}]
    loop_detector = LoopDetector()
    for iteration in range(MAX_ITERATIONS):
        response = await get_agent_action(messages)
        if response.is_final:
            return response.answer
        action_key = f'{response.tool}:{response.args}'
        if loop_detector.record(action_key):
            messages.append({'role': 'system', 'content': 'You are repeating yourself. Try a completely different approach.'})
            continue
        result = await execute_tool(response.tool, response.args)
        messages.append({'role': 'tool', 'content': result})
    return 'Task exceeded maximum iterations. Partial results: ' + get_partial_result(messages)

Logging Failures for Post-Mortem Analysis

Log every agent failure with enough context to diagnose it after the fact: the full task description, the complete action history up to the failure point, the failure type and error message, the iteration count, and the token usage. Store this in a failures table with an index on failure_type and task_id. Regularly review failure logs to identify which task types are most prone to specific failure modes and prioritize fixes accordingly.

import json
from dataclasses import asdict

async def log_agent_failure(task_id: str, failure: AgentFailure, history: list, pool):
    async with pool.acquire() as conn:
        await conn.execute('''
            INSERT INTO agent_failures
            (task_id, failure_type, step, tool_name, error_message,
             recoverable, action_history, failed_at)
            VALUES ($1, $2, $3, $4, $5, $6, $7, NOW())
        ''',
            task_id,
            failure.failure_type.value,
            failure.step,
            failure.tool_name,
            failure.error_message,
            failure.recoverable,
            json.dumps(history)
        )

Quick Check

Test your understanding of agent failure mode classification.

Lesson Recap

In this lesson you learned: six major agent failure modes include tool errors, malformed outputs, reasoning loops, context exhaustion, external service failures, and goal misunderstanding, loop detection via action history catches repetitive patterns before they exhaust the iteration budget, and mapping failure types to recovery actions enables automated self-healing. Next up we implement self-correction and reflective prompting.

常见问题解答

「分类智能体故障模式」课时是免费的吗?

是的 — 「分类智能体故障模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Engineering Academy 课程的其余内容,请升级到 CoddyKit PRO。 AI Engineering Academy 课程共包含 4 节课。

「分类智能体故障模式」这节课中我会学到什么?

建立智能体故障分类体系:工具错误、格式错误的输出、推理循环、上下文耗尽以及外部服务不可用,并为每种故障设计恢复策略。 你通过在浏览器中直接运行的动手代码来练习 AI Engineering Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 AI Engineering Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 AI Engineering Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「分类智能体故障模式」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 AI Engineering Academy 课中编写并运行代码吗?

能。每节 AI Engineering Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 分类智能体故障模式
  2. 自我纠错与反思式提示
  3. 检查点与任务恢复
  4. 人工介入升级
← 返回 AI Engineering Academy