Dynamic Workflows - Durable Execution for workflows and agents
Skip to content
Initializing search
GitHub
Guides
Tasks
Event Bus Orchestration
Best Practices
FAQ
Cookbook
AI Cookbook
Token Efficiency
SDKs
Reference
Workflow Definition
System Tasks
Operators
Task Definition
Event Handlers
Configuration
Metrics
Deploy
Dynamic workflows for agents
Conductor supports three levels of agent dynamism, from simple tool use to fully self-generating agents.
Agent loop: plan/act/observe with DO_WHILE
The defining pattern of an autonomous agent is the loop: call an LLM, execute a tool, observe the result, decide whether to continue. Conductor models this with DO_WHILE:
"name": "autonomous_agent",<br>"description": "Agent that loops until the task is complete",<br>"version": 1,<br>"schemaVersion": 2,<br>"tasks": [<br>"name": "agent_loop",<br>"taskReferenceName": "loop",<br>"type": "DO_WHILE",<br>"loopCondition": "if ($.loop['think'].output.result.done == true) { false; } else { true; }",<br>"loopOver": [<br>"name": "think",<br>"taskReferenceName": "think",<br>"type": "LLM_CHAT_COMPLETE",<br>"inputParameters": {<br>"llmProvider": "anthropic",<br>"model": "claude-sonnet-4-20250514",<br>"messages": [<br>"role": "system",<br>"message": "You are an agent. Available tools: ${workflow.input.tools}. Previous results: ${loop.output.results}. Respond with JSON: {\"action\": \"tool_name\", \"arguments\": {}, \"done\": false} or {\"answer\": \"...\", \"done\": true}"<br>},<br>"role": "user",<br>"message": "${workflow.input.task}"<br>],<br>"temperature": 0.1<br>},<br>"name": "act",<br>"taskReferenceName": "act",<br>"type": "SWITCH",<br>"evaluatorType": "javascript",<br>"expression": "$.think.output.result.done ? 'done' : 'call_tool'",<br>"decisionCases": {<br>"call_tool": [<br>"name": "execute_tool",<br>"taskReferenceName": "tool_call",<br>"type": "CALL_MCP_TOOL",<br>"inputParameters": {<br>"mcpServer": "${workflow.input.mcpServerUrl}",<br>"method": "${think.output.result.action}",<br>"arguments": "${think.output.result.arguments}"<br>},<br>"defaultCase": []<br>],<br>"outputParameters": {<br>"answer": "${loop.output.think.output.result.answer}",<br>"iterations": "${loop.output.iteration}"
What makes this durable:
Each iteration of the loop is a persisted checkpoint. If the agent crashes at iteration 12, it resumes from iteration 12 — not from iteration 1.
Every LLM call (prompt, response, token usage) is recorded. You can inspect exactly what the agent decided at each step.
Every tool call (input, output, status) is tracked. If a tool call fails, it retries according to the task's retry policy without re-running the LLM.
The loop counter and all intermediate state survive server restarts.
Dynamic workflow generation: agents that build their own plans
Conductor supports dynamic workflow execution where the complete workflow definition is provided at start time, without pre-registration. This is the most powerful form of agent dynamism — the LLM generates the entire execution plan as JSON, and Conductor runs it immediately.
An LLM generates a plan as a JSON workflow definition.
Your code passes that definition directly to the StartWorkflowRequest.
Conductor validates, persists, and executes it immediately.
Every step is durable, observable, and retryable — even though the workflow was generated at runtime.
"name": "dynamic_agent_planner",<br>"version": 1,<br>"schemaVersion": 2,<br>"tasks": [<br>"name": "generate_plan",<br>"taskReferenceName": "planner",<br>"type": "LLM_CHAT_COMPLETE",<br>"inputParameters": {<br>"llmProvider": "anthropic",<br>"model": "claude-sonnet-4-20250514",<br>"messages": [<br>"role": "system",<br>"message": "You are a workflow planner. Given a user task, generate a Conductor workflow definition as JSON. Available task types: LLM_CHAT_COMPLETE, CALL_MCP_TOOL, LIST_MCP_TOOLS, HTTP, HUMAN, LLM_SEARCH_INDEX. The workflow must include a 'name', 'tasks' array, and 'outputParameters'."<br>},<br>"role": "user",<br>"message": "${workflow.input.task}"<br>],<br>"temperature": 0.2<br>},<br>"name": "review_plan",<br>"taskReferenceName": "approval",<br>"type": "HUMAN",<br>"inputParameters": {<br>"generatedWorkflow": "${planner.output.result}"<br>},<br>"name": "execute_plan",<br>"taskReferenceName": "execution",<br>"type": "START_WORKFLOW",<br>"inputParameters": {<br>"startWorkflow": {<br>"workflowDefinition": "${planner.output.result}",<br>"input": "${workflow.input.taskInput}"<br>],<br>"outputParameters": {<br>"generatedPlan": "${planner.output.result}",<br>"executionId": "${execution.output.workflowId}"
What happens:
planner — LLM_CHAT_COMPLETE generates an entire workflow definition as JSON based on the user's task description.
approval — HUMAN task pauses the workflow so a reviewer can inspect the generated plan before it runs. This is critical — you don't want an LLM-generated workflow executing unsupervised.
execution — START_WORKFLOW launches the generated workflow definition directly. Conductor validates it, persists it, and executes it with full durability. No pre-registration needed.
The generated child workflow gets all the same guarantees as any Conductor workflow: persisted state, retry policies,...