AI Agent循环工程:构建自主驱动的智能体闭环系统 在实际构建智能体AI Agent应用时最容易被低估的部分不是模型能力而是如何让系统在多次调用之间形成闭环。很多初版智能体产品本质上是“包了一层接口的大模型调用”用户提问模型回答调用结束。但真正的智能体需要感知环境、执行动作、观察结果、根据反馈调整下一步并在多轮迭代中逼近目标。智能体时代把这种设计方式推到了前台它有一个更工程化的名字循环工程。循环工程解决的核心问题不是“模型能不能回答”而是“系统能不能在一个目标驱动下持续工作”。设计一个自主驱动的 AI 闭环系统不能只关注提示词写得好不好还要关注循环怎么启动、怎么终止、怎么防止卡死、怎么评估每一轮是否有效。这篇文章会从概念讲到最小可运行实现再讲到生产环境必须考虑的排查路径和治理机制。读完可以照着代码跑通一个“生成-评审-修改-再评审”的闭环智能体并知道如何把它扩展成更复杂的多智能体系统。1. 先理解智能体闭环系统为什么不是“调用一次大模型”1.1 单次调用和自主闭环的区别普通 AI 应用最常见的形态是用户输入一个问题程序把问题拼进提示词调用大模型接口拿到结果后直接展示。这个流程对聊天助手、翻译工具、摘要工具是够用的因为任务在模型输出那一刻就结束了。智能体应用完全不同。智能体有一个需要持续完成的目标这个目标往往不能靠一次推理完成。比如自动写一篇文章并修改到合格自动检查一段代码并修复问题自动完成数据分析并生成图表。这类任务需要模型输出一个中间结果再由另一个环节验证结果验证不通过就带着反馈重新生成直到通过或达到上限。这里的“闭环”指的是信息从系统流向模型模型输出又回到系统系统根据输出质量和任务目标决定是否继续迭代。没有闭环的智能体只是一个被装饰过的接口调用有闭环的智能体才具备自主性。下表是两种模式的核心差异维度单次调用自主闭环触发方式用户发起一次请求系统按目标自主迭代上下文只使用当前输入使用历史、记忆、状态失败处理返回错误或空结果根据反馈修正再执行结束条件模型输出即结束评估达标或达到上限工程重点调通接口、处理好参数循环可控、可观测、可干预1.2 循环工程的三层含义循环工程不是一个具体的框架而是一套设计方法。它包含三个从内到外的层次。第一层是运行循环。系统按照“感知-决策-行动-反馈”的顺序运转。感知阶段接收外部输入和当前状态决策阶段根据已有信息选择下一步动作行动阶段调用模型或工具产生结果反馈阶段把结果交给评估器判断是否达标。第二层是优化循环。模型产生的结果并不是最终答案而是待评估对象。评估器给出分数、通过状态和修改建议系统把建议拼回上下文让模型在下一次生成时参考。这个循环的价值在于让模型能够“反思”自己的输出而不是一次性碰运气。第三层是治理循环。工程环境里不能只关注功能还要关注循环会不会失控。治理循环要求在循环之外建立日志、监控、人工审批、预算控制和熔断机制确保系统在异常情况下可以被停止和恢复。1.3 闭环系统需要哪些核心模块一个可工作的闭环系统至少需要六个模块感知模块、记忆模块、决策模块、执行模块、反馈模块和评估模块。感知模块负责接收任务描述和外部数据。记忆模块保存历史上下文和执行状态避免系统每次从零开始。决策模块根据当前目标和历史记忆选择下一步动作可以是一个 LLM 调用也可以是规则路由。执行模块调用工具、函数或内容生成器真正产生结果。反馈模块收集执行后的现象和指标比如访问结果、命令行输出、评分结果。评估模块判断当前结果是否满足任务要求决定继续还是终止。这六个模块并不是所有场景都要完整实现。最小闭环可以先省略工具调用只保留“生成-评估-迭代”。后面扩展到生产系统时再逐步加入外部工具、知识库和多智能体协作。2. 设计自主驱动 AI 闭环系统的核心架构2.1 六模块的职责和输入输出设计闭环系统之前先要把每个模块的边界定义清楚。模块边界越清楚后续排查问题越容易。模块核心职责主要输入主要输出感知模块接收任务、环境信息用户指令、外部数据标准化的任务对象记忆模块保存历史状态和上下文多轮运行记录下一轮可用的上下文决策模块规划下一步动作目标、上下文、可用能力动作指令执行模块完成实际动作动作指令执行结果反馈模块收集执行后的观察结果执行结果、外部响应反馈信息评估模块判断是否达标任务目标、生成结果分数、通过状态、建议感知模块最常见的实现方式是先定义任务对象。任务对象包含任务 ID、指令内容、最大轮数、历史消息等字段。后续所有模块都围绕这个对象工作。记忆模块容易被忽略。很多人会在循环里把每一轮的完整对话都拼进提示词结果上下文越来越长费用越来越高模型反而丢失关键信息。更合理的做法是只把“上一轮评审意见”和“当前待修改文本”作为上下文来源必要时使用摘要压缩历史。决策模块和执行模块在最小闭环里可以合并。最简单的情况是系统不做复杂规划直接调用 LLM 生成内容。更复杂的情况是决策模块先判断“这个任务需要调用搜索接口还是写文件”再交给不同执行器。判断逻辑可以用 LLM 结构化输出实现也可以用规则实现。反馈模块和评估模块是闭环能成立的关键。反馈模块负责把执行结果转成评估器可读的输入评估模块负责产出可计算的结果。如果评估模块只用“好”或“不好”这种自然语言系统很难稳定决定是否终止。建议评估模块输出结构化内容例如 JSON 格式的分数、是否通过、修改建议。2.2 循环机制的运转流程一个最小闭环系统的运转流程可以用文字描述成下面的顺序系统收到任务创建 Task 对象初始化空上下文。生成器按任务和历史上下文生成第一版结果。评估器检查结果是否满足任务要求。如果通过系统输出结果并结束。如果未通过评估器产生修改建议系统把建议写回上下文。生成器基于上一版结果和修改建议生成新版结果。重复第 3 到第 6 步直到通过或达到最大轮数。这个流程的关键点在于结束条件。结束条件不能依赖模型“自己判断是否完成”而应该由独立的评估环节判断。如果生成器和评估器是同一个模型它们可以共用同一个模型接口但提示词必须区分角色避免生成器自说自话。实际工程中循环不会无限运行。必须设置最大轮数防止模型反复生成但始终不达标。最大轮数要结合成本和效果来设定。学习环境可以设 3 轮生产环境可以先设 5 轮再根据线上数据调整。2.3 为什么记忆和评估是闭环的关键记忆和评估这两个模块决定了闭环系统的质量上限。没有记忆系统每一轮都是独立生成修改建议无法被利用循环就变成了重复生成。没有评估系统无法判断任务是否完成循环要么提前结束要么永远不结束。评估模块尤其重要它相当于给系统一个外部标准。评估标准越客观循环越稳定。如果任务可以被规则量化例如代码能编译、字数区间正确、包含必需关键词建议先写规则判断。如果任务依赖语义质量例如文章是否通顺、方案是否合理再交给 LLM 评估。LLM 评估并不是万无一失。同一个模型既当生成器又当评审器时可能出现“自我认可”的倾向。缓解方法包括使用不同模型的评估接口、降低评估温度、要求输出结构化 JSON、增加人类抽查比例。在最小闭环示例里为了跑通流程可以先用同一个模型但生产环境要按需调整。3. 从零搭建一个最小闭环系统3.1 项目依赖和目录结构示例使用 Python 3.10 和两个依赖requests 用于调用大模型 HTTP 接口python-dotenv 用于加载本地环境变量。这里不绑定具体大模型 SDK因为 OpenAI 兼容接口在很多服务上都能复用换成其他服务时只需要调整 base_url。pip install requests python-dotenv项目目录按模块拆分方便后面扩展。agent-loop/ ├── .env ├── models.py ├── llm.py ├── agent.py └── main.py各文件职责如下文件职责models.py定义任务和数据模型llm.py封装大模型 HTTP 调用agent.py实现生成器、评估器和循环控制器main.py加载配置并启动运行3.2 定义任务和上下文数据模型数据模型要能表达任务 ID、任务指令、最大轮数和历史消息。使用 dataclass 可以让代码更简洁。# models.py from dataclasses import dataclass, field from typing import Dict, List dataclass class Task: id: str instruction: str max_rounds: int 3 history: List[Dict] field(default_factorylist) def to_messages(self, system_prompt: str) - List[Dict]: messages [{role: system, content: system_prompt}] messages.extend(self.history) return messageshistory 字段用来保存多轮交互记录。在最小闭环里不要在每轮把全部历史都塞进去通常只保存上一版文本和上一轮评审意见。否则上下文会迅速膨胀模型也抓不住重点。3.3 封装大模型接口llm.py 只做一件事通过 OpenAI 兼容的 /chat/completions 接口发送对话消息并返回文本内容。这样在后续切换模型服务时只需要改动 base_url 和模型名。# llm.py import requests from typing import Dict, List class LLMClient: def __init__(self, api_key: str, base_url: str, model: str, timeout: int 60): self.api_key api_key self.base_url base_url.rstrip(/) self.model model self.timeout timeout def chat(self, messages: List[Dict], temperature: float 0.7, max_tokens: int 1024) - str: url f{self.base_url}/chat/completions headers { Authorization: fBearer {self.api_key}, Content-Type: application/json } payload { model: self.model, messages: messages, temperature: temperature, max_tokens: max_tokens } resp requests.post(url, headersheaders, jsonpayload, timeoutself.timeout) resp.raise_for_status() data resp.json() return data[choices][0][message][content]这里没有使用 requests 的重试机制。生产环境需要增加超时重试、指数退避和错误码分类否则接口抖动会直接中断整个闭环。第 5 章会展开说明。3.4 实现生成器和评估器agent.py 是核心文件。生成器负责按任务和评审意见生成文本评估器负责判断结果是否合格。生成器提示词需要说明两点如果存在上一轮评审意见必须按意见修改输出正文内容不要输出额外解释。这样可以减少模型输出“好的我已经修改”这类无效内容。评估器提示词要求输出 JSON而且字段固定为 score、pass、reason、suggestions。结构化输出是评估模块能参与自动决策的前提。# agent.py import json import re from typing import Dict from llm import LLMClient from models import Task GENERATOR_SYSTEM ( 你是一个内容生成器。根据任务说明生成文本。 如果上轮存在评审意见必须严格按意见修改。 只输出正文内容不要输出解释。 ) EVALUATOR_SYSTEM ( 你是一个评审器。检查文本是否满足任务要求。 只输出JSON格式为 {\score\: 0-100, \pass\: true/false, \reason\: \简要原因\, \suggestions\: [\修改建议\]} )实现上要保持生成和评估的调用逻辑独立这样后续可以把评估器换成规则引擎或其他模型。def call_llm(client: LLMClient, messages, temperature0.7): try: content client.chat(messages, temperaturetemperature) return content.strip() except Exception as e: print(f[LLM调用异常] {e}) raise def generate(client: LLMClient, task: Task, context: str) - str: user_content f任务{task.instruction}\n\n评审意见和建议\n{context} messages task.to_messages(GENERATOR_SYSTEM) messages.append({role: user, content: user_content}) return call_llm(client, messages) def evaluate(client: LLMClient, task: Task, text: str) - Dict: messages [ {role: system, content: EVALUATOR_SYSTEM}, { role: user, content: f任务{task.instruction}\n\n待评审文本\n{text}, }, ] content call_llm(client, messages, temperature0.0) return parse_evaluation(content) def parse_evaluation(content: str) - Dict: try: return json.loads(content) except json.JSONDecodeError: match re.search(r\{.*\}, content, re.S) if match: return json.loads(match.group()) return { score: 0, pass: False, reason: 评估器输出无法解析, suggestions: [], }评估温度要设置为 0让评审结果尽可能稳定。如果评估器输出夹杂解释文字导致 JSON 解析失败正则提取最外层的 JSON 片段可以提高容错性。3.5 实现循环控制器循环控制器是整个系统的中枢。它负责控制最大轮数、调用生成器和评估器、判断终止条件、记录每轮结果。def run_loop(client: LLMClient, task: Task, min_score: int 80) - Dict: context 暂无评审意见。请开始第一次生成。 result { task_id: task.id, rounds: 0, final_text: , evaluations: [], } rounds 0 while rounds task.max_rounds: rounds 1 print(f第 {rounds} 轮生成开始) text generate(client, task, context) evaluation evaluate(client, task, text) print( f第 {rounds} 轮评分{evaluation[score]} f是否通过{evaluation[pass]} ) result[rounds] rounds result[final_text] text result[evaluations].append(evaluation) if evaluation[pass] or evaluation[score] min_score: print(闭环结束评分达标) break suggestions evaluation.get(suggestions, []) context .join(suggestions) if suggestions else evaluation.get(reason, 请继续优化) print(f评审建议{context}) else: print(达到最大轮次闭环结束) return result注意 exit 条件有两种pass 为 true或者 score 大于等于 min_score。实际项目中不要只依赖 pass因为模型生成的 JSON 字段可能不稳定。加上分数阈值相当于多一道保险。另一个关键是使用 while 循环的 else 分支只有循环正常耗尽轮次才会触发这样能区分“达标退出”和“超限退出”。3.6 配置和主入口环境变量放在 .env 文件里避免把密钥写进代码。LLM_API_KEYsk-demo LLM_BASE_URLhttps://api.openai.com/v1 LLM_MODELgpt-4o-mini LLM_TIMEOUT60如果使用的是本地大模型服务或兼容 OpenAI 的网关base_url 换成对应的服务地址。模型名也要按实际部署的模型调整不要照搬示例。# main.py import os from dotenv import load_dotenv from agent import run_loop from llm import LLMClient from models import Task load_dotenv() def main(): client LLMClient( api_keyos.getenv(LLM_API_KEY, ), base_urlos.getenv(LLM_BASE_URL, https://api.openai.com/v1), modelos.getenv(LLM_MODEL, gpt-4o-mini), timeoutint(os.getenv(LLM_TIMEOUT, 60)) ) task Task( iddemo-001, instruction写一段介绍智能体闭环系统的文字120字左右。, max_rounds3 ) result run_loop(client, task, min_score80) print(最终结果) print(result[final_text]) if __name__ __main__: main()运行命令python main.py这个最小系统已经能完成一次“生成-评估-迭代”的闭环过程适合用来理解循环的基本逻辑。注意示例里的任务和模型都需要按真实环境调整不要直接在业务中使用。4. 运行验证让系统自主完成一个小任务4.1 准备环境变量和接口连通性运行前先确认三件事API Key 是否有访问权限base_url 是否能连通模型名是否真实存在。这三项最容易出错。常见的检查方式是先通过 curl 或 Python 脚本直接调用一次接口确认能拿到正常响应再去跑闭环。不要在闭环运行后才开始排错那样会把接口问题误判成循环逻辑问题。curl -X POST $LLM_BASE_URL/chat/completions \ -H Authorization: Bearer $LLM_API_KEY \ -H Content-Type: application/json \ -d {model:gpt-4o-mini,messages:[{role:user,content:test}]}如果接口返回 200说明基础连通性正常。4.2 运行过程和预期输出配置好 .env 后直接运行 main.py。以“写一段介绍智能体闭环系统的文字”为例预期日志类似下面的形式第 1 轮生成开始 第 1 轮评分65是否通过False 评审建议内容缺少具体例子字数不足开头不够直接 第 2 轮生成开始 第 2 轮评分85是否通过True 闭环结束评分达标 最终结果 智能体闭环系统是目标驱动的多轮迭代系统。它在执行中持续感知结果、评估质量、调整动作直到达成目标。与单次模型调用不同闭环系统依靠反馈循环提升稳定性是工程化智能体的核心形态。如果第一轮就通过说明任务简单或评估标准宽松。可以在实际运行中把任务调难一些例如要求“必须包含代码示例”“必须给出对比表”这样更容易看到循环迭代的过程。4.3 验证闭环是否真正有效程序能跑通不代表闭环设计合理。至少要检查三个点。第一每一轮是否基于上一轮反馈进行修改。把第一轮文本和最后一轮文本对比如果内容完全相同说明生成器没有消费评审建议循环只是在空转。第二终止条件是否符合预期。如果任务明显不合格系统却因为 score 超过阈值提前退出说明评估器评分不严格。此时应该降低评估器的“自我认可”倾向或引入更明确的规则校验。第三最大轮数是否真正起到保护作用。把 max_rounds 改成 1确认系统只调用一次生成和一次评估。再改成 100确认系统不会因为任务长期不达标而无限运行。5. 关键参数和配置说明5.1 循环控制参数表闭环系统的行为主要由参数决定。参数调不好模型再好也跑不稳。参数含义示例值调大的影响调小的影响max_rounds最大迭代轮数3更可能达标但成本增加更快结束可能没达标min_score达标分数阈值80要求更严格轮数变多更容易退出质量下降temperature生成随机性0.7输出更多样可能不稳更稳定但可能缺乏变化eval_temperature评估随机性0.0结果随机不建议稳定可复现timeout单次接口超时60容忍慢接口但卡顿更久快速失败但可能误伤max_tokens单次输出上限1024支持更长内容成本增加可能截断答案在最小示例中生成温度和评估温度要分开控制。生成端可以保留 0.7 让内容有变化评估端建议固定为 0 或极低值保证评分可复现。5.2 提示词设计对闭环效果的影响提示词不是“越复杂越好”而是要明确角色、输出格式和参考信息。生成器提示词需要告诉模型三件事它是什么角色当前任务是什么上轮修改意见是什么。如果缺少角色设定模型可能输出与任务无关的说明。如果缺少修改意见模型无法理解为什么要改。评估器提示词需要明确评分标准。建议把任务要求和评审维度都放进提示词而不是只写“请评估以下文本”。例如要求“技术文章必须包含代码示例、参数表格、排错方法”评估器就会在 JSON 的 reason 中给出更具针对性的建议。如果模型不支持严格的 JSON 输出最好在提示词末尾加上“只输出 JSON不要包含解释文字”的约束并在代码里做正则解析兜底。更可靠的方式是使用支持 JSON Mode 的接口参数但要确认所调用的模型服务支持这个特性。5.3 LLM 接口调用的容错处理闭环系统比单次调用更容易触发接口错误因为它会在短时间内连续调用多次。常见错误包括限流、超时、上下文过长和临时性 5xx。requests 库默认不会重试。生产环境建议增加重试逻辑对不同的错误码做不同处理。状态码含义处理方式401鉴权失败直接报错重试没有意义429限流等待后重试或降低并发500服务端异常间隔重试最多 3 次503服务不可用等待后重试同时告警重试不能无限进行。每次重试之间要增加间隔通常采用指数退避例如 1 秒、2 秒、4 秒。同时要给整体循环设定预算上限例如“单任务最多花费 5000 token”或“单任务最多调用 20 次接口”避免模型反复生成导致费用失控。6. 常见问题排查循环卡死、重复输出、反馈失效6.1 故障现象和排查方向表闭环系统的问题通常集中在循环控制、输出解析和接口调用三个层面。问题现象常见原因检查方式处理建议循环永远不结束未设置 max_rounds 或设置过大检查循环条件和配置设置合理最大轮数并增加预算限制每一轮输出完全一样生成器没有接收或解析评审建议打印每轮 context 和输入消息检查 messages 是否携带上一轮建议评审结果时好时坏评估温度过高查看评估调用参数评估温度固定为 0JSON 解析失败评估器输出额外解释文字打印原始 output加强提示词约束用正则提取 JSON 兜底接口频繁超时单次请求体过大或服务不稳定查看调用耗时截断历史上下文增加超时重试任务明显不合格却判通过评估器与生成器使用同一模型抽查评估结果引入规则校验或使用独立评估模型6.2 通过日志和追踪定位问题排查闭环问题最有效的方式是给每一轮加上可追踪的日志。每轮日志至少包含以下字段轮次生成器输入消息摘要生成器输出前 100 个字符评审 JSON当前累计成本和 Token 数循环退出原因示例日志模板round2 statusgenerated input_len320 output_prefix闭环系统是... round2 statusevaluated score85 passtrue reason内容完整字数达标 round2 statusexit reasonscore_ok cost_tokens1800在多模块闭环里建议为每次任务生成 trace_id。循环开始前生成一个 UUID所有日志、评估记录、埋点数据都带上这个 ID后面把日志接入日志平台时能直接按任务聚合。6.3 防止失控循环的安全机制防止失控不能只靠 max_rounds。生产环境至少要有四道保护。第一道是轮次限制main 循环里必须判断最大轮数。第二道是金额或 Token 预算在每次调用前累加消耗超过预算就终止。第三道是人工审批当任务连续多次不达标或评估分数低于某条线时转人工处理。第四道是熔断机制当接口错误率超过阈值时暂停循环并告警避免持续调用加重服务负担。安全机制应该配置化而不是写死在代码里。配置文件需要区分开发、测试和生产环境分别指定不同的预算和超时阈值。7. 生产环境落地的最佳实践7.1 学习环境与生产环境的差异最小闭环系统适合理解原理但不适合直接上线。生产环境要在很多地方做额外加固。维度学习环境生产环境配置写在 .env使用配置中心或环境变量管理日志print 输出结构化日志接入统一平台监控无指标采集、告警、看板数据持久化不保存记忆、任务、评估记录入库权限控制无接口鉴权、操作审计容错单次 try/except重试、降级、熔断、回滚安全审核无内容合规、敏感信息过滤最小示例里的评估器输出只存在内存里。生产环境要把每一轮的生成文本、评审结果、修改建议、耗时和 Token 数保存到数据库方便复盘和调优。7.2 发布前检查清单上线一个闭环智能体前建议按这份清单逐项确认。[ ] 所有外部接口地址和密钥来自配置中心不写死在代码仓库。[ ] 每个任务都设置了 max_rounds 和预算上限。[ ] 生成器和评估器在不同情况下都能稳定输出预期格式。[ ] 所有 LLM 调用都支持超时重试且不会无限重试。[ ] 日志中能通过 trace_id 还原一次任务的完整执行过程。[ ] 存在人工审批入口至少可以在任务异常时终止。[ ] 评估结果经过人工抽查准确率符合业务要求。[ ] 定义了退出原因编码能区分达标退出、超轮退出和异常退出。[ ] 对敏感信息做了过滤不会把密钥或用户隐私拼进提示词。[ ] 有回滚方案模型或接口异常时可以降级到旧版本逻辑。7.3 从最小闭环到完整智能体平台的扩展方向最小闭环运行稳定后可以向三个方向扩展。第一个方向是多智能体协作。把生成器和评估器拆成独立 Agent甚至让多个 Agent 分别负责写作、检查、数据补充和最终汇总。多智能体之间通过消息队列通信每个 Agent 都有自己的循环和终止条件。第二个方向是工具调用。执行模块从“只调用模型”扩展成“调用搜索、数据库、文件系统、代码执行器”。这时候感知模块和反馈模块要处理更多外部状态例如工具返回的错误码、执行耗时、数据 schema。第三个方向是记忆持久化和知识管理。把历史任务、常见评审意见、长期偏好保存到向量数据库让系统在跨任务场景中复用经验。记忆从“单轮上下文”升级为“长期记忆”后闭环的迭代起点会明显提高。无论往哪个方向扩展核心都要守住循环工程的三个原则运行闭环要能自主迭代评估闭环要能控制质量治理闭环要能保障安全和可观测。先把最小闭环跑通再逐步增加复杂度比一开始就搭建庞大框架更容易形成可维护的智能体系统。