Automattic / Automattic/agents-api
Resumable event streams via event ids and cursors
- Dominant language
- PHP
- Stars
- 33
- Forks
- 8
- Avg merge
- 1h 36m
- Merged PRs (30d)
- 31
Description
## Problem
Streaming has no resume. The SSE helper writes `data:` frames only, so a browser `EventSource` has no event id to send back and reconnects with no position. On a dropped connection, a PHP timeout, a proxy cutting an idle stream, or a phone changing network, everything emitted meanwhile is lost to that client.
The data is already there. `agents/list-chat-run-events` takes a `cursor` and returns one with `has_more`. The stream just does not expose it, so clients have to choose between replaying a whole run and losing part of it. Long runs are where this hurts, and long runs are what run control was built for.
## Evidence
- `src/Runtime/functions-sse-response.php` — `agents_api_emit_sse_json_frame()` writes `data:` and flushes. No `id:` line.
- `src/Channels/register-agents-chat-run-control-abilities.php` — the events ability already accepts `cursor` and `limit` and returns `cursor` and `has_more`.
- `docs/external-clients.md` documents `message/stream` with no resume path.
## Required contract
- Emit an `id:` line on each SSE frame, using the same event id `agents/list-chat-run-events` returns, so stream position and page cursor are the same coordinate.
- Accept `Last-Event-ID` on the streaming routes, plus an explicit cursor parameter for clients that are not `EventSource`, and resume after that point.
- An unknown or expired cursor returns an explicit error. Never silently restart from the beginning of the run, which is how duplicates reach the user.
- Keep resume optional for adapters that cannot replay. Those reject the resume request rather than serving a partial stream as if it were complete.
## Tests
- A reconnect with `Last-Event-ID` receives only events after that id.
- An unknown or expired cursor returns an explicit error, not a full replay.
- A connection with no cursor behaves exactly as today.
- Event ids on the stream sort in the same order as the ids from `agents/list-chat-run-events` for the same run.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with src/Runtime/functions-sse-response.php and the streaming routes, then compare their behavior with src/Channels/register-agents-chat-run-control-abilities.php, which already handles cursors. Read docs/external-clients.md for the current client contract and add or run tests for reconnects, invalid cursors, no-cursor compatibility, and event ordering. Done means supported adapters resume after Last-Event-ID or an explicit cursor, while unsupported adapters reject resume explicitly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php
- Domain
- api, backend, stream-processing
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100