Skip to main content
Use the async runtime API when you want Sinas to run a function on behalf of a user without blocking your app’s request. Submit the job, get an execution_id back, and either poll for status or have Sinas POST the result to a URL you provide. This is the right pattern when an app — like a custom UI or another service — needs to fan out work for a logged-in user. Every job is attributed to the user whose bearer token kicked it off, so audit trails remain intact.

When to use it

  • Bulk workloads — ingestion runs, batch enrichment, anything that fans into N function calls.
  • Long jobs — a function that legitimately runs minutes or longer; the client doesn’t want to hold an open HTTP connection.
  • Cross-app workflows — a function on Sinas that calls back into your app’s API as the same user (Sinas-issued tokens are accepted by any app that validates via Sinas auth).
For sync execution where you want the result inline, use POST /functions/{ns}/{name}/execute instead.

Endpoint

Auth: the bearer’s sub is the job’s user. There’s no user_id override and no “act-as-user” mode — every queued job is attributable to the human (or human-equivalent account) whose token initiated it. Audit-log integrity depends on this. Permission: reuses the existing function-execute permissions — sinas.functions/{ns}/{name}.execute:own (or :all). No extra permission gates the queue path; anything you can execute synchronously, you can enqueue.

Response

Poll execution state via GET /executions/{execution_id} (returns the current status, output_data, error, etc.).

Callbacks

If callback_url is set, Sinas fires a single HTTP POST to that URL when the execution terminates (success, failure, or timeout). Fire-and-forget — no retries.
The callback carries a fresh Sinas-signed access token for the originating user. Apps validate it through the same auth path they already use for inbound function calls (Python SDK: SinasAuth; JS SDK: client.auth.getMe()).

Delivery semantics

  • Fire-and-forget: one POST attempt with a 10s timeout. No retry, no DLQ.
  • No backpressure: Sinas does not wait for callback success before marking the execution complete.
  • Resilience fallback: if the callback fails to deliver, poll GET /executions/{execution_id} to reconcile. The execution row records callback_status (sent / failed) and callback_response_code for operator visibility.

Allowlist policy

Callback hosts are gated by the CALLBACK_URL_HOSTS environment variable: SSRF guards always apply regardless of mode: the URL must use https:// and resolve to a non-private address. Managed-service operators typically deploy with an explicit allowlist; self-hosted single-tenant operators flip to * once.

SDK helpers

Python

JavaScript

Worked example

Your app submits 50 documents for ingestion on behalf of a signed-in user.
  1. The app’s backend, holding the user’s bearer, calls client.functions.enqueue(...) once per document.
  2. Each execution_id lands in a queue. A Sinas worker dequeues and runs myapp/ingest_document under the user’s identity.
  3. The function calls the app’s /api/v1/documents/{id}/mark-processed with the per-execution access token. The app’s SinasAuth validates the token via Sinas’s /auth/me, applies the user’s permissions, persists the update.
  4. When the function finishes, Sinas POSTs the result to callback_url. The app updates the run’s progress and notifies the user.
If ingest_document invokes a Sinas agent (client.chats.invoke(...)), the agent runs in-process under the same user; sub-agent fan-out is internal and doesn’t re-cross the app boundary, so the function token’s TTL never bites.

Batches

Submitting N executions one at a time works, but for genuine bulk workloads (50+ runs at once) you’d rather submit them as a single unit, store one id, and poll one aggregate. The batches API does that — for both functions and agents.

Submit — function batch

Submit — agent batch

Each input creates a fresh chat with agent.initial_messages pre-populated (templated with input_variables) followed by message. Agent batches have an approval policy: if a child agent tries to call a tool that requires approval, the execution is marked failed with an error — bulk agent runs must use agents whose enabled tools don’t require approval. Per-execution callback result for agent batches:
Full transcript fetchable via GET /chats/{chat_id}.

Poll a batch

Terminal status values:
  • completed — all children completed successfully
  • partial — all children terminal, ≥1 failed
  • failed — all children failed
  • cancelled — batch cancelled before all children terminated

Drill in

Cancel

Children with status pending or awaiting_input become cancelled. Running children must complete naturally; their results still count toward the batch.

Batch callback

When the last child terminates, Sinas POSTs the batch summary once to batch_callback_url:
Same auth / SSRF / fire-and-forget semantics as the per-execution callback. Per-execution callbacks (callback_url) and the batch callback are independent — both can be set, both fire.

Limits

  • MAX_BATCH_SIZE (env) caps how many inputs a single batch can have (default 1000).
  • Single-target batches only: every child in a batch hits the same function (or agent). For mixed targets, submit multiple batches.

SDK helpers

Python:
JavaScript:
  • Functions — defining the code that runs.
  • API Overview — runtime vs. management surfaces.
  • RBAC — how sinas.functions/{ns}/{name}.execute permissions resolve.