Skip to content

Instantly share code, notes, and snippets.

@thgaskell
Last active February 7, 2026 05:44
Show Gist options
  • Select an option

  • Save thgaskell/ac58711459ba4cf12589c84a0f4e5819 to your computer and use it in GitHub Desktop.

Select an option

Save thgaskell/ac58711459ba4cf12589c84a0f4e5819 to your computer and use it in GitHub Desktop.
Team Workflow Orchestrator — A Claude Code skill for orchestrating multi-step agent workflows using Agent Teams

Team Workflow Orchestrator for Claude Code Agent Teams

A Claude Code skill that orchestrates multi-step agent workflows using the Agent Teams feature. Define your entire workflow in a YAML file — steps, dependencies, custom agents, conditional branching, retry loops — and let the orchestrator coordinate a team of agents to execute it.

Motivations

Claude Code shipped task management skills earlier this week most likely in preparation for the Agent Team feature that's currently behind the CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS flag.

I worked on creating a skill that could:

  1. Read in a file that specified an entire workflow (steps, dependencies, agents/prompts, etc)
  2. Could reliably call the tasks without blowing up the main context window. (This was not very reliable since the main task would inconsistently call the TaskOutput tool which would dumped the entire subagent session jsonl file).

Fortunately, the SendMessage tool seems to have fixed this, and more importantly, supports the YAML configuration that was vibed up.

If you're just starting out with Agent Teams, I'd recommend trying this out as a starting point. The mermaid diagram is really to just help visualize the workflow rather than trying to interpret from the step declarations. But it also helps to reinforce the workflowflow when the model interprets the file.

You can even reference these Gist files and ask the model to create a new workflow file for your own use case!

Prerequisites

  • Claude Code CLI with Agent Teams enabled:
    export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1

Installation

  1. Copy team-workflow.md into your project's .claude/commands/ directory
  2. Place your workflow YAML files in .claude/workflows/ (or wherever you want)
your-project/
├── .claude/
│   ├── commands/
│   │   └── team-workflow.md    # The skill
│   └── workflows/
│       └── agent-loop.yml        # Example: implement + verify loop

Usage

/team-workflow <@path/to/workflow.yml> <task description>

The @ file reference expands the YAML inline. Everything after it is the task prompt.

Examples

# Run an implement-and-verify loop
/team-workflow @.claude/workflows/agent-loop.yml "Add input validation to the login form"

Workflow YAML Structure

Top-Level Fields

Field Required Description
name Yes Workflow identifier
description No Human-readable description
diagram No Mermaid diagram for visualization (also reinforces flow for the model)
agents No Reusable custom agent templates
inputs No Declared inputs with names, descriptions, defaults
steps Yes The workflow steps to execute

agents — Custom Agent Templates

Define reusable agent personas that steps can reference by name. Each agent gets system instructions that are prepended to the step prompt.

agents:
  security-expert:
    instructions: |                  # Required — system prompt for the agent
      You are a security auditor...
    tools: [Read, Grep, Glob]        # Optional — tool restrictions
    model: sonnet                    # Optional — haiku, sonnet, or opus

inputs — Workflow Parameters

Declare inputs that can be referenced in prompts via {{input.name}}.

inputs:
  - name: path
    description: Path to the code to analyze
    required: true
  - name: focus
    description: "Analysis focus: security, performance, quality, or auto"
    default: auto

steps — Workflow Steps

Each step defines an agent to run, what it depends on, and what prompt to give it.

steps:
  explore:
    agent: auto                    # Agent selection (see below)
    model: haiku                   # Optional model override
    prompt: |
      Explore the codebase at {{input.path}}...

  security_scan:
    agent: security-expert         # Reference to agents: section
    depends_on: [explore]          # Blocks until explore completes
    condition: "{{input.focus}} contains 'security'"  # Conditional execution
    prompt: |
      Codebase overview:
      {{explore.output}}           # Interpolated from previous step
      ...

  report:
    agent: general-purpose
    depends_on: [security_scan, perf_check]
    join: any                      # Runs when ANY dependency completes (vs all)
    prompt: |
      {{security_scan.output}}{{perf_check.output}}
      ...

Step Fields

Field Required Description
agent Yes Agent to use (see Agent Resolution below)
prompt Yes The task prompt, supports {{variable}} interpolation
depends_on No List of step names that must complete first
condition No Expression that must be true for step to run
join No all (default) or any — when to unblock with multiple dependencies
model No Model override: haiku, sonnet, or opus
on_failure No Retry configuration (see Retry Loops below)

Agent Resolution

