Persistent scheduler submissions¶
Runtime API execution and manual schedule endpoints require exactly one Idempotency-Key
header containing a UUID:
POST /api/v1/agents/{id}/executeinvokes an authorized registered agent.POST /api/v1/workflows/executeaccepts raw source with administrative authority.POST /api/v1/schedules/{id}/triggerinvokes a persisted schedule with administrative authority.
Generate the UUID once for a new task and retain it with the request. Resend the same UUID and request when the admission response is lost or when checking the result. Changing the UUID starts a different task and can repeat effects. Authentication and per-agent authorization run before claim lookup.
# Generate once; retain this value for subsequent retries.
INVOCATION_ID=$(cat /proc/sys/kernel/random/uuid)
curl -X POST http://localhost:8080/api/v1/workflows/execute \
-H "Authorization: Bearer $SYMBIONT_API_TOKEN" \
-H "Idempotency-Key: $INVOCATION_ID" \
-H "Content-Type: application/json" \
-d '{"workflow_id":"agent report() { with sandbox = \"docker\" {} }","parameters":{}}'
The claim binds the verified credential and key scope, execution endpoint, JSON input and complete selected agent configuration. All identified scheduler submissions share one project-wide ID domain. Another authenticated caller cannot use an existing ID to retrieve its result or start another execution. Credential, key-scope, source, agent ID or configuration changes conflict under an old ID. No token or secret is stored in the claim; its request identity is hashed.
Workflow submissions that omit agent_id derive the registration ID from the
invocation UUID, so a retry after restart selects the same identity. Supplying
agent_id retains the existing administrative create/replace behavior. A cached
workflow response does not replace a registration again. Registered-agent retries
require the original registration ID and configuration; if startup generated new
IDs, the old route is unavailable until that registration is restored. Submitting
the same invocation ID to a newly registered agent produces a conflict.
Outcomes¶
| HTTP | status |
Meaning |
|---|---|---|
| 200 | queued |
One new execution was admitted; includes its execution_id, agent_id and protected audit. |
| 200 | completed |
Returns the verified saved completion, with replayed: true; no new execution. |
| 422 | failed |
Returns a saved terminal failure whose effects are known; no new execution. |
| 409 | in_progress |
A claim owner still holds queued, executing or finalizing work. |
| 409 | unresolved |
No verified durable result exists. Inspect the original audit before deciding how to reconcile effects. |
| 409 | reconciled |
Returns a separate signed operator assessment; the original ID cannot execute again. |
| 409 | conflict |
The ID belongs to a different caller, endpoint, input or configuration. No original result or audit is exposed. |
| 400 | invalid_invocation_id / invalid_request |
Invalid header or workflow source; no execution was admitted. |
| 403 | forbidden |
A schedule identity or policy guard refused execution. |
| 404 | not_found |
The selected registered agent or schedule is unavailable. |
| 503 | unavailable |
The required execution service, queue or protected claim storage refused admission. A partially created claim can remain unresolved. |
Invocation responses echo Idempotency-Key, report Idempotency-Replayed, and
set Cache-Control: no-store. Saved results include output/error, elapsed time,
reported token usage, shared budget and the original audit reference. Poll using
the same authenticated submission; agent history remains a bounded in-memory
view and may be lost at restart.
The owner survives an unread or disconnected admission response. Cancellation and scheduler deadlines still stop execution and wait for cleanup. The claim is held until the final scheduler result is checked against its signed journal and persisted. Failed setup, cancellation before journal startup, unconfirmed effects, process death or result-storage failure leave the ID unresolved. A retry cannot turn those states into a fresh queue entry. A successful output publication followed by a crash therefore cannot silently cause another publication under that ID.
SDK and remaining routes¶
On Unix, AgentScheduler::schedule_identified_invocation accepts a trusted
InvocationIdentity and returns a queued handle or the existing durable state.
The default governed executor supplies the pinned project root. Custom executors
must explicitly support protected admission; the default trait method refuses it.
The combined request identity and saved result have the existing invocation-store
size limits. See invocation storage.
Ordinary SDK schedule_invocation and CronScheduler::trigger_now calls still
mean new work. Retry-capable cron callers use trigger_identified. Timer
occurrences and their recovery now use durable identities; see
cron recovery. Other execution routes still need corresponding
identity integrations. This does not establish exactly-once semantics for
arbitrary external services or automatic reconciliation of unknown effects.
scripts/test-scheduler-invocations.py exercises both shipping API endpoints,
concurrent admission, unread responses, output publication followed by SIGKILL,
restart without a provider and changed caller/source refusals. Protected observers
verify signed journals and useful output outside the worker's file grants.
Operator-reconciled submissions return HTTP 409 with status: "reconciled", the
original audit reference and a separate resolution receipt. The original ID
cannot enqueue work again. See operator reconciliation
for review, cron history repair and explicit resume.