Skip to content

Let the Runner decide what runs from memberships sent over the link - #1833

Draft
loganj wants to merge 2 commits into
agents-runner-pluginsfrom
agents-link-running
Draft

loganj wants to merge 2 commits into
agents-runner-pluginsfrom
agents-link-running

Conversation

@loganj

@loganj loganj commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

🤖 This is step 8 of the Manager/Runner split for agents. It is an inert refactor: what runs, and what the Agents screens show, stay the same.

Summary

The app splits its agent code into two parts. The Manager serves the screens and agent management. The Runner runs agents and owns their saved state. The goal is to run the Runner in its own hidden page, so only JSON may pass between them.

This is the first slice where real state goes over that link instead of a direct call:

  • The Manager sends the viewer's agent memberships, and who the viewer is, as a link topic.
  • The Runner decides what runs from them. It sends back the running agents and which of them have interrupted turns.
  • The Agents screens and the interrupted-turns notice show only what arrives over the link.

Both parts still share one page. They talk over an in-page MessageChannel, the same code path the hidden page will use.

Details

  • The Runner decides again on its own when one of these changes: a saved record, a turn in progress, one of its community sessions, the loaded agent types, or the viewer's communities. Before, the Manager called it for each change.
  • Waiting for the Runner. Each set of memberships the Manager sends has a revision, tagged with the Manager page it came from. The Runner sends back the revision it decided from, even when nothing that runs changed or deciding failed. A page that reloads does not take the Runner's answer to its last load as an answer to itself. Reading the agent list (refresh) now settles only after the Runner has decided from it. So create still resolves with the new agent running, and events that arrive right after it are not missed.
  • Agents keep their identity. The Manager keeps each agent object the Runner sent until the Runner sends a change to that agent, so screens do not re-render for nothing.
  • Core memory. The Runner now refreshes an agent's cached core memory when a new session starts in a community it watched before, including one the viewer left and joined again. Before, the Manager did this when its own binding changed. A community that is already live when the Runner first watches it is not refreshed. The first turn reads it once, as before.
  • Disconnects. The Runner's community connections now report every connection change, not only a changed session. So a community that goes from reconnecting to disconnected stops its agents in the Runner itself.
  • Viewer changes. If the viewer changes, the Runner waits for the memberships that come with the new viewer before it connects communities again.
  • Still direct calls, moved in later slices: records, runner controls (retype, session controls, notes), agent types and defaults, teams, templates and the classifier key.

Known limits

  • If the Runner's page never answers, refresh waits. In one page that cannot happen. The hidden-page slice must bound this wait. A closed link and a Runner that fails to decide no longer make anyone wait.
  • The Agents screens now see a change one message later. Three service tests that checked the running list right after a disconnect or a resume now wait for it.

Tests

  • New link tests: the Runner decides from what the Manager sends; a wait settles when nothing that runs changed, when deciding fails, and when the side closes; a reloaded Manager page waits for its own answer; unchanged agents keep their identity; interrupted turns are shown.
  • New connection tests: a community already live when watching starts is not renewed; one joined again is.
  • The full unit suite passes locally (11,963 tests). The only failures are the known emoji, status-editor and avatar-picker tests that always fail in this worktree.

🤖 Generated with Claude Code

loganj and others added 2 commits October 28, 2026 12:37
The Manager now sends the viewer's memberships to the Runner as a link
topic, and shows the running agents and interrupted turns the Runner
sends back. Only JSON crosses, over an in-page MessageChannel, as it will
between pages.

The Runner decides again on its own when a record, a turn in progress or
one of its sessions changes, when agent types load, and when the viewer
joins or leaves a community. It also refreshes cached core memory when a
new session follows an earlier state, instead of waiting for the Manager's
binding. A refresh of the agent list settles once the Runner has decided
from it, so a create resolves with the agent running.

Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Logan Johnson <loganj@squareup.com>
…rejoin

A revision now names the Manager page it counts for, so what the Runner
decided for an earlier load of that page never answers a new load's wait.
A closed Manager side no longer waits, and a Runner that fails to decide
still answers, so no caller waits forever.

A community the Runner watched before and joined again is renewed too,
so its agents' cached core memory is read again, as the Manager's binding
did before.

Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant