Learn-Claude-Code | 笔记 | Planning & Coordination | s11_new Error Recovery
目录
写在前面
learn-claude-code 项目目前有两条教程线,一条是之前的 s12 章节的,另一条是最近更新的 s20 章节的,大家如果刚学习这个项目的话推荐直接看最新的 s20 章节的教程即可,由于博主之前学习过 s12 章节的内容,因此打算把 s20 章节中新增章节的内容给补充学习,内容重复的章节博主这边就跳过了。
下面是旧版到新版的对应关系:
| Legacy 12-lesson track | Current 20-lesson track | Topic |
|---|---|---|
| old s01 | new s01 | Agent Loop |
| old s02 | new s02 | Tool Use |
| old s03 | new s05 | TodoWrite |
| old s04 | new s06 | Subagent |
| old s05 | new s07 | Skill Loading |
| old s06 | new s08 | Context Compact |
| old s07 | new s12 | Task System |
| old s08 | new s13 | Background Tasks |
| old s09 | new s15 | Agent Teams |
| old s10 | new s16 | Team Protocols |
| old s11 | new s17 | Autonomous Agents |
| old s12 | new s18 | Worktree Isolation |
| new only | s03, s04, s09, s10, s11, s14, s19, s20 | Permission, Hooks, Memory, System Prompt, Error Recovery, Cron, MCP, Comprehensive Agent |
从上表中我们可以看出我们需要补充的内容包括 s03(已补充)、s04(已补充)、s09(已补充)、s10(已补充)、s11、s14、s19 以及 s20 八个章节的内容。
新版学习路径如下:
主线:能动手 → 能做复杂任务 → 能记住和恢复 → 能长期运行 → 能协作 → 能扩展并合体

前言
在上篇文章 Learn-Claude-Code | 笔记 | Planning & Coordination | s10_new System Prompt 中,我们介绍了开源项目 learn-claude-code 新版第十个章节 s10_new: System Prompt 的内容,这篇文章我们继续跟着教程文档来学习规划与拆解相关内容,记录下个人学习笔记,和大家一起分享交流😄
Note:本篇文章主要学习记录 新版教程 第二部分 Planning & Coordination 中 s11: Error Recovery 章节的内容。
github:https://github.com/shareAI-lab/learn-claude-code
reference:https://chatgpt.com/
1. s11: Error Recovery
在前面的 s10 中,我们已经把 System Prompt 从一段硬编码字符串,升级成了由运行时状态动态组装出来的提示词系统。也就是说,Agent 在每一轮调用 LLM 之前,不再只是简单地把 messages 丢给模型,而是会先根据当前 workspace、工具列表、memory 内容等上下文,组装出一个更稳定、更可追踪的 system prompt。
但是到这里为止,Agent Loop 仍然有一个非常明显的问题:只要 LLM 调用过程中出现异常,整个 Agent 就会直接中断。
真实生产环境中的 Agent 不可能永远运行在理想条件下。模型可能输出到一半触发 max_tokens,上下文可能因为多轮对话、工具结果、记忆加载而超出窗口限制,API 服务也可能因为限流、过载、网络抖动而返回 429 或 529。如果这些错误都让主循环直接崩溃,那么这个 Agent 只能算是一个 Demo,而不是一个可以长期运行的工程系统。
所以 s11 的核心任务,就是给 Agent Loop 加上一层错误恢复能力。
它并没有推翻前面已经建立起来的结构。s10 的 prompt assembly 仍然保留,s08/s09 的压缩和记忆加载仍然保留,工具执行逻辑也没有变化。s11 真正新增的是:把 LLM 调用包进 try/except 中,并根据不同错误类型选择不同的恢复路径。
换句话说,s11 让 Agent 从 “出错即退出” 变成了 “出错先分类,分类后恢复,恢复后回到 loop 继续执行”。
2. 问题
在一个最简单的 Agent Loop 中,LLM 调用通常长这样:
response = client.messages.create(
model=MODEL,
system=system,
messages=messages,
tools=TOOLS,
max_tokens=8000,
)
如果这次调用成功,Agent 就继续判断 stop_reason,要么输出最终回答,要么执行工具,再把工具结果追加回 messages,进入下一轮循环。
但是如果这里报错,比如:
Error: 529 overloaded
或者:
prompt_too_long
或者模型虽然没有抛异常,但是返回了:
response.stop_reason == "max_tokens"
那么原来的 Agent Loop 就没有任何处理能力。
这三类错误在 Agent 系统中非常常见。第一类是输出被截断,说明模型还没说完就达到了输出 token 上限;第二类是上下文超限,说明当前 messages、system prompt、tool results、memory 等信息合起来已经超过模型可接受的上下文窗口;第三类是临时故障,例如 429 限流、529 过载,这类错误并不代表任务本身失败,而是服务端暂时不可用。
因此,s11 的工程目标不是让错误消失,而是让 Agent 面对错误时具备 “韧性”:能识别错误、选择恢复策略、限制恢复次数,并在恢复失败时干净退出。
3. 解决方案
本节的整体架构可以用下面这张图概括:

从主流程上看,s11 仍然延续了前面几节的 Agent Loop:
messages → prompt assembly → compress + load → LLM → TOOL_HANDLERS → messages → 下一轮
这里的 messages 仍然是对话历史,prompt assembly 来自 s10,compress + load 对应 s08 和 s09 中的压缩与记忆加载,TOOL_HANDLERS 仍然负责执行 bash、read_file、write_file 等工具。
唯一关键变化是:LLM 调用不再是裸调用,而是被错误恢复机制包裹起来。
当 LLM 正常返回时,Agent 继续原来的工具执行流程;当 LLM 返回 max_tokens 时,Agent 会尝试扩大输出预算或注入续写提示;当 API 抛出 prompt too long 错误时,Agent 会触发 reactive compact;当遇到 429 或 529 这类临时故障时,Agent 会进行指数退避重试,必要时切换 fallback model。
这就是 s11 的核心思想:恢复逻辑是 Agent Loop 的外壳,而不是 Agent Loop 的替代品。
s11 的教程版主要实现了三条最常见的恢复路径。
第一条路径是 max_tokens。这不是 API 异常,而是模型正常返回了响应,但响应被输出 token 上限截断了。也就是说,模型还能继续说,只是当前 max_tokens=8000 不够用。对于这种情况,s11 不会立刻把截断内容追加到 messages 中,而是先把输出预算从 8K 升级到 64K,然后用同一个请求重新调用一次模型。
第二条路径是 prompt_too_long。这类错误说明上下文太长,模型根本接收不了当前请求。这时继续重试没有意义,因为请求内容本身没有变。s11 的做法是触发一次 reactive_compact,也就是紧急压缩上下文。教学版中为了简化,只保留最后 5 条消息;真实系统中通常会调用 LLM 生成 compact summary,再用压缩后的上下文重试。
第三条路径是 429 / 529。这类错误不是任务逻辑错误,而是服务端临时状态问题。429 表示请求被限流,529 表示模型服务过载。s11 对这类错误采用指数退避加随机抖动:第一次等 0.5 秒,第二次等 1 秒,第三次等 2 秒,后面继续指数增长,但有最大等待上限。同时,如果连续多次遇到 529,并且配置了备用模型,系统可以切换到 fallback model 继续执行。
这三条路径对应三种不同的工程判断:
- max_tokens → 输出空间不够,所以扩大输出预算或续写
- prompt_too_long → 输入上下文太长,所以压缩上下文
- 429 / 529 → 服务暂时不可用,所以等待后重试或切换模型
这也是错误恢复设计中最重要的一点:不要盲目 retry,而是先判断错误类型,再选择最小恢复动作。
4. Error Recovery Paths 流程图分析
Web 教程中的 Error Recovery Paths 示例图,把 s11 的恢复路径拆成了更加直观的状态面板:左侧是 Failure inbox,中间是 RecoveryState,右侧是 Recovery action。

第一张图展示的是正常情况。LLM 调用成功,没有错误,也不需要恢复,Agent 直接进入正常的 tool loop。这一点很重要,因为错误恢复机制不应该干扰正常路径。正常路径必须仍然是最快、最简单、最低成本的路径。

第二张图展示 max_tokens 的恢复路径。模型输出被截断后,系统不会立刻生成续写提示,而是先把输出预算从 8K 提升到 64K,然后用相同请求重试。这个设计避免了过早把截断内容写入对话历史,也避免了模型在下一轮中对半截输出产生误解。

第三张图展示 prompt_too_long 的恢复路径。上下文超限时,继续原样重试没有任何意义,所以系统会执行 reactive compact,压缩 messages 后再重试一次。如果压缩后仍然太长,就干净退出,而不是无限压缩、无限重试。

第四张图展示 429 的恢复路径。429 的本质是限流,说明服务端不是不能处理这个任务,而是当前请求频率太高。因此最合理的恢复动作不是修改 prompt,也不是切换任务,而是等待一段时间再重试。这里采用指数退避和抖动,让重试行为对服务端更友好。

第五张图展示 529 的恢复路径。529 表示服务过载,和 429 一样也可以先退避重试。但如果连续多次发生 529,就说明当前模型可能持续不可用。这时系统可以切换到 fallback model,把任务继续推进下去。

第六张图把所有恢复路径合在一起:max_tokens、prompt_too_long、429、529 都进入同一个 Failure inbox,但它们不会被同一种方式处理。每一种错误都对应 RecoveryState 中的某些字段,也对应右侧的一种恢复动作。最终,要么恢复成功回到正常循环,要么达到限制后干净退出。
这组图非常好地说明了 s11 的核心理念:错误恢复不是 “失败后重跑一次”,而是对失败进行分类、记录状态、执行有限恢复动作。
完整动画演示如下图所示:

5. 工作原理(代码分析)
OK,下面我们就来看看代码具体是如何实现的:
1. RecoveryState:把恢复状态显式保存下来
s11 首先新增了一个 RecoveryState 类,用来记录当前 Agent 在错误恢复过程中的状态:
class RecoveryState:
"""Track recovery attempts across the loop."""
def __init__(self):
self.has_escalated = False
self.recovery_count = 0
self.consecutive_529 = 0
self.has_attempted_reactive_compact = False
self.current_model = PRIMARY_MODEL
这里每个字段都对应一类恢复控制。
has_escalated 表示是否已经把 max_tokens 从 8K 升级到 64K。这个动作只能做一次,因为如果无限升级输出预算,本质上是在掩盖模型输出过长的问题。
recovery_count 表示 max_tokens 触发后,续写提示已经使用了几次。代码中限制最多续写 3 次,避免模型一直 “接着说”,但没有真正完成任务。
consecutive_529 用来记录连续发生 529 过载的次数。如果连续过载达到阈值,并且配置了 FALLBACK_MODEL_ID,系统就会切换备用模型。
has_attempted_reactive_compact 表示是否已经做过一次紧急压缩。上下文超限的压缩也只给一次机会,因为如果压缩后仍然超限,说明当前任务已经无法在现有上下文窗口中继续推进。
current_model 则是当前使用的模型。默认是 PRIMARY_MODEL,在连续 529 时可以切换为 fallback model。
这个设计很关键:错误恢复不是 “遇到错误就临时写几行 if”,而是需要有状态地管理恢复过程。否则 Agent 无法知道某个恢复动作是否已经尝试过,也无法避免无限重试。
2. retry_delay:指数退避加随机抖动
针对 429 / 529 这类临时故障,s11 使用 retry_delay 计算重试等待时间:
def retry_delay(attempt, retry_after=None):
"""Exponential backoff with jitter. Retry-After takes priority."""
if retry_after:
return retry_after
base = min(BASE_DELAY_MS * (2 ** attempt), 32000) / 1000
jitter = random.uniform(0, base * 0.25)
return base + jitter
这里的基础延迟是 500ms × 2^attempt,并且最多不超过 32000ms,也就是 32 秒。随后再加上 0 到 25% 的随机抖动。
抖动的意义在于避免大量请求在同一时间重试。如果很多 Agent 同时遇到服务过载,然后都严格按照 0.5s、1s、2s 的固定间隔重试,就会再次形成流量尖峰。加入 jitter 后,每个请求的重试时间会略微错开,这样对服务端更友好。
如果服务端返回了 Retry-After,则优先听服务端的建议,而不是自己计算等待时间。
3. with_retry:把 429 / 529 收拢到统一重试逻辑
s11 中专门实现了一个 with_retry 函数,用来包裹真正的 LLM 调用:
def with_retry(fn, state: RecoveryState):
"""Exponential backoff for transient errors (429/529).
Non-transient errors are re-raised for the outer handler."""
for attempt in range(MAX_RETRIES):
try:
result = fn()
state.consecutive_529 = 0
return result
except Exception as e:
name = type(e).__name__
msg = str(e).lower()
这里传入的 fn 实际上就是一次 LLM API 调用。with_retry 的职责不是处理所有错误,而是只处理 “瞬态错误”,也就是 429 和 529。
当错误信息中包含 429 或 RateLimit 时,系统会打印限流日志,等待一段时间,然后继续重试:
if "ratelimit" in name.lower() or "429" in msg:
delay = retry_delay(attempt)
print(f" \033[33m[429 rate limit] retry {attempt+1}/{MAX_RETRIES},"
f" wait {delay:.1f}s\033[0m")
time.sleep(delay)
continue
当错误信息中包含 529 或 overloaded 时,系统会记录连续 529 的次数。如果连续过载次数达到阈值,并且配置了 fallback model,就切换模型:
if "overloaded" in name.lower() or "529" in msg or "overloaded" in msg:
state.consecutive_529 += 1
if state.consecutive_529 >= MAX_CONSECUTIVE_529:
if FALLBACK_MODEL:
state.current_model = FALLBACK_MODEL
state.consecutive_529 = 0
print(f" \033[31m[529 x{MAX_CONSECUTIVE_529}]"
f" switching to {FALLBACK_MODEL}\033[0m")
这段代码体现了一个很典型的工程分层:with_retry 只处理可以通过等待恢复的错误;如果不是 429 / 529,就重新抛出,让外层的 agent_loop 去处理。
也就是说,错误恢复并不是一个大而全的 except Exception,而是分层分类:
with_retry→ 处理 429 / 529 这类临时错误agent_loop→ 处理 prompt_too_long 这类上下文错误stop_reason→ 处理 max_tokens 这类模型返回状态
4. is_prompt_too_long_error:识别上下文超限
对于上下文超限,s11 提供了一个判断函数:
def is_prompt_too_long_error(e: Exception) -> bool:
"""Check whether an API error indicates prompt/context too long."""
msg = str(e).lower()
return (("prompt" in msg and "long" in msg)
or "prompt_is_too_long" in msg
or "context_length_exceeded" in msg
or "max_context_window" in msg)
这里没有依赖某一个固定的异常类型,而是通过错误信息中的关键词来判断。这是因为不同模型供应商、不同 SDK、不同兼容接口返回的错误字段可能并不完全一致。有的叫 prompt_too_long,有的叫 context_length_exceeded,有的可能描述为超过最大上下文窗口。
这种写法虽然不如强类型异常优雅,但在多模型、多供应商接入的 Agent 工程中非常实用。
5. reactive_compact:上下文超限后的紧急压缩
当检测到 prompt too long 后,s11 会触发 reactive_compact:
def reactive_compact(messages: list) -> list:
"""Emergency compact — teaching version keeps last N messages."""
print(" \033[31m[reactive compact] trimming to last 5 messages\033[0m")
tail = messages[-5:]
return [{"role": "user",
"content": "[Reactive compact] Earlier conversation trimmed. "
"Continue from where you left off."}, *tail]
这里教学版做了一个简化:直接保留最后 5 条消息,并在前面插入一条提示,说明早期对话已经被裁剪,让模型继续当前任务。
这和 s08 中的普通压缩不同。普通压缩更像是预防性维护:当上下文变长时,提前做 budget、snip、micro、autoCompact 等处理。而 reactive compact 是事故发生后的紧急恢复:API 已经明确告诉你上下文太长了,这时必须立刻缩短 messages,否则下一次请求还会失败。
所以两者的区别可以理解为:
- 普通 compact → 主动压缩,避免超限
- reactive compact → 被动恢复,超限后紧急裁剪
在真实系统中,reactive compact 通常不会只是简单保留最后几条消息,而是会调用模型生成一个更高质量的 compact summary,把关键任务状态、已执行操作、未完成目标保留下来,然后再重试。
6. agent_loop:三种恢复路径合并到主循环
s11 的主循环从结构上看仍然很熟悉:
def agent_loop(messages: list, context: dict):
"""Main loop with error recovery wrapping LLM calls."""
system = get_system_prompt(context)
state = RecoveryState()
max_tokens = DEFAULT_MAX_TOKENS
while True:
try:
response = with_retry(
lambda mt=max_tokens, mdl=state.current_model:
client.messages.create(
model=mdl, system=system, messages=messages,
tools=TOOLS, max_tokens=mt),
state)
这里有几个关键点。
第一,system = get_system_prompt(context) 仍然来自 s10。也就是说,s11 没有改变 system prompt 组装逻辑,只是在调用模型时增加了恢复能力。
第二,state = RecoveryState() 只在本次 agent loop 中创建一次,用来跟踪这一次任务执行过程中的恢复状态。
第三,真正调用 LLM 的地方被 with_retry 包起来,因此 429 / 529 会在这里先被处理。如果重试成功,response 正常返回;如果不是瞬态错误,异常会继续抛给外层。
外层首先处理 prompt too long:
except Exception as e:
if is_prompt_too_long_error(e):
if not state.has_attempted_reactive_compact:
messages[:] = reactive_compact(messages)
state.has_attempted_reactive_compact = True
continue
print(" \033[31m[unrecoverable] still too long after compact\033[0m")
messages.append({"role": "assistant", "content": [
{"type": "text",
"text": "[Error] Context too large, cannot continue."}]})
return
如果这是第一次上下文超限,就进行 reactive compact,然后 continue 回到 while 循环开头,重新调用 LLM。注意这里用的是:
messages[:] = reactive_compact(messages)
这表示原地修改 messages 列表,而不是创建一个新的局部变量。这一点很重要,因为外层的 history 引用的仍然是同一个列表。如果只是写成 messages = reactive_compact(messages),就可能导致外部历史和内部消息列表脱节。
如果已经做过一次 reactive compact 后仍然超限,Agent 就不再继续重试,而是追加一条错误消息并退出。这体现了 s11 的另一个原则:恢复必须有边界。
7. max_tokens:先升级,再续写
LLM 成功返回后,s11 会先检查 response.stop_reason:
if response.stop_reason == "max_tokens":
if not state.has_escalated:
max_tokens = ESCALATED_MAX_TOKENS
state.has_escalated = True
print(f" \033[33m[max_tokens] escalating"
f" {DEFAULT_MAX_TOKENS} -> {ESCALATED_MAX_TOKENS}\033[0m")
continue
这里最值得注意的是:第一次触发 max_tokens 时,不会把截断输出追加到 messages 中。
原因很简单:如果模型输出被截断了,这段输出可能是不完整的。直接把不完整内容追加进上下文,可能会污染后续推理。所以第一次恢复策略是扩大输出预算,然后用同一个 messages 重试一次。
如果升级到 64K 后仍然被截断,说明输出确实非常长。这时才把截断输出保留下来,并追加一个续写提示:
messages.append({"role": "assistant", "content": response.content})
if state.recovery_count < MAX_RECOVERY_RETRIES:
messages.append({"role": "user", "content": CONTINUATION_PROMPT})
state.recovery_count += 1
print(f" \033[33m[max_tokens] continuation"
f" {state.recovery_count}/{MAX_RECOVERY_RETRIES}\033[0m")
continue
续写提示是:
CONTINUATION_PROMPT = (
"Output token limit hit. Resume directly — "
"no apology, no recap. Pick up mid-thought."
)
这条提示的目标很明确:不要道歉,不要复述,不要总结,直接从中断处继续。
最多续写 3 次。如果 3 次之后仍然触发 max_tokens,就停止恢复:
print(" \033[31m[max_tokens] recovery limit reached\033[0m")
return
这就是 s11 对输出截断的完整策略:
- 第一次 max_tokens → 不保存截断输出,8K 升级到 64K,重试
- 64K 后仍 max_tokens → 保存截断输出,追加续写提示
- 连续续写超过 3 次 → 停止恢复,退出
8. 工具执行逻辑保持不变
如果模型没有触发 max_tokens,就正常追加 assistant response:
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason != "tool_use":
return
如果 stop_reason == "tool_use",说明模型要调用工具,后续逻辑和前面几节基本一致:
results = []
for block in response.content:
if block.type != "tool_use":
continue
print(f"\033[36m> {block.name}\033[0m")
handler = TOOL_HANDLERS.get(block.name)
output = handler(**block.input) if handler else f"Unknown: {block.name}"
print(str(output)[:200])
results.append({"type": "tool_result",
"tool_use_id": block.id, "content": output})
messages.append({"role": "user", "content": results})
工具执行完成后,工具结果仍然作为 user 消息追加回 messages,然后更新上下文并重新组装 system prompt:
context = update_context(context, messages)
system = get_system_prompt(context)
这说明 s11 的改造是非常克制的。它没有把工具执行、上下文更新、system prompt 组装全部打散重写,而是在 LLM 调用边界处加入恢复能力。
这也是本节最值得学习的工程方法:好的错误恢复机制不应该让主循环变得混乱,而应该像一层外壳一样包住不稳定的调用边界。
OK,以上就是 s11 Error Recovery 工作原理的完整分析了。
由于本章节内容不太好调试展示,大家可以自己试试看能不能触发 Error Recovery:
1. 让 Agent 生成一段很长的代码,观察截断后是否自动续写(看 [max_tokens] escalating 日志)
2. 连续读取大量文件撑大上下文,观察 reactive compact
3. 如果遇到 429/529,观察指数退避的日志输出
6. 相对 s10 的变更
| 组件 | 之前 (s10) | 之后 (s11) |
|---|---|---|
| 错误处理 | 无(一碰就崩溃) | 三种恢复模式 + 指数退避 |
| 新常量 | — | ESCALATED_MAX_TOKENS=64000, MAX_RETRIES=10, BASE_DELAY_MS=500, FALLBACK_MODEL |
| 新函数 | — | with_retry, retry_delay, reactive_compact, is_prompt_too_long_error, RecoveryState |
| 工具 | bash, read_file, write_file (3) | bash, read_file, write_file (3) — 不变 |
| 循环 | 裸调用 LLM | try/except 包裹 + continue 重试 |
7. 小结
在 s10 中,Agent 已经可以根据运行时状态动态组装 system prompt;到了 s11,这条主循环本身仍然没有被推翻,只是在调用 LLM 的位置外面包了一层更可靠的恢复机制。正常情况下,模型调用成功,流程继续进入工具执行;一旦出现异常,系统会先判断错误属于哪一类,再选择最小代价的恢复动作,而不是盲目重试。
这里最核心的三条路径分别对应三种常见问题:如果是 max_tokens,说明模型输出被截断,优先通过提升输出预算来恢复;如果是 prompt_too_long,说明上下文已经超限,就触发更激进的 reactive compact;如果是 429 或 529 这类临时服务错误,则通过指数退避、抖动以及必要时切换备用模型来降低失败影响。
因此,s11 真正补上的不是一个 “报错处理工具”,而是 Agent Harness 的韧性层。它让 Agent 在面对截断、超限、限流、过载这些生产环境中非常常见的问题时,不会立刻崩溃,而是能够有边界、有状态、有策略地恢复。每一种恢复路径都有明确触发条件、最大次数和退出条件,这一点非常重要:可靠的 Agent 不是无限重试,而是知道什么时候继续、什么时候降级、什么时候干净地退出。
OK,以上就是本期想要分享的全部内容了。
结语
本篇文章我们围绕 s11 Error Recovery 这一节,从问题出发,结合流程图与代码实现,完整梳理了 Agent 在面对输出截断、上下文超限以及服务端故障时,是如何通过分类恢复机制维持系统持续运行的。
相比前面的章节,s11 最本质的变化并不是新增了某种能力,而是第一次正式回答了一个工程系统必须面对的问题:当事情出错时,系统应该怎么办。
在前面的 Agent Loop、Tool Use、Memory、System Prompt 等章节中,我们一直在为 Agent 增加能力。但能力越强,运行时间越长,遇到异常的概率也就越高。如果每一次
max_tokens、prompt_too_long、429 或 529 都直接导致主循环退出,那么系统拥有再多能力,也很难真正应用到真实场景之中。s11 给出的解法非常克制:它没有修改 Agent Loop 的核心结构,也没有重写工具执行流程,而是在 LLM 调用边界之外增加了一层恢复外壳。对于不同类型的错误,系统选择不同的最小恢复动作——输出不够就扩容或续写,上下文过长就压缩,服务暂时不可用就退避重试或切换模型。整个过程始终围绕同一个原则展开:先理解失败原因,再执行恢复动作。
从工程视角来看,这一节真正补上的并不是几个
try/except,而是 Agent Runtime 中长期缺失的一块能力:可靠性。系统开始具备区分错误类型、跟踪恢复状态、限制恢复次数以及安全退出的能力。恢复过程不再是无边界的重试,而是一个有状态、有策略、有终点的受控流程。进一步来看,s11 的意义甚至超出了错误恢复本身。因为从这一节开始,Agent 不再只是一个能够执行任务的系统,而开始逐渐演化为一个能够在不确定环境中持续运行的系统。面对失败,它不再立即崩溃,而是尝试恢复;面对无法恢复的情况,也能够明确终止并保留一致状态。
如果说 s10 建立的是 Agent 的 “运行时配置能力”,那么 s11 建立的,就是 Agent 的 “运行时韧性”。而这一步,也正是 Agent 从 Demo 迈向生产级系统过程中不可或缺的一环。
下篇文章我们将来学习新版教程 s14 Cron Scheduler 章节的内容,敬请期待🤗
参考
更多推荐

所有评论(0)