Chaining workflows — Sequential breakdown

9 — Workflows & AgentsTrung cấp15 phút

User task: "Create a marketing article about AI, format nicely, remove any mention of being written by AI, no emojis, professional tone".

Bạn sẽ học được
  • Understand chaining pattern
  • Break long tasks thành focused subtasks
  • Solve "Claude ignores constraints" problem qua multi-step
  • Non-LLM processing giữa steps

Chaining pattern

Each step does 1 focused thing.

┌────────────────────────────────────────────┐
│                                            │
│  Input                                     │
│    │                                       │
│    ▼                                       │
│  Step 1 (Claude) — generate                │
│    │                                       │
│    ▼                                       │
│  [Optional non-LLM processing]             │
│    │                                       │
│    ▼                                       │
│  Step 2 (Claude) — refine                  │
│    │                                       │
│    ▼                                       │
│  [Optional processing]                     │
│    │                                       │
│    ▼                                       │
│  Step 3 (Claude) — polish                  │
│    │                                       │
│    ▼                                       │
│  Output                                    │
│                                            │
└────────────────────────────────────────────┘

Example: Marketing video workflow

Mix Claude calls + external APIs + code.

Each step focused → high quality.

1. find_trending_topic    [Twitter API]
2. select_best_topic      [Claude] — pick most engaging
3. research_topic         [Claude + web search]
4. write_video_script     [Claude] — focus purely on script
5. generate_voice         [TTS API]
6. generate_visuals       [Image API]
7. combine_video          [FFmpeg]
8. post_to_social         [Social API]

Why chain vs single prompt?

Single massive prompt

Claude trying to do everything → often miss constraints.

Chained

Step 4 only: write script (already have topic, audience, time constraint).

Claude focus → better quality. Easier test.

"Find trending topic, write script, ensure engagement, keep under 60 seconds,
use trending hashtags, professional tone, end with CTA..."

Long prompt problem solved by chaining

Constraints scale poorly in single prompt:

Claude prioritizes — some constraints win, others lose.

2-step solution

Step 1: Write article with soft constraints (tone, length, structure).

Constraints:
1. Not mention AI author
2. No emojis
3. Skip cliché phrases
4. Professional technical tone
5. Max 1000 words
6. Include 3 examples
7. Use headers/lists
8. Include meta description
9. Link to related articles
10. SEO-optimized

2-step solution

Step 2: Revise for hard constraints.

step_1 = """Write a technical article about AI trends.

Constraints:
- 1000 words
- Include 3 examples
- Use headers

Focus on content quality."""

Long prompt problem solved by chaining (tiếp)

Claude focus on revisions → catches all.

step_2 = f"""Revise this article:

<article>
{article_from_step_1}
</article>

Revisions:
1. Remove any mention of AI authorship
2. Remove all emojis
3. Rewrite cliché phrases to formal
4. Ensure professional tone throughout

Output: revised article only, no explanations."""

Non-LLM processing between steps

Chaining allows code between steps:

Code does deterministic work. LLM does creative.

async def article_workflow(topic):
    # Step 1: LLM generate
    raw_article = await claude(f"Write article: {topic}")
    
    # Step 2: Code extract images references
    image_refs = re.findall(r"!\[.*?\]\((.*?)\)", raw_article)
    
    # Step 3: Code validate images exist
    for ref in image_refs:
        if not await fetch_image_exists(ref):
            raw_article = raw_article.replace(f"]({ref})", "](placeholder.jpg)")
    
    # Step 4: LLM refine
    final = await claude(f"Improve flow of article:\n{raw_article}")
    
    return final

When chaining worth

✅ Good fit

⚠️ Overkill

  • Multi-constraint content generation
  • Multi-stage processing
  • Need intermediate validation
  • Different expertise per step (writer → editor → SEO)
  • Simple Q&A
  • Single-shot classification
  • Tasks with 1-2 constraints

Implementation pattern

Each step isolated → testable + replaceable.

class ContentWorkflow:
    async def run(self, topic: str) -> str:
        # Step 1
        draft = await self._step_1_generate(topic)
        
        # Step 2 (processing)
        cleaned = self._step_2_clean(draft)
        
        # Step 3
        refined = await self._step_3_refine(cleaned)
        
        # Step 4 (validation)
        if not self._step_4_validate(refined):
            raise WorkflowError("Final output failed validation")
        
        return refined
    
    async def _step_1_generate(self, topic):
        prompt = "Write article about {topic}..."
        return await claude(prompt)
    
    def _step_2_clean(self, text):
        # Python processing
        return text.strip()
    
    async def _step_3_refine(self, text):
        prompt = f"Refine this article:\n{text}"
        return await claude(prompt)
    
    def _step_4_validate(self, text):
        return len(text) > 500 and "AI" not in text.lower()

Chain + retry pattern

Retry unreliable steps.

async def robust_step(step_func, max_retries=3):
    for attempt in range(max_retries):
        try:
            result = await step_func()
            if validate(result):
                return result
        except Exception as e:
            logger.warning(f"Step attempt {attempt+1} failed: {e}")
    raise WorkflowError("Max retries exceeded")


# Apply per step
draft = await robust_step(lambda: claude(prompt_1))

Eval chained workflow

Numeric quality score → optimize.

test_cases = [
    {"topic": "AI Safety", "expected_keywords": ["alignment", "interpretability"]},
    ...
]

for test in test_cases:
    result = await content_workflow.run(test["topic"])
    
    # Validate each criterion
    has_keywords = all(kw in result for kw in test["expected_keywords"])
    length_ok = 800 < len(result.split()) < 1200
    no_emoji = not any(c in result for c in "😀🚀✨")
    
    score = sum([has_keywords, length_ok, no_emoji]) / 3

Anti-patterns

❌ Too many steps

10+ Claude calls per workflow = expensive + slow.

Fix: Merge steps if compatible. Cap at 5-7.

❌ Each step reinvents data

Step 1 creates data. Step 2 recreates partially. Step 3 loses info.

Fix: Pass structured state between steps.

❌ No error propagation

Step 2 fail silently → step 3 works with garbage.

Fix: Validate output của each step before continue.

❌ Lock sequence when parallel possible

Steps 2 và 3 independent → running sequential wastes.

Fix: Bài 6.75 — parallelization.

Áp dụng ngay

Bài tập 1: Identify chaining opportunity (10 phút)

Cho app của bạn, list 1 prompt dài với 5+ constraints. Design 2-step chain:

Bài tập 2: Implement + compare (30 phút)

Run both single-prompt vs chained. Measure:

Usually: chained higher quality + similar/slightly higher cost.

  • Step 1: generate focus on content
  • Step 2: refine focus on constraints
  • Quality (manual grade)
  • Cost (tokens × price)
  • Latency

Tóm tắt

🎯 Chaining = sequential subtasks, each focused.

🎯 Solves long-prompt problem — Claude ignores constraints.

🎯 Non-LLM steps in between for deterministic work.

🎯 Cap 5-7 steps to balance quality vs cost.

🎯 Per-step validation prevents error propagation.

Nội dung này có hữu ích không?