Skip to content

Commit 2aaee43

Browse files
committed
Checkpoint: Stabilizing commands
1 parent 1950096 commit 2aaee43

8 files changed

Lines changed: 127 additions & 10 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/commands",
6263
"protocol/extensibility",
6364
"protocol/schema"
6465
]

docs/protocol/commands.mdx

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
title: "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.
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 brief description of the expected input
69+
</ResponseField>
70+
71+
## Command lifecycle
72+
73+
1. **Discovery**: The Agent sends available commands after session creation
74+
2. **Display**: The Client displays these commands in its UI (e.g., in a slash command menu)
75+
3. **Invocation**: When the user selects a command, the Client includes it in the prompt
76+
4. **Execution**: The Agent processes the command as part of the prompt
77+
78+
Commands are not a separate protocol mechanism - they are simply a way for the Agent to advertise what slash commands it understands. The actual command invocation happens through the regular prompt mechanism.
79+
80+
## Dynamic updates
81+
82+
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:
83+
84+
- Added based on context (e.g., project type detection)
85+
- Removed when no longer relevant
86+
- Modified with updated descriptions or input hints
87+
88+
Clients may also add their own local commands (e.g., authentication commands) to the list before displaying them to users.
89+
90+
## Example usage
91+
92+
When a user types `/web climate change` in the Client, it would send:
93+
94+
```json
95+
{
96+
"jsonrpc": "2.0",
97+
"id": 3,
98+
"method": "session/prompt",
99+
"params": {
100+
"sessionId": "sess_abc123def456",
101+
"prompt": {
102+
"type": "text",
103+
"text": "/web climate change"
104+
}
105+
}
106+
}
107+
```
108+
109+
The Agent recognizes the command prefix and processes it accordingly, potentially using web search tools to gather information about climate change.

docs/protocol/schema.mdx

Lines changed: 4 additions & 0 deletions
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">
@@ -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

rust/client.rs

Lines changed: 3 additions & 5 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,9 +240,9 @@ 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")]

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: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@
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: 3 additions & 0 deletions
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
/**

0 commit comments

Comments
 (0)