|
| 1 | +--- |
| 2 | +title: "Session Info Update" |
| 3 | +--- |
| 4 | + |
| 5 | +- Author(s): [@ignatov](https://github.com/ignatov) |
| 6 | +- Champion: [@benbrandt](https://github.com/benbrandt) |
| 7 | + |
| 8 | +## Elevator pitch |
| 9 | + |
| 10 | +Add a `session_info_update` variant to the existing `SessionUpdate` notification type that allows agents to update session metadata (particularly title/name), enabling dynamic session identification in client UIs without requiring a new endpoint. |
| 11 | + |
| 12 | +## Status quo |
| 13 | + |
| 14 | +Currently, the ACP protocol provides session management through `session/new`, `session/load`, and `session/list` (unstable). The `session/list` endpoint returns `SessionInfo` objects that include an optional `title` field for displaying session names in client UIs. |
| 15 | + |
| 16 | +However, there are several problems: |
| 17 | + |
| 18 | +1. **No way to communicate title updates** - The `title` field in `SessionInfo` is static in the list response. Agents cannot dynamically update it as the session evolves. |
| 19 | + |
| 20 | +2. **No mechanism for real-time metadata updates** - Unlike commands (`available_commands_update`) or modes (`current_mode_update`), there's no way for agents to: |
| 21 | + - Auto-generate titles after the first meaningful exchange |
| 22 | + - Update titles as conversation context shifts |
| 23 | + - Provide custom metadata that reflects session state |
| 24 | + |
| 25 | +3. **Inconsistent with protocol patterns** - Other dynamic session properties use `session/update` notifications (commands, modes, plans), but metadata has no equivalent mechanism. |
| 26 | + |
| 27 | +The current workaround is for clients to: |
| 28 | + |
| 29 | +- Maintain their own title mapping (doesn't persist or sync) |
| 30 | +- Only show static metadata from `session/list` |
| 31 | +- Have no way to receive agent-generated titles in real-time |
| 32 | + |
| 33 | +## What we propose to do about it |
| 34 | + |
| 35 | +Add a new `session_info_update` variant to the existing `SessionUpdate` discriminated union that allows agents to notify clients about metadata changes. This update would: |
| 36 | + |
| 37 | +1. **Follow the existing `SessionUpdate` pattern**: |
| 38 | + - Uses the same notification mechanism as `available_commands_update`, `current_mode_update`, etc. |
| 39 | + - Sent via `session/update` method |
| 40 | + - Agent-initiated, no request/response needed |
| 41 | + |
| 42 | +2. **Align with `SessionInfo` structure**: |
| 43 | + - Contains the same fields as `SessionInfo` from `session/list` |
| 44 | + - All fields are optional (partial updates) |
| 45 | + - Enables incremental metadata updates |
| 46 | + - **Important**: `SessionInfoUpdate` must stay aligned with `SessionInfo` - when new fields are added to `SessionInfo`, they should also be added to `SessionInfoUpdate` as optional fields |
| 47 | + |
| 48 | +3. **Support common use cases**: |
| 49 | + - Agent auto-generates title after first prompt |
| 50 | + - Agent updates title as conversation context shifts |
| 51 | + - Agent provides custom metadata for client features (tags, status, etc.) |
| 52 | + - User explicitly requests title change (agent responds with update notification) |
| 53 | + |
| 54 | +4. **Integrate seamlessly**: |
| 55 | + - No new capability required (uses existing `session/update` mechanism) |
| 56 | + - Compatible with `session/list` - metadata should persist and be reflected in list responses |
| 57 | + - Works during active sessions |
| 58 | + |
| 59 | +### Notification Structure |
| 60 | + |
| 61 | +The agent sends a `session/update` notification with `sessionUpdate: "session_info_update"`: |
| 62 | + |
| 63 | +```json |
| 64 | +{ |
| 65 | + "jsonrpc": "2.0", |
| 66 | + "method": "session/update", |
| 67 | + "params": { |
| 68 | + "sessionId": "sess_abc123def456", |
| 69 | + "update": { |
| 70 | + "sessionUpdate": "session_info_update", |
| 71 | + "title": "Implement user authentication", |
| 72 | + "_meta": { |
| 73 | + "tags": ["feature", "auth"], |
| 74 | + "priority": "high" |
| 75 | + } |
| 76 | + } |
| 77 | + } |
| 78 | +} |
| 79 | +``` |
| 80 | + |
| 81 | +### SessionInfoUpdate Type |
| 82 | + |
| 83 | +The update type mirrors `SessionInfo` but with all fields optional: |
| 84 | + |
| 85 | +```typescript |
| 86 | +{ |
| 87 | + sessionUpdate: "session_info_update", |
| 88 | + title?: string | null, // Update or clear the title |
| 89 | + updatedAt?: string | null, // ISO 8601 timestamp (usually agent sets this) |
| 90 | + _meta?: object | null // Custom metadata (merged with existing) |
| 91 | +} |
| 92 | +``` |
| 93 | + |
| 94 | +**Note:** `sessionId` and `cwd` are NOT included since: |
| 95 | + |
| 96 | +- `sessionId` is already in the notification's `params` |
| 97 | +- `cwd` is immutable and set during `session/new` |
| 98 | + |
| 99 | +### Examples |
| 100 | + |
| 101 | +#### Update title and working directory metadata |
| 102 | + |
| 103 | +After the user sends their first meaningful prompt, the agent can generate and send a title along with metadata about the working directory: |
| 104 | + |
| 105 | +```json |
| 106 | +{ |
| 107 | + "jsonrpc": "2.0", |
| 108 | + "method": "session/update", |
| 109 | + "params": { |
| 110 | + "sessionId": "sess_abc123def456", |
| 111 | + "update": { |
| 112 | + "sessionUpdate": "session_info_update", |
| 113 | + "title": "Debug authentication timeout", |
| 114 | + "_meta": { |
| 115 | + "projectName": "api-server", |
| 116 | + "branch": "main" |
| 117 | + } |
| 118 | + } |
| 119 | + } |
| 120 | +} |
| 121 | +``` |
| 122 | + |
| 123 | +#### Update title as conversation evolves |
| 124 | + |
| 125 | +As the conversation shifts focus: |
| 126 | + |
| 127 | +```json |
| 128 | +{ |
| 129 | + "jsonrpc": "2.0", |
| 130 | + "method": "session/update", |
| 131 | + "params": { |
| 132 | + "sessionId": "sess_abc123def456", |
| 133 | + "update": { |
| 134 | + "sessionUpdate": "session_info_update", |
| 135 | + "title": "Debug authentication timeout → Add retry logic" |
| 136 | + } |
| 137 | + } |
| 138 | +} |
| 139 | +``` |
| 140 | + |
| 141 | +## Shiny future |
| 142 | + |
| 143 | +Once this feature exists: |
| 144 | + |
| 145 | +1. **Dynamic session identification** - Agents can: |
| 146 | + - Auto-generate meaningful titles from conversation content |
| 147 | + - Update titles as conversations evolve |
| 148 | + - Provide rich metadata for better organization |
| 149 | + |
| 150 | +2. **Improved client UIs** - Clients can: |
| 151 | + - Show real-time title updates in session lists |
| 152 | + - Display session status, tags, or other metadata |
| 153 | + - Update UI immediately without polling `session/list` |
| 154 | + |
| 155 | +3. **Consistent protocol patterns** - Session metadata updates work like other dynamic session properties (commands, modes), creating a unified model |
| 156 | + |
| 157 | +4. **Bidirectional workflows** - Combined with a potential future request method: |
| 158 | + - User renames session → client sends request → agent acknowledges with `session_info_update` notification |
| 159 | + - Agent auto-generates title → sends `session_info_update` notification → client displays it |
| 160 | + |
| 161 | +5. **Enhanced use cases**: |
| 162 | + - Session templates that auto-set titles and tags |
| 163 | + - Progress indicators via `_meta` |
| 164 | + - Integration with external tools via metadata |
| 165 | + - Rich session browsing and filtering |
| 166 | + |
| 167 | +## Implementation details and plan |
| 168 | + |
| 169 | +### Phase 1: Schema Changes |
| 170 | + |
| 171 | +1. **Update `schema.unstable.json`**: |
| 172 | + - Add `SessionInfoUpdate` type definition |
| 173 | + - Add new variant to `SessionUpdate` oneOf array |
| 174 | + - Align fields with `SessionInfo` but make all optional |
| 175 | + |
| 176 | +```json |
| 177 | +{ |
| 178 | + "SessionInfoUpdate": { |
| 179 | + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nUpdate to session metadata. All fields are optional to support partial updates.", |
| 180 | + "properties": { |
| 181 | + "_meta": { |
| 182 | + "description": "Extension point for implementations" |
| 183 | + }, |
| 184 | + "title": { |
| 185 | + "description": "Human-readable title for the session", |
| 186 | + "type": ["string", "null"] |
| 187 | + }, |
| 188 | + "updatedAt": { |
| 189 | + "description": "ISO 8601 timestamp of last activity", |
| 190 | + "type": ["string", "null"] |
| 191 | + } |
| 192 | + }, |
| 193 | + "type": "object" |
| 194 | + } |
| 195 | +} |
| 196 | +``` |
| 197 | + |
| 198 | +Add to `SessionUpdate` oneOf: |
| 199 | + |
| 200 | +```json |
| 201 | +{ |
| 202 | + "allOf": [ |
| 203 | + { |
| 204 | + "$ref": "#/$defs/SessionInfoUpdate" |
| 205 | + } |
| 206 | + ], |
| 207 | + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nUpdate to session metadata", |
| 208 | + "properties": { |
| 209 | + "sessionUpdate": { |
| 210 | + "const": "session_info_update", |
| 211 | + "type": "string" |
| 212 | + } |
| 213 | + }, |
| 214 | + "required": ["sessionUpdate"], |
| 215 | + "type": "object" |
| 216 | +} |
| 217 | +``` |
| 218 | + |
| 219 | +### Phase 2: Protocol Documentation |
| 220 | + |
| 221 | +2. **Create documentation** in `/docs/protocol/session-metadata.mdx`: |
| 222 | + - Explain the notification mechanism |
| 223 | + - Provide examples of common patterns |
| 224 | + - Document merge semantics for `_meta` |
| 225 | + - Clarify relationship with `session/list` |
| 226 | + |
| 227 | +3. **Update existing docs**: |
| 228 | + - Reference in `/docs/protocol/session-setup.mdx` |
| 229 | + - Add to `/docs/protocol/prompt-turn.mdx` session update section |
| 230 | + |
| 231 | +### Phase 3: SDK Implementation |
| 232 | + |
| 233 | +4. **Implement in Rust SDK**: |
| 234 | + - Add `SessionInfoUpdate` struct |
| 235 | + - Add variant to `SessionUpdate` enum |
| 236 | + - Update notification handling in agent and client traits |
| 237 | + - Add helper methods for common patterns |
| 238 | + |
| 239 | +5. **Implement in TypeScript SDK** (if applicable): |
| 240 | + - Add TypeScript types |
| 241 | + - Update notification handlers |
| 242 | + - Add helper methods |
| 243 | + |
| 244 | +### Phase 4: Example Implementation |
| 245 | + |
| 246 | +6. **Update example agents**: |
| 247 | + - Demonstrate auto-generating title from first prompt |
| 248 | + - Show updating metadata during session |
| 249 | + - Example of using `_meta` for custom fields |
| 250 | + |
| 251 | +### Compatibility Considerations |
| 252 | + |
| 253 | +- **Fully backward compatible**: This adds a new notification variant to an existing mechanism |
| 254 | +- **No breaking changes**: Existing agents and clients continue working |
| 255 | +- **Graceful degradation**: Clients that don't handle this notification simply ignore it |
| 256 | +- **No new capability needed**: Uses existing `session/update` infrastructure |
| 257 | + |
| 258 | +### Design Decisions |
| 259 | + |
| 260 | +**Why notification instead of request/response?** |
| 261 | + |
| 262 | +- Consistent with existing `SessionUpdate` patterns (`available_commands_update`, `current_mode_update`) |
| 263 | +- Agents initiate updates based on conversation state |
| 264 | +- Simpler than bidirectional request/response |
| 265 | +- Enables real-time updates without polling |
| 266 | + |
| 267 | +**Why make all fields optional?** |
| 268 | + |
| 269 | +- Allows partial updates (only update what changed) |
| 270 | +- More efficient - don't resend unchanged data |
| 271 | +- Flexible for different use cases |
| 272 | +- Mirrors partial update patterns in other protocols |
| 273 | + |
| 274 | +**Why not include `sessionId` and `cwd` in the update?** |
| 275 | + |
| 276 | +- `sessionId` is already in the notification params |
| 277 | +- `cwd` is immutable (set in `session/new`, never changes) |
| 278 | +- Keeps update focused on mutable metadata |
| 279 | + |
| 280 | +**How do `_meta` updates work?** |
| 281 | + |
| 282 | +- **Merge semantics**: New `_meta` fields are merged with existing ones |
| 283 | +- To clear a specific field: `"_meta": { "fieldName": null }` |
| 284 | +- To clear all custom metadata: `"_meta": null` |
| 285 | + |
| 286 | +### Security Considerations |
| 287 | + |
| 288 | +- **No additional security concerns**: Uses existing session authentication |
| 289 | +- **Input validation**: |
| 290 | + - Agents should validate title length (recommend 500 chars max) |
| 291 | + - Sanitize metadata to prevent injection |
| 292 | + - Validate `_meta` structure based on agent requirements |
| 293 | +- **Resource limits**: Agents should limit update frequency and metadata size |
| 294 | + |
| 295 | +## Frequently asked questions |
| 296 | + |
| 297 | +### Why not create a new endpoint like `session/update-metadata`? |
| 298 | + |
| 299 | +The notification pattern is more appropriate because: |
| 300 | + |
| 301 | +1. **Consistency**: Other dynamic session properties (commands, modes) use notifications |
| 302 | +2. **Agent-initiated**: Agents typically generate titles from conversation context |
| 303 | +3. **Real-time**: No request/response overhead, updates flow naturally |
| 304 | +4. **Simpler**: Reuses existing `session/update` infrastructure |
| 305 | + |
| 306 | +### How does this work with `session/list`? |
| 307 | + |
| 308 | +The updated metadata should persist and be reflected in subsequent `session/list` calls. The notification provides real-time updates to connected clients, while `session/list` provides the current state for discovery. |
| 309 | + |
| 310 | +### Can clients trigger title updates? |
| 311 | + |
| 312 | +This RFD covers agent-initiated updates. Client-initiated updates could work by: |
| 313 | + |
| 314 | +1. Client sends a prompt asking to rename session |
| 315 | +2. Agent updates its internal state |
| 316 | +3. Agent sends `session_info_update` notification |
| 317 | +4. Client receives and displays the update |
| 318 | + |
| 319 | +A future RFD could add explicit request/response for this if needed. |
| 320 | + |
| 321 | +### What if multiple updates are sent in quick succession? |
| 322 | + |
| 323 | +Clients should apply updates incrementally in order. Each notification represents a delta, not a full replacement (except for fields explicitly set to `null`). |
| 324 | + |
| 325 | +### Should `updatedAt` be automatically set by the agent? |
| 326 | + |
| 327 | +Yes, typically the agent should update this timestamp when any session activity occurs, not just when metadata changes. However, including it in `session_info_update` allows agents to explicitly control it if needed. |
| 328 | + |
| 329 | +### Do agents need a new capability for this? |
| 330 | + |
| 331 | +No. All agents that support `session/update` notifications can send this variant. Clients that don't recognize it will ignore it (standard JSON-RPC behavior). |
| 332 | + |
| 333 | +### How does this interact with `session/fork`? |
| 334 | + |
| 335 | +When forking, the parent session's metadata could be copied (implementation choice). The forked session would have its own `sessionId` and could receive separate `session_info_update` notifications. |
| 336 | + |
| 337 | +### What happens if title is too long? |
| 338 | + |
| 339 | +This is an implementation choice. Agents MAY: |
| 340 | + |
| 341 | +- Truncate long titles |
| 342 | +- Reject updates (though this is a notification, so no error response) |
| 343 | +- Set a reasonable limit (e.g., 500 characters) |
| 344 | + |
| 345 | +Clients SHOULD handle long titles gracefully (truncate in UI, show tooltip, etc.). |
| 346 | + |
| 347 | +### Can `_meta` have nested objects? |
| 348 | + |
| 349 | +Yes, `_meta` is an arbitrary object. Agents define its structure. The merge semantics apply recursively - nested objects are merged, not replaced entirely. |
| 350 | + |
| 351 | +### What alternative approaches did you consider, and why did you settle on this one? |
| 352 | + |
| 353 | +Several alternatives were considered: |
| 354 | + |
| 355 | +1. **Add a new request/response endpoint (`session/update-metadata`)** - This would be inconsistent with how other dynamic session properties (commands, modes) are handled. The notification pattern is more appropriate for agent-initiated updates. |
| 356 | + |
| 357 | +2. **Add title parameter to `session/new`** - Only allows setting title at creation time, doesn't support dynamic updates as the conversation evolves. |
| 358 | + |
| 359 | +3. **Client-side only metadata tracking** - Doesn't work across devices, can get out of sync, and duplicates storage. This is the current workaround and has significant limitations. |
| 360 | + |
| 361 | +4. **Generic `session/update` request for all properties** - Could conflict with immutable properties (sessionId, cwd) and has unclear semantics about what can be updated. |
| 362 | + |
| 363 | +The proposed notification-based approach: |
| 364 | + |
| 365 | +- **Consistent** with existing protocol patterns |
| 366 | +- **Flexible** for both agent-initiated and user-initiated updates |
| 367 | +- **Simple** to implement and understand |
| 368 | +- **Extensible** via `_meta` field |
| 369 | + |
| 370 | +## Revision history |
| 371 | + |
| 372 | +- **2025-11-28**: Initial draft proposal |
0 commit comments