Appearance
LiveKit Intervention Lifecycle
This document defines how a LiveKit-backed runtime creates and resolves OpenOrca interventions.
Creation
An intervention.created event is emitted when the LiveKit-backed application logic enters a pending human decision state, such as:
- an approval gate before a sensitive tool call
- a permission request for an external system
- a cost or policy threshold requiring operator review
- a clarification request that blocks continued execution
The bridge should create a durable intervention record keyed by:
interventionId: the OpenOrca-facing identifiersessionId: the LiveKit session or room identifierjobIdorworkflowId: the user-visible unit of workgateId: the underlying approval checkpoint identifieragentId: the participant or worker identity responsible for the request
Pending State Storage
Store pending decisions in a bridge-side durable store so intervention state survives bridge restarts and duplicate UI requests. These bridge-local fields are not part of the public Intervention interface exposed to the dashboard; they remain internal backend state used to manage resumes and retries. The stored record should include:
- current status:
pending,approved,denied,deferred,expired, ororphaned - timestamps for create, last update, and resolution
- the last known LiveKit session and job state
- any resume payload needed to continue the workflow
Resolution API Behavior
When the frontend sends POST /openorca/interventions/resolve, the bridge should translate the action as follows:
approve
- mark the intervention as approved if it is still pending
- send the corresponding approval or resume signal into the LiveKit-backed workflow
- emit
intervention.resolved - emit follow-up task or action events as the job resumes
deny
- mark the intervention as denied if it is still pending
- send the rejection or cancellation signal into the LiveKit-backed workflow
- emit
intervention.resolved - update the affected task to
failedor another terminal state chosen by the backend
later
- mark the intervention as deferred
- keep the underlying job paused or parked
- emit
intervention.resolvedonly if the UI should remove the current card and rely on a later re-created intervention - otherwise keep the intervention in the snapshot and refresh its timestamp/context to show it is still pending
Recommended default: treat later as a deferral that keeps the intervention visible in future snapshots, unless product requirements prefer clearing the queue temporarily.
Correlation Rules
interventionIdmust be unique and stable for the life of the decision.- The bridge must maintain a reversible mapping from
interventionIdto the underlying LiveKit session, task, and gate identifiers. - The affected
AgentTask.statusshould move towaiting_approvalwhile the intervention is pending. - The affected
ClawAgent.statusshould move tointervention_requiredwhile the intervention is pending.
Retry and Duplicate Handling
- Resolution requests must be idempotent by
interventionIdand final action. - Repeating the same final action should return success without re-sending the underlying LiveKit command.
- Conflicting follow-up decisions on an already resolved intervention should return a conflict response and leave the original decision intact.
- If the bridge cannot reach the LiveKit runtime after accepting a decision, store a retryable pending-delivery state and surface a degraded runtime status.
Stale Interventions
If the underlying LiveKit session or task has already ended:
- mark the intervention as
expiredororphaned - reject new decisions with a clear response message
- emit a task update reflecting the terminal session state if one is not already present
- remove the intervention from subsequent snapshots after the terminal state is observable to the operator
UI Expectations
When an intervention is stale or no longer actionable, the UI should show that the run already ended and that the pending decision can no longer be applied. The bridge should communicate that via the resolution response body and follow-up snapshot or task updates.