Skip to content

Commit 9b2edc2

Browse files
authored
Stabilize Slash Commands API (#88)
* Checkpoint: Stabilizing commands * Improve docs
1 parent 1950096 commit 9b2edc2

9 files changed

Lines changed: 132 additions & 16 deletions

File tree

docs/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"protocol/terminals",
6060
"protocol/agent-plan",
6161
"protocol/session-modes",
62+
"protocol/slash-commands",
6263
"protocol/extensibility",
6364
"protocol/schema"
6465
]

docs/protocol/overview.mdx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ Agents are programs that use generative AI to autonomously modify code. They typ
8484
`loadSession` capability).
8585
</ResponseField>
8686

87+
<ResponseField
88+
name="session/set_mode"
89+
post={[<a href="./schema#session%2Fset-mode">Schema</a>]}
90+
>
91+
[Switch between agent operating
92+
modes](./session-modes#setting-the-current-mode).
93+
</ResponseField>
94+
8795
### Notifications
8896

8997
<ResponseField
@@ -167,8 +175,12 @@ Clients provide the interface between users and agents. They are typically code
167175
name="session/update"
168176
post={[<a href="./schema#session%2Fupdate">Schema</a>]}
169177
>
170-
[Send progress updates](./prompt-turn#3-agent-reports-output) during prompt
171-
processing (no response expected).
178+
[Send session updates](./prompt-turn#3-agent-reports-output) to inform the
179+
Client of changes (no response expected). This includes: - [Message
180+
chunks](./content) (agent, user, thought) - [Tool calls and
181+
updates](./tool-calls) - [Plans](./agent-plan) - [Available commands
182+
updates](./slash-commands#advertising-commands) - [Mode
183+
changes](./session-modes#from-the-agent)
172184
</ResponseField>
173185

174186
## Argument requirements

docs/protocol/schema.mdx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,8 @@ Information about a command.
10981098

10991099
## <span class="font-mono">AvailableCommandInput</span>
11001100

1101+
The input specification for a command.
1102+
11011103
**Type:** Union
11021104

11031105
<ResponseField name="Object">
@@ -1106,7 +1108,7 @@ All text that was typed after the command name is provided as input.
11061108
<Expandable title="Properties">
11071109

11081110
<ResponseField name="hint" type={"string"} required>
1109-
A brief description of the expected input
1111+
A hint to display when the input hasn't been provided yet
11101112
</ResponseField>
11111113

11121114
</Expandable>
@@ -2225,6 +2227,8 @@ Available commands are ready or have changed
22252227
<ResponseField name="current_mode_update">
22262228
The current mode of the session has changed
22272229

2230+
See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
2231+
22282232
<Expandable title="Properties">
22292233

22302234
<ResponseField

docs/protocol/slash-commands.mdx

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
---
2+
title: "Slash Commands"
3+
description: "Advertise available slash commands to clients"
4+
---
5+
6+
Agents can advertise a set of slash commands that users can invoke. These commands provide quick access to specific agent capabilities and workflows. Commands are run as part of regular [prompt](./prompt-turn) requests where the Client includes the command text in the prompt.
7+
8+
## Advertising commands
9+
10+
After creating a session, the Agent **MAY** send a list of available commands via the `available_commands_update` session notification:
11+
12+
```json
13+
{
14+
"jsonrpc": "2.0",
15+
"method": "session/update",
16+
"params": {
17+
"sessionId": "sess_abc123def456",
18+
"update": {
19+
"sessionUpdate": "available_commands_update",
20+
"availableCommands": [
21+
{
22+
"name": "web",
23+
"description": "Search the web for information",
24+
"input": {
25+
"hint": "query to search for"
26+
}
27+
},
28+
{
29+
"name": "test",
30+
"description": "Run tests for the current project"
31+
},
32+
{
33+
"name": "plan",
34+
"description": "Create a detailed implementation plan",
35+
"input": {
36+
"hint": "description of what to plan"
37+
}
38+
}
39+
]
40+
}
41+
}
42+
}
43+
```
44+
45+
<ResponseField name="availableCommands" type="AvailableCommand[]">
46+
The list of commands available in this session
47+
</ResponseField>
48+
49+
### AvailableCommand
50+
51+
<ResponseField name="name" type="string" required>
52+
The command name (e.g., "web", "test", "plan")
53+
</ResponseField>
54+
55+
<ResponseField name="description" type="string" required>
56+
Human-readable description of what the command does
57+
</ResponseField>
58+
59+
<ResponseField name="input" type="AvailableCommandInput">
60+
Optional input specification for the command
61+
</ResponseField>
62+
63+
### AvailableCommandInput
64+
65+
Currently supports unstructured text input:
66+
67+
<ResponseField name="hint" type="string" required>
68+
A hint to display when the input hasn't been provided yet
69+
</ResponseField>
70+
71+
## Dynamic updates
72+
73+
The Agent can update the list of available commands at any time during a session by sending another `available_commands_update` notification. This allows commands to be added based on context, removed when no longer relevant, or modified with updated descriptions.
74+
75+
## Running commands
76+
77+
Commands are included as regular user messages in prompt requests:
78+
79+
```json
80+
{
81+
"jsonrpc": "2.0",
82+
"id": 3,
83+
"method": "session/prompt",
84+
"params": {
85+
"sessionId": "sess_abc123def456",
86+
"prompt": [
87+
{
88+
"type": "text",
89+
"text": "/web agent client protocol"
90+
}
91+
]
92+
}
93+
}
94+
```
95+
96+
The Agent recognizes the command prefix and processes it accordingly. Commands may be accompanied by any other user message content types (images, audio, etc.) in the same prompt array.

rust/client.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -214,22 +214,20 @@ pub enum SessionUpdate {
214214
/// See protocol docs: [Agent Plan](https://agentclientprotocol.com/protocol/agent-plan)
215215
Plan(Plan),
216216
/// Available commands are ready or have changed
217-
#[cfg(feature = "unstable")]
218217
#[serde(rename_all = "camelCase")]
219-
#[schemars(extend("x-docs-ignore" = true))]
220218
AvailableCommandsUpdate {
221219
available_commands: Vec<AvailableCommand>,
222220
},
223221
/// The current mode of the session has changed
222+
///
223+
/// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
224224
#[serde(rename_all = "camelCase")]
225-
// todo!
226225
CurrentModeUpdate { current_mode_id: SessionModeId },
227226
}
228227

229228
/// Information about a command.
230229
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
231230
#[serde(rename_all = "camelCase")]
232-
#[cfg(feature = "unstable")]
233231
pub struct AvailableCommand {
234232
/// Command name (e.g., "create_plan", "research_codebase").
235233
pub name: String,
@@ -242,14 +240,14 @@ pub struct AvailableCommand {
242240
pub meta: Option<serde_json::Value>,
243241
}
244242

243+
/// The input specification for a command.
245244
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
246245
#[serde(untagged, rename_all = "camelCase")]
247-
#[cfg(feature = "unstable")]
248246
pub enum AvailableCommandInput {
249247
/// All text that was typed after the command name is provided as input.
250248
#[schemars(rename = "UnstructuredCommandInput")]
251249
Unstructured {
252-
/// A brief description of the expected input
250+
/// A hint to display when the input hasn't been provided yet
253251
hint: String,
254252
},
255253
}

rust/example_client.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ impl acp::Client for ExampleClient {
9898
| acp::SessionUpdate::ToolCall(_)
9999
| acp::SessionUpdate::ToolCallUpdate(_)
100100
| acp::SessionUpdate::Plan(_)
101-
| acp::SessionUpdate::CurrentModeUpdate { .. } => {}
101+
| acp::SessionUpdate::CurrentModeUpdate { .. }
102+
| acp::SessionUpdate::AvailableCommandsUpdate { .. } => {}
102103
}
103104
Ok(())
104105
}

rust/rpc_tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,7 @@ async fn test_full_conversation_flow() {
727727
found_tool_update = true;
728728
}
729729
}
730+
SessionUpdate::AvailableCommandsUpdate { .. } => {}
730731
_ => {}
731732
}
732733
}

schema/schema.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,16 @@
254254
"description": "All text that was typed after the command name is provided as input.",
255255
"properties": {
256256
"hint": {
257-
"description": "A brief description of the expected input",
257+
"description": "A hint to display when the input hasn't been provided yet",
258258
"type": "string"
259259
}
260260
},
261261
"required": ["hint"],
262262
"title": "UnstructuredCommandInput",
263263
"type": "object"
264264
}
265-
]
265+
],
266+
"description": "The input specification for a command."
266267
},
267268
"BlobResourceContents": {
268269
"description": "Binary resource contents.",
@@ -1715,11 +1716,10 @@
17151716
}
17161717
},
17171718
"required": ["sessionUpdate", "availableCommands"],
1718-
"type": "object",
1719-
"x-docs-ignore": true
1719+
"type": "object"
17201720
},
17211721
{
1722-
"description": "The current mode of the session has changed",
1722+
"description": "The current mode of the session has changed\n\nSee protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)",
17231723
"properties": {
17241724
"currentModeId": {
17251725
"$ref": "#/$defs/SessionModeId"

typescript/schema.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,9 @@ export type SessionModeId = string;
401401
*/
402402
/** @internal */
403403
export type AgentNotification = SessionNotification | ExtNotification1;
404+
/**
405+
* The input specification for a command.
406+
*/
404407
export type AvailableCommandInput = UnstructuredCommandInput;
405408

406409
/**
@@ -1595,7 +1598,7 @@ export interface AvailableCommand {
15951598
*/
15961599
export interface UnstructuredCommandInput {
15971600
/**
1598-
* A brief description of the expected input
1601+
* A hint to display when the input hasn't been provided yet
15991602
*/
16001603
hint: string;
16011604
}

0 commit comments

Comments
 (0)