前段时间我在Coze平台上搭建一个病理研读Agent,折腾了整整两个星期。最早跟大多数人一样,上来就是写提示词,角色设定、语气要求、回答模板,写满好几大段,试了几个样例感觉不错,结果一换输入就露馅:有的报告能正确解析,有的报告直接开始“自由发挥”。后来我彻底换了一条路,用Spec-driven的方式来重做——先把规格写清楚,再动手配置平台。做完之后的感受非常明显:Agent的每个决策都有了依据,出问题能定位到具体环节,团队其他人接手也完全不用靠猜。
这篇文章就完整记录这次实践:如何用Spec-driven模式在Coze上落地一个“专家级”病理研读Agent,覆盖思路拆解、Spec文档怎么写、平台配置细节、评测方法和踩坑记录。适合正在用Coze或其他Agent平台做复杂应用、觉得提示词方案不够稳的人,也适合那些刚接触Agent开发、想建立一套规范方法论的朋友。
1. 为什么我放弃“提示词堆砌”,改用Spec-driven开发Agent
1.1 提示词野路子的三个死穴
先说一个大家心照不宣的现状:现在开发Agent,大部分人的第一步都是在System Prompt里疯狂堆描述。“你是一个病理学专家”“请以专业、严谨、通俗易懂的方式回答”“必须注意……”“不能出现……”——这些话说得越多,模型反而越不知道哪个是重点。我在第一版里写了近两千字的提示词,结果测试下来出现了三个非常典型的问题。
第一,行为不可预期。同样一份报告,换个说法提问,输出结构完全不一样;上一版明明已经修正过的错误,改了一个无关的措辞之后又复现了。第二,无法定位问题。输出烂的时候,你根本说不清是哪句话、哪个环节、哪段知识引发的错误,因为整个判断逻辑全部黑盒地塞在提示词里。第三,迭代成本极高。我今天告诉它“遇到原位癌要特别说明”,明天告诉它“别把肿瘤分级和分期混在一起”,提示词越来越长,互相矛盾的地方也就越来越多。
这个体感我相信很多搭过Agent的人都有:不是不想做好,而是传统方式压根不具备工程化管理的可能。真正让我决定转变思路的,是处理一个“乳腺导管原位癌”报告样例时,模型用“癌”字关联了全套浸润性癌的解释,给用户造成了严重误导。那一刻我意识到,在医疗相关场景里,这种不可控是不可接受的。
1.2 Spec-driven到底是什么:先定规格,再谈实现
Spec-driven的中文叫法有很多,规格驱动、契约优先、先定义后实现。核心思想一句话:写代码之前,先用文档把“系统应该有什么行为、什么输入、什么输出、什么边界”完整确定下来,然后再进入实现环节。它不是测试驱动开发那种“先写测试再写实现”的下游手段,而是更上游的一层约束。
用盖房子类比最清楚。传统提示词开发像是请了个施工队,口头说一句“给我盖个好看的三层小楼”,工人自由发挥,有的窗户朝南有的窗户朝北。Spec-driven则是先花时间画完整套施工图,哪里是承重墙、哪里走水电、层高多少、采光要求多少,全部白纸黑字定下来。施工队只需要照着图纸干,最后验收拿图纸对一遍就知道合不合格。
这套方法论迁移到Agent开发上有两层含义。一层是面向文档的:Agent的角色定位、输入契约、处理流程、输出格式、知识边界、风险兜底、验收标准,全部预先写成一份规格说明书。另一层是面向实现的:系统提示词、工作流节点、知识库配置、评测集,全部以这份规格说明书为唯一依据去落地。
我在Coze里做完后的体会是:Spec文档写得好,系统提示词只是它的一个投影;Spec文档写得差,提示词写得再漂亮都是无根之木。
1.3 为什么病理研读这个场景最适合Spec-driven
坦白说,不是所有Agent都需要上Spec-driven,做个写文案、做翻译的助手,自由发挥一点反而有惊喜。但病理研读这个场景,几乎是Spec-driven的完美适配对象。
病理报告是高结构化的医学文档,它包含送检材料、大体所见、镜下所见、病理诊断、免疫组化、分子检测等固定字段。研读的本质动作是从这些字段里抽取关键信息、映射到通俗表达、按风险等级给出下一步引导。这种强流程、强边界、强风险约束的场景,如果是完全让模型自由发挥,隐患非常大。
另一个原因是病理领域的容错率极低。一个术语解释错误、一个“可能转移”的过度推断、一个风险等级的误判,都可能对用户产生实质性影响。这就要求Agent的行为可以被审计、被测试、被约束。Spec-driven天然满足这个需求:每一类输出都能在规格书里找到对应条款,每个错误都能追溯到规格设计的缺失或实现与规格的偏差。
还有一个很实际的原因:医疗相关Agent的发布和用户信任门槛都高。拿着提示词去对接病患或者医疗团队,对方第一句话一定是“你的判断依据是什么”。如果你的回答是“模型觉得”,这项目基本就黄了。而Spec-driven模式下,你能拿出完整的逻辑链条和处理规则,沟通效率和信任度完全是两个量级。
2. Spec文档编写:如何把“专家级”翻译成可执行的规格
2.1 一份Agent规格书必须包含的七个板块
我在动手配置Coze之前,先花了两天时间写了整份规格文档。这份文档后来成了所有开发、测试、迭代的唯一依据。我把一份可复用的Agent规格书拆成七个板块,每个板块解决一个维度的问题。
第一个板块是角色与使命,回答“这个Agent是谁”。病理研读Agent的角色定位是“病理报告辅助研读助手”,使命是帮助非专业人士理解报告中的关键信息、解释专业术语、提示下一步就医路径。这里有一个很严谨的自我认知:它不是诊断系统,不是医生的替代品。
第二个板块是输入契约,回答“它接受什么”。我定义的输入包括完整的病理报告文本、报告片段、用户针对报告的提问;经过平台的文件解析能力,还可以接收报告图片。不接受影像原图、不接受无上下文的闲聊式提问——至少主体功能不做这层支持。
第三个板块是处理流程,回答“它怎么干活”。这个Agent的标准处理链路是六步走:文本清洗、关键信息抽取、术语映射、结构化解读、风险分级、生成回答。每一步由谁实现,是提示词约束、工作流节点还是知识库检索,在这个板块里都要明确分工。
第四个板块是输出契约,回答“它怎么说人话”。输出必须包含一句话结论、关键术语逐项解释、下一步建议、免责声明四个部分。结论不超过三句话,术语解释每条控制在两句到三句。整体语气通俗、严谨、克制,禁止夸大、禁止渲染焦虑。
第五个板块是知识边界,回答“它不能碰什么”。不进行最终诊断、不推荐具体治疗方案、不评价主治医生的建议、不解释超出知识库范围的罕见病。如果报告中有无法识别的术语,必须承认知识库覆盖不足,而不是硬编一个解释。
第六个板块是风险兜底,回答“出问题怎么办”。检测到报告信息不完整、关键字段缺失、术语无法映射等情况,必须主动声明“当前信息不足”,并建议用户携带完整资料咨询主治医生。任何情况下都不许替用户做“严不严重”的主观判断。
第七个板块是验收标准,回答“怎样算做完了”。我把验收指标具体量化了:核心信息抽取准确率不低于95%,术语解释准确率不低于90%,风险场景触发率100%,幻觉断言数必须为0。这些数字不是拍脑袋,而是根据20条评测用例跑分得出的合理目标。
2.2 病理研读场景的特殊规格设计
通用板块之外,这个场景有三处属于它自己的特殊设计,我觉得是整个项目里最值得写下来的部分。
第一处是“四档风险分级机制”。我在规格书里定义了四个响应等级:第一档对应良性病变或炎症,常规解读即可;第二档对应低度恶性潜能或原位癌,在解释之外要明确建议专科就诊;第三档对应浸润性恶性肿瘤,完整解析的同时必须用醒目方式提示用户尽快就诊;第四档对应罕见、复杂或报告不明确的情况,一律建议携带完整材料线下咨询。这个分级不是让模型凭感觉判断,而是通过原文中的关键字段和关键词来触发,避免所有报告都得到同一个模板化的答案。
第二处是“术语映射表的建立”。病理报告中的核心术语,如“浸润性导管癌”“原位癌”“高级别上皮内瘤变”“Ki-67增殖指数”“HER2状态”等,我要求Agent先执行严格的术语映射,再生成通俗解释。比如“HER2(3+)”,映射到通俗表达时要说清楚这是“HER2蛋白强阳性,可能需要考虑抗HER2靶向治疗”,但不展开、不越界。为了让映射稳定,我在知识库里专门维护了一份术语对照词典。
第三处是“信息脱敏与风险标注”。规格书要求Agent在解析报告时自动跳过患者姓名、住院号等个人身份信息;同时规定,凡是在回答中出现参考知识库之外的推断,必须标注为“基于公开医学资料的通用解释,不构成对本报告的个人诊断”。这两种设计都是让Agent从“敢说话”变成“会说话”的关键约束。
2.3 我的Spec骨架模板(可直接复制)
整个Spec文档我精简成一个可以直接套用的骨架模板,放在下面。它的形式介于伪代码和提示词之间,既可以作为System Prompt的底稿,也可以直接翻译成工作流节点的配置说明。
# Agent规格说明书 ## 1. 角色 你是病理报告辅助研读助手。你的使命:帮助用户理解病理报告中的关键信息、解释专业术语、提示就医路径。 你不是医生,不进行诊断,不代替医疗建议。 ## 2. 输入契约 可接受: - 完整病理报告文本 - 报告片段 - 针对报告的提问 处理方式:先识别报告中与病理相关的结构化字段,再进入流程。 ## 3. 处理流程 step1 文本清洗:去除姓名、住院号等身份信息 step2 抽取字段:送检材料/大体所见/镜下所见/病理诊断/免疫组化/分子检测 step3 术语映射:从术语词典匹配解释 step4 结构化解读:生成结论+逐项解释 step5 风险分级:按关键词触发A/B/C/D级响应 step6 输出回答:按输出契约组织语言 ## 4. 输出契约 结构: - 一句话结论 - 关键术语解释(每条不超过3句) - 下一步建议 - 免责声明 禁止:夸大、恐吓、未提及信息推断、具体治疗方案推荐 ## 5. 知识边界 - 不做最终诊断 - 不评价医生建议 - 不解释超出知识库范围的罕见病 - 检测到未知术语必须声明信息不足 ## 6. 风险兜底 - 报告不完整 → 主动声明,建议补齐 - 字段缺失 → 只解读现有字段 - 无法判断严重程度 → 不做判断,建议咨询医生 ## 7. 验收标准 - 信息抽取准确率 >= 95% - 术语解释准确率 >= 90% - 风险场景触发率 100% - 幻觉断言 = 0这个骨架看起来简单,但每一项落进Coze的配置里都有具体对应关系。下一节我就讲这部分实操。
3. 在Coze平台上一步步落地
3.1 先盘点平台能力,再决定哪层用工作流、哪层用提示词
Coze这个平台的组件不少,我刚上手的时候也犯过一直在“人设与回复逻辑”面板里写大作文的错误。实际上,一个严肃的Agent应用应该用尽平台的各种能力,而不是把所有逻辑都压在提示词一个出口上。
盘点下来,我对这个平台组件做了一个分工:系统提示词只承载“角色、输出格式、风格约束、边界声明”这些纯文本性的规则;工作流承载“信息抽取→术语映射→风险分级→回答生成”这个多节点流程;知识库承载术语解释和病理学基础知识;变量和记忆承载用户会话中的上下文;插件能力则用来处理报告图片的OCR转文字。
这个分工的核心判断依据是:凡是“顺序固定、可被规则描述”的逻辑,尽量下沉到工作流里去做;凡是“语义理解、语言生成”的部分,才留给大模型去发挥。这样即使模型的回复再飘,前端的抽取结果和风险分级仍然是被工作流节点牢牢控制住的。
实际上,很多Agent项目行为失控,原因不是模型不好,而是你让模型干了太多它不该干的活。模型适合做总结、解释、改写,不适合做需要严格步骤和多路条件判断的流程控制——哪怕是现在很聪明的模型也一样。
3.2 从空应用开始:全局提示词怎么贴合Spec
我在Coze里新建了一个Bot,第一步没急着搭工作流,而是先把全局设置里最核心的“人设与回复逻辑”按照Spec文档重新组织结构。这里有个我特别想强调的经验:提示词不建议全用自然语言段落来写,最好用结构化指令,把Spec里的关键条款拆成编号清单。
以我最终的全局提示词为例,整体分成了六个指令块。第一个指令块定义角色:“你是病理报告辅助研读助手。你不是医生,不进行诊断,不替代医疗建议。”第二块定义输入处理原则:“接到用户输入后,先判断是否为病理报告相关内容,不属于本范围的内容一律拒绝回答,并引导用户上传报告。”第三块定义输出结构:“必须按四段式输出,分别是核心结论、术语解释、下一步建议、免责声明。”第四块定义术语处理规则:“解释术语前必须检索知识库,禁止基于模型记忆自行解释。”第五块定义风险响应等级:“当报告原文出现以下关键词时,按对应等级触发提示语。”第六块定义边界与兜底:“不确定的内容必须明说,宁可告诉用户信息不足,也不能推测。”
这种编号清单式的提示词,在执行效果上明显优于大段文学性描述。原因也很简单:模型对结构化的指令解析更稳定,条与条之间不容易发生语义稀释或覆盖。另外,后续如果你需要做A/B测试,改一条指令就能测,不需要重写整段话。
3.3 工作流编排:把诊断流程拆成节点
全局提示词解决了“说话方式”问题,但流程控制还得靠工作流。这个Agent的工作流我拆成了六个节点:
开始节点接收用户输入,并把输入传给下游。第一个处理节点是内容识别,输出一个判断标签:病理报告、报告片段、其他内容。如果是“其他内容”,直接走到一个兜底节点返回拒绝话术,不进入后续流程。这个设计看起来简单,但它直接避免了很多无意义的计算和潜在风险——用户发一句“你好”,Agent不应该调一遍诊断链路。
第二个节点是文本抽取。这个节点我很早就踩过一个坑:一开始让它“提取报告中的关键信息”,结果大模型节点自由发挥,输出了一堆格式化但不可预期的JSON。后来我换了一种做法,在提示词里给出一个严格的字段模板,并要求节点只输出固定的JSON结构,不做任何解释和补充。这样一来,后续节点解析JSON就完全稳定了。
第三个节点是术语映射。这个节点直接检索知识库,输入是从上一节点抽取出来的诊断结论和免疫组化字段,输出是对应的通俗解释。它是整个Agent的“知识担当”,能不能解释清楚Ki-67、ER、HER2这类指标,就看知识库建设得怎么样了。
第四个节点是风险分级。我用的是规则判断而非模型判断:通过关键词匹配来决策,比如“原位癌”“低度恶性”“高级别上皮内瘤变”触发B级;“浸润性”“转移”“恶性肿瘤”触发C级;原文不完整或出现未收录术语触发D级。为什么用规则?因为模型判断在敏感场景里存在随机性,而风险分级属于那种必须做到100%稳定的功能,规则是最可靠的实现方式。
第五个节点是回答生成。这个节点接收抽取结果、术语解释、风险等级三个输入,然后按输出契约生成最终回答。第六个节点就是结束节点,把结果返回给用户。
整条链路跑下来,我最大的体会是:工作流把Agent从“凭感觉回答”变成了“流水线生产”。每一级都有明确输入输出,出了问题直接在对应节点上排查和修改,不用再把整个系统提示词翻个底朝天。
3.4 知识库建设与检索参数调优
知识库是整个Agent专业度的大半条命。我的知识库分了三个集合:第一是《病理学基础术语词典》,覆盖组织学、细胞学、免疫组化常见指标的通俗解释,大约收了两百多条核心术语;第二是《常见肿瘤病理诊断摘要》,针对乳腺癌、肺癌、消化道肿瘤等高频病种,整理了病理诊断常见句式和对应解读;第三是《报告结构与解读规范》,用来帮助模型理解一份完整病理报告应该包含哪几个部分。
文档导入后,分段处理是有讲究的。术语词典我按“一条术语一段”导入,每段控制在60字以内,保证精确检索;疾病摘要按主题分块,每块控制在500字以内,避免大段文本稀释语义。在知识库的检索设置里,我把结果条数设为3到5条,相似度阈值设在一个相对保守的水平,宁可检索不到也不让无关内容混进来。
实际用下来有一个容易被忽视的点:Coze的知识库检索结果是有权重的,调高“知识库优先”会让Agent更倾向于引用检索到的内容,但也会让它变得过于死板——哪怕用户只问一句“这个报告总体怎么样”,它也会强行引用知识库段落而不是直接回答。后来我折中了一下,把知识库权重调成中等,让模型在“有依据的回答”和“自然的对话体验”之间取一个平衡。
4. 测试与验收:凭什么说它达到了“专家级”
4.1 我设计的评测集与评分维度
搞了这么多配置,怎么说服自己这个Agent真的达到了“专家级”?我给自己定了一条规矩:没有测试数据,就不能算做完。我建了一个病理研读评测集,总共20条测试用例,分布在四个类别里。
第一类10条,是完整病理报告文本,用来测全流程解析能力。第二类5条,是报告片段加用户提问,比如只给“镜下所见”这段话,问“这说明什么”,测的是Agent在信息不完整时能否把已有内容说清楚。第三类3条,是干扰输入,比如用户上传了血常规报告或者干脆发一句无关的话,测的是Agent能不能守边界。第四类2条,是包含未知术语或明显信息缺失的报告,测风险兜底能力。
评分维度我设了四个:信息抽取准确率,看字段抽得对不对;术语解释正确率,看解释是否和知识库一致;输出格式合规率,看四段式结构是否整齐、长度要不要超标;风险边界合规率,看有没有出现越界断言,比如直接说“你这是癌症晚期”这种类型的话。
4.2 三轮迭代中的真实翻车案例
评测集不是摆设,我拿它跑出了三轮实实在在的迭代记录,每一轮都有翻车案例,也有对应的修复方案。
第一轮翻车最严重的就是术语解释环节。模型把“高级别上皮内瘤变”解释成“癌前病变,很快就会发展成癌症”,这个说法在医学上是粗糙且容易引起恐慌的。问题出在术语映射节点只做了模糊的语义匹配,没有和知识库精确对齐。解决方案是给知识库里的每一条术语增加“严禁使用表达”字段,比如这一条明确写入“禁止使用‘很快会变癌’等时间性预测表述”。加了这层约束之后,测试集里同类问题全部消失。
第二轮翻车发生在知识库检索命中上。我调低了相似度阈值后发现,Agent偶尔会拿“食管癌”的知识来解释“胃癌”的术语,因为两篇文档都含有“腺癌”这个共同词,检索时混淆了。后来我在知识库中给每个病种增加了“适用部位限定”的排除性描述,并在术语映射节点的提示词里强调“必须检查术语与报告中的解剖部位一致,不一致时不要引用”。
第三轮翻车是格式合规。有个用例输出里直接略过了“下一步建议”段落,原因是用户输入太长,模型在生成时发生了截断。我在回答生成节点的配置里把最大输出长度调大,同时把“四段式结构缺一不可”写进了生成提示词的最前面,并把“下一步建议”压缩成标准话术框架。这样即使内容再长,结构也不会丢。
4.3 验收通过的最低标准
三轮迭代之后,我的评测集跑出了这样一组数据:核心信息抽取准确率从第一轮的82%提升到96%,术语解释正确率从78%提升到92%,输出格式合规率达到100%,风险边界合规率保持100%,幻觉断言数量归零。
也就是说,我把第四条验收标准的红线定为“风险边界合规率必须100%”,任何一条测试用例出现越界断言都不算通过。这个标准对我自己来说很苛刻,但恰恰是这种苛刻让这个Agent敢被叫“专家级”。专家级不是指它比医生更懂病理,而是指它的行为方式像一个训练有素的助手:该说的话一句不少说,不该说的话一个字都不多讲,遇到自己不懂的会主动承认。
5. 常见问题与排查技巧实录
5.1 知识库命中率上不去,怎么排查
这是我在Coze上最常见的故障。排查顺序应该从知识库本身开始:先看分词是否合理,如果文档段落太长会让检索精度下降,建议按语义切割;再看相似度阈值,阈值过高会导致什么都检索不到,适当下调到0.3到0.4之间观察。第三看结果条数,设置的条数太少可能漏掉正确内容,设置太多又可能混入噪声,我一般取3到5条。最后看文档标题和正文首句,如果标题里没有关键词,信息检索时容易匹配失败,建议给文档加一个能概括主题的标题和首句摘要。
5.2 模型输出发散、出现“过度诊断”
“过度诊断”是我给这类问题起的黑话,指模型自行推断出了报告原文没有的信息。比如报告只写了“符合腺瘤样增生”,模型却加了一句话“需警惕恶变可能”。这类问题几乎都出在回答生成环节。解决办法有三层:第一层在抽取节点,强制只提取原文存在的字段;第二层在生成提示词里加硬性约束,“未出现在原文中的诊断信息一律禁止出现”;第三层在风险分级节点里加规则,凡是原文不包含“恶性”“癌”“浸润”等词,生成节点就统一按A/B级话术走,不允许人为拔高。
5.3 输出格式经常和Spec对不齐
格式不对齐的根子往往不在生成节点,而在输入截断或上下文污染。一个前一轮对话中出现的报告片段,可能混进下一轮的生成上下文里,导致结构混乱。我的做法是每一轮处理都从工作流重新抽取信息,不依赖上下文记忆;同时在回答生成节点的提示词开头,明确给出本次回答必须使用的字段数据,并声明“忽略一切与本次输入无关的上下文”。如果在评测集里发现某条用例格式不对,先看是不是输入文本超出模型最大输入长度,必要时在文本清洗节点加截断逻辑。
5.4 工作流节点执行不稳定时的排查路径
工作流偶尔会失败,日志里报的错往往不那么直白。我自己总结了一套排查路径:先确认是不是上游返回的JSON结构变了,比如抽取节点多返回了一个字段或漏掉了一个键;Coze的大模型节点偶尔会出现JSON带前后缀文字的情况,给了解析器麻烦。处理办法是给抽取节点加“只输出JSON,不要输出任何解释和前后缀”的强约束,并在下游解析前增加一个清洗步骤。其次再检查有没有节点超时,超长报告文本会拖慢大模型节点的响应,可以在文本清洗节点把内容压缩到关键字段再往下送,大幅降低超时概率。
最后的经验之谈
这套项目做完之后,我最大的改变是对Agent开发的整体认知。过去我总觉得Agent的能力上限取决于模型选得好不好、提示词写得妙不妙,现在我认为真正决定一个Agent能走多远的,是前面那份规格书写得细不细。
Spec文档里多写一行“遇到未知术语要明说”,Agent在线上就少给用户制造一个恐慌。工作流里多拆一个节点,后面排查问题时就多一条清晰的线索。知识库里多收一条精准的术语对照,模型就少一次靠记忆瞎编的机会。这些事看起来不酷,不像是“造一个专家级Agent”该有的样子,但恰恰是它们堆出了专业感和可靠性。
如果你想在Coze上做类似的垂直领域Agent,我的建议是从一份Spec文档开始,哪怕很简单,也先把角色、输入输出、流程、边界写清楚,再打开平台配置界面。相信我,你不会后悔这个顺序的。