Skip to content

feat: support resumable background runs over AG-UI - #1

Closed
ranst91 wants to merge 1 commit into
mainfrom
feat/agui-resumable-background-runs
Closed

ranst91 wants to merge 1 commit into
mainfrom
feat/agui-resumable-background-runs

Conversation

@ranst91

@ranst91 ranst91 commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds opt-in background execution to the AG-UI interface, so a run can outlive the request that started it and a client that disconnects can reconnect and pick up exactly where it left off.

Today an AG-UI run is executed inside the HTTP request handler. If the client goes away mid-run, the request is cancelled and the run dies with it. A long run is therefore only as durable as the browser tab that started it.

Agno already has everything needed to fix that: detached execution, a buffer of indexed run events, replay and tailing. This change consumes those from the AG-UI interface rather than adding anything alongside them.

How it works

A client opts in per run through forwardedProps.agnoBackground.enabled. Foreground stays the default and is untouched, down to carrying no added metadata. The interface starts the run detached and streams it by tailing the buffered event stream instead of the live producer, stamping a resume cursor on every event under metadata.agnoBackground. The cursor has two parts, the index of the Agno event and the ordinal within its expansion, because one Agno event can become several AG-UI events and a resuming client has to be able to land in the middle of one.

To resume, the client sends the same runId back with its last cursor. Everything up to that point is filtered out, the rest of the buffer is replayed in canonical order, and the stream continues live to completion. Messages, tool calls, tool results, state, errors and terminal events all survive the round trip, and message ids are minted deterministically for background runs so a replay reproduces the ids the first connection already saw.

Support is probed at runtime rather than inferred from a version, and a request that cannot be honored is refused with a run error rather than silently re-executed.

Agents and teams are both covered.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Improvement
  • Model update
  • Other:

Checklist

  • Code complies with style guidelines
  • Ran format/validation scripts (./scripts/format.sh and ./scripts/validate.sh)
  • Self-review completed
  • Documentation updated (comments, docstrings)
  • Examples and guides: Relevant cookbook examples have been included or updated (if applicable)
  • Tested in clean environment
  • Tests added/updated (if applicable)

Duplicate and AI-Generated PR Check

  • I have searched existing open pull requests and confirmed that no other PR already addresses this issue
  • If a similar PR exists, I have explained below why this PR is a better approach
  • Check if this PR was entirely AI-generated (by Copilot, Claude Code, Cursor, etc.)

Adds opt-in background execution to the AG-UI interface. Foreground runs
are untouched and remain the default.

A client opts in per run with forwardedProps.agnoBackground.enabled. The
interface starts the run detached, then streams it by tailing Agno's
buffered indexed event stream rather than the live producer. Every
emitted AG-UI event carries a resume cursor in metadata.agnoBackground:
the index of the Agno event it came from plus its ordinal within that
event's expansion. A client that drops the connection reconnects with
that cursor, receives the buffered remainder exactly once in canonical
order, and continues live to completion.

Ordinary messages, tool calls, tool results, state snapshots and deltas,
errors and terminal events all survive the round trip. Message ids are
minted deterministically for background runs so a replay reproduces the
ids the first connection saw; foreground keeps random ids.

Both agents and teams are covered. Support is probed at runtime rather
than by version, and a request the entity cannot honor is refused with a
run error instead of being silently downgraded or re-run. A cursor that
points past a trimmed buffer is refused rather than answered with a gap.

Consumes Agno's existing detached execution, event buffer, replay and
tailing without modifying them.

Tests cover replay ordering and exactly-once delivery deterministically,
plus a real uvicorn server with an actual mid-stream disconnect and
reconnect over HTTP, for both agents and teams.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant