ag-ui-protocol / ag-ui-protocol/ag-ui

[Feature] Paginated message history — /agents/state returns all events at once, unworkable for long enterprise conversations

Open
#2,159 3 comments 0 reactions 0 assignees View on GitHub
enhancement Integration
Dominant language
Python
Stars
15.9k
Forks
1.4k
Avg merge
1d 17h
Merged PRs (30d)
163

Description

## Summary

The current `POST /agents/state` endpoint returns the **full message history** of a thread in a single response. For enterprise deployments with long, multi-hour conversations this becomes a serious problem: the response grows unbounded, memory and latency increase with every turn, and there is no way to load history incrementally.

We are building an assistant used by engineers for complex development tasks. A single session can easily span dozens of tool calls, reasoning traces, and document attachments — conversations that in production regularly exceed what is reasonable to serialize and transfer in one shot.

## Why /agents/state doesn't work at scale

`/agents/state` was designed as a convenience endpoint to hydrate a frontend from scratch, but it has no pagination contract:

- It loads **all ADK session events**, converts them to AG-UI `Message[]` objects, and returns them in one JSON blob.
- There is no `limit`, `offset`, `cursor`, or `since` parameter.
- A conversation with 80 turns, multimodal attachments, and multiple tool calls can produce a response of several MB — and it only gets worse over time.
- The client has no way to request "give me the last N messages" or "messages after event X".

## What we need

A **paginated message-history endpoint** that:

1. Returns AG-UI `Message[]` objects (same shape as `/agents/state`, i.e. the output of `adk_events_to_messages`) — so the client stays in the AG-UI model and doesn't need to understand ADK internals.
2. Accepts pagination parameters — offset/limit for simplicity, or a cursor for robustness (e.g. `after=` or `since=`).
3. Returns total count so the client can render a "load more" / infinite-scroll UI.

A natural path: a dedicated `GET /agents/messages` (or `GET /agents/state/messages`) endpoint alongside `/agents/state`, using the same auth/identity resolution pipeline.

## Suggested shape

Request:
```
GET /agents/messages?threadId=&limit=50&offset=0
Authorization: Bearer
```

Response:
```json
{
"threadId": "…",
"messages": [ /* AG-UI Message[] */ ],
"total": 142,
"limit": 50,
"offset": 0
}
```

Or with a cursor:
```
GET /agents/messages?threadId=&limit=50&after=
```

```json
{
"threadId": "…",
"messages": [ /* AG-UI Message[] */ ],
"nextCursor": "",
"hasMore": true
}
```

## Related

- #640 (closed) — the original issue requesting message history at all; `/agents/state` was the resolution. This issue is the natural next step: making that history usable at scale.
- #1048 — performance impact of unbounded message serialization per streamed token; same root cause (no bound on the message list size).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.