Skip to content

fix(runner): reject a second turn before touching the sandbox - #6500

Merged
mmabrouk merged 8 commits into
feat/session-controlfrom
feat/session-single-turn-admission
Sep 4, 2026
Merged

fix(runner): reject a second turn before touching the sandbox#6500
mmabrouk merged 8 commits into
feat/session-controlfrom
feat/session-single-turn-admission

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Sep 2, 2026

Copy link
Copy Markdown
Member

Sending a second message while a session is running can make both turns terminate and leave the session unusable.

The runner now reads the first heartbeat admission result before resolving or changing the session environment. A rejected turn stops at the boundary. The active turn keeps its sandbox. The browser keeps the rejected text so the user can resend it.

Issue coverage

Closes the concurrent-send failure described by #6417, #5539, and #5538 for the reject policy. It does not implement Queue or Steer.

Dependencies

The runtime fix is independent of warm Stop and durable commands. The pull request is based on the RFC branch and will need a clean release base before merge.

Tests

A live local-provider test refused the second send in 0.18 seconds while the first turn completed and retained its sandbox.

How to review

  1. Review the first-heartbeat admission order.
  2. Review keepalive-pool behavior after rejection.
  3. Review client conflict handling and text preservation.
  4. Review the execution ID passed to the client.

@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 4, 2026 4:43pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Team

Run ID: 353b2aff-cfa9-4b00-896f-eda2f4f5ac9a

📥 Commits

Reviewing files that changed from the base of the PR and between 69db342 and e4fb78e.

⛔ Files ignored due to path filters (4)
  • api/uv.lock is excluded by !**/*.lock
  • clients/python/uv.lock is excluded by !**/*.lock
  • sdks/python/uv.lock is excluded by !**/*.lock
  • services/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (76)
  • .agents/skills/agent-release-gate/SKILL.md
  • .agents/skills/agent-release-gate/resources/path_triggers.py
  • .agents/skills/agent-release-gate/resources/qa_product.py
  • .agents/skills/agent-release-gate/resources/session_control.py
  • .agents/skills/agent-release-gate/resources/test_qa_product_concurrency.py
  • .agents/skills/agent-release-gate/resources/test_session_control.py
  • .all-contributorsrc
  • README.md
  • api/ee/src/dbs/postgres/sessions/records/dao.py
  • api/entrypoints/worker_streams.py
  • api/oss/src/apis/fastapi/evaluations/router.py
  • api/oss/src/routers/user_profile.py
  • api/oss/src/services/db_manager.py
  • api/oss/src/tasks/asyncio/sessions/records_worker.py
  • api/oss/src/tasks/asyncio/shared/consumer.py
  • api/oss/src/tasks/taskiq/triggers/worker.py
  • api/oss/src/utils/caching.py
  • api/oss/src/utils/crypting.py
  • api/oss/src/utils/env.py
  • api/oss/src/utils/exceptions.py
  • api/oss/src/utils/helpers.py
  • api/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.py
  • api/oss/tests/pytest/unit/sessions/test_records_worker_durability.py
  • api/oss/tests/pytest/unit/sessions/test_watch_publish.py
  • api/oss/tests/pytest/unit/triggers/test_triggers_worker_lifecycle.py
  • api/oss/tests/pytest/unit/utils/test_caching.py
  • api/pyproject.toml
  • clients/python/pyproject.toml
  • docs/design/agent-workflows/documentation/adapters/agenta.md
  • docs/design/agent-workflows/documentation/tools.md
  • docs/design/agent-workflows/interfaces/README.md
  • docs/design/agent-workflows/interfaces/in-service/harness-adapters.md
  • docs/design/agent-workflows/interfaces/public-edge/agent-config-schema.md
  • docs/design/agent-workflows/projects/default-agent-builtins/addendum-always-active.md
  • docs/design/session-control-and-live-events/README.md
  • docs/design/session-control-and-live-events/context.md
  • docs/design/session-control-and-live-events/decisions.md
  • docs/design/session-control-and-live-events/plan.md
  • docs/design/session-control-and-live-events/records-invariants.md
  • docs/design/session-control-and-live-events/requirements.md
  • docs/design/session-control-and-live-events/research.md
  • docs/design/session-control-and-live-events/rfc.md
  • docs/design/session-control-and-live-events/slice-admission.md
  • docs/design/session-control-and-live-events/slice-records-ack.md
  • docs/design/session-control-and-live-events/status.md
  • docs/design/session-control-and-live-events/tonight-handoff.md
  • hosting/kubernetes/helm/Chart.yaml
  • sdks/python/agenta/sdk/agents/adapters/vercel/stream.py
  • sdks/python/oss/tests/pytest/unit/agents/adapters/test_vercel_stream_conformance.py
  • sdks/python/pyproject.toml
  • services/pyproject.toml
  • services/runner/src/engines/sandbox_agent/errors.ts
  • services/runner/src/lifecycle/session-coordinator.ts
  • services/runner/src/protocol.ts
  • services/runner/src/server.ts
  • services/runner/src/sessions/admission.ts
  • services/runner/src/sessions/alive.ts
  • services/runner/tests/unit/session-admission.test.ts
  • services/runner/tests/unit/session-alive-interrupt.test.ts
  • services/runner/tests/unit/session-keepalive-dispatch.test.ts
  • services/runner/tests/unit/session-steer-mount-loss.test.ts
  • web/ee/package.json
  • web/mobile/package.json
  • web/mobile/src/features/chat/Composer.tsx
  • web/mobile/src/features/chat/LiveConversation.tsx
  • web/oss/package.json
  • web/oss/src/components/AgentChatSlice/AgentConversation.tsx
  • web/oss/src/components/AgentChatSlice/components/AgentMessage.tsx
  • web/package.json
  • web/packages/agenta-api-client/package.json
  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts
  • web/packages/agenta-chat/src/model/error.ts
  • web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts
  • web/packages/agenta-chat/tests/unit/model/error.test.ts
  • web/packages/agenta-entities/src/workflow/state/store.ts
  • web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 1 remains after this review.


📝 Summary

Summary by CodeRabbit

  • New Features
    • Concurrent messages are now refused safely while a session turn is running, preserving the active session.
    • Refused messages are restored to the composer and clearly labeled “Message not sent.”
    • Execution turn IDs are now exposed in streamed message metadata.
    • Build-kit settings persist across page reloads and remain separate by revision.
  • Bug Fixes
    • Session records are acknowledged only after successful database commits, with retry and recovery handling.
    • Record retention cleanup and cache invalidation now work correctly.
    • Invalid schedule and missing-user requests return clear errors instead of failing unexpectedly.
  • Documentation
    • Added design and release-gate documentation for session control, live events, and record durability.

Walkthrough

The change adds single-turn session admission, durable Redis record recovery, release-gate session-control validation, client turn correlation, persisted build-kit state, design documentation, utility fixes, tests, and version updates.

Changes

Session control and release validation

Layer / File(s) Summary
Standalone release-gate coverage
.agents/skills/agent-release-gate/*
Adds session-control cells, path triggers, result validation, CLI integration, and standalone-driver tests.
Session admission
services/runner/src/sessions/*, services/runner/src/server.ts, services/runner/src/lifecycle/session-coordinator.ts, services/runner/src/protocol.ts
Refuses concurrent turns before side effects, preserves busy environments, exposes first-heartbeat admission, and emits a live turn event with the admitted execution ID.
Client refusal handling
web/packages/agenta-chat/*, web/oss/src/components/AgentChatSlice/*, sdks/python/agenta/sdk/agents/adapters/vercel/stream.py, web/mobile/src/features/chat/*
Restores refused text, renders “Message not sent” without retry, forwards turnId metadata, and displays held mobile input while model access is blocked.
Admission and stream tests
services/runner/tests/unit/*, api/oss/tests/pytest/unit/sessions/*, web/packages/agenta-chat/tests/*, sdks/python/oss/tests/pytest/unit/agents/adapters/*
Covers refusal, approval resume, fail-open behavior, environment preservation, error classification, queue recovery, and turn metadata ordering.

Record durability

Layer / File(s) Summary
Commit-before-ack processing
api/oss/src/tasks/asyncio/sessions/records_worker.py, api/oss/src/tasks/asyncio/shared/consumer.py, api/entrypoints/worker_streams.py, api/oss/src/utils/env.py
Acknowledges records only after commit or intentional drop, reclaims pending entries, bounds deliveries, and defers drops while the write path is unhealthy.
Retention and durability validation
api/ee/src/dbs/postgres/sessions/records/dao.py, api/oss/tests/pytest/unit/sessions/test_records_worker_durability.py, api/oss/tests/pytest/unit/sessions/test_watch_publish.py
Uses record_id for retention deletion and tests commit, partial failure, reclaim, quota, logging, and notification behavior.

Design and supporting updates

Layer / File(s) Summary
Session-control design set
docs/design/session-control-and-live-events/*
Adds terminology, requirements, decisions, RFC material, research, implementation plans, status, handoff notes, and admission and record-durability slices.
Utility and trigger fixes
api/oss/src/utils/*, api/oss/src/tasks/taskiq/triggers/worker.py, api/oss/src/routers/user_profile.py, api/oss/src/services/db_manager.py, api/oss/src/apis/fastapi/evaluations/router.py, api/oss/tests/pytest/unit/triggers/*, api/oss/tests/pytest/unit/utils/*
Adds explicit validation, handles malformed schedule identifiers, fixes cache wildcard packing, caches Fernet creation, preserves request kwargs, and corrects a comment.
Workflow documentation, versions, and contributor metadata
docs/design/agent-workflows/*, api/pyproject.toml, clients/python/pyproject.toml, sdks/python/pyproject.toml, services/pyproject.toml, hosting/kubernetes/helm/Chart.yaml, web/*/package.json, .all-contributorsrc, README.md
Updates runner paths and built-in-tool documentation, increments package and chart versions to 0.114.8, and adds a contributor entry.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🟠 High · up to e4fb7

An oversized session record can cause later valid history records to be discarded, creating a material data-loss risk. Malformed trigger payloads may also escape validation, and some refusal envelopes can lose their stable client-visible code. These issues should be fixed before merge.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.41% which is insufficient. The required threshold is 60.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 204 functions across 44 files. (31 skippe… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: rejecting a second session turn before the runner touches the sandbox.
Description check ✅ Passed The description is directly related to the changeset. It explains the admission check, sandbox preservation, client behavior, scope, tests, and review focus.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 29.41% which is insufficient. The required threshold is 60.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 204 functions across 44 files. (31 skipped: 31 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/session-single-turn-admission

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] fix(runner): admit one turn per session before touching the sandbox pool fix(runner): reject a second turn before touching the sandbox 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-6500-agenta-docs-preview.mahmoud-637.workers.dev/docs
Inspect Actions run
Commit e4fb78eeb0137b091c951d05cde5ed22a0a97c0a

This comment updates in place on every push.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Preview URL https://gateway-pr-6500.up.railway.app/w
Project agenta-oss-clone-spike
Image tag pr-6500-4171039
Status Deployed
Railway logs Open logs
Workflow logs View workflow run
Updated at 2026-09-04T16:53:56.534Z

@mmabrouk
mmabrouk changed the base branch from agent/session-execution-rfc to main September 4, 2026 07:04

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mmabrouk mmabrouk added lgtm This PR has been approved by a maintainer 1 points Created by Linear-GitHub Sync labels Sep 4, 2026
A second user message on a session with a turn in flight killed both turns
and left the session locked until the 30-minute lease expired (#6417, #5539,
#5538). The platform's arbiter was always correct; the runner acted before
reading its answer.

The runner starts a turn's alive watchdog before it touches any sandbox, and
that watchdog's first heartbeat is an atomic `nx` acquire of the session's
`alive` lock in the API. When a second turn lost that acquire the API already
answered `is_current_turn: false`. The runner read it only as "abort later",
then walked into the keepalive pool, found the first turn's environment busy,
and destroyed it. Turn one lost its sandbox mid-answer and turn two aborted
on its own watchdog signal.

Read the answer before acting:

- `startAliveWatchdog` now reports `admitted`, the first beat's answer only. A
  later `is_current_turn: false` stays a cancel and keeps travelling the
  `onInterrupted` -> abort path. A network or HTTP failure still fails open.
- `server.ts` stops a refused turn at the edge, before the interaction sweep,
  before the persisting emitter, and before `run()`. Nothing is persisted, so
  the refused message never enters the session's history and the client can
  keep the user's text. The refusal streams as an `error` event carrying the
  new `session_turn_in_use` code plus a failed terminal result.
- The keepalive coordinator no longer evicts a `busy` entry. That branch was
  the destruction half of the bug. It now refuses, which is the backstop for
  the window admission leaves open when the API is unreachable. A `destroyed`
  entry still evicts and cold-starts, because nothing is in flight on it.

Queue and steer are out of scope: both need a durable pending-input store,
while refusing needs none. This is the `on_busy: reject` policy only.

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

The runner now refuses a message sent while another turn is already running
on the same session (#6417, #5539, #5538). A naive refusal is worse than the
bug for the person typing: the composer clears synchronously on submit, so
the text they wrote is gone and there is no way to get it back.

- `useAgentChatQueue` remembers the message it handed to `sendQueued`, both on
  the immediate path and on a queue release, and hands it back once through
  `takeLastSent`. A queued message never needed this; it is already in the
  queue and rendered by the dock. An immediately-sent one had nowhere to live.
  It is deliberately NOT re-queued: the queue releases on a settled "error"
  status, which for a refusal would re-send and be refused again in a loop.
- `AgentConversation` puts that text back into the composer when the stream
  error is the refusal. The rAF mirrors the edit-stash restore beside it,
  because the editor clears itself after `onSubmit` returns.
- The bubble says "Message not sent" instead of "The agent run failed", and
  offers no retry: nothing failed, and the text is already back in the box.
- `parseAgentRunError` carries the stable class for the refusal, so the code
  reaches the bubble whether it arrives on the message part or the error.

The refusal message is the contract with the runner. It is produced once, in
`services/runner/src/sessions/admission.ts`, and reaches the browser verbatim:
the SDK keeps a clean one-line runner error unchanged and the Vercel egress
passes it through as `errorText`. Both constants must stay byte-identical.

Mobile shares the queue hook and the error model but has its own composer and
error effect, so it gets the refusal class without the text restore.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV
The runner's edge now acts on the first heartbeat's `is_current_turn`, so the
three answers that decide a session's behaviour need their own coverage. The
API code is unchanged; these lock the contract the runner reads.

- A second turn arriving while a DIFFERENT turn holds `running` is refused,
  and the running turn's alive lock is untouched.
- A refused turn's end beat (its watchdog release) cannot clear the live
  turn's `running`, because the release is owner-scoped.
- An approval resume IS admitted while the previous turn is parked. `alive`
  alone cannot tell a park from a live turn; the absent `running` owner is
  what distinguishes them, and getting this wrong would stop every approval
  in the product from resuming.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV
What happens today with `path:line` evidence, what the three commits change
and why, the live test protocol and its results, what queue and steer still
need, and five open questions.

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

No first-party client can send `expected_execution_id` on the public Cancel
today, because the runner mints the turn id per execution and never tells
anyone. A Stop can therefore only mean "whatever is running now", never "the
turn I was watching".

The `start` frame cannot carry it. It is built and sent by the SDK's Vercel
egress before the runner replies at all (`vercel/stream.py`, the `start` yield
is the first statement of the projection), so a runner-minted id does not
exist yet at that point. Putting it there would mean moving the mint out of
the runner and threading a new correlation id through the normalizer, the
response models, and the routing layer for every workflow, not just agents.

Use the earliest frame that CAN carry it instead:

- The runner emits `{type: "turn", turnId}` as the first event of a
  session-owned run, immediately after admission. It goes through `liveEmit`,
  never the persisting emitter, because it is transport correlation and must
  not become a session record.
- The Vercel egress forwards it unchanged as `data-agent-turn`, in both the
  live and dev-twin projections. A missing, empty or non-string id emits no
  part, so a client is never handed a guard value that names nothing.

A refused turn emits none: it runs nothing, so there is nothing to stop.

Verified live: the frame arrives third, after `start` and `start-step` and
before any content, and its id is the one holding the session's alive lock.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV
Adds the section on why the `start` frame cannot carry a runner-minted turn id
and what carries it instead, with the live evidence. Updates the test table and
notes the keepalive test that was passing for the wrong reason.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV
Follow-up to ce0f1e1, which put the runner's admitted turn id on a
`data-agent-turn` part. Message metadata is the better carrier and the one
asked for: a client reads `message.metadata.turnId`, beside the `sessionId`
the `start` frame already sets and the `traceId`/`usage` the `finish` frame
adds, instead of scanning parts for it.

The `start` frame still cannot carry it. That frame is emitted before the
runner replies at all, so a runner-minted id does not exist yet. A
`message-metadata` chunk is the same channel one frame later, and it is a
first-class chunk in the pinned `ai@6.0.0-beta.150`.

Safe because the AI SDK MERGES metadata rather than replacing it
(`mergeObjects`), so the `finish` frame's own metadata lands beside the turn
id rather than over it. A test pins that: the two carry disjoint keys and the
turn id is written first. If the SDK ever changed to replace, a client would
lose the id exactly when a late Stop needs it.

Replaces the `data-agent-turn` part rather than adding to it. One fact should
travel one channel, and nothing consumes the part yet.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV
Records why the `start` frame cannot carry a runner-minted id, why a
`message-metadata` chunk one frame later can, and the merge behaviour that
makes it survive the `finish` frame. Live evidence updated to the new frame.

Claude-Session: https://claude.ai/code/session_01GAqSs7fw6QRi2n1ZJ2tmAV
@mmabrouk
mmabrouk force-pushed the feat/session-single-turn-admission branch from 141ebb7 to e4fb78e Compare September 4, 2026 16:41
@mmabrouk
mmabrouk changed the base branch from main to feat/session-control September 4, 2026 16:41
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
7 out of 8 committers have signed the CLA.

✅ tomatotomata
✅ Aman-goel-04
✅ shafeeq27edu-ai
✅ Christian-Sidak
✅ ashrafchowdury
✅ mmabrouk
✅ oforiwaasam
❌ allcontributors[bot]
You have signed the CLA already but the status is still pending? Let us recheck it.

@mmabrouk
mmabrouk merged commit 17787d8 into feat/session-control Sep 4, 2026
47 of 49 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/packages/agenta-chat/src/model/error.ts (1)

101-101: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve string envelope codes.

When status.code is "session_turn_in_use", Line 101 drops it. Return valid string codes too.

Proposed fix
-            return {message, code: typeof status?.code === "number" ? status.code : undefined}
+            return {
+                message,
+                code:
+                    typeof status?.code === "number" || typeof status?.code === "string"
+                        ? status.code
+                        : undefined,
+            }
🧹 Nitpick comments (2)
web/packages/agenta-entities/src/workflow/state/store.ts (1)

1469-1486: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Condense the multi-line comments in the chat queue, runner-error, and build-kit storage test files. web/AGENTS.md applies to all web/packages files. Keep comments to one short line, or at most two sentences for a genuinely surprising constraint. These blocks exceed that limit; retain only the essential rationale.

web/mobile/src/features/chat/LiveConversation.tsx (1)

150-151: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Shorten the added code comments.

web/AGENTS.md applies to all listed web/**/*.ts and web/**/*.tsx files. Keep each comment to one short line; retain only genuinely surprising constraints, limited to one or two sentences.


ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Team

Run ID: 353b2aff-cfa9-4b00-896f-eda2f4f5ac9a

📥 Commits

Reviewing files that changed from the base of the PR and between 69db342 and e4fb78e.

⛔ Files ignored due to path filters (4)
  • api/uv.lock is excluded by !**/*.lock
  • clients/python/uv.lock is excluded by !**/*.lock
  • sdks/python/uv.lock is excluded by !**/*.lock
  • services/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (76)
  • .agents/skills/agent-release-gate/SKILL.md
  • .agents/skills/agent-release-gate/resources/path_triggers.py
  • .agents/skills/agent-release-gate/resources/qa_product.py
  • .agents/skills/agent-release-gate/resources/session_control.py
  • .agents/skills/agent-release-gate/resources/test_qa_product_concurrency.py
  • .agents/skills/agent-release-gate/resources/test_session_control.py
  • .all-contributorsrc
  • README.md
  • api/ee/src/dbs/postgres/sessions/records/dao.py
  • api/entrypoints/worker_streams.py
  • api/oss/src/apis/fastapi/evaluations/router.py
  • api/oss/src/routers/user_profile.py
  • api/oss/src/services/db_manager.py
  • api/oss/src/tasks/asyncio/sessions/records_worker.py
  • api/oss/src/tasks/asyncio/shared/consumer.py
  • api/oss/src/tasks/taskiq/triggers/worker.py
  • api/oss/src/utils/caching.py
  • api/oss/src/utils/crypting.py
  • api/oss/src/utils/env.py
  • api/oss/src/utils/exceptions.py
  • api/oss/src/utils/helpers.py
  • api/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.py
  • api/oss/tests/pytest/unit/sessions/test_records_worker_durability.py
  • api/oss/tests/pytest/unit/sessions/test_watch_publish.py
  • api/oss/tests/pytest/unit/triggers/test_triggers_worker_lifecycle.py
  • api/oss/tests/pytest/unit/utils/test_caching.py
  • api/pyproject.toml
  • clients/python/pyproject.toml
  • docs/design/agent-workflows/documentation/adapters/agenta.md
  • docs/design/agent-workflows/documentation/tools.md
  • docs/design/agent-workflows/interfaces/README.md
  • docs/design/agent-workflows/interfaces/in-service/harness-adapters.md
  • docs/design/agent-workflows/interfaces/public-edge/agent-config-schema.md
  • docs/design/agent-workflows/projects/default-agent-builtins/addendum-always-active.md
  • docs/design/session-control-and-live-events/README.md
  • docs/design/session-control-and-live-events/context.md
  • docs/design/session-control-and-live-events/decisions.md
  • docs/design/session-control-and-live-events/plan.md
  • docs/design/session-control-and-live-events/records-invariants.md
  • docs/design/session-control-and-live-events/requirements.md
  • docs/design/session-control-and-live-events/research.md
  • docs/design/session-control-and-live-events/rfc.md
  • docs/design/session-control-and-live-events/slice-admission.md
  • docs/design/session-control-and-live-events/slice-records-ack.md
  • docs/design/session-control-and-live-events/status.md
  • docs/design/session-control-and-live-events/tonight-handoff.md
  • hosting/kubernetes/helm/Chart.yaml
  • sdks/python/agenta/sdk/agents/adapters/vercel/stream.py
  • sdks/python/oss/tests/pytest/unit/agents/adapters/test_vercel_stream_conformance.py
  • sdks/python/pyproject.toml
  • services/pyproject.toml
  • services/runner/src/engines/sandbox_agent/errors.ts
  • services/runner/src/lifecycle/session-coordinator.ts
  • services/runner/src/protocol.ts
  • services/runner/src/server.ts
  • services/runner/src/sessions/admission.ts
  • services/runner/src/sessions/alive.ts
  • services/runner/tests/unit/session-admission.test.ts
  • services/runner/tests/unit/session-alive-interrupt.test.ts
  • services/runner/tests/unit/session-keepalive-dispatch.test.ts
  • services/runner/tests/unit/session-steer-mount-loss.test.ts
  • web/ee/package.json
  • web/mobile/package.json
  • web/mobile/src/features/chat/Composer.tsx
  • web/mobile/src/features/chat/LiveConversation.tsx
  • web/oss/package.json
  • web/oss/src/components/AgentChatSlice/AgentConversation.tsx
  • web/oss/src/components/AgentChatSlice/components/AgentMessage.tsx
  • web/package.json
  • web/packages/agenta-api-client/package.json
  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts
  • web/packages/agenta-chat/src/model/error.ts
  • web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts
  • web/packages/agenta-chat/tests/unit/model/error.test.ts
  • web/packages/agenta-entities/src/workflow/state/store.ts
  • web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 1 remains after this review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
web/packages/agenta-chat/src/model/error.ts (1)

101-101: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve string envelope codes.

When status.code is "session_turn_in_use", Line 101 drops it. Return valid string codes too.

Proposed fix
-            return {message, code: typeof status?.code === "number" ? status.code : undefined}
+            return {
+                message,
+                code:
+                    typeof status?.code === "number" || typeof status?.code === "string"
+                        ? status.code
+                        : undefined,
+            }
api/oss/src/tasks/asyncio/sessions/records_worker.py (1)

254-255: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Process oversized entries before reclaiming later records.

When an individual payload exceeds max_batch_mb, this break leaves it and all later entries pending. StreamConsumer.reclaim_batch calls XCLAIM before process_batch, which increments every claimed entry’s delivery count. With a healthy write path, the reclaim pass can drop later valid records at max_deliveries without an append attempt. Handle the oversized entry as a singleton or dead-letter it, reset the byte accounting, and continue with later entries.

api/oss/src/tasks/taskiq/triggers/worker.py (1)

109-111: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Normalize project_id before UUID parsing.

If a task payload provides a non-string project_id, UUID(project_id) can raise AttributeError or TypeError, which except ValueError does not catch. Parse UUID(str(project_id)) and add a non-string payload test.

docs/design/session-control-and-live-events/rfc.md (1)

238-242: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Sensitive Data Exposure (CWE-319): Cleartext Transmission of Sensitive Information

Reachability: Internal · Exploitability: Difficult

Require encrypted control delivery.

Require authenticated encryption on every runner-to-API hop. Use HTTPS with certificate validation or mTLS. Reject HTTP endpoints. If redirects are supported, validate the destination and do not forward credentials to another authority.

🧹 Nitpick comments (2)
web/packages/agenta-entities/src/workflow/state/store.ts (1)

1469-1486: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Condense the multi-line comments in the chat queue, runner-error, and build-kit storage test files. web/AGENTS.md applies to all web/packages files. Keep comments to one short line, or at most two sentences for a genuinely surprising constraint. These blocks exceed that limit; retain only the essential rationale.

web/mobile/src/features/chat/LiveConversation.tsx (1)

150-151: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Shorten the added code comments.

web/AGENTS.md applies to all listed web/**/*.ts and web/**/*.tsx files. Keep each comment to one short line; retain only genuinely surprising constraints, limited to one or two sentences.


ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Team

Run ID: 353b2aff-cfa9-4b00-896f-eda2f4f5ac9a

📥 Commits

Reviewing files that changed from the base of the PR and between 69db342 and e4fb78e.

⛔ Files ignored due to path filters (4)
  • api/uv.lock is excluded by !**/*.lock
  • clients/python/uv.lock is excluded by !**/*.lock
  • sdks/python/uv.lock is excluded by !**/*.lock
  • services/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (76)
  • .agents/skills/agent-release-gate/SKILL.md
  • .agents/skills/agent-release-gate/resources/path_triggers.py
  • .agents/skills/agent-release-gate/resources/qa_product.py
  • .agents/skills/agent-release-gate/resources/session_control.py
  • .agents/skills/agent-release-gate/resources/test_qa_product_concurrency.py
  • .agents/skills/agent-release-gate/resources/test_session_control.py
  • .all-contributorsrc
  • README.md
  • api/ee/src/dbs/postgres/sessions/records/dao.py
  • api/entrypoints/worker_streams.py
  • api/oss/src/apis/fastapi/evaluations/router.py
  • api/oss/src/routers/user_profile.py
  • api/oss/src/services/db_manager.py
  • api/oss/src/tasks/asyncio/sessions/records_worker.py
  • api/oss/src/tasks/asyncio/shared/consumer.py
  • api/oss/src/tasks/taskiq/triggers/worker.py
  • api/oss/src/utils/caching.py
  • api/oss/src/utils/crypting.py
  • api/oss/src/utils/env.py
  • api/oss/src/utils/exceptions.py
  • api/oss/src/utils/helpers.py
  • api/oss/tests/pytest/unit/sessions/test_heartbeat_is_current_turn.py
  • api/oss/tests/pytest/unit/sessions/test_records_worker_durability.py
  • api/oss/tests/pytest/unit/sessions/test_watch_publish.py
  • api/oss/tests/pytest/unit/triggers/test_triggers_worker_lifecycle.py
  • api/oss/tests/pytest/unit/utils/test_caching.py
  • api/pyproject.toml
  • clients/python/pyproject.toml
  • docs/design/agent-workflows/documentation/adapters/agenta.md
  • docs/design/agent-workflows/documentation/tools.md
  • docs/design/agent-workflows/interfaces/README.md
  • docs/design/agent-workflows/interfaces/in-service/harness-adapters.md
  • docs/design/agent-workflows/interfaces/public-edge/agent-config-schema.md
  • docs/design/agent-workflows/projects/default-agent-builtins/addendum-always-active.md
  • docs/design/session-control-and-live-events/README.md
  • docs/design/session-control-and-live-events/context.md
  • docs/design/session-control-and-live-events/decisions.md
  • docs/design/session-control-and-live-events/plan.md
  • docs/design/session-control-and-live-events/records-invariants.md
  • docs/design/session-control-and-live-events/requirements.md
  • docs/design/session-control-and-live-events/research.md
  • docs/design/session-control-and-live-events/rfc.md
  • docs/design/session-control-and-live-events/slice-admission.md
  • docs/design/session-control-and-live-events/slice-records-ack.md
  • docs/design/session-control-and-live-events/status.md
  • docs/design/session-control-and-live-events/tonight-handoff.md
  • hosting/kubernetes/helm/Chart.yaml
  • sdks/python/agenta/sdk/agents/adapters/vercel/stream.py
  • sdks/python/oss/tests/pytest/unit/agents/adapters/test_vercel_stream_conformance.py
  • sdks/python/pyproject.toml
  • services/pyproject.toml
  • services/runner/src/engines/sandbox_agent/errors.ts
  • services/runner/src/lifecycle/session-coordinator.ts
  • services/runner/src/protocol.ts
  • services/runner/src/server.ts
  • services/runner/src/sessions/admission.ts
  • services/runner/src/sessions/alive.ts
  • services/runner/tests/unit/session-admission.test.ts
  • services/runner/tests/unit/session-alive-interrupt.test.ts
  • services/runner/tests/unit/session-keepalive-dispatch.test.ts
  • services/runner/tests/unit/session-steer-mount-loss.test.ts
  • web/ee/package.json
  • web/mobile/package.json
  • web/mobile/src/features/chat/Composer.tsx
  • web/mobile/src/features/chat/LiveConversation.tsx
  • web/oss/package.json
  • web/oss/src/components/AgentChatSlice/AgentConversation.tsx
  • web/oss/src/components/AgentChatSlice/components/AgentMessage.tsx
  • web/package.json
  • web/packages/agenta-api-client/package.json
  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts
  • web/packages/agenta-chat/src/model/error.ts
  • web/packages/agenta-chat/tests/unit/hooks/useAgentChatQueue.test.ts
  • web/packages/agenta-chat/tests/unit/model/error.test.ts
  • web/packages/agenta-entities/src/workflow/state/store.ts
  • web/packages/agenta-entities/tests/unit/agent-build-kit-ui-state-atom.test.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 1 remains after this review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1 points Created by Linear-GitHub Sync lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants