lifecycle.md 12 KB

Lifecycle(生命周期管理)

模块: gateway/core/lifecycle/

文档维护规范

  1. 先改文档,再动代码 - 新功能或重大修改需先完成文档更新、并完成审阅后,再进行代码实现
  2. 文档分层,链接代码 - 关键实现需标注代码文件路径;格式:module/file.py:function_name
  3. 简洁快照,日志分离 - 只记录已确认的设计

模块职责

Agent 生命周期管理,包括:

  • Trace 注册:调用 Agent 框架创建 Trace
  • Trace 查询:调用 Agent 框架查询 Trace 信息
  • Workspace 管理:确保 Workspace 目录存在和清理
  • 配置热重载:监听 Agent 技能配置变化并热重载

说明: Trace 元数据由 Agent 框架管理,Gateway 不维护副本


核心概念

Trace

基于 Agent Core 架构(详见 ../../../agent/docs/architecture.md):

  • Trace = Agent 的执行记录
  • 每个 Trace 有独立的 Workspace
  • Trace 数据结构由 Agent Core 定义

Workspace

  • 多个 Trace 可以共享一个 Workspace(主 Agent 和子 Agent)
  • 包含 Agent 的配置、记忆、技能等
  • Gateway 进程内目录:{GATEWAY_WORKSPACES_ROOT}/{sha256(workspace_id)}/(默认 /root/.gateway/workspaces/<64位hex>/),不是用明文 workspace_id 作目录名;详见下文「目录与 meta」。
  • 需要引用计数机制,确保清理时无活跃 Trace

模块结构

gateway/core/lifecycle/
├── __init__.py           # 聚合导出(TraceManager、WorkspaceManager 等)
├── errors.py             # LifecycleError、WorkspaceDockerError
├── config_watcher.py     # 配置热重载
├── workspace/
│   ├── manager.py        # WorkspaceManager(目录、引用计数)
│   └── docker_runner.py  # WorkspaceDockerRunner(沙箱容器)
└── trace/
    ├── manager.py        # TraceManager(Agent API 代理与本地登记)
    └── backend.py        # LifecycleTraceBackend(channels.TraceBackend)

关键功能

TraceManager

实现位置: gateway/core/lifecycle/trace/manager.py

职责:

  • 调用 Agent 框架创建 Trace
  • 查询 Trace 信息
  • 管理 Trace 和 Workspace 的关联关系

核心接口:

说明: Trace 的创建由 Agent API(HTTP)完成;Gateway 在拿到 trace_id 后通过 bind_agent_traceWorkspaceManager 建立关联。详见 gateway/core/lifecycle/trace/manager.py

class TraceManager:
    async def prepare_workspace_session(self, workspace_id: str) -> None:
        """调用 WorkspaceManager.ensure_session(目录 + 沙箱)"""
        pass

    async def bind_agent_trace(
        self,
        workspace_id: str,
        agent_trace_id: str,
        agent_type: str,
        metadata: dict | None = None,
    ) -> None:
        """Agent 返回 trace_id 后登记本地 meta 与 workspace 引用"""
        pass

    async def release_agent_trace(self, workspace_id: str, agent_trace_id: str) -> None:
        """解除绑定"""
        pass

    async def get_trace(self, trace_id: str) -> dict:
        """优先请求 Agent API,失败时返回 Gateway 本地登记"""
        pass

    async def list_traces(
        self,
        workspace_id: str | None = None,
        agent_type: str | None = None,
        *,
        limit: int = 50,
    ) -> list[dict]:
        """查询 Trace 列表(带 Agent API 查询参数约定)"""
        pass

    def get_workspace_id(self, trace_id: str) -> str:
        """同步:解析 workspace_id(Executor、gateway_exec 使用)"""
        pass

WorkspaceManager

实现位置: gateway/core/lifecycle/workspace/manager.py(Docker 编排见同目录 docker_runner.py

目录与 meta

磁盘布局与 manager.py 文档字符串一致:

根路径(环境变量) 默认(容器内) 用途
GATEWAY_WORKSPACES_ROOT /root/.gateway/workspaces 每个 workspace 一个子目录(名为 sha256(workspace_id)),其下含 .gateway/meta.json
GATEWAY_SHARED_ROOT /root/.gateway/shared 多会话/多 workspace 共享文件;沙箱内挂载为 /home/agent/shared

meta.json 路径:{GATEWAY_WORKSPACES_ROOT}/<hex>/.gateway/meta.json。由 WorkspaceManager._save_meta 写入,字段包含 workspace_idtrace_refsworkspace_container_id(沙箱容器 ID)等。在 volume_subpath 模式下,该目录与沙箱内 /home/agent/workspace 为同一块存储(命名卷 + Subpath),故 Agent 在沙箱里也能看到 workspace/.gateway/meta.json

Docker 沙箱(WorkspaceDockerRunner)

实现位置: gateway/core/lifecycle/workspace/docker_runner.py

  • 为每个 workspace 保证一个运行中的沙箱容器(镜像默认 agent/workspace:latest,容器名前缀 gws-)。
  • 挂载模式 GATEWAY_WORKSPACE_MOUNT_MODE
    • bind(默认)workspace_host_pathshared_host_path 解析后的路径直接 bind 到沙箱(适合 Gateway 与本机 Docker 守护进程同环境、路径对 Docker 可见)。
    • volume_subpath:使用命名卷 + VolumeOptions.Subpath,将 workspace 卷 的子目录 <hex> 挂到 /home/agent/workspaceshared 卷 整卷挂到 /home/agent/shared。要求同时设置 GATEWAY_WORKSPACE_DOCKER_VOLUMEGATEWAY_SHARED_DOCKER_VOLUME,且 Gateway 通过 宿主机 docker.sock 创建的容器与 Compose 使用同一 Docker(卷名一致)。
  • 镜像与网络:GATEWAY_WORKSPACE_IMAGE(默认 agent/workspace:latest);GATEWAY_WORKSPACE_DOCKER_NETWORK 指定沙箱加入的网络名(如 agent)。
  • 关闭沙箱编排:GATEWAY_WORKSPACE_DOCKER_ENABLED=false;若失败需中断会话则设 GATEWAY_WORKSPACE_DOCKER_REQUIRED=true

Gateway 环境变量(Workspace / Docker)

变量 说明
GATEWAY_WORKSPACES_ROOT Workspace 根目录(容器内常为 /root/.gateway/workspaces
GATEWAY_SHARED_ROOT 共享目录(容器内常为 /root/.gateway/shared
GATEWAY_WORKSPACE_MOUNT_MODE bindvolume_subpath
GATEWAY_WORKSPACE_DOCKER_VOLUME volume_subpath 时:workspace 数据 Docker 卷名(与 Compose 中 name: 一致,如 agent_workspace_root
GATEWAY_SHARED_DOCKER_VOLUME volume_subpath 时:shared 数据 Docker 卷名(如 agent_workspace_shared
GATEWAY_WORKSPACE_DOCKER_NETWORK 沙箱容器加入的网络名
GATEWAY_WORKSPACE_IMAGE 沙箱镜像,默认 agent/workspace:latest
GATEWAY_WORKSPACE_DOCKER_ENABLED 是否启用沙箱容器
GATEWAY_WORKSPACE_DOCKER_REQUIRED Docker 失败时是否视为致命错误

TraceManager(HTTP)GATEWAY_AGENT_API_BASE_URLGATEWAY_AGENT_API_TIMEOUT(与 Executor 共用 Agent 基址)。

仓库 docker-compose.yml(Gateway 服务)

  • 命名卷 workspace_root(固定名 agent_workspace_root)→ /root/.gateway/workspaces
  • 命名卷 workspace_shared(固定名 agent_workspace_shared)→ /root/.gateway/shared;使用 driver: local + bind,将卷绑定到宿主机目录,便于直接查看文件。
  • GATEWAY_SHARED_HOST_BIND仅用于 Compose 解析,写在项目根 .env 或 shell 环境中;作为 driver_opts.device 的宿主机路径。未设置时默认 ${PWD}/.gateway/shared(请在项目根执行 docker compose,并保证目录存在)。Gateway 进程不读取该变量。
  • 与上述卷名对应的环境变量:GATEWAY_WORKSPACE_DOCKER_VOLUME=agent_workspace_rootGATEWAY_SHARED_DOCKER_VOLUME=agent_workspace_shared,并通常配合 GATEWAY_WORKSPACE_MOUNT_MODE=volume_subpath

职责:

  • 创建和初始化 Workspace 目录
  • 管理 Workspace 引用计数
  • 清理无活跃 Trace 的 Workspace

核心接口:

class WorkspaceManager:
    async def create_workspace(self, workspace_id: str) -> str:
        """创建 Workspace 目录(含 meta),返回绝对路径"""
        pass

    async def ensure_session(self, workspace_id: str) -> str:
        """会话启动:目录 + 共享目录 + 按需启动沙箱;返回 Workspace 绝对路径"""
        pass

    async def get_workspace_path(self, workspace_id: str) -> str:
        """获取 Workspace 路径(不存在则抛错)"""
        pass

    def get_workspace_container_id(self, workspace_id: str) -> str | None:
        """读 meta 中沙箱容器 ID(供 Executor 注入 gateway_exec)"""
        pass

    async def add_trace_ref(self, workspace_id: str, trace_id: str) -> None:
        """增加 Trace 引用"""
        pass

    async def remove_trace_ref(self, workspace_id: str, trace_id: str) -> None:
        """移除 Trace 引用"""
        pass

    async def cleanup_workspace(self, workspace_id: str, force: bool = False) -> None:
        """清理 Workspace(检查引用计数,force=True 强制清理)"""
        pass

    async def list_workspaces(self) -> list[dict]:
        """列出所有 Workspace 及其引用计数、容器 ID 等"""
        pass

ConfigWatcher

实现位置: gateway/core/lifecycle/config_watcher.py

职责:

  • 监听 Agent 技能配置文件变化
  • 触发热重载回调
  • 不影响正在运行的 Trace

核心接口:

class ConfigWatcher:
    def watch(self, workspace_id: str, callback: callable):
        """监听指定 Workspace 的配置变化"""
        pass

    def stop_watch(self, workspace_id: str):
        """停止监听"""
        pass

典型流程

个人助理型 Agent 首次对话(与当前实现一致)

  1. 用户通过飞书发送消息;渠道层解析 workspace_id(如 feishu:<user_id>)。
  2. TraceManager.prepare_workspace_session(workspace_id) → 内部 WorkspaceManager.ensure_session(目录、shared、沙箱容器)。
  3. 调用 Agent HTTP API 创建/续跑 Trace,得到 trace_id
  4. TraceManager.bind_agent_trace(workspace_id, trace_id, agent_type, ...) 登记引用与本地 meta。
  5. Executor 侧通过 TaskManager.submit_task(trace_id, ...) 驱动 POST /api/traces/{id}/run(可带 gateway_exec 指向沙箱)。

数字员工型 Agent 串行处理

  1. 用户 A 发送消息
  2. Routing 模块查询数字员工的 Trace(共享 workspace_id)
  3. 如果无 Trace → 仍由 Agent API 创建 trace,再 bind_agent_trace(同上)
  4. 如果有 Trace 且正在处理 → 消息进入队列
  5. 当前对话结束 → 从队列取下一条消息

主 Agent 调用子 Agent

  1. 主 Agent 执行过程中需要子 Trace 时,由 Agent 侧创建子 trace(HTTP)
  2. Gateway 对子 trace 调用 bind_agent_trace(同一 workspace_id, 子 trace_id, ...)
  3. WorkspaceManager.add_trace_ref 维护引用;子 Agent 结束后 remove_trace_ref(或由渠道策略 release_agent_trace

Workspace 清理

  1. Trace 结束时调用 WorkspaceManager.remove_trace_ref(...)
  2. WorkspaceManager 检查引用计数
  3. 引用计数为 0 → 可以清理(可选延迟清理策略)
  4. 删除 Workspace 目录

错误处理

Trace 创建 / 绑定失败

  • Agent HTTP 创建或续跑失败 → 渠道/Executor 向用户返回友好错误;在未拿到 trace_id 时调用 bind_agent_trace
  • ensure_session(Docker 卷、沙箱)失败 → 若 GATEWAY_WORKSPACE_DOCKER_REQUIRED=true 则中断;否则可降级为无沙箱(见日志)

Workspace 引用计数不一致

  • 定期检查 Workspace 引用计数和实际 Trace 状态
  • 发现不一致 → 记录日志,修正引用计数

配置热重载失败

  • 配置文件格式错误 → 记录日志,保持旧配置
  • 不影响正在运行的 Trace

并发安全

  • TraceManager 和 WorkspaceManager 的关键操作需要加锁
  • 避免多个请求同时创建相同 workspace_id 的 Workspace

相关文档

  • 需求规划:生命周期管理需求
  • 架构设计:模块在整体架构中的位置
  • Agent Core 架构:Trace 数据结构定义
  • 仓库根目录 docker-compose.ymlgateway 服务的卷与环境变量与上文「Compose」小节一致,部署时以此为准。