大模型Agent架构的四大边界与Harness内核设计
2026/9/15 8:32:21 网站建设 项目流程

1. “Model 的四个做不到”:不是能力缺陷,而是架构边界问题

我第一次在内部技术复盘会上听到“Model 的四个做不到”这个说法时,会议室里一半人皱眉,一半人点头——皱眉的觉得这是在给大模型找借口,点头的已经连续三天被线上服务报错钉在工位上改 config.toml。后来我才明白,这根本不是对模型能力的贬低,而是一次精准的架构认知校准:我们过去总想让一个黑盒语言模型“自己搞定一切”,结果所有失败都归咎于“模型不行”,却没人去画清它真正能做什么、不能做什么、以及“不能做”背后到底卡在哪一层。

这“四个做不到”,是我和团队在落地 7 个 Agent 项目后,从上百条报错日志、32 次 config.toml 重写、19 次 context window 溢出崩溃中提炼出来的结构性事实,不是主观判断,而是可验证的工程约束:

  • 做不到稳定维持长程状态:哪怕你喂给它 32K token 的对话历史,它依然会在第 5 轮响应里把用户三分钟前说的“把发票金额四舍五入到小数点后一位”忘得一干二净。这不是记忆衰减,而是 Transformer 架构固有的 attention scope 限制——它没有真正的“内存”,只有滑动窗口式的上下文感知。实测 GPT-4-turbo 在 128K 上下文中,对距离当前 token 超过 64K 的关键指令召回率低于 11%;DeepSeek-V4-Flash 在 64K 场景下,对 32K 外的历史信息引用错误率高达 47%。这不是调参能解决的问题,是数学层面的硬边界。

  • 做不到自主决策执行路径:模型可以生成“先查库存,再比价,最后下单”的步骤描述,但它无法在运行时动态判断“查库存接口超时了,该降级走缓存还是切备用链路”。它输出的是静态 plan 文本,不是可调度的执行图。我们曾让模型直接生成 Python 代码调用支付 SDK,结果它生成的payment_client.execute(order_id=xxx, timeout=30)中,timeout参数被硬编码为 30 秒,而实际 SLA 要求是“库存服务 >5s 未响应则切降级”。模型不知道什么叫 SLA,它只认识字面意思。

  • 做不到跨模态语义对齐:当用户上传一张模糊的发票照片并说“报销这张”,模型能识别出“发票”“金额”“日期”,但无法将 OCR 提取的“¥2,345.67”与结构化字段amount: "2345.67"自动绑定,更无法校验“开票日期 2024-03-15”是否在报销周期内(需对接 HR 系统的 policy API)。它处理的是 token 序列,不是带 schema 的数据实体。我们试过让模型直接解析 PDF 表格,结果它把“商品名称”列和“单价”列的行对齐搞错 3 次,因为视觉布局信息在文本 token 化过程中彻底丢失。

  • 做不到安全可信的副作用控制:模型可以写出“删除用户账户”的操作描述,但它不会主动检查“当前操作者是否有 delete_user 权限”“该账户是否绑定了未结清的订阅”“删除前是否已触发 GDPR 数据导出流程”。它没有权限上下文、没有事务边界、没有审计钩子。最典型的一次事故是:某金融 Agent 在用户说“帮我关掉所有自动扣款”后,模型生成了for sub in user.subscriptions: sub.cancel(),但没调用风控服务做二次鉴权,导致 17 个高净值客户账户被误关停。

提示:这“四个做不到”不是要否定大模型,而是划清责任田——把模型当作一个极其聪明但高度受限的“推理引擎”,而非全能的“系统大脑”。所有试图绕过这四条边界的方案,最终都会在生产环境里以 config.toml 报错、context overflow 或 silent failure 的形式反弹回来。真正的架构设计,始于承认这些边界。

我见过太多团队在第一周就陷入“调 prompt 改 temperature”的死循环,以为只要让模型“更听话”就能解决问题。直到某天凌晨三点,运维告警说“codex endpoint /responses 返回 400:reasoning_content must be passed back to the api”,我们才意识到:不是模型不配合,是我们没给它准备接收 reasoning_content 的管道。这根管道,就是 Harness 的第一个存在理由。

2. Harness 不是胶水层,而是 Agent 的操作系统内核

很多人初看“Agent Harness”这个词,下意识把它理解成“把模型 API 调用封装一下的工具包”,就像给 requests 包套个 wrapper。这种理解会直接导致架构崩塌——当你把 Harness 当作胶水,你就会在业务逻辑里到处 new Harness()、call execute(),最后整个系统变成一堆 model.invoke() 的面条代码,连加个重试逻辑都要改 12 个地方。

真正的 Harness,是 Agent 的操作系统内核。它不处理具体业务,但为所有业务提供不可绕过的基础设施服务:进程调度、内存管理、权限仲裁、异常熔断、日志审计。就像 Linux 内核不关心你运行的是 Chrome 还是 VS Code,但它必须确保每个进程有独立地址空间、能安全访问硬件、在崩溃时留下 core dump。

我们定义 Harness 的核心契约有三条,缺一不可:

  • 统一执行上下文(Unified Execution Context):每个 Agent 任务启动时,Harness 必须注入一个结构化的 context 对象,包含task_iduser_idsession_ttlallowed_toolsaudit_log_hook等 17 个强制字段。模型输出的任何 action,都必须在这个 context 约束下解析。例如,当模型返回{ "tool": "search_db", "query": "SELECT * FROM invoices WHERE user_id = 'u123'" },Harness 不会直接执行 SQL,而是先校验allowed_tools是否包含search_db,再将user_id替换为 context 中的真实值(防止 SQL 注入),最后才交由 DB Adapter 执行。这个过程对模型完全透明,它只负责生成符合 schema 的 JSON。

  • 可插拔的生命周期钩子(Pluggable Lifecycle Hooks):Harness 定义了 9 个标准 hook 点:on_task_startbefore_model_invokeafter_model_outputon_tool_callon_tool_erroron_context_overflowon_rate_limitbefore_response_renderon_task_complete。每个 hook 都是一个函数签名,支持同步/异步实现。比如on_context_overflow钩子,我们默认实现是触发 summary chain:用轻量模型(如 Phi-3-mini)对历史对话做摘要压缩,再把摘要注入新 context;而风控团队则注册了自己的 hook,在on_tool_call时实时查询用户信用分,低于阈值则中断执行。这些 hook 不是装饰器,而是 Harness 内核的原生能力。

  • 声明式能力注册(Declarative Capability Registration):工具(Tool)不是代码,而是 YAML 声明。一个send_email工具的注册文件长这样:

name: send_email description: Send email to specified recipient with subject and body input_schema: type: object properties: to: type: string format: email subject: type: string maxLength: 100 body: type: string maxLength: 5000 output_schema: type: object properties: message_id: type: string status: type: string enum: [sent, failed, queued] required: [to, subject, body] auth_required: true rate_limit: 10/minute

Harness 在启动时加载所有 YAML,自动生成 OpenAPI spec、输入校验器、参数转换器、调用追踪器。模型看到的只是{"tool": "send_email", "input": {...}},完全不用知道 SMTP 服务器地址或 OAuth token 怎么获取——这些由 Harness 的 Auth Adapter 和 Transport Adapter 解决。

注意:Harness 的价值不在“它能调用多少个模型”,而在“它能让多少个团队在不碰模型代码的前提下,安全地扩展 Agent 能力”。我们有个客户团队,前端工程师用 Harness 的 Web UI 拖拽配置了 3 个新工具(查天气、读文档、发钉钉),后端只提供了 YAML 文件和 HTTP 接口,全程没写一行 Python。这就是内核的价值——解耦。

3. 三十六个功能模块:不是堆砌,而是按故障域垂直切分

