DEV Community

Cover image for AI Agentic Design Patterns You Need to Know
Oussama Fikri
Oussama Fikri

Posted on

AI Agentic Design Patterns You Need to Know

The world of Artificial Intelligence is buzzing with the concept of "agents" – autonomous AI systems that can reason, plan, and interact with their environment to achieve goals. But how do we structure these agents to be effective and reliable? The answer lies in agentic design patterns. These are reusable blueprints that provide a framework for building sophisticated AI agents.

This article walks you through four fundamental patterns, each demonstrated with a simple implementation in a different framework to help you get started.

1. The Reflection Pattern: Fostering Self-Improvement

The reflection pattern is all about enabling an AI agent to critique and refine its own work. This iterative process of self-improvement leads to higher quality and more accurate outputs. Imagine an AI tasked with writing a blog post. With the reflection pattern, it would first generate a draft, then a separate "critic" agent would review it for clarity, coherence, and tone. Based on this feedback, the original agent would then revise the draft.

Simple Implementation Example using LangGraph :

First, create the generator:

from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_fireworks import ChatFireworks

prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "You are an essay assistant tasked with writing excellent 5-paragraph essays."
            " Generate the best essay possible for the user's request."
            " If the user provides critique, respond with a revised version of your previous attempts.",
        ),
        MessagesPlaceholder(variable_name="messages"),
    ]
)
llm = ChatOpenAI(
    model="gpt-4.1-mini-2025-04-14",
    temperature=0.7
)
generate = prompt | llm
Enter fullscreen mode Exit fullscreen mode

Reflect :

reflection_prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "You are a teacher grading an essay submission. Generate critique and recommendations for the user's submission."
            " Provide detailed recommendations, including requests for length, depth, style, etc.",
        ),
        MessagesPlaceholder(variable_name="messages"),
    ]
)
reflect = reflection_prompt | llm
Enter fullscreen mode Exit fullscreen mode

Define graph :

from typing import Annotated, List, Sequence
from langgraph.graph import END, StateGraph, START
from langgraph.graph.message import add_messages
from langgraph.checkpoint.memory import MemorySaver
from typing_extensions import TypedDict


class State(TypedDict):
    messages: Annotated[list, add_messages]


async def generation_node(state: State) -> State:
    return {"messages": [await generate.ainvoke(state["messages"])]}


async def reflection_node(state: State) -> State:
    # Other messages we need to adjust
    cls_map = {"ai": HumanMessage, "human": AIMessage}
    # First message is the original user request. We hold it the same for all nodes
    translated = [state["messages"][0]] + [
        cls_map[msg.type](content=msg.content) for msg in state["messages"][1:]
    ]
    res = await reflect.ainvoke(translated)
    # We treat the output of this as human feedback for the generator
    return {"messages": [HumanMessage(content=res.content)]}


builder = StateGraph(State)
builder.add_node("generate", generation_node)
builder.add_node("reflect", reflection_node)
builder.add_edge(START, "generate")


def should_continue(state: State):
    if len(state["messages"]) > 6:
        # End after 3 iterations
        return END
    return "reflect"


builder.add_conditional_edges("generate", should_continue)
builder.add_edge("reflect", "generate")
memory = MemorySaver()
graph = builder.compile(checkpointer=memory)

config = {"configurable": {"thread_id": "1"}}

async for event in graph.astream(
    {
        "messages": [
            HumanMessage(
                content="Generate an essay on how is AI changing creative work today?"
            )
        ],
    },
    config,
):
    print(event)
    print("---")
Enter fullscreen mode Exit fullscreen mode

2. The Tool Use Pattern: Expanding Capabilities

AI agents can significantly enhance their capabilities by interacting with external tools and APIs. This is the essence of the tool use pattern. Think of it as giving your AI agent a toolbox. For instance, an agent could use a calculator for mathematical operations, a search engine API to access real-time information, or a weather API to get the latest forecast.

Simple Implementation Example using Google ADK :

An agent selecting the best tool from its set to answer a specific user request.

from google.adk.agents import Agent
from google.adk.tools import google_search, calculator

# Define a custom tool
def get_weather(location: str) -> dict:
    """Retrieve current weather information for a location.

    Args:
        location: The city or region to get weather for

    Returns:
        A dictionary with weather information
    """
    # In a real implementation, this would call a weather API
    return {"temperature": "72°F", "condition": "Sunny", "humidity": "45%"}

# Create a Tool-using agent
tool_agent = Agent(
    name="multi_tool_assistant",
    model="gemini-2.0-pro",
    instruction="""You are a helpful assistant with multiple tools at your disposal.
    Use the appropriate tool based on the user's request:
    - For factual questions, use the search tool
    - For calculations, use the calculator
    - For weather inquiries, use the weather tool
    Explain which tool you're using and why.""",
    description="An assistant that uses multiple tools to answer questions",
    tools=[google_search, calculator, get_weather]
)
Enter fullscreen mode Exit fullscreen mode

