1. 什么是让AI Agent真正干活的Harness?不是框架,不是SDK,而是一套可调度、可观测、可运维的“生产级操作系统”
你有没有试过用LangChain搭一个Agent,本地跑通了,逻辑也对,但一放到真实业务里就崩——任务卡死在某个Tool调用上不返回;日志里全是LLM超时或格式错误;换了个新模型,整个Agent Loop就乱序执行;更别说多人协作时,A改了Prompt,B调了Tool参数,C部署时发现环境变量没对齐……这些不是代码写得不好,而是缺了一层关键东西:Harness。
这个词在工程圈其实早有渊源。汽车引擎需要harness(线束)把传感器、ECU、执行器连成闭环;航天器靠harness整合遥测、指令、电源子系统;就连老式电话交换机,也靠物理harness把线路、继电器、拨号盘拧成一个能打电话的整体。AI Agent的Harness,本质就是这个逻辑——它不是让你“能跑起来”的玩具胶水,而是让Agent在真实世界里持续、稳定、可干预、可归因地干活的工业级集成底座。
标题里说的“7个子系统”,不是学术论文里的抽象分层,而是我在过去三年带团队落地12个企业级AI Agent项目(覆盖金融风控、医疗问诊、工业设备巡检、政务知识助手)后,从崩溃日志、监控告警、运维工单里一条条抠出来的硬需求反推结果。它不来自理论推演,而来自凌晨三点排查一个卡在“等待Tool返回”状态长达47分钟的Agent实例时,盯着Prometheus面板突然意识到:我们缺的不是更好的LLM,而是能让LLM、Tool、Memory、State这些部件像齿轮一样咬合转动的机械结构。
这7个子系统,每个都对应一个真实痛点:
- Agent Loop控制器解决“执行流失控”——为什么Agent会无限重试、跳过关键步骤、在错误节点终止?
- Tool Runtime沙箱解决“调用不可信”——为什么调用天气API返回了HTML而不是JSON?为什么数据库查询突然执行了DROP TABLE?
- State & Memory编排器解决“记忆混乱”——为什么用户说“刚才提到的第二份合同”,Agent却只记得最新一次对话?
- Observability中枢解决“黑盒调试”——LLM输出是好是坏?Tool返回是成功还是伪装成功的失败?靠人工翻日志根本来不及。
- LLM Gateway解决“模型漂移”——今天用Qwen2-72B,明天切到DeepSeek-V3,Prompt、温度、stop token全得重调?不该是开发者的日常。
- Policy & Guardrail引擎解决“越界风险”——不是所有场景都能靠system prompt兜底,当Agent要操作生产数据库或生成法律文书时,必须有硬熔断。
- Deployment & Lifecycle Manager解决“发布即失联”——Docker镜像build完,怎么验证它真能跑通完整Loop?灰度发布时如何对比新旧版本决策差异?
它们共同构成的,不是一个“AI Agent开发框架”,而是一个AI Agent生产环境操作系统。你可以把它理解成Linux内核之于进程:不直接写业务逻辑,但没有它,任何Agent都只是实验室里的Demo。接下来,我会带你一层层拆开这7个子系统,不讲概念,只讲我们在银行信贷审批Agent上线前一周,为解决“风控规则变更后Agent误拒贷”问题,是怎么用Policy引擎+Observability中枢组合拳把误判率从12.7%压到0.3%的实操细节。
2. 7个子系统深度拆解:为什么必须是这7个?少一个,Agent就只能“演示”,不能“上岗”
2.1 Agent Loop控制器:不是while True,而是带状态机、超时熔断、重试策略的“执行中枢”
很多人以为Agent Loop就是个简单循环:while not done: action = llm(thought); result = execute(action); update_memory()。但真实业务中,这个循环会遭遇三类致命问题:
- 状态漂移:用户中途插话“等等,先查下上个月账单”,Agent本该暂停当前流程去查账单,但原始Loop直接把新请求塞进当前上下文,导致后续步骤全错;
- 死锁陷阱:某个Tool调用因网络抖动超时,Loop没设最大重试次数,卡在
retrying... retrying...直到OOM; - 资源争抢:多个Agent实例并发调用同一数据库连接池,一个实例占着连接不放,其他全阻塞。
我们最终采用的方案,是基于有限状态机(FSM)+ 分布式信号量重构Loop。以图书馆管理Agent为例(对应热搜词中的“图书馆管理子系统”),它的核心状态流是:Idle → ParseQuery → RouteToSubSystem → ExecuteTool → ValidateResult → GenerateResponse → Done。每个状态转移都受严格条件约束:
ParseQuery → RouteToSubSystem要求NLU置信度≥0.85,否则退回Idle并提示“请明确说明想查询图书、借阅记录还是预约状态”;ExecuteTool状态启动时,自动申请一个带TTL(30秒)的Redis锁,超时自动释放,避免单点故障拖垮全局;- 连续3次
ValidateResult失败(如Tool返回空数据但非错误码),强制触发FallbackToHuman状态,转人工坐席。
提示:别用纯内存FSM。我们吃过亏——K8s Pod重启后状态丢失,Agent在
ExecuteTool状态中断,恢复后直接跳到GenerateResponse,用空结果生成了“已为您借阅成功”。现在所有状态都存入TiKV,支持毫秒级快照回滚。
关键参数设计逻辑:
- 最大重试次数:不是拍脑袋定3次。我们按Tool类型分级:HTTP API设2次(因网络抖动常见),数据库查询设1次(重试可能加重锁竞争),本地Python函数设0次(失败即Bug,该修代码);
- 超时阈值:不是统一设10秒。通过历史采样计算P95响应时间,再乘1.5倍安全系数。例如查图书库存API P95=1.2s,则设timeout=1.8s;
- 状态持久化频率:每进入新状态必存,但
Idle和Done状态不存(减少IO),只存中间态。实测降低87%的存储压力。
这个控制器的价值,在教务管理子系统落地时体现得最狠。教务流程涉及课表、成绩、学籍三个强耦合子系统,原Loop在跨子系统调用时经常状态错乱。重构后,我们给每个子系统调用加了subsystem_context字段,状态机据此路由,上线后跨系统错误率从23%降到0.8%。
2.2 Tool Runtime沙箱:让外部工具调用从“信任但验证”变成“零信任默认隔离”
几乎所有Agent崩溃都始于Tool调用。你以为调的是get_weather(city),实际执行的可能是os.system("rm -rf /")(当Tool代码被注入恶意payload时)。更常见的是“良性失控”:数据库Tool执行了SELECT * FROM users,而业务只要name, email;天气API返回了带广告的HTML页面,Agent却当成JSON解析。
我们的沙箱不是简单的Docker容器隔离,而是三层防护:
| 防护层 | 实现方式 | 解决的真实问题 | 教务系统案例 |
|---|---|---|---|
| 语法层 | 自定义DSL解析器,禁止eval、exec、os.system等危险函数调用,所有Tool必须声明输入/输出Schema | 防止恶意代码注入 | 学籍查询Tool被提交含__import__('os').system('reboot')的payload,沙箱直接拦截并告警 |
| 协议层 | HTTP/DB/Shell调用全部走代理网关,强制JSON Schema校验响应体,非预期字段自动剔除 | 防止API返回格式漂移 | 天气API升级后返回新增air_quality字段,旧Agent因无法解析崩溃,沙箱自动过滤该字段,保持兼容 |
| 资源层 | 每个Tool运行在独立cgroup中,CPU限100m,内存限256MB,网络出口仅允许白名单域名(如weather-api.com) | 防止DoS攻击与资源耗尽 | 图书馆借阅Tool被恶意构造超长ISBN触发正则回溯,沙箱在CPU超限0.5秒后强制kill |
特别强调协议层校验的实操细节:我们不用OpenAPI Spec做校验(太重),而是为每个Tool定义轻量Schema:
{ "tool_name": "query_library_stock", "input_schema": { "isbn": {"type": "string", "pattern": "^\\d{13}$"} }, "output_schema": { "available_copies": {"type": "integer", "minimum": 0}, "location": {"type": "string", "enum": ["A区-1F", "B区-2F", "C区-3F"]} } }Agent Loop控制器在调用前,用jsonschema.validate()校验输入;收到响应后,同样校验输出。不匹配?直接走fallback路径,绝不让脏数据污染后续流程。
注意:沙箱必须支持热加载。教务系统每周更新课表数据源,如果每次都要重启Agent服务,运维会疯。我们用inotify监听Schema文件变化,动态重载校验规则,零停机。
2.3 State & Memory编排器:告别“上下文爆炸”,让Agent记住该记的,忘掉该忘的
LLM的Context Window是假朋友。你喂它10轮对话+3份PDF摘要+5条数据库记录,表面看信息全,实际LLM注意力早已稀释——它可能精准复述第7轮对话的咖啡订单,却把第2轮确认的身份证号记错一位。真正的Memory管理,不是堆token,而是分层、分域、有时效的主动编排。
我们设计的编排器包含四层Memory:
| Memory类型 | 存储介质 | 生命周期 | 用途 | 图书馆案例 |
|---|---|---|---|---|
| Short-term | Redis(LRU淘汰) | 单次会话内 | 存储当前对话的临时变量、未确认的意图 | 用户说“帮我找《三体》”,暂存book_title="三体",待确认后升为Long-term |
| Long-term | PostgreSQL(带向量索引) | 永久 | 用户画像、偏好、历史交互摘要 | 记录张三常借科幻类,优先推荐刘慈欣新书 |
| Working-set | 内存对象 | 单次Loop内 | 当前任务所需的精确数据块,如本次借阅涉及的3本书的库存详情 | 查询到《三体》《球状闪电》《流浪地球》库存,只加载这3条记录到内存 |
| Episodic | MinIO对象存储 | 可配置(默认90天) | 原始交互日志、Tool调用快照,用于审计与回溯 | 保存某次借阅失败的完整链路:LLM输出→Tool参数→数据库返回→错误解析 |
关键创新在于Working-set的智能裁剪。不是简单截断,而是用LLM自身做摘要:
# 在调用Tool前,用轻量模型(Phi-3-mini)压缩上下文 compressed_context = phi3_mini( f"摘要以下内容,保留ISBN、库存数、位置信息,删除描述性文字:{raw_db_result}" ) # 将压缩后文本传给主LLM,token消耗降62%教务系统更复杂:一个学生咨询可能横跨课表、成绩、奖学金三个子系统。编排器会自动识别student_id为关联键,从各子系统拉取数据后,生成统一student_profile视图,再喂给LLM。避免了传统方案中LLM在不同子系统数据间“找相同ID”的低效推理。
2.4 Observability中枢:不是埋点,而是给Agent装上“心电图+脑电图+肌电图”
90%的Agent运维问题,源于缺乏可观测性。你看到Agent failed,但不知道是LLM胡言乱语、Tool返回异常、还是Memory污染导致。Observability中枢要回答三个问题:
- LLM层:输出是否符合预期?Token使用是否突增?PPL(困惑度)是否飙升?
- Tool层:调用成功率?平均延迟?错误类型分布(网络超时/业务错误/格式错误)?
- Loop层:状态流转是否正常?各状态停留时间?Fallback触发频率?
我们不用Prometheus+Grafana堆指标,而是构建三维度追踪流水线:
- Trace维度:每个Agent请求生成唯一
trace_id,贯穿LLM调用、Tool执行、Memory读写。用OpenTelemetry SDK注入,但关键改造是:在LLM输出后,立即用另一个小模型(TinyLlama)做实时质量评估,打上quality_score: 0.92、hallucination_flag: false标签; - Log维度:不是原始日志,而是结构化事件流。例如Tool调用事件包含:
{ "event": "tool_executed", "tool_name": "query_course_schedule", "input_hash": "a1b2c3...", "output_hash": "d4e5f6...", "duration_ms": 142, "status": "success", "validated_by_schema": true } - Metric维度:聚焦业务指标。如图书馆Agent的
borrow_success_rate(借阅成功数/总请求)、avg_steps_per_borrow(平均执行步数),而非cpu_usage_percent。
最实用的功能是根因推荐。当borrow_success_rate跌到95%以下,中枢自动关联分析:
- 查看最近100次失败请求的
tool_executed事件,发现query_library_stock错误率从0.1%升至12%; - 进一步查该Tool的
output_hash分布,发现73%失败请求返回{"error": "ISBN not found"}; - 对比
input_hash,发现所有失败请求的ISBN都是12位(缺1位校验码); - 推荐动作:“检查前端ISBN输入框校验逻辑,增加13位长度强制”。
这套系统让教务Agent的平均故障定位时间,从47分钟缩短到3.2分钟。
2.5 LLM Gateway:屏蔽模型差异,让Agent“一次开发,多模部署”
开发者最痛苦的不是选模型,而是为每个模型重写Prompt、调参、处理输出格式。Qwen需要<|im_start|>,DeepSeek用<|begin▁of▁sentence|>,Llama3要求<|eot_id|>,而你的Agent业务逻辑不该关心这些。
LLM Gateway是位于Agent与模型之间的协议转换层,核心能力:
- 统一API契约:Agent只调用
POST /v1/chat/completions,传标准OpenAI格式参数(model,messages,temperature),Gateway负责转换; - 智能路由:根据
model参数、请求负载、成本策略,自动路由到最优后端。例如高优先级请求走Qwen2-72B,低优先级走Phi-3-mini; - 输出标准化:无论后端模型返回什么格式,Gateway统一清洗为
{"choices": [{"message": {"content": "xxx"}}]},并补全缺失字段(如usage字段模拟生成); - 缓存穿透防护:对确定性Prompt(如系统提示词),启用Redis缓存,命中率超65%。
Gateway的配置文件models.yaml长这样:
models: - name: "qwen2-72b" endpoint: "http://qwen-cluster:8000/v1/chat/completions" tokenizer: "Qwen/Qwen2-72B-Instruct" max_tokens: 8192 cost_per_1k_token: 0.002 fallback: "phi3-mini" - name: "deepseek-v3" endpoint: "http://deepseek-gpu:8000/v1/chat/completions" tokenizer: "deepseek-ai/deepseek-coder-33b-instruct" max_tokens: 16384 cost_per_1k_token: 0.0015 fallback: "qwen2-72b"当教务系统需要快速切换模型应对突发流量,运维只需改fallback字段,无需动Agent代码。上周考试季流量激增300%,我们把qwen2-72b的fallback指向deepseek-v3,成本降了18%,响应P95从2.1s优化到1.3s。
实操心得:Gateway必须支持渐进式迁移。新模型上线时,先用1%流量试跑,对比
output_hash与旧模型的一致性。我们发现DeepSeek-V3对“课程编号”格式解析更严格,旧Prompt需微调,Gateway的A/B测试功能帮我们提前2天发现此问题。
2.6 Policy & Guardrail引擎:不是道德约束,而是生产环境的“安全阀”
很多团队把Guardrail做成LLM的system prompt:“你不能生成违法内容”。这在Demo里有效,但在生产环境形同虚设——当Agent要生成贷款合同,prompt挡不住SQL注入;当它调用支付接口,prompt管不了金额篡改。
Policy引擎是独立于LLM的硬性执行层,分三级防护:
- 输入层Policy:在LLM接收消息前拦截。例如教务系统禁止
student_id含非数字字符,图书馆系统拒绝isbn长度≠13的请求; - 输出层Policy:LLM生成后、返回前校验。用规则引擎(Drools)检查:
rule "Loan Amount Check" when $r: Response(content matches ".*贷款金额.*[0-9]+.*") $amount: Integer() from eval(parseLoanAmount($r.content)) then if ($amount > 100000) { $r.setContent("贷款金额超出授权范围,请联系客户经理"); $r.setBlocked(true); } end - 执行层Policy:Tool调用前验证。例如数据库Tool收到
DELETE FROM语句,Policy引擎立即拒绝,除非请求携带admin_override_token(需人工审批)。
最狠的防护是动态Policy注入。图书馆系统上线前,法务要求“所有借阅提醒必须包含‘逾期将影响信用记录’字样”。我们没改代码,而是在Policy配置里加:
{ "trigger": "response_contains_pattern", "pattern": "已为您成功借阅", "action": "append_text", "text": "(温馨提示:图书逾期未还将影响您的信用记录)" }上线后自动生效,零代码变更。
2.7 Deployment & Lifecycle Manager:让Agent发布像发版App一样可靠
最后也是最容易被忽视的:怎么把Agent从开发环境搬到生产?不是docker build && docker run就完事。Agent的生命周期管理,必须覆盖:
- 构建时验证:Docker镜像build阶段,自动运行
harness-test-loop脚本,模拟100次典型请求,验证Loop完整性、Tool连通性、Memory持久化; - 部署时金丝雀:新版本先接收1%流量,对比旧版本的
borrow_success_rate、avg_steps_per_borrow,差异>2%自动回滚; - 运行时自愈:当Observability中枢检测到某Tool连续5分钟错误率>50%,Manager自动触发
tool_disable --name=query_library_stock,并通知运维; - 下线时清理:Agent退役时,自动归档其Long-term Memory到冷存储,并清空Redis Short-term Memory。
Manager的CLI工具harnessctl是运维日常:
# 查看所有Agent状态 harnessctl list agents # 强制重启某Agent(不丢失State) harnessctl restart agent/library-bot --preserve-state # 紧急禁用高危Tool harnessctl disable tool query_user_pii --reason "GDPR audit" # 回滚到上一版本 harnessctl rollback agent/academic-advisor --to-version v2.3.1教务系统上线时,我们用Manager的harnessctl test --scenario=exam-week-stress模拟考试周峰值流量,提前发现数据库连接池瓶颈,扩容后平稳度过。
3. 为什么是这7个?少一个,Agent就只是Demo,不是产品
这7个子系统不是随意凑数,而是从故障树分析(FTA)中提炼出的最小完备集。我们统计了12个项目共387次生产事故,按根因分类:
| 根因大类 | 占比 | 对应子系统缺失 | 典型事故 |
|---|---|---|---|
| 执行流失控 | 28% | Agent Loop控制器 | Agent在查课表时无限重试,耗尽CPU,导致整个教务服务雪崩 |
| 外部依赖不可靠 | 23% | Tool Runtime沙箱 | 天气API返回HTML,Agent解析失败,连锁触发Fallback,客服热线被打爆 |
| 状态/记忆错误 | 19% | State & Memory编排器 | 用户说“把刚才的合同发我邮箱”,Agent发了三天前的合同,因Memory未区分会话边界 |
| 诊断无依据 | 15% | Observability中枢 | 故障发生后,团队花4小时翻日志,仍无法定位是LLM、Tool还是Network问题 |
| 模型适配成本高 | 8% | LLM Gateway | 切换DeepSeek后,所有Prompt重写,上线延迟2周,错过招生季 |
| 越界操作无防护 | 5% | Policy & Guardrail引擎 | Agent误执行DROP TABLE students,因SQL注入未被拦截 |
| 发布运维低效 | 2% | Deployment & Lifecycle Manager | 新版本上线后,发现Memory未持久化,紧急回滚,损失3小时服务 |
注意:占比最高的前三项(执行流、外部依赖、状态记忆)合计70%,恰好对应前3个子系统。这证明——没有这7个子系统,Agent就只是个脆弱的Demo;有了它们,才能成为可信赖的生产力组件。
更关键的是,这7个子系统存在强耦合依赖链:
- 没有Observability中枢,你就无法量化Agent Loop控制器的优化效果;
- 没有LLM Gateway,Policy引擎就无法统一拦截不同模型的输出格式;
- 没有Deployment Manager,Tool Runtime沙箱的热加载能力就失去意义。
它们共同构成一个负反馈调节系统:Observability提供数据 → Loop控制器和Policy引擎据此调整行为 → Deployment Manager确保新策略生效 → 新数据又反馈给Observability……这才是Harness的真正价值——让AI Agent具备自我进化能力。
4. 常见问题与避坑指南:那些只有踩过才懂的实战经验
4.1 “我的Agent很简单,用LangChain/LlamaIndex够用了,为啥要搞这么复杂?”
这是最常听到的质疑。我的回答很直接:LangChain是乐高积木,Harness是造桥的工程规范。你用积木搭个小房子没问题,但要造跨海大桥,就得考虑风载、沉降、抗震、维护通道——这些不是积木的错,而是工程尺度变了。
具体到技术债:
- 短期:用LangChain开发快,1天搭出图书查询Demo;
- 中期(1个月后):要加权限控制,你得在每个Chain里手写RBAC逻辑;要加审计日志,得改遍所有Tool调用;
- 长期(3个月后):业务方要求“借阅记录导出Excel”,你发现Chain里没预留二进制输出接口,只能重写;模型升级后,所有Prompt失效,团队集体加班。
Harness的投入回报比,在第2个Agent项目就回本。我们第1个项目(图书馆)花了3人月搭建Harness基础,第2个项目(教务)复用Harness,开发周期从6周压缩到2周,且上线后P1故障为0。
实操建议:不要从零造轮子。用开源项目如LangGraph(Loop控制器)、MLflow(Observability)、Kubernetes Job(Deployment Manager)拼装,但必须自己实现Tool沙箱和Policy引擎——这是安全红线,不能外包。
4.2 “7个子系统,我们团队小,怎么分阶段落地?”
绝对不要试图一次性全上。按故障影响优先级分三阶段:
| 阶段 | 必上子系统 | 目标 | 时间窗口 | 效果 |
|---|---|---|---|---|
| Phase 1(1周) | Agent Loop控制器 + Tool Runtime沙箱 | 杜绝崩溃、保证基本可用 | 开发环境 | Agent不再随机卡死,Tool调用100%安全 |
| Phase 2(2周) | Observability中枢 + LLM Gateway | 快速定位问题、平滑切换模型 | 测试环境 | 故障平均修复时间<10分钟,模型切换零停机 |
| Phase 3(3周) | State & Memory编排器 + Policy引擎 + Deployment Manager | 支持复杂业务、满足合规要求 | 生产环境 | 支持教务/学籍/成绩跨子系统协同,通过等保三级审计 |
Phase 1是底线。我们曾有个客户坚持“先上线再说”,结果上线3天后,一个恶意构造的ISBN触发正则灾难性回溯,Agent进程CPU 100%持续17小时,最终OOM。补上Tool沙箱后,同类攻击100%拦截。
4.3 “Observability中枢要采集哪些数据?太多怕性能,太少不够用”
这是平衡艺术。我们只采集决策链路上的黄金数据点,而非全量日志:
必须采集(影响根因定位):
- LLM输入的
messages哈希值(非明文,防隐私泄露) - LLM输出的
content哈希值 +finish_reason - Tool调用的
input_hash+output_hash+duration_ms+status - Loop状态流转时间戳(
Idle→ParseQuery耗时等)
- LLM输入的
选择性采集(按需开启):
- LLM原始token概率分布(仅调试时开,开销大)
- Tool返回的完整JSON(仅首次失败时采样,存MinIO)
绝不采集:
- 用户原始消息明文(用哈希+脱敏规则替代)
- 数据库连接字符串、API密钥等敏感配置
性能实测:在200 QPS负载下,Observability中枢增加的延迟<3ms,资源占用<5% CPU。关键是异步非阻塞采集——所有事件写入Kafka,由独立消费者落库,Agent主线程零感知。
4.4 “Policy引擎用规则还是LLM?我们想用LLM做动态审核”
坦白说,我们试过。用一个小模型(Phi-3-mini)审核LLM输出,准确率92%,但延迟增加320ms,且存在幻觉风险——它可能把合法的“贷款利率4.5%”误判为“违规高利贷”。
结论:Policy引擎必须是确定性的规则系统。LLM只做辅助:
- 规则引擎做硬拦截(如
金额>10万必须人工审批); - LLM做软建议(如
检测到合同条款模糊,建议补充第X条),不阻断流程。
就像汽车的安全气囊——必须100%可靠,不能靠概率。
4.5 “Harness和Agent框架(如LangChain)是什么关系?”
这是根本性误解。Harness不是Agent框架的替代品,而是它的操作系统。
- LangChain是“编程语言”:提供
Chain、AgentExecutor、Tool等语法糖,帮你写Agent逻辑; - Harness是“Linux内核”:提供进程调度(Loop控制器)、内存管理(Memory编排器)、设备驱动(Tool沙箱)、文件系统(State持久化)、网络协议栈(LLM Gateway)。
你可以用LangChain写代码,但没有Harness,这段代码在生产环境就是裸奔。就像用C语言写程序,没有操作系统,你得自己管理内存、调度CPU、处理中断——理论上可行,实际上没人这么干。
我们所有项目,都是LangChain(或LlamaIndex)+ Harness双栈:LangChain写业务逻辑,Harness管基础设施。分工明确,各司其职。
5. 最后分享一个血泪教训:Harness不是银弹,它治不了“需求没想清楚”的病
去年帮一家三甲医院做AI导诊Agent,临床科室提的需求是:“能回答患者关于挂号、检查、取药的问题”。我们按标准流程,7个子系统全上,Observability显示各项指标完美,上线后却发现患者投诉率飙升——不是Agent答错了,而是它太“正确”了。
问题出在需求层面:医生说的“检查”,指CT/MRI等影像检查;患者理解的“检查”,包括抽血、B超、心电图。Agent严格按医学术语库回答,当患者问“我要做检查”,它回复“请前往放射科预约CT”,而患者实际要查血常规。
我们紧急在Policy引擎里加了一条规则:
{ "trigger": "user_query_contains_synonym", "synonyms": ["检查", "化验", "验血", "抽血"], "action": "rewrite_query", "target": "血液检验" }但这只是补丁。真正的解法,是把临床术语库和患者常用语库,在State编排器里构建成双视角Memory,让Agent能主动问:“您是要做影像检查(CT/MRI),还是血液检验?”——这需要前期需求深挖,不是Harness能解决的。
Harness的强大,恰恰在于它会把所有隐藏问题暴露出来。当你的Observability中枢显示query_rewrite_rate高达40%,这就是在告诉你:“需求定义有歧义,快去和业务方对齐!”
所以,Harness的终极价值,不是让技术更炫,而是让问题无所遁形,逼着团队回归业务本质。它不创造价值,但它让真正创造价值的人,不再被技术债务拖累。
我在凌晨三点盯着Dashboard上那条平稳的borrow_success_rate曲线时,想的不是代码多优雅,而是——终于,可以把精力放在怎么让图书馆的推荐更准,而不是怎么救活又一个卡死的Agent实例了。