Skip to content

Commit b3aa5b5

Browse files
authored
Stabilize Session Modes (#87)
* Stabilize session modes * Update ts docs
1 parent cfaa0a5 commit b3aa5b5

13 files changed

Lines changed: 362 additions & 164 deletions

File tree

docs/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"protocol/file-system",
5959
"protocol/terminals",
6060
"protocol/agent-plan",
61+
"protocol/session-modes",
6162
"protocol/extensibility",
6263
"protocol/schema"
6364
]

docs/protocol/schema.mdx

Lines changed: 68 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,9 @@ Response from loading an existing session.
234234
Extension point for implementations
235235
</ResponseField>
236236
<ResponseField name="modes" type={<><span><a href="#sessionmodestate">SessionModeState</a></span><span> | null</span></>} >
237-
**UNSTABLE**
237+
Initial mode state if supported by the Agent
238238

239-
This field is not part of the spec, and may be removed or changed at any point.
239+
See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
240240

241241
</ResponseField>
242242

@@ -302,9 +302,9 @@ See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol
302302
Extension point for implementations
303303
</ResponseField>
304304
<ResponseField name="modes" type={<><span><a href="#sessionmodestate">SessionModeState</a></span><span> | null</span></>} >
305-
**UNSTABLE**
305+
Initial mode state if supported by the Agent
306306

307-
This field is not part of the spec, and may be removed or changed at any point.
307+
See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
308308

309309
</ResponseField>
310310
<ResponseField name="sessionId" type={<a href="#sessionid">SessionId</a>} required>
@@ -386,6 +386,59 @@ See protocol docs: [Check for Completion](https://agentclientprotocol.com/protoc
386386
Indicates why the agent stopped processing the turn.
387387
</ResponseField>
388388

389+
<a id="session-set_mode"></a>
390+
### <span class="font-mono">session/set_mode</span>
391+
392+
Sets the current mode for a session.
393+
394+
Allows switching between different agent modes (e.g., "ask", "architect", "code")
395+
that affect system prompts, tool availability, and permission behaviors.
396+
397+
The mode must be one of the modes advertised in `availableModes` during session
398+
creation or loading. Agents may also change modes autonomously and notify the
399+
client via `current_mode_update` notifications.
400+
401+
This method can be called at any time during a session, whether the Agent is
402+
idle or actively generating a response.
403+
404+
See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
405+
406+
#### <span class="font-mono">SetSessionModeRequest</span>
407+
408+
Request parameters for setting a session mode.
409+
410+
**Type:** Object
411+
412+
**Properties:**
413+
414+
<ResponseField name="_meta" type={"object"}>
415+
Extension point for implementations
416+
</ResponseField>
417+
<ResponseField
418+
name="modeId"
419+
type={<a href="#sessionmodeid">SessionModeId</a>}
420+
required
421+
>
422+
The ID of the mode to set.
423+
</ResponseField>
424+
<ResponseField
425+
name="sessionId"
426+
type={<a href="#sessionid">SessionId</a>}
427+
required
428+
>
429+
The ID of the session to set the mode for.
430+
</ResponseField>
431+
432+
#### <span class="font-mono">SetSessionModeResponse</span>
433+
434+
Response to `session/set_mode` method.
435+
436+
**Type:** Object
437+
438+
**Properties:**
439+
440+
<ResponseField name="meta" type={"object"}></ResponseField>
441+
389442
## Client
390443

391444
Defines the interface that ACP-compliant clients must implement.
@@ -1885,9 +1938,9 @@ See protocol docs: [Session ID](https://agentclientprotocol.com/protocol/session
18851938

18861939
## <span class="font-mono">SessionMode</span>
18871940

1888-
**UNSTABLE**
1941+
A mode the agent can operate in.
18891942

1890-
This type is not part of the spec, and may be removed or changed at any point.
1943+
See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
18911944

18921945
**Type:** Object
18931946

@@ -1906,17 +1959,13 @@ This type is not part of the spec, and may be removed or changed at any point.
19061959

19071960
## <span class="font-mono">SessionModeId</span>
19081961

1909-
**UNSTABLE**
1910-
1911-
This type is not part of the spec, and may be removed or changed at any point.
1962+
Unique identifier for a Session Mode.
19121963

19131964
**Type:** `string`
19141965

19151966
## <span class="font-mono">SessionModeState</span>
19161967

1917-
**UNSTABLE**
1918-
1919-
This type is not part of the spec, and may be removed or changed at any point.
1968+
The set of modes and the one currently active.
19201969

19211970
**Type:** Object
19221971

@@ -1936,12 +1985,16 @@ This type is not part of the spec, and may be removed or changed at any point.
19361985
</>
19371986
}
19381987
required
1939-
></ResponseField>
1988+
>
1989+
The set of modes that the Agent can operate in
1990+
</ResponseField>
19401991
<ResponseField
19411992
name="currentModeId"
19421993
type={<a href="#sessionmodeid">SessionModeId</a>}
19431994
required
1944-
></ResponseField>
1995+
>
1996+
The current mode the Agent is in.
1997+
</ResponseField>
19451998

19461999
## <span class="font-mono">SessionUpdate</span>
19472000

@@ -2184,18 +2237,6 @@ The current mode of the session has changed
21842237
</Expandable>
21852238
</ResponseField>
21862239

2187-
## <span class="font-mono">SetSessionModeResponse</span>
2188-
2189-
**UNSTABLE**
2190-
2191-
This type is not part of the spec, and may be removed or changed at any point.
2192-
2193-
**Type:** Object
2194-
2195-
**Properties:**
2196-
2197-
<ResponseField name="meta" type={"object"}></ResponseField>
2198-
21992240
## <span class="font-mono">StopReason</span>
22002241

22012242
Reasons why an agent stops processing a prompt turn.
@@ -2576,10 +2617,7 @@ See protocol docs: [Creating](https://agentclientprotocol.com/protocol/tool-call
25762617
<ResponseField name="fetch">Retrieving external data.</ResponseField>
25772618

25782619
<ResponseField name="switch_mode">
2579-
**UNSTABLE**
2580-
2581-
This tool kind is not part of the spec and may be removed at any point.
2582-
2620+
Switching the current session mode.
25832621
</ResponseField>
25842622

25852623
<ResponseField name="other">Other tool types (default).</ResponseField>

docs/protocol/session-modes.mdx

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
---
2+
title: "Session Modes"
3+
description: "How agents can operate in different modes"
4+
---
5+
6+
Agents can provide a set of modes they can operate in. Modes often affect the system prompts used, the availability of tools, and whether they request permission before running.
7+
8+
## Initial state
9+
10+
During [Session Setup](./session-setup) the Agent **MAY** return a list of modes it can operate in and the currently active mode:
11+
12+
```json
13+
{
14+
"jsonrpc": "2.0",
15+
"id": 1,
16+
"result": {
17+
"sessionId": "sess_abc123def456",
18+
"modes": {
19+
"currentModeId": "ask",
20+
"availableModes": [
21+
{
22+
"id": "ask",
23+
"name": "Ask",
24+
"description": "Request permission before making any changes"
25+
},
26+
{
27+
"id": "architect",
28+
"name": "Architect",
29+
"description": "Design and plan software systems without implementation"
30+
},
31+
{
32+
"id": "code",
33+
"name": "Code",
34+
"description": "Write and modify code with full tool access"
35+
}
36+
]
37+
}
38+
}
39+
}
40+
```
41+
42+
<ResponseField name="modes" type="SessionModeState">
43+
The current mode state for the session
44+
</ResponseField>
45+
46+
### SessionModeState
47+
48+
<ResponseField name="currentModeId" type="SessionModeId" required>
49+
The ID of the mode that is currently active
50+
</ResponseField>
51+
52+
<ResponseField name="availableModes" type="SessionMode[]" required>
53+
The set of modes that the Agent can operate in
54+
</ResponseField>
55+
56+
### SessionMode
57+
58+
<ResponseField name="id" type="SessionModeId" required>
59+
Unique identifier for this mode
60+
</ResponseField>
61+
62+
<ResponseField name="name" type="string" required>
63+
Human-readable name of the mode
64+
</ResponseField>
65+
66+
<ResponseField name="description" type="string">
67+
Optional description providing more details about what this mode does
68+
</ResponseField>
69+
70+
## Setting the current mode
71+
72+
The current mode can be changed at any point during a session, whether the Agent is idle or generating a response.
73+
74+
### From the Client
75+
76+
Typically, Clients display the available modes to the user and allow them to change the current one, which they can do by calling the [`session/set_mode`](./schema#session%2Fset-mode) method.
77+
78+
```json
79+
{
80+
"jsonrpc": "2.0",
81+
"id": 2,
82+
"method": "session/set_mode",
83+
"params": {
84+
"sessionId": "sess_abc123def456",
85+
"modeId": "code"
86+
}
87+
}
88+
```
89+
90+
<ParamField path="sessionId" type="SessionId" required>
91+
The ID of the session to set the mode for
92+
</ParamField>
93+
94+
<ParamField path="modeId" type="SessionModeId" required>
95+
The ID of the mode to switch to. Must be one of the modes listed in
96+
`availableModes`
97+
</ParamField>
98+
99+
### From the Agent
100+
101+
The Agent can also change its own mode and let the Client know by sending the `current_mode_update` session notification:
102+
103+
```json
104+
{
105+
"jsonrpc": "2.0",
106+
"method": "session/update",
107+
"params": {
108+
"sessionId": "sess_abc123def456",
109+
"update": {
110+
"sessionUpdate": "current_mode_update",
111+
"modeId": "code"
112+
}
113+
}
114+
}
115+
```
116+
117+
#### Exiting plan modes
118+
119+
A common case where an Agent might switch modes is from within a special "exit mode" tool that can be provided to the language model during plan/architect modes. The language model can call this tool when it determines it's ready to start implementing a solution.
120+
121+
This "switch mode" tool will usually request permission before running, which it can do just like any other tool:
122+
123+
```json
124+
{
125+
"jsonrpc": "2.0",
126+
"id": 3,
127+
"method": "session/request_permission",
128+
"params": {
129+
"sessionId": "sess_abc123def456",
130+
"toolCall": {
131+
"toolCallId": "call_switch_mode_001",
132+
"title": "Ready for implementation",
133+
"kind": "switch_mode",
134+
"status": "pending",
135+
"content": [
136+
{
137+
"type": "text",
138+
"text": "## Implementation Plan..."
139+
}
140+
]
141+
},
142+
"options": [
143+
{
144+
"optionId": "code",
145+
"name": "Yes, and auto-accept all actions",
146+
"kind": "allow_always"
147+
},
148+
{
149+
"optionId": "ask",
150+
"name": "Yes, and manually accept actions",
151+
"kind": "allow_once"
152+
},
153+
{
154+
"optionId": "reject",
155+
"name": "No, stay in architect mode",
156+
"kind": "reject_once"
157+
}
158+
]
159+
}
160+
}
161+
```
162+
163+
When an option is chosen, the tool runs, setting the mode and sending the `current_mode_update` notification mentioned above.
164+
165+
<Card icon="shield-check" horizontal href="./tool-calls#requesting-permission">
166+
Learn more about permission requests
167+
</Card>

rust/acp.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ impl Agent for ClientSideConnection {
211211
.map(|value| value.unwrap_or_default())
212212
}
213213

214-
#[cfg(feature = "unstable")]
215214
async fn set_session_mode(
216215
&self,
217216
arguments: SetSessionModeRequest,
@@ -619,7 +618,6 @@ impl Side for AgentSide {
619618
SESSION_LOAD_METHOD_NAME => serde_json::from_str(params.get())
620619
.map(ClientRequest::LoadSessionRequest)
621620
.map_err(Into::into),
622-
#[cfg(feature = "unstable")]
623621
SESSION_SET_MODE_METHOD_NAME => serde_json::from_str(params.get())
624622
.map(ClientRequest::SetSessionModeRequest)
625623
.map_err(Into::into),
@@ -686,7 +684,6 @@ impl<T: Agent> MessageHandler<AgentSide> for T {
686684
let response = self.prompt(args).await?;
687685
Ok(AgentResponse::PromptResponse(response))
688686
}
689-
#[cfg(feature = "unstable")]
690687
ClientRequest::SetSessionModeRequest(args) => {
691688
let response = self.set_session_mode(args).await?;
692689
Ok(AgentResponse::SetSessionModeResponse(response))

0 commit comments

Comments
 (0)