0Pricing
Claude Architect · 课时

本地恢复与升级

重试瞬态故障;对不可恢复的问题进行升级。

本地恢复与升级 是 CoddyKit 上的免费 Claude Architect 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Claude Architect 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Claude Architect 课程共包含 4 节课。

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

Two Ways a Step Can Fail

Inside an agentic system, a single tool call or subagent step can fail for very different reasons. The architect's job is to classify the failure before reacting.

  • Transient fault — a momentary, self-correcting problem: a network blip, a rate limit, a brief timeout. Retrying the exact same call may just work.
  • Non-recoverable failure — a structural problem: invalid credentials, a missing permission, a malformed request, or a business rule violation. Retrying changes nothing.

The core rule of this lesson: recover transient faults locally, escalate the non-recoverable.

Local Recovery: Keep It in the Subagent

In a hub-and-spoke multi-agent system, the coordinator delegates work to subagents. When a subagent hits a transient fault, it should try to fix it where it happened — without bubbling noise up to the coordinator.

This keeps the coordinator focused on orchestration instead of low-level retries, and it preserves the coordinator's context budget. Local recovery is the first line of defense.

def run_tool_with_local_recovery(tool, args, max_attempts=3):
    for attempt in range(max_attempts):
        result = tool(**args)
        if not result.get("isError"):
            return result
        # Only retry faults the result says are retryable
        if result.get("isRetryable") and result.get("errorCategory") == "transient":
            continue
        break  # validation / business / permission -> stop, escalate
    return result  # hand the structured error upward

Let the Error Tell You What to Do

You can only route intelligently if the failure is structured. A generic "Operation failed" blocks recovery — the agent can't tell a rate limit from a permission denial.

A well-designed MCP tool returns an error envelope:

  • isError: true
  • errorCategory: transient / validation / business / permission
  • isRetryable: boolean
  • message, attempted_query, partial_results

The errorCategory drives the decision: transient is a retry candidate; validation, business, and permission are not.

{
  "isError": true,
  "errorCategory": "transient",
  "isRetryable": true,
  "message": "Upstream timeout after 5s",
  "attempted_query": "SELECT * FROM orders WHERE customer_id = 4821",
  "partial_results": []
}

Failure vs Empty Result

A subtle but exam-critical distinction: an access failure is not the same as a valid empty result.

  • Failure — the query never completed (timeout, auth error). The data is unknown. This might be retryable.
  • Empty — the query ran successfully and found nothing. 0 rows is a correct, final answer. Retrying is pointless and misleading.

Conflating the two leads agents to retry forever on legitimate "no matches found" cases, or to report a real outage as "no data."

if result.get("isError"):
    handle_failure(result)          # access failure: maybe retry / escalate
elif len(result["rows"]) == 0:
    return "No matching records found."   # valid empty result, DONE
else:
    return result["rows"]

When to Escalate

Escalation means handing the problem up — to the coordinator, or ultimately to a human. Good escalation triggers are objective:

  • An explicit human request — escalate immediately, no further attempts.
  • A policy gap — the situation isn't covered by the rules the agent has.
  • No progress after attempts — local recovery exhausted.
  • A threshold violation — e.g. a refund exceeds an allowed limit.

Notice these are all things you can detect deterministically — not guesses about the user's mood.

Bad Escalation Triggers

Just as important: know what not to escalate on. These triggers feel reasonable but are unreliable and are classic exam distractors:

  • Sentiment analysis — escalating because the message "sounds angry."
  • Model self-rated confidence — "I'm only 4/10 confident, so escalate." Self-ratings are not calibrated.
  • Untrained classifiers bolted on as gatekeepers.

Instead, follow the proven pattern: acknowledge the emotion, propose a concrete solution, and escalate only if the customer reiterates the request. Behavior — a repeated explicit ask — is a far better signal than inferred feeling.

Escalate WITH Context, Not Just a Shrug

When a subagent escalates, it must propagate structured context so the coordinator (or human) can act without re-doing the work:

  • the failure type (the errorCategory),
  • the attempted query or action,
  • any partial results already gathered,
  • and viable alternatives.

An escalation that says only "it failed" forces the coordinator to start from zero. An escalation carrying partial results lets the rest of the workflow continue and the human resolve faster.

