AdvancedAI AgentsFree Guide

AI Agent Design Patterns — ReAct, Multi-Agent Systems

AI agents extend LLMs with a feedback loop — perceive → reason → act → observe → repeat — enabling them to solve multi-step tasks that a single prompt cannot.

What is it?

AI Agents are LLM-powered systems that take sequences of actions to accomplish goals, rather than responding to a single prompt. An agent perceives its environment through tool outputs, reasons about what to do next, takes actions (tool calls), and iterates until the task is complete. The key difference from a plain LLM call: agents have a feedback loop — outputs inform the next input.

How it works

The ReAct (Reasoning + Acting) pattern is the most widely used agent architecture:

Loop: while not done:

  1. LLM receives: [system prompt] + [conversation history] + [available tools as JSON schema]
  2. LLM outputs either: a. Tool call: {"name": "search", "input": {"query": "..."}} b. Final answer: direct text response (task complete)
  3. If tool call: execute tool → append result to history → go to 1
  4. If final answer: return to user

Context management is critical: each loop iteration adds messages to context. A complex task might require 20 iterations × 500 tokens = 10K tokens before answering. With GPT-4 at $10/1M input tokens, a complex agent task costs $0.10 just in context re-reading.

Multi-agent patterns: orchestrator agents delegate to specialized sub-agents. Example: ResearchAgent calls WebSearchAgent and DataAnalysisAgent in parallel, then synthesizes results. LangGraph and CrewAI implement graph-based multi-agent coordination.

Code example

import anthropic client = anthropic.Anthropic() tools = [{"name": "search_web", "description": "Search the web", "input_schema": {"type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"]}}] messages = [{"role": "user", "content": "What is the current price of Claude API?"}] while True: response = client.messages.create(model="claude-opus-4-5", max_tokens=1024, tools=tools, messages=messages) if response.stop_reason == "end_turn": print(response.content[0].text) break for block in response.content: if block.type == "tool_use": result = search_web(**block.input) messages.append({"role": "assistant", "content": response.content}) messages.append({"role": "user", "content": [{"type": "tool_result", "tool_use_id": block.id, "content": result}]})

Key concepts

ReAct loop (Reason + Act)tool calling / function callingtool schema (JSON)multi-agent orchestrationcontext accumulationmax_iterations guard

Common mistakes

No max_iterations limit. An agent trying to find information that does not exist will loop indefinitely. Always set a hard limit (typically 10–25 iterations) and return a 'could not complete' message when reached.

Tool descriptions that are too vague. Write descriptions like a contract: specify what the tool does, what inputs it expects, what it returns, and when NOT to use it.

Giving agents irreversible capabilities without confirmation. If an agent can send emails or delete records, require explicit human confirmation before any write operation to external systems.

Not handling tool errors in the agent loop. Tools fail — APIs return 429s, databases time out. Wrap tool calls in try/except and return structured error messages the LLM can reason about.

Using a single huge agent with 50 tools. The tool selection problem becomes overwhelming. Split into specialized agents (SearchAgent, CodeAgent) coordinated by an orchestrator.

Interview questions on this topic

How do you handle rate-limiting and token quotas when deploying multi-agent systems composed of multiple active loops?

Walk through the design of the Agent-User Interaction (AG-UI) protocol. How does it handle streaming tool call executions?

Practice answering these with structured learning → Start on CrackLab

Continue learning — explore the full AI Engineering curriculum

30+ structured topics from Python fundamentals to deploying production LLM systems. Free to start.

See all topics

Related free guides