AI Agent Harness 七个子系统:从裸调模型到稳定多步任务

发布时间:2026/11/2 3:50:00

AI Agent Harness 七个子系统:从裸调模型到稳定多步任务 1. 拆开“Harness”这个词先搞明白它到底管什么很多人第一次听到 AI Agent 的 Harness脑子里浮现的可能是某种硬件线束或者测试夹具。这个联想不算错因为 Harness 这个词本身就有“ harness 住、约束住、把散件整合成可运转整体”的意思。放到 AI Agent 的语境里Harness 就是那套把大模型、工具、记忆、循环控制、错误恢复、状态管理、输出解析全部串起来的工程骨架。没有它你手里只有一个会聊天的模型有了它模型才能真的去读文件、调接口、跑命令、改代码、查数据库最后把一件事从头到尾干完。我见过太多人搭 Agent 的路径是这样的先写一个while True循环把用户输入塞给模型模型返回什么就执行什么执行完再把结果塞回去。跑个 demo 没问题一旦任务超过五步或者中间某个工具报错整个流程就崩了。问题不在于模型不够聪明而在于缺少一个像样的 Harness 来管理“干活”这件事。Harness 要解决的核心问题就一句话让模型在不确定的环境里稳定地完成多步骤任务并且在出错时知道怎么退、怎么重试、怎么把状态传下去。这篇文章我会把 Harness 拆成七个子系统来讲每个子系统都说明它为什么存在、不管它会出什么事、以及实际搭建时怎么落地。如果你正在从零搭 Agent或者手里的 Agent 一上强度就翻车那这七个部分基本就是你排查问题的路线图。1.1 为什么“裸调模型”撑不起真实任务裸调模型的问题不是能力问题是工程问题。模型本身可以生成一段看起来能跑的代码但它不知道这段代码在目标环境里会不会因为缺少依赖而失败也不知道失败之后该换一种写法还是该停下来问人。真实任务里充满了这类“执行反馈”而裸调模型没有机制去消费这些反馈。举个很具体的例子。你让 Agent 去“把项目里所有 console.log 替换成 logger.info”。模型第一轮可能返回一个正则替换脚本。这个脚本跑起来可能因为文件编码问题失败也可能因为某些文件是二进制而报错。裸调模型的做法是把报错信息再塞回去让它重新生成。但如果没有 Harness 记录“哪些文件已经处理成功、哪些失败、失败原因是什么”模型第二轮很可能从头再来一遍把已经改好的文件又改一次或者直接卡在同一个错误上反复循环。Harness 的第一个价值就在这里它把“执行结果”变成结构化状态让模型每一轮都能基于最新状态做决策而不是靠对话历史里那堆自然语言去猜。状态管理、错误分类、重试策略、循环终止条件这些都不是模型该操心的事而是 Harness 的职责。1.2 七个子系统不是拍脑袋分的市面上讲 Agent 架构的文章喜欢画一张大图把 Planning、Memory、Tools、Execution 全堆在一起。这种画法看着全面但落地时你会发现每个部分都耦合在一起改一个地方崩三个地方。我后来习惯按“职责边界”来拆也就是每个子系统只干一件事子系统之间通过明确的数据结构通信。这样拆下来刚好是七个Agent Loop、LLM Integration、Tool Runtime、Memory State、Output Parser、Error Recovery、Observability。这七个不是理论分类是我在实际项目里反复调整后稳定下来的划分。比如 Output Parser 单独拿出来是因为模型输出格式不稳定这件事必须有一个专门的层去兜底不能让它污染主循环。Error Recovery 单独拿出来是因为错误处理逻辑一旦散落在各个工具里排查问题会非常痛苦。Observability 单独拿出来是因为 Agent 跑飞的时候你如果没有完整的调用链日志根本不知道它是在第几步开始跑偏的。2. Agent Loop整个 Harness 的心脏但别把它写成死循环Agent Loop 是 Harness 里最核心也最容易被写坏的部分。它的职责听起来很简单接收输入调用模型执行动作把结果喂回去直到任务完成。但“直到任务完成”这五个字里藏着大量工程细节。循环什么时候继续、什么时候停、什么时候该问人、什么时候该放弃这些判断如果没做好Agent 要么提前退出要么无限循环烧钱。我见过最典型的翻车场景是模型连续三轮返回同一个工具调用因为工具一直报同样的错而 Harness 没有检测“重复动作”的机制。结果就是 API 账单一路涨任务一点进展没有。另一个常见问题是循环没有最大步数限制模型陷入“我再试一次”的自我安慰里跑了五十步还在原地打转。2.1 循环的三种终止条件必须同时存在一个能上生产的 Agent Loop至少要有三种终止条件。第一种是任务完成信号通常由模型显式输出一个finish动作或者满足某个预设的完成条件。第二种是步数上限比如最多 20 步超过就强制停止并返回当前状态。第三种是重复检测如果连续 N 步的动作和参数完全一致或者状态没有发生任何变化就判定为卡死提前终止。这三种条件缺一不可。只有完成信号模型可能永远不输出只有步数上限模型可能在最后几步才找到正确路径被你提前砍掉只有重复检测模型可能用不同参数反复试错步数照样爆炸。实际配置时步数上限可以根据任务复杂度动态调整简单任务 8 到 10 步复杂任务 30 到 50 步。重复检测的窗口一般设 3 步连续 3 步状态无变化就触发。MAX_STEPS 30 REPEAT_WINDOW 3 def agent_loop(task, tools, llm): state init_state(task) history [] for step in range(MAX_STEPS): action llm.decide(state, history) if action.type finish: return state.result result tools.execute(action) new_state state.update(result) if is_repeated(history, action, new_state, REPEAT_WINDOW): return state.result_with_flag(stuck) history.append((action, result)) state new_state return state.result_with_flag(max_steps)这段伪代码里最关键的是is_repeated的判断逻辑。它不能只比较动作名称还要比较参数和状态变化。有时候模型会换一个措辞但实际做同一件事比如read_file和cat_file如果工具注册表没有做别名归一化重复检测就会失效。2.2 循环里该不该让模型“看到”全部历史这是一个很实际的取舍。把全部历史塞给模型好处是上下文完整坏处是 token 消耗大而且模型容易被早期无关信息干扰。我的做法是分层最近 3 步的完整动作和结果保留原文更早的历史压缩成摘要只保留“做了什么、结果如何、是否成功”三个字段。摘要可以由模型自己生成也可以用规则提取。这个策略在长任务里效果很明显。一个 20 步的任务如果每步都保留完整工具输出上下文很容易超过模型窗口。压缩之后token 消耗能降一半以上而且模型决策质量反而更稳定因为它不会被十步之前的报错信息带偏。注意压缩历史时一定要保留失败记录。很多 Agent 会重复犯同一个错误就是因为失败信息被摘要丢掉了。失败记录要单独存一个列表每轮都注入到提示里。3. LLM Integration别把模型当黑盒要当可替换的零件LLM Integration 这个子系统听起来就是“调 API”但实际上它决定了你的 Harness 能不能换模型、能不能降级、能不能在成本和效果之间做平衡。我见过太多项目把模型调用写死在业务逻辑里后来想换个更便宜的模型做简单任务发现要改几十个地方。正确的做法是把模型调用抽象成一个接口Harness 只依赖这个接口不依赖具体是哪家模型。这个接口至少要支持三件事同步调用、流式调用、带工具调用的结构化输出。同步调用用于简单决策流式调用用于需要实时反馈的场景结构化输出用于工具调用和状态更新。不同模型对这三件事的支持程度不一样有的模型工具调用很稳有的模型流式输出会丢字段。Harness 要做的是把这些差异屏蔽掉对上暴露统一的调用方式。3.1 模型路由简单任务别用贵模型一个很实用的优化是模型路由。Harness 在每一轮决策前先判断当前任务的复杂度然后选择不同档位的模型。判断复杂度可以用规则比如“是否需要多步推理”“是否涉及代码生成”“上下文长度是否超过阈值”。简单任务用轻量模型复杂任务用强模型成本能降不少效果损失很小。我自己的配置是意图识别和状态摘要用轻量模型工具参数生成用中等模型复杂规划和错误恢复用强模型。这个分层不是固定的要根据实际任务分布调整。如果大部分任务都是简单查询那轻量模型的比例可以更高。关键是 Harness 要记录每个模型调用的耗时、token 消耗和成功率这样你才能知道路由策略有没有效果。3.2 工具调用的格式兼容层不同模型返回工具调用的格式差异很大。有的返回 JSON有的返回 XML有的用特殊 token 标记。如果 Harness 直接解析模型原始输出换模型时解析逻辑就要重写。我的做法是在 LLM Integration 层加一个格式兼容层把不同模型的输出统一转换成内部的标准动作格式。这个兼容层要处理几种常见情况JSON 字段名不一致、参数嵌套层级不同、多工具调用时的数组结构差异、以及模型偶尔返回自然语言而不是结构化数据。最后一种情况最麻烦需要有一个 fallback 解析器用正则或者轻量模型把自然语言里的动作意图提取出来。这个 fallback 不追求 100% 准确但能避免因为格式问题导致整个循环崩溃。模型输出格式常见问题兼容层处理方式JSON字段名不统一如toolvsaction字段名映射表XML嵌套层级深解析慢转换为中间 JSON特殊 token多工具调用边界不清按 token 分割后逐个解析自然语言无结构无法直接执行正则加轻量模型提取4. Tool Runtime工具不是函数是带副作用的操作Tool Runtime 是 Harness 里最接近“干活”的部分。很多人把工具当成普通函数来写输入参数、返回结果看起来没问题。但 Agent 的工具和普通函数有一个本质区别它们有副作用而且副作用可能失败、可能部分成功、可能产生不可逆的影响。比如写文件这个操作写到一半磁盘满了文件处于半截状态比如调外部 API请求发出去了但响应超时你不知道对方到底执行了没有。Tool Runtime 要解决的就是这些“不干净”的问题。它需要给每个工具定义清晰的输入输出 schema需要处理超时和重试需要记录副作用需要在可能的情况下支持回滚。这些机制不是可选项是 Agent 能不能安全跑真实任务的前提。4.1 工具描述的质量决定模型会不会用模型选择工具的依据是工具描述。描述写得好模型一次就能选对描述写得模糊模型就会乱试。一个好的工具描述要包含四要素这个工具做什么、什么时候该用、参数是什么意思、返回什么结果。很多人只写第一项结果模型在需要读文件的时候去调了写文件的工具。我习惯在工具描述里加“反例”。比如读文件的工具描述里会写“不要用这个工具来修改文件内容修改请用 write_file”。这种负向提示对减少误调用很有效。另外参数描述要说明格式和约束比如“路径必须是绝对路径”“超时单位是秒”。模型对这些细节很敏感写清楚了能减少大量参数错误。4.2 超时、重试和幂等性工具执行必须设超时。没有超时的工具调用会把整个 Agent 卡死。超时时间根据工具类型定本地文件操作 5 秒外部 API 15 到 30 秒复杂计算可以到 60 秒。超时之后不能直接抛异常结束要返回一个结构化的超时结果让模型决定是重试还是换方案。重试要区分错误类型。网络抖动导致的超时可以重试参数错误导致失败重试没有意义。重试次数一般设 2 到 3 次每次间隔可以指数退避。对于有副作用的工具重试前要检查幂等性。比如“追加一行日志”重试两次会写两行这种工具要么设计成幂等要么在重试前先查询状态。def execute_with_retry(tool, params, max_retries3): for attempt in range(max_retries): try: result tool.run(params, timeouttool.timeout) return result except TimeoutError: if attempt max_retries - 1: return ToolResult.timeout() time.sleep(2 ** attempt) except ParamError as e: return ToolResult.param_error(str(e)) except Exception as e: if not tool.idempotent: return ToolResult.unknown_state(str(e)) if attempt max_retries - 1: return ToolResult.failed(str(e))这段代码里unknown_state这个返回类型很重要。对于非幂等工具超时之后你不知道操作有没有生效这时候不能简单说“失败”要说“状态未知”让模型决定是去查一下还是人工介入。实操心得给每个工具标注idempotent和side_effect两个属性。side_effect为 true 的工具在重试和错误恢复时要特别小心。我一般会把这些工具的调用记录单独存一份方便事后审计。5. Memory StateAgent 的“记性”和“账本”是两回事很多人把 Memory 和 State 混在一起讲导致实现的时候也混在一起。我的经验是这两者要分开。State 是当前任务的“账本”记录每一步做了什么、结果是什么、现在处于什么阶段。Memory 是跨任务的“经验”记录以前遇到过什么类似问题、怎么解决的、哪些方案有效。State 是短期的、结构化的、必须准确的Memory 是长期的、模糊的、用于参考的。分开的好处是State 可以设计得很严格每一步都必须更新保证任务执行的可追溯性。Memory 可以设计得很灵活用向量检索或者关键词匹配允许不精确。如果把两者混在一起要么 State 被 Memory 的模糊性污染要么 Memory 被 State 的严格结构限制住。5.1 State 的最小结构State 至少要有四个字段任务目标、当前步骤序号、已完成动作列表、当前环境快照。任务目标是原始输入的规范化版本防止多轮之后模型忘了要干什么。当前步骤序号用于循环控制和日志追踪。已完成动作列表记录每个动作的类型、参数、结果和状态。环境快照记录任务相关的环境变量比如当前工作目录、已修改的文件列表、已调用的 API 列表。环境快照这个字段很容易被忽略但在错误恢复时非常关键。比如 Agent 改了三个文件之后失败了你需要知道是哪三个文件才能决定是回滚还是继续。如果没有环境快照你只能去翻日志效率很低。5.2 Memory 的检索策略Memory 的检索不能只靠向量相似度。向量相似度找的是“语义相近”但 Agent 需要的是“情境相近”。一个任务失败的原因可能和另一个任务失败的原因语义上不相似但情境上很相似比如都是因为权限不足。我的做法是混合检索先用关键词过滤出候选集再用向量相似度排序最后用规则加权比如同一工具、同一错误类型、同一项目路径的 Memory 权重更高。Memory 的写入也要有策略。不是所有任务都值得记只有那些“有教训”的任务才值得。判断标准可以是任务失败过、重试超过三次、或者人工介入过。这些任务的经验最有价值。写入时要把任务目标、失败原因、最终解决方案结构化存储方便后续检索。维度StateMemory生命周期单任务跨任务数据结构严格结构化半结构化或向量准确性要求必须准确允许模糊更新频率每步更新任务结束后写入主要用途循环控制、错误恢复经验参考、策略优化6. Output Parser模型输出不可信解析层要能兜底Output Parser 是 Harness 里最不起眼但最容易出问题的部分。模型输出格式不稳定是常态尤其是当提示里包含大量上下文时模型很容易在 JSON 外面包一层自然语言或者漏掉某个字段或者把字符串写成数字。如果主循环直接解析模型原始输出这些格式问题会直接导致循环崩溃。Output Parser 的职责是把模型输出转换成内部标准动作格式并且在转换失败时提供有意义的错误信息让模型有机会修正。它要处理的不只是 JSON 解析还包括字段缺失、类型错误、枚举值不合法、多动作嵌套等情况。6.1 解析失败时的修复策略解析失败后不能直接抛异常要返回一个结构化的解析错误包含原始输出和失败原因。这个错误会作为下一轮的输入喂给模型让它重新生成。为了提高修复成功率错误信息里要包含期望的格式示例。比如“你的输出缺少action字段期望格式是{action: ..., params: {...}}”。如果连续两轮解析失败就要考虑降级策略。降级策略可以是用更简单的提示重新调用模型、用规则提取关键信息、或者直接返回人工介入。我一般会在解析层加一个“宽松模式”当严格解析失败时尝试用正则提取动作名称和参数虽然可能不完整但至少能让循环继续而不是直接卡死。6.2 多动作输出的处理有些模型会一次返回多个动作比如“先读文件再修改再保存”。这种输出如果直接执行中间任何一步失败都会导致后续步骤基于错误状态执行。我的做法是强制单动作输出在提示里明确要求“每轮只返回一个动作”。如果模型还是返回多个解析层只取第一个并在结果里提示“检测到多动作已执行第一个请基于结果决定下一步”。这个策略牺牲了一点效率但换来了状态的可控性。多动作执行在简单场景下看起来快但在复杂场景下会让错误定位变得非常困难。单动作执行虽然多几轮但每一步都有明确的状态记录出问题容易排查。def parse_output(raw): try: data json.loads(raw) except json.JSONDecodeError: match re.search(r\{.*\}, raw, re.DOTALL) if match: try: data json.loads(match.group()) except json.JSONDecodeError: return ParseError(raw, 无法提取 JSON) else: return ParseError(raw, 输出中未找到 JSON) if action not in data: return ParseError(raw, 缺少 action 字段) if not isinstance(data.get(params, {}), dict): return ParseError(raw, params 必须是对象) return Action(data[action], data.get(params, {}))这段代码展示了从严格解析到宽松解析的降级路径。实际使用时ParseError会被记录并注入下一轮提示让模型知道上一轮输出哪里不合格。7. Error Recovery错误不是异常是 Agent 的日常输入Error Recovery 是区分玩具 Agent 和生产力 Agent 的分水岭。玩具 Agent 遇到错误就崩生产力 Agent 把错误当成一种正常的执行结果基于错误信息调整策略。这个子系统要做的不是“避免错误”而是“让错误变得可理解、可分类、可恢复”。错误分类是第一步。我一般把错误分成四类参数错误、环境错误、权限错误、未知错误。参数错误是模型给的参数不对比如路径不存在、类型不匹配这类错误直接把错误信息返回给模型它通常能自己修正。环境错误是外部条件不满足比如网络超时、磁盘满这类错误需要重试或者换方案。权限错误是当前身份不允许执行某个操作这类错误重试没用需要升级权限或者换工具。未知错误是没法归类的这类错误要记录详细上下文方便人工排查。7.1 错误恢复的决策树错误恢复不能靠模型自由发挥要有一个决策树来引导。决策树的第一层是错误类型第二层是重试次数第三层是任务关键性。比如参数错误且重试次数小于 2直接返回错误让模型修正环境错误且重试次数小于 3等待后重试权限错误直接返回并建议人工介入未知错误记录并返回如果连续出现两次终止任务。这个决策树可以硬编码在 Harness 里也可以作为提示的一部分让模型参考。我的做法是硬编码基础规则同时在提示里告诉模型“遇到权限错误不要重试直接报告”。这样既保证了基本行为可控又给了模型一定的灵活性。7.2 错误信息的结构化错误信息不能是一大段自然语言要结构化。至少包含错误类型、错误码、错误消息、发生位置、建议动作。结构化之后模型更容易理解Harness 也更容易做统计和告警。比如“错误类型权限错误错误码EACCES位置write_file(/etc/config)建议检查文件权限或换路径”。我见过很多 Agent 把原始异常堆栈直接塞给模型结果模型被堆栈里的无关信息干扰反而找不到重点。结构化错误信息就是帮模型做了一次信息过滤把真正有用的部分提取出来。错误类型典型场景恢复策略重试上限参数错误路径不存在、类型不匹配返回错误让模型修正2环境错误网络超时、磁盘满等待后重试或换方案3权限错误无权限读写、无权限调用报告并建议人工介入0未知错误未分类异常记录上下文连续两次终止1避坑技巧错误恢复里最容易犯的错是“无限重试同一个错误”。一定要在 State 里记录每个错误的出现次数同一个错误码出现超过阈值就强制换策略或终止。8. ObservabilityAgent 跑飞的时候你得知道它在哪一步跑偏Observability 是 Harness 的“黑匣子”。Agent 和普通程序不一样它的执行路径不是预先确定的而是模型每一步决策出来的。这意味着出问题的时候你不能靠读代码来定位只能靠日志和追踪。没有 Observability 的 Agent跑飞了就是一团黑你只知道结果不对不知道哪一步开始不对。Observability 要记录的东西比普通程序多。除了常规的请求日志、错误日志还要记录每一轮的模型输入输出、工具调用参数和结果、状态变化、决策耗时、token 消耗。这些数据要能按任务 ID 串联起来形成一个完整的执行链路。8.1 关键指标和告警Agent 的监控指标和普通服务不一样。普通服务看 QPS、延迟、错误率Agent 还要看任务完成率、平均步数、重复动作率、解析失败率、人工介入率。这些指标能反映 Agent 的“健康度”。比如重复动作率突然升高说明模型可能陷入了某种循环解析失败率升高说明提示或者模型输出格式出了问题。告警阈值要根据历史数据来定。我一般会设几个硬阈值单任务步数超过 50 告警单任务 token 消耗超过预算告警连续三个任务失败告警。这些告警不需要很精确目的是在问题扩大之前引起注意。8.2 执行链路的可视化日志是给人看的但 Agent 的日志量很大纯文本很难快速定位问题。我的做法是把执行链路结构化存储每一步是一个节点包含动作、参数、结果、耗时、状态变化。然后提供一个简单的查询界面可以按任务 ID 查看完整链路也可以按错误类型筛选。这个链路数据还有一个用途用于优化提示和工具描述。通过分析失败任务的链路你能发现模型在哪些环节容易出错然后针对性地改提示或者改工具设计。比如发现模型经常在“选择工具”这一步出错那就要优化工具描述发现模型经常在“参数格式”上出错那就要在提示里加更多示例。class TraceNode: def __init__(self, step, action, params, result, duration, state_delta): self.step step self.action action self.params params self.result result self.duration duration self.state_delta state_delta self.timestamp time.time() def log_trace(task_id, node): trace_store.append(task_id, node) metrics.record_step(task_id, node) if node.duration SLOW_THRESHOLD: alert(f任务 {task_id} 第 {node.step} 步耗时过长)这段代码展示了追踪节点的最小结构。实际使用时result和state_delta要做脱敏处理避免敏感信息进入日志。9. 七个子系统怎么串起来一个最小可运行 Harness 的搭建顺序知道了七个子系统各自干什么接下来的问题是按什么顺序搭。我的建议是从 Agent Loop 和 LLM Integration 开始先把“模型能决策、循环能跑”这条主线打通。然后加 Tool Runtime让 Agent 能真的操作环境。接着加 Output Parser解决格式不稳定问题。再加 State让循环有记忆。然后加 Error Recovery让 Agent 能扛错误。最后加 Memory 和 Observability前者提升长期效果后者提升可维护性。这个顺序不是绝对的但符合“先跑通、再跑稳、再跑好”的逻辑。很多人一上来就搞 Memory 和 Observability结果主循环还没跑通记了一堆没用的日志。先把核心链路跑通再逐步加外围能力这样每一步都有可验证的产出。9.1 最小 Harness 的代码骨架class Harness: def __init__(self, llm, tools, config): self.llm llm self.tools tools self.config config self.parser OutputParser() self.state State() self.tracer Tracer() def run(self, task): self.state.init(task) for step in range(self.config.max_steps): prompt self.build_prompt() raw self.llm.call(prompt) action self.parser.parse(raw) if isinstance(action, ParseError): self.state.record_parse_error(action) continue if action.type finish: return self.state.result result self.tools.execute(action) self.state.update(action, result) self.tracer.log(step, action, result) if self.state.is_stuck(): return self.state.result_with_flag(stuck) return self.state.result_with_flag(max_steps)这个骨架里build_prompt负责把 State、工具描述、错误历史组装成提示。is_stuck负责重复检测。result_with_flag返回带状态标记的结果方便上层判断是正常完成还是异常终止。9.2 配置项和默认值配置项说明建议默认值max_steps单任务最大步数30repeat_window重复检测窗口3tool_timeout工具默认超时秒15max_retries工具最大重试次数3parse_retry解析失败最大重试2memory_top_kMemory 检索返回条数5这些默认值不是拍脑袋定的是我在不同项目里调整后觉得比较稳的起点。实际使用时根据任务类型微调比如代码生成任务步数可以放宽到 50简单查询任务可以收紧到 10。10. 实际跑起来之后最容易踩的五个坑第一个坑是提示太长导致模型“失忆”。当 State 和工具描述加起来超过模型窗口的一半时模型对早期信息的注意力会明显下降。解决办法是压缩历史只保留最近几步的完整信息更早的用摘要。第二个坑是工具描述太抽象。比如“处理文件”这种描述模型根本不知道什么时候该用。工具描述要具体到“读取指定路径的文本文件内容返回字符串”并且说明适用场景和不适用场景。第三个坑是错误恢复变成无限重试。前面提过一定要在 State 里记录错误次数同一个错误超过阈值就换策略。我一般设 2 次同一个错误码出现 2 次就强制终止或人工介入。第四个坑是 Memory 污染。如果 Memory 里存了大量低质量经验检索出来的参考信息反而会误导模型。Memory 写入要严格只存有明确教训的任务并且定期清理过时条目。第五个坑是 Observability 缺失导致无法复盘。Agent 出问题的时候如果没有完整的执行链路你只能靠猜。我的做法是每个任务都生成一个 trace ID所有日志和状态都关联这个 ID出问题直接按 ID 查。最后分享一个实操小技巧在 Harness 里加一个“干跑模式”工具调用只记录不执行。这个模式用于测试提示和循环逻辑不会产生副作用调试起来很安全。等干跑模式跑通了再切到真实执行。这些子系统拆开看都不复杂难的是让它们协同工作。我的经验是先把 Agent Loop 和 Tool Runtime 做扎实这两个是“干活”的核心。Output Parser 和 Error Recovery 是“保命”的决定 Agent 能不能在真实环境里存活。State、Memory、Observability 是“提升”的决定 Agent 能不能越用越好。按这个优先级来搭比一上来就追求大而全的架构要靠谱得多。
延伸阅读

