Visual Workflows
Visual workflows let you build multi-step automations using a drag-and-drop builder in the dashboard. Unlike markdown-based workflows (defined as JSON or YAML files in ~/.zubo/workspace/workflows/), visual workflows are created entirely in the browser with an interactive canvas, step palette, and real-time execution preview.
Copy-Paste Task Cards
Secure API Access
Enable API auth and create a key before exposing ports beyond localhost.
zubo config set auth.enabled true
zubo auth create-key my-app
Set Local Model Fallback
Keep responses available during provider outages or API quota issues.
zubo config set failover '["openai","ollama"]'
zubo config set providers.ollama.model llama3.3
Common Errors
If auth.enabled is true, all /api/* calls require Authorization: Bearer <key>. Create a new key if needed.
curl -H "Authorization: Bearer YOUR_KEY" http://localhost:3000/api/dashboard/status
Use failover and switch temporarily to a responsive provider or smaller model. Check logs for repeated timeout patterns.
zubo model openai/gpt-4o-mini
zubo logs --follow
If local providers fail, ensure the runtime is running and a model is installed.
ollama serve
ollama pull llama3.3
Visual Workflows vs. Markdown Workflows
Zubo supports two workflow formats. Choose the one that fits your use case:
| Feature | Visual Workflows | Markdown Workflows |
|---|---|---|
| Creation | Dashboard drag-and-drop builder | JSON/YAML files in ~/.zubo/workspace/workflows/ |
| Step types | Tool, Agent, Condition, Message, Delay | Agent steps with dependency resolution |
| Triggers | Manual, Cron, Webhook | Manual, Cron |
| Variables | {{trigger.payload}}, {{steps.stepId.result}} | {{prev.result}}, named variables |
| Editing | Visual canvas in browser | Text editor |
| Best for | Interactive building, non-technical users, webhook-driven automation | Version control, CI/CD, complex pipelines |
Both formats are stored in the database and can be triggered via the API. Visual workflows are additionally accessible through the dashboard builder. Markdown workflows are documented in Agents & Workflows.
Step Types
Visual workflows are composed of steps. Each step has a type, a unique ID, optional configuration, and connections to other steps.
Tool Step
Execute a built-in tool or MCP tool. Configure the tool name and input parameters. The step result contains the tool's output.
{
"id": "search-web",
"type": "tool",
"tool": "web_search",
"input": {
"query": "{{trigger.payload.topic}} latest news"
}
}
Agent Step
Send a prompt to the agent (or a specific sub-agent) and capture the response. The agent has full access to tools and memory within the step.
{
"id": "summarize",
"type": "agent",
"agent": "default",
"prompt": "Summarize these search results: {{steps.search-web.result}}"
}
Condition Step
Branch the workflow based on a condition. Evaluates a JavaScript expression and routes to different steps based on the result.
{
"id": "check-sentiment",
"type": "condition",
"expression": "{{steps.analyze.result.sentiment}} === 'negative'",
"ifTrue": "escalate",
"ifFalse": "log-result"
}
Message Step
Send a message to a specific channel. Useful for notifications and alerts at any point in the workflow.
{
"id": "notify",
"type": "message",
"channel": "telegram",
"content": "Workflow complete. Result: {{steps.summarize.result}}"
}
Delay Step
Pause the workflow for a specified duration. Useful for rate limiting, waiting for external processes, or scheduling follow-ups.
{
"id": "wait",
"type": "delay",
"duration": "5m"
}
Duration supports shorthand notation: 30s (seconds), 5m (minutes), 2h (hours), 1d (days).
Trigger Types
Every workflow has a trigger that defines when it runs.
Manual Trigger
Run the workflow on demand via the dashboard or API. You can pass an optional payload that is available as {{trigger.payload}} in all steps.
{
"trigger": {
"type": "manual"
}
}
Cron Trigger
Run the workflow on a schedule using a cron expression. The trigger payload contains the scheduled time.
{
"trigger": {
"type": "cron",
"schedule": "0 9 * * 1-5"
}
}
Webhook Trigger
Run the workflow when a specific webhook receives an event. The full webhook payload is available as {{trigger.payload}}.
{
"trigger": {
"type": "webhook",
"webhookId": "wh_a1b2c3"
}
}
Template Variables
Template variables use double-brace syntax and are resolved at execution time. They allow data to flow between steps and from the trigger into the workflow.
| Variable | Description |
|---|---|
{{trigger.payload}} | The full payload from the trigger (webhook body, manual input, or cron metadata). |
{{trigger.payload.field}} | Access a specific field within the trigger payload using dot notation. |
{{steps.stepId.result}} | The output of a previously completed step, referenced by its step ID. |
{{steps.stepId.status}} | The status of a step: "completed", "failed", or "skipped". |
{{workflow.name}} | The name of the currently running workflow. |
{{workflow.runId}} | The unique ID of the current workflow execution. |
{{env.VARIABLE}} | Access an environment variable. |
Variable Resolution Example
# Step 1: Fetch data
{
"id": "fetch",
"type": "tool",
"tool": "http_request",
"input": { "url": "https://api.example.com/data/{{trigger.payload.id}}" }
}
# Step 2: Process with agent (references step 1 result)
{
"id": "process",
"type": "agent",
"prompt": "Analyze this data: {{steps.fetch.result}}"
}
# Step 3: Notify (references step 2 result)
{
"id": "notify",
"type": "message",
"channel": "telegram",
"content": "Analysis complete: {{steps.process.result}}"
}
Dashboard Builder
The visual workflow builder is accessible from the Workflows panel in the dashboard. It provides an interactive canvas for creating and editing workflows without writing JSON.
- Canvas — a zoomable, pannable workspace where steps are placed and connected. Drag steps from the palette on the left to add them to the canvas. Connect steps by dragging from one step's output handle to another step's input handle.
- Step palette — a sidebar listing all available step types (Tool, Agent, Condition, Message, Delay). Click or drag a step type to add it to the canvas.
- Step configuration — click any step on the canvas to open its configuration panel on the right. Configure the step type's specific fields (tool name, prompt text, condition expression, channel, duration).
- Trigger selector — the trigger is configured at the top of the canvas. Choose Manual, Cron, or Webhook and fill in the required fields.
- Test run — click the Run button to execute the workflow immediately with a test payload. Each step highlights in real time as it executes: blue for running, green for completed, red for failed.
- Execution history — the Runs tab shows all past executions of the workflow with their status, duration, trigger source, and step-by-step results.
- Auto-save — changes to the workflow are saved automatically as you edit. There is no explicit save button.
API Endpoints
All visual workflow endpoints are under /api/workflows/visual and require authentication when auth.enabled is true.
List Visual Workflows
GET /api/workflows/visual
Returns all visual workflows with their metadata, step count, and trigger type.
Response:
{
"workflows": [
{
"id": "vw_abc123",
"name": "Daily Report",
"trigger": { "type": "cron", "schedule": "0 9 * * 1-5" },
"stepCount": 4,
"enabled": true,
"lastRunAt": "2026-02-15T09:00:00Z",
"lastRunStatus": "completed",
"createdAt": "2026-02-10T12:00:00Z"
}
]
}
Get Visual Workflow
GET /api/workflows/visual/:id
Returns the full workflow definition, including all steps, connections, and trigger configuration.
Create Visual Workflow
POST /api/workflows/visual
Content-Type: application/json
{
"name": "Daily Report",
"trigger": { "type": "cron", "schedule": "0 9 * * 1-5" },
"steps": [
{
"id": "fetch-news",
"type": "tool",
"tool": "web_search",
"input": { "query": "tech news today" }
},
{
"id": "summarize",
"type": "agent",
"prompt": "Summarize: {{steps.fetch-news.result}}"
},
{
"id": "send",
"type": "message",
"channel": "telegram",
"content": "{{steps.summarize.result}}"
}
],
"connections": [
{ "from": "fetch-news", "to": "summarize" },
{ "from": "summarize", "to": "send" }
]
}
Create a new visual workflow. Returns the created workflow with its generated id.
Update Visual Workflow
PUT /api/workflows/visual/:id
Content-Type: application/json
{
"name": "Updated Report",
"steps": [...],
"connections": [...]
}
Update a workflow's name, trigger, steps, or connections. All fields are optional — only included fields are updated.
Delete Visual Workflow
DELETE /api/workflows/visual/:id
Delete a workflow and all its execution history. Returns 204 No Content on success.
Run Visual Workflow
POST /api/workflows/visual/:id/run
Content-Type: application/json
{
"payload": { "topic": "AI research" }
}
Execute a workflow immediately with an optional payload. The payload is available as {{trigger.payload}} in all steps. Returns the run ID for tracking execution.
Response:
{
"runId": "run_xyz789",
"status": "started",
"workflowId": "vw_abc123"
}
Get Workflow Runs
GET /api/workflows/visual/:id/runs?limit=20
Returns the execution history for a workflow.
Response:
{
"runs": [
{
"runId": "run_xyz789",
"status": "completed",
"trigger": "manual",
"startedAt": "2026-02-15T14:00:00Z",
"completedAt": "2026-02-15T14:00:12Z",
"durationMs": 12340,
"steps": [
{ "id": "fetch-news", "status": "completed", "durationMs": 3200 },
{ "id": "summarize", "status": "completed", "durationMs": 8100 },
{ "id": "send", "status": "completed", "durationMs": 420 }
]
}
]
}
Toggle Visual Workflow
PUT /api/workflows/visual/:id/toggle
Content-Type: application/json
{
"enabled": false
}
Enable or disable a workflow. Disabled workflows do not execute on their cron or webhook triggers but can still be run manually via the API.