Agent spec What happens
Explore, Plan, Bash, general-purpose Uses that agent type directly
auto Auto-selects based on prompt keywords (explore → Explore, test → Bash, etc.)
agent-name Looks up in agents: section, prepends instructions to prompt
Inline {instructions:, tools:, model:} Creates an ephemeral one-off agent

Inline Ephemeral Agents

For one-off specialized agents, define them inline on the step:

steps:
  adaptive_analysis:
    agent:
      name: adaptive-analyzer
      instructions: |
        You are an adaptive code analyst who determines
        the most pressing concerns...
      tools: [Read, Grep, Glob]
    prompt: |
      Analyze the codebase...

Template Variables

Pattern Resolves to
{{input.name}} Value from workflow inputs or defaults
{{input.task}} The task description from the command invocation
{{step_name.output}} Output from a completed step

Conditions

Steps can be conditionally skipped:

condition: "{{input.focus}} contains 'security'"   # substring match
condition: "{{verify.output}} contains 'VERDICT: PASS'"
condition: "{{step.output}} exists"                 # step completed
condition: "not {{step.output}} empty"              # not empty

Skipped steps produce "SKIPPED: condition not met" as their output.

Retry Loops

Steps can define on_failure to retry from an earlier step:

verify:
  depends_on: [run_tests, code_review]
  prompt: |
    Output VERDICT: PASS or VERDICT: FAIL
  on_failure:
    goto: plan          # Step to retry from
    max_retries: 3      # Max retry cycles

When VERDICT: FAIL is detected, the orchestrator re-runs from goto forward, injecting failure context into the prompt.

Parallel Execution

The orchestrator automatically parallelizes steps using dependency layers:

Layer 0: [explore]              → runs first (no dependencies)
Layer 1: [scan, check, review]  → run in parallel (all depend on explore)
Layer 2: [report]               → runs after Layer 1 completes

Steps in the same layer are spawned as parallel team members.

How It Works

The orchestrator:

  1. Parses the YAML into a dependency graph
  2. Topologically sorts steps into parallel layers
  3. Creates a team via the Agent Teams API
  4. Walks layers in order, spawning all agents in a layer simultaneously
  5. Waits for completion, then interpolates outputs into the next layer's prompts
  6. Handles retries if a step fails and has on_failure configured
  7. Cleans up the team after all steps complete

Example Workflow

  • agent-loop.yml — Retry loop: explores → plans → implements → tests + reviews → verifies (retries on failure) → reports
name: agent-loop
description: Simple task → plan → implement → verify loop with retry on failure
# ┌─────────────────────────────────────────────────────┐
# │ Task → Plan → Implement → Verify (loop on failure) │
# └─────────────────────────────────────────────────────┘
diagram: |
graph TD
A[task_intake] --> B[plan]
B --> C[implement]
C --> D[run_tests]
C --> E[code_review]
D --> F{verify}
E --> F
F -->|PASS| G[report]
F -->|FAIL| B
agents:
code-reviewer:
instructions: |
You are a thorough code reviewer. Compare the implementation against the plan
and verify that all requirements are met.
For each requirement in the plan, check:
1. Is it implemented correctly?
2. Are there edge cases missed?
3. Is the code clean and follows project conventions?
Your output MUST end with one of:
- VERDICT: PASS — all requirements met, code is correct
- VERDICT: FAIL — list what needs to be fixed
tools: [Read, Grep, Glob]
model: sonnet
inputs:
- name: task
description: Description of the coding task (feature, bug fix, refactor, etc.)
required: true
- name: path
description: Path to the relevant code or project root
default: "."
- name: max_retries
description: Maximum number of plan→implement→verify retry cycles
default: 3
steps:
# Step 1: Understand the task and codebase context
task_intake:
agent: Explore
model: haiku
prompt: |
Explore the codebase at {{input.path}} to understand the project context
for the following task:
{{input.task}}
Identify:
- Project structure, language, and framework
- Files most relevant to the task
- Existing patterns and conventions
- Any tests or test infrastructure present
# Step 2: Create an implementation plan
plan:
agent: Plan
depends_on: [task_intake]
prompt: |
Create a clear, actionable implementation plan for the following task.
Task:
{{input.task}}
Codebase context:
{{task_intake.output}}
{{verify.output}}
Your plan MUST include:
1. Summary of changes needed
2. Specific files to create or modify
3. Step-by-step implementation approach
4. Expected behavior after implementation
5. How to verify correctness (test cases to add/run)
# Step 3: Execute the plan
implement:
agent: general-purpose
depends_on: [plan]
prompt: |
Implement the changes described in the plan below.
Plan:
{{plan.output}}
Requirements:
- Follow existing code style and conventions
- Add or update tests as specified in the plan
- Make only the changes described — do not over-engineer
# Step 4a: Run the test suite
run_tests:
agent: Bash
depends_on: [implement]
prompt: |
Run the project's test suite to verify the implementation.
Detect the project type and run the appropriate test command:
- Node.js: npm test or npx jest
- Python: pytest or python -m pytest
- Go: go test ./...
- Rust: cargo test
- Or check for a Makefile / package.json scripts
Report the full test output including pass/fail counts.
If no test infrastructure exists, note that and report PASS.
# Step 4b: Review the code against the plan
code_review:
agent: code-reviewer
depends_on: [implement]
prompt: |
Review the implementation against the original plan.
Task:
{{input.task}}
Plan:
{{plan.output}}
Read the files that were changed and verify the implementation
is correct, complete, and follows the plan.
# Step 5: Evaluate results and decide pass/fail
verify:
agent: general-purpose
model: haiku
depends_on: [run_tests, code_review]
prompt: |
Evaluate the test results and code review to determine if the
implementation is complete and correct.
Test results:
{{run_tests.output}}
Code review:
{{code_review.output}}
If ALL of the following are true, output VERDICT: PASS
- Tests pass (or no test failures introduced)
- Code review found no critical issues
Otherwise, output VERDICT: FAIL and list the specific issues
that need to be addressed in the next iteration.
You MUST output exactly one of:
- VERDICT: PASS
- VERDICT: FAIL
on_failure:
goto: plan
max_retries: "{{input.max_retries}}"
# Step 6: Final summary (only reached on PASS)
report:
agent: general-purpose
model: haiku
depends_on: [verify]
condition: "{{verify.output}} contains 'VERDICT: PASS'"
prompt: |
Write a brief summary of what was accomplished.
Task:
{{input.task}}
Plan:
{{plan.output}}
Test results:
{{run_tests.output}}
Code review:
{{code_review.output}}
Format:
- What was done (1-3 bullet points)
- Files changed
- Test status

Team Workflow Orchestrator

Execute multi-step agent workflows as coordinated teams. The YAML's depends_on field is the sole source of truth for parallelism and blocking.

Usage

/team-workflow <@workflow.yml> <task description>

The @workflow.yml file reference expands inline. Everything after it is the task prompt.

Arguments

$ARGUMENTS


Orchestration Instructions

You are a team workflow orchestrator. You will parse a workflow YAML, create an agent team, execute steps in dependency order, and handle retries on failure.

Phase 1: Parse Arguments

The arguments contain two parts:

  1. Workflow definition — the YAML content from the @file reference. Look for YAML structure with name:, steps:, and optionally agents:, inputs:, diagram:.
  2. Task prompt — the remaining text after the YAML content. This is the high-level task description that maps to {{input.task}} in workflow templates.

Extract both. If no YAML is found, ask the user to provide a workflow file.

Phase 2: Build Execution Graph

From the parsed workflow:

  1. Build a dependency graph from each step's depends_on field
  2. Topological sort into layers — a layer is a set of steps whose dependencies are all in earlier layers. Steps with no dependencies form Layer 0.
  3. Evaluate condition gates to determine which steps will run vs skip
  4. Note any on_failure retry loops
  5. Resolve agents: section templates for custom agent definitions

Display the execution plan before starting:

📋 Workflow: <name>
   <description>

🔄 Execution Plan:
   Layer 0: [step1, step2] → parallel team members
   Layer 1: [step3] → team member (blocked by step1, step2)
   Layer 2: [step4, step5] → parallel team members (blocked by step3)
   Layer 3: [step6] → team member (conditional: PASS)

Phase 3: Execute

  1. Create team immediately:

    Teammate(operation: "spawnTeam", team_name: "<workflow-name>")
    
  2. Initialize state:

    state = {
      input: { task: "<prompt>", ...parsed inputs },
      steps: {}  // step_name -> output string
    }
    
  3. Walk layers in order. For each layer:

    a. Create tasks + spawn team members in parallel — use a single message with multiple Task tool calls for all steps in the layer:

    // For EACH step in the layer, create a task then spawn an agent:
    
    // 1. Create task
    TaskCreate(subject: "Step: <name>", description: "<prompt>", activeForm: "<-ing form>")
    
    // 2. Assign and mark in-progress
    TaskUpdate(taskId: "<id>", owner: "<agent-name>", status: "in_progress")
    
    // 3. Spawn agent as team member
    Task(
      name: "<descriptive-name>",
      subagent_type: "general-purpose",
      model: step.model || agent.model || default,
      team_name: "<workflow-name>",
      mode: "default",
      prompt: "<role instructions if custom agent>\n\n<interpolated step prompt>\n\n<TEAM COORDINATION RULES>"
    )
    

    b. All agents use subagent_type: "general-purpose" — for custom agents defined in the agents: section, prepend the agent's instructions to the step prompt:

    ## Your Role
    <agent.instructions>
    
    ## Task
    <step.prompt>
    

    c. Respect model from the step definition or agent definition.

    d. Wait for all agents in the layer to complete before moving to the next layer. Wait passively for teammate messages — do NOT poll TaskList in a loop.

    e. Extract outputs from completed tasks and store in state.steps[name].output. Interpolate {{step.output}} from completed steps into next layer's prompts.

  4. After all layers complete, clean up team (see Cleanup Protocol).

