
“A001这个SKU现在库存多少”——一句话问出来摆在WMS系统里的AI Agent面前就变成了一个“准确性”问题而不是“语义理解”问题。前几讲我们把Agent的骨架搭好、提示词模板也调顺了团队已经开始把业务问题往Agent上堆。结果马上撞到一个让人头大的事实大模型根本没有摸过我数据库里的任何一张表。你跟它聊业务流程它能给你说出一套很完整的SOP你问它某个SKU的实时库存它只会回你“根据相关资料目前库存约在几百件左右”。这个“约”字一出来仓储负责人的脸色基本就变了。WMS不是知识问答系统库存数量、单据状态、货位占用这些都是强事实数据。事实数据不能靠“推测”只能靠访问。这一讲的核心任务就是给Agent装上一套真正能触达数据库的“手”让大模型以工具调用的方式安全、精准地读写那15张核心业务表。我按项目里的习惯做了一个很有仪式感的总结15张表确定数据边界19个AI工具确定能力边界两者对齐Agent才算真正开始“上岗”。1. 为什么前几讲做完Agent还是“够不着”库里数据1.1 我在前三讲解决了什么还剩下什么这个系列走到第4讲前面的铺垫不能再忽略。第1讲我们把Agent的工程骨架搭起来选型、项目结构、模型接入目的是让Agent能跑起来第2讲我们把WMS领域的业务提示词、角色设定和常用术语灌进去目的是让模型说话像个懂仓储的人第3讲我们开始做任务拆解和流程编排让Agent知道一个复杂的查询应该分几步去回答。但你回头看看这三步本质上都发生在“模型推理”这一侧。模型确实是变专业了它会说“入库单”“波次”“上架”这些词了但它的所有知识来源仍然只是训练语料和我塞进去的那几段上下文。WMS里的数据是每秒钟都在变的一个盘点单刚审核完库存数字就变了一个拣货任务完成库存流水立刻要记账。这些东西不存在于任何一本训练资料里只存在于数据库里。所以必须承认一个边界推理层的优化解决的是“表达得像不像”存储层的打通解决的是“答得准不准”。第4讲要做的就是把这个断层补上。这也是为什么我把这讲起名叫“让大模型真正摸到数据库”——它得先摸到才能谈得上准不准。1.2 RAG和向量检索为什么救不了库存查询可能会有人问那我不接数据库我用RAG把库存数据灌到向量库里行不行我在项目早期真的试过这个方案把WMS的库存表定时同步成一个文本快照切块、向量化、存进向量数据库然后让Agent去检索。结论是演示的时候挺好看真用起来非常不靠谱。原因说穿了也简单。库存数据的查询条件是精确过滤SKU编码要完全匹配、仓库要按编码过滤、货位要按库区维度聚合。向量数据库擅长的是语义相似度匹配它会把“SKU A001”和“SKU A002”看作相近的东西返回给你。但对于库存查询来说相近的东西毫无意义我要的就是那一个SKU差一个字符都不行。而且库存是强时效数据每分钟都在变向量库同步的延迟哪怕只有几分钟都可能在仓管员问“这批货能不能发”的时候给出一个过期的数字。所以RAG在我这个场景里只适合做一件事知识问答比如“退货流程怎么走”“盘点差异怎么处理”这类SOP问题。一旦问题落到具体数字上必须放弃向量检索直接走数据库实时查询。这两条路线在WMS Agent里是并行的不是替代关系。1.3 正确姿势工具函数包住SQL而不是让模型裸写SQL想让大模型摸数据库最粗暴的思路是Text2SQL让模型自己生成SQL然后执行。我在项目初期也动过这个念头但很快打消了后面第5节我会专门展开原因。这里先给一个结论性的方向我们采用的方法是把SQL封装进预设的工具函数里大模型只负责传参数不负责写SQL。打个比方这就好比一个访客进你的仓库你可以给他一张全局门禁卡让他自己去开所有的门也可以安排一个库管员跟着他他只需要告诉库管员“我要到A区拿一份货单”具体开哪扇门、走哪条通道由库管员判断。我选的一定是后者。预设工具相当于库管员模型只管表达意图、传递参数具体落在哪张表上、拼什么SQL完全由工具的逻辑决定。这个架构有几个非常实际的好处一是权限可控工具只读的读、该写的走审批二是输出稳定每个工具返回什么样的结构在代码里写死了不会因为模型换参数名而乱掉三是便于审计每次工具调用都会留下日志谁在什么时间查了什么数据一目了然。2. WMS里的15张核心表Agent的认知地图2.1 主数据四张表仓库、库区、货位、商品设计工具之前先把WMS的数据地图铺开。一个中大型WMS的库表可能有上百张但真正和Agent日常问答高度相关的我认为可以收敛到15张表。第一组是四张主数据表它们是所有业务单据的基础维度。wms_warehouse仓库表记录仓库编码、仓库名称、地址、状态。多仓场景下几乎所有库存查询都要关联这张表确认仓库维度。wms_storage_area库区表一条仓库下分成多个库区按业务类型分为收货区、存储区、拣货区、退货区等。库区表的关键字段是area_type它决定了这个区域是做什么用的。wms_storage_location货位表货位是物理库存的最小位置维度字段包含库区ID、巷道、排、层、货位类型以及是否冻结。货位编码一般遵循“区-库-排-层-位”的统一规则比如A010201代表A区1库2排0层1位。wms_sku商品主数据表包含SKU编码、SKU名称、条码、单位、规格、品牌、安全库存、默认货位。这张表是库存和单据关联商品维度时绕不开的核心。这四张表本身不产生业务变动但它们是Agent回答“哪个仓”“哪个区”“哪个货位”“哪个商品”这类基础定位问题的底表。我在给Agent写工具说明时会把这张表直接作为“空间坐标系”来描述让模型知道货位和库区是从属关系SKU是商品维度不要搞混。2.2 库存事实层批次、余额、流水第二组是库存事实的三张表它们是我认为整个WMS数据模型里最值得花时间理解的部分。wms_batch批次表记录SKU所属的批次号、生产日期、效期、入库日期、质检状态。加了批次维度之后库存才能精确到“哪一批货还有多少”。wms_inventory库存余额表按SKU、仓库、货位、批次维护当前库存余额。字段里最关键的一组是四个数量总在库数、冻结数、占用数、可用数。后面写工具定义时这四个字段的含义我会原封不动地写进描述里因为模型对“可用”和“在库”的区分经常出问题。wms_inventory_flow库存流水表每次库存变动都会记一条流水包括变动类型、变动前数量、变动后数量、关联单号、操作人、时间。有这张表在Agent才能回答“这个SKU最近7天出库了多少”“这批货是什么时候入库的”这类历史追溯问题。这三张表的基本关系是wms_batch提供批次标签wms_inventory是某个时间点的余额快照wms_inventory_flow是变动轨迹。余额是结果流水是原因。Agent分析库存异常时我通常引导它先用余额表定位现状再用流水表回溯原因这是一个很高效的排查路径。2.3 入库链路三张表入库单、入库明细、上架任务从这一组开始就进入业务流程表了。入库链路的三张表是物流从“收货”到“可售”之间的核心凭证。wms_inbound_order入库单表单据头记录入库单号、供应商、仓库、预期到货时间、收货完成时间、整体状态。wms_inbound_order_detail入库单明细表明细行记录每个SKU的预期收货数量、实际收货数量、已上架数量、目标货位等。一张入库单包含多个明细行。wms_putaway_task上架任务表记录从收货暂存区到存储货位的上架执行任务包含来源货位、目标货位、SKU、数量、任务状态和执行人。这三张表之间的关系是入库单头 明细描述“我要收什么”上架任务描述“收到之后放到哪里”。Agent在回答“采购订单PO-1001的货现在收到哪一步了”时需要一次性关联这三张表才能给出完整答案入库单是不是已收货、明细里实际收了多少、上架任务还剩余多少没执行。2.4 出库链路三张表出库单、出库明细、拣货任务出库侧的逻辑和入库侧对称但我个人觉得实际使用中出库的查询频率比入库高得多。wms_outbound_order出库单表记录出库单号、客户、优先级、计划发货时间、拣货完成时间、发货时间、整体状态。wms_outbound_order_detail出库单明细表明细行记录每个SKU的需求数量、已分配数量、已拣货数量、波次号、状态。wms_picking_task拣货任务表记录拣货的执行维度包括来源货位、目标集货位、SKU、拣货数量、任务状态。出库侧有一个独特的维度波次。波次是把多个出库单按一定策略打包到一起集中拣货的编排单位。所以Agent回答“今天上午生成的波次执行到哪了”时实际是在查wms_outbound_order_detail.wave_no关联到wms_picking_task的状态。这是出库链路查询里最重要的一个关联模式。2.5 异常与调整两张表盘点单、库内调拨单最后补上两张“保底表”这类表平时不问但一旦仓库里出了账实不符或者库内调整它们就是排查的入口。wms_stocktake_order盘点单表记录盘点任务的账存数量、实盘数量、差异数量、盘点状态、复核人。Agent在查“这个月盘亏最厉害的SKU是哪些”时主要就是聚合这张表。wms_stock_transfer库内调拨/移动表记录库内从源货位到目标货位的移动包含SKU、批次、移动数量、状态、原因。货位调整、补货移动、库内整理都会产生这类记录。我个人在项目里的习惯是把这两张表规划成异常响应的“终结者”盘点和调拨处理的本质是对账和纠偏Agent在回答差异类问题时不光要给出差异数量还要引导用户定位差异来源。这时候wms_inventory_flow就会派上用场形成一条完整的排查链路。2.6 表关系速查给后面写工具用的关联地图为了不让后面写SQL时去现翻表结构我把15张表之间的主要关联键整理成一个速查表Agent工具的参数校验和SQL绑定都基于这张表设计。起点表关联表关联键说明wms_inventorywms_skusku_id库存指向商品主数据wms_inventorywms_storage_locationlocation_id库存落在货位维度wms_inventorywms_batchbatch_id库存可选关联批次wms_storage_locationwms_storage_areaarea_id货位归属库区wms_inbound_order_detailwms_inbound_orderinbound_order_id明细归属单据头wms_putaway_taskwms_inbound_order_detailinbound_detail_id上架任务关联入库明细wms_outbound_order_detailwms_outbound_orderoutbound_order_id明细归属单据头wms_picking_taskwms_outbound_order_detailoutbound_detail_id拣货任务关联出库明细wms_inventory_flow各种单号order_no流水通过单号回溯业务来源这张表的价值在于Agent工具里大部分都是多表关联查询提前把关联键在工具层固定成参数可以避免模型在提示词里瞎猜字段名。3. 19个AI工具分组设计能力边界怎么划3.1 为什么不能一张表对应一个工具设计工具时最容易踩的灰区是既然有15张表是不是做15个查询工具就够了我的答案是远远不够。原因在于Agent接到的问题很少是单表查询比如“A001在华东仓还有多少可用库存”这个问题至少需要同时关联wms_sku、wms_inventory、wms_storage_location、wms_warehouse四张表。如果一张表一个工具模型就得连续调用四个工具自己做关联既慢又容易把语义搞错。所以我设计工具的原则是按业务问题聚合不按单表拆分。一个工具对应一个高频业务场景工具内部去处理复杂的表关联。项目最终收敛出19个工具分成四组库存查询类8个、单据任务类5个、经营分析类4个、运营动作类2个。下面分别展开。3.2 库存查询类8个只读工具撑起“实时看货”能力库存查询是Agent最核心的看家本领我把它拆成8个工具每个工具解决一类明确的库存问题query_sku_basic按SKU编码查询商品主数据返回品名、规格、单位、安全库存、状态。query_stock_onhand按SKU汇总查询多仓库/多货位的实时在库数量返回总在库、冻结数、占用数、可用数。query_stock_by_location按货位编码查询该货位上的库存明细适合“某个位置现在码了什么货”这类问题。query_stock_by_batch按批次号查询某批次的库存分布适合效期管理和批次追溯。query_available_stock计算指定SKU在指定仓库的可用库存内部逻辑是“在库-冻结-已分配”供订单承诺使用。query_expiry_alert按指定天数范围查询即将过期或已过期的批次列表。query_low_stock按安全库存阈值扫描低于安全库存的SKU清单。query_inventory_flow按SKU、时间范围、变动类型查询库存流水用于变动追溯。这8个工具覆盖了日常“库存还有多少”“货在哪”“什么时候过期”“哪些快断货”这几大高频问题。写工具描述时我会刻意强调字段口径比如query_stock_onhand的输出中“可用数 在库数 - 冻结数 - 占用数”避免Agent把数据传回给用户时把口径说错。3.3 单据任务类5个工具让Agent能“盯住业务流程”库存是结果单据是过程。仓储管理员很多时候问的不是“还剩多少”而是“那一单现在卡在哪一步”。这组工具解决的就是跟踪问题。query_inbound_progress输入入库单号返回入库单头状态、各明细的实际收货数量和已上架数量判断到底卡在收货还是上架。query_outbound_progress输入出库单号返回单据状态、波次号、拣货进度、是否已发货。query_putaway_task按状态、库区查询待上架、上架中、已完成的上架任务列表。query_picking_task按波次号或状态查询拣货任务进度返回已完成数量与总数量。query_stocktake_diff按盘点单号或时间范围查询盘点差异明细按差异数量倒序排列。这一组工具对状态字段的表达要求很高。我在工具描述里会明确给出WMS的状态枚举比如入库单的状态码有“草稿/部分收货/已收货/已上架/关闭”这样模型根据用户语气匹配状态词时才不容易错。3.4 经营分析类4个工具让Agent从“查数”走向“分析”Agent如果只能查数本质上就是个语音版的报表工具。要让它有“参谋”的样子就得加一点分析型工具。这一组工具在SQL层面基本都走聚合查询不是简单地把记录列出来。analyze_inventory_turnover按SKU或分类计算指定时间范围的库存周转率输出周转天数用来判断哪些货卖得慢、资金压得重。analyze_slow_moving按时间阈值扫描滞销/呆滞SKU输出库存金额、最后出库时间、建议处理方式。analyze_location_utilization按库区维度统计货位占用率支持定位空置率高或者过载的库区。analyze_workload统计指定日期的入库单量、出库单量、拣货任务量、完成率输出库内作业负荷概览。这四个工具在实现上有更强的SQL聚合能力。底层SQL基本都带GROUP BY、SUM、AVG这类操作。我曾经踩过一个坑分析类工具的入参如果不固定“时间范围”模型经常漏传时间导致全量扫描。所以这组工具的时间参数在工具层做了必填约束缺了就直接报错提示逼着模型向用户追问时间条件。3.5 运营动作类2个有限写入工具权限必须“软写”讲到这里很多人会问有没有写操作WMS的写操作风险极高直接让模型执行update库存表这种事我在生产环境是绝对不碰的。所有写操作都采用“软写”模式也就是生成一张待审核的业务单由仓管员在WMS管理端审批后才真正生效。create_stock_adjustment按SKU、货位、调整数量、原因创建库存调整单。正数代表盘盈入库负数代表盘亏出库。这个工具不直接改库存只插入一条待审批的调整单记录。freeze_unfreeze_stock按库存ID或SKU仓库维度发起冻结/解冻申请。同样走审批流审批通过后才真正修改冻结状态。让模型发起写操作时我在工具逻辑里加了三个防线第一数量绝对值不能超过设定阈值第二原因字段必填并且要做关键词合理性校验第三所有写操作都落入操作日志表即使最终没有审批通过整个过程也能追踪。写操作宁可慢不可错这是WMS Agent和普通聊天机器人最大的不同。4. 工具注册与SQL绑定的实现细节4.1 一份规范的Function Schema长什么样工具设计是脑力活落地写代码时最常用的就是Function Calling这套标准。我拿query_stock_onhand举个例子看一下在代码里注册的时候这个工具的定义应该怎么写。{ type: function, function: { name: query_stock_onhand, description: 按SKU编码查询指定仓库中的实时库存汇总返回总在库数、冻结数、占用数、可用数。可用数在库数-冻结数-占用数。不传仓库编码时默认查询所有仓库。, parameters: { type: object, properties: { sku_code: { type: string, description: 商品SKU编码精确匹配如A001 }, warehouse_code: { type: string, description: 仓库编码可选如WH001 } }, required: [sku_code] } } }这里有两个我特别强调的点description里把字段计算口径写清楚是提升模型判断准确率的性价比最高的一步必填参数只有sku_codewarehouse_code是可选因为用户可能就想看全仓的库存少一个参数模型也能完成任务。4.2 Python工具函数SQL绑定与参数校验Schema是给模型看的真正干活的还是背面的Python函数。我习惯把每个工具写成一个函数函数内部做参数校验、SQL拼接、结果格式化三层逻辑。def query_stock_onhand(sku_code: str, warehouse_code: str None) - str: 查询SKU实时库存汇总。 参数校验、SQL聚合、结果格式化。 # 第一层参数校验 if not sku_code or len(sku_code) 50: return json.dumps({error: sku_code不能为空且长度不能超过50}, ensure_asciiFalse) params {sku_code: sku_code} sql SELECT w.warehouse_code, w.warehouse_name, SUM(inv.qty_onhand) AS qty_onhand, SUM(inv.qty_frozen) AS qty_frozen, SUM(inv.qty_locked) AS qty_locked, SUM(inv.qty_available) AS qty_available FROM wms_inventory inv JOIN wms_sku s ON inv.sku_id s.id AND s.sku_code %(sku_code)s JOIN wms_warehouse w ON inv.warehouse_id w.id WHERE inv.qty_onhand ! 0 if warehouse_code: sql AND w.warehouse_code %(warehouse_code)s params[warehouse_code] warehouse_code sql GROUP BY w.warehouse_code, w.warehouse_name ORDER BY qty_onhand DESC rows db_query(sql, params) if not rows: return json.dumps({message: f未查询到SKU {sku_code} 的库存记录}, ensure_asciiFalse) return json.dumps(rows, ensure_asciiFalse, defaultstr)这段代码展示的是最常用的聚合查询模式。要注意的地方是SQL里全部用参数绑定不拼字符串这是在数据库层面防注入的关键结果统一转成JSON字符串返回给模型模型拿到结构化数据后再用自己的语言组织成回答查询结果为空时也不要返回空列表而是给一段明确的中文说明这样模型不会顺着空列表编造出“该SKU已售罄”的结论。4.3 多工具连续调用Agent处理复合问题的完整链路单个工具好写真正体现Agent能力的地方在于多步调用。用户问“A001现在还有多少可用库存最近7天出库了多少”这个问题就需要连续调用两个工具query_stock_onhand和query_inventory_flow。流程会是这样展开第一步Agent拿到用户问题后根据工具描述判断需要查库存和流水第二步先调用query_stock_onhand获得当前库存汇总第三步再调用query_inventory_flow传入SKU编码、变动类型为“出库”、时间范围是最近7天第四步把两个工具的结果拼在一起组织回答A001当前总在库1280件其中冻结50件、已分配120件、可用1110件。最近7天累计出库320件。整个链路的编排由Agent自己完成但每一步都落在固定工具上所以输出质量是可控的。对于复杂一点的场景比如“把低于安全库存且最近两周没有补货的SKU列出来”工具设计上其实可以专门做一个组合工具把两个判断一次性做完减少模型来回调用的次数。4.4 让Agent的答案带上“数据出处”这个细节是我在实际使用后补的一个功能但我觉得价值被严重低估。默认情况下Agent只会给用户一个数字答案用户很难判断这个数字到底是查出来的还是模型编的。我在工具返回结果里额外附加了一个字段记录SQL执行的数据库服务器时间、数据来源表名列表、查询耗时。Agent在组织最终回答时会自然带出一句数据来源为库存汇总表和库存流水表查询时间14:32:07。别小看这行字它既是对用户的交代也是对模型幻觉的一种隐性约束。当模型明确知道自己是在陈述一次真实查询结果时它编造信息的概率会明显降低。这也是企业内部用户建立对AI Agent信任感的起点。5. 上线前我踩过的坑和补救方案5.1 让人心惊肉跳的Text2SQL诱惑我不止一次在产品讨论会上听到“既然大模型这么强直接让它写SQL多省事”的说法。从Demo演示的角度看Text2SQL确实很惊艳但放到生产环境会发现几个非常现实的问题。模型会根据自己的训练知识去猜表名字段名哪怕是给足了表结构它也可能把wms_stock_transfer写成wms_transfer_order。对了还好错了你根本不知道它下一次会猜出什么来。同时SQL执行超时没有兜底一个没带时间过滤条件的聚合查询直接在全表几百万条流水上跑一遍能把数据库连接池打满影响生产线上的正常业务。还有一个问题是审计困难模型生成的SQL每次都不一样出了数据问题几乎没办法回溯责任。我把Text2SQL只保留在一个受限的私有场景里用给数据分析师提供一个只读库的临时查询入口并且强制开启查询超时和只读账号。面向业务用户的Agent绝对采用预设工具方案。工具预设意味着SQL是Review过的、索引是提前看过的、执行计划是可控的这是生产环境最稳妥的路。5.2 SKU、单位和多仓库三处最容易翻车的细节工具都写好之后测试阶段最先暴露出来的问题不是技术框架而是一些业务上的“老资历才能踩到的坑”。第一个坑是SKU主数据有重复编码的历史问题。系统早期导入数据不规范同一个商品可能对应两个SKU编码一个在用、一个废弃。工具在查询前不能只按sku_code精确匹配我加了一层主数据状态过滤默认只查状态为“启用”的SKU。第二个坑是单位混乱。WMS里有些商品按件存有些按箱存查询结果如果只给一个数量用户根本不知道是件还是箱。我在工具的输出格式里强制要求带上单位字段同时描述里提示模型“如果用户没说明按什么单位查询优先返回基础计量单位并注明单位”。第三个坑是多仓库维度。默认情况下模型非常容易忽略“哪个仓”这个条件导致把所有仓的库存加在一起回复用户。我在query_stock_onhand的描述里写了“不传仓库编码时默认查询所有仓库”但这还不够实际更稳妥的做法是在大多数库存工具里把warehouse_code设为必填宁可让模型多追问用户一句也不能让它答一个不存在的“全仓总数”。5.3 写操作必须软写并且要有三层保险关于写操作我在3.5节提过软写模式这里再展开说一下实现层的保险设计。第一层是数量校验create_stock_adjustment工具里调整数量绝对值超过500直接拒绝执行第二层是原因校验调整原因必须是预设关键词比如“盘点差异”“损坏报废”“补录差异”如果模型传了一个“随便改一下”这种无意义原因系统直接返回错误让模型要求用户给出明确理由第三层是权限校验调用写操作工具前会检查当前登录用户的角色只有仓管员角色允许创建调整单普通访客角色只能走只读工具。这三层保险看着麻烦但它们保证了Agent即使被诱导、被注入也不会出现“一句话把库存改没了”的事故。WMS对写操作的容忍度极低宁可让用户多做一步审批也不能让一个模型请求直接动底层数据。5.4 响应速度优化数据库返回快不代表Agent快上线初期我们收到的第一条负面反馈是“太慢了”。查一次库存用户在界面上转了七八秒才出结果。拆开耗时发现数据库查询本身只要80毫秒前后端网络耗时也不大大头都耗在了模型推理上模型要理解问题、分析该调哪个工具、生成参数JSON、等待工具返回后再生成回答。两步推理加在一起四五秒很正常七八秒也能遇到。我做了两个方向的优化。一是把高频问题尽量设计成单工具查询避免模型绕两三个来回二是给工具开启流式输出先把工具执行状态“正在查询库存数据”返回给前端用户至少知道系统在工作心理上会觉得快很多。另外我在数据库层为wms_inventory、wms_inventory_flow这些高频查询表加了组合索引sku_id warehouse_id status把底层SQL响应控制在100毫秒内给模型推理留出足够的时间预算。5.5 权限与审计给数据库侧和工具侧各装一道闸最后一遍安全收尾。数据库侧我给Agent专用的数据库账号设置为只读账号只能执行SELECT所有写操作走应用层API数据库账号层面断绝了update/delete的可能。工具侧每次调用都记录完整的入参、出参、用户ID、时间戳存进独立的agent_audit_log表。这些日志平时没有人看但出现数据争议时它就是排查的重要证据。审计日志的字段我建议至少包含这八个工具名、入参JSON、出参摘要、用户ID、会话ID、仓库编码、耗时、创建时间。有了这份日志才能回答“刚才是哪个用户让Agent查了什么数据、Agent返回了什么结果”这个最基本的追溯问题。6. 从“摸到”到“用好”后续演进的经验与建议15张表、19个工具全部上线后Agent才算真正开始接触业务。我自己后续的使用体会是工具数量不要急着膨胀先把现有19个工具的命中率和准确率跑稳。每次用户问了一个现有工具答不了的问题我会先判断这个问题是不是高频高频才增加工具低频就直接告诉用户不支持。另外我建议每个工具都要有一个版本概念。工具改了SQL、改了输出字段都会影响Agent在模型侧的判断升级工具的时最好同步把工具描述也更新并且跑一遍对应的回归测试。LLM应用的测试不像传统软件那么容易自动化我的做法是维护了一份“50个高频问题正确答案”的黄金回归集每次工具升级后把这50个问题全部跑一遍快速发现模型是否因为工具描述或参数结构的变化而答错。接下来这个项目我已经在规划两个方向的延展一是把经营分析类工具往预测方向走比如基于历史出库流水的安全库存动态建议、补货预测二是把多个工具组合成更上层的“技能”比如“库位利用率分析”和“波次任务进度”组合成一个“仓内运营健康度”技能让Agent从回答单个问题进化到主动汇报仓内整体运行状态。这一讲的内容说到底核心只有一句话让大模型摸到数据库靠的不是把SQL能力交给模型而是把数据能力和业务规则提前封装成工具让模型在安全边界内精准调用。做到这一步Agent才会真正开始成为仓管团队里的一个“数字同事”而不只是一个会聊天的机器人。