Introduction to Agentic Pipelines

Introduction to Agentic Patterns

Welcome to the next step of your journey toward building effective agents! In our previous courses, you've built a solid foundation by exploring basic workflows with simple LLM calls, then progressing to integrate tools and create autonomous agents that can make decisions and execute tasks independently.

Now we're taking the next major leap: agentic patterns. These are sophisticated workflows that leverage the power of autonomous agents working together in coordinated ways to solve complex problems.

In this lesson, we'll focus on agentic pipelines — one of the most fundamental and powerful agentic patterns. You'll learn how to design specialized agents, connect them in sequence, and create workflows where each agent contributes its unique expertise to produce comprehensive solutions. By the end of this lesson, you'll have built a complete three-agent pipeline that can tackle complex multi-step mathematical problems with remarkable clarity and precision.

What Are Agentic Pipelines?

An agentic pipeline is a workflow where multiple specialized autonomous agents work together in sequence, with each agent performing its specific role before passing the results to the next agent in the chain. This differs fundamentally from simple prompt chaining in several crucial ways.

In basic prompt chaining, you send a series of prompts to an LLM, where each prompt builds on the previous response. In the simpler chaining pattern we've used earlier in this learning path, each step is typically another prompt/response turn rather than a separately configured autonomous agent with its own focused role, tools, and boundaries. It is like asking the same person to wear different hats — they might do okay, but they are not truly specialized.

Agentic pipelines, however, use autonomous agents that are each designed with specific expertise, dedicated tools, and focused system prompts. Each agent can perform multiple internal steps, make decisions about how to approach its part of the problem, and use tools autonomously. Importantly, within the pipeline, a single agent might take several internal steps — analyzing, planning, using tools, and refining its approach — before generating a final result that is chained to the next agent. This means each stage of the pipeline can be as sophisticated as needed, while the overall flow remains clean and manageable.

Agent Specialization Principles

The foundation of effective agentic pipelines lies in proper agent specialization. Each agent should be designed as an expert in its specific domain, with clear boundaries about what it should and shouldn't do. This specialization is what transforms a simple sequence of LLM calls into a powerful, coordinated system.

When designing specialized agents, follow these key principles:

  • Single Responsibility: Each agent should have one clear, focused role and excel at that specific task.
  • Appropriate Tools: Provide only the tools that are relevant to the agent's specific function.
  • Focused System Prompt: Write system prompts that clearly define what the agent should do, what it should avoid, and how it should format outputs.
  • Clear Boundaries: Explicitly state what the agent should not attempt, preventing scope creep.
  • Output Formatting: Ensure each agent's output is structured to work seamlessly with the next agent in the pipeline.

This separation of concerns makes each agent more reliable and the overall system easier to debug and maintain. The system prompt is particularly crucial for specialization, as it acts like a job description that keeps the agent focused on its expertise while ensuring its outputs integrate smoothly with the rest of the pipeline.

What We'll Build

In this lesson, we'll construct a sophisticated three-agent pipeline that can solve complex multi-step mathematical problems. Our pipeline will consist of:

  1. Problem Analyzer Agent — Breaks down complex problems into clear, sequential steps.
  2. Calculator Agent — Executes mathematical operations using specialized tools.
  3. Solution Presenter Agent — Formats results into educational, easy-to-understand solutions.

By the end, you'll see how three specialized agents working together can produce more comprehensive and reliable results than a single general-purpose agent attempting to handle everything at once.

Setting Up Tools and Agent Class

Before we build our pipeline agents, let's quickly set up the necessary requirements and tools:

Ruby
require "json"
require_relative "agent"
require_relative "functions"

# Load tool schemas
tool_schemas = JSON.parse(File.read("schemas.json"))

# Math tools (name => Ruby callable)
math_tools = {
  "sum_numbers" => method(:sum_numbers),
  "multiply_numbers" => method(:multiply_numbers),
  "subtract_numbers" => method(:subtract_numbers),
  "divide_numbers" => method(:divide_numbers),
  "power" => method(:power),
  "square_root" => method(:square_root)
}

In Ruby, we use require_relative to load our local Agent class and functions. The schemas.json file (same as the previous course) contains the tool definitions. The math_tools hash maps tool names to Ruby callables, which the Agent#call_tool method uses to execute each tool when needed.

Now we're ready to build our specialized agents for the pipeline.

Building the Problem Analyzer Agent

Let's start building our pipeline with the first agent — the Problem Analyzer. This agent's job is to take complex problems and break them down into clear, actionable steps without performing any calculations itself.

Ruby
# Agent 1: Problem Analyzer
problem_analyzer = Agent.new(
  name: "problem_analyzer",
  system_prompt: (
    "You are a mathematical problem analyzer. Your job is to:\n" \
    "1. Break down complex math problems into clear, sequential steps\n" \
    "2. Identify what calculations are needed at each step\n" \
    "3. Output a structured plan that another agent can follow to perform calculations\n" \
    "4. Do NOT perform the actual calculations - just create the step-by-step plan"
  )
)

Notice how this agent has no tools at all — we don't pass a tools: or tool_schemas: parameter. This is intentional because we want it to focus purely on analysis and planning. The system prompt explicitly tells it not to perform calculations, which helps maintain clear boundaries between agents. This focused approach ensures our analyzer will create structured plans that the next agent can easily follow.

Building the Calculator Agent

The second agent in our pipeline is the Calculator Agent, which takes the analysis plan and executes all the mathematical operations using the available tools.

Ruby
# Agent 2: Calculator Agent
calculator_agent = Agent.new(
  name: "calculator_agent",
  system_prompt: (
    "You are a calculator agent. Your job is to:\n" \
    "1. Take a step-by-step calculation plan\n" \
    "2. Execute each calculation using your available math tools\n" \
    "3. Show your work clearly for each step\n" \
    "4. Provide the numerical results in a structured format"
  ),
  tools: math_tools,
  tool_schemas: tool_schemas
)

This agent has access to all the mathematical tools (sum_numbers, multiply_numbers, subtract_numbers, etc.) through the tools: parameter, along with their schemas via tool_schemas:. The system prompt focuses it on execution rather than planning.

When this agent runs, the Agent#run method automatically detects when Claude wants to use tools (checking for stop_reason == "tool_use"). It then calls Agent#call_tool internally for each tool use, which prints debugging information like 🔧 Tool called: sum_numbers({:a=>12, :b=>8}) and executes the Ruby callable. The emphasis on showing work and providing structured results ensures the next agent in the pipeline has clear information to work with.

Building the Solution Presenter Agent

The final agent in our pipeline is the Solution Presenter, which takes the raw calculation results and formats them into a clear, educational solution that's easy to understand.

Ruby
# Agent 3: Solution Presenter
solution_presenter = Agent.new(
  name: "solution_presenter",
  system_prompt: (
    "You are a solution presenter. Your job is to:\n" \
    "1. Take calculation results and present them as a complete, educational solution\n" \
    "2. Explain what each step accomplished and why it was necessary\n" \
    "3. Provide the final answer clearly\n" \
    "4. Make the solution easy to understand for someone learning math"
  )
)

Like the Problem Analyzer, this agent has no tools because its job is purely communicative. It focuses on taking technical calculation results and transforming them into human-friendly explanations that emphasize educational value. Now that we have our three specialized agents, let's see how they connect together in our pipeline.

Stage 1: Problem Analysis

Let's start our pipeline by running the Problem Analyzer agent with a complex mathematical problem:

Ruby
# Define our complex problem
complex_problem = <<~PROBLEM
  A rectangular garden is 12 meters long and 8 meters wide.
  How much fencing is needed to go around the perimeter?
  Also, if grass seed is needed at a rate of 0.25 kg per square meter,
  how much grass seed is required for the entire garden?
PROBLEM

# Create the initial message with the complex problem for the analyzer
analysis_messages = [{ role: "user", content: complex_problem }]

# Run the problem analyzer to break down the problem into steps
analysis_history, analysis_output = problem_analyzer.run(analysis_messages)

# Display the analysis output
puts analysis_output

In Ruby, we use a heredoc (<<~PROBLEM) for multi-line strings, which automatically removes leading indentation. The run method returns two values using parallel assignment: analysis_history contains the complete message history (useful for continuing conversations with the same agent), and analysis_output is the final text response that we'll pass to the next stage.

