1. Hermes Agent Loop 是什么它解决的不是“能不能跑”而是“怎么跑得稳、跑得准、跑得可追溯”如果你最近在 GitHub 上搜 AIAgent 相关项目或者在技术社区里看到有人讨论“Hermes Agent v0.21Bot Mode”、“Hermes Studio 下载”、“Hermes 接入企微 Bot 后用户 ID 加密怎么解析”甚至刷到“Ubuntu 安装 Hermes”“Windows Hermes Agent 桌面版配置”这类实操帖——那你大概率已经踩进了 Hermes 的实际落地现场。它不是又一个玩具级 LLM 封装工具而是一套面向生产环境设计的智能体执行框架核心价值不在“调用大模型”而在“让大模型的每一次推理、每一次工具调用、每一次状态流转都可观察、可干预、可审计”。Hermes Agent Loop 这个标题里的“Loop”绝不是指简单循环调用 API而是指一个闭环的、带状态管理、带错误熔断、带上下文保鲜、带工具调度仲裁的执行生命周期。我去年在给一家做智能客服中台的客户做 PoC 时就拿 Hermes 替换了他们原来自研的“Prompt 函数名硬编码”方案。原来一个订单查询流程要写 7 个 if-else 分支判断用户意图现在只用定义 3 个 toolget_order_status、get_refund_policy、escalate_to_human然后靠 Hermes 的 Loop 自动决策调用顺序和终止条件。上线后意图识别误判率从 18% 降到 2.3%更关键的是——当某次get_order_status返回超时系统不是直接崩掉或返回模糊提示而是自动降级到缓存数据 记录 trace_id运维同事能立刻在日志里定位是哪个环节卡住、重试了几次、最终用了哪条 fallback 路径。这才是 Loop 的真实分量它把 AI 的不确定性装进了一个确定性的执行容器里。你可能注意到热搜词里反复出现 “API mode” 和 “tool execution”。这恰恰点破了 Hermes 的底层设计哲学它不试图替代 LLM而是做 LLM 的“执行管家”。LLM 只负责生成 JSON 格式的 tool call 请求比如{ name: search_knowledge_base, arguments: { query: 发票开具流程 } }Hermes 负责解析这个 JSON、校验参数合法性、查白名单、限流、打日志、调用真实函数、捕获异常、决定是否重试或切换工具、再把结果结构化塞回上下文——整个过程对 LLM 透明但对开发者完全可控。这也是为什么你会看到“Hermes Agent OBSIDIAN”“Hermes 配合什么开发工具使用”这类搜索——它天然适配 Obsidian 做知识图谱联动、适配 VS Code 做本地调试、适配企业微信 Bot 做会话路由因为它不绑定任何前端形态只专注把“指令→执行→反馈”这个链条打磨到工业级精度。所以别被“Agent”这个词带偏去想科幻电影里的自主意识体。Hermes Agent Loop 的本质是一套为 LLM 应用服务的、轻量级但高可靠的执行中间件。它适合三类人一是正在把大模型能力嵌入现有业务系统的后端工程师需要稳定、可监控的工具链二是做垂直领域智能体如法律咨询、IT 运维助手的产品经理需要快速验证 tool 组合效果并沉淀 SLO三是高校研究者想在可控环境下复现 agent 决策路径而不是被黑盒模型输出牵着鼻子走。接下来我们就一层层剥开这个 Loop 的筋骨看它到底怎么把“AI 能力”变成“可交付的软件模块”。2. 整体架构设计为什么 Hermes 不用 LangChain也不学 AutoGen它的 Loop 是“窄而深”的工程选择Hermes 的架构图在官网文档里只有一页但背后全是取舍。它没有像 LangChain 那样堆砌 50 模块Chain、Memory、Callback、OutputParser…也没有像 AutoGen 那样搞多 agent 协作编排。它的核心就一张图Input → Planner → Tool Executor → State Manager → Output五步闭环每一步都针对真实生产痛点做了加固。这种“窄而深”的设计不是功能少而是把有限的精力全砸在最关键的执行环节上。我拆过 v0.21 的源码它的 Loop 主循环代码不到 200 行但每个函数都有 3 层防御输入校验、执行熔断、结果归一化。下面说说这五步为什么这么设计以及它刻意避开哪些“看起来很美”的坑。2.1 Planner拒绝“自由发挥”只做结构化意图解析很多团队用 LLM 做 agent 时第一步就栽在 Planner 上。他们让模型直接输出“下一步该做什么”结果模型一会儿说“查数据库”一会儿说“发邮件”一会儿又“调用天气 API”完全不可控。Hermes 的 Planner 强制要求 LLM 输出严格符合预定义 schema 的 JSON比如{ tool_name: search_knowledge_base, tool_args: { query: 如何申请电子发票, category: finance }, confidence: 0.92 }这个 schema 不是随便定的。tool_name必须来自注册的 tool 白名单防止模型胡编函数名tool_args的字段和类型由 tool 定义时的 Pydantic Model 约束比如query是 strcategory是枚举值confidence是模型自己打的分用于后续熔断决策。我实测过在 DeepSeek-Hermes 模型上加了这个 schema 约束后Planner 的输出合规率从 63% 提升到 99.2%。关键是这个约束不靠 prompt 巧妙引导而是靠JSON Schema Validator 在 runtime 强制校验——如果模型输出格式不对直接报错绝不容错。这听起来反直觉但正是生产环境需要的宁可失败一次也不能让错误指令流入下游。提示Hermes 的 Planner 不做“多步规划”它只管当前 step。所谓“多步”是靠 Loop 外层的状态机驱动的。比如用户问“帮我查订单再告诉我怎么退货”Planner 第一次只输出get_order_status等结果回来拼进 context再触发第二次 Planner才可能输出get_refund_policy。这种“单步聚焦”设计让每一步的输入输出边界极其清晰debug 时一眼就能看出是哪次调用出了问题。2.2 Tool Executor不是简单反射调用而是带策略的执行引擎Tool Executor 看似只是“找到函数并执行”但 Hermes 给它加了四层策略第一层是权限沙箱。每个 tool 注册时必须声明scope如user:read、order:writeExecutor 会检查当前 session 的 token 权限是否匹配。这直接解决了“Hermes 接入企微 Bot 后用户 ID 加密怎么解析”的根源问题——不是去破解加密而是让 tool 执行前先校验session.user_id是否有权限调用get_user_profile。第二层是熔断器。默认配置下单个 tool 连续 3 次超时5s或 5 次异常就会被自动熔断 60 秒。熔断期间所有对该 tool 的请求直接返回预设 fallback比如缓存数据或兜底文案避免雪崩。我在压测时故意把search_knowledge_base的 mock 延迟设成 10s结果 Loop 自动降级到本地 SQLite 缓存用户无感知。第三层是参数归一化。比如get_order_status的order_id参数可能来自用户口语“查我昨天下的单”、来自企微消息的event.order_id字段、或来自上一步 tool 的返回值。Executor 会统一调用normalize_order_id()函数做标准化确保传给后端服务的永远是 12 位纯数字字符串。第四层是可观测性埋点。每次执行都会记录tool_name、input_hash、duration_ms、statussuccess/timeout/error、retry_count这些日志直接对接 Prometheus不用额外写监控代码。2.3 State Manager用轻量级状态机替代复杂 MemoryHermes 没有搞复杂的 ConversationBufferMemory 或 SummaryMemory。它的 State Manager 就是一个带 TTL 的 key-value storekey 是session_idvalue 是一个精简的 dict{ history: [ {role: user, content: 查订单}, {role: assistant, tool_call: {...}, tool_result: {...}}, {role: user, content: 退货流程呢} ], context: { user_info: {id: enc_abc123, level: vip}, last_order: {id: ORD20240501001, status: shipped} }, loop_count: 3, max_loop: 8 }注意两点第一history只存原始对话和 tool 交互不存 LLM 的 intermediate reasoning那些“让我思考一下…”的废话省下 70% token第二context是结构化数据不是大段文本方便后续 tool 直接读取字段比如context.last_order.id。这个设计牺牲了“记忆浪漫感”换来了极高的状态同步效率——在分布式部署时State Manager 可以直接用 Redis Cluster不需要强一致的分布式事务。我们线上集群用 Redis平均状态读写延迟 8ms比用 PostgreSQL 存 conversation history 快 12 倍。2.4 Loop 的闭环逻辑为什么它叫 Loop而不是 PipelinePipeline 是线性的A→B→C走完就结束。Hermes 的 Loop 是带条件跳转的状态机[Start] ↓ [Planner] → (output valid?) → No → [Error Handler] → [Retry or Fallback] ↓ Yes [Tool Executor] → (success?) → No → [Error Handler] → [Retry or Fallback] ↓ Yes [State Update] → (should continue?) → Yes → [Planner] (next iteration) ↓ No [Output Generator] → [End]这个“should continue?” 判断逻辑很关键。它不依赖 LLM 的“自我判断”而是由三个硬规则控制loop_count max_loop防死循环默认 8tool_result.get(final_answer) is not Nonetool 显式标记这是终局答案planner_confidence 0.7且loop_count 3低置信度还反复调用说明卡住了强制终止。我见过太多 agent 因为模型反复在两个 tool 间横跳比如search_knowledge_base→get_refund_policy→search_knowledge_base→ …而耗尽 token。Hermes 用这三条规则把“无限 loop”变成了“有限试探”既给了模型发挥空间又守住了底线。3. 核心细节解析从 Ubuntu 安装到企微 Bot 接入手把手拆解每个关键环节光看架构不够得落到键盘上。Hermes 的安装和配置不像 Docker 一键 run 那么傻瓜但也没到要编译内核的程度。它的设计哲学是“让懂的人快让新手不懵”。下面我按真实部署顺序把从零开始到接入企微 Bot 的全流程拆解重点讲清每个步骤背后的 why而不是 just copy-paste。3.1 环境准备为什么推荐 Ubuntu 22.04 LTS而不是 Windows 桌面版官方文档说支持 Windows但实际生产环境我强烈建议用 Ubuntu 22.04 LTS。原因有三第一tool 依赖的兼容性。Hermes 默认集成的search_knowledge_basetool 依赖llama-cpp-python而 Windows 上编译 llama.cpp 的 wheel 包经常出问题尤其是 CUDA 版本冲突。Ubuntu 22.04 的 GCC 11.2 和 glibc 版本与官方预编译 wheel 完全匹配pip install hermes-agent一行搞定。第二systemd 服务管理。生产环境不可能一直开着 terminal。Ubuntu 下用 systemd 写个 service 文件/etc/systemd/system/hermes.service就能实现开机自启、日志轮转、内存超限自动重启。Windows 桌面版的“后台运行”其实是伪装成托盘程序一旦用户登出就停了。第三企微 Bot 的网络策略。企业微信服务器只接受 HTTPS 回调且要求域名备案。Ubuntu 上用 Nginx 反向代理 Lets Encrypt 免费证书5 分钟搞定Windows 桌面版还得折腾 IIS 或 Caddy证书更新也麻烦。实操心得我在测试环境用过 Windows 桌面版v0.21最大的坑是hermes agent obsidian插件无法读取本地 vault 的.obsidian/plugins目录因为 Windows 路径权限机制和 Obsidian 的 sandbox 冲突。切到 Ubuntu WSL2 后用ln -s /mnt/c/Users/xxx/ObsidianVault ~/obsidian-vault建软链问题消失。所以别被“桌面版”字眼迷惑它本质是个本地开发辅助工具不是生产运行载体。3.2 安装部署指定安装目录的正确姿势以及为什么不能用--userHermes 官网下载页提供 tar.gz 包解压后是hermes-core和hermes-studio两个目录。很多人直接cd hermes-core pip install -e .结果发现hermes命令找不到。这是因为 pip 的-e模式会把包装到 Python site-packages 的 egg-link 文件里而hermesCLI 是通过pyproject.toml的console_scriptsentry point 注册的需要pip install后重新生成 console script。正确指定安装目录的步骤以/opt/hermes为例# 1. 创建目录并赋权 sudo mkdir -p /opt/hermes sudo chown $USER:$USER /opt/hermes # 2. 解压到目标目录 tar -xzf hermes-core-v0.21.tar.gz -C /opt/hermes --strip-components1 # 3. 进入目录用 pip install不是 pip install -e cd /opt/hermes pip install . # 4. 验证安装 hermes --version # 应输出 0.21.0注意绝对不要用pip install --user。因为--user会把 CLI 脚本装到~/.local/bin而这个路径不一定在$PATH里尤其 systemd service 启动时。sudo pip install也不行会导致权限混乱。最佳实践是用venv隔离python3 -m venv /opt/hermes/venv source /opt/hermes/venv/bin/activate pip install /opt/hermes # 注意是目录路径不是 ./3.3 配置文件详解config.yaml里每个字段的真实作用Hermes 的灵魂在config.yaml。它不像其他框架那样有几十个配置项核心就 7 个 section但每个都直击要害# config.yaml llm: provider: deepseek # 支持 deepseek, ollama, openai model: deepseek-chat # 模型名必须和 provider 对应 api_base: http://localhost:8000/v1 # 如果用 ollama这里是 http://localhost:11434 api_key: sk-xxx # deepseek 官网申请的 key tools: - name: search_knowledge_base module: hermes.tools.kb_search enabled: true timeout: 10 # 单位秒超时即熔断 - name: get_user_profile module: hermes.tools.user_profile enabled: true scope: [user:read] # 权限 scope和企微 token 校验联动 state: backend: redis # 可选 redis, memory, file redis_url: redis://localhost:6379/0 webhook: port: 8001 # 接收企微回调的端口 secret: your_wecom_secret # 企微后台配置的 callback secret logging: level: INFO file: /var/log/hermes/hermes.log # 日志路径需提前创建目录 observability: prometheus_port: 9090 # 暴露 metrics 的端口关键字段解读llm.api_base如果填http://localhost:8000/v1Hermes 会按 OpenAI 格式调用如果填http://localhost:11434Ollama 默认它会自动转换成 Ollama 格式。不用改代码靠配置驱动。tools.timeout不是简单的requests.timeout而是整个 tool 执行周期包括参数归一化、权限校验、实际函数调用的总超时。我设过 3s结果search_knowledge_base因为 ES 查询慢被频繁熔断改成 10s 后稳定。webhook.secret这就是解决“hermes接入企微bot拿到的会话用户id是加密的怎么解析”的钥匙。企微回调的user_id是加密的但msg_signature是用这个 secret 算出来的 HMAC-SHA256。Hermes 内置校验逻辑只要 secret 匹配就自动解密user_id并存入state.context.user_info.id后续 tool 直接用。observability.prometheus_port暴露的 metrics 包含hermes_tool_calls_total{tool_namesearch_knowledge_base,statussuccess}这种维度配合 Grafana 就能做出“各 tool 成功率趋势图”比翻日志高效十倍。3.4 接入企微 Bot从创建 Bot 到解析加密 user_id 的完整链路这是热搜词里最高频的场景。整个流程分四步每步都有易错点Step 1企微后台创建 Bot进入「管理后台」→「应用管理」→「创建应用」→ 类型选「内部应用」关键设置可信域名填你服务器的公网域名如hermes.yourcompany.com不是 IP接收消息服务器配置的URL填https://hermes.yourcompany.com/callback注意是 httpsToken和EncodingAESKey随便填Hermes 不用这两个它用secret做签名校验回调 URL的Secret复制下来粘贴到config.yaml的webhook.secret。Step 2Nginx 反向代理配置server { listen 443 ssl; server_name hermes.yourcompany.com; ssl_certificate /etc/letsencrypt/live/hermes.yourcompany.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/hermes.yourcompany.com/privkey.pem; location /callback { proxy_pass http://127.0.0.1:8001; # 对应 config.yaml 的 webhook.port proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }注意proxy_pass后面不能加/否则路径会变成http://127.0.0.1:8001//callbackHermes 路由匹配失败。Step 3Hermes 启动并监听# 激活 venv source /opt/hermes/venv/bin/activate # 启动自动加载 config.yaml hermes serve --config /opt/hermes/config.yaml启动后访问https://hermes.yourcompany.com/callback应返回{status: ok}这是企微健康检查的 endpoint。Step 4解析加密 user_id 的实操企微回调的 body 是 XML其中FromUserName字段是加密的。Hermes 在hermes/webhook/wecom.py里做了三件事用webhook.secret和回调的msg_signature、timestamp、nonce重新计算 HMAC-SHA256校验通过后用encoding_aes_key企微后台生成的 43 位 base64 字符串解密FromUserName解密结果是USERIDCORPID格式Hermes 自动拆成user_idUSERID和corp_idCORPID存入 state。所以你在 tool 里直接写context.user_info.id就能拿到明文 user_id根本不用自己写解密逻辑。这也是为什么搜索“hermes接入企微bot拿到的会话用户id是加密的怎么解析”会有那么多困惑——答案就是别解析Hermes 已帮你做完。4. 实操过程与核心环节实现从零写一个get_refund_policytool看 Loop 如何驱动它理论说完来个实战。我们以“获取退货政策”这个高频需求为例手写一个完整的 tool并让它被 Hermes Loop 自动调度。这个过程能让你彻底看清Hermes 怎么把一段 Python 函数变成 Loop 里可插拔、可监控、可熔断的执行单元。4.1 Tool 开发遵循 Hermes 的 4 个契约Hermes 的 tool 不是随便写的函数必须满足四个契约否则 Loop 不认契约 1函数签名必须是def tool_name(**kwargs) - Dict[str, Any]不能有位置参数所有输入都通过**kwargs传入。这样 Planner 输出的 JSON 才能无缝映射。契约 2必须有tool装饰器且声明name和descriptionfrom hermes.tool import tool tool( nameget_refund_policy, descriptionGet refund policy for a specific product category. Input: category (str, e.g., electronics, clothing) ) def get_refund_policy(**kwargs) - dict: category kwargs.get(category, general) # 实际业务逻辑 policies { electronics: 7 days unopened, with original packaging, clothing: 30 days, with tags attached, general: 14 days, no questions asked } return { policy: policies.get(category, policies[general]), valid_until: 2025-12-31 }契约 3必须有 Pydantic Model 定义参数规范在同目录下建schema.pyfrom pydantic import BaseModel class GetRefundPolicyInput(BaseModel): category: str # 必填字段类型 str # Hermes 会用这个 Model 校验 Planner 输出的 arguments契约 4必须在config.yaml的tools列表里注册tools: - name: get_refund_policy module: hermes.tools.refund_policy # 模块路径对应 refund_policy.py enabled: true timeout: 5 scope: [policy:read]4.2 注册与发现Hermes 怎么找到你的 toolHermes 启动时会扫描config.yaml里tools列表的module路径动态 import 模块。关键在hermes/tool/__init__.py的load_tools()函数def load_tools(config_tools: List[dict]) - Dict[str, Tool]: tools {} for tool_config in config_tools: if not tool_config.get(enabled): continue module importlib.import_module(tool_config[module]) # 找到模块里所有被 tool 装饰的函数 for attr_name in dir(module): attr getattr(module, attr_name) if hasattr(attr, _is_hermes_tool): # tool 装饰器打的标记 tools[attr._tool_name] attr return tools所以只要你把refund_policy.py放在hermes/tools/目录下并在config.yaml里正确配置moduleHermes 就能自动发现它。不用改任何框架代码。4.3 Loop 调度实录一次完整的get_refund_policy执行过程我们模拟用户发送消息“手机坏了怎么退货”。以下是 Hermes 日志里截取的真实执行链路已脱敏# Step 1: Planner 接收输入生成 tool call INFO: Planner input: [{role:user,content:手机坏了怎么退货}] INFO: Planner output: {tool_name:get_refund_policy,tool_args:{category:electronics},confidence:0.87} # Step 2: Tool Executor 校验参数 INFO: Validating tool_args for get_refund_policy with schema GetRefundPolicyInput INFO: Validation passed. categoryelectronics # Step 3: 权限校验检查 session token 是否有 policy:read INFO: Permission check passed for scope [policy:read] # Step 4: 执行函数 INFO: Executing get_refund_policy with args {category: electronics} INFO: get_refund_policy returned {policy: 7 days unopened, with original packaging, valid_until: 2025-12-31} # Step 5: 更新 state INFO: Updated state.context.refund_policy {policy: 7 days unopened..., valid_until: 2025-12-31} # Step 6: Loop 判断是否继续 INFO: Loop count 1/8. tool_result has no final_answer. Continuing...接着Planner 收到新 context含refund_policy字段生成第二轮输出{ tool_name: none, final_answer: 根据我们的退货政策手机属于电子产品支持7天内未拆封、原包装完好情况下退货。有效期至2025年12月31日。 }Loop 检测到final_answer直接跳到 Output Generator返回给企微。实操心得我在写第一个 tool 时犯了个典型错误——把return {policy: ...}写成return 7 days...字符串。结果 Loop 报错TypeError: expected dict, got str。Hermes 的严格性在这里体现它要求 tool 输出必须是结构化 dict这样后续步骤才能可靠地提取字段。这个“不灵活”恰恰是生产环境最需要的确定性。4.4 监控与调优如何用 Prometheus 查看这个 tool 的健康度Hermes 暴露的 metrics 端点/metrics里关于get_refund_policy的指标有hermes_tool_calls_total{tool_nameget_refund_policy,statussuccess}hermes_tool_calls_total{tool_nameget_refund_policy,statustimeout}hermes_tool_duration_seconds_bucket{tool_nameget_refund_policy,le5}直方图看多少请求在 5s 内完成我在 Grafana 里建了个面板发现get_refund_policy的timeoutrate 突然升到 12%。排查发现是因为category字段有时是用户口语“我买的苹果手机”而我的schema.py里category: str没做清洗导致函数里policies.get(苹果手机)返回 None函数卡在return前。解决方案是在 tool 函数里加清洗逻辑def get_refund_policy(**kwargs) - dict: raw_category kwargs.get(category, general) # 清洗映射口语到标准分类 category_map {手机: electronics, 电脑: electronics, 衣服: clothing} category category_map.get(raw_category, raw_category) # ... rest of logic加了这三行timeout rate 降到 0.3%。这就是 Loop Metrics 带来的精准治理能力问题在哪优化哪不靠猜。5. 常见问题与排查技巧实录那些官网没写的坑我都替你踩过了Hermes 文档写得简洁但真实世界远比文档复杂。我把过去一年在 3 个客户项目里遇到的、最常被问到的 7 个问题连同根因和速查方案整理成表。这些问题90% 的新手会在头两周撞上。问题现象根本原因速查命令/步骤解决方案hermes serve启动报错ModuleNotFoundError: No module named hermespip install未成功或 venv 未激活which hermes看命令路径python -c import hermes; print(hermes.__file__)用pip install /opt/hermes绝对路径重装确认source venv/bin/activate企微回调 404Nginx 日志显示upstream prematurely closed connectionHermes 服务未启动或webhook.port配置和proxy_pass不一致curl -v http://127.0.0.1:8001/callbackss -tuln | grep :8001检查config.yaml的webhook.port确认hermes serve进程在运行systemctl status hermesPlanner 总是输出tool_name: noneLoop 不调用任何 toolLLM 模型未正确加载或llm.model名称拼写错误hermes llm-test --config config.yaml内置测试命令检查config.yaml的llm.model是否和模型服务实际名称一致如 ollama list 显示deepseek-chat:latest则填deepseek-chatget_user_profiletool 执行时报Permission denied: user:read企微回调的user_id未成功解密导致state.context.user_info为空hermes state-get --session session_id查看 state 内容检查config.yaml的webhook.secret是否和企微后台完全一致大小写、空格确认企微回调的msg_signature正确search_knowledge_base返回空结果但 ES 集群正常tool 的index_name配置错误或query字段未映射为text类型curl -X GET http://es:9200/index_name/_mapping在config.yaml的 tool 配置里加index: kb_articlesES mapping 中确保content字段 type 为textLoop 执行 3 次后就停止max_loop未生效config.yaml的max_loop写在了错误层级如写在llm:下hermes config-validate --config config.yaml验证配置语法max_loop必须是顶级字段和llm:、tools:同级hermes agent obsidian插件不显示知识库内容Obsidian vault 路径权限不足或config.yaml的obsidian_vault_path是相对路径ls -l /path/to/vault/.obsidian/plugins检查config.yaml中路径是否以/开头用绝对路径配置obsidian_vault_path: /home/user/my-vaultchmod -R 755 /home/user/my-vault5.1 最难 debug 的问题Planner 置信度忽高忽低导致 Loop 行为不稳定这是高级用户才会遇到的深度问题。现象是同样一句话“查我的订单”有时 Planner 输出get_order_statusconfidence 0.95有时输出noneconfidence 0.42毫无规律。根因往往不在 Hermes而在 LLM 的 temperature 设置。Hermes 的 Planner 默认用temperature0.3这是为了降低随机性。但如果 LLM 服务端如 Ollama的全局配置是temperature0.7那每次请求的实际温度就是 0.7导致输出抖动。解决方案有两个方案 A推荐在config.yaml的llm下显式覆盖llm: # ... other fields temperature: 0.3 # 强制固定 top_p: 0.9方案 B在 LLM 服务端统一配置如果是 Ollama编辑~/.ollama/config.json{ temperature: 0.3, top_p: 0.9 }我选方案 A因为它是 per-app 配置不影响其他服务。加了这行后Planner 的 confidence 标准差从 0.28 降到 0.05Loop 行为