Investigation: workflow engine boundary is overcomplicated (executor.ts + dag-executor.ts)
Issue: Draft
Type: ARCHITECTURE
Investigated: 2026-04-12
Problem
The workflow execution layer is carrying too many concerns across two overlapping entrypoints:
Today the engine owns:
- execution order / orchestration
- provider resolution and capability warnings
- platform message delivery
- tool-call formatting
- approval / cancel / timeout handling
- workflow event persistence
- structured-output fallback behavior
- retry classification
This makes workflow behavior harder to extend safely, and it duplicates policy in more than one place. The biggest smell is that both executor.ts and dag-executor.ts define their own safe message-delivery wrappers and adjacent execution policy.
First Principles
The workflow engine should primarily own:
- node scheduling
- state transitions
- execution results
It should not also be the place where platform delivery policy, provider-specific user warnings, and every edge-case message path are embedded.
Evidence
- Duplicate message delivery primitives:
- Provider resolution and workflow/platform concerns are mixed in the DAG layer:
dag-executor.ts is very large and now serves as both engine and delivery adapter:
Desired End State
Split the workflow execution system into clearer layers:
-
execution kernel
- node ordering
- dependency handling
- retries / cancellation semantics
- execution results
-
provider execution adapter
- invoke providers
- consume normalized
MessageChunks
- map provider outcomes into node results
-
platform delivery layer
- best-effort message sending
- tool formatting
- SSE / chat delivery policy
- user-facing warnings
This does not require a rewrite. The goal is to stop accumulating more delivery/policy logic inside the engine.
Scope
In scope:
- reduce duplication between
executor.ts and dag-executor.ts
- extract shared message-delivery policy
- make workflow-engine responsibilities more explicit
- keep provider-specific logic out of the scheduling layer
Out of scope:
- changing workflow YAML semantics
- provider registry / Phase 2 work
- large UI changes
Acceptance Criteria
Validation
bun run type-check
bun --filter @archon/workflows test
bun run lint
Metadata
- Investigated by: Codex
- Timestamp: 2026-04-12
- Artifact:
.claude/PRPs/issues/issue-workflow-engine-boundary-refactor.md
Investigation: workflow engine boundary is overcomplicated (
executor.ts+dag-executor.ts)Issue: Draft
Type: ARCHITECTURE
Investigated: 2026-04-12
Problem
The workflow execution layer is carrying too many concerns across two overlapping entrypoints:
Today the engine owns:
This makes workflow behavior harder to extend safely, and it duplicates policy in more than one place. The biggest smell is that both
executor.tsanddag-executor.tsdefine their own safe message-delivery wrappers and adjacent execution policy.First Principles
The workflow engine should primarily own:
It should not also be the place where platform delivery policy, provider-specific user warnings, and every edge-case message path are embedded.
Evidence
dag-executor.tsis very large and now serves as both engine and delivery adapter:Desired End State
Split the workflow execution system into clearer layers:
execution kernel
provider execution adapter
MessageChunksplatform delivery layer
This does not require a rewrite. The goal is to stop accumulating more delivery/policy logic inside the engine.
Scope
In scope:
executor.tsanddag-executor.tsOut of scope:
Acceptance Criteria
executor.tsanddag-executor.tsValidation
bun run type-check bun --filter @archon/workflows test bun run lintMetadata
.claude/PRPs/issues/issue-workflow-engine-boundary-refactor.md