agent-compose English GitHub

agent-compose.yml 配置手册

本文档说明当前代码实际接受的 agent-compose.yml / agent-compose.yaml 字段、默认值、约束和使用方式。解析器采用严格字段校验:未知字段、重复字段以及类型不符都会报错,因此字段名必须与本文一致。

重要:项目级工作区只支持顶层复数键 workspaces。顶层 workspace 已不受支持,会被当作未知字段拒绝。Agent 选择某个工作区时仍使用单数键 agents.<agent>.workspace

可以在应用配置前进行本地校验:

agent-compose config --quiet
agent-compose -f ./path/to/agent-compose.yml config

第一条命令只校验;第二条还会输出归一化后的配置,并对标记为 secret 的值进行脱敏。默认查找当前目录下的 agent-compose.yml,其次查找 agent-compose.yaml;两者同时存在时应使用 -f/--file 明确选择。

兼容性策略

公开 YAML 编写格式自 v2608.1.0 起保持稳定:该版本或后续任一稳定版本能够接受的配置,在之后的稳定版本中仍应有效。这是向后兼容承诺;新版本仍可增加可选字段,而使用严格解析器的旧版本不保证识别这些新字段。

删除或改名稳定字段、进行不兼容的类型变更,以及把可选字段改为必填字段均属于破坏性变更。收窄已有短写形式或校验约束,以及改变默认值、插值或归一化语义,也必须经过兼容性审查。安全修复可以有意拒绝不安全的历史值,但必须说明影响和迁移方式。

仓库通过机器可读的 v2608.1.0 字段契约以及累积的解析和归一化 fixture 执行该策略。agent-compose config --quiet 仍是用户使用已安装版本校验项目配置的入口;跨版本契约比较属于仓库 CI 职责,不新增独立 CLI 命令。

完整结构速览

下面的配置用于展示字段所在位置。它刻意包含了较多能力,实际项目只需保留需要的部分。

name: review-pipeline

env_file:
  - .env
  - .env.local

variables:
  DISPLAY_NAME: review-pipeline
  CONTROL_TOKEN:
    value: ${CONTROL_TOKEN}
    secret: true

workspaces:
  source:
    provider: file
    path: .
  upstream:
    provider: git
    url: https://github.com/example/project.git
    ref: main
    target: .

mcp_servers:
  local-tools:
    type: local
    command: npx
    args: ["-y", "@example/mcp-server"]
    env:
      API_TOKEN:
        value: ${MCP_API_TOKEN}
        secret: true
  issue-tracker:
    type: remote
    transport: http
    url: ${ISSUE_TRACKER_MCP_URL}
    headers:
      Authorization:
        value: Bearer ${ISSUE_TRACKER_TOKEN}
        secret: true

octobus_servers:
  internal:
    url: https://octobus.internal.example
    token: ${OCTOBUS_INTERNAL_TOKEN}
  public:
    url: https://octobus.example
    token: ${OCTOBUS_PUBLIC_TOKEN}

volumes:
  cache:
    name: review-cache
    driver: local
    labels:
      purpose: agent-cache
    options: {}

agents:
  reviewer:
    enabled: true
    provider: codex
    model: ${REVIEW_MODEL}
    system_prompt: |
      Review changes carefully and report concrete evidence.
    image: chaitin/agent-compose-guest:latest
    build:
      context: .
      dockerfile: guest-images/Dockerfile.agent-compose-guest
      target: runtime
      args:
        CHANNEL: stable
      platforms: [linux/amd64]
      tags: [review-agent:latest]
      no_cache: false
      pull: true
    driver:
      docker: {}
    env:
      LOG_LEVEL: info
      SERVICE_TOKEN:
        value: ${SERVICE_TOKEN}
        secret: true
    mcp_servers:
      - local-tools
      - name: audit-api
        type: remote
        transport: sse
        url: https://mcp.example.com/sse
        headers:
          Authorization:
            value: Bearer ${AUDIT_TOKEN}
            secret: true
    capset_ids:
      - engineering
      - internal/code-review
    skills:
      - ./skills/review
      - name: release-check
        provider: git
        url: https://github.com/example/agent-skills.git
        path: skills/release-check
        ref: main
    volumes:
      - cache:/cache
      - type: bind
        source: ./reports
        target: /workspace/reports
        read_only: false
    workspace:
      name: source
    scheduler:
      enabled: true
      sandbox_policy: sticky
      triggers:
        - name: hourly-review
          cron: "0 * * * *"
          prompt: Review the current workspace.
          sandbox_policy: new
    jupyter:
      enabled: false
      guest_port: 8888

通用规则

严格解析

环境变量来源和优先级

env_file 决定 ${NAME} 插值时可读取哪些 dotenv 文件。加载顺序如下:

  1. env_file 列表顺序加载,后面的文件覆盖前面的同名值。
  2. 运行 agent-compose CLI 的进程环境最后覆盖 dotenv 文件。

若未配置 env_file,CLI 先查配置文件所在目录的 .env,不存在时再查当前工作目录的 .env。显式写 env_file: [] 表示不自动加载任何 dotenv 文件。显式文件不存在、不可读或列表中有空路径都会失败。

${NAME} 只支持简单形式,不支持 shell 的 ${NAME:-default}、命令替换或递归展开。引用的变量不存在时配置校验失败。

当前支持插值的位置包括:

其他字符串字段不会自动插值,例如 nameproviderimagesystem_prompt、Workspace 的其他字段、Build 字段和 Scheduler 字段。

环境值的两种写法

variablesagents.*.env、MCP env 和 MCP headers 都使用同一个值结构:

PLAIN_VALUE: hello
SECRET_VALUE:
  value: ${SECRET_VALUE}
  secret: true
字段 类型 默认值 作用
value string "" 实际值;在受支持的位置执行 ${NAME} 插值。
secret bool false 标记敏感值。规范化配置输出会显示 ********,运行时仍使用真实值。

secret 是脱敏元数据,不会自行从环境读取值;仍需在 value 中写 ${NAME}

顶层字段

字段 类型 必填 作用
name string 条件必填 项目标识。省略时按照 Docker Compose 规则从配置文件目录推导。
env_file string 或 string[] 指定插值使用的 dotenv 文件。相对路径以配置文件目录为基准。
variables map 项目级命名变量及 secret 元数据,写入规范化项目配置。它们不会自动继承到 Agent 的 env,也不会成为其他 ${NAME} 的变量来源。
workspaces map 可复用的项目级 Workspace 定义。只能使用复数形式。
mcp_servers map 可由 Agent 按名称引用的 MCP Server 定义。
octobus_servers map 由 qualified capset_ids 选择的具名项目级 OctoBus Server。
volumes map 项目管理或引用的持久 Volume。
agents map Agent 定义;map key 是 Agent 名。

name

name: code-review

名称必须匹配 ^[a-z0-9][a-z0-9_-]*$。例如 review-v22-review 合法,Review 和包含空格的名称不合法。省略名称时,目录 basename 会转为小写、移除不支持的字符并裁掉开头的 _-。最终名称是 daemon 内全局唯一的 project 身份;移动 compose 文件不会创建另一个 project。

env_file

单文件可以写标量:

env_file: .env.production

多文件写列表:

env_file:
  - .env
  - .env.production

variables

variables:
  REGION: cn-hangzhou
  RELEASE_TOKEN:
    value: ${RELEASE_TOKEN}
    secret: true

variables 当前用于保存项目级配置值和脱敏语义。若某个值要传入 sandbox,仍需在对应 Agent 的 env 中声明。

workspaces:项目级工作区

顶层必须使用 workspaces

workspaces:
  source:
    provider: file
    path: .

以下旧写法无效:

# 错误:顶层 workspace 会被严格解析器拒绝
workspace:
  provider: file
  path: .

每个 workspaces.<key> 支持:

字段 类型 适用范围 作用
name string 兼容字段 顶层条目的实际名称由 map key 决定;通常不要重复填写。
provider string 必填 filegit
url string git 必填 Git clone URL;file 不允许设置。
ref string git 可选 Git branch、tag 或 commit。
path string file 必填 相对于 compose 文件目录的来源路径,不可逃逸项目根目录;Git Workspace 不支持仓库内子目录。
target string 可选 sandbox workspace 根目录下的目标目录,默认 .
username string git 可选 Git HTTP 用户名。
password string git 可选 Git 密码,只允许完整环境引用 ${NAME}
token string git 可选 Git token,只允许完整环境引用 ${NAME}

本地 Workspace 在每次项目 run 创建时被复制为隔离快照,Agent 对快照的修改不会写回源目录。

workspaces:
  source:
    provider: file
    path: ./src
  release-branch:
    provider: git
    url: https://github.com/example/service.git
    ref: release
    target: .

Workspace 选择规则:

mcp_servers:项目级 MCP

项目级 MCP 是命名映射,名称须符合稳定标识符格式。支持 localremote 两类。

Local MCP

mcp_servers:
  filesystem:
    type: local
    command: npx
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
    env:
      NODE_ENV: production
字段 类型 必填 说明
type string 必须为 local
command string sandbox 内启动 MCP Server 的命令。
args string[] 命令参数;空项和重复项会在规范化时去除。
env map 进程环境,支持值对象和 ${NAME} 插值。
transport string 禁止 Local MCP 不接受该字段的非空值。
url string 禁止 Local MCP 不接受 URL。
headers map 禁止 Local MCP 不接受 HTTP headers。

Remote MCP

mcp_servers:
  docs:
    type: remote
    transport: sse
    url: https://mcp.example.com/sse
    headers:
      Authorization:
        value: Bearer ${MCP_TOKEN}
        secret: true
字段 类型 必填 说明
type string 必须为 remote
transport string ssehttp
url string 远程 MCP 地址,支持 ${NAME} 插值。
headers map 请求头,支持值对象、secret 和插值。
command string 禁止 Remote MCP 不执行本地命令。
args string[] 禁止 Remote MCP 不接受命令参数。
env map 禁止 Remote MCP 不接受进程环境。

项目级 MCP 不会自动注入所有 Agent。Agent 必须在自己的 mcp_servers 中引用或定义需要的 Server。

octobus_servers:项目级 OctoBus Server

项目可以声明多个具名 OctoBus Server:

octobus_servers:
  internal:
    url: https://octobus.internal.example
    token: ${OCTOBUS_INTERNAL_TOKEN}
  public:
    url: https://octobus.example
    token: ${OCTOBUS_PUBLIC_TOKEN}
字段 类型 必填 含义
url string OctoBus Server 的绝对 httphttps URL;不允许包含用户信息或 fragment。支持 ${NAME} 插值。
token string daemon 连接该 Server 时使用的 Bearer token。支持 ${NAME} 插值;空值表示不配置鉴权 token。

map key 是 Server 名称,必须符合稳定标识符格式。Agent 通过 <server>/<capset> 形式限定现有 capset_ids 条目来选择 Server,例如 internal/code-review。仅声明 Server 不会自动向 Agent 授权。

OctoBus token 天然属于敏感信息。应把它保存在环境变量或 dotenv 配置中,并通过 ${NAME} 引用。daemon 会保留解析后的 token 以代理请求,但会在面向用户的规范化输出中将其脱敏,也不会把它注入 sandbox。不要把字面 token 提交到 compose 文件中。

项目 API 或规范化输出中的脱敏值 ******** 并不是凭据本身。ApplyProject 保持原有的完整替换语义,不会把该 marker 解释为“保留”;compose 和 CLI 的 re-apply 流程仍必须从原始、以环境变量为凭据来源的配置中解析并提交真实 secret。

PatchProject 用于基于已脱敏的 GetProject 结果编辑现有项目。请求必须携带完整目标 ProjectSpec、项目引用和当前 spec hash。在现有 secret 的同一稳定位置提交 ******** 会保留已存值;在新增、移动后或非 secret 的位置使用 marker 会被拒绝。提交真实值会替换 secret,省略集合项则会删除该项。Patch 不能创建或重命名项目,也不能修改 source;当前 hash 过期时返回 ABORTED。CLI 仍使用 ApplyProject,这些 Patch 语义不会改变 CLI 行为。

项目 re-apply 与 MCP Server 沿用相同的 managed agent 配置模型。运行中的 sandbox 保留创建时固化的 capset_ids 授权集合,后续调用则从当前 managed agent definition 解析所引用的 Server。因此,更新 Server URL 或 token 无需重建 sandbox 即可生效。新增 capset 只对新 sandbox 可用;如果旧 sandbox 已授权的 capset 所对应 Server 已无法解析,该调用会失败,不会回退到其他 Server。

volumes:项目级 Volume

volumes:
  cache: {}
  shared-data:
    name: existing-data
    driver: local
    external: true
    labels:
      owner: platform
    options:
      tier: fast
字段 类型 默认值 作用
name string 由项目和 key 派生 指定底层 Volume 名。
driver string local Volume driver。local 使用 daemon 所在主机目录;agent 使用 k8s runtime 时,k8s 会创建 Kubernetes PersistentVolumeClaim。
external bool false true 时引用已经存在的 Volume,而不是由项目创建。
labels map[string]string 附加标签。key/value 会去除首尾空白。
options map[string]string Driver 选项。k8s 支持 size(默认 1Gi)、storage_classaccess_mode(默认 ReadWriteOnce)和 namespace(默认 K8S_NAMESPACE/default)。PVC 使用 daemon 所在的 Kubernetes 集群。

Volume map key 必须符合稳定标识符格式。Agent 通过 agents.<name>.volumes 挂载项目 Volume。

agents.<name>

agents 是以 Agent 名为 key 的映射:

agents:
  reviewer:
    provider: codex
    image: chaitin/agent-compose-guest:latest

支持的字段如下:

字段 类型 默认值 作用
enabled bool true 是否启用 Agent。禁用后定义保留但不可按正常流程运行,Scheduler 也不会启用。
display_name string Agent 的可读显示名称。
description string Agent 职责的可读说明。
provider string codex Agent CLI/provider:codexclaudegeminiopencodepidsh。兼容别名会在持久化边界归一化。
model string provider/daemon 默认 模型名;Pi 和 dsh 要求使用 <llm-provider-id>/<model-name>;支持 ${NAME} 插值。
system_prompt string 附加的系统提示,适合使用 YAML `
image string daemon 默认镜像 Guest 镜像引用,也会作为 build 的一个输出 tag。
build string/object agent-compose build 使用的镜像构建配置。
driver object Docker 运行时 driver,必须且只能选择一个 key。
env map 注入 sandbox 的环境变量。
mcp_servers scalar/object/list 引用项目级 MCP,或声明 Agent 专属 MCP。
capset_ids string[] 允许该 Agent sandbox 使用的 OctoBus capability set 声明;可用 <server>/<capset> 选择项目 Server。
skills list 注入 Agent 的 Skill 来源。
volumes list Volume 或 bind mount 列表。
workspace object 显式引用一个顶层 workspaces 条目,或定义 Agent 内联 Workspace。
sandbox object 删除已停止 runtime Sandbox 生命周期配置。
scheduler object 自动触发 Agent 的 Scheduler。
jupyter object disabled Agent run 的 Jupyter 默认配置。

enabledprovidermodelsystem_prompt

agents:
  reviewer:
    enabled: true
    provider: claude
    model: ${CLAUDE_MODEL}
    system_prompt: |
      Focus on correctness, security, and regression risk.

Provider 支持 codexclaudegeminiopencodepidsh。当前兼容归一化还接受 claude-code / claude_codegemini-cli / gemini_cliopen-code / open_codepi-agent / pi_agentdeepseek / deepseek-harness / deepseek_harness,新配置建议使用规范名称。

Pi 和 dsh 是多模型 Agent,因此 model 必须同时标识已配置的 LLM provider 和模型,例如:

agents:
  reviewer:
    provider: pi
    model: openai/gpt-5.4

第一个 / 前的部分是 agent-compose 中配置的 LLM Provider ID,后面的全部内容是发送给上游的字面量 Model ID,Model ID 本身还可以包含 /。Pi 和 dsh 的模型流量都通过 sandbox runtime LLM facade 转发,上游凭据仍只保留在 daemon 中。

Daemon models.json

daemon 在启动时加载一次 $DATA_ROOT/models.json。文件不存在是合法状态:catalog-owned 条目按不存在处理,已有 system 和环境 Provider 的默认值保持不变。修改文件后需要重启 daemon。

{
  "default": "gateway/deepseek-v4-flash",
  "providers": {
    "gateway": {
      "baseUrl": "https://gateway.example.com/api/openai",
      "protocol": "chat_completions",
      "apiKey": "${GATEWAY_API_KEY}",
      "models": [
        {
          "id": "deepseek-v4-flash",
          "maxOutputTokens": 8192
        }
      ]
    },
    "openai": {
      "baseUrl": "https://api.openai.com/v1",
      "protocol": "responses",
      "apiKey": "$OPENAI_API_KEY"
    }
  }
}

default 是可选的 provider/model 引用。每个 Provider 都必须提供 baseUrl,并选择 responseschat_completionsanthropic_messagesapiKey 和 Header 值可以是字面量,也可以是完整的 $NAME / ${NAME} 引用;daemon 在启动时从自身环境解析。JSON 非法、未知字段、Protocol 不受支持、Token 上限非法或环境变量引用无法解析都会使 daemon 启动失败。

可选的 models 数组只补充模型级元数据和行为,包括 idnamebaseUrlprotocolheaders 和正整数 maxOutputTokens。模型级 protocol 必须与 Provider 的协议族兼容:OpenAI Provider(responseschat_completions)只允许 responseschat_completions,Anthropic Provider(anthropic_messages)只允许 anthropic_messages。这些属性属于具体的 Provider/Model 部署,共享同一 Model ID 的 Provider 不会相互覆盖;该数组也不是白名单。只要 gateway Provider 已配置,gateway/a-model-not-listed-here 仍会使用 Provider 默认配置,把右侧 Model ID 原样发送给上游。

所有兼容的 Coding Agent 和 scheduler.llm 使用这份目录完成 agent-compose 的 Provider 路由和模型选择;它不替代 Agent 自身的模型能力目录。Agent 中完整配置的 LLM_API_ENDPOINTLLM_API_PROTOCOLLLM_API_KEY 仍是更高优先级的兼容路径;daemon 自身完整的 LLM_* 配置也继续作为默认值,并优先于 models.json.default。Catalog Provider ID 如果与已有非 catalog Provider 冲突,daemon 会在不覆盖原配置的前提下启动失败。

image

agents:
  reviewer:
    image: chaitin/agent-compose-guest:latest

运行时会确保所选 driver 能使用该镜像。若同时配置 buildimage 也会加入构建 tag;若两者均未提供 tag,执行 agent-compose build 会失败。

GitHub CI 会向 Docker Hub 发布以下镜像:

镜像 用途 Dockerfile 平台
chaitin/agent-compose 控制面 daemon Dockerfile linux/amd64linux/arm64
chaitin/agent-compose-guest Sandbox guest runtime guest-images/Dockerfile.agent-compose-guest linux/amd64linux/arm64
chaitin/agent-compose-guest:archlinux 可选的 Arch Linux sandbox guest runtime guest-images/Dockerfile.agent-compose-guest-archlinux linux/amd64

Agent 的 image 可以使用任一 guest 镜像。daemon 镜像用于部署控制面,不能作为 guest 镜像使用。两个 guest 都不绑定某一个 driver;CI 不发布 BoxLite-only、Microsandbox-only 或其他 driver 专用 guest 镜像。

build

短写法只指定 context:

build: ./guest

完整写法:

build:
  context: ./guest
  dockerfile: Dockerfile
  target: runtime
  args:
    VERSION: "1.2.3"
  platforms:
    - linux/amd64
  tags:
    - example/guest:latest
  no_cache: false
  pull: true
字段 类型 默认值 作用
context string . Build context;相对路径以 compose 文件目录为基准。
dockerfile string Dockerfile Dockerfile 路径,由镜像构建后端解释。
target string 多阶段构建 target。
args map[string]string Build args;key 去除首尾空白且不能为空。
platforms string[] 目标平台,格式为 os/arch;当前最多一个。
tags string[] 输出镜像 tag,可与 Agent image 以及 CLI --tag 合并。
no_cache bool false 禁用构建缓存。
pull bool false 构建时拉取较新的基础镜像。

当前 agent-compose build 使用 Docker daemon image store。CLI 同名选项可以覆盖或追加 YAML 配置。

driver

省略 driver 时默认为:

driver:
  docker: {}

必须且只能选择一个 runtime:

driver:
  docker:
    host: ""

或:

driver:
  boxlite:
    kernel: ""
    rootfs: ""

或:

driver:
  microsandbox:
    profile: secure

或:

driver:
  k8s:
    context: production
    namespace: agent-compose
Driver 子字段 当前状态
docker host 支持的稳定 driver。host 被解析和保留;daemon 的 Docker 边界仍由部署配置决定。
boxlite kernel, rootfs Linux 构建可编译支持;运行时初始化是惰性的。子字段会去除首尾空白。
microsandbox profile Linux 构建可编译支持;运行时初始化是惰性的。profile 会去除首尾空白。
k8s context, namespace 通过 Kubernetes 创建 sandbox Pod。context 选择 kubeconfig context;省略时由 client-go 使用 kubeconfig 当前 context 或集群内配置。namespace 覆盖 K8S_NAMESPACE,最终回退到 default
firecracker kernel, rootfs 仅保留在解析 schema 中;当前规范化会明确报 unsupported runtime driver firecracker,不可使用。

k8s driver 要求 daemon 运行在目标集群内部。对外支持的安装入口是 charts/agent-compose Helm Chart:

helm install agent-compose ./charts/agent-compose \
  --kube-context prod-cluster \
  --namespace team-a \
  --create-namespace

Helm release 的 namespace 会作为默认 K8S_NAMESPACE;Chart 也会根据这个 namespace 渲染 daemon Service DNS 回调地址和 ClusterRoleBinding subject。Sandbox Pod 不会挂载 daemon 的数据 PVC,也不使用 hostPath;provision 好的 workspace 和 provider home 配置通过 Kubernetes Exec 流式传入 Pod。

为完整说明 schema,下面的结构可以被解析器识别,但当前会在规范化阶段失败:

# 当前实现中无效。
driver:
  firecracker:
    kernel: /path/to/kernel
    rootfs: /path/to/rootfs

即使 schema 支持某个 driver,当前二进制也必须编译了该 driver。可通过 agent-compose --json versioncompiled_drivers 查看;这不代表 KVM、Docker daemon 或运行时制品健康。

env

env:
  LOG_LEVEL: debug
  API_TOKEN:
    value: ${API_TOKEN}
    secret: true

这些值进入 Agent sandbox。相同名称的空项会在后续边界归一化;secret: true 控制展示脱敏。

mcp_servers

引用一个项目级 MCP:

mcp_servers: filesystem

引用多个:

mcp_servers:
  - filesystem
  - issue-tracker

定义 Agent 专属 MCP:

mcp_servers:
  - name: private-tools
    type: local
    command: private-mcp
    args: ["serve"]

内联对象支持 nametypetransportcommandargsenvurlheaders,其 local/remote 约束与项目级 MCP 相同。内联 MCP 必须提供 name;同一 Agent 内不能重复声明同名内联 MCP。重复引用同一个项目级 MCP 会去重。

capset_ids

capset_ids:
  - legacy-capset
  - internal/engineering
  - public/ticketing

列表会去除空值和重复值。真实 capset ID 必须符合 OctoBus 的 ^[a-zA-Z][a-zA-Z0-9_-]{0,62}$ 规则。legacy-capset 这类未限定值使用 daemon 全局 OctoBus 配置,从而保持已有项目文件的行为。internal/engineering 这类限定值选择 octobus_servers.internalinternal 仅供 agent-compose 选择上游,OctoBus 收到的 capset ID 仍为 engineering。限定值引用未声明 Server、包含多个 / 或真实 capset ID 不合法时会产生配置校验错误。

限定值和未限定值可以混用。新增 octobus_servers 绝不会改变未限定值的路由。完整声明仍是 sandbox 的授权边界:授权 internal/engineering 不会同时授权 engineeringpublic/engineering

所选 ID 用于注入 capability gateway 环境和能力说明。未限定值缺少 daemon 全局 gateway 配置、Server 不可达或能力说明获取失败时采用 best-effort 行为并产生 warning,sandbox 仍会继续创建。项目级 OctoBus URL 和 token 始终留在 daemon 中,不会进入 guest metadata 或能力说明。

skills

Skill 目录必须包含有效的 SKILL.md。provider 支持 filehttpgit;同一 Agent 的最终 Skill 名不可重复。ZIP 是内容格式,不是 provider。

本地目录:

skills:
  - name: review
    provider: file
    path: ./skills/review

Git 来源:

skills:
  - name: review
    provider: git
    url: https://github.com/example/skills.git
    path: review
    ref: v1.0.0
    username: ${GIT_USERNAME}
    token: ${GIT_TOKEN}

远程 ZIP:

skills:
  - name: review
    provider: http
    url: https://downloads.example.com/review.zip
    format: zip
    path: review
字段 类型 作用
name string Skill 名;省略时从 path/URL 推导,最终必须符合稳定标识符格式。
provider string 必填,支持 filehttpgit
url string httpgit 必填。
path string file 的本地路径;Git 或 ZIP 内容内的子目录。相对 file 路径以 compose 文件目录为基准。
ref string Git branch、tag 或 commit。
format string 可选内容格式,目前只支持 zip;HTTP Skill 必须设置。
username string HTTP/Git 用户名,可插值。
password string HTTP/Git 密码,只允许完整环境引用 ${NAME}
token string HTTP/Git token,只允许完整环境引用 ${NAME}

passwordtoken 不允许明文。执行 configup 时,CLI 会从项目 dotenv/进程环境解析完整的 ${NAME} 引用,再把项目提交给 daemon;引用对应的变量缺失时保留引用本身而不是报错,并在 clone 时再解析。面向用户的规范化输出和项目 API 会对解析后的凭据脱敏。远程 ZIP 下载限制为 HTTP(S),并执行大小、压缩包和网络地址安全检查。

Git ref 会在各自业务生命周期中解析:Skill 在 Agent run 时解析,Workspace 在 sandbox provisioning 时解析,Scheduler 来源在 config/up 时解析并保存脚本快照。因此 moving branch 在三处可能得到不同 commit;需要严格一致时,应在 ref 中直接填写 commit SHA。

volumes

短写格式是 source:target[:ro|rw]

volumes:
  - cache:/cache
  - ./reports:/workspace/reports:ro

长写格式:

volumes:
  - type: volume
    source: cache
    target: /cache
    read_only: false
  - type: bind
    source: ./reports
    target: /workspace/reports
    read_only: true
字段 类型 必填 作用
type string volumebind。省略时:source 命中顶层 Volume、是绝对路径或以 . 开头时可推断,否则按 Volume。
source string 顶层 Volume key/有效 Volume 名,或 bind 的 host source。
target string Guest 内绝对路径。
read_only bool 只读挂载,默认 false

同一 Agent 不能将多个条目挂到相同 target。短写使用 : 分隔,因此不适合包含冒号的 source/target,此时应使用长写。

Kubernetes(k8s)driver 不支持本地 bind 挂载。bind 的 source 指向 daemon 所在机器上的路径,而该路径在 Pod 内不可用。请改用 driver: k8s 的顶层命名 Volume(由 PVC 提供);配置校验阶段会直接拒绝 bind 挂载。

workspace:Agent 选择或内联工作区

这里是 Agent 内部的单数 workspace,与顶层复数 workspaces 不是同一个层级。

引用顶层条目:

workspace:
  name: source

内联本地 Workspace:

workspace:
  provider: file
  path: ./src

内联 Git Workspace:

workspace:
  provider: git
  url: https://github.com/example/project.git
  ref: main
  target: .

name 与任一来源字段或 target 同时出现,该对象按内联 Workspace 处理,而不是从顶层继承后局部覆盖。需要复用时只写 name

sandbox:已停止 runtime 生命周期

默认情况下,停止 sandbox 会在确认 stop 后删除 driver runtime 及其私有可写状态,同时保留 sandbox 元数据、日志、workspace 和声明的持久挂载;resume 会创建新的 runtime。若需要重新启动同一个容器、Box 或 microVM sandbox,请显式保留私有 runtime 状态:

sandbox:
  stopped_runtime_policy: retain

stopped_runtime_policy 只接受 retainremove(默认值):

Kubernetes driver 不接受 retain:Kubernetes Pod 没有“已停止但仍保留”的状态,停止 sandbox 会删除 Pod。请使用 remove,让 resume 根据镜像和持久挂载重新创建 Pod。若后续调度任务需要复用同一个运行中的 Pod,请使用 sandbox_policy: sticky;sticky 完成后会保持 Pod 运行,它与 stopped-runtime retention 是两种不同的生命周期策略。

有效策略会在 sandbox 创建时生成快照;之后修改项目配置只影响新 sandbox。没有策略快照的历史 sandbox 会继续保留 runtime。agent-compose inspect sandbox <sandbox> --json 通过 stopped_runtime_policystopped_runtime_statestopped_runtime_last_errorstopped_runtime_released_at 展示生命周期记录。状态含义如下:

对于 remove,daemon 会先持久化 release_pending。如果生命周期记录中存在晚于最近一次确认 stop 的启动或启动尝试,即使粗粒度 VM 状态是 failed 而不是 running,也会先确认 driver stop;之后才删除 runtime 并把记录标记为 released。这个顺序可避免部分启动的 runtime 被跳过 stop,或未经确认便被破坏性释放。磁盘上的 ownership record 格式属于内部恢复状态,不是稳定的运维接口。

scheduler

Scheduler 可以使用声明式 triggers,也可以使用 JavaScript script;两者互斥。

字段 类型 默认值 作用
enabled bool true 是否启用该 Agent 的 Scheduler。禁用 Agent 也会使其 Scheduler 无效。
sandbox_policy string new Scheduler 默认 sandbox 策略:newsticky
concurrency_policy string skip 整个 Agent Scheduler 的重叠运行策略:skipparallel
run_timeout duration 单次 scheduler run 的最大时长。为空时继承 SCHEDULER_RUN_TIMEOUT;支持 30m2h 等 Go duration。
model string Agent 的模型 scheduler.llm 默认使用的 provider/model;调用参数中的 modelLLM_MODEL 优先。
triggers list 声明式触发器。
script string/object 内联 JavaScript,或扁平的 file/http/git 来源配置。不能和 triggers 同时使用。

new 为每次调用创建新 sandbox;sticky 允许 Scheduler 绑定并复用 sandbox。单个 Trigger 的 sandbox_policy 可覆盖执行 Agent 时的策略。

concurrency_policy 作用于整个 Agent Scheduler,包括全部声明式或脚本注册的 Trigger,以及手动 Scheduler 调用。skip 会把与同一 Scheduler 既有运行重叠的新 run 记录为 skipped,且不会排队补跑;parallel 允许重叠 run 并行执行。它不是 Trigger 级策略。

脚本型 scheduler 可以用 scheduler.llm.asyncscheduler.agent.async 并行发起 host 调用。两个 scheduler env 用于限制同时进行的数量:

Env 默认值 说明
LLM_MAX_CONCURRENCY 8 同时进行的 scheduler.llm.async 调用数。
AGENT_MAX_CONCURRENCY 3 同时进行的 scheduler.agent.async 运行数。

agent 的上限明显更低:每个并行 agent 运行都会创建独立 sandbox,而 sandbox 创建本身没有数量限制,且每次运行都要经由 SQLite 连接池写入(SQLITE_MAX_OPEN_CONNS,默认 4 条)。非正整数会被忽略并回退到默认值。scheduler.agent.async 始终使用 new sandbox 策略:并行 agent 无法共享同一个 sandbox。

声明式 Trigger

每个 Trigger 必须且只能写一个 kind 字段:cronintervaltimeoutevent

scheduler:
  enabled: true
  sandbox_policy: sticky
  concurrency_policy: parallel
  triggers:
    - name: nightly
      cron: "0 2 * * *"
      timezone: Asia/Shanghai
      prompt: Run the nightly review.
    - name: heartbeat
      interval: 30m
      prompt: Check service health.
    - name: startup-once
      timeout: 15s
      prompt: Perform the startup check.
      sandbox_policy: new
    - name: webhook-review
      event:
        topic: webhook.github.push
      prompt: Review the pushed changes.
字段 类型 必填 作用
name string 可读的稳定名称;同一 Scheduler 中非空名称不可重复。省略时 ID 会结合列表位置稳定派生。
cron string 四选一 5 字段 cron,支持可选秒字段和 robfig/cron descriptor。默认使用 daemon 的本地时区。
timezone string cron trigger 使用的 IANA 时区,例如 UTCAsia/ShanghaiLocal 或省略该字段时使用 daemon 本地时区;其他 trigger 类型不能使用。
interval duration 四选一 周期,例如 30s5m2h;必须大于 0,实际注册精度至少 1ms。
timeout duration 四选一 一次性延迟,例如 15s;必须大于 0,实际注册精度至少 1ms。
event.topic string 四选一 内层 topic 是订阅的非空 topic,可使用如 webhook.github.push
prompt string 触发后发送给 Agent 的 prompt;空值默认为 Run agent <name>.
sandbox_policy string 本次 Agent 调用使用 stickynew;省略时不在生成的调用中显式覆盖。

Daemon 本地时区优先取 TZ,未设置时取操作系统的 /etc/localtime。项目提供的 Docker Compose 会以只读方式挂载宿主机 /etc/localtime;仅当 daemon 需要有意使用不同于宿主机的时区时,才在 .env 中设置 TZ。修改时区后需要重启 daemon。持久化时间戳仍统一使用 UTC。

内联脚本

scheduler:
  enabled: true
  script: |
    scheduler.interval("review", async function () {
      return scheduler.agent("Review the workspace.");
    }, 60000);

脚本由 Scheduler runtime 验证,并从脚本注册结果获取触发器。

外部脚本

本地文件:

scheduler:
  enabled: true
  script:
    provider: file
    path: ./scheduler.js

HTTP URL:

scheduler:
  enabled: true
  script:
    provider: http
    url: https://example.com/scheduler.js

外部脚本 mapping 使用与 Skill、Workspace 相同的来源字段:

应用项目时 CLI 会读取脚本并将内容快照保存到项目规范,而不是让 daemon 以后重新读取来源。HTTP 读取限制包括 10 秒超时、最大 1 MiB、最多 5 次 redirect、UTF-8 校验;HTTPS 不允许降级 redirect 到 HTTP,URL userinfo 不允许使用。

jupyter

jupyter:
  enabled: true
  guest_port: 8888
字段 类型 默认值 作用
enabled bool false Agent run 未用 CLI 显式覆盖时,是否启用 Jupyter。
guest_port int daemon JUPYTER_GUEST_PORT Guest 内监听端口。0 使用 daemon 默认;显式值必须在 1–65535。

设置 guest_port 但保持 enabled: false 会保留端口配置,但默认不启动 Jupyter。CLI run --jupyter 可以为单次运行启用。

常见错误与迁移提示

升级时存在同名 project

升级不会归并已有的同名 project,因为名称和 compose 路径相同并不能证明它们的历史数据等价。一个 project 保留原名:优先 active project,其次按最近更新时间排序,最后使用创建时间和完整 ID 做确定性排序。其余 project 依次改为下一个可用的 <name>-N,并跳过已经存在的数字后缀。

每个 project 的 ID 以及 revision、agent、scheduler、run、sandbox 和 volume 关联仍属于原 project。升级后使用 agent-compose project ls 查看分配后的名称;后续如需更新带后缀的 project,应在对应 compose 文件中设置该名称。

顶层误写 workspace

错误:

workspace:
  provider: file
  path: .

正确:

workspaces:
  source:
    provider: file
    path: .

agents:
  reviewer:
    workspace:
      name: source

同时配置 Scheduler script 和 triggers

二者互斥。把所有注册逻辑放入 script,或完全使用声明式 triggers

以为 variables 会自动进入 sandbox

variables 不会继承到 Agent。需要显式写:

variables:
  API_URL: https://api.example.com

agents:
  reviewer:
    env:
      API_URL: https://api.example.com

如果目标是复用部署环境值,可在两个位置都写 ${API_URL},并通过 env_file 或 CLI 进程环境提供。

以为项目 Workspace 会被自动选择

顶层 workspaces 不会被自动选择。Agent 省略 workspace 时,即使项目只定义了一个条目,也不会配置 Workspace。需要使用时应设置 workspace.name 或内联 Workspace;不使用时应省略该 key,而不是写 workspace: {}

选择未编译或运行条件不满足的 driver

配置 schema 通过不代表 runtime 一定可启动。BoxLite/Microsandbox 只在 Linux 完整构建中编译,并依赖 KVM 和对应运行时制品;Docker 需要可达的 Docker daemon。

最小配置示例

name: docker-minimal

agents:
  reviewer:
    provider: codex
    image: chaitin/agent-compose-guest:latest
    driver:
      docker: {}

验证并应用:

agent-compose config --quiet
agent-compose up
agent-compose run reviewer --prompt "Review this project."