Skip to content

Commit cea2090

Browse files
committed
Default the Agents API to the first runtime and enable each route.
A request that does not name an adapter uses codex. Name qwen-code to use the other one. Agents endpoints are in the catalogue with scope agents:use. The cloud examples use the base template and python -m playwright.
1 parent fda7645 commit cea2090

23 files changed

Lines changed: 482 additions & 223 deletions

‎docs/en/guide/agents-api.md‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Field-by-field refusals are in [Hosted agents](hosted-agents.md). This page is t
88

99
## Install a CLI
1010

11-
Neither CLI is installed by default. Installing both into the base image makes the image large.
11+
Install one CLI. Installing both into the base image makes the image large. When the request does not name an adapter, the server uses the first in the product order: `codex`. Name Qwen Code in the request, or set `EBX_AGENTS_DEFAULT=qwen-code`, to use the other one.
1212

1313
```bash
1414
npm install -g @openai/codex # binary name: codex
@@ -38,12 +38,23 @@ python examples/agents/complete_case.py
3838

3939
The shapes below are what the server returns. The server assigns the session id.
4040

41-
A model id such as `gpt-5` does not select a CLI:
41+
When the request does not name an adapter, the server uses the first in the product order (`codex`). A model id such as `gpt-5` is passed to that CLI. It does not switch the adapter:
4242

4343
```text
44-
POST /v1/agents/sessions 400
44+
POST /v1/agents/sessions {"agent":{"model":"gpt-5"}} 200
45+
agent.id: codex
46+
agent.model: gpt-5
4547
X-Easy-Sandbox-Local: 1
46-
code: agents.adapter_required
48+
```
49+
50+
`GET /v1/agents/runtimes` uses the same paging as the other lists, so the default `order` is `desc`. Pass `order=asc` to see the product order `codex`, then `qwen-code`. `default: true` marks the runtime used when the request does not name one. The flag does not follow the array index. With no config it is on `codex`. After `EBX_AGENTS_DEFAULT=qwen-code` it moves to `qwen-code`.
51+
52+
Name the other one:
53+
54+
```text
55+
POST /v1/agents/sessions {"adapter":"qwen-code","agent":{"model":"gpt-5"}} 200
56+
agent.id: qwen-code
57+
agent.model: gpt-5
4758
```
4859

4960
An adapter name that is not supported today, for example `claude-code`:

‎docs/en/guide/best-practices.md‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,51 @@ The Agents routes stay off until the process is started with `EBX_SERVER_ENABLED
2828

2929
Codex and Qwen Code are supported today. Checklist, the local header, and the 404s: [Hosted agents — Best practices](hosted-agents.md#best-practices).
3030

31+
## One agent by default
32+
33+
Install only the CLI you are going to call. Installing both Codex and Qwen Code makes the image large.
34+
35+
The server's order is `codex`, then `qwen-code`. A request that does not name an adapter uses the first. `GET /v1/agents/runtimes?order=asc` returns them in that order. The list's default `order` is `desc`. `default: true` marks the one in effect. It does not follow the array index.
36+
37+
```bash
38+
npm install -g @openai/codex
39+
```
40+
41+
To use Qwen Code, send `adapter`, `runtime`, or the `X-EBX-Adapter` header, or set `model` to `qwen-code` (aliases `qwen` and `qwencode`). A model id such as `gpt-5` is passed to the selected CLI. It does not switch the adapter.
42+
43+
Move the default off the first entry:
44+
45+
```bash
46+
export EBX_AGENTS_DEFAULT=qwen-code
47+
```
48+
49+
A JSON file named by `EBX_AGENTS_CONFIG` does the same with a top-level `default` or `agents.default`. `claude-code`, Cursor, and Qoder stay 404.
50+
51+
## Open Agents routes one endpoint at a time
52+
53+
`groups.agents: true` is only the gate for this group. Each Agents route has its own endpoint id, the same way `upload` and `shell` do. The default scope is `agents:use`. This opens session create and nothing else:
54+
55+
```python
56+
from easy_sandbox.server import SandboxServer, ServerPolicy, default_table
57+
58+
policy = ServerPolicy.only("agents_sessions_create").with_options(groups={"agents": True})
59+
server = SandboxServer(route_table=default_table(), policy=policy)
60+
```
61+
62+
The same policy in YAML:
63+
64+
```yaml
65+
groups:
66+
agents: true
67+
endpoints:
68+
"*":
69+
enabled: false
70+
agents_sessions_create:
71+
enabled: true
72+
```
73+
74+
These endpoints do not accept `paths` or specialised `params`. A policy that sets either fails to load. The full endpoint id list is in [Fine-grained capabilities](fine-grained-capabilities.md).
75+
3176
## Secrets are not echoed
3277

3378
`GET /env` omits a variable whose name contains `TOKEN`, `SECRET`, `KEY`, `PASSWORD`, or `CREDENTIAL`. When a policy is loaded it also omits `EBX_SERVER_TOKEN`, `EBX_SERVER_POLICY`, `EBX_SERVER_POLICY_FILE`, every `token_env` name, and every name that starts with `EBX_SERVER_`.

‎docs/en/guide/fine-grained-capabilities.md‎

Lines changed: 72 additions & 72 deletions
Large diffs are not rendered by default.

‎docs/en/guide/hosted-agents.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ The template server listens on **port 9000**. Point an OpenAI-shaped client at `
1818
* Codex and Qwen Code are supported today. A body that names an adapter that is not supported yet is HTTP 404 `not_found_error` with `x-should-retry: false`.
1919
* Treat every response as local. Read the header `X-Easy-Sandbox-Local: 1` (errors included). `x_easy_sandbox.compute` is `local_process`, `local_state`, or `none`.
2020
* Do not call `POST /v1/responses/input_tokens`. It is 404 `agents.not_implemented_locally` with `x-should-retry: false`. No tokenizer matches the model the CLI will call.
21+
* Install one CLI in the image. A request that does not name an adapter uses the first in the product order (`codex`). Name `adapter`, `runtime`, or `X-EBX-Adapter`, or set `EBX_AGENTS_DEFAULT`, to use another.
22+
* Open endpoints one id at a time. `groups.agents: true` is only the gate. Each route's default scope is `agents:use`. See [Fine-grained capabilities](fine-grained-capabilities.md).
2123
* Leave the group off until a session needs it. Start the process with `EBX_SERVER_ENABLED_GROUPS=agents`.
2224
* Keep model API keys out of the HTTP client. The server token, when set, is the only credential these examples send.
2325

@@ -62,8 +64,9 @@ Selection order:
6264
1. `X-EBX-Adapter` header, or a body field `adapter` / `runtime` (top-level or under `agent`)
6365
2. `agent.model` or `model` when that string is one of the names above (a real model id such as `gpt-5-codex` is passed through to the CLI and does not choose an adapter)
6466
3. Config `agents.default`: the `EBX_AGENTS_DEFAULT` environment variable, or in `EBX_AGENTS_CONFIG` a JSON string at `default` or `agents.default`
67+
4. Otherwise the first runtime in the product order: `codex`, then `qwen-code`
6568

66-
If none of those names an adapter, the response is **400** `agents.adapter_required`.
69+
`GET /v1/agents/runtimes` defaults to `order=desc`. `order=asc` is the product order above. `default: true` marks the runtime step 4 selected. It does not follow the array index. A real model id (`gpt-5`) is passed to that CLI and does not change the adapter. Name the other runtime in the request to use it.
6770

6871
## Sessions, events, items, turns
6972

@@ -97,7 +100,7 @@ curl -s -D - -o /dev/null -X POST \
97100

98101
`GET .../items`, `GET .../turns`, `GET .../turns/{turn_id}`, and `GET .../turns/{turn_id}/items` return the list envelope `{object, data, first_id, last_id, has_more}`. `limit` is 1–100 (default 20) and `order` is `asc` or `desc` (default `desc`).
99102

100-
`GET /v1/agents/runtimes` lists **codex** and **qwen-code** only, including whether each binary is on `PATH`.
103+
`GET /v1/agents/runtimes` lists **codex** and **qwen-code** only, including whether each binary is on `PATH`. Each object has `default`. That flag is true for the runtime used when the request does not name one. `order=asc` is `codex`, then `qwen-code`. The default `order` is `desc`.
101104

102105
## Agent definitions
103106

‎docs/en/guide/template-server-api.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ All of these need Playwright. If `import playwright` fails the handler returns `
569569

570570
### `agents` (off until enabled)
571571

572-
Turn the group on with `EBX_SERVER_ENABLED_GROUPS=agents` (or `default_table().enable_group(CapabilityGroup.AGENTS)` before `serve()`). This slice hosts the Codex CLI (`codex`) and Qwen Code (`qwen-code`, also `qwen` and `qwencode`). Any other adapter name is `404` `not_found_error` with `x-should-retry: false`. If the body and `agents.default` (`EBX_AGENTS_DEFAULT`) name neither adapter, create calls are `400` `agents.adapter_required`.
572+
Turn the group on with `EBX_SERVER_ENABLED_GROUPS=agents` (or `default_table().enable_group(CapabilityGroup.AGENTS)` before `serve()`). Codex CLI (`codex`) and Qwen Code (`qwen-code`, also `qwen` and `qwencode`) are supported today. An adapter name that is not supported yet is `404` `not_found_error` with `x-should-retry: false`. When the body and `agents.default` (`EBX_AGENTS_DEFAULT`) do not name an adapter, create calls use the first in the product order: `codex`. Each Agents route can be enabled on its own. Endpoint ids are in [Fine-grained capabilities](fine-grained-capabilities.md). The default scope is `agents:use`.
573573

574574
Every route here is a local operation. Every response carries `X-Easy-Sandbox-Local: 1` and every object an `x_easy_sandbox` label (`local`, `compute`, `differences`). A field the server cannot honor is `400` with `param`, never accepted and ignored. Objects belong to the caller; a foreign id answers like an unknown id.
575575

@@ -597,7 +597,7 @@ Every route here is a local operation. Every response carries `X-Easy-Sandbox-Lo
597597

598598
No local capability, `404` `not_found_error` (`agents.not_implemented_locally`, `x-should-retry: false`): `POST /v1/responses/input_tokens`, `DELETE /v1/models/{id}`, and executor registration and channel.
599599

600-
The CLIs are not installed until a session uses them. See [Hosted agents](hosted-agents.md) for every refusal, environment variable and difference code. Best practices (Codex and Qwen only, the local header, 404 for Claude, Cursor, and Qoder, and 404 for `input_tokens`) are in [Hosted agents — Best practices](hosted-agents.md#best-practices).
600+
The CLIs are not installed until a session uses them. See [Hosted agents](hosted-agents.md) for every refusal, environment variable and difference code. Supported adapters, the local header, and the 404s for names that are not supported yet and for `input_tokens` are in [Hosted agents — Best practices](hosted-agents.md#best-practices).
601601

602602
---
603603

‎docs/zh/guide/agents-api.md‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
## 安装 CLI
1010

11-
默认不装。两个都装进基础镜像会把镜像做大。
11+
默认只装一个。两个都装进基础镜像会把镜像做大。没在请求里点名时,服务端用产品顺序里的第一个:`codex`。要用 Qwen Code,在请求里写出来,或用 `EBX_AGENTS_DEFAULT=qwen-code` 把默认换成它。
1212

1313
```bash
1414
npm install -g @openai/codex # 二进制名 codex
@@ -38,12 +38,23 @@ python examples/agents/complete_case.py
3838

3939
下面是响应形状。会话 id 由服务端生成。
4040

41-
未给出适配器名,模型 id `gpt-5` 不会用来选 CLI:
41+
未给出适配器名时,用顺序里的第一个(`codex`)。模型 id `gpt-5` 传给这个 CLI,不用来换适配器:
4242

4343
```text
44-
POST /v1/agents/sessions 400
44+
POST /v1/agents/sessions {"agent":{"model":"gpt-5"}} 200
45+
agent.id: codex
46+
agent.model: gpt-5
4547
X-Easy-Sandbox-Local: 1
46-
code: agents.adapter_required
48+
```
49+
50+
`GET /v1/agents/runtimes` 和其他列表一样,默认 `order=desc`。加上 `order=asc` 才是产品顺序 `codex`、`qwen-code`。`default: true` 标出没点名时会用的那一个,不看它在数组里的位置。没有配置时标在 `codex` 上。`EBX_AGENTS_DEFAULT=qwen-code` 之后改到 `qwen-code`。
51+
52+
要点名另一个:
53+
54+
```text
55+
POST /v1/agents/sessions {"adapter":"qwen-code","agent":{"model":"gpt-5"}} 200
56+
agent.id: qwen-code
57+
agent.model: gpt-5
4758
```
4859

4960
目前未支持的适配器名称,例如 `claude-code`:

‎docs/zh/guide/best-practices.md‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,51 @@ Agents 路由保持关闭,直到进程以 `EBX_SERVER_ENABLED_GROUPS=agents`
2828

2929
目前支持 Codex 和 Qwen Code。检查清单、本地响应头和 404 见[托管代理 — 最佳实践](hosted-agents.md#最佳实践)。
3030

31+
## 默认一个 agent
32+
33+
镜像里只安装要调用的那一个 CLI。Codex 和 Qwen Code 都装进去会把镜像做大。
34+
35+
服务端的顺序是 `codex`,然后 `qwen-code`。请求没有点名适配器时,用第一个。`GET /v1/agents/runtimes?order=asc` 按这个顺序返回。列表默认的 `order` 是 `desc`。`default: true` 标出当前默认,不看数组下标。
36+
37+
```bash
38+
npm install -g @openai/codex
39+
```
40+
41+
要用 Qwen Code,在请求里写 `adapter`、`runtime` 或请求头 `X-EBX-Adapter`,或把 `model` 写成 `qwen-code`(别名 `qwen`、`qwencode`)。`gpt-5` 这种模型 id 会传给被选中的 CLI,不会用来换适配器。
42+
43+
把默认从第一个换成另一个:
44+
45+
```bash
46+
export EBX_AGENTS_DEFAULT=qwen-code
47+
```
48+
49+
`EBX_AGENTS_CONFIG` 指向的 JSON 里,顶层 `default` 或 `agents.default` 作用相同。`claude-code`、Cursor、Qoder 仍然是 404。
50+
51+
## 按接口打开 Agents 路由
52+
53+
`groups.agents: true` 只是这组路由的门。和 `upload`、`shell` 一样,每个 Agents 路由有自己的端点 id,默认 scope 是 `agents:use`。只打开创建会话:
54+
55+
```python
56+
from easy_sandbox.server import SandboxServer, ServerPolicy, default_table
57+
58+
policy = ServerPolicy.only("agents_sessions_create").with_options(groups={"agents": True})
59+
server = SandboxServer(route_table=default_table(), policy=policy)
60+
```
61+
62+
同一份策略写成 YAML:
63+
64+
```yaml
65+
groups:
66+
agents: true
67+
endpoints:
68+
"*":
69+
enabled: false
70+
agents_sessions_create:
71+
enabled: true
72+
```
73+
74+
这些端点不接受 `paths` 和专用 `params`。写上会在加载策略时失败。完整端点 id 见[细粒度能力](fine-grained-capabilities.md)。
75+
3176
## 密钥不会被回显
3277

3378
`GET /env` 会略过名称里含有 `TOKEN`、`SECRET`、`KEY`、`PASSWORD` 或 `CREDENTIAL` 的变量。加载了策略时,还会略过 `EBX_SERVER_TOKEN`、`EBX_SERVER_POLICY`、`EBX_SERVER_POLICY_FILE`、每一个 `token_env` 名称,以及每一个以 `EBX_SERVER_` 开头的名称。

0 commit comments

Comments
 (0)