opbox

The agenttask.* family (19 verbs). Every verb enters through the one front door: it is capability-checked, permission-checked, scope-checked and audited before it runs (see Security & permissions). Each entry below lists its capability, risk class (which fixes the minimum autonomy level), the minimum caller permission, its availability tier, whether it is idempotent, and any outbound egress.

Cancelagenttask.cancel

PropertyValue
Capabilityagenttask.write
Risk classSensitive - autonomy L2
Min. permissionAdmin
AvailabilityOn demand (MCP tier 2)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

([2026] VJS-CC-OPBOX 55). Cancel a NON-TERMINAL agent task (QUEUED/LEASED/ESCALATED) - the operator/parent-kill path the break-glass + bulk-cancel sites compose (SEC-F08: org.freeze/org.lockdown abort in-flight work via agenttask.cancel). A guarded CAS WHERE status NOT IN ('DONE','FAILED','CANCELLED') flips status->CANCELLED + stamps finished_at (the ck_agent_task_terminal backstop: finished_at is set IFF terminal) and clears the lease lifecycle (a cancelled task holds no lease). An ALREADY-TERMINAL task (DONE/FAILED/CANCELLED) is refused (fail-closed Conflict, INV-3 - you cannot cancel completed/failed/already-cancelled work; CANCELLED is itself terminal so a re-cancel is the same Conflict, never a silent no-op). One AuditEvent (the dispatch appends it, INV-8). Workspace-scoped (RLS + the explicit predicate).

Input { taskId } (fields ending in ? are optional)

Call POST /v/agenttask.cancel with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool agenttask.cancel.

Checkpointagenttask.checkpoint

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

Persists the durable agent state + renews the lease (heartbeat). Only the LEASE HOLDER may checkpoint (the guard pins lease_owner + status=‘LEASED’), so a stale/foreign worker cannot overwrite a re-leased task’s state. An optional terminal status (DONE|FAILED) marks completion, stamping finished_at (INV-3) - the ONE write path to a terminal task. A non-terminal checkpoint loops the task back to LEASED with a fresh lease.

CC-OPBOX 32 B3 - two changes on the non-terminal renewal path: • heartbeat-only - checkpoint is now OPTIONAL: a pure lease renewal with no payload keeps the existing checkpoint (the worker is alive but has nothing new to persist). A terminal call still requires nothing extra; only the prior unconditional “requires a checkpoint” BadInput is lifted. • LEASE_RUNAWAY guard - each non-terminal renewal increments lease_extensions; once it would exceed MAX_LEASE_EXTENSIONS (4) OR now()-first_leased_at exceeds LEASE_WALLCLOCK_CAP_SECONDS the renewal is REFUSED and the task is FORCE-REQUEUED (status=QUEUED, lease lifecycle cleared) as a fail-closed LEASE_RUNAWAY Conflict - a wedged worker cannot hold a task forever (the cooperative floor; the re-drive resumes from the last persisted checkpoint). A TERMINAL checkpoint is exempt (it ENDS the lease; the count is irrelevant) and never trips the guard.

Input { taskId, checkpoint?, status?, lastError? } (fields ending in ? are optional)

Call POST /v/agenttask.checkpoint with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Clearagenttask.checkpoint.clear

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentYes
EgressNone - in-box (pure Postgres, no outbound call)

Delete every checkpoint for a task (post-success/abandon). { taskId }. Idempotent (0 rows = success). DEFERRED (built, not wired).

Call POST /v/agenttask.checkpoint.clear with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool agenttask.checkpoint.clear.

Pruneagenttask.checkpoint.prune

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionAdmin
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

(AdminOnly/system). GLOBAL retention sweep of checkpoint rows older than the cutoff (workspace-agnostic - PLATFORM scope, NOT ctx.workspace_id; agent.md FLAG). { olderThanDays?:int (default 30) }. DEFERRED (built, not wired): Class-1 cron, bearerless + platform scope.

Call POST /v/agenttask.checkpoint.prune with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Writeagenttask.checkpoint.write

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

Append a per-phase resume checkpoint; phase_index is assigned monotonically per task inside the tx (an advisory xact lock serialises concurrent lease-handoff writers). { taskId, phaseKey, state(json, <=1MiB), outputs(json[]) }. DEFERRED (built, not wired).

Call POST /v/agenttask.checkpoint.write with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool agenttask.checkpoint.write.

Claimagenttask.claim

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

The guarded UPDATE ... WHERE status='QUEUED' RETURNING is the single source of truth for “did I win the lease” (TOCTOU-safe, INV-4 style - the same discipline as gate.apply + review.claim). rows_affected==0 ⇒ the task is not QUEUED (a concurrent winner already leased it, or it is ESCALATED/terminal) ⇒ Conflict (no double-claim). The lease_owner + expiry + heartbeat are written; the payload + checkpoint are RETURNED so the worker resumes from where it was.

Input { taskId } (fields ending in ? are optional)

Call POST /v/agenttask.claim with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Claim Nextagenttask.claimNext

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

Implements CC-OPBOX 18 C1(i) / 20 D1’s ratio - “the agent CLAIMS THE QUEUE over MCP” - so the caged AGENT seat self-drains (CC-OPBOX 22, Position A) without an operator handing it a taskId (agenttask.list is ADMIN, so a MEMBER seat cannot enumerate). Atomically claims the OLDEST QUEUED task it is ALLOWED to run (optionally filtered to a carrier verb, e.g. agent.run): the WHERE pre-filters to autonomy_ceiling >= ctx.autonomy_level (the C2 bound, so a claimant never leases a task above its reach + never poison-loops), and FOR UPDATE SKIP LOCKED LIMIT 1 makes concurrent drainers each win a DISTINCT task (no double-claim, no blocking). An empty queue is {claimed:false} (not an error). Confers NO new capability: identical lease + ceiling semantics to claim, just selection-by-availability.

Input { verb? } (fields ending in ? are optional)

Call POST /v/agenttask.claimNext with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Createagenttask.create

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

depth = parent.depth+1 (threaded via parentTaskId, never ambient - INV-16); a root task is depth 0. verb MUST be a registered registry row (INV-11: no “queue a call you can never drive”). A depth over MAX_AGENT_TASK_DEPTH=5 is a hard deny BEFORE any write (fail-closed).

Input { verb, payload?, parentTaskId?, runId?, matterId?, matterStepId? } (fields ending in ? are optional)

Call POST /v/agenttask.create with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Escalateagenttask.escalate

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

The task hit an over-autonomy action it may not perform; it mints a one-shot ESCALATION Gate via the CANONICAL gate.propose verb (ctx.call_verb, INV-1 - no second escalation store/path) and records escalation_gate_id, moving to ESCALATED. The gate is an action-gate {targetVerb, inputHash} (gate.apply consumes the one-shot grant). Only a LEASED holder (or a QUEUED task) may escalate; a terminal task cannot.

Input { taskId, targetVerb?, inputHash?, reason? } (fields ending in ? are optional)

Call POST /v/agenttask.escalate with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Createagenttask.ext.create

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

The 1:1 frontend runtime/UI tail, written post-mint so the ext never exists without its kernel agent_task SoR row. { agentTaskId, title, prompt, sourceType, sourceId?, sourceMatterId?, sourceStepId?, childKey?, priority?, requiresHumanReview? }. Unique(agent_task_id).

Call POST /v/agenttask.ext.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool agenttask.ext.create.

Set Waitingagenttask.ext.setWaiting

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

The FRONTEND-DERIVED WAITING_CHILDREN park/wake CAS on the ext (the kernel has no such status). { agentTaskId, waiting, declaredChildKeys? }. CAS-guarded on waiting_for_children = NOT waiting so a concurrent/repeat transition lands exactly once; rows_affected==0 -> { changed

} (caller maps to ALREADY_WAITING / silent no-op). On park (true) the declared child-key set is recorded; on wake (false) it is left intact.

Call POST /v/agenttask.ext.setWaiting with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool agenttask.ext.setWaiting.

Updateagenttask.ext.update

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

Partial claim-stamp / telemetry patch by agentTaskId (only the supplied keys are written; last-write-wins). { agentTaskId, claimTokenHash?, claimedAt?, costUsd?, durationMs?, toolCallCount?, result?, progressText? }. claimTokenHash is the frontend-computed SHA-256 of the kernel lease handle (never plaintext - B7); the kernel only persists it.

Call POST /v/agenttask.ext.update with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool agenttask.ext.update.

Feedagenttask.feed

PropertyValue
Capabilityagenttask.read
Risk classRead - autonomy L0
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)
Render schemaYes - drives an inline chat artefact and a GUI panel

The single-task read a Hatchet agent-step’s await polls for its result. Owner-guarded: created_by == the caller OR tier >= ADMIN (an admin break-glass), plus workspace RLS, fail-closed - a non-owner gets the SAME not-found as a missing task (no existence leak, the CC-OPBOX 37 confinement). Returns the status + the checkpoint (the agent writes its structured output to checkpoint.output on DONE - the C2 contract) so the flow can resolve. Reuses the existing agent_task store (no new store; gate-(b) modelled-surfaced READ, CC-OPBOX 24/18 C6). [2026] VJS-CC-OPBOX 104: the matter READ-HOME for agent metacognition. Returns the reasoning chain - the rationale + the autonomy each task exercised - for a matter, a regenerable VIEW over the agent_task rows (the write-grain), never a second store (Steering #2). READ/MEMBER but SCOPED (the data.audit.feed pattern): a caller reads ONLY the feed of a matter it can itself read - the INV-17 matter read-fence proves access BEFORE disclosure (anti-IDOR, not-found-equivalent deny for a non-grantee), workspace-RLS-bound. With matterId OMITTED it returns the workspace’s NON-matter (CoS/board) reasoning (matter_id IS NULL) - so an org-level deliberation is never stranded (CC-OPBOX 104 Q4).

Input { taskId } (fields ending in ? are optional)

Call POST /v/agenttask.feed with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Getagenttask.get

PropertyValue
Capabilityagenttask.read
Risk classRead - autonomy L0
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)
Render schemaYes - drives an inline chat artefact and a GUI panel

A read operation in the agenttask.* family. Called through the one governed front door: capability, permission tier, autonomy, scope and egress are all resolved before the handler runs, and the call is audited (INV-1, INV-8).

Call POST /v/agenttask.get with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Listagenttask.list

PropertyValue
Capabilityagenttask.read
Risk classRead - autonomy L0
Min. permissionAdmin
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)
Render schemaYes - drives an inline chat artefact and a GUI panel

The queue + status + lastError read over agent_task (zero new store, INV-14). IDOR-scoped to the workspace (the explicit predicate + RLS backstop).

Input { status?, matterId? } (fields ending in ? are optional)

Call POST /v/agenttask.list with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Rank By Objectiveagenttask.rankByObjective

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentYes
EgressNone - in-box (pure Postgres, no outbound call)

The Executive loop-prioritisation function: judge a candidate task against its matter’s overriding objective and SET its priority (the EX-3 column claim_next drains). Deterministic set-overlap: priority = the count of distinct objective tokens that also appear in the candidate’s descriptor (its verb + payload summary/title/description). A matter with NO objective (or a task with no matter) ranks at 0 (the floor - nothing to align against). Reuses the SAME guarded priority write as reorder (non-terminal, RLS-scoped); idempotent (same objective+candidate => same priority). NOT Sensitive - pure backlog sequencing, no privilege change.

Input { taskId } (fields ending in ? are optional)

Call POST /v/agenttask.rankByObjective with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool agenttask.rankByObjective.

Releaseagenttask.release

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

([2026] VJS-CC-OPBOX 32 B2). The cooperative back-off path: the lease HOLDER voluntarily relinquishes its lease (it cannot make progress right now, or is shedding load) and returns the task to QUEUED so another worker can claim it. Guarded WHERE status='LEASED' AND lease_owner=$actor (the C2 lease-holder guard, fully replacing any token guard - no weakening): a stale/foreign caller, or a non-LEASED task, matches 0 rows -> the existing claim_conflict (single-winner preserved). The checkpoint is left INTACT so the next claim resumes from it; the lease lifecycle is cleared (lease_owner/expiry/heartbeat NULL, first_leased_at NULL so a fresh claim starts a new runaway budget). NOT a new engine - it re-opens the row for the SAME claim path (the requeue sibling, for a LIVE lease rather than a FAILED task).

Input { taskId } (fields ending in ? are optional)

Call POST /v/agenttask.release with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Reorderagenttask.reorder

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentYes
EgressNone - in-box (pure Postgres, no outbound call)

Set the integer priority (default 0) of a NON-terminal task (QUEUED/LEASED/ESCALATED) in this workspace’s backlog. Higher priority drains first (claim_next ORDER BY priority DESC, created_at ASC), making the board the whitepaper’s “continuously reordered backlog of the most valuable things to do next”. Workspace-scoped (RLS + explicit predicate): a caller may reorder ONLY their own workspace’s tasks - no cross-workspace, no privilege change (NOT Sensitive: pure backlog sequencing). Idempotent. A terminal task (DONE/FAILED/CANCELLED) is refused (INV-3: priority is moot once the work is over); an unknown task is a BadInput with no existence leak.

Input { taskId, priority } (fields ending in ? are optional)

Call POST /v/agenttask.reorder with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool agenttask.reorder.

Requeueagenttask.requeue

PropertyValue
Capabilityagenttask.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentYes
EgressNone - in-box (pure Postgres, no outbound call)

M7 error-recovery (the fee-earner’s “my thing broke” loop): a FAILED task returns to QUEUED, its checkpoint INTACT so a fresh claim resumes from where it broke. NOT a new engine - it re-opens the row for the SAME claim path. Guarded WHERE status='FAILED'; a non-FAILED task (still running / terminal-success / cancelled) is refused (no re-driving live or done work).

Input { taskId } (fields ending in ? are optional)

Call POST /v/agenttask.requeue with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool agenttask.requeue.