Chaining AI Like a Pro
One AI call is nice. But the real magic happens when you chain them together—feeding the output of one model into the input of the next. Think of it as building an assembly line for intelligence.
What You'll Learn
- How to pass data between multiple AI steps
- Mixing AI calls with Python processing
- The three patterns that solve 90% of multi-step problems
Your First Pipeline
Let's build something real: a tool that extracts key points from an article, then turns them into a tweet thread.
name: article-to-tweets
version: "1.0.0"
description: Turn articles into tweet threads
steps:
# Step 1: Extract the essence
- type: prompt
provider: claude
prompt: |
Extract 5 key insights from this article.
Be specific and quotable.
{input}
output_var: key_points
# Step 2: Transform into tweets
- type: prompt
provider: claude
prompt: |
Turn these insights into a compelling tweet thread.
Each tweet under 280 characters.
Make the first tweet a hook.
Insights:
{key_points}
output_var: thread
output: "{thread}"
The magic is in line 20: {key_points} contains the output from Step 1. Data flows downstream automatically.
The Variable Waterfall
Think of variables like water flowing downhill—they only go forward, never back:
Input
{input}
Step 1
{key_points}
Step 2
{thread}
Output
Step 2 can use: {input}, {key_points}
Step 2 cannot use: Variables from Step 3 (doesn't exist yet!)
Adding Python Glue
AI is great at language. Python is great at data wrangling. Together? Unstoppable.
name: email-extractor
version: "1.0.0"
description: Extract and deduplicate emails from messy text
steps:
# AI finds the emails
- type: prompt
provider: claude
prompt: |
Extract all email addresses from this text.
Return them comma-separated, nothing else.
{input}
output_var: emails_raw
# Python cleans them up
- type: code
code: |
# Split, clean, deduplicate
emails = [e.strip().lower() for e in emails_raw.split(',')]
emails = [e for e in emails if '@' in e and '.' in e]
unique_emails = sorted(set(emails))
count = len(unique_emails)
clean_list = '\n'.join(unique_emails)
output_var: clean_list, count
# AI formats the output nicely
- type: prompt
provider: claude
prompt: |
Format these {count} email addresses as a clean list
with any obvious categorization (personal, work, etc):
{clean_list}
output_var: result
output: "{result}"
Pro Tip: Code Steps Return Multiple Variables
Notice output_var: clean_list, count—you can export multiple variables
from a single code step. Just list them comma-separated.
The Three Patterns That Solve Everything
Extract → Transform → Format
prompt # Pull out data
code # Clean/filter
prompt # Make it pretty
Use for: Data extraction, report generation
Analyze → Synthesize
prompt # Break it down
prompt # Build it up
Use for: Summaries, insights, rewriting
Validate → Process
code # Check input
prompt # Do the work
Use for: Safe processing, error handling
When Things Go Wrong
Warning: Steps Are All-Or-Nothing
If Step 2 fails, Step 3 never runs. Design defensively!
steps:
# Guard clause in code
- type: code
code: |
if not input.strip():
processed = "ERROR: Empty input"
is_valid = False
else:
processed = input
is_valid = True
output_var: processed, is_valid
# Only meaningful if valid
- type: prompt
provider: claude
prompt: |
Summarize this text: {processed}
output_var: summary
Try It: Build a Code Explainer
Exercise
Build a tool that:
- Identifies the programming language
- Explains what the code does (using the language info)
- Suggests improvements
See the solution
name: code-explainer
version: "1.0.0"
description: Understand and improve any code
steps:
- type: prompt
provider: claude
prompt: |
What programming language is this?
Reply with just the language name.
{input}
output_var: language
- type: prompt
provider: claude
prompt: |
Explain this {language} code in plain English.
Describe what each part does.
{input}
output_var: explanation
- type: prompt
provider: claude
prompt: |
Suggest 3 improvements for this {language} code.
Consider readability, performance, and best practices.
Code:
{input}
Current understanding:
{explanation}
output_var: improvements
output: |
## Language: {language}
## Explanation
{explanation}
## Suggested Improvements
{improvements}
Debugging Multi-Step Tools
# See what prompts are being built
cat test.txt | my-tool --dry-run
# Watch each step execute
cat test.txt | my-tool --verbose
# Test with mock provider first
cat test.txt | my-tool --provider mock
Next Up
Ready to go deeper? Learn the full power of code steps:
- Code Steps Deep Dive - Python superpowers in your tools
- Advanced Workflows - Multi-provider, conditional logic, and more