Skip to main content

The Agentic Layer

Workflow Configuration

One file orchestrates the entire workflow. Phase ordering, loop limits, gate bindings, tool permissions, template routing. This is the control plane.

workflow.yaml: The Control Plane

The workflow.yaml file is the central config for your agentic layer. It defines which phases run, in what order, how many retries each loop gets, what happens on failure, and which gates and templates apply. Every other artifact in the agentic layer is referenced from here.

Two approaches to workflow definition

Declarative (YAML + engine)

A workflow.yaml file defines phases, gates, loops, and escalation rules. A separate workflow engine reads the YAML and orchestrates execution. This is the approach shown throughout this page.

When to use it: When you want one engine to serve multiple projects, or when non-engineers need to configure workflow behavior. The workflow definition is data, not code.

Trade-off: You need to build or adopt a workflow engine that interprets the YAML. The engine is a significant piece of software: phase orchestration, state management, retry logic, escalation routing.

Imperative (scripts)

Orchestrator scripts chain phase executors together directly. Each script defines a workflow variant: which phases run, in what order, with what error handling. Different autonomy levels are different scripts (or the same script with different configuration parameters).

When to use it: When you're building for a single project, or when the workflow needs to do things YAML can't easily express (subprocess management, environment setup, notification formatting). The workflow definition is code, not data.

Trade-off: Workflow behavior is spread across script files rather than centralized in one config. Adding a new workflow variant means writing a new script (or parameterizing an existing one).

Which one is right?

The framework is agnostic. The important thing is that workflow configuration is separate from phase implementation. Your plan template shouldn't know whether it was invoked by a YAML engine or a Python script. The rest of this page uses YAML because it's easier to read in documentation, but every YAML example has an imperative equivalent.

Maturity note: Teams often start with imperative scripts (faster to build, easier to debug) and migrate to declarative config when they need to reuse the same engine across multiple projects.

Minimum viable vs full enterprise

Minimal ~10 lines
# workflow.yaml -- minimum viable config
# Enough to run the workflow with defaults

version: 1

phases:
  # - intent    # optional: requirement refinement
  - plan
  - build
  - test
  - review
  - deploy

# Everything else uses framework defaults:
# - Loop limits: 3
# - Escalation: human
# - Gates: built-in
# - Templates: prompts/{phase}.md

Imperative equivalent

The same workflow defined as a script:

# workflow_sdlc.py -- equivalent to the YAML above
phases = ["plan", "build", "test", "review", "deploy"]

for phase in phases:
    result = run_phase(phase, issue, state)

    if not result.success:
        if phase_config[phase].get("retry"):
            result = run_healing_loop(phase, result, max_retries=3)

        if not result.success:
            if phase_config[phase]["required"]:
                escalate(phase, result)
                break
            else:
                log_warning(phase, result)

The behavioral logic is identical. The difference is where the configuration lives (YAML file vs code).

Enterprise ~80 lines
# workflow.yaml -- full enterprise config

version: 1

# -- Phase Ordering ------
phases:
  - plan
  - build
  - test
  - review
  - document
  - deploy
  - monitor

# -- Template Routing ----
templates:
  plan:
    feature: prompts/plan-feature.md
    bug: prompts/plan-bug.md
    task: prompts/plan-task.md
    patch: prompts/plan-patch.md
    default: prompts/plan.md
  build: prompts/build.md
  test: prompts/test.md
  review: prompts/review.md
  document: prompts/document.md
  deploy: prompts/deploy.md
  monitor: prompts/monitor.md

# -- Feedback Loops ------
loops:
  test_retry:
    max: 3
    trigger: test.fail
    action: rebuild
    cooldown_ms: 5000
  review_patch:
    max: 3
    trigger: review.blockers
    action: rebuild_and_retest
    cooldown_ms: 5000
  full_rebuild:
    max: 1
    trigger: review.architectural
    action: replan_and_rebuild

# -- Escalation ----------
escalation:
  handler: human
  timeout_hours: 24
  notification:
    channel: engineering
  context:
    - plan
    - build_report
    - test_results
    - review_issues
    - failure_history

# -- Quality Gates -------
gates:
  after_build: gates/build-lint.yaml
  after_test: gates/test-coverage.yaml
  after_review: gates/review-severity.yaml
  after_document: gates/doc-completeness.yaml
  after_deploy: gates/deploy-readiness.yaml

# -- Tool Permissions ----
tools:
  configs:
    file_system: tools/file-system.yaml
    code_execution: tools/code-execution.yaml
    external_apis: tools/external-apis.yaml
    context_providers: tools/context-providers.yaml
  phase_overrides:
    plan:
      code_execution: disabled
      file_system.write: disabled
    review:
      code_execution: disabled
      file_system.write: disabled

# -- Parallel Execution --
parallel:
  - [document, deploy_prepare]

# -- Monitoring ----------
monitoring:
  track:
    - workflow_success_rate
    - average_iterations_per_loop
    - phase_duration_ms
    - cost_per_run
    - escalation_rate
  alert_on:
    escalation_rate_above: 0.3
    avg_iterations_above: 2.5

Configuration reference

Define which phases run and in what order. You can skip phases or reorder them. Default: plan, build, test, review, document, deploy, monitor.

# Skip document for quick patches
phases:
  - plan
  - build
  - test
  - review
  - deploy    # skip document for speed

Maximum retries per feedback loop. Too few (1) = every transient failure escalates. Too many (10) = workflow burns time on unfixable issues. Default: 3.

loops:
  test_retry:
    max: 3
  review_patch:
    max: 3
  full_rebuild:
    max: 1     # full rebuilds are expensive -- keep low

What happens when loops exhaust. Who gets notified, what context they receive, how long before auto-close.

escalation:
  handler: human          # human | auto_close | fallback_workflow
  timeout_hours: 24
  notification:
    channel: engineering
    mention: "@oncall"
  context:
    - plan
    - build_report
    - test_results
    - review_issues
    - failure_history

Map gate files to phase triggers. Reference external YAML or inline criteria.

gates:
  after_test: gates/test-coverage.yaml
  after_review: gates/review-severity.yaml
  after_document:
    inline:                          # inline gate definition
      criteria:
        has_changelog_entry: true
      on_fail: retry
      max_retries: 1

Override the default tool permission matrix for specific projects.

tools:
  phase_overrides:
    review:
      external_apis.browser: enabled  # enable visual review
    build:
      external_apis.git: disabled    # builds should not touch git

Use custom templates instead of defaults. Supports issue-type routing.

templates:
  plan:
    feature: prompts/plan-feature.md
    bug: prompts/plan-bug.md
    default: prompts/plan.md
  build: prompts/custom-build.md     # project-specific

Phases that can run concurrently. Only phases without data dependencies can run in parallel.

parallel:
  - [document, deploy_prepare]       # run at the same time

The complete directory structure

agentic-layer/
├── prompts/                          # Prompt templates
│   ├── plan.md                       # Default plan template
│   ├── plan-feature.md               # Issue-type routing variants
│   ├── plan-bug.md
│   ├── plan-task.md
│   ├── plan-patch.md
│   ├── build.md
│   ├── test.md
│   ├── review.md
│   ├── document.md
│   ├── deploy.md
│   └── monitor.md
├── gates/                            # Quality gate definitions
│   ├── test-coverage.yaml
│   ├── review-severity.yaml
│   ├── doc-completeness.yaml
│   ├── build-lint.yaml
│   └── deploy-readiness.yaml
├── tools/                            # Tool integration configs
│   ├── file-system.yaml
│   ├── code-execution.yaml
│   ├── external-apis.yaml
│   └── context-providers.yaml
├── commands/                         # Human-invoked commands
│   ├── commit.md
│   ├── security-audit.md
│   └── explain.md
├── skills/                           # Agent-invoked skills
│   ├── run-tests.md
│   ├── lint-check.md
│   └── dependency-check.md
└── workflow.yaml                     # Central orchestration config
DirectoryContentsTypical Count
prompts/One markdown file per phase, plus routing variants7-15 files
gates/One YAML file per quality gate3-5 files
tools/One YAML file per tool category4 files
commands/One markdown file per custom command3-10 files
skills/One markdown file per reusable skill3-10 files
Rootworkflow.yaml1 file

Configuration by team size

PHASES

Skip document

LOOP LIMITS

2 (save cost)

GATES

test-coverage only

TEMPLATES

Defaults, no routing

TOOLS

Minimal config

TOTAL FILES

~10

# Solo: fast and lean
phases: [plan, build, test, review, deploy]
loops:
  test_retry: { max: 2 }
  review_patch: { max: 2 }
gates:
  after_test: gates/test-coverage.yaml