Skip to content

docs(sessions): define durable commands and replaceable control delivery - #6497

Open
mmabrouk wants to merge 3 commits into
agent/session-execution-rfcfrom
spike/session-durable-commands-design
Open

docs(sessions): define durable commands and replaceable control delivery#6497
mmabrouk wants to merge 3 commits into
agent/session-execution-rfcfrom
spike/session-durable-commands-design

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Sep 2, 2026

Copy link
Copy Markdown
Member

Session commands need durable acceptance and a transport-independent route to the runner.

This design specifies the session command table, guarded state transitions, claim recovery, direct API-to-runner delivery, and runner-initiated long polling. The RFC now selects direct delivery for version one. Long polling is parked in Linear AGE-4253.

Issue coverage

Design only. It supports the Stop, concurrent-send, Queue, Steer, and approval issue groups but closes no runtime issue.

Dependencies

This pull request depends only on the session RFC branch. Runtime implementation is in #6503.

How to review

  1. Review the command states and SQL transition guards.
  2. Review direct-delivery failure recovery.
  3. Treat long polling as parked design, not version-one scope.
  4. Review the public and private route boundaries.

Work package B of the session-control RFC. An implementation-ready design for
reliable API-to-runner commands, version one, with Cancel as the only command
kind.

- Traces today's Stop path and its 0 to 30 second delay chain, with path:line.
- Defines the `session_commands` table, its columns by semantic role, indexes,
  two-layer idempotency, and retention.
- Defines the pending/claimed/applied/obsolete machine with the compare-and-set
  guard for each transition, so two API replicas cannot both claim or settle.
- Defines the claim lease, expiry and re-delivery, and runner-side deduplication.
- Defines the long-poll and outcome routes, their runner-token authentication,
  the hold, and the backoff table.
- Defines the heartbeat fallback field and how the runner deduplicates.
- Walks Stop end to end plus five failure cases, holding Redis ownership until
  settlement and leaving `alive` in place so the session resumes warm.
- Adds the control-delivery port in Python and TypeScript, a seven-PR migration
  sequence, and the unit, integration and live-stack test plan.

`api-design.md` carries only the version-one route contracts, in the house DTO
style, after a field-by-field interface review.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV
Answers sections 3 and 4 of the architecture review.

- H-2: the claim loop is session-scoped and process-level, alive for the
  session's warm lifetime. The runner declares the sessions it holds, taken from
  the execution registry and the keep-alive pool keys, so a parked approval keeps
  a channel after its heartbeat stops. Stop cancels that session's pending
  interaction, the call the kill route already makes.
- H-3: three guards. The target is pinned at admission, the runner refuses to
  abort an execution that started after the command's created_at, and first-party
  clients always send expected_execution_id.
- H-4: settlement keys off heartbeat age, not the 3600 second Redis TTL. Lease is
  90 seconds, three heartbeat intervals. Names the watchdog branch as the
  settlement owner and states the one-writer rule.
- H-5: the applied-command set lives beside the session pool, outlives a loop
  restart, and re-applying only re-sends the acknowledgement.
- H-6: claims are queries over durable state, never a cursor.
- Interfaces: target, input, policy and delivery groups in the envelope; no
  owner_replica_id and no runner_url in the record.

Adds a direct-call adapter section. The runner gains POST /cancel beside
POST /kill and the API a client beside kill_runner_sandbox, both small, both
behind the same port and settling through the same outcome route. States what
the durable record adds over a bare direct call and what breaks with two
replicas, so the default adapter is a one-line choice.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV
…uard

Two amendments from the team lead's review.

Section 9 becomes "the direct-call adapter as an alternative first adapter",
the review's 8b. It now states the insert-then-call ordering, the parked-approval
lookup through SessionPool.awaitingApproval that both adapters need, the three
things the adapter cannot do, and a recommendation to build it first.

The wrong-replica failure is made loud without a census: a not_held answer for a
session whose row is alive with a fresh heartbeat is the mis-route and nothing
else produces it, so it logs, counts, and settles as lost rather than
not_running. A required single-replica flag and a heartbeat-fed replica census
are offered as optional preventive checks. Retrying across the load balancer is
rejected.

The stale-Stop guard becomes four guards, led by an API-side comparison of the
command's arrival time with the current turn's start time. There is nowhere to
read that time today: updated_at is the heartbeat, runner-minted turn ids are
uuid4, the Redis value is compared whole by the release script, and the
session_turns append is fire-and-forget. So add session_streams.turn_started_at,
stamped by the same statement that writes turn_id, guarded by a CASE so repeated
heartbeats do not move it. A null start time does not fire the guard; the
runner's in-memory check catches that case. The outcome value is
superseded_by_newer_turn.

Section 5 states that a claim is a query over durable state with no cursor, so a
command created while nothing was listening is returned by the next claim.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV
@vercel

vercel Bot commented Sep 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
agenta-documentation Ready Ready Preview Sep 2, 2026 10:15pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • release/.*

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Team

Run ID: 72271308-beba-4031-a7d1-5cc212824094

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mmabrouk mmabrouk changed the title [overnight] docs(sessions): durable command and control-delivery design (Spike B) docs(sessions): define durable commands and replaceable control delivery Sep 3, 2026
@mmabrouk
mmabrouk marked this pull request as ready for review September 3, 2026 11:15
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

📘 Docs preview

Status ✅ Ready
Preview https://pr-6497-agenta-docs-preview.mahmoud-637.workers.dev/docs
Inspect Actions run
Commit 86281fa313c76b93be411429e5d92dd4fb34a5ed

This comment updates in place on every push.

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