运行生命周期
本章从用户视角出发,完整描述“用户发一条消息后,系统到底做了什么“。系统采用 SessionWorker(会话工作进程)模式——容器以 Deployment(部署)方式长驻运行,通过 WebSocket(网络套接字) 双向通道与 Backend 实时通信。
1. SessionWorker 核心特性
| 特性 | 说明 |
|---|---|
| K8s 资源类型 | Deployment(部署)+ Service(服务)→ 长驻 Pod |
| 容器生命周期 | 跨越多轮对话持续运行,按空闲策略自动回收 |
| 通信方式 | WebSocket 双向:Worker 启动后主动连接 Backend WS 端点,消息和事件通过同一持久连接传输 |
| 实时交互 | ✅ 支持 agentcore 向用户提问、请求权限确认 |
| 流式输出 | ✅ token 片段实时推送,用户即时看到推理过程 |
| 状态连续性 | 内存中直接保持 + Worker 通过协议把 checkpoint 持久化到 Backend |
| 安全机制 | 非 root 运行、丢弃所有 capabilities、seccomp 限制 |
2. 首次启动:从用户消息到容器就绪
sequenceDiagram
participant U as 用户
participant H as Helper(本地前端)
participant B as Backend(本地后端)
participant K as K3s 编排器
participant W as SessionWorker(长驻容器)
rect rgb(230, 245, 255)
Note over U,W: ① 创建会话
U->>H: 选择智能体,开始对话
H->>B: POST /api/v1/sessions
B->>B: 创建 SessionRecord,初始化会话状态目录
B-->>H: 返回 session_id
end
rect rgb(255, 245, 230)
Note over U,W: ② 发送首条消息
U->>H: 输入消息
H->>B: POST /api/v1/runs
Note over B: 校验会话 → 解析 Agent 包<br/>→ 合并 API 密钥 → 查库生成 run-context.json<br/>→ 组装 LaunchPlan
end
rect rgb(230, 255, 230)
Note over B,W: ③ K3s 编排器创建资源
B->>K: 提交 LaunchPlan
K->>K: 渲染 Deployment + Service
K->>W: 创建 ConfigMap(包文件)
K->>W: 创建 Secret(API 密钥)
K->>W: 创建 Deployment(Worker Pod)
K->>W: 创建 Service(探针 + 备用端口)
end
rect rgb(255, 230, 255)
Note over W: ④ Worker 启动流程
W->>W: 创建工作目录
W->>W: 写入运行时元数据文件
W->>W: touch /tmp/agent-store-worker.ready
W->>W: 注册 TERM 信号处理器
W->>W: 启动心跳循环(每 30 秒)
W->>W: 启动 agentcore 进程
W->>B: 建立 WebSocket 连接 ws://backend/ws/workers/RUN_ID
W->>B: WS state_change IDLE
W->>W: 读取 /workspace/in/run-context.json
Note over W: readinessProbe 通过 → Pod 就绪
end
rect rgb(230, 245, 255)
Note over B,W: ⑤ 推送首条消息并返回结果
B->>B: 检测到 Worker IDLE 且 WS 连接就绪
B->>W: WS push_message(用户消息)
W->>W: agentcore 调用大模型推理
W-->>B: WS stream_chunk × N
B-->>H: 转发流式内容
H-->>U: 实时显示 AI 回复
W->>B: WS message_response isComplete
B->>B: 写入数据库
end
3. 后续对话:Worker 已就绪
当 Worker 已处于 IDLE 状态时,后续消息无需重新创建 Deployment,延迟极低:
sequenceDiagram
participant U as 用户
participant H as Helper
participant B as Backend
participant W as Worker Pod
U->>H: 继续对话
H->>B: POST /api/v1/runs(同一 session_id)
B->>B: 检测到 Worker 已就绪(IDLE)
B->>W: WS push_message(新消息 + 更新的上下文)
W->>W: agentcore 处理
W-->>B: WS stream_chunk + message_response
B-->>H: 转发
H-->>U: 实时显示
Note over U,W: 全程在 localhost,延迟在毫秒级
4. 交互式通信:agentcore 向用户提问
这是 SessionWorker 最重要的能力之一——agentcore 可以在执行过程中主动向用户发起请求:
sequenceDiagram
participant U as 用户
participant H as Helper
participant B as Backend
participant W as Worker Pod
Note over W: agentcore 执行工具前需要用户确认
W->>B: WS ask_user 事件
B->>B: 标记 Worker 状态 → WAITING_USER
B->>H: WS 推送询问
H->>U: 弹出确认对话框
alt 用户同意
U->>H: 点击"确认"
H->>B: POST 用户回复
B->>W: WS user_reply(用户确认)
B->>B: 标记 Worker 状态 → BUSY
W->>W: 继续执行
else 用户拒绝
U->>H: 点击"取消"
H->>B: POST 用户拒绝
B->>W: WS user_reply(用户拒绝)
W->>W: 跳过该操作,继续推理
end
典型场景:
- 删除文件前请求确认
- 需要用户提供额外信息(如数据库连接串)
- 执行高风险操作前的授权确认
- 多选题或分支决策
5. 分阶段详解
阶段一:校验与准备(Backend 负责)
当 Backend 收到创建运行的请求后,依次执行:
- 校验 Session(会话):确认会话存在且未关闭
- 解析 agent package(智能体包):从包目录索引中读取开发者包
- 解析 RuntimeProfile(运行时配置模板):确定基础镜像和资源配额
- 合并 provider 配置:将 API 密钥从环境变量、运行时模板、本次请求三层合并
- 校验输入文件和挂载:确认文件存在,挂载路径在白名单内
阶段二:创建工作区(Backend 负责)
Backend 为本次运行创建独立的工作区目录:
workspaces/[run-id]/
in/ ← 输入文件:附件 + run-context.json
out/ ← 输出文件(SessionWorker 模式下主要通过回调返回)
tmp/ ← 临时文件
同时从数据库中提取数据,生成 in/run-context.json(详见 输入输出流程)。
阶段三:组装 LaunchPlan(启动计划)
LaunchPlan 是整个运行的完整不可变描述:
| 类别 | 内容 |
|---|---|
| 身份与路由 | run_id、session_id、user_id、package_name |
| 运行时与包 | 镜像地址、容器入口、资源限制、Agent 包文件 |
| 文件与状态 | 工作区路径、可选的本地缓存路径、checkpoint 恢复策略 |
| 编排策略 | 卷后端类型(HostPath / PVC)、镜像模式、协议通道类型 |
| 交互配置 | worker_event_channel(事件通道)、worker_idle_policy(空闲策略) |
| 集群目标 | namespace、service account、是否真实提交 |
阶段四:K3s 编排器渲染和提交
编排器执行以下步骤:
workload_worker.rs组装 Deployment + Service 定义- 容器暴露 8081 端口(control 控制端口)
- 配置 readiness/liveness 探针(检查
/tmp/agent-store-worker.ready标记文件) - 注入所有环境变量(事件通道、空闲策略、包信息、会话信息等)
apply.rs按顺序创建:ConfigMap → Secret → Service → Deployment- 设置 OwnerReference(Deployment 拥有 Service、ConfigMap、Secret)
阶段五:容器内执行
graph TB
START[Pod 启动] --> DIRS[创建工作目录]
DIRS --> META[写入运行时元数据]
META --> READY["创建 ready 标记<br/>/tmp/agent-store-worker.ready"]
READY --> TRAP[注册 TERM 信号处理]
TRAP --> BEAT[启动心跳循环]
BEAT --> SERVE[建立 WebSocket 连接到 Backend]
SERVE --> CTX[读取 run-context.json]
CTX --> WAIT[等待 Backend 推送消息]
WAIT --> RECV{收到消息}
RECV -->|用户消息| INFER[调用大模型推理]
RECV -->|用户回复| RESUME[恢复被暂停的执行]
RECV -->|TERM 信号| DRAIN[优雅关闭]
INFER --> NEED{需要用户输入?}
NEED -->|是| ASK[WS 发送 ask_user 事件]
ASK --> WAIT
NEED -->|否| STREAM[流式推送 token]
STREAM --> TOOLS[执行工具调用]
TOOLS --> DBREQ{需要查库/写库?}
DBREQ -->|是| SYNCREQ[发送 backend_query / backend_command]
SYNCREQ --> DBRESP[等待 Backend 响应]
DBRESP --> DONE[WS 发送 message_response]
DBREQ -->|否| DONE
DONE --> SAVE[发送 checkpoint_put 并等待 ACK]
SAVE --> WAIT
RESUME --> INFER
DRAIN --> SAVE_EXIT[发送最终 checkpoint_put 后退出]
阶段六:状态回收
| 行为 | 说明 |
|---|---|
| 结果写入 | Backend 实时接收协议事件,写入数据库 |
| Worker 状态更新 | Backend 通过 K8s 状态观察 + 协议事件共同更新 Worker 生命周期状态 |
| 资源清理 | Worker DRAINING 后自动退出,K8s 清理 Deployment + Service + ConfigMap + Secret |
| 会话连续性 | 内存状态持续保持;checkpoint 通过协议写入 Backend 管理的数据库 |
各阶段的同步 / 异步定义
| 阶段 | 语义 | 说明 |
|---|---|---|
| 创建 Session | 同步 | 需要立即返回 session_id |
| 提交 Run | 混合 | API 返回 run_id 是同步,Worker 启动和执行是异步 |
| K3s 创建资源 | 异步 | Deployment 提交成功不代表 Pod 已立刻就绪 |
| Worker 建立 WS 连接 | 异步 | 连接建立后由 state_change(IDLE) 告知 Backend |
| Backend 推送消息 | 异步 | 推送后结果稍后通过流式事件返回 |
| Worker 查库 / 取 checkpoint | 同步 | 必须等 Backend 响应才能继续 |
| Worker 流式输出 | 异步 | token 片段持续推送,不阻塞推理主循环 |
| Worker 保存 checkpoint | 同步 | 发送 checkpoint_put 后等待 ACK,确保状态可恢复 |
| ask_user 交互 | 混合 | 发起提问异步,但业务流程暂停等待回复 |
| 空闲回收 | 异步 | Backend / K8s 触发回收,Worker 稍后完成退出 |
6. Worker 生命周期状态机
stateDiagram-v2
[*] --> PENDING : Backend 创建 Deployment
PENDING --> IDLE : Pod 就绪, ready 标记文件存在
IDLE --> BUSY : Backend 通过 WS 推送消息
BUSY --> WAITING_USER : agentcore 回调 ask_user
WAITING_USER --> BUSY : 用户回复经 WS 推送
BUSY --> IDLE : 任务完成
IDLE --> DRAINING : 空闲超时, idle_ttl_seconds
DRAINING --> [*] : 优雅关闭完成
BUSY --> FAILED : 执行出错
PENDING --> FAILED : Pod 启动失败
IDLE --> FAILED : livenessProbe 失败
| 状态 | 含义 | Backend 行为 |
|---|---|---|
| PENDING | Deployment 已创建,Pod 尚未就绪 | 等待,轮询 Pod 状态 |
| IDLE | 容器就绪,等待消息 | 可以推送新消息 |
| BUSY | 正在执行用户请求 | 接收流式事件,不发新消息 |
| WAITING_USER | agentcore 在等待用户回复 | 转发询问给用户,等待回复 |
| DRAINING | 空闲超时,正在优雅关闭 | 不再推送消息,等待退出 |
| FAILED | 容器启动或执行失败 | 上报错误,可能需要重新创建 |
7. 空闲回收与优雅关闭
7.1 空闲策略(WorkerIdlePolicy)
为避免长驻容器浪费资源,通过空闲策略控制回收:
| 参数 | 类型 | 说明 |
|---|---|---|
idle_ttl_seconds | 必填 | 空闲多少秒后自动关闭(如 300 = 5 分钟) |
max_lifetime_seconds | 可选 | 容器最大存活时间(如 3600 = 1 小时) |
7.2 优雅关闭流程
当容器收到 TERM 信号时(空闲超时、手动取消或 K8s 重调度):
1. SIGTERM 信号到达
2. 写入时间戳到 /workspace/session/worker-draining.log
3. 删除 /tmp/agent-store-worker.ready 标记文件
4. readinessProbe 立即失败 → K8s 停止路由新请求到此 Pod
5. 当前任务完成(如果有),通过 `checkpoint_put` 把状态发给 Backend
6. 进程退出(exit 0)
7. K8s 等待 terminationGracePeriodSeconds(30 秒)后 SIGKILL
7.3 Worker 重启恢复
当用户在 Worker 关闭后继续对话,Backend 会自动创建新的 Deployment:
- 新 Worker 启动,Backend 从数据库读取会话历史和最近 checkpoint 摘要,生成
run-context.json - Worker 建立 WebSocket 连接后,如需完整恢复数据,发送
checkpoint_get - Backend 查询数据库并返回最新可用 checkpoint
- agentcore 根据返回结果恢复执行状态
- 从用户角度看,对话无缝继续
8. 多轮对话的连续性
8.1 内存级连续性
容器不退出期间,agentcore 在内存中保持:
- 完整的对话上下文
- 大模型的会话状态
- 工具调用结果缓存
8.2 Backend 统一持久化
当前方案下,checkpoint 与会话状态的权威存储都在 Backend 管理的数据库中。
数据流如下:
sequenceDiagram
participant W as Worker
participant B as Backend
participant DB as 数据库
W->>B: checkpoint_put
B->>DB: 写入 checkpoint / session state
DB-->>B: 写入成功
B-->>W: checkpoint_put_ack
恢复时则反过来:
sequenceDiagram
participant W as Worker
participant B as Backend
participant DB as 数据库
W->>B: checkpoint_get
B->>DB: 查询最新 checkpoint
DB-->>B: 返回 snapshot
B-->>W: checkpoint_get_result
这意味着:
- 容器内不需要直接打开数据库文件
- 容器内不需要持有数据库连接信息
- Backend 统一负责权限、审计和数据裁剪
本地文件目录仍然可以保留给缓存、日志、临时产物使用,但它不再是权威状态来源。
9. 会话的关闭与重新打开
| 操作 | 效果 | 数据影响 |
|---|---|---|
| close(关闭) | 标记为已归档;Worker 收到 TERM 信号优雅退出 | 历史、文件、状态目录全部保留 |
| reopen(重开) | 恢复为活跃状态 | 可继续发送消息,Worker 按需重新启动 |
10. 运行状态流转
stateDiagram-v2
[*] --> PENDING : 创建 RunRecord
PENDING --> SUBMITTED : K3s Deployment 创建成功
PENDING --> PREVIEWED : dry-run 模式, 仅渲染 YAML
SUBMITTED --> COMPLETED : Worker 回调 message_response
SUBMITTED --> FAILED : 执行失败
SUBMITTED --> CANCELLED : 用户取消
| 状态 | 含义 |
|---|---|
| PENDING | 已记录但未提交到 K3s |
| SUBMITTED | Deployment + Service 已创建或 Worker 已就绪 |
| PREVIEWED | 只渲染了 YAML,未真正提交(dry-run 调试) |
| COMPLETED | 正常完成 |
| FAILED | 执行出错 |
| CANCELLED | 用户取消,已清理资源 |
下一步
了解了完整的生命周期后,请继续阅读 输入输出流程。