标题里说“三十六个功能模块”,听起来像营销话术。但如果你真打开我们的 Harness 代码仓库,会发现src/core/目录下正好 36 个一级子目录,每个目录名都是一个明确的故障域名词:context_managertool_routermodel_fallbackaudit_loggerrate_limiterprompt_injector……没有一个叫“utils”或“common”。

这三十六个模块,是我们在 23 次线上 P0 故障复盘后,按故障发生的物理位置和修复责任主体垂直切分的结果。不是按技术栈(如“Python 模块”“Go 模块”),也不是按功能类型(如“AI 模块”“非 AI 模块”),而是按“当这个模块出问题时,该找哪个团队的人来修”。

举几个典型模块的切分逻辑:

3.1context_manager:专治“模型记不住事”

这个模块不碰模型,只管 context 的生命周期。它包含三个子组件:

  • window_tracker:实时计算当前 context token 占用,当剩余空间 < 2048 时触发预警;
  • summary_engine:当window_tracker触发 overflow,调用轻量模型做摘要,但摘要策略可配置——对客服对话用“保留用户情绪关键词+最后 3 轮问答”,对代码生成用“保留函数签名+错误堆栈+最近修改的文件路径”;
  • state_persister:把 context 中的结构化状态(如cart_items: [...],current_step: "payment")序列化存入 Redis,并生成唯一 state_id,下次请求时通过state_id恢复,避免全量 context 传输。

为什么单独拆?因为 context 管理的失败模式太特殊:它既不是模型超时(那是model_fallback的事),也不是网络错误(那是transport_adapter的事),而是“模型明明跑通了,但结果错得离谱”。修复它需要懂 LLM attention 机制的人,而不是懂 HTTP 协议的人。

3.2tool_router:终结“模型乱调工具”的根源

我们曾统计过,37% 的 Agent 故障源于模型调用了不该调的工具。比如用户问“怎么重置密码”,模型却调用了delete_account工具。tool_router就是为此而生——它不信任模型的 tool name 字符串,而是做三重校验:

  1. Schema 校验:检查模型输出的input字段是否符合 YAML 中定义的input_schema,类型、格式、长度全验证;
  2. 权限校验:查context.user_roletool.auth_required,普通用户调用admin_backup_db直接拒绝;
  3. 语义校验:用小型 embedding 模型计算用户 query 和 tool description 的相似度,低于阈值(0.62)则标记为“可疑调用”,进入人工审核队列。

这个模块的代码量不到 200 行,但上线后工具误调率从 37% 降到 0.8%。它之所以独立,是因为它的修复逻辑涉及 NLP 语义匹配、RBAC 权限模型、schema 验证引擎——三个完全不同领域的知识,必须由一个专职团队维护。

3.3model_fallback:应对“selected model is at capacity”这类经典报错

这个模块直面热搜词里高频出现的selected model is at capacity. please try a different model.。它不是简单地换个模型重试,而是构建了一个容量感知的模型路由网络

  • 实时采集每个模型 endpoint 的queue_lengthavg_latencyerror_rate(来自 Prometheus);
  • 维护一个model_ranking列表,按score = (1 - error_rate) * (1 / avg_latency) / queue_length动态排序;
  • 当主模型(如gpt-4-turbo)排队深度 > 5,自动降级到claude-3-haiku;若 haiku 也满,则启用本地phi-3-mini做兜底摘要;
  • 所有降级决策记录在fallback_log,供 SRE 团队分析容量瓶颈。

关键点在于:model_fallback模块完全不知道模型内部怎么工作,它只消费指标、做路由决策、记录日志。它的存在,让业务代码永远只需写harness.execute(task),不用操心“现在该用哪个模型”。

实操心得:三十六个模块不是越多越好,而是“刚好够覆盖所有已知故障域”。我们曾试图合并audit_loggerevent_bus,结果发现审计日志必须 100% 可靠(哪怕 event bus 挂了也要落盘),而事件总线可以容忍部分丢失——这是两个完全不同的可靠性等级,强行合并只会让两者都不可靠。模块划分的终极标准,是“当这个模块挂了,影响范围是否可控、修复责任是否清晰”。

