Hermes Agent 源码专题【左扬精讲】—— AIAgent 核心循环:消息处理与工具调用

Hermes Agent 核心原理专题【左扬精讲】—— AIAgent 核心循环:消息处理与工具调用

本文深入剖析 AIAgent 的核心对话循环:消息如何组织、工具调用如何解析、迭代如何控制、错误如何恢复。

agent/conversation_loop.py   ← 核心对话循环逻辑
run_agent.py                 ← AIAgent 主类(含 _execute_tool_calls 等方法)
agent/iteration_budget.py    ← 线程安全的迭代预算计数器
agent/error_classifier.py    ← API 错误分类与恢复策略
agent/tool_executor.py       ← 工具调用执行器(并发/顺序)

消息格式 工具调用 迭代控制 错误恢复

学习重点提示

必须掌握

  • 理解 AIAgent.run_conversation 是核心循环入口
  • 理解消息格式与 OpenAI 兼容的实现方式
  • 理解工具调用的解析与分发机制
  • 理解 IterationBudget 如何控制迭代次数

需要了解

  • 错误分类与智能切换策略
  • 并发工具执行与顺序执行的选择逻辑

目录

一、消息格式与 OpenAI 兼容

What — 消息格式是什么?

Hermes Agent 使用 OpenAI 兼容的消息格式,所有消息都是标准的字典结构,包含 rolecontent 等字段。这种设计使得 Hermes 可以对接任何兼容 OpenAI API 协议的模型提供商。

Why — 为什么需要 OpenAI 兼容的消息格式?

Hermes 是一个多提供商聚合的 Agent 框架,需要同时支持 Anthropic、OpenRouter、Ollama、本地模型等多种后端。如果每种后端都使用自己的消息格式,代码复杂度将指数级增长。

没有 OpenAI 兼容格式会发生什么?

  • 每新增一个模型提供商,都需要重写消息构建逻辑
  • 无法复用 OpenAI SDK,增加开发成本
  • 跨提供商切换变得极其困难
How — 消息格式的源码实现

源码视角:agent/conversation_loop.py 第 712-755 行,消息构建逻辑:

api_messages = []
for idx, msg in enumerate(messages):
    api_msg = msg.copy()  # 复制消息,避免污染原始数据

    # 注入临时上下文到当前轮次的用户消息
    # 来源:内存管理器预取 + 插件 pre_llm_call 钩子
    if idx == current_turn_user_idx and msg.get("role") == "user":
        _injections = []
        if _ext_prefetch_cache:
            _fenced = build_memory_context_block(_ext_prefetch_cache)
            if _fenced:
                _injections.append(_fenced)
        if _plugin_user_context:
            _injections.append(_plugin_user_context)
        if _injections:
            _base = api_msg.get("content", "")
            api_msg["content"] = _base + "\n\n" + "\n\n".join(_injections)

    # 为所有 assistant 消息传递 reasoning 给 API
    # 这确保多轮推理上下文被保留
    agent._copy_reasoning_content_for_api(msg, api_msg)

    # 移除 'reasoning' 字段 - 仅用于轨迹存储
    if "reasoning" in api_msg:
        api_msg.pop("reasoning")
    # 移除 finish_reason - 严格 API 不接受(如 Mistral)
    if "finish_reason" in api_msg:
        api_msg.pop("finish_reason")
    # 移除内部 thinking-prefill 标记
    api_msg.pop("_thinking_prefill", None)

    api_messages.append(api_msg)

注意:这里使用的是消息副本 api_msg = msg.copy(),确保原始消息不被修改。

1.1 消息角色类型

Hermes 支持以下几种消息角色:

角色说明示例
system 系统提示词 Agent 行为规范、技能列表
user 用户消息 用户输入的问题或指令
assistant 助手回复 包含 content 和/或 tool_calls
tool 工具执行结果 包含 tool_call_id 和 content

1.2 tool_calls 消息结构

当模型决定调用工具时,返回的消息包含 tool_calls 字段:

How — tool_calls 消息结构
# assistant 消息中的 tool_calls 结构示例
{
    "role": "assistant",
    "content": None,
    "tool_calls": [
        {
            "id": "call_abc123",           # 工具调用唯一 ID
            "type": "function",
            "function": {
                "name": "read_file",        # 工具名称
                "arguments": '{"path": "/etc/passwd"}'  # JSON 字符串参数
            }
        }
    ]
}

工具执行完成后,会追加一条 tool 角色的消息:

# tool 消息结构
{
    "role": "tool",
    "tool_call_id": "call_abc123",     # 关联到哪个 tool_call
    "content": '{"success": true, "data": "..."}'  # 工具返回结果(JSON 字符串)
}

小结

  • Hermes 使用 OpenAI 兼容的消息格式,便于对接多种模型提供商
  • 消息通过副本传递,原始数据不受污染
  • tool_callstool 消息构成工具调用闭环

二、核心对话循环:run_conversation

What — run_conversation 是什么?

run_conversationAIAgent 类的核心方法,驱动一次用户对话经过整个 Agent 循环(模型调用、工具分发、重试、压缩、后置钩子)。函数定义位于 agent/conversation_loop.py 第 469 行。

Why — 为什么需要 run_conversation?

Agent 的本质是一个"推理-执行"循环:模型输出决定是否需要调用工具,工具结果又反馈给模型继续推理。这个循环需要精细控制:迭代次数限制、中断处理、错误恢复、上下文压缩等。

没有 run_conversation 会发生什么?

  • 无法限制 Agent 的最大迭代次数,可能陷入无限循环
  • 无法处理 API 错误和重试,稳定性无法保证
  • 无法支持上下文压缩,长对话会超出模型上下文限制

2.1 循环入口条件

源码视角:agent/conversation_loop.py 第 563 行的循环条件:

How — 循环退出条件
while (api_call_count < agent.max_iterations
        and agent.iteration_budget.remaining > 0) or agent._budget_grace_call:
    # Reset per-turn checkpoint dedup so each iteration can take one snapshot
    agent._checkpoint_mgr.new_turn()

    # 检查中断请求(如用户发送了新消息)
    if agent._interrupt_requested:
        interrupted = True
        _turn_exit_reason = "interrupted_by_user"
        if not agent.quiet_mode:
            agent._safe_print("\n⚡ Breaking out of tool loop due to interrupt...")
        break

    api_call_count += 1
    agent._api_call_count = api_call_count
    agent._touch_activity(f"starting API call #{api_call_count}")

三个退出条件:

  • 迭代次数耗尽api_call_count >= max_iterations
  • 预算耗尽iteration_budget.remaining <= 0
  • 用户中断_interrupt_requested == True

2.2 API 调用与响应处理

源码视角:agent/conversation_loop.py 第 969-1006 行的 API 调用逻辑:

How — API 调用流程
try:
    agent._reset_stream_delivery_tracking()

    # 为当前 provider 重新应用 reasoning echo
    # (provider 切换后可能需要不同的 reasoning 字段)
    agent._reapply_reasoning_echo_for_provider(api_messages)

    api_kwargs = agent._build_api_kwargs(api_messages)

    # 执行 API 调用(支持流式和非流式)
    if _use_streaming:
        response = agent._interruptible_streaming_api_call(
            api_kwargs, on_first_delta=_stop_spinner
        )
    else:
        response = agent._interruptible_api_call(api_kwargs)

    api_duration = time.time() - api_start_time

    # 验证响应格式
    response_invalid = False
    if agent.api_mode == "chat_completions":
        _ctv = agent._get_transport()
        if not _ctv.validate_response(response):
            response_invalid = True

2.3 响应解析与工具调用判断

源码视角:agent/conversation_loop.py 第 3717-3733 行的工具调用判断:

How — 工具调用判断与分发
# 检查工具调用
if assistant_message.tool_calls:
    if not agent.quiet_mode:
        agent._vprint(f"{agent.log_prefix}🔧 Processing {len(assistant_message.tool_calls)} tool call(s)...")

    # 验证工具调用名称 - 检测模型幻觉
    for tc in assistant_message.tool_calls:
        if tc.function.name not in agent.valid_tool_names:
            # 尝试自动修复工具名称
            repaired = agent._repair_tool_call(tc.function.name)
            if repaired:
                print(f"{agent.log_prefix}🔧 Auto-repaired tool name: '{tc.function.name}' -> '{repaired}'")
                tc.function.name = repaired

    # 执行工具调用
    agent._execute_tool_calls(assistant_message, messages, effective_task_id, api_call_count)

小结

  • run_conversation 是 Agent 的核心循环,驱动整个推理-执行流程
  • 循环受三个条件控制:迭代次数、预算耗尽、用户中断
  • API 响应需要验证格式有效性,再判断是否包含工具调用

三、工具调用的解析与分发

What — 工具调用是什么?

工具调用是模型决定执行某个动作(如读写文件、搜索网络、执行代码)的机制。Hermes 通过 tools/registry.py 注册工具,通过 run_agent.py_execute_tool_calls 执行工具。

Why — 为什么需要工具调用?

纯语言模型只能输出文本,无法操作外部系统。工具调用扩展了模型的能力边界,使其可以:读取文件、执行命令、访问网络、操作数据库等。

没有工具调用会发生什么?

  • Agent 只能回答知识性问题,无法执行实际操作
  • 无法构建真正有用的自动化流程
  • 失去了 Agent 与传统聊天机器人的本质区别

3.1 工具注册机制

源码视角:tools/registry.py 第 151 行的 ToolRegistry 类:

How — ToolRegistry 源码
class ToolRegistry:
    """Singleton registry that collects tool schemas + handlers from tool files."""

    def __init__(self):
        # ... 初始化逻辑

    def register(
        self,
        name: str,
        toolset: str,
        # ... 其他参数
    ) -> None:
        # 注册工具 schema 和处理器

每个工具文件在导入时通过 registry.register() 注册自己的 schema 和处理函数。自动发现机制确保无需手动维护导入列表。

3.2 工具执行器

源码视角:run_agent.py 第 5157-5251 行的工具执行方法:

How — 工具执行入口
def _execute_tool_calls(self, assistant_message, messages: list,
                        effective_task_id: str, api_call_count: int = 0) -> None:
    """Execute tool calls from the assistant message and append results to messages.

    仅当批次看起来是独立的情况下才分并发执行:
    - 只读工具始终可以并行
    - 文件读写仅在目标路径不重叠时并行
    """
    # ... 路径重叠检测逻辑 ...

    # 根据依赖关系选择执行模式
    if all_independent:
        return self._execute_tool_calls_concurrent(
            assistant_message, messages, effective_task_id, api_call_count
        )
    else:
        return self._execute_tool_calls_sequential(
            assistant_message, messages, effective_task_id, api_call_count
        )

并发执行最多使用 8 个工作线程(_MAX_TOOL_WORKERS = 8,定义于 run_agent.py 第 203 行和 agent/tool_executor.py 第 52 行)。

3.3 工具名称验证与修复

源码视角:agent/conversation_loop.py 第 3726-3760 行的工具名称验证逻辑:

How — 工具名称自动修复
# 验证工具调用名称 - 检测模型幻觉
for tc in assistant_message.tool_calls:
    if tc.function.name not in agent.valid_tool_names:
        # 尝试自动修复工具名称
        repaired = agent._repair_tool_call(tc.function.name)
        if repaired:
            print(f"{agent.log_prefix}🔧 Auto-repaired tool name: '{tc.function.name}' -> '{repaired}'")
            tc.function.name = repaired

# 检查是否还有无效工具调用
invalid_tool_calls = [
    tc.function.name for tc in assistant_message.tool_calls
    if tc.function.name not in agent.valid_tool_names
]
if invalid_tool_calls:
    agent._invalid_tool_retries += 1

    if agent._invalid_tool_retries >= 3:
        # 连续 3 次无效工具调用后停止
        agent._vprint(f"{agent.log_prefix}❌ Max retries (3) for invalid tool calls exceeded.")
        return {
            "final_response": None,
            "messages": messages,
            "completed": False,
            "partial": True,
            "error": f"Model generated invalid tool call: {invalid_preview}"
        }

自动修复失败时,返回错误给模型,让模型在下一轮修正。这是"Agent 自我纠正"机制的一部分。连续 3 次无效工具调用后,Agent 会停止并返回错误。

小结

  • 工具通过注册表模式管理,支持动态注册
  • 执行器根据工具依赖关系选择并发或顺序模式
  • 工具名称自动修复机制减少模型幻觉影响

四、迭代预算与中断机制

What — 迭代预算是指什么?

IterationBudget 是线程安全的迭代计数器,控制 Agent 的最大执行轮次。默认主 Agent 90 次,子 Agent 50 次。

Why — 为什么需要迭代预算?

没有预算限制的 Agent 可能陷入无限循环(如模型不断调用工具但不产生有效输出)。迭代预算是防止资源耗尽的安全机制。

