Skip to main content

Workflow JSON Format

GenieBuilder workflows can be exported as JSON files and imported into any GenieBuilder instance. This page documents the transfer format so you can create workflows programmatically, share them across teams, or have an AI agent generate them for you.

Agent-driven workflow creation

Have an agent point at this schema and ask it to create anything you want. Then import the JSON into GenieBuilder for agentic execution.

Top-Level Wrapper

Every workflow JSON file uses this envelope:

{
"format": "genie-builder.workflow",
"version": 1,
"exportedAt": "2026-03-27T12:00:00.000Z",
"workflow": { ... }
}
FieldTypeRequiredDescription
formatstringYesMust be "genie-builder.workflow" (the legacy "devoxx-genie.workflow" is also accepted on import)
versionnumberYesMust be 1 (current version)
exportedAtstringYesISO 8601 timestamp of when the file was created
workflowobjectYesThe workflow definition (see below)

Workflow Object

The workflow object contains the full definition:

FieldTypeRequiredDescription
namestringYesDisplay name of the workflow
descriptionstringYesShort description of what the workflow does
nodesarrayYesArray of node objects
edgesarrayYesArray of edge objects
branchTemplatestringYesGit branch name template (supports template variables)
commitTemplatestringYesCommit message template
prTemplatestringYesPull request body template
createGitBranchbooleanNoWhether to create a feature branch per run (default: true)
edgeTypestringNoVisual edge routing style: "default", "straight", "step", or "smoothstep"

Nodes

Every node shares these base fields:

FieldTypeRequiredDescription
idstringYesUnique identifier within the workflow
typestringYesOne of "start", "step", "decision", "end"
labelstringYesDisplay label shown in the editor
positionobjectYes{ "x": number, "y": number } — canvas coordinates

Start Node

Every workflow must have exactly one start node. It configures iteration limits and optional task/branch bindings.

{
"id": "start",
"type": "start",
"label": "Start",
"position": { "x": 0, "y": 0 },
"config": {
"maxIterations": 3,
"taskId": "task-123",
"baseBranch": "main"
}
}
Config FieldTypeRequiredDescription
maxIterationsnumberNoMaximum retry iterations (default: 3)
taskIdstringNoPre-bound task ID (usually left empty so the user picks one at run time)
baseBranchstringNoBase branch for PRs (usually left empty to use the current branch)

Step Node

Steps are the workhorses of a workflow — each one sends a prompt to an LLM executor.

{
"id": "implement",
"type": "step",
"label": "Implement Changes",
"position": { "x": 0, "y": 200 },
"executor": {
"type": "cli-runner",
"id": "claude-code"
},
"toolSet": {
"git": true,
"backlog": true,
"shell": false
},
"promptTemplate": "Implement the task:\n\nTitle: {{task.title}}\nDescription: {{task.description}}",
"expectsVerdict": false,
"includeHistory": true,
"timeoutMs": 300000
}
FieldTypeRequiredDescription
executorobjectYesExecutor — see below
toolSetobjectNoTool permissions (defaults to all false)
promptTemplatestringNoPrompt sent to the executor (supports template variables)
expectsVerdictbooleanNoWhen true, the step must produce a structured verdict for decision routing
includeHistorybooleanNoWhen true (default), the executor receives conversation history from prior steps
timeoutMsnumberNoStep timeout in milliseconds

Executor

FieldTypeRequiredDescription
typestringYes"cli-runner" or "chat-provider"
idstringYesIdentifier of the runner or provider (e.g. "claude-code", "codex")
modelstringConditionalRequired when type is "chat-provider"; the model to use

Tool Set

FieldTypeDefaultDescription
gitbooleanfalseRead/write git operations
backlogbooleanfalseTask management access
shellbooleanfalseExecute shell commands

Decision Node

Decision nodes route execution based on conditions attached to their outgoing edges. They have no extra fields beyond the base.

{
"id": "review-gate",
"type": "decision",
"label": "Review Passed?",
"position": { "x": 0, "y": 400 }
}

End Node

End nodes terminate the workflow with a status.

{
"id": "done",
"type": "end",
"label": "Completed",
"position": { "x": 0, "y": 600 },
"status": "completed"
}
FieldTypeRequiredValues
statusstringYes"completed", "failed", or "cancelled"

Edges

Edges connect nodes and optionally carry conditions for decision routing.

{
"id": "edge-review-to-gate",
"source": "review",
"target": "review-gate",
"label": "Pass",
"condition": {
"and": [
{ "field": "verdict", "op": "eq", "value": "pass" }
]
}
}
FieldTypeRequiredDescription
idstringYesUnique edge identifier
sourcestringYesID of the source node
targetstringYesID of the target node
sourceHandlestringNoSource port identifier
targetHandlestringNoTarget port identifier
labelstringNoDisplay label on the edge
conditionobjectNoCondition that must be satisfied for the edge to be followed

Edge Conditions

Conditions use an and array of clauses — all must be true for the edge to activate.

{
"and": [
{ "field": "verdict", "op": "eq", "value": "fail" },
{ "field": "canRetry", "op": "eq", "value": true }
]
}

Each clause has:

FieldTypeDescription
fieldstringContext field to evaluate (e.g. "verdict", "canRetry", "iterationsExhausted")
opstringOperator: "eq", "neq", "gt", "lt", "gte", "lte"
valuestring | number | booleanValue to compare against

On decision nodes, one outgoing edge may omit the condition to act as the default (fallback) path.

Template Variables

Templates in branchTemplate, commitTemplate, prTemplate, and step promptTemplate fields support {{variable}} substitution:

VariableDescription
{{task.id}}Task identifier (e.g. "TASK-123")
{{task.title}}Task title
{{task.description}}Task description
{{task.slug}}URL-friendly task title
{{run.id}}Unique workflow run ID
{{run.iteration}}Current iteration number
{{run.maxIterations}}Maximum allowed iterations
{{run.branchName}}Generated git branch name
{{workspace.projectPath}}Absolute path to the project root
{{git.baseBranch}}Base branch for PRs
{{workflow.commitMessage}}Generated commit message
{{workflow.prBody}}Generated PR description
{{steps.<step-id>.summary}}Summary output from a previous step
{{steps.<step-id>.findings}}Structured findings from a verdict step

Workflows that reference {{task.*}} variables will prompt the user to select a task before starting a run.

Validation Rules

When a JSON file is imported, GenieBuilder validates the graph structure. Import is rejected if any of these rules fail:

RuleDescription
Non-empty graphThe workflow must contain at least one node
Exactly one start nodeThere must be exactly one node with type: "start"
At least one end nodeThere must be at least one node with type: "end"
No incoming edges on startThe start node must have no incoming edges
One outgoing edge from startThe start node must have exactly one outgoing edge
No outgoing edges from endEnd nodes must have no outgoing edges
Decision fan-outDecision nodes must have at least 2 outgoing edges
Single default edgeDecision nodes may have at most one unconditional (default) edge
Valid edge referencesEvery edge source and target must reference an existing node ID
All nodes reachableEvery node must be reachable from the start node via BFS traversal
chat-provider needs modelSteps using executor type "chat-provider" must specify a model

Complete Example

Below is a full, importable workflow that implements a task and then reviews the result with a feedback loop. Copy this JSON, save it as a .json file, and import it via the workflow editor toolbar.

{
"format": "genie-builder.workflow",
"version": 1,
"exportedAt": "2026-03-27T12:00:00.000Z",
"workflow": {
"name": "Implement & Review Loop",
"description": "A two-agent workflow: one implements a task, another reviews it, with a retry loop on failure.",
"branchTemplate": "feature/{{task.slug}}",
"commitTemplate": "feat: {{task.title}}",
"prTemplate": "## Summary\nImplements {{task.id}} — {{task.title}}\n\n## Description\n{{task.description}}",
"createGitBranch": true,
"edgeType": "smoothstep",
"nodes": [
{
"id": "start",
"type": "start",
"label": "Start",
"position": { "x": 300, "y": 0 },
"config": {
"maxIterations": 3
}
},
{
"id": "implement",
"type": "step",
"label": "Implement",
"position": { "x": 300, "y": 150 },
"executor": {
"type": "cli-runner",
"id": "claude-code"
},
"toolSet": {
"git": true,
"backlog": true,
"shell": true
},
"promptTemplate": "You are working on: {{task.title}}\n\n{{task.description}}\n\nImplement the changes in the project at {{workspace.projectPath}}. Follow existing code conventions.",
"expectsVerdict": false,
"includeHistory": true
},
{
"id": "review",
"type": "step",
"label": "Review",
"position": { "x": 300, "y": 300 },
"executor": {
"type": "cli-runner",
"id": "claude-code"
},
"toolSet": {
"git": true,
"backlog": false,
"shell": false
},
"promptTemplate": "Review the changes made for: {{task.title}}\n\nCheck for correctness, code quality, and test coverage. Output a structured verdict.",
"expectsVerdict": true,
"includeHistory": false
},
{
"id": "review-gate",
"type": "decision",
"label": "Review Passed?",
"position": { "x": 300, "y": 450 }
},
{
"id": "fix",
"type": "step",
"label": "Fix Issues",
"position": { "x": 550, "y": 300 },
"executor": {
"type": "cli-runner",
"id": "claude-code"
},
"toolSet": {
"git": true,
"backlog": false,
"shell": true
},
"promptTemplate": "The reviewer found issues:\n\n{{steps.review.summary}}\n\nFindings:\n{{steps.review.findings}}\n\nFix all reported issues in the project at {{workspace.projectPath}}.",
"expectsVerdict": false,
"includeHistory": true
},
{
"id": "done",
"type": "end",
"label": "Completed",
"position": { "x": 300, "y": 600 },
"status": "completed"
},
{
"id": "failed",
"type": "end",
"label": "Failed",
"position": { "x": 550, "y": 600 },
"status": "failed"
}
],
"edges": [
{
"id": "edge-start-implement",
"source": "start",
"target": "implement"
},
{
"id": "edge-implement-review",
"source": "implement",
"target": "review"
},
{
"id": "edge-review-gate",
"source": "review",
"target": "review-gate"
},
{
"id": "edge-gate-done",
"source": "review-gate",
"target": "done",
"label": "Pass",
"condition": {
"and": [
{ "field": "verdict", "op": "eq", "value": "pass" }
]
}
},
{
"id": "edge-gate-fix",
"source": "review-gate",
"target": "fix",
"label": "Fail + Retry",
"condition": {
"and": [
{ "field": "verdict", "op": "eq", "value": "fail" },
{ "field": "canRetry", "op": "eq", "value": true }
]
}
},
{
"id": "edge-gate-failed",
"source": "review-gate",
"target": "failed",
"label": "Exhausted"
},
{
"id": "edge-fix-review",
"source": "fix",
"target": "review"
}
]
}
}

How this workflow runs

  1. Start — initializes the run with up to 3 iterations
  2. Implement — an AI agent writes the code changes using git, backlog, and shell tools
  3. Review — a separate agent reviews the diff and produces a pass/fail verdict
  4. Review Passed? — routes based on the verdict:
    • Pass — proceeds to Completed
    • Fail + can retry — routes to Fix Issues, which loops back to Review
    • Iterations exhausted — falls through to Failed (default edge)
  5. The loop continues until the review passes or iterations run out

Importing and Exporting

  • Export: In the workflow editor, click the export button in the toolbar. The JSON file is saved to your downloads folder.
  • Import: Click the import button and select a .json file. If a workflow with the same name already exists, you can choose to create a copy or overwrite it.
Future format support

BPMN 2.0 notation import and export will be supported in a future release.