Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

运行时总体架构

这一章解释 backend/ 里“谁负责什么”,以及一次运行到底由哪些对象拼出来。

1. 启动时会装配哪些核心组件

build_application(应用装配入口)在启动时会把下面这些组件接起来:

代码对象当前职责
AppConfig(进程级配置)读取 HTTP 监听地址、存储根目录、包目录、运行时配置、集群模式、默认命名空间、默认服务账号、挂载白名单、Job TTL
FileBackedStore(文件型状态存储)维护 state.jsonuploads/workspaces/,保存 sessionartifactmount grantrun
PackageCatalog(Agent 包目录索引)backend/packages/* 加载成内存里的 LoadedPackage(已加载 Agent 包)
RuntimeProfileCatalog(运行时模板目录索引)backend/config/runtime_profiles.yaml 加载成内存里的 RuntimeProfile
K3sOrchestrator(K3s 编排器)渲染和可选提交 ConfigMapSecretJob,并观察 K8s 状态
ApplicationService(应用服务层)串起 API、状态存储、工作区准备、K8s 提交、状态刷新、多轮会话同步
Router(HTTP 路由)对外暴露 /api/v1/* 接口

这意味着当前后端是一个“单进程控制面 + K3s 执行面”的结构:

  • API 请求先进入 Router(HTTP 路由)
  • RouterApplicationService(应用服务层)
  • ApplicationService 同时依赖本地持久化状态和 K3sOrchestrator(K3s 编排器)
  • 真正执行 agentcore 的单元是被后端提交出去的 K3s Job

2. 当前系统里最重要的几个对象

2.1 SessionRecord(逻辑会话记录)

SessionRecord 表示“同一用户的一段逻辑会话”。核心字段包括:

  • user_id
  • default_package
  • status
  • history
  • latest_run_id
  • closed_at

它的职责是保存多轮对话时间线,容器实例由后续的 run 单独创建。

2.2 ArtifactRecord(上传文件记录)

ArtifactRecord 表示用户上传到 backend 的文件元数据。文件本体会先落到 uploads/,后续在创建 run 时复制进当前 run 的工作区。

2.3 MountGrantRecord(宿主机挂载授权记录)

MountGrantRecord 表示“允许某个用户把某个 backend 所在主机目录挂进容器”。它是显式授权对象,包含:

  • host_path
  • mount_path
  • access_mode

2.4 RunRecord(一次运行记录)

RunRecord 描述一次真实运行,包含:

  • 所属会话 session_id
  • 使用的包 package_name
  • 使用的运行时模板 runtime_profile
  • 工作区模式 workspace_mode
  • 输入文件 artifact_ids
  • 可选挂载授权 mount_grant_id
  • provider 环境变量键名 provider_env_keys
  • 工作区根目录 workspace_root
  • 运行状态 status
  • K8s 资源引用 resources
  • 渲染结果 rendered

当前物理隔离单元就是 RunRecord

2.5 RuntimeProfile(运行时配置模板)

RuntimeProfile 决定一次 run 的基础运行时底座,主要包括:

  • 基础镜像 image
  • 容器入口 executable
  • 安装策略 installStrategy
  • 执行模式 executionMode
  • 默认模型和默认 Base URL
  • namespace、service account
  • CPU、内存、临时存储的 requests / limits

从运行时设计上看,RuntimeProfile 表达的是“怎样启动一个 agentcore 容器”,并不绑定实现语言。

2.6 AgentPackageManifest(Agent 包清单)

AgentPackageManifest 定义 agent package 本身的业务层意图,主要包括:

  • runtime
  • entry
  • policy
  • assets

当前包目录示例位于:

  • backend/packages/codex-reviewer/
  • backend/packages/claude-code-builder/

这些目录名是样例包名,架构层仍统一按 agent package 理解。

3. agentcoreagent package 当前怎样组合

3.1 agentcore 在当前代码里对应什么

如果把 agentcore 理解为“真正提供执行底座的运行时”,那在当前代码里它主要对应三部分:

  • RuntimeProfile(运行时配置模板)
  • 运行时镜像 image
  • 容器入口 executable

它们以共享模板的方式存在。

3.2 agent package 在当前代码里对应什么

如果把 agent package 理解为“开发者提供的提示词、工具声明、环境事实和策略”,那它对应:

  • agent.yaml
  • prompt/system.md
  • build_in_tools.yaml
  • env/env_facts.yaml
  • 其它包内文本文件

这些文件在运行时由后端加载成 LoadedPackage(已加载 Agent 包),再通过 ConfigMap 注入 Pod 内的 /opt/agent/package

3.3 两者的绑定时机

LaunchPlan(一次运行的不可变启动计划)是 agentcoreagent package 真正结合的地方。它同时持有:

  • package
  • runtime_profile
  • workspace_mode
  • provider_env
  • mount_grant
  • workspace_host_path
  • namespace
  • service_account

随后 K3sOrchestrator 会把这个 LaunchPlan 渲染成三类资源:

  1. ConfigMap
  2. Secret
  3. Job

3.4 当前组合模式的结论

结论很明确:

  • 共享的是 RuntimeProfile 和基础镜像
  • 独立的是每次运行的 Pod、工作区、ConfigMapSecret
  • 一次 run 会把“共享运行时模板 + 当前 agent package + 当前工作区 + 当前 provider 凭据”拼成一个独立运行单元

4. 当前隔离模型与连续性模型

4.1 逻辑隔离按 session

SessionRecord 保存:

  • 历史消息
  • 默认包
  • 会话状态
  • 最近一次 run

它定义的是“同一段对话时间线”。

4.2 物理隔离按 run

每次 create_run(创建运行)都会创建:

  • 一个独立工作区目录
  • 一个独立 ConfigMap
  • 一个可选独立 Secret
  • 一个独立 K3s Job
  • 一个独立 Pod

这意味着当前模型是:

  • 逻辑连续性按 session
  • 物理执行隔离按 run

4.3 会话连续性今天靠什么保持

当前代码里的连续性主要来自三块持久化数据:

  1. SessionRecord.history(会话消息历史)
  2. ArtifactRecord(上传文件记录)和 uploads/ 下的原始文件
  3. RunRecord(运行记录)和 workspaces/<run-id>/out/ 下的结果文件

ApplicationService::sync_session_conversation_history(同步会话历史)会在新 run 开始前刷新该 session 下旧 run 的状态;ApplicationService::sync_run_assistant_message(同步助手回答)会把已完成 run 的 final-answer.md 回填进 SessionRecord.history。这样同一 session 的下一轮可以拿到前一轮回答。

4.4 agentcore 的 checkpoint 连续性应该怎样接入

从通用运行时架构看,agentcore 的 checkpoint 连续性应该依赖持久化挂载路径,典型模式是:

  • 为每个 session 分配一个持久化状态目录
  • 在同一 session 的每次 run 中都把这个目录挂到固定路径
  • agentcore 在该目录内保存 checkpoint、状态数据库、工具缓存和恢复索引
  • 由 backend 保存 session_id -> checkpoint_root 的索引

当前代码已经具备:

  • run 级工作区持久化
  • session / run 元数据持久化
  • reopen 同一 session

当前代码还没有显式的:

  • checkpoint_root 字段
  • session 级持久化状态卷
  • resume API

这部分会在“当前实现边界”章节里继续说明。

5. K8s Rust 调用在当前架构中的位置

这一节专门把代码和功能对应起来。

5.1 backend/src/k8s/mod.rs 负责真正访问集群

K3sOrchestrator::new(K3s 编排器初始化)通过 Client::try_default() 创建 kube 客户端,并调用:

  • ensure_namespace:确保 namespace 存在
  • ensure_service_account:确保 service account 存在且关闭自动挂载 token

K3sOrchestrator::submit_run(提交运行)负责:

  • job_builder::build_bundle 在内存里构造 ConfigMapSecretJob
  • apply 模式下调用 Api<ConfigMap>::create
  • 调用 Api<Secret>::create
  • 调用 Api<Job>::create

K3sOrchestrator::inspect_run_status(检查运行状态)负责:

  • Api<Job>::get_opt 读取 Job 状态
  • Api<Pod>::list 读取同一 Job 对应 Pod 的状态
  • 把 Job / Pod 观察结果映射成 RunStatus

K3sOrchestrator::cluster_status(读取集群状态)负责:

  • Api<Node>::list 读取节点
  • 汇总可调度节点数、taint、磁盘压力和阻塞原因

K3sOrchestrator::cancel_run(取消运行)负责:

  • Api<Job>::delete
  • Api<ConfigMap>::delete
  • Api<Secret>::delete

5.2 backend/src/k8s/job_builder.rs 负责把计划渲染成资源

job_builder::build_bundle(构建运行资源包)会:

  1. 构建承载 package 文件的 ConfigMap
  2. 构建承载 provider 凭据的 Secret
  3. 构建真正执行 run 的 Job

build_job(构建 Job)会把下面这些设置落到资源定义里:

  • /workspace 工作区挂载
  • /opt/agent/package 包目录挂载
  • 可选的用户授权挂载
  • allowPrivilegeEscalation: false
  • capabilities.drop = ["ALL"]
  • runAsNonRoot = true
  • fsGroup = 1000
  • seccompProfile = RuntimeDefault
  • ttl_seconds_after_finished

5.3 backend/src/service.rs 负责把业务对象和 K8s 编排串起来

ApplicationService::create_run(创建运行)是控制流入口,它会:

  1. 校验 session
  2. 解析 package
  3. 解析 RuntimeProfile
  4. 合并 provider 配置
  5. 校验输入文件和挂载
  6. 做集群预检
  7. 同步历史回答
  8. 追加本轮用户消息
  9. 创建工作区
  10. run-context.json
  11. 组装 LaunchPlan
  12. K3sOrchestrator::submit_run
  13. 持久化 RunRecord

6. 当前样例 runtime profile 如何理解

runtime_profiles.yaml 里当前有多组样例 profile。它们在代码里沿用了历史命名,例如:

  • codex-standard
  • claude-code-standard
  • codex-cli-standard
  • claude-code-cli-standard

这些名字只代表当前仓库里已有的样例配置。架构层需要关注的是下面这些字段:

  • image
  • executable
  • installStrategy
  • executionMode
  • requests
  • limits

因此如果后续接入新的 Rust agentcore、Python agentcore 或其它容器入口,后端运行时模型本身不需要变化,变化点主要是:

  • 基础镜像
  • 容器入口
  • checkpoint 目录约定
  • 执行模式适配器

7. backend 与 agentcore 的责任边界

当前更合理的责任边界是:

  • agentcore 负责自己的执行逻辑、checkpoint、工作目录状态、工具调用和恢复逻辑
  • agent package 负责提示词、工具声明、环境事实和策略
  • backend 负责保存 sessionrun、上传文件、工作区目录、K8s 资源引用、结果文件索引以及 reopen/resume 入口

这条边界与 agentcore 的实现语言无关。