没有迭代预算会发生什么?

  • 模型可能陷入无限循环,耗尽 API 配额
  • 用户无法预测 Agent 的最大运行时间
  • 无法支持定时任务等需要确定性预算的场景

4.1 IterationBudget 实现

源码视角:agent/iteration_budget.py 第 17-60 行的完整实现:

How — IterationBudget 源码
class IterationBudget:
    """Thread-safe iteration counter for an agent."""

    def __init__(self, max_total: int):
        self.max_total = max_total
        self._used = 0
        self._lock = threading.Lock()

    def consume(self) -> bool:
        """Try to consume one iteration.  Returns True if allowed."""
        with self._lock:
            if self._used >= self.max_total:
                return False
            self._used += 1
            return True

    def refund(self) -> None:
        """Give back one iteration (e.g. for execute_code turns)."""
        with self._lock:
            if self._used > 0:
                self._used -= 1

    @property
    def remaining(self) -> int:
        with self._lock:
            return max(0, self.max_total - self._used)

注意 execute_code 工具调用可以退还预算,因为它本质上是程序化调用,不消耗外部资源。

4.2 中断机制

源码视角:run_agent.py 第 2363 行的 interrupt 方法:

How — 中断请求处理
def interrupt(self, message: str = None) -> None:
    """
    Request the agent to interrupt its current tool-calling loop.

    Call this from another thread (e.g., input handler, message receiver)
    to gracefully stop the agent and process a new message.
    """
    self._interrupt_requested = True
    self._interrupt_message = message

    # 向所有工具发送中止信号
    # 将中断范围限定在此 Agent 的执行线程
    if self._execution_thread_id is not None:
        _set_interrupt(True, self._execution_thread_id)
        self._interrupt_thread_signal_pending = False
    else:
        # 中断请求在 run_conversation() 完成绑定前到达
        # 延迟到启动完成后再发送工具级中断信号

4.3 优雅退出

源码视角:agent/conversation_loop.py 第 563-573 行的中断检查点:

How — 中断检查点
while (api_call_count < agent.max_iterations
        and agent.iteration_budget.remaining > 0) or agent._budget_grace_call:
    # ...

    # 检查中断请求(如用户发送了新消息)
    if agent._interrupt_requested:
        interrupted = True
        _turn_exit_reason = "interrupted_by_user"
        if not agent.quiet_mode:
            agent._safe_print("\n⚡ Breaking out of tool loop due to interrupt...")
        break  # 优雅退出循环

中断后,已完成的消息历史会保留,Agent 可以从中断点恢复。

小结

  • IterationBudget 线程安全地控制最大迭代次数
  • execute_code 调用可退还预算,不消耗资源配额
  • 中断机制确保用户可以随时停止 Agent
  • 中断后消息历史保留,支持恢复

五、错误处理与恢复策略

What — 错误处理是什么?

Hermes 内置智能错误分类与恢复系统 agent/error_classifier.py,根据错误类型选择最优恢复策略:重试、压缩、切换凭证、回退到备用 provider 等。

Why — 为什么需要智能错误处理?

API 调用可能因网络问题、限流、认证失败、上下文超限等多种原因失败。简单的"失败重试"往往不够,需要根据错误类型选择不同策略。

没有智能错误处理会发生什么?

  • 上下文超限时仍然不断重试,浪费资源
  • 认证失败时不尝试刷新凭证,体验差
  • 无法自动切换到备用 provider,容错能力弱

5.1 错误分类体系

源码视角:agent/error_classifier.py 第 24-64 行的 FailoverReason 枚举:

How — FailoverReason 枚举
class FailoverReason(enum.Enum):
    """Why an API call failed — determines recovery strategy."""

    # 认证 / 授权
    auth = "auth"                          # 瞬时认证失败 - 刷新/轮换
    auth_permanent = "auth_permanent"      # 认证彻底失败 - 中止

    # 计费 / 配额
    billing = "billing"                    # 配额耗尽 - 立即轮换
    rate_limit = "rate_limit"            # 限流 - 退避后轮换

    # 服务端
    overloaded = "overloaded"            # 503/529 - 退避
    server_error = "server_error"          # 500/502 - 重试

    # 传输层
    timeout = "timeout"                    # 连接/读取超时 - 重建客户端 + 重试

    # 上下文 / 负载
    context_overflow = "context_overflow"  # 上下文过大 - 压缩而非切换
    payload_too_large = "payload_too_large"  # 413 - 压缩
    image_too_large = "image_too_large"   # 图片过大 - 缩小并重试

    # 模型 / provider 策略
    content_policy_blocked = "content_policy_blocked"  # 安全过滤拒绝 - 不要重试
    model_not_found = "model_not_found"  # 404 - 回退到不同模型

    # 未知
    unknown = "unknown"                    # 不可分类 - 退避重试

5.2 重试策略

源码视角:agent/conversation_loop.py 第 952 行附近的重试循环:

How — 重试循环
api_start_time = time.time()
retry_count = 0
max_retries = agent._api_max_retries  # 最大重试次数
_RETRY = TurnRetryState()
max_compression_attempts = 3

while retry_count < max_retries:
    try:
        # 执行 API 调用
        response = run_llm_execution_middleware(...)

        # 验证响应格式
        if agent.api_mode == "chat_completions":
            _ctv = agent._get_transport()
            if not _ctv.validate_response(response):
                response_invalid = True

    except Exception as e:
        # 分类错误并确定恢复策略
        classified = classify_api_error(e, ...)

        if classified.should_compress:
            # 执行上下文压缩
            _RETRY.restart_with_compressed_messages = True
        elif classified.should_fallback:
            # 切换到备用 provider
            if agent._try_activate_fallback():
                retry_count = 0  # 重置重试计数
                continue
        elif not classified.retryable:
            # 不可重试的错误,直接失败
            break

        retry_count += 1

5.3 上下文压缩

当上下文超限时,Hermes 会尝试压缩历史消息:

How — 压缩触发与重试
if _RETRY.restart_with_compressed_messages:
    api_call_count -= 1
    agent.iteration_budget.refund()  # 退还预算,因为这是压缩重启

    # 统计压缩重启次数,防止无限循环
    # 当压缩后仍无法放入上下文时,会话将中止

压缩尝试最多 3 次(max_compression_attempts = 3)。

5.4 工具调用错误的特殊处理

源码视角:agent/conversation_loop.py 第 3726-3760 行的无效工具调用处理:

How — 无效 tool_calls 参数处理
# 验证工具调用名称 - 检测模型幻觉
for tc in assistant_message.tool_calls:
    if tc.function.name not in agent.valid_tool_names:
        repaired = agent._repair_tool_call(tc.function.name)
        if repaired:
            tc.function.name = repaired

invalid_tool_calls = [
    tc.function.name for tc in assistant_message.tool_calls
    if tc.function.name not in agent.valid_tool_names
]
if invalid_tool_calls:
    agent._invalid_tool_retries += 1

    if agent._invalid_tool_retries >= 3:
        # 连续 3 次无效工具调用后停止
        agent._vprint(f"{agent.log_prefix}❌ Max retries (3) for invalid tool calls exceeded.")
        return {
            "final_response": None,
            "messages": messages,
            "completed": False,
            "partial": True,
            "error": f"Model generated invalid tool call: {invalid_preview}"
        }

小结

  • 错误分类体系覆盖认证、计费、服务端、传输、上下文等多种场景
  • 每个错误类型有对应的恢复策略(重试/压缩/轮换/中止)
  • 上下文压缩最多尝试 3 次,防止无限循环
  • 工具调用错误有特殊处理,支持模型自我修正

六、FAQ 20 问

FAQ 分组说明

以下 20 组 FAQ 涵盖 AIAgent 核心循环的常见问题,按主题分为四组:消息格式(1-5)、循环控制(6-10)、工具系统(11-15)、错误处理(16-20)。

Q1. Hermes 的消息格式与 OpenAI 完全一致吗?

不完全一致,但高度兼容。Hermes 在 OpenAI 格式基础上扩展了一些字段(如 reasoning_contentreasoning_details),用于支持模型的思考过程。这些扩展字段在发送给标准 OpenAI API 时会被自动清理。

Q2. 消息中的 tool_calls 和 tool 消息必须配对吗?

必须配对。每个 tool_calls 条目必须有对应的 tool 消息,通过 tool_call_id 关联。如果缺少对应消息,会导致角色交替错误。

Q3. 为什么需要消息副本(api_msg = msg.copy())?

避免污染原始消息历史。发送给 API 的消息需要做一些变换(如注入上下文、清理内部字段),这些变换不能影响会话历史。使用副本确保原始消息保持不变。

