How to Develop Multi-Step Workflow Skills with Conditional Logic in Claude
Build Claude skills that branch and loop by writing natural-language conditionals inside SKILL.md files, using variable assignment, idempotent tool hints, and explicit if/else blocks that the model executes as step-by-step instructions.
ComposioHQ’s awesome-claude-skills repository provides a framework for packaging Claude capabilities as reusable skills. To develop multi-step workflow skills with conditional logic, you write instructional markdown that Claude interprets as an execution plan, combining tool definitions in JSON with human-readable control flow statements.
Architecture of a Conditional Workflow Skill
A skill that supports branching execution consists of four distinct layers stored in the skill directory.
Skill Metadata (SKILL.md frontmatter) declares the skill name, description, and required tools. The requires field can list optional tools; their presence or absence serves as a boolean condition for later branches.
Tool Definitions (JSON configurations) describe each external API or CLI Claude may invoke. According to mcp-builder/reference/python_mcp_server.md, tools accept idempotentHint and openWorldHint booleans that inform the model whether a call can be safely retried or requires external knowledge.
Workflow Instructions (the body of SKILL.md) provide the execution script. Unlike imperative code, this is natural-language prose containing branching blocks (If … then … else …) and loop constructs (While …). Claude scans these instructions to determine the highest-scoring next step based on current context.
Reference Files (reference/*.md) store large static resources like JSON schemas. Conditional steps can include these only when needed, keeping the active prompt window small.
Implementing Conditional Logic in SKILL.md
Claude parses the markdown as instructional prose, not code, so conditionals must be explicit and unambiguous.
Branching with Natural-Language If-Else
Write branches using bold keywords and backtick variables.
- **If** `user_input.file` is present **then**
- `upload = file_upload(user_input.file)`
- Respond: "File uploaded successfully."
- **Else**
- Ask: "Please attach the file you'd like me to process."
The model evaluates the condition by checking the bound variables in its working memory. If the condition evaluates true, it executes the indented sub-steps; otherwise, it jumps to the Else block.
Variable Assignment and State Management
Create variables by wrapping tool calls or literals in backticks. This binds the result to a name you can reference in subsequent conditions.
- `page = http_fetch(url)`
- **If** `page` contains "Error 404" **then**
- Respond: "The page was not found."
- **Goto** Step 1
Variables persist across steps, allowing you to build state machines where the value of attempt or success determines the next branch.
Looping and Retry Logic
Implement loops using While guards that combine Boolean conditions.
- `attempt = 0`
- **While** `attempt < 3` **and** not `sent`
- `sent = email_send(to, subject, body)`
- **If** not `sent` **then**
- `attempt = attempt + 1`
- `sleep(2)`
- **If** `sent` **then**
- Respond: "Email sent!"
- **Else**
- Respond: "Failed after 3 attempts."
As documented in skill-creator/SKILL.md, the Goto keyword redirects execution to a labeled step, enabling you to restart a workflow or skip sections without deep nesting.
Configuring Tool Hints for Safe Branching
When a tool is safe to call multiple times (e.g., a GET request), set idempotentHint: true in its JSON definition. This allows Claude to retry the tool inside loops without fear of side-effects. For tools that reach live external systems, set openWorldHint: true so the model treats the step as a discovery operation. These hints are defined in mcp-builder/reference/python_mcp_server.md and consumed by the planner in mcp-builder/SKILL.md.
Complete SKILL.md Template for Multi-Step Workflows
Below is a minimal skeleton you can copy from template-skill/SKILL.md and adapt for conditional workflows.
# My Conditional Skill
description: "Example skill that demonstrates conditional branching and loops."
requires:
- http_fetch
- optional: report_generator
workflow:
- **Step 1 – Gather input**
Ask the user for a URL (`url`).
- **Step 2 – Validate input**
**If** `url` is empty **then**
- Prompt: "Please provide a valid URL."
- **Goto** Step 1
**Else**
- **Goto** Step 3
- **Step 3 – Fetch the page**
`page = http_fetch(url)`
- **Step 4 – Check for errors**
**If** `page` contains "Error 404" **then**
- Respond: "The page was not found. Try another URL."
- **Goto** Step 1
**Else**
- **Goto** Step 5
- **Step 5 – Process the content**
Extract the title with a regex.
- **Step 6 – Optional extra step**
**If** the title includes the word "Report" **then**
- Call the `report_generator` tool.
**Else**
- Return the title to the user.
- **Step 7 – Completion**
Summarise what was done and finish.
Practical Code Examples
Conditional Tool Invocation
Check a boolean flag before invoking an expensive operation.
- **If** `needs_summary` is true **then**
- `summary = summarizer(text)`
- Return `summary`
- **Else**
- Return the original `text`
Input Validation Branch
Route the workflow based on file presence.
- **If** `user_input.file` is present **then**
- `upload = file_upload(user_input.file)`
- **Else**
- Ask: "Please attach the file."
Retry With Idempotent Safety
Leverage the idempotentHint to safely repeat a network call.
- `attempt = 0`
- **While** `attempt < 3` **and** not `success`
- `success = api_call(endpoint)`
- **If** not `success` **then** `attempt = attempt + 1`
Best Practices for Production Skills
Keep each atomic step limited to a single action (fetch, then check). This improves reliability when Claude backtracks. Use explicit variable names like page_content rather than result to reduce ambiguity in condition evaluation.
Limit prompt size by moving large JSON schemas into separate files under reference/ and including them only when the condition requires. As noted in skill-share/SKILL.md, versioning your skill allows downstream users to inspect the conditional logic without parsing the entire instruction set.
Test each branch independently by simulating inputs that trigger the Else path and the While exit condition before publishing.
Summary
- Structure: Package conditional workflows in
SKILL.mdusing metadata headers, tool definitions, and natural-language instructions. - Syntax: Use bold If, Then, Else, and While keywords with backtick variables for branching and looping.
- Safety: Configure
idempotentHintandopenWorldHintin tool JSON to control retry behavior inside loops. - State: Assign results to variables (
page = http_fetch(url)) and reference them in subsequent conditions. - References: Offload large schemas to
reference/*.mdfiles to avoid context window overflow.
Frequently Asked Questions
How does Claude evaluate conditions in a SKILL.md file?
Claude treats the markdown as an instruction manual. When it encounters a line starting with If, it evaluates the backtick variable against the condition using its reasoning engine, then selects the indented block beneath then or Else based on the outcome. This process is documented in skill-creator/SKILL.md as "instructional prose parsing."
Can I nest conditional blocks inside loops?
Yes. Indent sub-steps beneath a parent If or While to create nested scopes. Ensure you maintain consistent indentation (two spaces or four spaces) so Claude recognizes the hierarchy. Variables assigned inside a loop remain available in the outer scope after the loop terminates.
What is the difference between idempotentHint and openWorldHint?
idempotentHint: true tells Claude that calling the tool multiple times produces the same result as calling it once, making it safe for retry loops. openWorldHint: true signals that the tool accesses external live systems that the model cannot fully predict, prompting Claude to treat the step as a discovery action. Both are defined in mcp-builder/reference/python_mcp_server.md.
Where should I store complex conditional logic to keep the main file readable?
Move large schemas, API response examples, or detailed regex patterns into separate markdown files under a reference/ directory. Use conditional includes (or simply reference them by name in a step) to load this content only when a specific branch requires it, following the pattern established in template-skill/SKILL.md.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →