docs: update Chats API and platform controls docs to match current state (#23803)

The Chats API docs and platform controls docs had fallen behind the
implementation. This brings them up to date.

## Chats API docs (`chats-api.md`)

### Breaking: archive/unarchive endpoints removed

The old `POST /{chat}/archive` and `POST /{chat}/unarchive` endpoints no
longer exist. Replaced with the `PATCH /{chat}` update endpoint
(`{"archived": true/false}`).

### Chat object updated

Added all new fields to the example response and a new reference table:
- `build_id`, `agent_id` — workspace agent binding
- `parent_chat_id`, `root_chat_id` — delegated/child chat lineage
- `pin_order` — pinned chats
- `labels` — general-purpose key-value labels
- `mcp_server_ids` — MCP server bindings
- `has_unread` — read/unread tracking
- `diff_status` — PR/diff metadata

### New endpoints documented

- `PATCH /{chat}` — update chat (title, archived, pin_order, labels)
- `PATCH /{chat}/messages/{message}` — edit a user message
- `GET /watch` — watch all chats via WebSocket
- `POST /{chat}/title/regenerate` — regenerate title
- `GET /{chat}/diff` — get diff/PR status
- `DELETE /{chat}/queue/{id}` / `POST /{chat}/queue/{id}/promote` —
queue management

### Updated existing endpoint docs

- Create chat: added `mcp_server_ids` and `labels` fields
- Send message: added `mcp_server_ids` field
- List chats: added `q` and `label` query parameters
- Stream: noted read cursor behavior on connect/disconnect

## Platform controls docs

### Template allowlist (`platform-controls/index.md`)

- Updated the "Template routing" section to document the template
allowlist setting (**Agents** > **Settings** > **Templates**)
- Removed the "Template scoping for agents" bullet from "Where we are
headed" since it shipped

### Template optimization (`template-optimization.md`)

- Added "Restrict available templates" section documenting the allowlist
UI, behavior, and scope (agents only, not manual workspace creation)

---

*PR generated with Coder Agents*
This commit is contained in:
Matt Vollmer
2026-03-30 10:28:15 -04:00
committed by GitHub
parent 0fb3e5cba5
commit 8e57498a87
3 changed files with 146 additions and 28 deletions
+108 -20
View File
@@ -39,13 +39,22 @@ The response is the newly created `Chat` object:
"id": "a1b2c3d4-...",
"owner_id": "...",
"workspace_id": null,
"build_id": null,
"agent_id": null,
"parent_chat_id": null,
"root_chat_id": null,
"last_model_config_id": "...",
"title": "hello world",
"status": "waiting",
"last_error": null,
"diff_status": null,
"created_at": "2025-07-17T00:00:00Z",
"updated_at": "2025-07-17T00:00:00Z",
"archived": false
"archived": false,
"pin_order": 0,
"mcp_server_ids": [],
"labels": {},
"has_unread": false
}
```
@@ -70,11 +79,13 @@ A typical integration follows three steps:
`POST /api/experimental/chats`
| Field | Type | Required | Description |
|-------------------|-------------------|----------|-------------------------------------------------|
| `content` | `ChatInputPart[]` | yes | The user's prompt as one or more content parts. |
| `workspace_id` | `uuid` | no | Pin the chat to a specific workspace. |
| `model_config_id` | `uuid` | no | Override the default model configuration. |
| Field | Type | Required | Description |
|-------------------|---------------------|----------|-------------------------------------------------|
| `content` | `ChatInputPart[]` | yes | The user's prompt as one or more content parts. |
| `workspace_id` | `uuid` | no | Pin the chat to a specific workspace. |
| `model_config_id` | `uuid` | no | Override the default model configuration. |
| `mcp_server_ids` | `uuid[]` | no | Attach MCP servers to this chat. |
| `labels` | `map[string]string` | no | Key-value labels for the chat (max 50). |
Each `ChatInputPart` has a `type` field. The simplest form is a text part:
@@ -92,10 +103,11 @@ range).
`POST /api/experimental/chats/{chat}/messages`
| Field | Type | Required | Description |
|-------------------|-------------------|----------|-----------------------------------|
| `content` | `ChatInputPart[]` | yes | The follow-up message content. |
| `model_config_id` | `uuid` | no | Override the model for this turn. |
| Field | Type | Required | Description |
|-------------------|-------------------|----------|-------------------------------------|
| `content` | `ChatInputPart[]` | yes | The follow-up message content. |
| `model_config_id` | `uuid` | no | Override the model for this turn. |
| `mcp_server_ids` | `uuid[]` | no | Override MCP servers for this turn. |
If the agent is currently processing, the message is queued automatically.
The response indicates whether the message was delivered immediately or
@@ -111,6 +123,17 @@ queued:
When `queued` is `true`, `message` is absent and `queued_message` is
returned instead.
### Edit a message
`PATCH /api/experimental/chats/{chat}/messages/{message}`
Edits a previously sent user message. The agent re-processes from the
edited message onward, truncating any messages that followed it.
| Field | Type | Required | Description |
|-----------|-------------------|----------|----------------------------------|
| `content` | `ChatInputPart[]` | yes | The replacement message content. |
### Stream updates
`GET /api/experimental/chats/{chat}/stream`
@@ -141,6 +164,10 @@ connect the server sends an initial snapshot of the chat state before
switching to live events. Use `after_id` when reconnecting to skip
messages the client already has.
Connecting to the stream also updates the caller's read cursor for
unread tracking. On disconnect the cursor is advanced to the latest
message.
Event types inside each batch:
| Type | Description |
@@ -152,12 +179,35 @@ Event types inside each batch:
| `retry` | The server is retrying a failed LLM call (includes backoff). |
| `queue_update` | The queued message list changed. |
### Watch all chats
`GET /api/experimental/chats/watch`
Opens a **one-way WebSocket** that pushes events for all chats owned by
the authenticated user. Use this to drive a sidebar or notification
indicator without polling.
Each event is a JSON object with `kind` and `chat` fields:
| Kind | Description |
|----------------------|----------------------------------|
| `created` | A new chat was created. |
| `status_change` | A chat's status changed. |
| `title_change` | A chat's title was updated. |
| `diff_status_change` | A chat's diff/PR status changed. |
| `deleted` | A chat was deleted. |
### List chats
`GET /api/experimental/chats`
Returns all chats owned by the authenticated user.
| Query parameter | Type | Required | Description |
|-----------------|----------|----------|------------------------------------------------------------------|
| `q` | `string` | no | Search query string. |
| `label` | `string` | no | Filter by label as `key:value`. Repeat for multiple (AND logic). |
### Get a chat
`GET /api/experimental/chats/{chat}`
@@ -177,12 +227,28 @@ Returns the messages and queued messages for a chat.
Returns available models. Use this to discover valid values for
`model_config_id`.
### Archive / unarchive
### Update a chat
`POST /api/experimental/chats/{chat}/archive`
`POST /api/experimental/chats/{chat}/unarchive`
`PATCH /api/experimental/chats/{chat}`
Archive hides a chat from the default list without deleting it.
Updates chat metadata. All fields are optional; omitted fields are left
unchanged.
| Field | Type | Description |
|-------------|---------------------|-------------------------------------------------------------------------------------|
| `title` | `string` | Set a new title. |
| `archived` | `bool` | `true` to archive, `false` to unarchive. Archiving clears `pin_order`. |
| `pin_order` | `int32` | `0` to unpin; `>0` on an unpinned chat to pin it; `>0` on a pinned chat to reorder. |
| `labels` | `map[string]string` | Replace all labels. Use `null`/omit to leave unchanged, `{}` to clear. |
**Response**: `204 No Content`.
### Regenerate title
`POST /api/experimental/chats/{chat}/title/regenerate`
Regenerates the chat title using conversation context. Returns the
updated `Chat` object.
### Interrupt
@@ -191,6 +257,26 @@ Archive hides a chat from the default list without deleting it.
Stops the agent's current processing loop and returns the chat to
`waiting` status.
### Manage queued messages
When a message is queued because the agent is busy, you can manage the
queue:
`DELETE /api/experimental/chats/{chat}/queue/{queuedMessage}`
Removes a queued message before it is processed.
`POST /api/experimental/chats/{chat}/queue/{queuedMessage}/promote`
Promotes a queued message to be processed next.
### Get diff contents
`GET /api/experimental/chats/{chat}/diff`
Returns the current diff/PR status for a chat, including additions,
deletions, changed files, and pull request metadata when available.
## File uploads
Attach images to a chat by uploading them first:
@@ -211,9 +297,11 @@ validates actual file content regardless of the declared `Content-Type`.
## Chat statuses
| Status | Meaning |
|-----------|--------------------------------------------------------------|
| `waiting` | Idle — newly created, finished successfully, or interrupted. |
| `pending` | Queued for processing. |
| `running` | Agent is actively working. |
| `error` | Agent encountered an error. |
| Status | Meaning |
|-------------|--------------------------------------------------------------|
| `waiting` | Idle — newly created, finished successfully, or interrupted. |
| `pending` | Queued for processing. |
| `running` | Agent is actively working. |
| `paused` | Agent is paused (e.g. waiting for user input). |
| `completed` | Agent finished and the task is complete. |
| `error` | Agent encountered an error. |
@@ -61,9 +61,18 @@ Python backend services in the payments repo" — platform teams can guide the
agent toward the correct infrastructure without requiring developers to
understand template selection at all.
Administrators can also restrict which templates are available to agents using
the template allowlist in **Agents** > **Settings** > **Templates**. When the
allowlist is configured, the agent can only see and provision workspaces from
the selected templates. When the allowlist is empty, all templates are
available. This is separate from what developers see when manually creating
workspaces, so you can apply stricter policies to agent-created workspaces
without affecting the manual workspace experience.
See [Template Optimization](./template-optimization.md) for best practices on writing
discoverable descriptions, configuring network boundaries, scoping credentials,
and designing template parameters for agent use.
discoverable descriptions, restricting template visibility, configuring network
boundaries, scoping credentials, and designing template parameters for agent
use.
## Where we are headed
@@ -97,11 +106,6 @@ Examples of what this looks like:
from the control plane, agent workspaces do not need outbound access to LLM
providers. You can create templates that only permit access to your git
provider and nothing else.
- **Template scoping for agents.** We intend to let administrators restrict
which templates are available in the agentic interface, separate from what
developers see when manually creating workspaces. This lets you apply stricter
policies to agent-created workspaces without affecting the developer
experience for manually-created ones.
### Tool customization
@@ -6,11 +6,37 @@ execute builds.
When a workspace is needed, the agent reads the available templates, selects
the appropriate one based on its name and description, and provisions a
workspace automatically.
workspace automatically. Administrators can restrict which templates the agent
can see using the [template allowlist](#restrict-available-templates).
This guide covers best practices for creating templates that are discoverable
and useful to Coder Agents.
## Restrict available templates
By default, the agent can see and provision any template in the deployment.
Administrators can restrict this to a specific set of templates using the
template allowlist.
To configure the allowlist:
1. Navigate to **Agents** > **Settings** > **Templates**.
2. Select the templates you want agents to be able to use.
3. Click **Save**.
When the allowlist is configured, the agent's `list_templates`,
`read_template`, and `create_workspace` tools are filtered to only include
the selected templates. The agent cannot see or provision templates that are
not on the list.
When no templates are selected, the allowlist is inactive and all templates
are available to agents.
The allowlist only affects agent-created workspaces. Developers can still
manually create workspaces from any template they have access to. This lets
platform teams apply stricter policies to agent workloads without affecting
the manual workspace experience.
## Write discoverable template descriptions
The agent selects templates by reading their names and descriptions — the same