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 integrating tools and creating 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 in which 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 in which 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. 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 gets passed 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.

This differs fundamentally from basic prompt chaining. In basic prompt chaining, you send a series of prompts to an LLM, where each prompt builds on the previous response. The LLM processes each prompt independently, without specialized context, tools, or persistent expertise. It's like asking the same person to wear different hats for each task. Agentic pipelines, however, use autonomous agents that are each designed with specific expertise, dedicated tools, and focused system prompts.

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 set up the necessary imports and tools. We will continue using the custom Agent class that we built in the previous course. As you'll remember, this class simplifies our workflow by encapsulating the logic for interacting with the LLM, managing conversation state, and automatically executing tool calls when the model requests them.

import fs from "fs";
import { Agent } from "./agent";
import {
  sumNumbers,
  multiplyNumbers,
  subtractNumbers,
  divideNumbers,
  power,
  squareRoot
} from "./functions";

// Load tool schemas
const schemasJson = fs.readFileSync("schemas.json", "utf-8");
const toolSchemas = JSON.parse(schemasJson);

// Math tools
const mathTools: Record<string, Function> = {
  sum_numbers: sumNumbers,
  multiply_numbers: multiplyNumbers,
  subtract_numbers: subtractNumbers,
  divide_numbers: divideNumbers,
  power: power,
  square_root: squareRoot
};

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.

// Agent 1: Problem Analyzer
const problemAnalyzer = new Agent({
  name: "problem_analyzer",
  systemPrompt:
    "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 — 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.

// Agent 2: Calculator Agent
const calculatorAgent = new Agent({
  name: "calculator_agent",
  systemPrompt:
    "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: mathTools,
  toolSchemas: toolSchemas
});

This agent has access to all the mathematical tools (sumNumbers, multiplyNumbers, subtractNumbers, etc.), but its system prompt focuses it on execution rather than planning. 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.

// Agent 3: Solution Presenter
const solutionPresenter = new Agent({
  name: "solution_presenter",
  systemPrompt:
    "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:

// Define our complex problem
const complexProblem = `
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?
`;

// Create the initial message with the complex problem for the analyzer
const analysisMessages: Array<Record<string, unknown>> = [
  { role: "user", content: complexProblem }
];

// Run the problem analyzer to break down the problem into steps
const [analysisHistory, analysisOutput] = await problemAnalyzer.run(
  analysisMessages
);

// Display the analysis output
console.log(analysisOutput);

The run method returns the full conversation history (all interactions) and the final string output. We use the analysisOutput to pass to the next stage of our pipeline, while the analysisHistory is preserved if we ever need to audit the specific reasoning steps the agent took.

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

Plan to solve:

Perimeter (fencing needed)
1) Identify given dimensions: length L = 12 meters, width W = 8 meters.
2) Recall rectangle perimeter formula: P = 2 × (L + W).
3) Substitute the given values into the formula: P = 2 × (12 m + 8 m).
4) Carry out the addition inside parentheses, then multiply by 2 to get P in meters.
5) Interpret P as the total length of fencing required.

Grass seed required
1) Recall rectangle area formula: A = L × W.
2) Substitute the given values: A = 12 m × 8 m.
3) Compute the area A in square meters.
4) Use the seeding rate r = 0.25 kg per square meter.
5) Multiply the area by the rate to get total seed mass: Seed = A × r.
6) Report the result in 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:

// Pass the analysis plan to the calculator agent for execution
const calculationMessages: Array<Record<string, unknown>> = [
  {
    role: "user",
    content: "Execute this calculation plan: " + analysisOutput
  }
];

// Run the calculator agent to perform all mathematical operations
const [calculationHistory, calculationOutput] = await calculatorAgent.run(
  calculationMessages
);

// Display the calculation final output
console.log(calculationOutput);

The Calculator Agent takes the structured plan and methodically executes each calculation using its mathematical tools:

🔧 Tool called: sum_numbers({"a":12,"b":8})
🔧 Tool called: multiply_numbers({"a":2,"b":20})
🔧 Tool called: multiply_numbers({"a":12,"b":8})
🔧 Tool called: multiply_numbers({"a":96,"b":0.25})
Calculation plan execution with step-by-step work and results:

Perimeter (fencing needed)
1) Given dimensions: L = 12 m, W = 8 m.
2) Formula: P = 2 × (L + W).
3) Substitute: P = 2 × (12 m + 8 m).
4) Compute inside parentheses: 12 + 8 = 20; then multiply by 2: 2 × 20 = 40.
5) Interpretation: P = 40 meters of fencing required.

Grass seed required
1) Formula: A = L × W.
2) Substitute: A = 12 m × 8 m.
3) Compute area: 12 × 8 = 96 m².
4) Seeding rate: r = 0.25 kg/m².
5) Compute seed mass: Seed = A × r = 96 × 0.25 = 24 kg.
6) Result: 24 kilograms of grass seed required.

Structured results
- Perimeter (fencing): 40 m
- Area: 96 m²
- Grass seed: 24 kg

Notice how the tool logs show exactly which mathematical functions were called during the calculation process. 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:

// Combine original problem and calculation results for final presentation
const presentationPrompt =
  "Present this solution clearly based on the original problem and " +
  "calculations:\n\n" +
  `Original Problem: ${complexProblem}\n\n` +
  `Calculation Results: ${calculationOutput}`;

// Create the final message for the solution presenter
const presentationMessages: Array<Record<string, unknown>> = [
  { role: "user", content: presentationPrompt }
];

// Run the solution presenter to create the final educational output
const [presentationHistory, presentationOutput] = await solutionPresenter.run(
  presentationMessages
);

// Display the final output
console.log(presentationOutput);

In the code above, we use array destructuring [presentationHistory, presentationOutput] to capture the two values returned by the run method. While we primarily display presentationOutput to the user, presentationHistory is essential for debugging or if we wanted to allow the user to ask follow-up questions about the specific way the solution was presented.

The Solution Presenter transforms the raw calculations into a polished, educational explanation:

Solution

We are given a rectangle with length 12 meters and width 8 meters. We need:
1) The amount of fencing to go around it (the perimeter).
2) The amount of grass seed needed, given a rate of 0.25 kg per square meter (which requires the area).

Perimeter (fencing needed)
- What we're finding: The perimeter is the total distance around the rectangle, so we add all sides.
- Why this step: A rectangle has two lengths and two widths; the formula P = 2(L + W) quickly adds them.
- Compute:
  - L = 12 m, W = 8 m
  - P = 2 × (L + W) = 2 × (12 + 8) = 2 × 20 = 40
- Interpretation: 40 meters of fencing are needed.

Area (for grass seed)
- What we're finding: The area tells us how much surface is covered by the garden.
- Why this step: The amount of seed depends on the total area, so we must compute A = L × W.
- Compute area:
  - A = 12 m × 8 m = 96 m²
- Use the seeding rate to find mass of seed:
  - Rate r = 0.25 kg per m²
  - Seed needed = A × r = 96 × 0.25 = 24 kg

Final answers
- Fencing required (perimeter): 40 meters
- Grass seed required: 24 kilograms
- (Area used in the calculation: 96 m²)

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 accomplished architecturally: we defined a simple three-stage sequence (analyze → calculate → present), while each agent handled significant internal complexity 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