Q4. reasoning_content 和 reasoning 字段有什么区别?

用途不同。reasoning 用于轨迹存储,reasoning_content 用于 API 传输。有些 provider(如 Moonshot)要求 assistant 消息携带 reasoning_content 字段。

Q5. 模型输出的 thinking block 被过滤了吗?

是的,特殊处理。纯思考消息(只有 thinking block,没有可见内容和工具调用)会被丢弃,防止某些 API 报错。

Q6. max_iterations 和 iteration_budget 有什么区别?

本质相同,但 budget 更精细。max_iterations 是循环条件的硬限制,iteration_budget 额外支持退还机制(如 execute_code 不消耗预算)。

Q7. 什么是 grace call(宽限调用)?

预算耗尽后的最后一次调用。iteration_budget.remaining == 0 时,Agent 还会给模型一次额外机会(grace call)完成响应,确保用户体验。

Q8. 用户中断后消息历史会丢失吗?

不会丢失。中断发生时,当前轮次已完成的消息会被持久化到 SessionDB。用户可以随时恢复会话。

Q9. 循环退出后如何决定 final_response?

多级 fallback。优先使用最后一轮模型的实际回复,如果没有则使用 content_with_fallback(模型同时返回内容和工具调用时的文本 fallback),最后才是超时/中断提示。

Q10. step_callback 是什么?

Gateway 钩子事件。step_callback 在每个 API 调用前触发,用于 gateway 的 agent:step 事件,让外部系统可以监听 Agent 进度。

Q11. 工具调用名称自动修复的原理是什么?

编辑距离匹配。当模型输出的工具名不在有效列表中时,_repair_tool_call() 会计算与所有有效工具名的编辑距离,返回最接近的一个。

Q12. 哪些工具可以并发执行?

无依赖的工具。只读工具(如 read_fileweb_search)始终可并发。文件写入工具仅在目标路径不重叠时并发。

Q13. 工具执行结果为什么必须是 JSON 字符串?

API 协议要求。OpenAI 兼容的 tool 消息格式要求 content 是字符串。工具处理函数应返回 json.dumps(result)

Q14. 什么是 Housekeeping Tools?

轻量级工具子集。todo_toolmemory 等。当一轮所有工具调用都是 Housekeeping Tools 时,Agent 会跳过流式输出直接进入下一轮。

Q15. 工具调用的 token 消耗如何统计?

按实际 API 返回统计。每次 API 调用后,Hermes 从响应中提取 usage 信息,累加到会话统计中。

Q16. context_overflow 和 payload_too_large 错误有什么区别?

原因不同。context_overflow 是模型上下文窗口超限,payload_too_large 是 HTTP 413 错误。两者都触发压缩,但 payload_too_large 可能还需要分块处理。

Q17. rate_limit 错误会立即切换 provider 吗?

不会,先退避再轮换。限流错误先执行指数退避(jittered_backoff),退避后仍失败才尝试切换到备用 provider。

Q18. billing 错误为什么立即切换?

因为不可恢复。配额耗尽不是临时问题,等待毫无意义。Hermes 会立即尝试切换到有配额的 provider。

Q19. 压缩失败后 Agent 会怎样?

终止并返回错误。压缩尝试最多 3 次仍超限时,Agent 会中止并返回上下文超限错误,提示用户缩短对话或增加上下文窗口。

Q20. Nous Portal 限流有什么特殊处理?

全局感知与跳过。Hermes 维护一个全局限流状态,所有会话共享。当某个会话检测到限流时,其他会话会跳过 API 调用直接尝试备用 provider。

FAQ 总纲

  • 消息格式兼容 OpenAI,扩展字段自动清理
  • 循环控制通过 IterationBudget + 中断机制实现
  • 工具系统支持并发执行和自动名称修复
  • 错误处理根据类型选择最优恢复策略

七、后续 Roadmap

敬请期待

本篇介绍了 AIAgent 核心循环的架构设计。后续文章将深入剖析:

  • Agent 内存管理与上下文压缩
  • 工具系统的完整实现细节
  • Gateway 消息路由机制
  • SessionDB 会话持久化
  • 插件系统与生命周期钩子

欢迎持续关注!


posted @ 2026-07-15 20:20  左扬  阅读(28)  评论(0)    收藏  举报