When we run this first stage, the Problem Analyzer breaks down our multi-step problem into a clear, structured plan:

text
# Mathematical Problem Analysis

## Problem Breakdown

This problem has **two distinct parts** requiring different geometric formulas.

---

## Part 1: Fencing (Perimeter)

**Goal:** Find the total length of fencing needed to surround the garden.

### Steps:
**Step 1 — Identify the formula**
> Use the rectangle perimeter formula:
> **P = 2 × (length + width)**

**Step 2 — Identify the known values**
- Length = 12 meters
- Width = 8 meters

**Step 3 — Calculate the sum inside the parentheses**
> Compute: 12 + 8

**Step 4 — Multiply by 2**
> Compute: 2 × (result from Step 3)

**Step 5 — State the result**
> The answer is in **meters**

---

## Part 2: Grass Seed (Area)

**Goal:** Find the total amount of grass seed needed to cover the garden.

### Steps:
**Step 1 — Identify the formula**
> Use the rectangle area formula:
> **A = length × width**

**Step 2 — Identify the known values**
- Length = 12 meters
- Width = 8 meters

**Step 3 — Calculate the area**
> Compute: 12 × 8
> Result is in **square meters (m²)**

**Step 4 — Apply the seeding rate**
> Use the rate: **0.25 kg per m²**
> Compute: Area (from Step 3) × 0.25

**Step 5 — State the result**
> The answer is in **kilograms (kg)**

---

## Summary of Required Calculations

| # | Operation | Purpose |
|---|-----------|---------|
| 1 | 12 + 8 | Sum of length and width |
| 2 | 2 × (result 1) | Total perimeter (fencing) |
| 3 | 12 × 8 | Total area of garden |
| 4 | (result 3) × 0.25 | Total grass seed required |

---

## Expected Output Format
- **Fencing needed:** result of Calculation #2 → **meters**
- **Grass seed required:** result of Calculation #4 → **kilograms**

Notice how the Problem Analyzer successfully identified all the necessary steps and formulas without performing any calculations. This structured plan now becomes the input for our Calculator Agent in the next stage.

Stage 2: Mathematical Calculations

Now we pass the analysis plan to our Calculator Agent to execute all the mathematical operations:

Ruby
# Pass the analysis plan to the calculator agent for execution
calculation_messages = [
  {
    role: "user",
    content: "Execute this calculation plan: #{analysis_output}"
  }
]

# Run the calculator agent to perform all mathematical operations
calculation_history, calculation_output = calculator_agent.run(calculation_messages)

# Display the calculation final output
puts calculation_output

In Ruby, we use string interpolation with #{} to embed the analysis_output directly into our prompt. The Calculator Agent takes the structured plan and methodically executes each calculation using its mathematical tools:

text
🔧 Tool called: sum_numbers({:a=>12, :b=>8})
🔧 Tool called: multiply_numbers({:a=>12, :b=>8})
🔧 Tool called: multiply_numbers({:a=>2, :b=>20})
🔧 Tool called: multiply_numbers({:a=>96, :b=>0.25})
All four calculations complete! Here's the full structured breakdown:

---

## ✅ Calculation Results

### Part 1 — Fencing (Perimeter)
| Step | Operation | Result |
|------|-----------|--------|
| #1 | 12 + 8 | **20 m** |
| #2 | 2 × 20 | **40 m** |

### Part 2 — Grass Seed (Area)
| Step | Operation | Result |
|------|-----------|--------|
| #3 | 12 × 8 | **96 m²** |
| #4 | 96 × 0.25 | **24 kg** |

---

## 🏁 Final Answers

- 🪚 **Fencing needed:** **40 meters**
- 🌱 **Grass seed required:** **24 kilograms**

Notice how the tool logs show exactly which mathematical functions were called during the calculation process. These logs come from the puts statement inside Agent#call_tool, showing the Ruby hash syntax for the arguments (:a=>12, :b=>8). The Calculator Agent successfully executed all the mathematical operations using its tools and provided clear numerical results. These calculation results now flow to our final agent for presentation.

Stage 3: Solution Presentation

Finally, we use the Solution Presenter to format the results into a comprehensive, educational solution:

Ruby
# Combine original problem and calculation results for final presentation
presentation_prompt = <<~PROMPT
  Present this solution clearly based on the original problem and calculations:

  Original Problem: #{complex_problem}

  Calculation Results: #{calculation_output}
PROMPT

# Create the final message for the solution presenter
presentation_messages = [{ role: "user", content: presentation_prompt }]

# Run the solution presenter to create the final educational output
presentation_history, presentation_output = solution_presenter.run(presentation_messages)

# Display the final output
puts presentation_output

We use a heredoc with string interpolation to cleanly construct our prompt, embedding both the complex_problem and the calculation_output. The Solution Presenter transforms the raw calculations into a polished, educational explanation:

text
# 🌿 Rectangular Garden Problem — Complete Solution

## Understanding the Problem

We have a rectangular garden with these dimensions:
- **Length = 12 meters**
- **Width = 8 meters**

We need to find **two things**:
1. How much fencing surrounds the garden (perimeter)
2. How much grass seed covers the garden (area)

---

## Part 1 — Fencing Needed (Perimeter)

The **perimeter** is the total distance around the outside of the rectangle. Think of it as walking along every edge of the garden — you'd travel along two long sides and two short sides.

**The Formula:**
$$P = 2 \times (length + width)$$

**Step 1** — Add the length and width together:
$$12 + 8 = 20 \text{ m}$$

> *Why? A rectangle has two pairs of equal sides, so we first find the combined length of one pair.*

**Step 2** — Multiply by 2 to account for both pairs of sides:
$$2 \times 20 = \boxed{40 \text{ meters}}$$

> *Why? We double our result because there are two lengths AND two widths in a rectangle.*

---

## Part 2 — Grass Seed Required (Area)

The **area** tells us how much flat surface the garden covers. This is what we need to seed with grass.

**The Formula:**
$$A = length \times width$$

**Step 3** — Multiply length by width:
$$12 \times 8 = 96 \text{ m}^2$$

> *Why? Area measures the space inside the shape, calculated by multiplying the two dimensions together.*

**Step 4** — Apply the seeding rate (0.25 kg per square meter):
$$96 \times 0.25 = \boxed{24 \text{ kg}}$$

> *Why? Every square meter needs 0.25 kg of seed, so we multiply the total area by the rate to find the total seed needed.*

---

## ✅ Final Answers

| Question | Answer |
|----------|--------|
| 🪚 Fencing needed (perimeter) | **40 meters** |
| 🌱 Grass seed required | **24 kilograms** |

---

## 💡 Key Takeaway

> - **Perimeter** = distance *around* a shape → used for fencing, borders, frames
> - **Area** = space *inside* a shape → used for flooring, seeding, painting

These two measurements solve completely different real-world problems, even though they use the same two dimensions!

This final stage demonstrates how the Solution Presenter takes technical calculation results and transforms them into a clear, educational explanation that shows the reasoning behind each step. Our three-agent pipeline has successfully tackled a complex multi-step problem through specialized collaboration, with each agent contributing its unique expertise to produce a comprehensive solution.

Reflecting on Pipeline Architecture

Notice what we have accomplished architecturally: we defined a simple three-stage sequence (analyze → calculate → present), while each agent handled significant internal complexity that we didn't need to manage. The Calculator Agent made multiple tool calls and formatting decisions internally, but we only orchestrated the high-level flow between agents.

This separation of orchestration from execution makes complex problems manageable — you focus on workflow while each agent handles its domain expertise.

We could specialize our agents further with additional tools:

  • Problem Analyzer: formula lookup tools, problem-type databases
  • Calculator Agent: unit conversion, statistical functions, graphing tools
  • Solution Presenter: diagram generation, readability checkers, LaTeX formatting

More specialized tools make each agent more capable within its domain, while keeping the overall pipeline structure clean and understandable.

Summary and Next Steps

You've now mastered the fundamentals of agentic pipelines by building specialized agents that work together in sequence. This pipeline pattern breaks complex problems into manageable pieces, makes systems easier to debug, and allows each agent to excel at its specific task.

In the upcoming practice exercises, you'll build your own agentic pipeline. The three-agent math pipeline you've learned here will serve as your foundation for creating much more sophisticated agentic systems!

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal