How to Create Orchestration Skills that Coordinate Sub-Skills in Claude Plugins

Orchestration skills act as a "conductor" for multi-step workflows, sequencing existing sub-skills via Claude's Message-Calling-Protocol (MCP), handling data flow between steps, and managing user interactions without containing domain-specific logic.

The Claude Plugins Community repository demonstrates a battle-tested architectural pattern for building orchestration skills that delegate specialized work to sub-skills while maintaining clean separation of concerns. Rather than embedding low-level business logic, orchestrators contain only glue code to parse MCP payloads, invoke sub-skills, and coordinate execution sequences, making complex workflows modular and maintainable.

Minimal Core Logic and the Conductor Pattern

Effective orchestration skills follow the conductor pattern: they contain no domain-specific processing logic, only the coordination code necessary to sequence sub-skills and pass data forward. As implemented in the TRES Finance plugin's onboarding skill, the orchestrator "does not contain its own low-level logic – instead, it drives the user through 8 sequential steps, invoking the dedicated skill for each one" (tres-finance-plugin/skills/tres-onboarding/SKILL.md).

This architectural constraint ensures that:

  • Domain logic remains encapsulated in specialized sub-skills
  • Orchestration stays testable with minimal mocking requirements
  • Workflows remain flexible as steps can be rearranged without rewriting business logic

MCP-Driven Invocation and Data Flow

Each sub-skill invocation occurs through Claude's Message-Calling-Protocol (MCP). The orchestrator prepares JSON payloads representing the MCP request, delegates execution to Claude, then parses the response to extract data for subsequent steps.

In tres-finance-plugin/skills/tres-asc845-swap-reprice-skill/scripts/orchestrate_reprice.py, the orchestrator handles the full MCP lifecycle: parsing the JSON response, filtering data, creating a human-readable preview, and writing a mutation plan for the next execution step. This pattern appears in lines 14-27 and 38-48, where the script processes raw subtransaction data before forwarding it to domain-specific helpers.

#!/usr/bin/env python3
"""
General pattern for an orchestration skill.
1️⃣ Parse MCP JSON input.
2️⃣ Optionally filter / configure.
3️⃣ Call a low-level sub-skill (via an imported helper).
4️⃣ Print a preview for the user.
5️⃣ Write a machine-readable plan + mutation list.
"""
import argparse, json, sys
from reprice_swaps import build_reprice_plan, print_preview   # ← reusable logic

def main():
    parser = argparse.ArgumentParser(description="Example orchestrator")
    parser.add_argument("--input", "-i", required=True, help="MCP JSON input")
    parser.add_argument("--output", "-o", default="plan.json")
    parser.add_argument("--mutations-output", default="mutations.json")
    args = parser.parse_args()

    # 1️⃣ Load MCP payload

    with open(args.input) as f:
        raw = json.load(f)

    # 2️⃣ Normalise to a list of subtransactions

    subtxs = raw.get("data", {}).get("subTransaction", {}).get("results", [])
    
    # 3️⃣ Build the domain-specific plan

    plan = build_reprice_plan(subtransactions=subtxs)
    
    # 4️⃣ Show preview

    print_preview(plan)

    # 5️⃣ Persist plan & mutations

    with open(args.output, "w") as f:
        json.dump(plan, f, indent=2)

if __name__ == "__main__":
    main()

Standardized Input/Output Contracts

Orchestration scripts maintain strict contracts for data exchange. They accept a well-defined input file (typically the raw MCP JSON) and emit two distinct artifacts:

  • Human-readable preview: A formatted summary for user confirmation
  • Machine-readable plan: A JSON structure consumed by downstream mutation runners

The orchestrate_reprice.py script demonstrates this dual-output pattern in lines 92-100, where --output writes the reprice plan and --mutations-output writes the ready-to-execute mutation list. This separation allows Claude to present results to users while simultaneously preparing structured data for automated execution.

def generate_execution_script(plan, out_path):
    """Create a JSON file with mutation details Claude can execute."""
    execution = {
        "summary": plan["summary"],
        "mutation_template": {
            "query": """mutation SetManualFiatValue($id: ID!, $newFiatValue: String!, $currency: String) {
  setManualFiatValue(id: $id, newFiatValue: $newFiatValue, currency: $currency) {
    subTransaction { id fiatValue isManualFiatValue }
  }
}""",
            "note": "Execute one per inflow subtransaction."
        },
        "mutations": [
            {
                "variables": {
                    "id": m["subtx_id"],
                    "newFiatValue": m["new_fiat_value"],
                    "currency": m["currency"],
                },
                "description": f"Reprice subtx {m['subtx_id']}"
            }
            for m in plan.get("mutations", [])
        ],
        "total_mutations": len(plan.get("mutations", [])),
    }
    with open(out_path, "w") as f:
        json.dump(execution, f, indent=2)
    return execution

Filtering and Configuration Pass-Through

Orchestration skills expose command-line flags that narrow workflow scope without implementing filtering logic themselves. These flags are parsed and forwarded directly to the sub-skills performing the computation.

In the ASC-845 reprice orchestrator, flags like --account-name, --activity-tags, and --currency are defined in the argument parser and passed to build_reprice_plan (tres-finance-plugin/skills/tres-asc845-swap-reprice-skill/scripts/orchestrate_reprice.py, lines 98-104). This allows users to constrain operations while keeping the orchestrator agnostic of filtering implementation details.

parser.add_argument("--account-name", help="Filter by account")
parser.add_argument("--currency", default="usd")
args = parser.parse_args()

# Forward configuration to sub-skill

plan = build_reprice_plan(
    subtransactions=subtxs,
    target_name=args.account_name,
    currency=args.currency,
)

Progressive Roadmap Presentation for Users

User-facing orchestrators (such as the onboarding workflow) implement progressive disclosure by confirming intent, gathering context, then displaying a plain-text roadmap before execution begins. The roadmap enumerates the sequence of sub-skills that will run, setting clear expectations.

According to tres-onboarding/SKILL.md (lines 47-61), the orchestrator prints a structured roadmap like:


Here's the onboarding roadmap for Acme Corp:

1. Upload Wallets — Add on-chain wallets and/or exchange accounts
2. Data Collection (Commit) — Pull on-chain data for the uploaded wallets
3. Validate Balances — Cross-check TRES balances against on-chain sources
4. Reconciliation — Review and resolve any balance gaps
5. Cost Basis — Configure and run cost basis calculation
6. Export Unidentified Addresses — Extract 3rd-party addresses
7. Import Contacts — Label and import the identified addresses
8. Rollup Rules — Set up transaction aggregation for high-volume wallets

This pattern ensures users understand the multi-step commitment before the orchestrator begins invoking sub-skills via MCP calls.

Resumability and Step Tracking

Because each step executes as a separate sub-skill invocation, orchestrators can pause after any step and resume from the next incomplete step later. The onboarding skill (tres-onboarding/SKILL.md, lines 92-98) explicitly defines resumability mechanisms by tracking the last completed step in state, allowing workflows to survive interruptions without restarting from step one.

This architecture requires:

  • State persistence between steps (storing the last completed step index)
  • Idempotent sub-skills that can be safely re-invoked if needed
  • Conditional logic in the orchestrator to skip already-completed steps

Reusable Utilities and Helper Modules

Common helper functions (mutation batching, JSON formatting, data transformation) are extracted into separate modules and imported by orchestrators. The orchestrate_reprice.py script imports build_reprice_plan and print_preview from reprice_swaps.py (lines 32-34), demonstrating how domain logic remains in specialized modules while orchestrators focus on coordination.

This separation enables:

  • Code reuse across multiple orchestrators requiring similar transformations
  • Independent testing of business logic without MCP infrastructure
  • Easier maintenance as fixes to helper functions propagate to all dependent orchestrators

Summary

  • Orchestration skills contain only glue code to sequence sub-skills and manage data flow, delegating all domain logic to specialized sub-skills
  • MCP-driven invocation allows orchestrators to trigger sub-skills via JSON payloads and parse responses for subsequent steps
  • Standardized contracts require orchestrators to produce both human-readable previews and machine-readable execution plans
  • Configuration pass-through enables user-defined filters (--account-name, --currency) to narrow scope without bloating orchestrator logic
  • Resumability is inherent to the architecture because discrete sub-skill invocations allow workflows to pause and resume at step boundaries
  • Helper modules encourage code reuse across orchestrators while keeping the conductor layer thin and testable

Frequently Asked Questions

What is the primary responsibility of an orchestration skill?

An orchestration skill acts as a workflow conductor that sequences sub-skills, manages data handoffs between steps, and handles user interaction. According to the Claude Plugins Community patterns, it should never contain domain-specific business logic—that processing belongs entirely in the sub-skills being orchestrated.

How do orchestration skills communicate with sub-skills?

They communicate via Claude MCP (Message-Calling-Protocol). The orchestrator constructs a JSON payload representing the request, delegates execution to Claude, then parses the MCP response to extract results for the next workflow step. This appears in orchestrate_reprice.py where the script parses raw MCP JSON before forwarding data to helper functions.

Why should orchestrators output both preview and plan files?

Dual output serves different consumers: the human-readable preview provides immediate user feedback confirming what actions will occur, while the machine-readable plan (typically JSON) provides structured data for automated mutation runners or subsequent sub-skills. This separation of concerns appears in the ASC-845 reprice skill where --output and --mutations-output serve distinct downstream needs.

Can users filter workflows without modifying orchestrator code?

Yes. Orchestration skills expose command-line flags (--account-name, --activity-tags, --currency) that narrow scope. These flags are parsed by the orchestrator and passed directly to sub-skills like build_reprice_plan, allowing users to constrain operations while the orchestrator remains agnostic of filtering implementation details.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →