第1章 Agent 生命周期¶
学习目标¶
- 理解 Agent 的完整设计流程与生命周期阶段
- 掌握 Agent 循环(Perceive-Decide-Act)的运行机制
- 学会使用 OpenAI Agents SDK 实现 Agent 迭代执行
- 理解终止条件设计与错误处理、重试策略
- 能够为真实业务设计可观测、可恢复的 Agent
问题导入¶
某团队上线了一个"工单处理助手",让 LLM 直接生成回复就返回。结果上线一周暴露三大问题:①遇到需要多次查询数据库的工单,Agent 只查一次就回答,答非所问;②工具偶发超时,Agent 直接报错退出,用户体验差;③没有明确的"完成"判断,有时模型明明已给出答案却继续空转,Token 成本飙升。
这些问题的根因都在于:团队只写了"一次调用",而没有设计 Agent 生命周期。Agent 不是"调一次 LLM",而是一个会"感知—决策—行动—观察"持续迭代的循环系统。生命周期管理决定了 Agent 何时启动、如何推进、何时终止、出错怎么办。本章将系统讲解 Agent 生命周期的每个阶段,并用 OpenAI Agents SDK 实现一个可控、可观测的 Agent 循环。
核心概念¶
1. Agent 设计流程¶
构建一个 Agent 通常包含五步:
- 目标定义:明确 Agent 要解决什么问题(如"处理用户工单")
- 能力设计:确定 Agent 需要哪些工具、哪些知识
- 指令编写:用 system prompt 约束 Agent 行为边界
- 循环设计:定义感知—决策—行动的迭代结构
- 终止与恢复:设计完成条件、最大轮数、错误重试与断点续跑
2. 初始化阶段¶
初始化阶段负责装配 Agent 运行所需的全部要素:
- 指令(Instructions):定义角色、规则、输出格式
- 工具集(Tools):Agent 可调用的函数列表
- 上下文(Context):注入用户身份、会话状态等运行时数据
- 模型配置:选择 model、temperature、max_tokens
OpenAI Agents SDK 通过 Agent 类完成初始化,所有配置以声明式参数传入。
3. Agent 循环(Perceive-Decide-Act)¶
Agent 的核心是一个不断迭代的循环,每个迭代包含三个阶段:
- Perceive(感知):接收用户输入或上一轮工具结果,更新上下文
- Decide(决策):LLM 基于当前上下文决定下一步——调用工具还是给出最终答案
- Act(行动):执行工具调用,将结果作为新的"感知"喂回模型
这个循环会持续进行,直到模型判定任务完成或触发终止条件。
4. 终止条件¶
合理的终止条件防止 Agent 死循环:
- 自然终止:模型不再发起工具调用,直接输出 final_output
- 最大轮数(max_turns):硬性上限,SDK 的
Runner.run支持 - 超时控制:整体执行时间上限
- 完成信号:通过特定工具或关键字标记完成
5. 错误处理与重试¶
工具调用可能失败(网络超时、参数错误、权限不足),需设计:
- 捕获异常:把错误信息作为 observation 回传给模型,让其自我修正
- 重试策略:对瞬时错误指数退避重试,对参数错误让模型重新决策
- 熔断降级:连续失败 N 次后停止,返回兜底响应
- 可观测性:记录每轮的输入、输出、耗时,便于事后排查
原理图¶
stateDiagram-v2
[*] --> 初始化
初始化 --> 感知 : 装配指令/工具/上下文
state 循环 {
感知 --> 决策 : 更新上下文
决策 --> 行动 : 调用工具
行动 --> 感知 : 工具结果回传
决策 --> 完成 : 无工具调用
}
感知 --> 错误处理 : 工具异常
错误处理 --> 决策 : 重试/回传错误
错误处理 --> 终止 : 熔断/超限
完成 --> [*] : 输出 final_output
终止 --> [*] : 兜底响应
note right of 循环
Perceive-Decide-Act
持续迭代直到完成
end note
图:Agent 生命周期状态机——从初始化进入感知—决策—行动循环,遇错回传或重试,满足终止条件后退出
示例代码¶
1. 最小 Agent 循环(OpenAI Agents SDK)¶
"""
第1章示例:用 OpenAI Agents SDK 实现最小 Agent 循环
依赖:pip install openai-agents
"""
import asyncio
from agents import Agent, Runner, function_tool
@function_tool
def query_order(order_id: str) -> str:
"""查询订单状态。参数 order_id:订单号"""
# 模拟数据库查询
db = {
"A1001": "已发货,预计明日送达",
"A1002": "处理中,预计 2 天后发货",
}
return db.get(order_id, f"订单 {order_id} 不存在")
@function_tool
def refund_order(order_id: str, reason: str) -> str:
"""发起退款。参数 order_id:订单号,reason:退款原因"""
return f"已为订单 {order_id} 创建退款工单,原因:{reason},预计 3 个工作日到账"
# 初始化 Agent:声明指令、工具、模型
agent = Agent(
name="客服助手",
instructions=(
"你是一个电商客服助手。处理用户订单查询与退款请求。"
"如果用户只查询,调用 query_order;如果用户要求退款,先查询再调用 refund_order。"
"每次行动后基于结果决定下一步,信息充分时给出最终回答。"
),
tools=[query_order, refund_order],
model="gpt-4o-mini",
)
async def main():
# Runner 负责驱动整个 Perceive-Decide-Act 循环
result = await Runner.run(
agent,
"我的订单 A1001 还没到,如果明天还不到就退款,原因是物流太慢。",
max_turns=8, # 终止条件:最多 8 轮
)
print("最终回复:", result.final_output)
print("总轮数:", len(result.raw_responses))
if __name__ == "__main__":
asyncio.run(main())
运行结果示例:
最终回复: 您的订单 A1001 当前状态为"已发货,预计明日送达"。
若明日仍未送达,我已为您创建退款工单(原因:物流太慢),
预计 3 个工作日到账,请留意短信通知。
总轮数: 3
2. 带错误处理与重试的 Agent 循环¶
"""
带错误处理与重试的 Agent 循环:手动管理迭代,便于自定义错误策略
"""
import asyncio
from openai import AsyncOpenAI
from agents import Agent, Runner, function_tool, ToolError
client = AsyncOpenAI()
@function_tool
def unreliable_api(query: str) -> str:
"""模拟不稳定的 API:偶发失败"""
import random
if random.random() < 0.5:
raise RuntimeError("API 超时")
return f"查询 {query} 的结果:OK"
agent = Agent(
name="容错助手",
instructions="遇到工具错误时,向用户说明并最多重试 2 次,仍失败则给出兜底回答。",
tools=[unreliable_api],
model="gpt-4o-mini",
)
async def run_with_guardrail(agent, user_input, max_turns=6):
"""带熔断机制的运行器:连续失败 3 次即终止"""
try:
result = await Runner.run(
agent,
user_input,
max_turns=max_turns,
)
return result.final_output
except ToolError as e:
# SDK 会把工具异常转为 observation,此处兜底
return f"工具连续异常,已熔断:{e}"
except Exception as e:
return f"Agent 异常终止:{e}"
if __name__ == "__main__":
out = asyncio.run(run_with_guardrail(agent, "请调用 unreliable_api 查询 weather"))
print(out)
企业案例¶
案例 1:客服 Agent 生命周期管理¶
某电商平台客服 Agent 需处理咨询、查询、退款、投诉四类工单。团队基于生命周期设计:
- 初始化:按工单类型加载不同工具集(查询类用
query_order,退款类用refund_order+query_order) - 循环控制:
max_turns=10,单工单最多 10 轮交互 - 终止策略:模型输出 final_output 即完成;超过 10 轮升级人工
- 错误处理:订单系统超时重试 3 次(指数退避 1s/2s/4s),仍失败则提示用户稍后重试
- 可观测:每轮记录 tool_name、latency、token_usage,接入 Prometheus
上线后工单自动解决率从 42% 提升到 78%,平均处理时长下降 35%。关键经验:生命周期可观测比单纯提升准确率更重要——知道 Agent 在哪一步卡住,才能持续优化。
案例 2:数据分析 Agent 的断点续跑¶
某数据团队的 Agent 需执行"取数—清洗—分析—出图"长流程,单次可能跑 20+ 轮。团队将每轮的上下文快照存入 Redis,若进程崩溃可从最近 checkpoint 恢复,避免从头重跑。这是生命周期管理在"长任务"场景下的延伸:状态持久化 + 断点续跑。
常见问题¶
Q1:Agent 和单次 LLM 调用的本质区别是什么?
A:单次调用是"问—答"一对一映射;Agent 是一个循环系统,能根据中间结果动态决定下一步,可多次调用工具、多轮推进,直到满足终止条件。Agent 的核心价值在于"自主迭代"。
Q2:max_turns 设多少合适?
A:取决于任务复杂度。简单查询 3-5 轮,多步推理 8-12 轮,长流程任务 20+ 轮并配合 checkpoint。原则是够用即可,过大会导致成本失控,过小会截断必要推理。
Q3:工具调用失败时,应该重试还是把错误告诉模型?
A:两者结合。瞬时错误(网络抖动、超时)用指数退避重试;参数错误(模型传错参数)把错误信息作为 observation 回传,让模型自我修正;业务错误(订单不存在)直接回传让模型据此回答。所有错误都应可观测。
Q4:如何判断 Agent "卡住"了?
A:三个信号:①连续 N 轮调用同一工具且参数几乎相同;②模型输出"我再试试"等无进展语句;③Token 消耗突增但 final_output 未产出。检测到后应强制终止并降级。
Q5:Agent 循环必须用 LLM 做决策吗?
A:不一定。简单路由可用规则决策(如关键字匹配),复杂推理才需 LLM。混合架构(规则 + LLM)能显著降低成本,企业中常用"LLM 决策 + 规则兜底"。
面试题¶
- 简答题:描述 Agent 的 Perceive-Decide-Act 循环,并说明每个阶段的输入输出。
参考要点:Perceive 接收用户输入或工具结果更新上下文;Decide 由 LLM 决定调用工具或给出答案;Act 执行工具并把结果回传作为下一轮感知。
- 设计题:一个 Agent 调用工具 5 次都失败,应该如何处理?请给出完整策略。
参考要点:区分错误类型(瞬时/参数/业务);瞬时错误指数退避重试;参数错误回传让模型修正;连续失败触发熔断,返回兜底响应并告警。
-
实现题:用 OpenAI Agents SDK 实现一个带
max_turns和超时控制的 Agent 运行器。 -
原理题:为什么说"Agent 生命周期的可观测性比准确率更重要"?
参考要点:准确率是结果指标,可观测性是过程指标;Agent 多轮迭代,无法定位卡点就无法优化;生产环境需要知道每轮的输入输出耗时才能排障。
- 对比题:Agent 的"自然终止"和"强制终止"有何区别?分别何时使用?
练习题¶
-
基础实现:用 OpenAI Agents SDK 实现一个"天气查询 Agent",工具为
get_weather(city),设置max_turns=5,观察不同问题下的实际轮数。 -
错误注入:在示例 2 基础上,构造一个 80% 概率失败的工具,验证熔断机制是否生效,并统计平均重试次数。
-
可观测性:为 Agent 循环增加日志,记录每轮的 tool_name、耗时、token 数,输出为 JSONL 文件便于分析。
小结¶
Agent 生命周期是构建可靠 Agent 的地基。本章核心:Agent 不是一次调用,而是"初始化—感知—决策—行动"的迭代循环;终止条件(max_turns、完成信号)防止失控;错误处理(重试、回传、熔断)保障鲁棒;可观测性支撑持续优化。掌握生命周期后,下一步要解决"Agent 如何规划多步任务"——这正是第 2 章的主题。