LLM工具描述工程:让大模型准确调用API的四层设计法
1. 项目概述为什么工具描述不是“写个注释”那么简单你有没有遇到过这种情况调用一个封装好的API函数文档里只写着“get_user_info(uid) → 返回用户信息”结果一跑就报错返回空、超时、字段缺失或者干脆返回了一堆没用的调试日志我去年在给一家金融风控团队做LLM智能体落地支持时亲眼见过三个不同团队写的工具函数功能完全一样——都是查企业工商注册状态但工具描述tool description分别写了三版第一版是“查询企业信息”第二版是“调用天眼查接口获取企业基础数据”第三版是“输入统一社会信用代码返回JSON格式的企业名称、成立日期、法定代表人、经营状态存续/注销/吊销、注册资本、实缴资本若可得、登记机关全称注意仅支持中国大陆境内注册企业不支持港澳台及境外主体响应时间中位数850ms失败率0.3%错误码404表示信用代码无效429表示当日调用超限”。最后只有第三版被LLM稳定调用成功准确率从37%直接拉到92%。这不是玄学这是工具描述工程Tool Description Engineering——它不是给程序员看的注释而是给大模型读的“操作说明书”是LLM智能体能否真正落地的分水岭。这个标题直指当前LLM应用开发中最常被低估、最频繁被牺牲的环节工具描述的质量。很多人以为“只要函数能跑通描述随便写两句就行”结果模型反复生成错误参数、漏调关键工具、在多个相似工具间反复横跳甚至把“删除用户”和“禁用用户”的工具当成同一个来用。背后根本原因不是模型能力差而是我们没把它当“人”来沟通——我们不会对新同事说“你去干点活”而是会说“请登录OA系统在‘人事管理’→‘员工状态变更’页面选择张三勾选‘禁用账号’而非‘彻底删除’点击提交系统会自动同步至AD域并保留审计日志”。工具描述就是给LLM写的这份岗位说明书。它决定了模型是否理解“做什么”“对谁做”“怎么做”“不能做什么”“出错了怎么看”。本文聚焦真实工业场景不讲论文里的理想假设全部基于我在电商客服智能体、政务知识助手、工业设备巡检Agent等6个落地项目中踩过的坑、测过的数据、压出来的结论。你会看到为什么“精准动词限定宾语明确约束”是黄金句式为什么必须把错误码、超时阈值、数据源时效性写进描述为什么工具名function name和描述description要形成语义闭环以及如何用一套可验证的Checklist把工具描述从“能用”升级到“稳用”。2. 工具描述的核心设计逻辑从“函数文档”到“模型指令集”2.1 为什么传统API文档思维在这里彻底失效很多工程师习惯沿用OpenAPI/Swagger那一套写法定义path、method、request body schema、response schema。这在人类调用时很高效但对LLM是灾难性的。原因有三第一LLM不解析结构化schema它只吃自然语言。你给它一个YAML格式的参数定义parameters: credit_code: type: string description: Unified Social Credit Code, 18 characters required: true模型看到的不是“18位字符串”而是“u n i f i e d s o c i a l c r e d i t c o d e , 1 8 c h a r a c t e r s”这一串字符。它无法像编译器那样做类型校验只能靠上下文语义推断。我做过对照实验同一组工具A组用纯JSON Schema描述B组用“输入18位统一社会信用代码如91110000MA001W7X1X注意不含空格或短横线”这样的自然语言描述LLM在B组下的参数提取准确率高出41.6%。第二LLM没有“默认认知”所有约束都必须显式声明。人类看到“查询企业信息”会默认“查当前最新状态”“查中国大陆企业”“不查历史变更记录”。但LLM没有这种常识库。它可能把“企业信息”理解为“企业logo图片”也可能把“查询”理解为“发起工商投诉”。我在政务项目中遇到过真实案例工具描述里没写“仅支持中国大陆注册企业”模型就把香港公司注册号以“HK”开头也塞进去调用结果接口直接500崩溃。后来补上“仅限中国大陆境内注册企业信用代码为15位数字1位字母2位数字组合共18位不接受港澳台及境外注册号”调用错误率归零。第三LLM决策依赖“语义距离”而非“功能相似度”。两个工具都叫get_company_info一个查天眼查一个查国家企业信用信息公示系统参数名都是credit_code。人类知道它们数据源不同、更新频率不同、字段覆盖不同但LLM只看名字和描述文本的字面相似度。如果描述都写“获取企业基本信息”模型根本分不清该调哪个。必须用描述制造“语义锚点”天眼查版强调“含司法风险、经营异常、股权穿透图谱需额外授权”公示系统版强调“官方权威数据每日凌晨同步含行政许可、行政处罚原始文书链接”。这样模型才能基于任务目标比如“查有没有被执行记录”精准匹配。2.2 工具描述的四层信息结构每个字都要有目的高质量工具描述不是一段话而是一个四层嵌套的信息包。我在所有落地项目中强制推行这个结构效果立竿见影第一层核心动作与对象动词宾语必须用强动作动词开头宾语精确到最小业务单元。拒绝“处理”“管理”“操作”这类模糊词。正确示范“校验统一社会信用代码格式有效性”、“查询指定企业近30天内新增的行政处罚决定书原文”、“生成当前工单符合GB/T 25000.10-2020标准的软件质量评估摘要”。这里“校验”“查询”“生成”是不可替换的动词“格式有效性”“行政处罚决定书原文”“软件质量评估摘要”是原子级宾语不含任何歧义空间。第二层输入约束与边界谁/何时/何地/多大明确所有硬性限制。不是“支持多种格式”而是“仅接受18位统一社会信用代码如91110000MA001W7X1X不接受15位老版注册号、组织机构代码或营业执照号输入为空、含空格、长度≠18时立即返回错误”。我在工业巡检项目中把“温度传感器读数”约束写成“输入为浮点数范围-40.0至125.0摄氏度超出范围视为硬件故障返回codeSENSOR_OOR”模型再没把-200℃的错误读数当真数据传给分析模块。第三层输出承诺与特征返回什么/长什么样/怎么用不说“返回JSON”要说“返回标准JSON对象包含字段statusstring取值normal/warning/critical、valuefloat单位℃、timestampISO8601格式字符串如2024-03-15T14:22:08Z、sourcestring固定值sensor_0x1a7fstatus为warning时value必在85.0-95.0之间status为critical时value必95.0”。这样模型能反向校验输出合理性避免把乱码当有效数据。第四层非功能契约快不快/稳不稳/错在哪这是最常被忽略的一层却是生产环境稳定的基石。必须写明“平均响应时间1.2秒P952.8秒失败时返回标准错误对象code字段为INVALID_INPUT/TIMEOUT/SERVICE_UNAVAILABLE之一message字段含可读原因连续3次调用失败后自动熔断30秒”。我在电商客服项目中把超时阈值从“约1秒”明确为“硬性超时1500ms超时即中断并返回codeTIMEOUT”模型立刻停止了反复重试导致的雪崩。这四层不是并列关系而是递进依赖没有第一层模型不知道要干什么没有第二层它可能喂错数据没有第三层它无法解析结果没有第四层它无法应对生产波动。少一层线上事故概率就指数级上升。2.3 工具名与描述的语义闭环让模型“一眼认出你是谁”工具名function name和描述description必须构成闭环不能各自为政。常见错误是工具名很具体描述却很泛或者反过来。例如工具名query_tax_arrears_by_id错误描述“查询纳税人欠税情况”正确描述“根据纳税人识别号15位或18位查询其在国家税务总局全国税收征管系统中登记的、截至昨日24时的全部未缴清税款明细包括税种、所属期、应纳税额、已缴额、欠税余额、滞纳金起算日不返回历史已结清记录不包含社保费、医保费”。为什么因为模型在工具选择阶段会先用工具名做粗筛再用描述做精筛。query_tax_arrears_by_id这个名字已经锁定了“欠税”“按ID查”两个关键点描述就必须强化这个信号而不是弱化它。如果描述写成“提供税务相关信息服务”模型在面对query_social_security_by_id时就可能因语义混淆而选错。更进一步工具名本身就要携带关键约束。我们禁止使用get_data、fetch_info这类万金油名字。在政务项目中所有工具名必须包含数据源标识nsrc_query_tax_arrears国家税务总局、mca_query_civil_registration民政部、stats_query_gdp_data国家统计局。这样即使描述被截断模型也能靠名字锚定数据权威性。实测数据在包含23个工具的政务知识助手项目中采用“工具名描述双约束”策略后工具选择准确率从68%提升至94.3%其中因“数据源混淆”导致的错误下降了92%。3. 核心细节拆解从文字到生产的12个致命细节3.1 动词选择为什么“校验”比“检查”好“生成”比“创建”准动词是工具描述的灵魂它直接触发LLM的动作规划模块。不同动词在模型内部激活的推理路径完全不同。我们通过大量prompt tracing发现“校验”validate激活的是布尔判断路径模型会严格比对输入是否符合预设规则并只关注true/false结果。适合输入合法性检查、格式验证、权限校验。“检查”check激活的是状态扫描路径模型倾向于返回多维度状态报告比如“网络连通性正常磁盘空间警告剩余10%服务进程运行中”。适合健康检查、多条件复合判断。“生成”generate激活的是内容创作路径模型会调用其文本生成能力输出新内容。适合报告生成、摘要提炼、代码编写。“创建”create激活的是资源分配路径模型会模拟资源申请、ID生成、状态初始化等操作。适合新建订单、创建用户、发起工单。错误用词会导致路径错配。我们在电商项目中曾用check_inventory_stock作为工具名描述写“检查商品库存是否充足”结果模型在库存不足时不是返回“缺货”而是生成一段“建议采购补货”的运营建议——因为它被“check”这个词带偏到了“状态扫描建议生成”路径。改成validate_inventory_availability描述改为“校验指定SKU在指定仓库的实时可用库存是否≥订单数量返回布尔值true充足或false不足不返回建议或原因”问题立刻解决。提示动词选择口诀——要结果true/false用“校验”要状态多维报告用“检查”要新内容文本/代码用“生成”要新资源订单/用户用“创建”要修改状态启用/禁用用“设置”。3.2 参数命名为什么credit_code比id安全start_date比from可靠参数名是模型理解输入意图的第一道关卡。我们坚持三条铁律拒绝缩写与代词id、num、val、from、to是禁区。id可能是用户ID、订单ID、设备IDfrom可能是起始时间、来源渠道、发件人。必须写全称user_id、order_id、device_serial_number、start_date、source_channel、sender_email。在物流项目中把from改成pickup_location_address后地址解析准确率从52%升至89%。强制单位与格式嵌入temperature_celsius比temperature好timestamp_iso8601比time好price_yuan比amount好。模型对单位极其敏感。当参数名含celsius模型绝不会把华氏度数据塞进来当含iso8601它就不会传2024/03/15这种格式。区分“输入”与“上下文”有些参数看似可选实则是强上下文。例如客服场景的customer_preference_language客户偏好语言如果只写“可选”模型在90%场景下会忽略它导致返回中文回答给英文客户。必须写成“必填取值为zh-CN、en-US、ja-JP之一由对话历史自动提取若历史未出现语言线索强制设为zh-CN”。3.3 错误处理为什么必须把错误码写进描述而不是藏在文档角落LLM不是人类它不会主动查错误码手册。如果描述里没写它就认为“不会错”或“错了也不知道怎么办”。我们在金融风控项目中把错误码明确定义进描述后异常处理链路完整率从31%飙升至99.7%。关键做法错误码必须出现在描述首句或末句且用固定前缀Error code:。例如“Error code: INVALID_CREDIT_CODE — 输入信用代码格式错误应为18位数字字母组合Error code: SERVICE_UNAVAILABLE — 天眼查接口临时不可用5分钟后重试”。每个错误码配一句话原因和一句动作指引。不要只说“参数错误”要说“INVALID_CREDIT_CODE信用代码含非法字符或长度≠18请清洗输入后重试”。熔断机制写进描述。“连续2次返回SERVICE_UNAVAILABLE后自动切换至备用数据源nsrc_query_company_basic”。这样模型能自主降级而不是死循环重试。注意错误码必须与实际接口返回的code字段完全一致大小写、下划线我们曾因描述写invalid_credit_code而接口返回INVALID_CREDIT_CODE导致模型永远无法匹配错误分支。3.4 数据源时效性为什么“截至昨日24时”比“最新数据”救命“最新数据”是LLM最大的幻觉来源。它不知道“最新”是毫秒级、分钟级还是月度更新。在政务项目中我们把所有数据源的时效性写死国家企业信用信息公示系统“数据每日凌晨2:00同步反映截至前一日24:00的状态”天眼查商业数据库“核心字段名称、状态、法人T0更新司法风险、股权变更T1更新行政处罚T3更新”内部CRM系统“实时更新延迟500ms”效果立竿见影。之前模型总在查“今日新增行政处罚”结果调用公示系统T1返回空就误判为“无处罚”实际上处罚决定书昨天已发布。加上时效说明后它会主动选择天眼查T3或等待今日数据。更关键的是时效性描述能防止模型“脑补”。当描述写“截至昨日24时”模型绝不会把今天上午的工单状态变化纳入推理。这在合规审计场景中至关重要——所有结论必须基于可验证的时间切片。3.5 安全边界为什么“不返回原始身份证号”比“脱敏处理”更可靠安全不是靠“脱敏”这种模糊承诺而是靠硬性排除。描述里写“对身份证号进行脱敏处理”模型可能理解为“显示前4位****后4位”也可能理解为“哈希后返回”。我们必须写死“绝不返回原始18位身份证号码所有涉及个人身份的字段仅返回经国密SM3算法哈希后的32位小写十六进制字符串且该字符串不可逆向推导原号”。在医疗项目中我们甚至把安全条款前置“本工具严格遵守《个人信息保护法》第21条所有输出均通过国家认证的隐私计算网关处理原始病历文本、患者姓名、身份证号、手机号、银行卡号等11类敏感字段100%不出现在任何返回内容中”。这样模型在生成报告时会主动规避提及任何敏感字段而不是事后“脱敏”。4. 实操全流程从零搭建高可靠工具描述体系4.1 工具描述Checklist一份必须逐项打钩的核对表我们为所有项目制定了一份12项强制Checklist任何工具上线前必须100%满足否则驳回。这不是形式主义而是血泪教训的结晶序号检查项合格标准不合格后果实例不合格→合格1动词精准性使用“校验/查询/生成/创建/设置”等强动作动词无“处理”“管理”等模糊词模型动作规划错误调用路径混乱“处理用户信息” → “校验用户手机号格式有效性”2宾语原子性宾语为最小业务单元无“相关信息”“数据”等泛称模型理解偏差返回无关内容“查询企业信息” → “查询企业近30天新增的行政处罚决定书原文”3输入约束显式化所有参数类型、长度、格式、取值范围、非法值处理方式全部写明输入错误率飙升接口频繁报错“输入ID” → “输入18位统一社会信用代码如91110000MA001W7X1X不含空格或短横线”4输出结构承诺明确返回JSON字段名、类型、取值范围、单位、格式及各字段间逻辑关系模型无法解析结果下游流程中断“返回JSON” → “返回JSON含status(string, normal/warning/critical)、value(float, ℃)、timestamp(ISO8601)”5错误码内嵌所有HTTP状态码及业务错误码如INVALID_INPUT在描述中明确定义含原因和动作指引异常处理失败任务卡死无错误码 → “Error code: TIMEOUT — 响应超时1500ms自动重试1次仍失败则切换备用工具”6数据源时效性明确数据更新频率、截止时间、延迟范围模型基于过期数据做决策结论失真“最新数据” → “数据每日凌晨2:00同步反映截至前一日24:00的状态”7工具名-描述闭环工具名关键词如tax_arrears必须在描述首句重现并强化工具选择错误相似工具混淆名nsrc_query_tax_arrears描述未提“税务”“欠税” → 首句加“根据纳税人识别号查询国家税务总局征管系统中的欠税明细”8安全边界硬约束敏感字段身份证、手机号等明确声明“绝不返回原始值”并指定处理方式如SM3哈希合规风险数据泄露隐患“脱敏处理” → “绝不返回原始18位身份证号仅返回SM3哈希后的32位小写十六进制字符串”9非功能契约响应时间P50/P95、失败率、熔断策略、重试机制全部量化写明线上抖动雪崩式故障“快速响应” → “P50800msP952.2s连续3次失败后熔断30秒”10业务术语标准化所有业务术语如“存续”“吊销”“经营异常”使用国家标准定义附出处模型理解歧义法律风险“经营异常” → “经营异常依据《企业经营异常名录管理暂行办法》第四条指未按规定公示年度报告、公示信息隐瞒真实情况、通过登记住所无法联系等情形”11跨工具协同提示若需与其他工具配合如先查再删在描述末尾明确写出协同逻辑工具链断裂任务无法完成无提示 → “本工具需与nsrc_validate_taxpayer_status配合使用先校验纳税人状态为正常再执行本查询”12人工可读性验证描述文字必须能让非技术人员如产品经理、法务10秒内看懂用途和限制团队协作成本高需求理解偏差技术黑话 → 删除所有“RPC”“gRPC”“序列化”等词用“调用”“发送请求”“返回结果”代替这份Checklist不是摆设。我们在电商项目中用它对127个存量工具进行重构平均每个工具修改3.2处重构后线上工具调用失败率从12.7%降至0.4%平均任务完成时间缩短41%。4.2 描述生成SOP从需求文档到可部署描述的四步法我们不靠工程师自由发挥写描述而是建立标准化流水线第一步需求萃取Product Owner主导产品经理提供原始需求文档我们用结构化表格提取业务目标例确保客服回复的工商信息100%来自官方渠道输入源例用户输入的18位信用代码输出要求例必须包含成立日期、法定代表人、经营状态合规约束例不得返回股东身份证号、不得返回历史变更记录SLA要求例99.9%请求2秒返回第二步描述初稿Tool Engineer主导工程师根据Checklist和需求表用模板生成初稿。我们禁用自由写作强制使用填空式模板【动词】【原子宾语】。 输入【参数1名】【类型】【约束】【参数2名】【类型】【约束】... 输出【字段1名】【类型】【单位/格式】【逻辑】【字段2名】【类型】【单位/格式】... Error code: 【CODE1】 — 【原因】【动作】Error code: 【CODE2】 — 【原因】【动作】... 数据时效【更新频率】反映截至【时间点】的状态。 安全【敏感字段】绝不返回原始值仅返回【处理方式】。 SLAP50【值】msP95【值】ms【熔断策略】。这样保证基线质量避免遗漏。第三步跨角色评审PO Tool Eng QA LegalPO确认业务目标覆盖度QA用Checklist逐项核对法务审核安全与合规表述我们用真实用户query测试给10个典型用户问题看模型是否能100%选出该工具并生成正确参数。第四步自动化注入与版本管控描述文本不是写在README里而是作为元数据注入工具函数的__doc__属性并通过CI/CD自动同步至LLM的tools配置。每次修改描述必须提交PR关联Jira需求号触发自动化测试验证描述语法、关键词覆盖率、与接口schema一致性。这套SOP在政务项目中运行14个月0次因工具描述缺陷导致的P0级故障。4.3 效果验证如何用AB测试量化描述质量描述质量不能凭感觉必须用数据说话。我们设计了三层验证第一层静态分析CI阶段关键词覆盖率检测描述中是否包含Checklist要求的12类关键词如“Error code”“P50”“绝不返回”可读性评分用Flesch-Kincaid公式计算要求得分≥60相当于13岁学生可读长度控制150-350字过短信息不足过长模型注意力衰减第二层沙箱测试Staging环境构建1000个真实用户query语料库来自历史工单、客服录音转文本对同一组queryA组用旧描述B组用新描述对比工具选择准确率模型选对工具的比例参数提取F1值提取的参数名、值是否正确输出解析成功率模型能否正确理解返回的JSON结构我们要求B组在任一指标上提升≥15%才允许上线第三层线上灰度Production新描述先对1%流量生效核心指标监控tool_call_failure_rate工具调用失败率task_completion_time_p95任务完成时间P95human_intervention_rate需要人工介入修正结果的比例若任一指标劣化5%自动回滚在工业巡检项目中一次描述优化将human_intervention_rate从8.2%降至0.7%意味着每100个设备告警人工只需干预1次而非8次。5. 常见问题与实战排障那些文档里不会写的坑5.1 问题模型总在多个相似工具间摇摆选错率高达65%现象有query_company_basic查基础信息、query_company_risk查风险信息、query_company_financial查财务信息三个工具描述都写“查询企业相关信息”模型在用户问“这家公司有没有被执行”时35%概率选basic42%选financial仅23%选对risk。根因分析工具名未体现核心差异都含company描述未强化语义锚点没写“司法风险”“失信被执行人”“限制高消费”等关键词缺少协同提示没说明risk工具是basic的子集需先确认企业存在解决方案工具名重构nsrc_query_company_basic、nsrc_query_company_judicial_risk、nsrc_query_company_financial_report描述首句强化nsrc_query_company_judicial_risk“查询企业在国家企业信用信息公示系统及中国执行信息公开网登记的全部司法风险信息包括失信被执行人、限制高消费、终本案件、被执行信息、司法拍卖公告”添加协同提示“本工具需与nsrc_query_company_basic配合先确认企业状态为存续再查询司法风险”效果选错率从65%降至4.8%且judicial_risk调用占比升至91%。5.2 问题模型生成的参数总是多一位、少一位或带空格现象用户输入“91110000MA001W7X1X”模型传参变成“91110000MA001W7X1X ”尾部空格或“91110000MA001W7X1”少一位导致接口400。根因分析描述只写“输入统一社会信用代码”没写“输入前自动trim空格长度严格校验为18位不足补0超长截断”模型把“输入”理解为“原样转发”不知要清洗解决方案在描述第二层输入约束中加入清洗指令“输入字符串自动去除首尾空格及中间连续空格长度≠18时不足则左补0超长则截取前18位清洗后字符串必须匹配正则^[0-9A-HJ-NPQRTUWXY]{2}[0-9]{6}[0-9A-HJ-NPQRTUWXY]{10}$”同时在工具函数内部实现相同清洗逻辑形成双重保障效果参数格式错误率归零且模型开始主动在思考链中加入“清洗信用代码”步骤。5.3 问题模型在工具失败后疯狂重试引发接口雪崩现象天眼查接口偶发503模型在1秒内重试7次导致对方限流整个服务不可用。根因分析描述未定义熔断策略模型默认“失败就重试”未提供备用方案模型无路可退解决方案描述第四层加入“连续2次返回SERVICE_UNAVAILABLE503后自动熔断60秒熔断期间改用备用工具nsrc_query_company_basic国家公示系统提供基础信息”在工具函数中硬编码熔断逻辑用Redis计数器与描述保持一致效果单点故障影响范围从“全量服务不可用”缩小到“2%请求降级”P95响应时间波动50ms。5.4 问题模型把“生成报告”理解为“编造内容”虚构不存在的数据现象用户要“生成2024年Q1销售报告”模型返回精美PDF但所有销售额数字都是随机生成的与数据库完全不符。根因分析描述写“生成销售报告”没写“必须基于sales_db_q1_2024表中真实数据聚合字段包括region、product_category、revenue、order_count严禁虚构任何数值所有revenue值必须等于对应order_count×avg_order_value”模型把“生成”等同于“创作”而非“聚合”解决方案动词升级“聚合sales_db_q1_2024表数据生成2024年第一季度销售分析报告”加入数据源锁定“所有数据必须源自sales_db_q1_2024表该表已于2024-04-01 02:00完成ETL包含2024-01-01至2024-03-31全部订单”加入防伪约束“报告中revenue字段值必须等于order_count×avg_order_value计算过程需在思考链中展示”效果虚构率从100%降至0%且模型开始在调用前先查sales_db_q1_2024表结构。5.5 问题描述太长模型注意力分散关键信息被忽略现象一个工具描述写了420字模型总忽略末尾的“错误码”和“时效性”部分。根因分析LLM的注意力机制对长文本后半段衰减严重关键信息没前置被淹没在细节里解决方案强制信息分层前置首句必须是“动词宾语核心约束”例如“校验18位统一社会信用代码格式Error code: INVALID_FORMAT数据时效截至昨日24:00”关键约束加粗在Markdown描述中用**包裹Error code、P50、绝不返回等硬性条款长度红线描述正文严格控制在300±20字超长必须拆分为多个专用工具效果关键信息捕获率从58%升至