hermes-agent/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/agent-loop.md
Teknium 76135b329d
docs(i18n): translate all docs into Simplified Chinese (zh-Hans) (#31942)
Translates the full English docs corpus (335 files) into Simplified
Chinese under website/i18n/zh-Hans/. Combined with PR #31895 (cross-
locale link fix), the 简体中文 locale toggle now serves a complete
Chinese site with working cross-page navigation.

Pipeline:
- Claude Sonnet 4.6 via OpenRouter, 8-way concurrent
- Preserves frontmatter keys, code blocks, MDX/JSX, link URLs, brand
  names, and technical jargon (prompt/token/hook/MCP/ACP/etc.)
- Translates only frontmatter title/description and prose
- Two largest files (configuration.md 93KB, research-paper-writing.md
  107KB) retried with 64K max_tokens after initial fence-drift
- 3 manual post-fixes for MDX edge cases the model didn't escape:
  < in optional-skills-catalog table, double-quotes in an alt= tag,
  and a bare URL adjacent to a full-width period

Cost: ~$30 total (Sonnet 4.6 input $3/M + output $15/M).

Verified `npm run build` succeeds for both en and zh-Hans locales,
no double-prefixed /docs/zh-Hans/docs/ URLs in rendered output,
all in-page navigation resolves correctly.

Translations are machine-generated and may need human review on
specific pages — but they're an enormous improvement over the
previous state (3 zh-Hans pages out of 335).
2026-05-25 01:47:38 -07:00

10 KiB
Raw Blame History

sidebar_position title description
3 Agent Loop 内部机制 AIAgent 执行流程、API 模式、工具、回调及回退行为的详细说明

Agent Loop 内部机制

核心编排引擎是 run_agent.py 中的 AIAgent 类——这是一个大型文件15k+ 行),负责处理从 prompt提示词组装到工具分发再到 provider 故障转移的所有逻辑。

核心职责

