Long-running & recurring jobs
Handle results that arrive in seconds, hours, or continuously over weeks.
OpenHelm runs are asynchronous. There are three ways to consume results, matched to how long the work takes.
1. Seconds — inline
Fast tasks settle quickly. Over MCP, the tool call bounded-waits (~75s) and returns the result in one turn; if it isn't ready it returns a task_id and you call check_result.
2. Minutes to hours — poll or webhook
POST /v1/runs returns 202 immediately with a task_id and poll_url. Either:
- Poll
GET /v1/runs/{id}untilstatusis terminal, or - Supply a `callback_url` and receive an HMAC-signed webhook on completion.
Verifying the webhook
The body is { "event": "run.completed" | "run.failed", "data": <TaskEnvelope> }. The signature header is Stripe-style:
X-OpenHelm-Signature: t=<unix_seconds>,v1=<hex>
signed_payload = `${t}.${rawBody}`
expected = HMAC_SHA256(api_key.signing_secret, signed_payload)Reject anything that doesn't match, and de-dupe on data.task_id (deliveries can repeat).
3. Recurring — register once, receive forever
Create a scheduled job (schedule_type of interval, cron, or email) and it fires your webhook on every run. A long-lived monitor (a daily briefing, an inbox watcher, a weekly report) streams results back for weeks with no polling. List a job's history with GET /v1/runs?job_id=….
Tip: webhooks beat polling for anything time-sensitive. Acknowledge fast (2xx), then process out-of-band.