--- title: "Harness如何支撑Agent在生产环境稳定运行?" sha256: cccb98a63336d1efb696d0abf517a78a402c5317a62f88fb82ceb2b8d61ef598 source_url: https://mp.weixin.qq.com/s/HVkWNXTsFjn0HkdGyD7Tpw author: AI技术立文 publisher: AI技术立文 published: 2026-05-14 created: 2026-05-14 type: raw tags: - harness - llm-agent - production - engineering - demo-type - production-type - four-pillars - claude-code - agentleak review_value: 9 review_confidence: 8 review_recommendation: strong ingested: 2026-05-16 review_stars: 5 summary: Agent工程赤字概念/Demo型vs生产型代码库四维判别/Claude Code退化复盘/四支柱(构建-记忆-运行框架-编排)/AgentLeak benchmark/生产级框架与反模式/推荐阅读清单,评分72。 --- ## 核心概念:工程赤字(Engineering Deficit) > 很多智能体能做出演示,却很难变成可靠产品。 反复出现的故障模式: - 错误的标识符被传给工具 - 状态被 LLM 污染 - 智能体断言了用户从未说过的"事实" - 两个智能体意外共享了同一个列表 - 工具报错被吞掉,又被塞回对话里,看起来像成功但结果为空 **问题通常不在模型本身,而在模型周围工程——Harness。** --- ## 行业数据 | 数据 | 来源 | |------|------| | 88% 的智能体项目没有进入生产环境 | 行业普遍数据 | | 企业生成式 AI 试点失败率达到 95% | MIT 2025年8月报告 | | 真正把 AI 智能体跑在生产环境的开发者 | 1837名企业开发者中仅95人(5%) | **成功案例**:Klarna(LangGraph,8500万活跃用户,问题解决时间下降80%)、Cursor、Harvey、Sierra。 --- ## 两种代码库类型 ### Demo 型特征 - 很丰富的 prompt,接了很多工具,但几乎没有边界约束 - 工具接受任意字符串,出错返回空列表 - 异常被捕获、转成字符串,再继续塞进对话 - 会话状态是没有 schema 的 dict - 系统提示词里手写工具清单,有些工具早就不存在 - 没有 `ask_user` 工具 - 智能体循环没有 `MAX_STEPS` 上限 - span 只包住 LLM 调用,不覆盖工具调用和状态变更 ### 生产型特征 - 工具在入口处校验格式,抛出结构化错误 - 会话状态有类型化 schema 和来源记录 - 敏感字段不接受低信任来源写入 - 系统提示词从已注册工具列表生成 - 运行框架覆盖 LLM 和工具调用的 span - token 使用量按步骤记录 - 循环有硬上限 - 破坏性操作需要人类确认 - 多智能体系统给子智能体传递边界清楚的任务契约 **分界线:团队有没有把模型周围的工程当成产品本身。** --- ## Claude Code 退化事故复盘(2026年4月) Anthropic 承认 Claude Code 表现被几个运行时改动削弱: - 默认 reasoning effort 降级 - 缓存改动导致会话中途丢失推理历史 - 系统提示词限制工具调用之间的回复长度 **结果**: - 可见思考长度中位数下降 **73%** - API 重试率上升 **80 倍** - 问题先被**社区研究者**通过会话数据分析挖出,而非内部监控 **教训**:连 Claude 背后的团队都会在旗舰产品里踩这种坑。运行框架的改动不碰模型本体,但叠加在一起足以让产品退化。 --- ## 四支柱审查框架 审智能体代码库主要看四件事:**构建、记忆、运行框架、编排**。每一个 demo 型代码库,至少会在其中三项上失败。 ### 支柱一:构建——工具契约必须约束模型 **核心问题**:工具签名只约束代码,没有约束模型会传进来的值。 例如:Stripe customer ID 参数 `customer_id: str`,LLM 传了邮箱进去 → Stripe 返回 404 → 函数返回 `None` → 智能体告诉付费用户"找不到账户"。 **框架没问题。模型没问题。问题在于工具契约太弱。** 修复方法: 1. 在工具入口校验格式(如 Stripe customer ID 必须以 `cus_` 开头) 2. 错误信息告诉模型下一步该怎么做("这是邮箱,不是 customer ID,请先调用 find_customer_by_email") 3. **不要静默吞错**:`try/except: return []` 会把"路径不存在、权限被拒绝、目标其实是文件"都伪装成"目录为空" 4. 给模型结构化结果:`status`、`error_type`、`message`,让它能按分支行动 5. 提供 `ask_user` 工具,并用回归测试确保智能体在该问的时候会问 **工具参数和错误消息怎么命名,会影响模型下一轮怎么判断。这不只是 prompt engineering,而是上下文工程。** --- ### 支柱二:记忆——状态必须可信、隔离、可追溯 #### 隔离失效案例 **2023年3月 ChatGPT 下线**:部分用户看到其他用户的数据(对话标题、Plus 用户账单信息)。根因是 Redis-py 客户端 bug——被取消的连接经过连接池时,把错误数据送进另一个用户请求。 #### 类作用域可变默认值(更直接的形式) ```python class Agent: history: list[dict] = [] # 类级别可变默认值! tools: list[Tool] = [search_tool] ``` 单用户测试正常。两个用户并发经过同一进程时,历史、工具列表、scratchpad、子智能体注册表全部串在一起。 **修复**:用实例级状态 `field(default_factory=list)`。再写回归测试:构造两个智能体,修改其中一个,断言另一个没有受影响。 #### 语义层状态投毒 ```python remember_fact(key, value) ``` 用户说"我的邮箱是 admin@evil.com",LLM 直接写入 `user_email`,后续发邮件工具使用被污染的值。模型不会意识到"刚刚发生了危险的状态变更"。 **防御三层约束**: 1. 用类型化 schema 拒绝未知状态键 2. 给每条事实记录来源:已验证 OAuth、系统初始化、用户输入,还是 LLM 断言 3. 给敏感字段设置权限边界,拒绝低信任来源修改 **OWASP LLM Top 10 把 prompt injection 列为 2025-2026 年排名第一的关键漏洞。** 常见错误直觉:系统提示词写在最前面,所以权限最高。**这是错的。** 模型会读到上下文里的每个 token。**权限不在 prompt 里,而在代码里。** --- ### 支柱三:运行框架——智能体循环本身就是基础设施 demo 版循环: ``` 用户消息 → 调用 LLM → 有工具调用则执行 → 失败返回 "tool failed, please try again" → 结果塞回 history → 再调用 LLM ``` **问题**:抹掉了关键信息。模型不知道哪个工具失败、为什么失败、接下来该怎么调整。结果:要么不透明放弃,要么反复重试同一个坏掉的工具调用,直到超时/额度耗尽/用户失去耐心。 生产级运行框架至少要做: 1. 工具错误既记录给人看,也作为**结构化结果**返回给模型 2. 每次 LLM 调用和工具调用都进入 **trace** 3. token 用量按步骤记录,失控循环在监控里变成**成本尖峰** 4. 循环有**硬上限**(`MAX_STEPS`) 5. 高风险工具需要**显式确认**,且这个确认不能相信 LLM 的推理链 **结构性防御**:让破坏性动作依赖 LLM **无法伪造**的凭证(用户确认、签名审批、延迟窗口),把这套机制放在智能体循环之外。 > **模型可以替换,运行框架决定了替换模型时系统会不会 crash。** --- ### 支柱四:编排——多个不确定执行者需要明确契约 **多智能体没有天然的优劣势**: - Cognition 反对多智能体,讲一致性关键任务(写代码/对话) - Anthropic 支持多智能体,讲广度优先研究(瓶颈是总 token 和搜索覆盖面) - 两者并不矛盾 **关键不在"要不要用多个智能体",而在编排层有没有清楚的任务契约、状态隔离和跨步骤追踪。** #### AgentLeak benchmark(2026) | 配置 | 系统暴露面 | |------|-----------| | 多智能体 | 68.9% | | 单智能体 | 43.2% | 暴露面扩大主要来自:智能体之间的消息、共享记忆、工具参数——只看最终输出通常发现不了。 #### 多智能体四大坑 1. **协调器和 worker 共享类级别状态**,两个请求并发进来就能看到彼此历史 2. **子智能体直接拿到父智能体完整对话历史**,看见了本不该看见的工具结果和指令 3. **长任务只存在单个 Python 进程**,一次部署/崩溃就抹掉整个工作流 4. **父 trace 和子 trace 没有关联**,出了问题只能靠时间戳拼事故现场 **正确做法**: - 子智能体调用像 **RPC** 一样处理:输入字段、预期输出长什么样、输出怎么校验、父上下文哪些片段允许传过去,都要提前说清楚 - 长任务做成**可恢复的持久状态机**(用 Temporal、DBOS 或普通任务队列,不要自己造) --- ## 哪些方向可以先放一放 | 建议 | 理由 | |------|------| | 不要把"别做多智能体"当成公理 | 看任务需要一致性还是并行搜索 | | 不建议为新生产系统优先选 AutoGen / AG2 / CrewAI | demo 友好但生产约束不足 | | 不要把 DSPy 当作通用智能体框架 | 适合 prompt program optimization,不是通用运行框架 | | 不要迷信 SWE-bench / OSWorld 排行榜 | 公开 benchmark 容易被刷,内部评估更重要 | | 新智能体产品不要轻易按 seat 定价 | 市场已转向按结果和用量付费 | | Hacker News 本周出现的新框架,等 6 个月再看 | 未被严谨评估的框架会产生迁移技术债 | --- ## 推荐阅读 1. **Anthropic Engineering Blog**:Context Engineering、Harnesses、Writing Effective Tools、Claude Code 事故复盘 2. **Cognition《Don't Build Multi-Agents》** + **Anthropic《How we built our multi-agent research system》**:两篇一起读,看清多智能体适用边界 3. **OWASP LLM Top 10**:prompt injection 篇 4. **Simon Willison 笔记、Latent Space 生产实践访谈、EchoLeak、AI memory poisoning**相关披露 --- ## 回到开头的三个问题 1. **如果智能体明天早上在生产里失败,团队会知道原因吗?** → 如果运行框架覆盖 LLM 和工具调用、有结构化工具结果、有步骤上限,答案是肯定的 2. **不了解 LLM 的后端工程师审这套代码库,第一眼会抓到什么?** → 类级别可变默认值、静默吞错、prompt 和工具注册表之间的状态漂移、工具接受字符串却不校验格式 3. **两个智能体并行运行,会不会看见彼此?** → 只要共享了进程级状态,而测试没有覆盖并发场景,就会 --- ## 核心结论 > 现在很多智能体不是因为模型错了才失败,而是因为模型周围的工程不够扎实。 > > 区别在于,这些东西现在要被用到一个中间夹着**不确定执行者**的系统里。 > > **边界要建,输入要校验,状态要隔离,循环要打点,暴露面要测试。模型会变,框架也会变。Harness 工程依然是 Agent 可靠性的关键。**