模块: gateway/core/lifecycle/
module/file.py:function_nameAgent 生命周期管理,包括:
说明: Trace 元数据由 Agent 框架管理,Gateway 不维护副本
基于 Agent Core 架构(详见 ../../../agent/docs/architecture.md):
{GATEWAY_WORKSPACES_ROOT}/{sha256(workspace_id)}/(默认 /root/.gateway/workspaces/<64位hex>/),不是用明文 workspace_id 作目录名;详见下文「目录与 meta」。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)
实现位置: gateway/core/lifecycle/trace/manager.py
职责:
核心接口:
说明: Trace 的创建由 Agent API(HTTP)完成;Gateway 在拿到 trace_id 后通过 bind_agent_trace 与 WorkspaceManager 建立关联。详见 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
实现位置: gateway/core/lifecycle/workspace/manager.py(Docker 编排见同目录 docker_runner.py)
磁盘布局与 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_id、trace_refs、workspace_container_id(沙箱容器 ID)等。在 volume_subpath 模式下,该目录与沙箱内 /home/agent/workspace 为同一块存储(命名卷 + Subpath),故 Agent 在沙箱里也能看到 workspace/.gateway/meta.json。
实现位置: gateway/core/lifecycle/workspace/docker_runner.py
agent/workspace:latest,容器名前缀 gws-)。GATEWAY_WORKSPACE_MOUNT_MODE:
bind(默认):workspace_host_path、shared_host_path 解析后的路径直接 bind 到沙箱(适合 Gateway 与本机 Docker 守护进程同环境、路径对 Docker 可见)。volume_subpath:使用命名卷 + VolumeOptions.Subpath,将 workspace 卷 的子目录 <hex> 挂到 /home/agent/workspace,shared 卷 整卷挂到 /home/agent/shared。要求同时设置 GATEWAY_WORKSPACE_DOCKER_VOLUME 与 GATEWAY_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_WORKSPACES_ROOT |
Workspace 根目录(容器内常为 /root/.gateway/workspaces) |
GATEWAY_SHARED_ROOT |
共享目录(容器内常为 /root/.gateway/shared) |
GATEWAY_WORKSPACE_MOUNT_MODE |
bind 或 volume_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_URL、GATEWAY_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_root、GATEWAY_SHARED_DOCKER_VOLUME=agent_workspace_shared,并通常配合 GATEWAY_WORKSPACE_MOUNT_MODE=volume_subpath。职责:
核心接口:
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
实现位置: gateway/core/lifecycle/config_watcher.py
职责:
核心接口:
class ConfigWatcher:
def watch(self, workspace_id: str, callback: callable):
"""监听指定 Workspace 的配置变化"""
pass
def stop_watch(self, workspace_id: str):
"""停止监听"""
pass
workspace_id(如 feishu:<user_id>)。TraceManager.prepare_workspace_session(workspace_id) → 内部 WorkspaceManager.ensure_session(目录、shared、沙箱容器)。trace_id。TraceManager.bind_agent_trace(workspace_id, trace_id, agent_type, ...) 登记引用与本地 meta。TaskManager.submit_task(trace_id, ...) 驱动 POST /api/traces/{id}/run(可带 gateway_exec 指向沙箱)。bind_agent_trace(同上)bind_agent_trace(同一 workspace_id, 子 trace_id, ...)WorkspaceManager.add_trace_ref 维护引用;子 Agent 结束后 remove_trace_ref(或由渠道策略 release_agent_trace)WorkspaceManager.remove_trace_ref(...)trace_id 时调用 bind_agent_traceensure_session(Docker 卷、沙箱)失败 → 若 GATEWAY_WORKSPACE_DOCKER_REQUIRED=true 则中断;否则可降级为无沙箱(见日志)docker-compose.yml:gateway 服务的卷与环境变量与上文「Compose」小节一致,部署时以此为准。