Skip to content

Persistent invocation identities

Ordinary ORGA symbi run invocations now print an invocation ID before execution. To retry a request, pass the same ID, source, input and loop settings:

symbi run reviewer --input '{"task":"review the change"}' \
  --invocation-id 72d6a833-b825-4b22-b50c-206337d77f7c

Choose a fresh UUID for a new intended invocation. Omitting the option generates a new ID and therefore starts a new task; it is not a retry. Retain the ID when automating calls so a lost response cannot cause the next attempt to silently create another task.

IDs are scoped to the canonical project directory and the trusted cli:orga entry point. The request identity binds the selected agent name and source, literal input and loop configuration. Reusing an ID with a changed request is refused. Separate projects or scopes have separate identity domains.

Results and interrupted work

One process creates the durable claim before starting work. It keeps an exclusive file lock while the invocation is active. Concurrent attempts using that ID exit with code 2 and report that the invocation is already in progress. The signed run start binds the invocation ID, scope and request hash; the claimed journal refuses a second run start.

A finished invocation persists its small CLI result only after verifying its protected run journal. Retrying returns that saved result and the original audit reference without contacting a provider or starting a worker. The normal exit status is preserved: 0 for loop completion, 1 for a recorded terminal failure.

If the process crashes, a result write fails, an effect is unknown, or a claim is incomplete, the original identity remains claimed. Retrying exits with code 2 and requires reconciliation; it cannot obtain execution authority again. Even a signed terminal Completed does not make an unknown tool effect cacheable. On the initial attempt, bounded and escaped tool errors remain visible on stderr alongside the unresolved status and audit reference. Errors during setup after claiming can also leave an unresolved invocation with an empty or incomplete journal. These cases are deliberately not retried automatically. Use crash inspection and backend evidence to establish the original outcome. Operator reconciliation can then persist a separate signed assessment. Repeating a reconciled CLI invocation returns the receipt with exit 3; HTTP routes return HTTP 409 with status: "reconciled". Neither response repeats work or manufactures a missing runtime result.

The CLI stores only its displayed output, iteration count, total tokens and termination reason. Its saved result does not reconstruct a live reasoning loop or grant access to a previous worker. The audit is verified again before a cached result is returned. A missing or corrupted original journal fails closed.

Storage and limits

Claims live in the runtime-owned .symbiont/invocations/ directory alongside protected audit storage. The directory is mode 0700 and files are mode 0600. Claim files refuse symbolic links, hard links, special files, unsafe ownership and permissions. A store lock serializes creation and result writes across processes; lock waits are bounded to two seconds.

The store currently permits 4,096 retained files (claims and reconciliation receipts) and 64 MiB of total claim/result/receipt data, with at most 2 MiB per file and 1 MiB per request identity or cached result. Exhaustion refuses work or result delivery without deleting existing identities. Capacity configuration and an archival policy that preserves duplicate detection remain outstanding. Preserve claims with their journals. Deleting records, restoring an older store snapshot or selecting a different project can discard the history needed to detect a duplicate.

Private claim/result files rely on the runtime's filesystem boundary; the separate journal supplies signed execution evidence. Workers receive neither store nor signing-key access. SDK callers of reasoning::invocation supply a trusted scope and must distinguish authenticated callers when using one project.

HTTP submissions

HTTP Input submissions require an Idempotency-Key UUID. The first request binds it to the authenticated caller, URI, JSON payload and trusted target. Completed results survive server restarts; concurrent owners and unresolved outcomes return HTTP 409 without another execution. The owner retains the claim through cleanup and saving the result, including after disconnection. See HTTP retry states for authentication scope, credential rotation and response details.

Current scope

Persistent caller-retry handling applies to ordinary CLI ORGA runs and HTTP Input submissions, runtime API registered-agent/workflow/manual schedule submissions, and persisted timer occurrences. See cron recovery. See scheduler retry states. Managed CLI agents reject --invocation-id explicitly. Managed sessions and other entry points still need their corresponding identity integrations. Independently, reasoning loops and governed tool sessions now stop further execution after unconfirmed tool or child outcomes; see stopping uncertain execution. Interrupted file-publication reconciliation and exactly-once guarantees for arbitrary external services remain outside this implementation.

The focused unit tests cover concurrent owners, cached results, scope and payload conflicts, lost outcomes, damaged records, unsafe paths and exhausted storage. The shipping crash test adds retries during a real worker action, retries after SIGKILL both during execution and after output publication, result retrieval with provider/Docker access unavailable, and changed-request refusal, alongside useful permitted work.