Mark a task as external and genroc will create a queue of waiting tasks,
which you can poll and process with your own worker.
When to use
The queue + worker architecture is suitable for resource-intensive processing. It protects your system from being overwhelmed: if there are too many tasks at once, they simply wait in the queue on genroc's side.
If the work is lightweight and it's more about timing or providing data,
it's better to expose a simple REST endpoint and use the fetch action.
Basic concept
Genroc doesn't know about your worker. You simply mark a task as external,
and your worker asks genroc: "Do you have any work? If yes, I claim it."
For this, there is the /api/external-tasks/claim
endpoint. You must specify which process and task you want to claim.
Give your worker the
workerpermission. That's all it needs.
Example:
{
"worker_id": "worker-1",
"limit": 5,
"process": "expense-approval",
"task": "approval",
"lease_ms": 30000
}
Each worker has to have a unique id, so genroc can distinguish who
claimed what. limit is how many tasks you want to claim, so here you can
receive up to 5 tasks per claim. process is the process name and task
is the task id.
Leasing
A task is leased to you for the time you've requested. If your worker
doesn't provide a result in that time or doesn't renew the lease,
genroc allows a different worker to claim it instead
(only_once tasks will fail with external.lost
in this case).
Claim response
{
"items": [
{
"token": "550e8400-e29b-41d4-a716-446655440000.6.1",
"process": "expense-approval",
"version": 2,
"task": "approval",
"external_input": {
"amount": 420,
"submitter": "alice"
},
"waiting_since": "2026-09-25T09:12:00Z",
"deadline": "2026-09-26T09:12:00Z"
}
]
}
The most important fields are external_input, which is the input passed into the external action,
and the unique token, which you need when submitting the result (and when renewing).
deadline tells the worker when the work needs to be finished. It comes from
the timeout field (the timeout also includes time spent in the queue).
objects field
If external_input contained large values, they are null in it and listed in the item's
objects field, with paths starting at external_input. Fetch each one with
GET /api/objects/{ref}, parse its data (it is JSON text) and put it back at its path.
Read more in the next chapter.
Resolving the task
Once your worker has finished, use the /api/external-tasks/resolve
endpoint to submit the result:
{
"token": "550e8400-e29b-41d4-a716-446655440000.6.1",
"result": {
"approved": true
}
}
If the work ended with an error, you can submit the error this way:
{
"token": "550e8400-e29b-41d4-a716-446655440000.6.1",
"error": {
"code": "over_budget",
"message": "Amount exceeds the submitter's limit",
"data": { "limit": 300 }
}
}
The result is validated against result_schema, and the error code and data
are validated against the raises field (code and message are always required).
Renewing leases
If your worker can run for a longer time, you should use genroc's lease renewal. Make leases e.g. 30s and renew them e.g. every 10s. This lets genroc know that the worker is alive and the work is advancing (a bit like a heartbeat).
For renewing, there is the /api/external-tasks/renew
endpoint, which accepts a list of tokens for the tasks you want to renew.
Cancelled/lost leases
The renew endpoint lets you know if a task is no longer worth working on.
This can happen when the process is cancelled or the lease is lost.
You can use this to stop the work before it finishes to avoid wasting resources.
Releasing a task
If your worker is not able to finish the task and you want it to be picked up
by a different worker as soon as possible, you can explicitly release the task
with the /release endpoint.
Reusable tasks tied to workers
Workers are tied to a specific process and task, so if you want to make this reusable, create a child process and make the other processes call it. This allows you to specify a typed API. This is also how TypeScript evaluation works.