workflow
Modules
Module workflow
ballerina/workflow Ballerina library
Ballerina Workflow Library
The ballerina/workflow library provides durable, fault-tolerant workflow orchestration for Ballerina applications. It lets you define long-running business processes — spanning minutes, hours, or days — that automatically recover from crashes and process restarts without losing progress.
Overview
Workflows and activities are ordinary Ballerina functions:
@workflow:Workflow— A durable function that orchestrates a business process. The runtime checkpoints every step and replays recorded history to recover from failures.@workflow:Activity— A function that performs a single non-deterministic operation (API call, database query, email send). Once an activity completes, its result is recorded and never re-executed during replay.
import ballerina/workflow; @workflow:Activity function checkInventory(string item) returns boolean|error { // Call external inventory API return true; } @workflow:Workflow function processOrder(workflow:Context ctx, OrderRequest request) returns OrderResult|error { boolean inStock = check ctx->callActivity(checkInventory, {"item": request.item}); if !inStock { return {orderId: request.orderId, status: "OUT_OF_STOCK"}; } return {orderId: request.orderId, status: "COMPLETED"}; }
Authoring guidelines
- Workflow functions must contain only orchestration logic (control flow and waiting for data). All business logic and non-deterministic operations - database calls, external API calls, I/O - belong in activity functions.
- Activities must be invoked through
ctx->callActivity(...)from within a workflow function. Calling an activity function directly is a compile-time error. - When calling an activity, pass its arguments as a record whose keys exactly match the activity function's parameter names - for example,
ctx->callActivity(checkInventory, {"item": request.item})forfunction checkInventory(string item). - When using the Ballerina Integrator tooling, place all
@workflow:Workflowand@workflow:Activityfunctions in the project'sfunctions.balfile. - Store the workflow ID returned by
workflow:run()so that laterworkflow:sendData()calls can be routed to the correct running instance.
Starting a Workflow
Use workflow:run() to start a workflow instance from any entry point — HTTP service, scheduled job, message consumer, or main:
string workflowId = check workflow:run(processOrder, {orderId: "ORD-001", item: "laptop"});
Receiving External Data
A workflow can pause and wait for external input — approvals, payment confirmations, user decisions — using future-based event records. Send data to a running workflow with workflow:sendData():
// In the workflow — wait for a human decision ApprovalDecision decision = check wait events.approval; // From outside — deliver the decision check workflow:sendData(processOrder, workflowId, "approval", {approverId: "mgr-1", approved: true});
Multi-Future Waits with ctx->await
Use ctx->await to wait for multiple futures at once, with optional quorum and timeout:
| Pattern | Example |
|---|---|
| Wait for all | ctx->await([f1, f2]) |
| Wait for any (first wins) | ctx->await([f1, f2], 1) |
| Quorum (N of M) | ctx->await([f1, f2, f3], 2) |
| With deadline | ctx->await([f1, f2], timeout = {hours: 48}) |
Error Handling
Activity errors are returned as plain Ballerina values. The workflow decides what happens next:
string|error result = ctx->callActivity(chargeCard, {"amount": input.amount}); if result is error { // retry with a different card, fall back, or compensate }
Enable automatic retries for transient failures:
string result = check ctx->callActivity(chargeCard, {"amount": input.amount}, retryOnError = true, maxRetries = 3);
Configuration
Add a Config.toml to your project. For local development with no server:
[ballerina.workflow] mode = "IN_MEMORY"
For production, connect to a Temporal server:
[ballerina.workflow] mode = "TEMPORAL" temporalHost = "localhost" temporalPort = 7233 namespace = "default" taskQueue = "my-task-queue"
Documentation
| Guide | Description |
|---|---|
| Get Started | Write and run your first workflow |
| Key Concepts | Workflows, activities, external data, and timers |
| Write Workflow Functions | Signatures, determinism rules, and durable sleep |
| Write Activity Functions | Activity patterns and retry options |
| Handle Data | Waiting for external input and sending data |
| Handle Errors | Propagation, retry, fallback, and compensation |
| Configure the Module | Connection settings, TLS, and namespaces |
Examples
| Example | Description |
|---|---|
| Get Started | First workflow |
| Order Processing | HTTP-triggered workflow with result polling |
| Human in the Loop | Pause for a human approval |
| Wait for All | Dual authorization — both teams must approve |
| Alternative Wait | First responder wins (approval ladder) |
| Forward Recovery | Pause for corrected data and retry |
| Error Propagation | Fail the workflow on a critical error |
| Error Fallback | Fall back to a secondary activity |
| Error Compensation | Saga: undo committed steps on failure |
Functions
completeHumanTask
function completeHumanTask(string taskWorkflowId, anydata result, [string, string...]? callerRoles, string? userId) returns error?Completes a pending human task by sending the result back to the waiting workflow.
The taskWorkflowId is the child workflow ID of the task, which is
available via the inbox/task-listing API and is composed as:
"humantask-<parentWorkflowId>-<taskName>-<uuid>".
check workflow:completeHumanTask(taskWorkflowId, {approved: true, comment: "LGTM"});
If callerRoles is provided the function fetches the userRoles stored on the task
and returns an error when none of the caller's roles appear in that list.
When omitted the role check is skipped; enforcement is then the caller's responsibility.
Parameters
- taskWorkflowId string - Temporal workflow ID of the human task child workflow
- result anydata - The value to return to the workflow (must be compatible with the declared
T)
- callerRoles [string, string...]? (default ()) - Roles held by the caller; validated against the task's configured
userRoles
- userId string? (default ()) - The user ID of the person completing the task (used for auditing)
Return Type
- error? - An error if the task cannot be found, is already completed, or the caller is unauthorized
getPendingAgentEvents
function getPendingAgentEvents(string agentId) returns PendingAgentEvent[]|errorLists the data events a running durable agent has accepted but not yet
answered. Use after a crash or restart to rediscover in-flight event turns
for a session and fetch their answers via DurableAgent.getDataResult /
waitForDataResult — nothing is lost while the agent works, however long
the turn takes.
workflow:PendingAgentEvent[] pending = check workflow:getPendingAgentEvents(agentId); foreach var pendingEvent in pending { string answer = check agent.waitForDataResult(agentId, pendingEvent.token); }
Parameters
- agentId string - Target agent (workflow) ID
Return Type
- PendingAgentEvent[]|error - The in-flight event turns (empty when the agent is idle), or an error
getWorkflowResult
Waits for a workflow to complete and returns its result.
anydata raw = check workflow:getWorkflowResult(workflowId);
Parameters
- workflowId string - The workflow ID
- timeoutSeconds int (default 30) - Maximum wait time in seconds
Return Type
- anydata|error - Result of the workflow as anydata, or an error
run
Starts a new workflow instance and returns its unique ID.
string workflowId = check workflow:run(orderProcess, input = {"orderId": "ORD-123"});
Parameters
- processFunction
function() ()- The workflow function (must have@Workflow)
- input anydata (default ()) - Optional input data for the workflow. Must match the workflow
function's declared input parameter type (any
anydatasubtype)
sendData
function sendData( function() () workflow, string workflowId, string dataName, anydata data) returns error?Sends data to a running workflow's events record.
check workflow:sendData(orderProcess, workflowId, "approval", {approved: true});
Parameters
- workflow
function() ()- The workflow function (must have@Workflow)
- workflowId string - Target workflow ID (from
run)
- dataName string - Field name in the workflow's events record
- data anydata - The data payload
Return Type
- error? - An error if sending fails
Classes
workflow: DurableAgent
A durable AI agent declared as an object. Must be assigned to a module-level
final variable (compiler-enforced) — the compiler plugin reads the constructor
config to generate the Temporal registration at module init, and the module-level
variable name becomes the agent's stable identity.
The object itself is a declaration anchor: capability registration is generated at compile time from the constructor config, and the driver methods are lowered by the compiler plugin to the context-appropriate runtime primitive.
final workflow:DurableAgent orderAgent = check new ({ systemPrompt: {role: "Order assistant", instructions: "Help the user."}, model: wso2Model, activities: [checkInventory, reserveStock], events: [{name: "chat", request: string, response: string, cardinality: workflow:MULTI_EVENT}] });
Constructor
Declares the agent. Capabilities are fixed here and registered with the workflow runtime at module init by the compiler plugin.
init (*DurableAgentConfig config)- config *DurableAgentConfig - The agent's complete configuration
bindAgentName
function bindAgentName(string agentName)Binds the agent's stable identity — its module-level variable name — to this object. Called by the compiler-plugin-generated module-init code; not part of the public API surface. The first binding wins; later calls are ignored.
Parameters
- agentName string - The agent's module-level variable name
run
Starts the agent durably and returns the new instance ID — always the ID,
never the result (a durable agent may suspend for days on a human task, so
no caller thread is blocked). Outside a workflow this is a top-level start;
inside a @workflow:Workflow the agent runs as a Temporal child workflow.
Parameters
- query string - The user turn appended to the agent's system prompt
- input anydata (default ()) - Optional structured input for the run
sendData
Sends an event to a running instance on a declared channel and returns a correlation token for reading that turn's response.
Parameters
- instanceId string - The agent instance ID returned by
run
- eventName string - A channel declared in the agent's
events
- data anydata - The payload; must match the channel's declared
requesttype
getResult
Returns the final result of an instance if it has finished, without waiting.
While the instance is still working (e.g. suspended on a human task) a
workflow:AgentBusyError is returned — check back later, or use waitForResult.
Parameters
- instanceId string - The agent instance ID returned by
run
- T typedesc<anydata> (default <>) - Expected result type (inferred from context)
Return Type
- T|error - The result as
T, aworkflow:AgentBusyErrorwhile in progress, or an error
getDataResult
Returns the response for a specific sendData turn if it is ready, without
waiting. While the turn is unanswered a workflow:AgentBusyError is returned.
Parameters
- instanceId string - The agent instance ID returned by
run
- token string - The correlation token returned by
sendData
- T typedesc<anydata> (default <>) - Expected response type (inferred from context)
Return Type
- T|error - The turn's response as
T, aworkflow:AgentBusyErrorwhile unanswered, or an error
waitForResult
Waits until the instance finishes and returns its result. Inside a workflow this durably suspends the caller (no thread held); from a service it blocks but is resumable — if the caller crashes, calling again after restart resumes the wait, because the result lives in history.
Parameters
- instanceId string - The agent instance ID returned by
run
- T typedesc<anydata> (default <>) - Expected result type (inferred from context)
Return Type
- T|error - The result as
T, or an error
waitForDataResult
Waits for a specific sendData turn's response (same durability guarantees
as waitForResult).
Parameters
- instanceId string - The agent instance ID returned by
run
- token string - The correlation token returned by
sendData
- T typedesc<anydata> (default <>) - Expected response type (inferred from context)
Return Type
- T|error - The turn's response as
T, or an error
Clients
workflow: Context
Workflow execution context providing activity execution, durable sleep, deterministic time, and multi-future await APIs.
Constructor
Creates a workflow execution context wrapping the native context handle.
This constructor is called by the workflow runtime; do not instantiate Context directly.
init (handle nativeContext)- nativeContext handle - Native context handle from the workflow engine
callActivity
function callActivity( function() () activityFunction, map<anydata|object {}> args, typedesc<anydata> T, AutoRetry|HumanReview|NoAutomaticRetry retryPolicy) returns T|errorExecutes an activity function. A completed activity is never re-executed on
workflow replay — its recorded result is reused, even across process crashes
and restarts. A failed attempt may run again, however: AutoRetry re-executes
the activity automatically and HumanReview lets a human rerun it, so make the
activity's side effects idempotent (or deduplicate them) when retries are enabled.
PaymentResult result = check ctx->callActivity(processPayment, args = {"orderId": orderId});
Parameters
- activityFunction
function() ()- The activity function (must have@Activity)
- args map<anydata|object {}> (default {}) - Arguments to pass to the activity. Values are normally
anydata. Module-levelfinalclient objectvariables may also be passed for activity parameters whose declared type is a client object; the compiler plugin validates the call site and substitutes a"connection:<name>"marker for transport across the workflow execution boundary.
- T typedesc<anydata> (default <>) - Expected return type (inferred from context)
- retryPolicy AutoRetry|HumanReview|NoAutomaticRetry (default NoAutomaticRetry) - Retry behaviour on failure:
()/NoAutomaticRetry(default) — error is returned as-is, no retry.AutoRetry— automatic backoff retry with configurable attempts and delays.HumanReview— on failure a review task is created for a human to decide whether to retry (optionally with new input) or permanently fail the activity.
Return Type
- T|error - The activity result as
T, or an error
await
function await(future<anydata>[] futures, Unsigned32 minCount, Duration? timeout, typedesc<anydata|error|(anydata|error)[]> T) returns TWaits for at least minCount data futures to complete. Results are a positional tuple
aligned to input order. Use nullable types (T?) for partial waits.
The result can be captured in several ways:
// Wait for all (tuple binding pattern) [Approval, Payment] [approval, payment] = check ctx->await([events.approval, events.payment]); // Capture the whole result, including a possible timeout, without `check` [Approval, Payment]|error result = ctx->await([events.approval, events.payment]); if result is error { /* handle timeout */ } // Handle each position independently (a slot is a value or an error) [Approval|error, Payment|error] [a, p] = check ctx->await([events.approval, events.payment]); // Wait for any (1 of 2) — use nilable members for partial waits [Approval?, Payment?] result = check ctx->await([events.approval, events.payment], minCount = 1);
Parameters
- futures future<anydata>[] - Data futures from the workflow's events record
- minCount Unsigned32 (default <int:Unsigned32>futures.length()) - Minimum completions required (default: all)
- timeout Duration? (default ()) - Maximum wait duration; returns an error on timeout
Return Type
- T - Positional tuple of values (
nilfor an incomplete position), or an error
awaitHumanTask
function awaitHumanTask(string taskName, string|string[] userRoles, map<json> payload, string? title, string? description, Duration? timeout, typedesc<anydata> T) returns T|HumanTaskTimeoutErrorCreates a human task and blocks until a human completes it or the optional timeout elapses.
Internally, the task is modelled as a durable Temporal child workflow whose type is taskName,
so the task survives worker restarts. Register the task name at module init time via
wfInternal:registerHumanTask(taskName) (the compiler plugin generates this call automatically).
ApprovalDecision d = check ctx->awaitHumanTask("approveExpense", "FINANCE_APPROVER", payload = {"amount": 1200, "currency": "USD"}, title = "Approve order", timeout = {hours: 24} ) on fail workflow:HumanTaskTimeoutError e { check ctx->callActivity(notifyEscalation, args = {"taskName": e.detail().taskName}); return e; };
Parameters
- taskName string - Identifies the task type; used as the Temporal workflow type and child workflow ID
- payload map<json> (default {}) - Read-only JSON object rendered as key-value pairs next to the form
- title string? (default ()) - Short summary shown in the inbox. Defaults to
taskNamewhen omitted
- description string? (default ()) - Additional context shown alongside the form. Optional
- timeout Duration? (default ()) - Maximum time to wait. Omit (or pass
()) to wait indefinitely
- T typedesc<anydata> (default <>) - Expected result type; drives form schema generation and runtime validation
Return Type
- T|HumanTaskTimeoutError - The typed value submitted by the human, or a
HumanTaskTimeoutError
runChildWorkflow
Starts a child workflow and returns its instance ID without waiting for the result. The child is a true Temporal child workflow: its lifecycle is tied to this workflow, so when this workflow closes, in-flight children are cancelled with it.
Use getChildWorkflowResult (non-blocking) or waitForChildWorkflow (durable wait)
to read the child's result later — this enables fan-out/fan-in orchestration:
string kycId = check ctx->runChildWorkflow(kycWorkflow, input = customer); // fan out string scoreId = check ctx->runChildWorkflow(scoreWorkflow, input = customer); Kyc kyc = check ctx->waitForChildWorkflow(kycId); // gather Score score = check ctx->waitForChildWorkflow(scoreId);
Parameters
- childWorkflow
function() ()- The child workflow function (must have@Workflow)
- input anydata (default ()) - Optional input for the child workflow. Must match the child workflow
function's declared input parameter type (any
anydatasubtype)
getChildWorkflowResult
Returns the result of a child workflow started with runChildWorkflow if it has
already completed, without waiting. While the child is still running (e.g. suspended
on a human task) a workflow:WorkflowBusyError is returned — check back later, or
switch to the blocking waitForChildWorkflow form.
Kyc|error result = ctx->getChildWorkflowResult(kycId); if result is workflow:WorkflowBusyError { /* still running — do other work */ }
Parameters
- childWorkflowId string - The child workflow instance ID returned by
runChildWorkflow
- T typedesc<anydata> (default <>) - Expected result type (inferred from context)
Return Type
- T|error - The child's result as
T, aworkflow:WorkflowBusyErrorwhile the child is still running, or an error if the child failed
waitForChildWorkflow
Waits durably until a child workflow started with runChildWorkflow completes and
returns its result. The wait is a durable suspend — no thread is held, and the wait
survives worker crashes and restarts (on replay the result is served from history).
Parameters
- childWorkflowId string - The child workflow instance ID returned by
runChildWorkflow
- T typedesc<anydata> (default <>) - Expected result type (inferred from context)
Return Type
- T|error - The child's result as
T, or an error if the child failed
callWorkflow
function callWorkflow( function() () childWorkflow, anydata input, typedesc<anydata> T) returns T|errorStarts a child workflow and durably waits for its result — runChildWorkflow
followed by waitForChildWorkflow fused into one call. "Blocking" here is a durable
suspend, not a held thread, so this is safe for long-running children.
Receipt receipt = check ctx->callWorkflow(billingWorkflow, input = order);
Parameters
- childWorkflow
function() ()- The child workflow function (must have@Workflow)
- input anydata (default ()) - Optional input for the child workflow. Must match the child workflow
function's declared input parameter type (any
anydatasubtype)
- T typedesc<anydata> (default <>) - Expected result type (inferred from context)
Return Type
- T|error - The child's result as
T, or an error if the child failed
sendDataToChildWorkflow
function sendDataToChildWorkflow(string childWorkflowId, string dataName, anydata data) returns error?Sends data to a running workflow instance's events record from inside a workflow.
This is the in-workflow counterpart of workflow:sendData and is typically used to
signal a child workflow started with runChildWorkflow, but accepts any workflow
instance ID.
check ctx->sendDataToChildWorkflow(childId, "approval", {approved: true});
Parameters
- childWorkflowId string - Target workflow instance ID (usually from
runChildWorkflow)
- dataName string - Field name in the target workflow's events record
- data anydata - The data payload
Return Type
- error? - An error if sending fails
sleep
Durable sleep that survives process crashes and restarts. Do not use runtime:sleep() in workflows.
check ctx.sleep({seconds: 30});
Parameters
- duration Duration - The duration to sleep
Return Type
- error? - An error if the sleep fails, otherwise nil
currentTime
function currentTime() returns UtcReturns the deterministic workflow time. Use instead of time:utcNow() inside workflows.
time:Utc now = ctx.currentTime();
Return Type
- Utc - The current workflow time as
time:Utc
isReplaying
function isReplaying() returns booleanChecks whether the workflow is recovering from a failure (re-executing recorded history).
Return Type
- boolean -
trueif recovering,falseon first execution
getWorkflowId
Get the unique workflow ID.
getWorkflowType
Get the workflow type name.
Constants
workflow: NoAutomaticRetry
No automatic retry by the engine. Errors from the activity are returned
directly to the caller. This is the default behaviour when no retryPolicy
is specified. Note that an AI agent may still decide to call the activity
again from its own reasoning — this policy only disables engine-driven
retries.
workflow: NoRetry
DeprecatedDeprecated alias of NoAutomaticRetry.
Deprecated
Use NoAutomaticRetry instead: it makes explicit that only engine-driven
retries are disabled (an AI agent may still re-invoke the activity).
Enums
workflow: EventCardinality
How a declared event channel consumes its requests.
Members
workflow: Mode
Deployment mode for the workflow runtime.
Members
temporal server start-dev)Annotations
workflow: Activity
Marks a function as a workflow activity.
@workflow:Activity function sendEmail(EmailRequest req) returns EmailResponse|error { }
workflow: Workflow
Marks a function as a workflow.
@workflow:Workflow function orderProcess(Order input) returns OrderResult|error { }
Configurables
workflow: mode
Deployment mode for the workflow runtime.
LOCAL— Connects to a locally running server (e.g.,temporal server start-dev). This is the default mode.CLOUD— Managed cloud deployment. Requiresurl,namespace, and authentication (authApiKeyor mTLS certificate/key pair).SELF_HOSTED— Self-hosted server. Requiresurl; authentication is optional.IN_MEMORY— Lightweight in-memory engine with no external server. Workflows are not persisted and will be lost on restart. All other connection/scheduler fields are ignored in this mode.
workflow: url
Server URL for the workflow runtime.
For LOCAL mode, defaults to "localhost:7233".
For CLOUD mode, use the cloud endpoint (e.g., "
workflow: namespace
Workflow namespace.
For LOCAL and SELF_HOSTED modes, defaults to "default".
For CLOUD mode, use your cloud namespace (e.g., "
workflow: authApiKey
API key for bearer-token authentication. Required for CLOUD mode (unless mTLS is configured). Optional for SELF_HOSTED mode. Ignored in LOCAL and IN_MEMORY modes.
workflow: authMtlsCert
Path to the mTLS client certificate file (PEM format).
Used for CLOUD or SELF_HOSTED modes with mutual TLS authentication.
Must be provided together with authMtlsKey.
Ignored in LOCAL and IN_MEMORY modes.
workflow: authMtlsKey
Path to the mTLS client private key file (PEM format).
Used together with authMtlsCert for mutual TLS authentication.
Ignored in LOCAL and IN_MEMORY modes.
workflow: authCaCert
Path to the CA certificate file (PEM format) used to verify the server's TLS certificate. Set this when the Temporal server uses a certificate from a private or self-signed CA that is not in the JVM's default trust store. Applicable to CLOUD mode (API key over TLS) and SELF_HOSTED mode (TLS or mTLS). Ignored in LOCAL and IN_MEMORY modes.
workflow: taskQueue
Task queue name for workflow and activity polling. Each workflow program should use a unique task queue to avoid conflicts. Ignored in IN_MEMORY mode.
workflow: maxConcurrentWorkflows
Maximum number of concurrent workflow task executions. Controls how many workflow tasks the workflow scheduler processes in parallel. Must be a positive integer. Ignored in IN_MEMORY mode.
workflow: maxConcurrentActivities
Maximum number of concurrent activity executions. Controls how many activities the workflow scheduler processes in parallel. Must be a positive integer. Ignored in IN_MEMORY mode.
workflow: activityRetryInitialInterval
Initial delay (in seconds) before the first activity retry attempt.
Part of the default retry policy applied to all activities unless
overridden per-call via ActivityOptions (e.g., maxRetries, retryDelay).
Must be a positive integer.
workflow: activityRetryBackoffCoefficient
Backoff multiplier applied to the activity retry interval after each attempt. For example, with an initial interval of 1s and coefficient of 2.0, retries occur at 1s, 2s, 4s, 8s, etc. Must be >= 1.0.
workflow: activityRetryMaximumInterval
Maximum delay (in seconds) between activity retries. Caps the exponential backoff to prevent excessively long waits. 0 means unset/no upper limit and is allowed. When explicitly set to a non-zero value it must be a positive integer (> 0).
workflow: activityRetryMaximumAttempts
Maximum number of activity retry attempts.
- 1 means no retries (execute once only, the default).
- 0 means unlimited retries.
- Any positive value sets the retry cap.
Records
workflow: ActivityDecl
An activity capability of a durable agent, with optional gating and retry config.
For the no-config case pass the bare @workflow:Activity function instead.
Fields
- activity
function() ()- The@workflow:Activityfunction
- name? string - Tool name advertised to the model; defaults to the function name
- description? string - Tool description advertised to the model; defaults to the function's doc comment
- bindings? map<anydata|object {}> - Fixed arguments partially applied to the activity (e.g. a
connection), hidden from the model: only the remaining data parameters appear in the tool's schema. Client objects are bound by referencing their module-levelfinalvariable
- requiresApproval boolean(default false) - When
true, aPRE_RUNreview activity gates every call
- retryPolicy AutoRetry|HumanReview|NoAutomaticRetry(default NoAutomaticRetry) - Retry behaviour on failure, as for
ctx->callActivity
workflow: ActivityOptions
Options for activity execution via callActivity.
Fields
- retryOnError boolean(default false) - Enable automatic retries on failure (default:
false)
- maxRetries int(default 0) - Maximum retry attempts (default: 0, no retries)
- retryDelay decimal(default 1.0) - Initial delay in seconds before the first retry (default: 1.0)
- retryBackoff decimal(default 2.0) - Multiplier applied to delay after each retry (default: 2.0)
- maxRetryDelay? decimal - Cap on the delay between retries, in seconds
workflow: AutoRetry
Automatic retry configuration. When the activity fails, it is automatically retried according to the configured backoff policy.
Fields
- maxRetries int(default 3) - Maximum retry attempts (default: 3)
- retryDelay decimal(default 1.0) - Initial delay in seconds before the first retry (default: 1.0)
- retryBackoff decimal(default 2.0) - Multiplier applied to delay after each retry (default: 2.0)
- maxRetryDelay? decimal - Cap on the delay between retries, in seconds
workflow: DurableAgentConfig
The complete, self-declarative configuration of a durable agent. Capability kinds are separate fields so each renders as its own edge type in the diagram.
Fields
- systemPrompt SystemPrompt - The agent's identity: role + instructions (the per-run query
is appended as the user turn by
run)
- model ModelProvider - The model provider used for the agent's LLM calls
- inputType typedesc<anydata>?(default string) - The agent's workflow input type, used by
runand the management API start.string(the default) means the query text itself is the input; a data type declares a structuredruninput payload validated against it;()declares a no-input agent (started empty, typically driven by its event channels)
- resultType typedesc<anydata>?(default ()) - When declared, the agent produces a typed final result: as the
reasoning loop concludes, one more durable model call converts the
conversation outcome into this type, and
waitForResult/getResultreturn it.()keeps the final text response
- activities (ActivityDecl|
function() ())[](default []) -@workflow:Activityfunctions, bare or asActivityDeclwhen gating/roles/bindings are needed
- tools (ToolDecl|ToolConfig|BaseToolKit|
function() ())[](default []) - AI tools:@ai:AgentToolfunctions,ai:ToolConfigs, toolkits, orToolDeclwhen gating is needed
- events EventDecl[](default []) - Named event channels with request/response types and cardinality
- humanTasks HumanTaskDecl[](default []) - Human task capabilities. Capability names share one namespace across activities, tools, events, human tasks, and peers: a name claimed twice is rejected when the agent registers, so the program fails at startup
- peers PeerDecl[](default []) - Peer durable agents advertised as delegable tools
- maxIter int(default 16) - Hard cap on reasoning iterations per turn
workflow: Duration
A time duration, structurally identical to time:Duration. Declared in this module so
timeout fields render as first-class workflow forms without a cross-module type reference;
time:Duration values remain assignable.
Fields
- years int(default 0) - The duration in years
- months int(default 0) - The duration in months
- weeks int(default 0) - The duration in weeks
- days int(default 0) - The duration in days
- hours int(default 0) - The duration in hours
- minutes int(default 0) - The duration in minutes
- seconds decimal(default 0.0) - The duration in seconds
workflow: EventDecl
A named event channel of a durable agent. request/response capture both
sides' types and the channel's duplexity: a response type declares a duplex
(request-response) channel whose turn answers are read with
getDataResult/waitForDataResult; a nil response declares a one-way
channel — data flows in, no result is read back.
Fields
- name string - The channel name (unique across all of the agent's capabilities)
- request typedesc<anydata> - Type of the payload sent to the agent on this channel
- response typedesc<anydata>?(default ()) - Type of the agent's reply for this channel;
()for one-way channels
- cardinality EventCardinality(default MULTI_EVENT) - Business cardinality of the channel: re-armed per turn
(
MULTI_EVENT, the default) or consumed once (SINGLE_EVENT)
workflow: HumanTaskDecl
A human task capability of a durable agent.
Fields
- name string - The task name (unique across all of the agent's capabilities)
- resultType typedesc<anydata>(default anydata) - Expected result type; drives form schema generation and validation
- title? string - Short summary shown in the inbox; defaults to
name
- description? string - Additional context shown alongside the form
- timeout? Duration - Maximum time to wait for completion; omit to wait indefinitely
workflow: HumanTaskTimeoutDetail
Detail fields carried by a HumanTaskTimeoutError.
Fields
- taskName string - The
taskNamevalue passed toawaitHumanTask
- taskWorkflowId string - Temporal child workflow ID of the timed-out task instance
- timedOutAfter string - Configured deadline as an ISO-8601 duration (e.g.
"PT24H")
- timedOutAt string - ISO-8601 timestamp at which the timeout was recorded
workflow: PeerDecl
A peer durable agent advertised to this agent's model as a delegable tool. The framework runs the peer as a Temporal child workflow.
Fields
- agent DurableAgent - The peer
workflow:DurableAgent
- name string - Tool name advertised to the model (unique across all capabilities)
- description? string - What the peer does, for the model
- 'wait boolean(default true) - When
true(default) the delegation blocks durably for the peer's result; whenfalsethe peer runs async and replies oncallbackChannel
- callbackChannel? string - Declared event channel that receives the async peer's reply;
required when
wait = false
- requiresApproval boolean(default false) - When
true, aPRE_RUNreview activity gates the delegation
workflow: PendingAgentEvent
A data-event turn a durable agent has accepted but not yet answered. Returned
by getPendingAgentEvents so callers can rediscover in-flight event turns
after a crash and fetch their answers via DurableAgent.getDataResult /
waitForDataResult.
Fields
- token string - The turn's correlation token (as returned by
DurableAgent.sendData)
- eventName string - The event channel the turn was sent on
workflow: ToolDecl
An AI tool capability of a durable agent, with optional gating config. For the
no-config case pass the ai:ToolConfig/ai:BaseToolKit/@ai:AgentTool function
directly.
Fields
- tool BaseToolKit|ToolConfig|FunctionTool - The tool: an
@ai:AgentToolfunction, anai:ToolConfig, or a toolkit
- requiresApproval boolean(default false) - When
true, aPRE_RUNreview activity gates every call
Errors
workflow: AgentBusyError
Returned by the non-blocking getResult/getDataResult reads when the agent
instance (or the specific turn) is still in progress — e.g. suspended on a human
task. Check back later, or use the blocking waitForResult/waitForDataResult
forms, which durably wait and are resumable across crashes.
workflow: HumanTaskTimeoutError
Returned by awaitHumanTask when no human acts within the configured deadline.
Catch with on fail workflow:HumanTaskTimeoutError e to run compensation logic.
workflow: WorkflowBusyError
Returned by the non-blocking ctx->getChildWorkflowResult read when the child
workflow is still running (e.g. suspended on a human task). Check back later, or
use the blocking ctx->waitForChildWorkflow form, which durably suspends until
the child completes.
Union types
workflow: HumanReview
HumanReview
Human-review retry policy: the role(s) permitted to decide the retry review.
Passing a role name (or list of role names) as the retryPolicy creates a
review task on activity failure so a matching human can decide to retry,
retry with different input, or permanently fail. The task name is derived
automatically from the activity being called.
Simple name reference types
workflow: ManualRetry
DeprecatedManualRetry
Deprecated alias of HumanReview.
Deprecated
Use HumanReview instead.
Import
import ballerina/workflow;Metadata
Released date: 1 day ago
Version: 0.8.2
License: Apache-2.0
Compatibility
Platform: java21
Ballerina version: 2201.13.4
GraalVM compatible: No
Pull count
Total: 3621
Current verison: 17
Weekly downloads
Keywords
workflow
Contributors