06. Dynamic Workflows — Automatic Task Decomposition and Phase Execution
Learning Objectives
After completing this tutorial, you will be able to:
- Explain what the
--dynamicflag does internally - Automatically decompose complex tasks into phases and execute them
- Inspect workflow structure and status with
euleragent workflow show - Handle phase-by-phase approvals and resume with
euleragent workflow resume - Integrate with external systems via the REST API (
euleragent serve) - Decide when to choose
--dynamicversus regular patterns
Prerequisites
- Workspace initialization complete (
euleragent init) - Agent created:
euleragent new marketing-expert --template marketing-expert
workspace.yamlconfiguration:
cat .euleragent/config/workspace.yaml
llm_profiles:
local:
provider: ollama
base_url: http://localhost:11434
model: qwen3:32b # tool calling 지원 모델 필요
timeout_seconds: 120
keep_alive: 5m
is_external: false
openai:
provider: openai
api_key: ''
model: gpt-4o-mini
base_url: https://api.openai.com/v1
is_external: true
default_llm_profile: local # --dynamic은 실제 LLM 필수 (fake 불가)
rag:
web_search:
provider: fake # 테스트용 (실제: tavily | brave)
require_approval: true
Important:
--dynamicrequires the LLM to call thesystem.plan_workflowtool to decompose tasks. This feature does not work withdefault_llm_profile: fake. A real LLM such as Ollama or OpenAI is required.
What is --dynamic?
A regular euleragent run processes a task in a single agentic loop. When you add --dynamic, the LLM first automatically decomposes the task into multiple phases, then executes each phase sequentially.
Two-Stage Protocol
Stage 1 — Planning: Only the system.plan_workflow tool is provided to the LLM. The LLM decomposes the task into a list of phases.
{
"workflow_title": "마케팅 전략 분석",
"phases": [
{"title": "리서치", "task": "경쟁사 정보 수집", "mode": "plan"},
{"title": "분석", "task": "데이터 종합 분석", "mode": "plan"},
{"title": "보고서 작성", "task": "최종 리포트 생성", "mode": "execute"}
]
}
Stage 2 — Phase-by-Phase Execution:
- plan phases: Only web.search is provided to the LLM, which proposes search queries. These go to the approval queue, and the workflow pauses.
- execute phases: Collected results are injected into the context, and the final output is generated.
Phase Classification Rules
| Mode Keyword | Classification |
|---|---|
execute, synthesis, write, report, draft, create, generate, produce, compile |
execute phase |
research, gather, collect, search, analyze |
plan phase |
| If the last phase has none of these keywords | Automatically promoted to execute |
MCP search sources and workflow phases: In environments with MCP search providers configured, each workflow phase can use different search sources. For example, you can specify
--source-setto use academic sources (academic) during the research phase and news sources (news) during the analysis phase. The SearchRouter automatically routes to the appropriate MCP source based on each phase's query characteristics.
Step-by-Step Walkthrough
Step 1: Start a Workflow with --dynamic
euleragent run marketing-expert \
--task "LangChain, CrewAI, AutoGen 3개 AI 에이전트 프레임워크를 분석하고 EulerAI의 경쟁 전략 마케팅 보고서를 작성해줘. 웹 검색 결과 기반으로 작성해야 해." \
--dynamic
Internal behavior:
1. The LLM calls system.plan_workflow to decompose the task into phases
2. The runner classifies each phase (plan/execute)
3. WorkflowRunner executes the first phase
4. When web.search is proposed, the workflow automatically pauses
Expected output:
Workflow 'AI Framework Competitive Analysis' created (3 phases, run_id=a1b2c3d4e5f6)
Phase 0: [plan] 리서치 단계 — LangChain, CrewAI, AutoGen 정보 수집
Phase 1: [plan] 분석 단계 — 프레임워크 비교 및 EulerAI 포지셔닝
Phase 2: [execute] 보고서 작성 — 경쟁 마케팅 전략 보고서 생성
Workflow paused at phase 0 (2 approval(s) pending).
Use: euleragent approve accept-all --run-id a1b2c3d4e5f6 --actor "user:you" --execute
Then: euleragent workflow resume a1b2c3d4e5f6 --execute
Step 2: Check Workflow Status
euleragent workflow show a1b2c3d4e5f6
Expected output:
Workflow: AI Framework Competitive Analysis
Run ID: a1b2c3d4e5f6
Status: paused
Phases: 3 total, current=0
→ [0] 리서치 단계 (plan) — paused
Approvals pending: apv_001, apv_002
[1] 분석 단계 (plan) — pending
[2] 보고서 작성 (execute) — pending
View in JSON format:
euleragent workflow show a1b2c3d4e5f6 --format json
{
"workflow_id": "wf_x1y2z3",
"run_id": "a1b2c3d4e5f6",
"title": "AI Framework Competitive Analysis",
"status": "paused",
"current_phase": 0,
"phases": [
{
"index": 0,
"title": "리서치 단계",
"mode": "plan",
"status": "paused",
"pending_approvals": ["apv_001", "apv_002"]
},
{
"index": 1,
"title": "분석 단계",
"mode": "plan",
"status": "pending"
},
{
"index": 2,
"title": "보고서 작성",
"mode": "execute",
"status": "pending"
}
]
}
Inspect the workflow JSON file directly:
cat .euleragent/runs/a1b2c3d4e5f6/workflow.json
Step 3: Approve and Execute the First Phase
# 승인 목록 확인
euleragent approve list --run-id a1b2c3d4e5f6
Expected output:
Pending approvals (2):
ID TOOL RISK STATUS
apv_001 web.search medium pending
apv_002 web.search medium pending
Accept all approvals for the first phase and execute:
euleragent approve accept-all --run-id a1b2c3d4e5f6 --actor "user:you" --execute
Expected output:
Accepted and executed 2 approval(s).
[OK] web.search (apv_001) — "LangChain features 2025" → 5 results
[OK] web.search (apv_002) — "CrewAI AutoGen comparison" → 4 results
Executed 2/2 successfully.
Step 4: Resume the Workflow
Add the --execute flag to automatically handle approvals for all subsequent phases:
euleragent workflow resume a1b2c3d4e5f6 --execute
Expected output:
Resuming workflow 'AI Framework Competitive Analysis' from phase 0...
Phase 0 (리서치 단계) — approvals resolved → marked finished.
Starting phase 1 (분석 단계, plan)...
Phase 1 paused (1 new approval(s)) — auto-executing with --execute...
[OK] web.search (apv_003) — "EulerAI positioning AI agent market" → 3 results
Executed 1/1 — continuing...
Starting phase 2 (보고서 작성, execute)...
Phase 2 paused (1 new approval(s)) — auto-executing with --execute...
[OK] web.search (apv_004) — "EulerAI competitive advantages" → 4 results
Phase 2 re-running with search results injected (web.search excluded)...
LLM generating final report...
Workflow 'AI Framework Competitive Analysis' finished (run_id=a1b2c3d4e5f6).
Artifacts:
.euleragent/runs/a1b2c3d4e5f6/artifacts/phase_0/plan.md
.euleragent/runs/a1b2c3d4e5f6/artifacts/phase_1/plan.md
.euleragent/runs/a1b2c3d4e5f6/artifacts/phase_2/result.md
What
--executedoes: It automatically accepts and executes new approvals that arise in subsequent phases. Without--execute, runningworkflow resumerequires manual handling each time a new approval is generated.
Step 5: Review Artifacts
Each phase's output is stored in a separate subdirectory:
ls .euleragent/runs/a1b2c3d4e5f6/artifacts/
phase_0/ phase_1/ phase_2/
# 리서치 단계 결과 (plan.md: 검색 제안 및 요약)
cat .euleragent/runs/a1b2c3d4e5f6/artifacts/phase_0/plan.md
# 분석 단계 결과 (plan.md: 비교 분석)
cat .euleragent/runs/a1b2c3d4e5f6/artifacts/phase_1/plan.md
# 최종 보고서 (result.md: 마케팅 전략 리포트)
cat .euleragent/runs/a1b2c3d4e5f6/artifacts/phase_2/result.md
Full run directory structure:
.euleragent/runs/a1b2c3d4e5f6/
├── input.json # 실행 입력 (플래닝 메타데이터)
├── messages.jsonl # 모든 단계의 LLM 대화 기록 (누적)
├── tool_calls.jsonl # 모든 단계의 도구 호출 기록 (누적)
├── approvals.jsonl # 모든 승인 기록 (누적)
├── workflow.json # 최종 워크플로우 상태
├── workflow_events.jsonl # 이벤트 로그 (created/started/paused/resumed/finished)
├── search_routing.jsonl # 검색 라우팅 결정 기록 (MCP 사용 시)
└── artifacts/
├── phase_0/
│ └── plan.md
├── phase_1/
│ └── plan.md
└── phase_2/
└── result.md
If you are using MCP search providers, each phase's search routing decisions are recorded in search_routing.jsonl:
cat .euleragent/runs/a1b2c3d4e5f6/search_routing.jsonl
{"phase": 0, "query": "LangChain features 2025", "routed_to": "tavily", "source_set": "default", "timestamp": 1740268215.0}
{"phase": 0, "query": "CrewAI AutoGen comparison", "routed_to": "brave", "source_set": "default", "timestamp": 1740268216.0}
{"phase": 1, "query": "EulerAI positioning AI agent market", "routed_to": "tavily", "source_set": "default", "timestamp": 1740268240.0}
Check the workflow event history:
cat .euleragent/runs/a1b2c3d4e5f6/workflow_events.jsonl
{"type": "workflow.created", "run_id": "a1b2c3d4e5f6", "phases": 3, "timestamp": 1740268200.0}
{"type": "workflow.phase.started", "phase_id": "phase_0", "mode": "plan", "timestamp": 1740268210.0}
{"type": "workflow.paused", "phase_id": "phase_0", "approval_ids": ["apv_001", "apv_002"], "timestamp": 1740268215.0}
{"type": "workflow.resumed", "phase_id": "phase_0", "timestamp": 1740268230.0}
{"type": "workflow.phase.finished", "phase_id": "phase_0", "timestamp": 1740268231.0}
{"type": "workflow.phase.started", "phase_id": "phase_1", "mode": "plan", "timestamp": 1740268232.0}
{"type": "workflow.phase.finished", "phase_id": "phase_1", "timestamp": 1740268250.0}
{"type": "workflow.phase.started", "phase_id": "phase_2", "mode": "execute", "timestamp": 1740268251.0}
{"type": "workflow.finished", "run_id": "a1b2c3d4e5f6", "timestamp": 1740268310.0}
Step 6: REST API — euleragent serve
Use the REST API when integrating with CI/CD pipelines or dashboards:
# 터미널 1: 서버 시작
euleragent serve
Expected output:
euleragent API server running at http://localhost:8844
WebSocket: ws://localhost:8844/ws/events
Press Ctrl+C to stop.
API calls from terminal 2:
# 런 상태 확인
curl http://localhost:8844/runs/a1b2c3d4e5f6/status
{"run_id": "a1b2c3d4e5f6", "state": "paused", "agent": "marketing-expert"}
# 워크플로우 상태 확인
curl http://localhost:8844/runs/a1b2c3d4e5f6/workflow
{
"status": "paused",
"current_phase": 0,
"phases": [{"index": 0, "status": "paused"}, ...]
}
# 승인 목록 조회
curl "http://localhost:8844/approvals?run_id=a1b2c3d4e5f6"
[
{"id": "apv_001", "tool_name": "web.search", "status": "pending"},
{"id": "apv_002", "tool_name": "web.search", "status": "pending"}
]
# CI/CD: 모든 승인 일괄 수락 + 실행
curl -X POST \
"http://localhost:8844/approvals/accept-all?run_id=a1b2c3d4e5f6&execute=true"
{"accepted": 2, "executed": 2, "failed": 0}
Receive real-time events via WebSocket:
# wscat 설치: npm install -g wscat
wscat -c ws://localhost:8844/ws/events
{"type": "server.connected", "timestamp": 1740268200.0}
{"type": "workflow.phase.started", "run_id": "a1b2c3d4e5f6", "phase_id": "phase_1"}
{"type": "workflow.paused", "run_id": "a1b2c3d4e5f6", "approval_ids": ["apv_003"]}
{"type": "workflow.finished", "run_id": "a1b2c3d4e5f6"}
--dynamic vs Regular Patterns — Selection Guide
| Situation | Recommended Approach |
|---|---|
| Simple task with clear steps | Regular euleragent run |
| Multiple web searches followed by report generation | --dynamic |
| Complex task where decomposition is unclear | --dynamic |
| Running the same pipeline repeatedly | Formalize with --task-file |
| Complex dependencies between steps | --dynamic |
| Quick single task | Regular euleragent run --mode execute |
| CI/CD automation | euleragent serve + REST API |
Expected Output Summary
# 워크플로우 생성
Workflow 'AI Framework Competitive Analysis' created (3 phases, run_id=a1b2c3d4e5f6)
Phase 0: [plan] 리서치 단계
Phase 1: [plan] 분석 단계
Phase 2: [execute] 보고서 작성
Workflow paused at phase 0 (2 approval(s) pending).
# 워크플로우 상태 확인
euleragent workflow show a1b2c3d4e5f6
→ [0] 리서치 단계 (plan) — paused
[1] 분석 단계 (plan) — pending
[2] 보고서 작성 (execute) — pending
# 승인 후 재개
euleragent workflow resume a1b2c3d4e5f6 --execute
Phase 1 auto-executing... [OK] web.search
Phase 2 re-running with results injected...
Workflow finished.
FAQ / Common Errors
Q: I get the error "Agent did not call system.plan_workflow."
--dynamic requires a real LLM. Check that default_llm_profile in workspace.yaml is not set to fake:
default_llm_profile: local # fake가 아닌 실제 LLM 프로필
Verify that Ollama is running and a model with tool calling support is available:
ollama list
ollama serve
Q: All phases are shown as [plan] and no result.md is generated.
When working correctly, the last phase is automatically promoted to execute. This feature may not be present in older versions. Upgrade and try again:
pip install -e . --upgrade
To verify manually:
euleragent workflow show <run-id> --format json | python3 -m json.tool
# 마지막 phase의 "mode" 확인
Q: The workflow keeps pausing at the same phase after workflow resume.
Check if there are remaining pending approvals:
euleragent approve list --run-id a1b2c3d4e5f6
If there are still pending approvals:
euleragent approve accept-all --run-id a1b2c3d4e5f6 --actor "user:you" --execute
euleragent workflow resume a1b2c3d4e5f6 --execute
Q: The workflow immediately finishes without any approval steps.
This was a bug in earlier versions. In the latest version, only web.search is provided to the LLM during plan phases, ensuring search proposals are always generated. Upgrade and try again.
Also verify that web.search is included in the agent's tools.yaml allowlist:
cat .euleragent/agents/marketing-expert/tools.yaml
# allowlist에 web.search 포함 여부 확인
Q: I want to change the default port for euleragent serve.
euleragent serve --port 9000
Then access it at http://localhost:9000.
Common Mistakes (Order Issues)
| Symptom | Cause | Recovery |
|---|---|---|
Error: No workflow found for run 'X'. |
Tried workflow resume on a run executed without --dynamic |
euleragent run <agent> --task '...' --dynamic |
Error: Run 'X' not found. |
Incorrect run ID | ls .euleragent/runs/ |
| Pending approvals remain, cannot resume | Approvals not fully processed | euleragent approve accept-all --run-id <id> --execute |
Next step: 07_web_rag.md — Learn how to combine web search with a local knowledge base (RAG).