AIAgent 负责:

  • 通过 prompt_builder.py 组装有效的系统 prompt 和工具 schema
  • 选择正确的 provider/API 模式(chat_completionscodex_responsesanthropic_messages
  • 发起支持取消操作的可中断模型调用
  • 执行工具调用(顺序执行或通过线程池并发执行)
  • 以 OpenAI 消息格式维护对话历史
  • 处理压缩、重试和回退模型切换
  • 跨父 agent 和子 agent 追踪迭代预算
  • 在上下文丢失前将持久化内存刷写到磁盘

两个入口点

# 简单接口——返回最终响应字符串
response = agent.chat("Fix the bug in main.py")

# 完整接口——返回包含消息、元数据、用量统计的 dict
result = agent.run_conversation(
    user_message="Fix the bug in main.py",
    system_message=None,           # 省略时自动构建
    conversation_history=None,      # 省略时自动从 session 加载
    task_id="task_abc123"
)

chat() 是对 run_conversation() 的轻量封装,从结果 dict 中提取 final_response 字段。

API 模式

Hermes 支持三种 API 执行模式,通过 provider 选择、显式参数和 base URL 启发式规则来确定:

API 模式 用途 客户端类型
chat_completions 兼容 OpenAI 的端点OpenRouter、自定义及大多数 provider openai.OpenAI
codex_responses OpenAI Codex / Responses API openai.OpenAI(使用 Responses 格式)
anthropic_messages 原生 Anthropic Messages API 通过适配器使用 anthropic.Anthropic

模式决定了消息的格式化方式、工具调用的结构、响应的解析方式,以及缓存/流式传输的工作方式。三种模式在 API 调用前后均收敛到相同的内部消息格式OpenAI 风格的 role/content/tool_calls dict

模式解析顺序:

  1. 显式 api_mode 构造函数参数(最高优先级)
  2. Provider 特定检测(例如 anthropic provider → anthropic_messages
  3. Base URL 启发式规则(例如 api.anthropic.comanthropic_messages
  4. 默认:chat_completions

单轮生命周期

agent loop 的每次迭代按以下顺序执行:

run_conversation()
  1. 若未提供则生成 task_id
  2. 将用户消息追加到对话历史
  3. 构建或复用已缓存的系统 promptprompt_builder.py
  4. 检查是否需要预检压缩(上下文超过 50%
  5. 从对话历史构建 API 消息
     - chat_completions直接使用 OpenAI 格式
     - codex_responses转换为 Responses API 输入项
     - anthropic_messages通过 anthropic_adapter.py 转换
  6. 注入临时 prompt 层(预算警告、上下文压力提示)
  7. 若使用 Anthropic应用 prompt 缓存标记
  8. 发起可中断的 API 调用_interruptible_api_call
  9. 解析响应:
     - 若有 tool_calls执行工具追加结果回到步骤 5
     - 若为文本响应:持久化 session按需刷写内存返回

消息格式

所有消息在内部均使用兼容 OpenAI 的格式:

{"role": "system", "content": "..."}
{"role": "user", "content": "..."}
{"role": "assistant", "content": "...", "tool_calls": [...]}
{"role": "tool", "tool_call_id": "...", "content": "..."}

推理内容(来自支持扩展思考的模型)存储在 assistant_msg["reasoning"] 中,并可选择通过 reasoning_callback 展示。

消息交替规则

agent loop 强制执行严格的消息角色交替规则:

  • 系统消息之后:User → Assistant → User → Assistant → ...
  • 工具调用期间:Assistant含 tool_calls→ Tool → Tool → ... → Assistant
  • 不允许连续出现两条 assistant 消息
  • 不允许连续出现两条 user 消息
  • 只有 tool 角色可以连续出现(并行工具结果)

Provider 会验证这些序列,并拒绝格式错误的历史记录。

可中断的 API 调用

API 请求被封装在 _interruptible_api_call() 中,该方法在后台线程中执行实际的 HTTP 调用,同时监听中断事件:

┌────────────────────────────────────────────────────┐
│  主线程                        API 线程             │
│                                                    │
│   等待:                        HTTP POST           │
│    - 响应就绪          ───▶    发送至 provider       │
│    - 中断事件                                       │
│    - 超时                                          │
└────────────────────────────────────────────────────┘

当发生中断(用户发送新消息、/stop 命令或信号)时:

  • API 线程被放弃(响应被丢弃)
  • agent 可以处理新输入或干净地关闭
  • 不会将部分响应注入对话历史

工具执行

顺序执行与并发执行

当模型返回工具调用时:

  • 单个工具调用 → 直接在主线程中执行
  • 多个工具调用 → 通过 ThreadPoolExecutor 并发执行
    • 例外:标记为交互式的工具(如 clarify)强制顺序执行
    • 无论完成顺序如何,结果均按原始工具调用顺序重新插入

执行流程

for each tool_call in response.tool_calls:
    1. 从 tools/registry.py 解析处理器
    2. 触发 pre_tool_call 插件 hook
    3. 检查是否为危险命令tools/approval.py
       - 若危险:调用 approval_callback等待用户确认
    4. 使用参数 + task_id 执行处理器
    5. 触发 post_tool_call 插件 hook
    6. 将 {"role": "tool", "content": result} 追加到历史

Agent 级工具

部分工具在到达 handle_function_call() 之前,由 run_agent.py 提前拦截:

工具 拦截原因
todo 读写 agent 本地任务状态
memory 向持久化内存文件写入内容(有字符限制)
session_search 通过 agent 的 session DB 查询 session 历史
delegate_task 以隔离上下文生成子 agent

这些工具直接修改 agent 状态,并返回合成的工具结果,不经过注册表。

回调接口

AIAgent 支持平台特定的回调,用于在 CLI、gateway 和 ACP 集成中实现实时进度展示:

回调 触发时机 使用方
tool_progress_callback 每次工具执行前后 CLI spinner、gateway 进度消息
thinking_callback 模型开始/停止思考时 CLI "thinking..." 指示器
reasoning_callback 模型返回推理内容时 CLI 推理展示、gateway 推理块
clarify_callback 调用 clarify 工具时 CLI 输入提示、gateway 交互消息
step_callback 每次完整 agent 轮次结束后 Gateway 步骤追踪、ACP 进度
stream_delta_callback 每个流式 token启用时 CLI 流式展示
tool_gen_callback 从流中解析出工具调用时 CLI spinner 中的工具预览
status_callback 状态变更时(思考、执行等) ACP 状态更新

预算与回退行为

迭代预算

agent 通过 IterationBudget 追踪迭代次数:

  • 默认90 次迭代(可通过 agent.max_turns 配置)
  • 每个 agent 拥有独立预算。子 agent 获得独立预算,上限为 delegation.max_iterations(默认 50——父 agent 与子 agent 的总迭代次数可超过父 agent 的上限
  • 达到 100% 时agent 停止并返回已完成工作的摘要

回退模型

当主模型失败时429 限流、5xx 服务器错误、401/403 鉴权错误):

  1. 检查配置中的 fallback_providers 列表
  2. 按顺序尝试每个回退 provider
  3. 成功后,使用新 provider 继续对话
  4. 遇到 401/403 时,在故障转移前尝试刷新凭据

回退系统也独立覆盖辅助任务——视觉、压缩和网页提取各自拥有独立的回退链,可通过 auxiliary.* 配置节进行配置。

压缩与持久化

压缩触发时机

  • 预检API 调用前):对话超过模型上下文窗口的 50%
  • Gateway 自动压缩:对话超过 85%(更激进,在轮次之间运行)

压缩过程

  1. 首先将内存刷写到磁盘(防止数据丢失)
  2. 将中间对话轮次摘要为紧凑的摘要内容
  3. 保留最后 N 条消息完整不变(compression.protect_last_n默认20
  4. 工具调用/结果消息对保持完整(不拆分)
  5. 生成新的 session 血缘 ID压缩会创建一个"子" session

Session 持久化

每轮结束后:

  • 消息保存到 session 存储(通过 hermes_state.py 使用 SQLite
  • 内存变更刷写到 MEMORY.md / USER.md
  • 可通过 /resumehermes chat --resume 恢复 session

关键源文件

文件 用途
run_agent.py AIAgent 类——完整的 agent loop
agent/prompt_builder.py 从内存、技能、上下文文件和个性组装系统 prompt
agent/context_engine.py ContextEngine ABC——可插拔的上下文管理
agent/context_compressor.py 默认引擎——有损摘要算法
agent/prompt_caching.py Anthropic prompt 缓存标记和缓存指标
agent/auxiliary_client.py 用于辅助任务的辅助 LLM 客户端(视觉、摘要)
model_tools.py 工具 schema 集合,handle_function_call() 分发

相关文档