Dynamic ReACT Loop with Conductor

opiniateddev1 pts0 comments

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,...

workflow output loop name conductor task

Related Articles