diff --git a/docs/docs.json b/docs/docs.json index e70858d1..1e82d644 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -88,7 +88,7 @@ "tab": "RFDs", "pages": [ "rfds/about", - { "group": "Draft", "pages": [] }, + { "group": "Draft", "pages": ["rfds/sessions-list-api"] }, { "group": "Preview", "pages": [] }, { "group": "Accepted", "pages": ["rfds/introduce-rfd-process"] }, { "group": "Completed", "pages": [] } diff --git a/docs/rfds/sessions-list-api.mdx b/docs/rfds/sessions-list-api.mdx new file mode 100644 index 00000000..88598045 --- /dev/null +++ b/docs/rfds/sessions-list-api.mdx @@ -0,0 +1,347 @@ +--- +title: "Session List API" +--- + +Author(s): [@ahmedhesham6](https://github.com/ahmedhesham6) +Champion: [@benbrandt](https://github.com/benbrandt) + +## Elevator pitch + +Add a `session/list` endpoint to the ACP protocol that allows clients to query and enumerate existing sessions from an agent, enabling session management features like session history, session switching, and session cleanup. + +## Status quo + +Currently, the ACP protocol provides session management through `session/new` and `session/load` endpoints. However, there is no way for clients to: + +1. **Discover existing sessions** - Clients cannot query what sessions exist on an agent +2. **Display session history** - Users cannot see a list of their past conversations +3. **Manage multiple sessions** - Switching between sessions requires clients to track session IDs themselves +4. **Clean up old sessions** - No way to discover stale or abandoned sessions for cleanup + +This creates several problems: + +- **Poor user experience** - Users cannot browse their conversation history or resume previous sessions easily +- **Client-side complexity** - Each client must implement its own session tracking and persistence +- **Inconsistent behavior** - Different clients handle session management differently, leading to fragmented experiences + +The current workaround is for clients to maintain their own session registry, but this: + +- Requires persistent storage on the client side +- Can get out of sync if sessions are created/destroyed outside the client +- Doesn't work across different client instances or devices +- Cannot leverage agent-side session metadata or state + +## What we propose to do about it + +Add a new `session/list` JSON-RPC method to the protocol that returns metadata about sessions known to the agent. This endpoint would: + +1. **Return a list of sessions** with essential metadata: + - `sessionId` - Unique identifier + - `createdAt` - Timestamp when session was created + - `updatedAt` - Timestamp of last update to the session + - `cwd` - Working directory for the session + - `title` - Optional human-readable title (could be auto-generated from first prompt) + - `_meta` - Optional agent-specific metadata + +2. **Support filtering and pagination**: + - Filter by creation date, last accessed date, or working directory + - Limit the number of results returned + - Search by title or agent-provided metadata + +3. **Be an optional capability**: + - Agents advertise `listSessions: true` in initialization if they support this feature + - Clients check for this capability before attempting to call `session/list` + - Agents without persistent session storage don't need to implement this + +### JSON-RPC Request + +The client calls `session/list` with optional filtering and pagination parameters: + +```json +{ + "jsonrpc": "2.0", + "id": 2, + "method": "session/list", + "params": { + "cwd": "/home/user/project", + "createdAfter": "2025-10-20T00:00:00Z", + "limit": 20, + "continuationToken": "offset:20", + "search": "auth" + } +} +``` + +#### Request Parameters + +All parameters are optional: + +- `cwd` (string) - Filter sessions by working directory +- `createdAfter` (string) - ISO 8601 timestamp, only return sessions created after this time +- `createdBefore` (string) - ISO 8601 timestamp, only return sessions created before this time +- `updatedAfter` (string) - ISO 8601 timestamp, only return sessions updated after this time +- `limit` (number) - Maximum number of results to return (default: 50, max: 1000) +- `continuationToken` (string) - Opaque/stringified token from a previous response for cursor-based pagination +- `search` (string) - Free-text search across titles or agent metadata + +#### Minimal Request Example + +A request with no filters returns all sessions with default sorting: + +```json +{ + "jsonrpc": "2.0", + "id": 2, + "method": "session/list", + "params": {} +} +``` + +### JSON-RPC Response + +The agent responds with a list of sessions and cursor pagination metadata: + +```json +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "sessions": [ + { + "sessionId": "sess_abc123def456", + "createdAt": "2025-10-29T10:30:00Z", + "updatedAt": "2025-10-29T14:22:15Z", + "cwd": "/home/user/project", + "title": "Implement session list API", + "_meta": { + "messageCount": 12, + "hasErrors": false + } + }, + { + "sessionId": "sess_xyz789ghi012", + "createdAt": "2025-10-28T09:15:00Z", + "updatedAt": "2025-10-28T16:45:30Z", + "cwd": "/home/user/another-project", + "title": "Debug authentication flow" + }, + { + "sessionId": "sess_uvw345rst678", + "createdAt": "2025-10-27T14:00:00Z", + "updatedAt": "2025-10-27T15:30:00Z", + "cwd": "/home/user/project" + } + ], + "hasMore": true, + "nextContinuationToken": "offset:40" + } +} +``` + +#### Response Fields + +**Response object:** + +- `sessions` (array) - Array of session information objects +- `hasMore` (boolean) - Whether more results are available after this page +- `nextContinuationToken` (string, optional) - Pass this token in the next request's `continuationToken` to fetch the next page + +**SessionInfo object:** + +- `sessionId` (string, required) - Unique identifier for the session +- `createdAt` (string, required) - ISO 8601 timestamp when session was created +- `updatedAt` (string, required) - ISO 8601 timestamp of last activity +- `cwd` (string, required) - Working directory for the session +- `title` (string, optional) - Human-readable title (may be auto-generated from first prompt) +- `_meta` (object, optional) - Agent-specific metadata (e.g., message count, error status, tags) + +#### Empty Result Example + +When no sessions match the criteria: + +```json +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "sessions": [], + "hasMore": false + } +} +``` + +## Shiny future + +Once this feature exists: + +1. **Clients can build session browsers** - Users can view a list of all their conversations, sorted by recency or relevance +2. **Session switching becomes seamless** - Users can easily switch between ongoing conversations +3. **Better resource management** - Clients can identify and clean up old or inactive sessions +4. **Cross-device continuity** - Users could potentially access their sessions from different devices (if agent supports it) +5. **Improved UX patterns**: + - "Recent conversations" sidebar + - Search through past sessions + - Archive/delete old sessions + - Resume interrupted work easily + +Agents that implement this feature gain: + +- Better visibility into active sessions +- Opportunity to implement session lifecycle policies +- Foundation for future features like session sharing or collaboration + +## Implementation details and plan + +### Phase 1: Core Protocol Changes + +1. **Update schema.json** to add: + - `session/list` method definition + - `ListSessionsRequest` and `ListSessionsResponse` types + - `SessionInfo` type + - `listSessions` capability flag + +2. **Update protocol documentation** in `/docs/protocol/session-setup.mdx`: + - Document the new endpoint + - Explain when to use it vs. maintaining client-side session tracking + - Provide examples of common use cases + +### Phase 2: Reference Implementation + +3. **Implement in Rust SDK** (`rust/agent.rs` and `rust/client.rs`): + - Add `list_sessions` method to agent trait + - Provide default implementation (empty list) for agents without persistence + - Add client method to call `session/list` + +4. **Add to TypeScript SDKs** (if applicable): + - Update TypeScript types + - Add client methods + +### Phase 3: Example Implementation + +5. **Create example agent** that demonstrates: + - In-memory session registry + - Automatic title generation from first prompt + - Session lifecycle management (cleanup after N days) + - Pagination and filtering + +### Compatibility Considerations + +- **Backward compatible**: Existing agents continue working without implementing this +- **Capability-based**: Clients check for `listSessions` capability before using +- **No breaking changes**: No modifications to existing endpoints + +### Security Considerations + +- **Session isolation**: Agents must ensure sessions are only listed for the authenticated client +- **Resource limits**: Agents should enforce reasonable limits on pagination to prevent abuse + +## Frequently asked questions + +### What alternative approaches did you consider, and why did you settle on this one? + +Several alternatives were considered: + +1. **Client-side session tracking only** - This is the current approach, but it has limitations: + - Doesn't work across devices + - Can get out of sync + - Adds complexity to every client implementation + +2. **Session events/notifications** - Push notifications when sessions are created/destroyed: + - More complex to implement + - Requires long-lived connections + - Still requires client-side state management + - Better suited as a future enhancement, not a replacement + +3. **File-based session manifest** - Agent writes session list to a file that clients read: + - Couples agent and client file system access + - Doesn't work for remote agents + - No standard format + +The proposed RPC approach is: + +- **Consistent with existing protocol design** - Uses same RPC patterns as other endpoints +- **Flexible** - Supports filtering, pagination, and agent-specific metadata +- **Optional** - Agents can opt-in based on their architecture +- **Simple** - Single request/response pattern, easy to implement and use + +### Why not make this mandatory for all agents? + +Many agents may not have persistent storage or multi-session capabilities. Making this optional: + +- Allows simple, stateless agents to remain compliant +- Reduces implementation burden +- Lets agents evolve session management over time + +### How does this interact with `session/load`? + +`session/load` remains the mechanism to actually restore a session. `session/list` is for discovery only: + +1. Client calls `session/list` to get available sessions +2. User selects a session +3. Client calls `session/load` with the chosen `sessionId` + +Agents may support `session/list` without supporting `session/load` (e.g., for read-only session browsing). + +### Should we include session content in the list response? + +No, for several reasons: + +- **Performance** - Full conversation history could be large +- **Privacy** - Listing sessions might be less sensitive than exposing full content +- **Separation of concerns** - Use `session/load` to get full session content + +### What about session deletion? + +Session deletion is intentionally left out of this RFD to keep scope focused. A future `session/delete` endpoint could be proposed separately. For now, agents can implement their own lifecycle policies. + +### How should pagination work for large session lists? + +We use cursor-based pagination with an opaque continuation token: + +- Request includes `limit` and optional `continuationToken` +- Response includes `hasMore` and `nextContinuationToken` when more data is available +- Clients should not assume anything about the token's contents; treat it as opaque +- The token MUST be a string; never send a raw JSON object as the token + +Good request example: + +```json +{ + "jsonrpc": "2.0", + "id": 2, + "method": "session/list", + "params": { + "cwd": "/home/user/project", + "createdAfter": "2025-10-20T00:00:00Z", + "limit": 20, + "continuationToken": "offset:0", + "search": "auth" + } +} +``` + +Corresponding response example: + +```json +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "sessions": [ + /* ... */ + ], + "hasMore": true, + "nextContinuationToken": "offset:20" + } +} +``` + +## Revision history + +- **2025-10-29**: Initial draft proposal +- **2025-10-30**: Update to use `_meta` field for agent-specific metadata +- **2025-10-30**: Switch from offset-based to cursor-based pagination using continuation tokens +- **2025-10-30**: Rename `lastAccessedAt` to `updatedAt` for consistency +- **2025-10-30**: Remove `preview` field from SessionInfo (out of scope) +- **2025-10-30**: Remove session orphaning from problem statement +- **2025-10-30**: Replace `sortBy`/`sortOrder` with `search` parameter; remove `total` count from response