Tags: 🔴 BLOCKER (FE can't proceed) · 🟡 CONFIRM (FE can build once the contract is agreed). Ordered by how much FE work each unblocks.
PR #4916 shipped the durable read plane (transcripts) live — FE step 1 (server-backed history) is wired and working. The control planes (interactions/HITL, streams/live-run) are scaffolded in the API but not wired to the runner, so the FE-side API surface is built and parked. The points below are what it takes to light those up.
- Payload stability — is
payloadguaranteed 1:1 with the ACPAgentEventunion (services/agent/src/protocol.ts)? Any event types the FE should expect that aren't in that union? - Ordering & pagination — is
queryTranscriptsalways ordered ascending by uuid7id?SessionTranscriptQueryRequestonly hassession_id— is there a result cap / cursor for long sessions, or does it return the whole log? sendervalues — confirm the exact set (user/runner/system?). FE groups messages by this.- User-turn persistence — is the user's own message persisted as a transcript event
(
sender=user), and with what payload shape (plain text? multimodal/files)? Determines how we replay user turns. - Deltas vs coalesced — does the transcript store
message_start/delta/endrows or only the coalescedmessage? (FE handles both; just want to know.) - 64KB truncation — payloads over the cap become
{"_truncated": true}. How should the FE render a truncated event?
- Confirm FE treats
/sessions/statesas read-only (onlygetStatefor sandbox awareness) and must neversetState(data)(it'd clobber the runner'sSessionRecord). Correct? - Is sandbox resume fully automatic by
session_idonce a run goes through the runner — i.e. the FE does nothing? Or is there anything FE-side (e.g.setStateSandboxId)? - Is there a state value worth surfacing in the UI (e.g. "sandbox alive")?
- 🔴 Rows aren't created — the runner emits
interaction_requestto the transcript but does not create aSessionInteractionrow, soqueryInteractionsis empty for real runs. Who creates the row, and when (should be on park)? - 🔴 Respond doesn't transition status —
respondInteractionenqueues a re-invoke but leavesstatus.code = pendingforever (only the admintransitionendpoint flips it). Should respond transition pending→resolved/denied? - ID correlation — transcript
interaction_request.idappears to map toSessionInteraction.token, not.id(unique onproject+session+token). Confirm the intended FE flow: query by token → respond by row id? Or will the transcript event carry the interaction row id directly? - Answer shape —
respondInteraction.answeris an unvalidatedDict. What exact shape for approve vs deny ({approved: true/false}?), and is there an "always allow" option — where is it stored/honored on resume? - Resume-after-respond — responding does not continue the run inline; does the FE
then call
invokeStream? Confirm the intended sequence (and whether it only applies to the streams path). - Scope — confirm v1 =
user_approvalonly; FE keepsuser_input/tool_callgated off.
- 🔴 invoke is a stub —
SessionStreamsService.invoke/_start_run(api/oss/src/core/sessions/streams/service.py) only acquires Redis locks + writes aSessionStream/session_runnersrow; it does not invoke the runner and streams nothing. - 🔴 No stream-return path — there's no SSE/attach endpoint delivering v6 chunks.
The "watch live run" path is unspecified + NOT STARTED
(
docs/designs/sessions/streams/tasks.md). What's the planned transport — aGET /sessions/streams/attachreturningtext/event-streamv6 chunks? WebSocket? The FEuseChattransport needs arequest → streamed-response, so we need the endpoint + content-type. - Replace vs complement — the FE currently streams fine from the runner service
(
/api/agent/chat). Does the streams model replace that, or is it invoke = coordination layered on top of the existing runner stream? This decides whether step 4 is a transport rewire or just adding force/attach/detach/liveness around the current path. - Mode semantics — when wired, what should the FE do per
SessionInvokeResponseModel.mode(send/steer/cancel/attach/detach) and forforce/detached? - Timeline — the brief frames streams as the multi-replica-correct path; what's the rough sequencing for 16–18?
- FE history (the picker) is localStorage-only, so a session this browser never ran won't
appear. Transcripts is per-session (no list). Is there / will there be a
sessions-list endpoint (by project/app), or should FE keep using the observability
ag.session.id-off-traces aggregation? Align on the canonical "list sessions" source.
- Is
client.mounts.*(agent working-dir file CRUD) actually live/wired, and what's the priority? (FE panel is optional/last.)
- What's the canonical way to get a populated local env — which compose profile +
entrypoints (e.g.
worker_transcripts) must be running forqueryTranscriptsto return rows? Several endpoints depend on a runner/worker rebuild. - The design docs are labelled "draft / not implemented." Can they be marked with what's actually live so the FE has a contract source of truth?
The full @agenta/entities/session surface — querySessionTranscripts (in use), plus
parked getSessionState, queryInteractions / fetchInteraction / respondInteraction,
and queryStreams / getStreamLiveness / invokeSessionStream — all matching the
generated client, ready to wire the day each plane lands.