Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/pages/agent-compose-yaml-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,8 @@ driver:
| `k8s` | `context`, `namespace` | Creates sandbox Pods through Kubernetes. `context` selects a kubeconfig context; when omitted, client-go uses the kubeconfig current context or in-cluster configuration. `namespace` overrides `K8S_NAMESPACE`, whose final fallback is `default`. |
| `firecracker` | `kernel`, `rootfs` | Reserved in the parser schema. Normalization currently returns `unsupported runtime driver firecracker`, so it cannot be used. |

The `boxlite` and `microsandbox` drivers boot a real kernel with its own user-space network stack and DNS instead of joining the Docker network. Such a sandbox does not resolve Docker Compose service names, and it cannot reach a daemon that is published only on the host loopback. On those drivers `AGENT_COMPOSE_RUNTIME_BASE_URL` (or the driver-specific override) must be an address the sandbox itself can reach — for example the host bridge address used by the KVM deployment — and the daemon must actually be published on that address. Otherwise the runtime LLM facade and the egress proxy stay unreachable from the sandbox even though the daemon reports healthy, and the first `run --prompt` fails with `error sending request for url (http://<compose-service-name>:<port>/api/runtime/…)`.

The k8s driver builds its client from kubeconfig: it uses an explicit
`K8S_KUBECONFIG`/`KUBECONFIG` path when set, otherwise the `~/.kube/config`
loading rules, and falls back to in-cluster configuration only when neither
Expand Down Expand Up @@ -968,6 +970,16 @@ The selected IDs drive capability gateway environment and guide injection. Missi

A resolved skill directory must contain a valid `SKILL.md`. Providers can be `file`, `http`, or `git`; final skill names must be unique within an agent. ZIP is a content format, not a provider.

`SKILL.md` must start with YAML frontmatter: the first line is a `---` fence, the frontmatter ends at the next `---` line, and both `name` and `description` inside it must be non-empty. The frontmatter `name` must be exactly the name configured for that skill. Project validation checks only the skill-name rules; the content rules are enforced when the sandbox starts:

| Condition | Error | Reported when |
| --- | --- | --- |
| No frontmatter | `skill <name> invalid SKILL.md: frontmatter is required` | sandbox start |
| Missing `name` or `description` | `skill <name> SKILL.md requires name and description` | sandbox start |
| Frontmatter `name` differs from the configured name | `skill name mismatch: configured "<configured>", SKILL.md "<declared>"` | sandbox start |

A `SKILL.md` that violates these rules therefore passes `config`/`config --quiet` and fails on the first `run`.

An agent whose `provider` is `dsh` accepts a narrower set of skill names: `^[a-z0-9]+(?:-[a-z0-9]+)*$`, lowercase letters and digits joined by single hyphens. DSH silently drops a skill named otherwise, so such a name is rejected when the project is validated. The `name` in the skill's `SKILL.md` must be the same value.

An interactive session uses the skills published into its sandbox when the sandbox was last prepared. A session attached to a sandbox that is already running does not pick up skills added, removed, or changed since; they take effect once the sandbox is prepared again, for example when a new sandbox starts.
Expand Down Expand Up @@ -1234,6 +1246,8 @@ A scheduler uses either declarative `triggers` or JavaScript `script`; the two f

`new` creates a new sandbox for scheduler calls. `sticky` allows the scheduler to bind and reuse a sandbox. A trigger-level `sandbox_policy` controls the generated agent call for that trigger.

`sandbox_policy` shapes the sandbox of the agent calls a scheduler generates, for declarative triggers and script schedulers alike. One case silently falls back to `new`: a call that carries per-call options — `title`, `driver`, `guestImage`, `workspaceId`, `env`, or `volumes` — runs in its own fresh session sandbox, and the sticky binding is neither looked up nor recorded. `title` is only a display field, so adding a title to an otherwise unchanged call can turn a sticky scheduler into one sandbox per call. A declarative trigger issues a bare `scheduler.agent(<prompt>)` call, with `{ sandboxPolicy: … }` added only when the trigger declares one, so it stays on the sticky path.

`concurrency_policy` applies to the whole agent scheduler, including all declarative or script-registered triggers and manual scheduler invocations. With `skip`, a run that overlaps another run from the same scheduler is recorded as `skipped` and is not queued. With `parallel`, overlapping runs may execute concurrently. It is not a per-trigger policy.

Script schedulers can run host calls in parallel with `scheduler.llm.async` and `scheduler.agent.async`. Two scheduler env values cap how many run at once:
Expand Down
9 changes: 7 additions & 2 deletions docs/pages/command-line-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,12 @@ not authenticate the sender: any client that can reach the endpoint can forge
a GitHub event. Use it only behind a trusted reverse proxy or network access
control. If a source token is configured, the token is still required, so a
proxy can authenticate the request and inject it. A tokenless unsigned source
cannot share its webhook URL with another enabled source because it would make
source selection ambiguous.
must not share its webhook URL with another enabled source, because two such
sources make source selection ambiguous. The daemon accepts the second
`PUT /api/webhook-sources/<source-id>` without warning and stores both sources;
the ambiguity is reported when a delivery arrives, as
`409 {"error":"unsigned webhook source is ambiguous"}`. Keep at most one enabled
tokenless unsigned source per webhook URL.

Because signature secrets are write-only, omitting or sending an empty
`signature_secret` while updating an existing source preserves its current
Expand Down Expand Up @@ -362,6 +366,7 @@ Notes:
- `down` only affects the selected project.
- When using `-f` or `--project-name`, verify that the command targets the intended project.
- If some sandboxes cannot be stopped, the command exits non-zero, reports the failed items, and leaves the project active so `down` can be retried.
- `down` cancels scheduler runs that are still in flight. A cancelled run is recorded as `failed` with `context canceled` (plus `docker runtime could not confirm termination of guest execution` when the guest stop cannot be confirmed), and its `sandboxids` list is empty even when the run had already started a sandbox. Wait until the scheduler is idle — `scheduler runs` showing no `running` row — before calling `down` when run history matters.

## `run`: Run a Sandbox

Expand Down
14 changes: 14 additions & 0 deletions docs/pages/zh-CN/agent-compose-yaml-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,8 @@ driver:
| `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`,不可使用。 |

`boxlite` 与 `microsandbox` 会启动一个真正的内核,拥有自己的用户态网络栈与 DNS,**不加入 Docker 网络**。因此这类 sandbox 既**不解析 Docker Compose 服务名**,也**访问不到只发布在宿主回环上的 daemon**。在这两个驱动上,`AGENT_COMPOSE_RUNTIME_BASE_URL`(或驱动专用覆盖项)必须填写 **sandbox 自己能访问到**的地址——例如 KVM 部署里宿主网桥的地址——并且 daemon 要真的发布在该地址上。否则即使 daemon 健康,runtime LLM facade 与前置代理在 sandbox 内依然不可达,第一次 `run --prompt` 会以 `error sending request for url (http://<compose 服务名>:<port>/api/runtime/…)` 失败。

k8s driver 通过 kubeconfig 构建 client:设置了显式的 `K8S_KUBECONFIG`/`KUBECONFIG`
路径时使用该路径,否则使用 `~/.kube/config` 的加载规则;只有两者都解析不到配置时才回退到
集群内配置。Sandbox Pod 通过 `K8S_RUNTIME_BASE_URL`(会覆盖
Expand Down Expand Up @@ -938,6 +940,16 @@ capset_ids:

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

`SKILL.md` 必须以 YAML frontmatter 开头:第一行是 `---` 围栏,frontmatter 在下一个 `---` 行结束,其中的 `name` 与 `description` **都必须非空**,且 frontmatter 里的 `name` 必须与配置中该 Skill 的名字完全一致。项目校验只检查 Skill 名规则;下面是内容规则,**都在 sandbox 启动时才报错**:

| 情况 | 报错 | 出现时机 |
| --- | --- | --- |
| 没有 frontmatter | `skill <name> invalid SKILL.md: frontmatter is required` | sandbox 启动 |
| 缺 `name` 或缺 `description` | `skill <name> SKILL.md requires name and description` | sandbox 启动 |
| frontmatter 的 `name` 与配置不一致 | `skill name mismatch: configured "<配置值>", SKILL.md "<声明值>"` | sandbox 启动 |

也就是说,违反上述规则的 `SKILL.md` 能通过 `config`/`config --quiet`,直到第一次 `run` 才失败。

`provider` 为 `dsh` 的 Agent 只接受更窄的 Skill 名:`^[a-z0-9]+(?:-[a-z0-9]+)*$`,即小写字母和数字,中间用单个连字符连接。DSH 会静默丢弃不符合该规则的 Skill,因此这类名字在项目校验时即被拒绝。Skill 的 `SKILL.md` 中的 `name` 必须是同一个值。

交互式会话使用的是沙箱最近一次准备时发布进去的 Skill。附着到一个已在运行的沙箱时,此后新增、删除或修改的 Skill 不会生效;要等沙箱再次准备(例如启动新的沙箱)后才生效。
Expand Down Expand Up @@ -1198,6 +1210,8 @@ Scheduler 可以使用声明式 `triggers`,也可以使用 JavaScript `script`

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

`sandbox_policy` 决定的是 Scheduler 生成的 Agent 调用所用 sandbox,声明式 Trigger 与脚本式 Scheduler 都适用。有一种情况会**静默退回 `new`**:调用只要带上**调用级选项**——`title`、`driver`、`guestImage`、`workspaceId`、`env` 或 `volumes`——就会使用一次独立的新会话 sandbox,`sticky` 要复用的绑定既不查也不写。由于 `title` 只是展示字段,给一个本来没变的调用加上标题,就可能把 sticky 变成「每次调用一个新 sandbox」。声明式 Trigger 发出的是裸 `scheduler.agent(<prompt>)` 调用,仅在 Trigger 自己声明了策略时才追加 `{ sandboxPolicy: … }`,因此始终走 sticky 路径。

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

脚本型 scheduler 可以用 `scheduler.llm.async` 和 `scheduler.agent.async` 并行发起 host 调用。两个 scheduler env 用于限制同时进行的数量:
Expand Down
9 changes: 7 additions & 2 deletions docs/pages/zh-CN/command-line-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,12 @@ GitHub 也允许 webhook 的 Secret 留空。若要直接接收这类无签名
token 留空。未配置 signature secret 时,daemon 会跳过签名校验。该模式不会认证
发送者:任何能够访问此 endpoint 的客户端都可以伪造 GitHub 事件,因此只能在受信任
的反向代理或网络访问控制之后使用。若 source 配置了 token,daemon 仍会要求该
token,便于代理完成认证后注入。无 token 的 unsigned source 不能与另一个启用的
source 共用 webhook URL,否则无法唯一选择 source。
token,便于代理完成认证后注入。无 token 的 unsigned source **不得**与另一个启用的
source 共用同一个 webhook URL,因为两个这样的 source 会让选择变得不唯一。daemon 接受
第二个 `PUT /api/webhook-sources/<source-id>` 时**不会有任何预警**,两个 source 都会
被存下来;直到真正投递时才以
`409 {"error":"unsigned webhook source is ambiguous"}` 报出歧义。请把每个 webhook URL
上的「启用且无签名无 token」的 source 控制在一个以内。

由于 signature secret 是 write-only,更新已有 source 时省略
`signature_secret` 或传入空值会保留当前 secret。若要将已有的 signed source 切换为
Expand Down Expand Up @@ -330,6 +334,7 @@ agent-compose -f /path/to/project/agent-compose.yml down
- `down` 只影响当前 project。
- 使用 `-f` 或 `--project-name` 时,应确认定位到的是预期 project。
- 如果部分 sandbox 停止失败,命令返回非零退出码并说明失败项,同时保持 project 为 active,以便再次执行 `down`。
- `down` 会取消仍在飞行的 scheduler run。被取消的 run 记为 `failed`,错误为 `context canceled`(若无法确认 guest 已停止,还会带上 `docker runtime could not confirm termination of guest execution`),且它的 `sandboxids` 是**空**的,即使该 run 已经起过 sandbox。关心 run 历史时,请先等 scheduler 空闲(`scheduler runs` 里没有 `running` 行)再执行 `down`。

## `run`:运行 sandbox

Expand Down
Loading