Workers
Conduit orchestrates; workers execute. A serviceTask carries a
<conduit:taskTopic> that the engine uses purely as a routing label — it knows
nothing about HTTP, gRPC, Kafka, or any other transport. Workers poll the engine, run the
side effect, and report the outcome back.
Reference SDKs ship in the engine's repo at workers/,
one independent build per language. Each SDK conforms to a single language-agnostic wire contract
(PROTOCOL) and exposes registration sugar native to its host language.
What is an external task?
An external task is a regular <bpmn:serviceTask> with a
<conduit:taskTopic> extension element. The element type is ordinary BPMN; the
topic is what tells the engine "don't run this yourself — hand it off to a worker." There is no
separate ExternalTask element kind in Conduit.
<bpmn:serviceTask id="ping" name="Ping URL">
<bpmn:extensionElements>
<conduit:taskTopic>http.call</conduit:taskTopic>
</bpmn:extensionElements>
</bpmn:serviceTask>
The engine writes the task into its job queue, workers poll
/api/v1/external-tasks/fetch-and-lock for tasks matching their topic, run the side
effect, and report back via /complete, /failure, or
/bpmn-error. The "external task" name refers to the runtime mode and the API path,
not a BPMN element. See the
Service Task element page for the full element
reference, including the alternative HTTP-push mode (deprecated; replaced by the reference HTTP
worker).
Pick your language
#[handler(topic = "http.call")]
async fn http_call(task: &ExternalTask)
-> Result<HandlerResult, HandlerError> { /* ... */ } @TaskHandler(topic = "http.call")
public class HttpCallHandler implements Handler {
public HandlerResult handle(ExternalTask t) { /* ... */ }
} @handler(topic="http.call")
async def http_call(task: ExternalTask) -> Complete:
return Complete([Variable.string("status", "ok")]) export const httpCall = defineHandler({
topic: "http.call",
async handle(task) { return HandlerResult.complete([]); },
}); runner.Register("http.call", func(ctx context.Context, t *cw.ExternalTask)
(*cw.Result, error) { return cw.Complete(), nil }) Cross-cutting
Protocol
The five endpoints under /api/v1/external-tasks/*, the JSON variable shape, the
U/S error envelope, and the at-least-once semantic contract.
Idempotency
At-least-once means workers can see the same task twice. Per-handler strategies for HTTP, CSV, GCS, and Kafka producers; the optional Postgres dedupe store.
Make it safe →Examples
End-to-end pairs: a tiny BPMN with <conduit:taskTopic> alongside the worker
that handles it. One example per SDK.