
hermes-agent 这个名字第一次看到的时候我就觉得挺有意思。Hermes 在神话里是传递消息的信使跑得快、路径灵活、能穿梭于不同神域之间而一个叫 hermes-agent 的项目说白了就是想做 AI 界的那个“信使”把大模型和外部工具、数据、系统串联起来让模型不再只是“纸上谈兵”而是真正能动手干活的智能体。这篇文章我想从项目设计、核心实现、实操过程和踩坑经验几个方面把我做 hermes-agent 二次开发和落地部署时积累的东西完整写出来。如果你正准备做 AI Agent 项目或者已经在用类似的自主代理框架这篇文章应该能帮你省下不少弯路。1. 项目整体设计与思路拆解1.1 Hermes-agent 到底解决什么问题先说清楚一个背景单靠大模型本身我们能做到的其实只有“对话”。你问它问题它给你答案但让它去查数据库、改文件、调接口、定时执行任务它就无能为力了。早期大家解决这个问题靠的是写死工作流比如用户触发某个槽位程序进行相应的 API 调用流程僵硬到不行换个说法就没法识别更别提多步骤复杂任务。hermes-agent 这一类项目的核心价值是把大模型从“聊天大脑”升级成“执行大脑”。它的基本逻辑是你给一个模糊的、多步骤的自然语言指令Agent 先拆解成子任务再根据子任务选择合适的工具、生成调用参数、执行并观察结果然后决定下一步动作直到完成整个目标。这套逻辑在业内通常叫做“规划-执行-观察”循环也就是 Plan-Execute-Observe 闭环。我做这个项目改造之前团队里已经有几条固定的自动化脚本在跑。痛点非常明显需求一变就要改代码流程稍微复杂一点脚本就变成意大利面条。后来我把几条最核心的流程迁移到 hermes-agent 上效果好了不止一个量级。比如处理工单这件事过去是一套硬编码的 if-else现在换成了 Agent 根据工单内容自己决定查什么表、调什么接口、给什么结论迁移之后维护成本明显下降。1.2 为什么选 Agent 架构而不是传统流程编排很多第一次接触 Agent 的人会问我直接用 FastAPI 写个回调不就行了吗为什么非得上 Agent这个问题的答案恰恰是理解 hermes-agent 设计意图的关键。传统流程编排是把“路径”画好程序照着走。Agent 架构则是只给“目的地”和“工具箱”路径由模型自己走。拿外卖场景类比传统流程像固定套餐你只能选 A 套餐或者 B 套餐Agent 像是给你一张菜单加一个厨房你说“我想吃点辣的但又不想太油腻”厨房自己决定做什么菜。前者确定性强适合流程稳定的场景后者灵活性强适合需求多变、语义复杂的场景。hermes-agent 在架构上的取舍也是围绕这个核心展开的。它没有把工具调用写成死代码而是通过“工具注册机制”让 Agent 动态感知有哪些工具可用再通过“任务规划器”让模型自己决定调用顺序和调用参数。这种方式最适合的场景包括语义多变的工单处理、需要查多份资料才能回答的问答系统、需要联动多个内部系统的运维自动化以及数据分析和报表生成这类链条较长的业务。1.3 系统总体架构模块划分和职责边界我在二次开发 hermes-agent 时把整个系统分成五个核心模块任务规划器、工具执行器、记忆管理器、模型网关、配置中心。任务规划器负责接收用户目标把大目标拆成可执行的小步骤工具执行器负责真正去调外部 API、执行命令、操作文件记忆管理器维护两类记忆——短期记忆当前任务的上下文和长期记忆跨任务的偏好和关键结论模型网关统一封装底层大模型接口避免业务代码直接依赖具体模型厂商配置中心统一管理系统参数和工具参数。这五个模块不是并列关系而是有明确的调用顺序用户输入先进规划器规划器向模型网关请求规划结果然后根据规划结果将具体动作交给工具执行器工具执行器返回结果后又回传给规划器让模型判断下一步动作。整个循环中记忆管理器随时读写上下文配置中心提供全局参数。这种分层的架构有一个明显优点每层都可独立替换。模型网关这层我可以从 OpenAI 切换到国产模型只需要改配置不用动业务代码工具执行器可以随时挂载新工具只需要完成注册文件任务规划器的策略也可以从“一次规划全部执行”切换成“逐步规划逐步执行”。对于做工程的人来说这种低耦合的设计是最省心的。2. 核心细节解析与实操要点2.1 任务规划模块拆解逻辑和 Prompt 设计任务规划是整个 Agent 的灵魂也是最难做好的部分。我最初接触 hermes-agent 时以为规划就是简单的“把用户问题丢给大模型让它输出 JSON 格式的子任务步骤”实际做下来发现远没有这么简单。模型确实能输出步骤但步骤的质量参差不齐要么太粗导致工具执行器不知道该调什么要么太细导致上下文爆炸。后来我在项目里做了两个关键优化。第一在 Prompt 里加入“动作空间约束”明确告诉模型当前环境中有哪些工具可选、每个工具的输入参数格式是什么、什么情况算异常需要重试。第二引入“二次校验机制”模型生成规划后不直接执行而是先过一层语法校验和规则校验比如检查参数类型、检查工具名称是否存在、检查是否引用了未定义的变量。举一个具体的规划 Prompt 片段这是我调试很多次后觉得相对稳定的版本你是 hermes-agent 的任务规划器。用户的目标是{user_goal} 当前可用的工具有 {tools_schema} 请输出 JSON 数组每个元素包含 - step_id: 步骤编号 - tool_name: 要调用的工具名 - tool_params: 工具参数对象 - description: 步骤说明 要求 1. 每一步只能调用一个工具 2. 必须基于前一步的输出决定后续步骤 3. 如果信息不足调用 search_knowledge 工具补充背景 4. 输出必须是合法的 JSON不要包含任何解释文本这个 Prompt 的关键点在于“每一步只能调用一个工具”。一开始我允许模型并行调用多个工具结果上下文一多模型就晕了经常出现参数串位的情况。强制单步调用后虽然执行时间变长了一点但稳定性和可调试性提升了非常多。在真实业务场景里稳定性永远是第一位的。2.2 工具调用机制注册、参数匹配和异常处理工具层是 hermes-agent 和真实世界交互的桥梁。我之前在自研版本里走过一段弯路工具逻辑直接写在 Agent 主代码里加一个新工具就要改主循环改着改着代码就烂掉了。后来参考 hermes-agent 的插件化设计把工具做成了“注册-发现-调用”三个阶段的机制。注册阶段每一个工具都是一个独立的 Python 类或者函数通过装饰器挂载到全局工具注册表里。以项目里的一个查库存工具为例它的简化实现长这样from hermes_agent import register_tool register_tool( namequery_inventory, description根据商品编码查询当前库存数量, parameters{ type: object, properties: { sku_code: {type: string, description: 商品编码}, warehouse_id: {type: string, description: 仓库ID可选} }, required: [sku_code] } ) def query_inventory(sku_code: str, warehouse_id: str None): # 这里写真实的库存查询逻辑 result inventory_service.query(sku_code, warehouse_id) return {status: success, data: result}注意这里的 parameters 字段它是给大模型看的函数签名模型靠它来理解怎么调用工具、填什么参数。这个 schema 越精确模型调参的准确率越高。我建议字段描述里尽量写“什么时候要填这个参数”以及“默认值是什么”比如 warehouse_id 后面加了“可选”模型就会在用户没提仓库时自动忽略而不是瞎编一个。调用阶段的核心是参数校验。模型生成的参数经常会出现字符串多余空格、数字被写成字符串、枚举值不在范围内的问题所以无论模型输出什么都必须经过 Pydantic schema 校验再进入真实工具。校验失败时不能直接报错终止而是要返回给模型一个“参数错误”的信号让模型根据错误信息重新生成参数这种重试机制在实战里极其重要。2.3 记忆管理短期上下文和长期知识的协同记忆管理是 Agent 项目里最容易被人忽视、实际上最影响体验的部分。没有记忆的 Agent 就是个金鱼——你说完上句它马上就忘多轮任务基本没法完成。hermes-agent 里把记忆分成两个层面我分别说一下实现思路。短期记忆我用的方案是“滑动窗口 关键信息摘要”。滑动窗口控制最近 N 轮对话的原始文本始终在上下文中保证模型对当前状态的感知当窗口快满时触发一次摘要操作把前面若干轮对话的核心内容压缩成一个“历史摘要”块替换掉原始文本以此来缓解上下文空间不够用的问题。长期记忆我用的是“向量库 结构化 JSON”双写策略。对话中凡是涉及用户偏好、项目关键参数、之前任务结论的内容都会在每轮结束后被抽取出来写入两个地方向量库用于后续语义检索结构化 JSON 用于精确 key-value 查询。比如用户上周说过“库存低于 100 要提醒我”这个偏好会被抽取成 {preference: low_stock_alert, threshold: 100}下次执行库存巡检任务时 Agent 可以先查 JSON 拿到这个阈值比向量检索更高效精准。长期记忆这里要特别注意一点不是所有对话内容都值得存。我一开始贪多求全什么内容都入库结果向量库越来越脏检索出来的结果经常误导 Agent。后来加了一层“记忆准入规则”——只有当信息满足“可执行”“可复用”“跨会话有效”三个条件之一时才写入长期记忆这个规则执行后记忆质量提升非常明显。2.4 状态机与执行循环如何避免 Agent 停不下来Agent 跑起来容易让它停下来难。我早期调试时遇到过 Agent 在一个失败工具上调用了十几次每次都报错每次都不换方案最后还是我手动 kill 进程才结束。后来我在 hermes-agent 里引入了两个核心机制步数硬上限和状态机流转校验。步数上限很好理解在配置里设置 max_steps默认 10 步不管 Agent 觉得自己有没有完成执行满 10 步就强制终止并返回“任务可能未完成”的提示。这个值不能设得太小也不能太大太小了复杂任务做不完太大了遇到死循环时白白消耗 token。按我的经验业务型任务设置在 8 到 15 步之间比较合适研究型任务可以放宽到 20 步左右。状态机流转校验更容易被忽略。hermes-agent 的执行状态我定义了四个PLANNING、EXECUTING、WAITING_OBSERVATION、FINISHED。每个状态定义了合法的跳转路径比如 PLANNING 只能跳 EXECUTING 或 FINISHED不能直接跳 WAITING_OBSERVATION。这类校验在实现上不难但能有效拦截模型的“乱跳”行为尤其是在并行任务场景下状态机规则能避免出现多个步骤同时执行导致的状态错乱。3. 实操过程与核心环节实现3.1 环境准备与基础配置真正动手做 hermes-agent 之前先把环境规范好。我推荐使用 Python 3.10 以上版本因为 Agent 项目大量用到 Pydantic v2 的特性旧版本会有兼容问题。项目依赖我放在 requirements.txt 里核心包包括 hermes-agent 主框架、openai 客户端库、pydantic、pyyaml、faiss-cpu向量检索用、loguru日志用。安装完依赖后第一件事不是写代码而是写配置文件。我把 hermes-agent 的配置分成了三层基础配置、模型配置、工具配置。基础配置包括 Agent 名称、日志级别、最大步数模型配置包括模型接口地址、API Key、温度参数工具配置包括每个工具的开关状态和独立参数。配置文件用 YAML 格式我最开始用 JSON但 JSON 不能写注释时间一长就忘了每个参数是干嘛的YAML 友好得多。贴一份简化版的核心配置agent: name: hermes-agent-dev max_steps: 12 max_retries: 3 log_level: DEBUG model: provider: openai_compatible base_url: ${MODEL_BASE_URL} api_key: ${MODEL_API_KEY} model_name: gpt-4o-mini temperature: 0.2 max_tokens: 2048 memory: short_window: 8 long_term_store: ./data/memory_store use_vector: true tools: query_inventory: enabled: true timeout_seconds: 10 send_email: enabled: true smtp_host: ${SMTP_HOST}注意我写的是${MODEL_BASE_URL}这种形式这是环境变量占位符。API Key 和密码这类敏感信息绝对不能硬编码进 YAML否则一旦配置文件被推到仓库就泄露了。我在项目里封装了一个配置加载函数先读取 YAML再递归替换环境变量占位符这个习惯真的很重要。3.2 核心代码实现Agent 主循环写法和执行流程配置好环境后核心就是 Agent 主循环。我把 hermes-agent 里最重要的循环逻辑简化成一段可运行的代码方便你看懂整个执行流程from hermes_agent.core import Agent, Task from hermes_agent.memory import MemoryManager from hermes_agent.tools import get_tool_schemas, call_tool agent Agent.from_config(config.yaml) def run_agent(goal: str): task Task(goalgoal) memory MemoryManager.from_config(agent.config) for step in range(1, agent.max_steps 1): # 1. 构建当前轮次的完整上下文 prompt build_execution_prompt( goaltask.goal, historymemory.get_recent_context(), tool_schemasget_tool_schemas(), last_observationtask.last_observation ) # 2. 请求模型返回一个决策 decision agent.llm.chat_json(prompt) if not decision: break # 3. 判断是否结束 if decision.get(action) finish: task.status completed task.final_answer decision.get(answer, ) break # 4. 执行工具调用 try: observation call_tool( decision[tool_name], decision[tool_params] ) except ToolExecutionError as e: observation { status: error, message: str(e), suggestion: 请检查参数后重试或尝试其他工具 } # 5. 记录观察结果到记忆 task.last_observation observation memory.add_step(step, decision, observation) # 6. 输出调试日志 logger.info( fStep {step}: {decision[description]} - {observation[status]} ) else: task.status unfinished task.final_answer 已达到最大步数限制未能完成目标 return task.to_dict()这段代码里最能看出 Agent 的节奏决策、执行、观察、再决策每一步的观察结果都要回灌到下一次的 Prompt 里。这里有个容易踩坑的细节最后那个else子句挂在 for 循环上是 Python 里“循环未被 break 时执行”的特殊用法。正常情况下模型会在最后输出 finish 动作跳出循环如果一直没输出循环耗尽就会走 else 分支任务状态标记为未完成。用这个写法比在循环内部判断step max_steps更简洁。3.3 工具集成示例从需求到注册完成的完整流程光有主循环还不够得接上真实工具才有价值。我用一个非常常见的“查天气再发通知”场景演示工具集成的完整流程。这个需求拆解下来是两步第一步查目标城市的天气数据第二步把结果发送到指定通知渠道。查天气工具的实现from hermes_agent import register_tool import httpx register_tool( namequery_weather, description根据城市名称查询当前天气情况, parameters{ type: object, properties: { city: {type: string, description: 城市中文名如北京}, days: {type: integer, description: 查询未来几天的天气默认1} }, required: [city] } ) async def query_weather(city: str, days: int 1): async with httpx.AsyncClient(timeout5) as client: resp await client.get( https://api.example.com/weather, params{city: city, days: days} ) resp.raise_for_status() data resp.json() return { status: success, city: city, days: days, weather: data[forecast] }发通知工具的实现register_tool( namesend_notification, description向指定渠道发送通知消息, parameters{ type: object, properties: { channel: { type: string, enum: [email, sms, dingtalk], description: 通知渠道 }, content: {type: string, description: 通知文本内容} }, required: [channel, content] } ) def send_notification(channel: str, content: str): if channel email: email_service.send(content) elif channel sms: sms_service.send(content) elif channel dingtalk: dingtalk_service.send(content) return {status: success, channel: channel}这两个工具注册完成后什么都不用改Agent 就能在收到“查一下上海明天天气然后邮件发给我”这样的指令时自己规划出两步骤先 query_weather 再 send_notification。这就是工具注册机制带来的扩展性优势——新增能力不需要改动主流程代码只需要写工具函数和 schema 描述就行。3.4 参数选择思路温度、步数、上下文窗口的平衡很多新手做 Agent 项目时对参数设置很随意温度默认填 1最大 token 填最大值看起来“给模型更多发挥空间”实际效果却很差。我在 hermes-agent 项目里调试出一套相对可靠的参数选择方法。先说温度。Agent 的规划环节本质上需要的是“稳定性”而不是“创造性”所以温度设置要偏低。我实测下来规划阶段的温度设置在 0.1 到 0.3 之间最合适。低于 0.1模型输出可能过于机械工具选择时容易漏掉最优解高于 0.3模型开始“自由发挥”可能出现工具名写错、参数格式不合法这类低级错误。如果是用于头脑风暴类的 Agent温度可以提高到 0.7但我建议把不同用途的 Agent 拆成不同配置而不是试图用一个温度兼顾所有场景。再说上下文窗口的预算分配。假设模型上下文窗口是 8K token我会这样分系统 Prompt 和工具 Schema 占 2K短期记忆和当前任务上下文占 4K模型输出预留 1.5K剩下 0.5K 作为缓冲。这个分配不是随便拍的因为工具 Schema 在 Agent 中可能非常长——我项目里挂载了 20 个工具时仅 schema 就有 1.5K 左右。如果工具继续增加就必须考虑“只向模型暴露必要的工具 Schema”而不是不分青红皂白全灌进去。3.5 效果示例一个真实任务的完整执行记录上面讲了半天原理不如看一个真实的执行日志。这是我用 hermes-agent 跑一个“查询本周销售数据并按渠道汇总邮件发送”任务时的调试输出2025-06-10 10:00:01 | INFO | 任务启动目标查询本周销售数据并按渠道汇总邮件发送 2025-06-10 10:00:03 | INFO | Step 1: 调用 query_sales_data(periodthis_week) 2025-06-10 10:00:06 | INFO | Step 1 完成 - {status: success, rows: 128} 2025-06-10 10:00:07 | INFO | Step 2: 调用 aggregate_by_channel(input上周数据) 2025-06-10 10:00:10 | WARNING | Step 2 失败 - {status: error, message: 字段 input 无法识别应传入 data 字段} 2025-06-10 10:00:10 | INFO | 触发参数重试机制 2025-06-10 10:00:12 | INFO | Step 2 retry: 调用 aggregate_by_channel(data上一步输出) 2025-06-10 10:00:14 | INFO | Step 2 完成 - {sales: {online: 5321, offline: 2103}} 2025-06-10 10:00:15 | INFO | Step 3: 调用 send_email(content本周线上销售 5321 元...) 2025-06-10 10:00:17 | INFO | Step 3 完成 - {status: success} 2025-06-10 10:00:17 | INFO | 任务完成总步数 3总耗时 16 秒注意 Step 2 的那次失败是我故意模拟的模型把 data 参数错写成了 input。要是没有重试机制整个任务到这里就断了。加了重试以后模型看到错误提示自己就把参数名改对了整个过程只多花了几秒。这也印证了我前面的观点Agent 项目里容错设计比算法设计更容易出效果。4. 常见问题与排查技巧实录4.1 模型输出的 JSON 总是解析失败怎么办这是 Agent 开发里发生率最高的问题。模型声称输出 JSON实际输出的内容里夹杂着解释性文字、Markdown 代码块标记、或者 JSON 格式本身不合法。我在 hermes-agent 里做了三道防线。第一道防线是 Prompt 强约束在系统提示里明确写“输出必须是合法 JSON不要使用 Markdown 代码块包裹不要输出任何解释文字”。第二道防线是解析容错先用正则去掉可能包裹的json 和标签再尝试 json.loads失败后尝试截取第一个{到最后一个}之间的内容再解析。第三道防线是格式纠正回调如果前两道都失败把“JSON 解析失败请重新输出合法 JSON”作为错误信息回传给模型让模型自己修正这一招对强模型特别有效。三道防线下来解析失败率能从最初的 20% 以上降到 2% 以下。当然如果模型实在拉胯用 JSON Mode 或者 Function Calling 接口是更省心的路子只不过不是所有模型都支持。4.2 上下文超长被截断任务做到一半就失忆了这个问题在长任务场景里几乎必现。Agent 每执行一步就把历史决策和观察结果追加到上下文里步骤一多上下文迟早爆掉。截断发生后模型会丢失任务早期的关键信息比如业务规则、用户偏好导致后面的决策质量断崖式下降。我推荐的解决思路是多层记忆压缩。当上下文接近窗口上限时先触发“步骤级摘要”把已经完成的前 N 步决策和观察用一小段总结替代。如果还不够再触发“目标级摘要”把整个任务的目标、已完成进度、剩余步骤压缩成结构化描述。经过这两层压缩后上下文占用通常能减少 60% 以上而且关键信息丢失的概率比直接暴力截断低得多。这里要记住一个原则永远不要把原始日志全部塞进上下文。日志是给人看的Agent 需要的是“状态摘要”和“决策依据”不是过程流水账。4.3 工具调用陷入死循环成本飞快上涨我在调一个数据分析 Agent 时遇到过最头疼的问题模型反复调用同一个工具每次都得到同样的结果然后继续调用同一工具好像脚本被卡住了一样。排查下来发现原因是模型没有从“失败的观察结果”中学到东西每次都走同样的路。解决死循环有两个有效手段。第一个是“循环检测”在执行循环中记录最近 N 步的工具调用指纹如果发现相同的工具和相同参数连续出现 3 次以上就打断循环并强制模型换策略。第二个是“失败惩罚提示”当某个工具调用失败后在上下文中追加一行“该工具上次调用失败请尝试修改参数或选择其他工具”给模型更强的行为引导。结合我自己的经历强烈建议在开发环境里把 API 调用成本监控配上。Agent 项目调试过程中很容易就跑出几美元的费用如果没有监控告警等发现的时候账单已经不好看了。4.4 常见问题速查表症状、原因和处理方案我把另外几个高频问题整理成表格方便你排查时对照参考。症状常见原因处理方案Agent 完全没调用任何工具直接回答工具 Schema 未正确加载或 Prompt 中工具描述不够明确检查工具注册表确认模型能看到工具描述工具被调用但参数全是空值参数描述缺失模型不知道要填什么在 schema 的 description 里写明参数来源同一错误反复出现且不修正模型能力不足重试提示未生效换更强模型或者在 Prompt 中强调阅读错误信息任务很快结束但答案错误模型“偷懒”规划时跳过了必要步骤提高 max_steps并在 Prompt 要求“先列出完整计划”本地模型响应极慢模型服务并发不足工具调用重试过多检查模型服务带宽缩短每步超时时间中文指令能懂但工具参数全是英文乱码编码问题工具返回值或日志编码不一致统一使用 UTF-8在 HTTP 请求头中声明字符集4.5 调试与可观测性让 Agent 的每一步都透明可控Agent 项目调试最大的痛点是“不可预测”——同样的输入两次运行的路径可能完全不一样出了问题很难复现。所以我从第一天起就在 hermes-agent 里做了完整的 trace 埋点。每一步的决策、工具调用、返回结果、重试次数、消耗的 token 数全部格式化输出到结构化日志里。日志记录分两级开发环境用“完整模式”所有原始 Prompt 和模型输出都保留生产环境用“摘要模式”只记录关键状态和异常信息避免把敏感数据刷进日志。把两步打通后排查问题时我通常这样操作先看 summary 日志定位是哪一步出问题再打开完整模式重新跑一遍拿到原始上下文最后对比模型输入的完整信息找出决策偏差的原因。我想强调的是Agent 项目的“可调试性”不是一个加分项而是必须项。没有这套观测体系你根本不知道模型是怎么得出某个结论的出了问题只能干瞪眼。如果你正在做 Agent 项目我建议你第一步先把 trace 系统搭起来再写业务逻辑也不迟。4.6 模型选型与降级策略最后聊一下模型选型。hermes-agent 这类框架通常号称“模型无关”但在真实使用中不同模型的 Agent 表现差距非常大。我在项目里体验下来顶级商用模型在规划能力和工具调用准确率上明显领先但也不是说本地模型就完全不能做 Agent只是需要更多的兜底设计。我的建议是采用“双层模型策略”主模型用能力强的商用模型负责规划和决策辅助模型用本地轻量模型负责摘要压缩和简单分类任务。这样既保证了核心路径的执行质量又把成本控制住了。同时要设计好降级链路——当主模型 API 不可用时自动切换到一个能力稍弱的备选模型继续执行而不是直接让整个 Agent 挂掉。Agent 的核心价值是自动化那么它自身的可用性也应该自动化保障。5. 写在最后的几点体会hermes-agent 这个项目我从零到一跑通花了大概一个多月回过头来看最大的体会是Agent 框架的代码真的不难写难的是如何驯服模型的不确定性。你说它聪明吧它会把参数名写错你说它笨吧给它错误提示它又能自己纠正。做 Agent 项目的核心能力其实就是设计一套“让模型犯错也不致命”的机制。如果你想上手这样的项目我建议从小处开始先不用追求复杂记忆、多工具并行这些高级特性找一个单一业务场景挂两三个工具把主循环跑通再逐步加入记忆和容错。踩过一次“死循环扣费”的坑之后你就知道 Agent 工程到底比写普通后端多哪些讲究了。最后再分享一个细节技巧给工具命名和写 description 时一定要参考“用户怎么说话”而不是“程序员怎么命名”。比如工具内部叫SalesQueryService没问题但对模型暴露的名字尽量用query_sales_data这种动词开头的短语description 里写清楚“这个工具干什么、什么场景用、不适用什么场景”。模型理解工具越准确整个 Agent 的表现就越靠谱。这些细节杂而不碎踩过坑之后你会明白它们才是决定一个 Agent 项目能不能落地的关键。