def escalate(coordinator, failure):
    coordinator.report(
        failure_type=failure["errorCategory"],
        attempted_query=failure["attempted_query"],
        partial_results=failure.get("partial_results", []),
        alternatives=["retry via read-replica", "ask user for order ID"],
    )

Don't Abort the Whole Workflow

One failed branch should not collapse the entire job. In a multi-agent research system, if one source is unreachable, the coordinator should still aggregate the successful branches and clearly annotate the gap in coverage.

Two failure modes to avoid:

  • Silent suppression — swallowing the error so the final answer looks complete but isn't. This destroys trust and provenance.
  • Whole-workflow abort — killing every other branch because one failed.

The middle path: continue, deliver partial results, and be explicit about what's missing.

Caps Are a Safety Net, Not the Plan

A retry loop needs a bound, but the bound is a safety net — never the primary control mechanism. The same principle governs the whole agentic loop: you terminate on stop_reason reaching end_turn, and iteration caps merely prevent runaway loops.

For retries specifically: stop because the structured error says isRetryable: false, or because progress has been made — not merely because you hit attempt #3. The cap exists so a transient-looking-but-permanent fault can't spin forever.

# Cap = backstop. The REAL stop signal is the error category.
for attempt in range(MAX_ATTEMPTS):   # safety net only
    res = call_tool(args)
    if not res["isError"]:
        return res
    if not res["isRetryable"]:        # primary, decision-driven stop
        return escalate(res)
    sleep(backoff(attempt))
return escalate(res)                  # exhausted -> escalate, never silent

Deterministic Guards for Hard Limits

Some escalations protect against financial, legal, or safety consequences — for example, a refund above a policy threshold. Here, prompt guidance (~90% reliable) is not enough.

Use a hook for 100% deterministic enforcement. A PostToolUse or outgoing-call hook can block a policy-violating action before it ever executes, forcing escalation to a human. Prompts persuade; hooks guarantee.

# .claude hook: block refunds over $500 -> force escalation
def on_outgoing_call(call):
    if call.tool == "process_refund" and call.args["amount"] > 500:
        return {
            "block": True,
            "reason": "Refund exceeds $500 policy limit; escalate to human.",
        }
    return {"block": False}

Putting It Together: The Decision Flow

For any failed step, walk this flow:

  • 1. Empty, not failed? Return the valid empty result. Done.
  • 2. Transient + retryable? Recover locally with bounded retries and backoff.
  • 3. Recovered? Continue the workflow.
  • 4. Non-recoverable (validation / business / permission), explicit human request, policy gap, threshold violation, or retries exhausted? Escalate with structured context and partial results.

Never silently suppress, never abort the whole workflow, and never escalate on sentiment or self-rated confidence.

Quick Check

A subagent's database tool returns isError: true, errorCategory: "permission", isRetryable: false, with the attempted query and empty partial results. What should the subagent do?

Recap: Recover Local, Escalate the Rest

Key takeaways:

  • Classify first: transient (retryable) vs non-recoverable (validation/business/permission).
  • Recover transient faults locally in the subagent with bounded retries; the cap is a safety net, the structured error is the real stop signal.
  • Distinguish access failure from a valid empty result — 0 rows is a final answer, not a retry trigger.
  • Escalate the non-recoverable with structured context: failure type, attempted query, partial results, alternatives.
  • Escalate on objective triggers (explicit human request, policy gap, no progress, threshold violation) — never on sentiment or self-rated confidence.
  • Enforce financial/legal/safety limits with hooks, not prompts. Never silently suppress; never abort the whole workflow on one failure.

常见问题解答

「本地恢复与升级」课时是免费的吗?

是的 — 「本地恢复与升级」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Claude Architect 课程的其余内容,请升级到 CoddyKit PRO。 Claude Architect 课程共包含 4 节课。

「本地恢复与升级」这节课中我会学到什么?

重试瞬态故障;对不可恢复的问题进行升级。 你通过在浏览器中直接运行的动手代码来练习 Claude Architect,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Claude Architect 需要有经验吗?

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

「本地恢复与升级」课时需要多长时间?

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

我能在这节 Claude Architect 课中编写并运行代码吗?

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

此课程中的所有课时

  1. 明确的升级触发条件
  2. 反模式:情绪与置信度评分
  3. 结构化错误上下文
  4. 本地恢复与升级
← 返回 Claude Architect