更多相关文章

2026/11/2 3:50:00

前端错误处理全攻略:从捕获到监控的工程实践

1. 前端错误处理的痛点与价值作为一名经历过无数深夜调试的前端老兵,我深知错误处理对开发效率的影响。记得去年双十一大促前夜,我们的电商页面突然出现了一个诡异的JS报错,整个团队花了6个小时才定位到问题——原来是一个未处理的Promise re…

2026/11/2 3:50:00

匹配滤波器原理与MATLAB实现:从雷达回波中提取微弱信号

简介:匹配滤波器是通信与信号处理中实现最佳接收、在噪声环境下最大化输出信噪比的核心技术,本资源面向学习信号检测理论并希望动手实践的高校学生与工程技术人员,围绕其原理推导与MATLAB实现展开。压缩包共2个文件,以1个m脚本和1…

2026/11/2 3:45:00

Hermes Agent架构拆解:从子系统边界到执行路径

讲真的,整理 Agent 框架的架构资料这段时间,我最大的感触是:市面上聊 Agent 的文章不少,但大多数都停在“什么是 Agent”“怎么调工具”这个层面,真正把子系统边界、执行链路、数据流向掰开揉碎讲清楚的内容太少了。正…

2026/11/2 4:50:04

短剧系统高并发架构与支付闭环实战

1. 项目概述:短剧系统的商业价值与技术挑战短剧内容近年来呈现爆发式增长,这种单集时长3-5分钟的碎片化娱乐形式,特别适合移动互联网时代的用户消费习惯。一个成熟的短剧系统需要同时解决内容生产、高效分发、即时互动和商业变现四大核心需求…

2026/11/2 4:50:04

短剧平台高并发架构设计与支付系统优化实践

1. 项目背景与核心价值短剧内容消费正在成为数字娱乐领域的新风口。根据行业数据显示,2023年国内短剧市场规模同比增长超过300%,单部爆款作品日播放量可达数千万次。这种内容形态具有单集时长短(3-5分钟)、剧情紧凑、制作周期快等…

2026/11/2 4:50:04

三大AI模型开发3D游戏实测:Step 5、DeepSeek、GLM谁更胜一筹?

最近我把几个新模型拉到同一个考场里做了一件挺有意思的事:用完全相同的需求,让 Step 5 Preview、DeepSeek V4 Pro 和 GLM5.3 分别从零做一个 3D 小游戏,然后对比它们从出方案到跑通、再到改需求的全过程。先说结论:三个模型都能写…

2026/11/2 4:50:04

NVIDIA自动驾驶实时检测模型的技术解析与应用

1. 项目概述:自动驾驶实时检测的技术革命NVIDIA自动驾驶实验室最新发布的"用于自主系统的实时检测基础模型"标志着自动驾驶感知技术迈入新阶段。这套解决方案通过深度融合计算机视觉与边缘计算,在嵌入式GPU平台上实现了亚毫秒级的环境感知响应…

2026/11/2 4:50:04

Next.js + LangGraph.js 构建简历 AI Agent 实战

1. 为什么简历工具值得用 AI Agent 重做一遍简历这个赛道,表面上看已经被各种模板站和在线编辑器做烂了,但真正动手做过的人都知道,传统简历工具的天花板非常低。用户打开一个网页,填表单、选模板、导出 PDF,整个链路是…

2026/11/2 4:45:04

Higress底层原理:Gateway API、Envoy深度定制与Wasm沙箱机制解析

1. 为什么今天必须搞懂 Higress 的底层逻辑Higress 不是又一个“换个壳的网关”,它是一次对云原生流量治理范式的重新定义。如果你正在用 Kubernetes 做生产级服务编排,却还在用 Nginx Ingress 手写 rewrite 规则、靠 ConfigMap 硬 reload、为 TLS 终止反…

2026/11/1 0:01:26

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/1 1:01:33

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 1:04:04

工业级SPI隔离设计:硬件抗扰与信号完整性实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 1:04:04

PLFM_RADAR:主动探测数据通道,构建低误报的数据感知系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/2 1:04:04

工业SPI隔离设计:MAX14431与STM32F746硬件抗干扰实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/1 0:01:26

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/1 1:01:33

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