Skip to content
Merged
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
64 changes: 62 additions & 2 deletions codex-rs/app-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
- [Skills](#skills)
- [Apps](#apps)
- [Auth endpoints](#auth-endpoints)
- [Adding an experimental field](#adding-an-experimental-field)
- [Experimental API Opt-in](#experimental-api-opt-in)

## Protocol

Expand Down Expand Up @@ -789,7 +789,67 @@ Field notes:
- `windowDurationMins` is the quota window length.
- `resetsAt` is a Unix timestamp (seconds) for the next reset.

## Adding an experimental field
## Experimental API Opt-in

Some app-server methods and fields are intentionally gated behind an experimental capability with no backwards-compatible guarantees. This lets clients choose between:

- Stable surface only (default): no opt-in, no experimental methods/fields exposed.
- Experimental surface: opt in during `initialize`.

### Generating stable vs experimental client schemas

`codex app-server` schema generation defaults to the stable API surface (experimental fields and methods filtered out). Pass `--experimental` to include experimental methods/fields in generated TypeScript or JSON schema:

```bash
# Stable-only output (default)
codex app-server generate-ts --out DIR
codex app-server generate-json-schema --out DIR

# Include experimental API surface
codex app-server generate-ts --out DIR --experimental
codex app-server generate-json-schema --out DIR --experimental
```

### How clients opt in at runtime

Set `capabilities.experimentalApi` to `true` in your single `initialize` request:

```json
{
"method": "initialize",
"id": 1,
"params": {
"clientInfo": {
"name": "my_client",
"title": "My Client",
"version": "0.1.0"
},
"capabilities": {
"experimentalApi": true
}
}
}
```

Then send the standard `initialized` notification and proceed normally.

Notes:

- If `capabilities` is omitted, `experimentalApi` is treated as `false`.
- This setting is negotiated once at initialization time for the process lifetime (re-initializing is rejected with `"Already initialized"`).

### What happens without opt-in

If a request uses an experimental method or sets an experimental field without opting in, app-server rejects it with a JSON-RPC error. The message is:

`<descriptor> requires experimentalApi capability`

Examples of descriptor strings:

- `mock/experimentalMethod` (method-level gate)
- `thread/start.mockExperimentalField` (field-level gate)

### For maintainers: Adding experimental fields and methods
Use this checklist when introducing a field/method that should only be available when the client opts into experimental APIs.

At runtime, clients must send `initialize` with `capabilities.experimentalApi = true` to use experimental methods or fields.
Expand Down
Loading