Skip to the content.

ADR-005: Plan-First, Human-Checkpointed Workflow

Status: Accepted
Date: 2026-05-09

Context

Embercore automates multi-step marketing workflows using LLM-powered agents. A typical workflow might involve research → copywriting → design brief → assembly. Two execution philosophies were considered:

  1. Autonomous execution — The system plans and executes without human intervention. Fast, but risky for brand-sensitive marketing content.
  2. Plan-first with checkpoints — Generate a plan, let humans review it, then execute with approval gates. Slower, but ensures quality and brand alignment.

Marketing teams need to maintain control over brand voice, messaging accuracy, and strategic alignment. Fully autonomous AI-generated marketing content poses reputational risk.

Decision

We implement a plan-first, human-checkpointed workflow with pause/resume support.

Phase 1: Plan generation (Athena)

Athena generates a structured plan spec from a natural-language brief:

// plan/plan.go
type Spec struct {
    Name        string  `yaml:"name"`
    Description string  `yaml:"description"`
    Input       Input   `yaml:"input"`
    Steps       []Step  `yaml:"steps"`
}

type Step struct {
    Name       string   `yaml:"name"`
    Agent      string   `yaml:"agent"`
    Prompt     string   `yaml:"prompt"`
    DependsOn  []string `yaml:"depends_on"`
    Checkpoint bool     `yaml:"checkpoint"`
}

Plans are validated (plan.Validate) and topologically sorted (plan.TopoSort via Kahn’s algorithm) to determine execution order and parallelizable layers.

Phase 2: Human review

Before execution, the generated plan can be:

Phase 3: Checkpoint-gated execution (Hermes)

Hermes executes the plan step by step. Steps marked checkpoint: true trigger an approval gate:

// agents/hermes/hermes.go
type CheckpointHandler func(step plan.Step, output string) (approved bool, feedback string, err error)

At each checkpoint:

  1. Hermes pauses execution and presents the step output
  2. The handler (interactive stdin prompt or MCP request_approval tool) asks for human approval
  3. If approved → execution continues to the next step
  4. If rejected → feedback is captured, and the step can be re-executed or the run paused

Phase 4: Pause and resume

Execution state is persisted in SQLite (via Hestia) and on the filesystem (internal/state/):

CLI workflow

# Step 1: Generate a plan
embercore plan --model claude-sonnet-4-20250514 "Launch campaign for new product"

# Step 2: Review the plan
embercore status <plan-id>

# Step 3: Execute with checkpoint approvals
embercore run <plan-id>

# Step 4: Resume if paused
embercore resume <run-id>

Consequences

Benefits:

Trade-offs:

Related decisions: