Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [] }
Expand Down
347 changes: 347 additions & 0 deletions docs/rfds/sessions-list-api.mdx
Original file line number Diff line number Diff line change
@@ -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
Comment on lines +146 to +147
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of following MCP's pattern here?: https://modelcontextprotocol.io/specification/2025-06-18/server/utilities/pagination

They call it nextCursor and you use the presence of it for the same meaning as your hasMore boolean, which I think makes sense


**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