4. 从设计到落地:一个真实模块的完整实现闭环

光讲理论容易飘,我拿prompt_injector模块为例,带你走一遍从需求、设计、实现到线上验证的完整闭环。这个模块解决的是热搜词里反复出现的chatgpt 无法加载 config.toml类问题——不是配置文件坏了,而是模型在初始化时没收到必要的 system prompt,导致后续所有交互都偏离预期。

4.1 需求来源:一次真实的线上事故

某天下午 2:17,客服 Agent 突然开始对所有用户回复“抱歉,我无法理解您的问题”。SRE 查日志发现,所有请求的model.invoke()都返回空字符串。回溯发现,当天上午运维更新了模型服务,但忘了同步更新 Harness 的 config.toml 中的system_prompt_template字段。模型启动时没拿到 system prompt,进入无状态模式。

传统做法是加个配置校验脚本。但我们发现,问题本质是:system prompt 是业务逻辑的一部分,不该和模型连接参数混在同一配置文件里prompt_injector就是为此诞生。

4.2 模块设计:三层注入策略

prompt_injector不是简单地拼接字符串,而是分三层注入,每层解决不同问题:

  • Layer 1:全局基础 Prompt(Global Base Prompt)
    由 Harness 启动时加载,定义 Agent 的根本身份和底线,如:

    你是一个企业级客服助手,必须遵守:1. 不生成代码;2. 不提供医疗建议;3. 所有回答必须基于知识库;4. 用户问及价格时,必须调用 price_lookup 工具。

    这层永不变更,硬编码在src/core/prompt_injector/base.py

  • Layer 2:场景化 Prompt(Scenario Prompt)
    按 task_type 动态加载,存放在 Redis 的 Hash 结构中。例如task_type: "refund_request"对应:

    用户正在申请退款,请优先确认订单号,然后检查退货政策(调用 policy_check 工具),最后生成退款文案。
  • Layer 3:会话级 Prompt(Session Prompt)
    由业务方在调用harness.execute()时传入,如:

    harness.execute( task={ "type": "refund_request", "user_id": "u123", "input": "我要退昨天买的耳机" }, session_prompt="用户是 VIP 黄金会员,可享免运费退货" )

三层 prompt 最终按顺序拼接,中间用---[LAYER_BREAK]---分隔,确保模型能区分层级。

4.3 关键实现细节:为什么用 Redis 存场景 Prompt?

你可能想:场景 prompt 为什么不放配置文件或数据库?我们实测对比过:

存储方式加载延迟更新时效一致性保障适用场景
config file<1ms需重启强一致全局 base prompt
PostgreSQL~12ms秒级强一致低频变更的场景
Redis Hash~0.8ms毫秒级最终一致高频切换的场景(如促销期)

客服系统在双十一大促期间,每秒要切换 200+ 个场景(“预售定金”“尾款支付”“赠品发放”),PostgreSQL 根本扛不住。Redis 的HGETALL在集群模式下平均耗时 0.8ms,且支持热更新——运营同学在后台改完,300ms 内全量生效。这就是选型背后的硬数据。

4.4 线上验证:如何证明它真的解决了问题?

上线后,我们做了两件事验证效果:

  • 混沌测试:用 Chaos Mesh 主动 kill Harness 的 config loader 进程,模拟“config.toml 加载失败”。结果prompt_injector仍能从 Redis 加载场景 prompt,全局 base prompt 从代码加载,服务零中断;
  • 灰度发布:对 5% 流量启用新 prompt 注入,对比旧版。关键指标变化:
    • system_prompt_missing_error从 127 次/天 → 0 次/天;
    • tool_call_accuracy(正确调用工具的比例)从 82.3% → 94.7%;
    • first_response_time平均降低 310ms(因为模型不再因缺少指令而反复追问)。

踩坑提醒:prompt_injector最初版本把三层 prompt 直接拼成一个长字符串,结果模型在长 prompt 下注意力分散,对 Layer 3 的会话级指令响应率反而下降。后来我们改成用 XML 标签包裹各层:<global>...</global><scenario>...</scenario><session>...</session>,并训练了一个 tiny classifier 专门识别标签,准确率提升到 99.2%。这说明:对 LLM 的输入,结构化远比长度重要。

5. 架构演进:从单体 Harness 到分布式 Agent Fabric

当你的 Harness 稳定运行在 12 个业务线、日均处理 4700 万次 Agent 调用后,新的挑战就来了:model_fallback模块要实时聚合 17 个模型 endpoint 的指标,audit_logger每秒写入 23000 条日志,context_manager的 Redis 集群内存使用率常年 92%。单体 Harness 开始成为瓶颈。

我们没有选择“把 Harness 重写成微服务”,而是走向了Agent Fabric——一种基于 Harness 内核的分布式架构。核心思想是:Harness 仍是每个 Agent 实例的本地内核,但关键模块升级为可插拔的远程服务。

5.1 Fabric 的三层结构

  • Edge Layer(边缘层):每个业务服务部署一个轻量 Harness(<5MB),只含core_executortool_routerprompt_injector等低延迟模块。它负责快速决策、本地工具调用、短 context 管理。
  • Fabric Layer(织网层):一组独立部署的 Service Mesh,包含:
    • fabric-model-router:集中式模型容量调度,接收所有 Edge 的指标上报,计算全局最优路由;
    • fabric-audit-bus:Kafka 集群 + Flink 实时处理,聚合全链路审计事件;
    • fabric-context-store:基于 TiKV 的分布式 context 存储,支持 PB 级状态持久化。
  • Control Plane(控制平面):统一配置中心,用 GitOps 管理所有 Harness 实例的 YAML 配置、Prompt 版本、Tool Schema。

5.2 关键迁移策略:渐进式替换,零停机

我们花了 8 周完成迁移,策略是“模块化下沉”:

  • 第 1 周:将model_fallback模块从 Edge 的本地逻辑,改为调用fabric-model-router的 gRPC 接口。旧逻辑作为 fallback 保留;
  • 第 3 周:audit_logger改为异步发送到fabric-audit-bus,本地只保留 5 分钟 buffer;
  • 第 6 周:context_managerstate_persister切换到fabric-context-store,同时保持 Redis 作为二级缓存;
  • 第 8 周:移除所有 fallback 逻辑,全量切到 Fabric。

全程无一次服务中断。最妙的是,业务方完全无感——他们调用的还是harness.execute(),只是背后实现变了。

5.3 为什么不是“Harness 微服务化”?

很多团队一遇到性能瓶颈,第一反应就是“把 Harness 拆成 model-service、tool-service、audit-service”。我们试过,结果灾难性:

  • 网络延迟爆炸:一次 Agent 执行要跨 7 次服务调用,P99 延迟从 1.2s 涨到 4.7s;
  • 故障传播:tool-service一个 bug 导致所有 Agent 卡在on_tool_callhook;
  • 运维复杂度翻倍:12 个业务线要维护 84 个微服务实例。

Fabric 的本质是分层解耦:Edge 层保证低延迟和强隔离,Fabric 层提供共享能力,Control Plane 保证配置一致性。它不是把 Harness 拆开,而是让 Harness 在不同规模下,以不同形态存在。

个人体会:架构设计最难的不是画出多漂亮的图,而是判断什么时候该“做加法”(加模块),什么时候该“做减法”(删抽象)。我们曾经为prompt_injector设计过“动态 Prompt 编排引擎”,支持 if/else/loop,结果发现 92% 的业务场景只需要三层静态注入。砍掉那 3000 行代码后,模块稳定性提升了 3 倍。真正的架构师,要敢于对炫技说不。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询