3. The Planning Pattern: Charting a Course for Complex Tasks

Effective AI agents don't just react to their environment; they plan. The Planning pattern involves an agent formulating a sequence of actions to achieve a specific goal. This can range from simple, short-term plans to complex, hierarchical plans that adapt to changing circumstances. Planning allows agents to be proactive, anticipate challenges, and work towards long-term objectives, making their behavior more purposeful and efficient.

Simple Implementation Example using CrewAI :

An agent planning its route to a destination, considering intermediate steps.

import os
from crewai import Agent, Task, Crew, Process
from crewai.llms import ChatOpenAI

# Set your API key
os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY_HERE"

# Define the specific LLM you want to use
llm = ChatOpenAI(model_name="gpt-4.1-mini-2025-04-14", temperature=0.7)

# Define your agents
planner = Agent(
  role='Trip Planner',
  goal='Create a detailed, step-by-step travel plan from a starting point to a destination.',
  backstory="""You are a meticulous travel planner. You are an expert at breaking down
  a journey into a series of clear, manageable steps. You consider all aspects of travel,
  including walking, public transport, and driving.""",
  verbose=True,
  allow_delegation=False
)

executor = Agent(
  role='Travel Route Executor',
  goal='Follow a given travel plan step-by-step.',
  backstory="""You are a diligent and precise travel assistant. Your job is to take a
  pre-made plan and announce each step as you "execute" it, ensuring the journey is
  followed exactly as planned.""",
  verbose=True,
  allow_delegation=False,
)

# Define the tasks
# Task 1: The Planning Task
# The planner agent will take this task and create the plan.
plan_task = Task(
  description='Create a simple travel plan to get from my "Home" to my "Work" office. The plan should have at least 3 steps, including using a bus.',
  expected_output='A numbered or bulleted list of steps to follow.',
  agent=planner
)

# Task 2: The Execution Task
# The executor agent will take the output of the plan_task and "execute" it.
# The 'context' parameter is key here, as it chains the tasks together.
execute_task = Task(
  description='Execute the travel plan provided. Announce each step clearly before proceeding.',
  expected_output='A confirmation message for each step in the plan.',
  agent=executor,
  context=[plan_task] # This tells the task to use the result from 'plan_task' as input.
)

# Create the crew
trip_crew = Crew(
  agents=[planner, executor],
  tasks=[plan_task, execute_task],
  process=Process.sequential, # The tasks will run one after the other.
  llm=llm
)

# Start the crew's work
print("## Kicking off the Trip Planning Crew...")
result = trip_crew.kickoff()

print("Final Result:")
print(result)
Enter fullscreen mode Exit fullscreen mode

4. The Multi-agent Collaboration Pattern: The Power of Teamwork

Some problems are too complex for a single AI agent to solve alone. The Multi-Agent Collaboration pattern involves multiple AI agents working together, each with their own roles and responsibilities, to achieve a common goal. This can involve agents specializing in different tasks, sharing information, and coordinating their actions. By combining their strengths, collaborative agents can tackle challenges that would be impossible for individual agents, leading to more robust and intelligent systems.

Simple Implementation Example using AutoGen :

Two agents: one to write code and one to run it and provide feedback.

import autogen
import os

# Configuration for the OpenAI model
config_list = [
    {
        "model": "gpt-4.1-2025-04-14",
        "api_key": os.environ.get("OPENAI_API_KEY"),
    }
]

# 1. Create the Coder Agent
# This agent writes Python code to solve tasks.
coder = autogen.AssistantAgent(
    name="Coder",
    llm_config={"config_list": config_list}
)

# 2. Create the Executor Agent
# This agent acts as the user's proxy to execute the code and report results.
user_proxy = autogen.UserProxyAgent(
    name="Executor",
    human_input_mode="NEVER",  # Fully automated collaboration
    code_execution_config={
        "work_dir": "coding_output",  # Directory to save and run code
        "use_docker": False,        # Set to True if you have Docker installed for safety
    },
)

# 3. Start the Chat
# The Executor agent initiates the conversation with the Coder agent.
user_proxy.initiate_chat(
    recipient=coder,
    message="""Write a Python script that prints the first 8 numbers of the Fibonacci sequence."""
)
Enter fullscreen mode Exit fullscreen mode

These four design patterns—Reflection, Tool Use, Planning, and Multi-Agent Collaboration—are fundamental to building AI agents that are not just smart, but also adaptable, efficient, and capable of tackling real-world complexities. By understanding and applying these patterns, we can unlock the full potential of AI and create truly intelligent systems.

Top comments (0)