Critical: Include these exact instructions in every team member prompt:

TEAM COORDINATION RULES — you MUST follow these:
1. Do NOT create new tasks or use TaskCreate. You are already assigned to task #<ID>. Focus on the implementation work, not task management.
2. When finished, update task #<ID>'s description with your results using TaskUpdate.
3. Mark task #<ID> as completed using TaskUpdate(taskId: "<ID>", status: "completed").
4. Send a message to the team lead summarizing what you did:
   SendMessage(type: "message", recipient: "team-lead", content: "<summary>", summary: "<5 words>")

Retry Loop Handling

When a step has on_failure:

on_failure:
  goto: plan          # step to retry from
  max_retries: 3      # max retry cycles

Detection: After the step completes, check its output for failure indicators:

  • Look for VERDICT: FAIL in the output
  • Check if the step's condition evaluates to false

On failure:

  1. Increment retry counter
  2. Inject failure context into the goto step's prompt:
    PREVIOUS ATTEMPT FAILED. Issues to address:
    <failure output>
    
    This is retry <N> of <max_retries>.
    
  3. Re-execute from the goto step forward (re-run all downstream steps)
  4. Shut down and replace any team members from the previous attempt

On max retries exceeded:

  • Report failure with all attempt outputs
  • Do NOT continue to conditional success steps

Condition Evaluation

For steps with condition:

  • {{x.output}} contains 'VERDICT: PASS' → check substring
  • {{x.output}} exists → step completed (not skipped)
  • {{x.output}} empty → output is empty
  • not <expr> → negation

If condition is false, skip the step and mark it in state:

state.steps[name].output = "SKIPPED: condition not met"

Cleanup Protocol

After the workflow completes (or fails after max retries):

  1. Shut down all team members:

    SendMessage(type: "shutdown_request", recipient: "<name>", content: "Workflow complete.")
    

    Wait for agents to acknowledge or go idle, then proceed.

  2. Clean up team:

    Teammate(operation: "cleanup")
    
  3. Final report:

    📋 Workflow: <name> — <PASS or FAIL>
    
    Steps:
      ✅ step1 (team: "scanner") — 12s     ┐ Layer 0 (parallel)
      ✅ step2 (team: "checker") — 15s      ┘ Layer 0 (parallel)
      ✅ step3 (team: "analyzer") — 30s       Layer 1
      ✅ step4 (team: "reporter") — 5s        Layer 2 (conditional)
    
    Retries: 0 of 3
    
    Result:
      <output from final/terminal step>
    

Anti-Patterns to Avoid

These were discovered through empirical testing:

  1. Never pre-create all tasks with blockedBy chains and hope agents self-organize. Agents don't reliably pick up tasks from the shared list. The orchestrator must explicitly assign work and inject context.

  2. Never poll TaskList in a loop. After spawning team members, wait passively. Teammate messages are delivered to you automatically. If an agent appears stalled, the user may be reviewing permission prompts — wait for user input rather than repeatedly checking. The user will tell you if an agent needs to be terminated.

  3. Always delete duplicate tasks. Team member agents tend to create their own tasks despite being told not to. Check TaskList after each step and delete any tasks that weren't created by the orchestrator.

  4. Always inject previous step outputs into prompts. The template variable system ({{step.output}}) only works if the orchestrator manually interpolates values. Agents cannot read other agents' outputs on their own.

  5. Always include the TEAM COORDINATION RULES verbatim in every team member prompt. Without them, agents create duplicate tasks, forget to update status, and fail to message the team lead.


Variable Interpolation Reference

Before passing a prompt to any agent, replace all template variables:

Pattern Replacement
{{input.task}} The user's task prompt
{{input.<name>}} Named input value (from workflow inputs + defaults)
{{<step>.output}} Stored output from completed step

If a referenced step hasn't completed yet (e.g., in retry context), replace with empty string and note in a comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment