Orchestrations
On this page
Creating an orchestrationOrchestration statusNode typesInput mappingCondition expressionsTrigger typesExternal agentsExecuting an orchestrationMCP and A2A integrationExport and importVisual builderRun historyAPI referenceLimitsOrchestrations let you compose tools, agents, conditional logic, and parallel execution into DAG-based workflows. While pipelines chain tools sequentially, orchestrations support branching, fan-out/fan-in, loops, external agent invocation, and sub-orchestration nesting.
Active orchestrations are automatically exposed as MCP tools and A2A skills, just like pipelines.
Creating an orchestration
Dashboard
Navigate to Orchestrations in the sidebar. Click New Orchestration, enter a name, and you'll land in the visual builder. Add nodes from the palette, draw edges between them, and configure each node in the side panel.
API
curl -X POST https://api.fold.run/orchestrations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "classify-and-route",
"description": "Classify input then route to handler",
"trigger_type": "manual",
"nodes": [
{ "id": "trigger_1", "type": "trigger", "label": "Start", "config": { "type": "trigger", "trigger_type": "manual" }, "position": { "x": 250, "y": 0 } },
{ "id": "agent_1", "type": "agent", "label": "Classify", "config": { "type": "agent", "agent_type": "local", "prompt_template": "Classify: {{data}}" }, "position": { "x": 250, "y": 120 } },
{ "id": "output_1", "type": "output", "label": "Result", "config": { "type": "output", "output_type": "return" }, "position": { "x": 250, "y": 240 } }
],
"edges": [
{ "id": "e1", "source": "trigger_1", "target": "agent_1" },
{ "id": "e2", "source": "agent_1", "target": "output_1" }
]
}'Orchestration status
| Status | Description |
|---|---|
draft |
Being built. Can be executed for testing but not exposed via MCP/A2A. |
active |
Live. Auto-registered as orchestration:{name} MCP tool and A2A skill. |
archived |
Disabled. Cannot be executed. |
Node types
Every orchestration is a directed graph of nodes connected by edges. Each node has a type that determines its behavior.
| Type | Purpose | Handles |
|---|---|---|
trigger |
Entry point. Exactly one per orchestration. | Source of input data. |
tool |
Execute a deployed MCP tool (function). | Same dispatch as pipeline steps. |
agent |
Invoke an agent — your workspace's Fold Agent or an external A2A agent. | Prompt templates, skill selection. |
condition |
Branch based on an expression. Two outgoing edges: true and false. | If/else routing. |
parallel |
Fan out to multiple downstream nodes concurrently. | Concurrent execution. |
merge |
Wait for parallel branches to complete, then collect results. | Strategy: wait for all or first. |
loop |
Repeat connected nodes until a condition is false or max iterations reached. | Iterative processing. |
sub_orchestration |
Execute another orchestration as a nested step. | Composition and reuse. |
output |
Terminal node. Returns the result, sends to a webhook, or delivers to a channel. | Final delivery. |
Input mapping
Nodes can map their input from prior node outputs, the trigger input, or literal values.
| Source | Format | Example |
|---|---|---|
| Trigger input | $trigger.fieldName |
$trigger.message |
| Node output | $nodes.nodeId.field |
$nodes.agent_1.output.category |
| Literal value | literal:value |
literal:en |
Dot notation supports nested paths: $nodes.scorer.output.results.score.
If no input_mapping is specified, the output of the previous node is passed through directly.
Condition expressions
Condition nodes and loop continue-conditions evaluate simple expressions:
$nodes.classifier.output.category == "urgent"
$nodes.scorer.output.score > 0.8
$trigger.priority != "low"
$nodes.validator.output.valid exists| Operator | Description |
|---|---|
== |
Equal (string comparison) |
!= |
Not equal |
> < >= <= |
Numeric comparison |
contains |
Left string contains right substring |
exists |
Value is not null or undefined |
The left side is always a node or trigger reference. The right side is a literal (string in quotes, number, true, false, null).
Trigger types
The trigger node determines how the orchestration is started.
| Type | How it fires |
|---|---|
manual |
Executed via API call or dashboard button. |
webhook |
HTTP request to https://{org}.fold.run/_orchestrations/{name}. |
schedule |
Cron expression evaluated every minute. |
event |
Reserved for future event-driven triggers. |
Webhook example
Set trigger_type to webhook, then POST to your organization's subdomain:
curl -X POST https://my-org.fold.run/_orchestrations/classify-and-route \
-H "Content-Type: application/json" \
-d '{ "message": "My server is down" }'Schedule example
Set trigger_type to schedule with a cron expression in trigger_config:
{
"trigger_type": "schedule",
"trigger_config": { "cron": "0 9 * * 1-5" }
}This fires the orchestration every weekday at 9 AM.
External agents
Orchestrations can invoke agents outside your organization via A2A or MCP.
Registering an external agent
curl -X POST https://api.fold.run/external-agents \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "url": "https://other-agent.example.com", "protocol": "a2a" }'The platform fetches the agent's card (.well-known/agent.json for A2A or tool list for MCP), caches its skills, and makes it available in the orchestration builder.
Using an external agent in a node
Set the agent node to agent_type: "external", reference the registered agent by ID, and select a skill:
{
"type": "agent",
"agent_type": "external",
"external_agent_id": "ext_abc123",
"skill": "summarize",
"input_mapping": { "text": "$nodes.fetcher.output.content" }
}Refreshing metadata
POST /external-agents/{id}/refreshRe-fetches the agent card and updates cached skills. Agents marked unreachable are automatically flagged if discovery fails.
Executing an orchestration
API
curl -X POST https://api.fold.run/orchestrations/orch_abc/execute \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "input": { "message": "Help with billing" } }'The response includes the final output and per-node results:
{
"id": "orchrun_xyz",
"orchestration_id": "orch_abc",
"status": "completed",
"output": { "category": "billing", "response": "Routing to billing team..." },
"node_results": [
{ "node_id": "trigger_1", "node_type": "trigger", "status": "success", "duration_ms": 0 },
{ "node_id": "agent_1", "node_type": "agent", "status": "success", "duration_ms": 450 },
{ "node_id": "output_1", "node_type": "output", "status": "success", "duration_ms": 1 }
],
"duration_ms": 451
}Durable execution
For long-running orchestrations, add ?durable=true to execute via the durable workflow engine. The orchestration runs with automatic crash recovery and retries. The response returns immediately with a running status — poll the run endpoint for completion.
Dashboard
Open an orchestration and click Run in the header. Results appear in the run history below the builder.
MCP and A2A integration
Active orchestrations are automatically registered as:
- MCP tool:
orchestration:{name}— callable via your/.well-known/mcpendpoint - A2A skill:
orchestration:{name}— callable viatasks/sendortasks/sendSubscribeat/_a2a/
Streaming execution via tasks/sendSubscribe emits per-node results as artifact events over Server-Sent Events.
Export and import
Export
GET /orchestrations/{id}/exportReturns a portable JSON document with fold-orchestration/v1 format. Use this to back up orchestrations or share them between workspaces.
Import
curl -X POST https://api.fold.run/orchestrations/import \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @my-workflow.orchestration.jsonImported orchestrations start in draft status. The name must be unique within the workspace.
Visual builder
The dashboard includes a visual DAG builder at Orchestrations > {name}:
- Add nodes from the palette at the top (9 node types available)
- Draw edges by dragging from a node's output handle to another node's input handle
- Click a node to open the configuration panel on the right
- Condition nodes have two output handles — true (left) and false (right)
- Configure input mappings, agent prompts, conditions, and output destinations per node
- Save, toggle status, run, and export from the header
Run history
Each execution is recorded with per-node results. View runs at Orchestrations > {name} or click a run ID to see the full detail page with input/output JSON for every node.
GET /orchestrations/{id}/runs # List runs
GET /orchestrations/runs/{runId} # Get specific runAPI reference
| Method | Path | Description |
|---|---|---|
POST /orchestrations |
Create orchestration | |
GET /orchestrations |
List orchestrations | |
GET /orchestrations/:id |
Get orchestration | |
PUT /orchestrations/:id |
Update orchestration (bumps version) | |
DELETE /orchestrations/:id |
Delete orchestration | |
POST /orchestrations/:id/execute |
Execute orchestration | |
GET /orchestrations/:id/runs |
List runs | |
GET /orchestrations/runs/:runId |
Get run details | |
GET /orchestrations/:id/export |
Export as JSON | |
POST /orchestrations/import |
Import from JSON | |
POST /external-agents |
Register external agent | |
GET /external-agents |
List external agents | |
GET /external-agents/:id |
Get external agent details | |
POST /external-agents/:id/refresh |
Refresh agent metadata | |
DELETE /external-agents/:id |
Remove external agent |
Limits
- Maximum 50 nodes per orchestration
- Maximum 100 edges per orchestration
- Sub-orchestration nesting depth: 5 levels
- Loop max iterations: 50
- Orchestration name must match
^[a-z0-9][a-z0-9-]*$(max 63 characters) - External agent discovery timeout: 10 seconds
- External agent invocation timeout: 25 seconds