Multi-agent AI systems in 2025: architecture, tools, pitfalls
How to build production-ready multi-agent systems in 2025: Hermes-style orchestration, LangChain, autogen, evaluation. Practical guide with code and real pitfalls.
Multi-agent AI systems in 2025
Over the past two years I have built five multi-agent systems for various clients β from lead generation platforms to internal code analysis tools. Each looked different on a diagram, but the patterns repeat. This post is about those patterns.
What a multi-agent system actually is
It is not five LLM models calling each other indefinitely. It is problem decomposition into roles:
- Planner β receives the high-level goal, breaks it into steps
- Executor β performs concrete actions (function calling, API, database)
- Reviewer β critiques Executor's output, requests a fix or accepts
- Researcher (optional) β supplies context, documents, code snippets
A well-designed multi-agent system is not a chat. It has state, it has control flow and it has a way to stop when the task is done or when it gets stuck in a loop.
Minimal architecture that works in production
The simplest system maintainable in production is 2 agents + a loop with iteration limit:
import openai
import json
MAX_ITERATIONS = 8
def run_agent_loop(task: str) -> str:
state = {"task": task, "history": [], "iteration": 0}
while state["iteration"] < MAX_ITERATIONS:
state["iteration"] += 1
# Planner: decides what is next
plan = call_planner(state)
state["history"].append({"role": "planner", "content": plan})
if plan["action"] == "DONE":
return plan["final_answer"]
if plan["action"] == "TOOL_CALL":
# Executor: performs the concrete call
result = call_executor(plan["tool"], plan["args"])
state["history"].append({"role": "executor", "content": result})
# Reviewer: critiques
critique = call_reviewer(state)
state["history"].append({"role": "reviewer", "content": critique})
if critique["approved"]:
return critique["final_answer"]
raise RuntimeError(f"Agent loop stuck after {MAX_ITERATIONS} iterations")
This is the skeleton β 30 lines handling planning, execution and validation. Add:
- persistence (
stateto Redis/SQLite, not in memory) - observability (LangSmith or a custom logger with token counts)
- schema validation on every output (Pydantic / Zod)
- rate limiting (429 from OpenAI is not an exception, it is normal)
And you have a production-grade system.
Hermes-style orchestration: a pattern that works in my projects
Internally I call it Hermes-style after my main agent framework (Hermes Agent, which is what I work on). The key idea: the orchestrator is a thin layer over deterministic code, not over another LLM.
βββββββββββββββββββββββββββββββββββββββββββββββ
β Orchestrator (Python/TypeScript) β
β βββββββββββββββββββββββββββββββ β
β - knows what the user wants β
β - calls agents in the right order β
β - validates results (Zod) β
β - logs everything β
ββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β
βββββββββΌββββββββ
βΌ βΌ βΌ
Agent1 Agent2 Agent3
(LLM) (LLM) (LLM)
β β β
βΌ βΌ βΌ
Tools Tools Tools
The orchestrator is not an LLM. It is plain code with if/else, loops, retry logic. Only the inner agents are LLMs. This inverts a typical mistake: people make the orchestrator an LLM, then wonder why it hallucinates at the control level.
Tools β when to use what
| Framework | When to use | When NOT to use | |-----------|-------------|-----------------| | Own code (OpenAI function calling) | 1-3 agents, prototype, MVP | Above 5 agents, you need a state graph | | LangGraph | 4+ agents, complex graph, persistence | Simple sequential pipeline β overengineering | | autogen (Microsoft) | Conversational agents, research, exploration | Production needing low latency and low cost | | CrewAI | Role-based agents (like a crew), content creation | When you need precise control flow | | LlamaIndex Agents | RAG-heavy workflow (agents read documents) | Mostly function calling, no RAG |
My recommendation: start with your own code. Frameworks give 30% time savings at the start, but 200% more pain when debugging in production, when LangChain version changes and everything breaks.
Five pitfalls I have seen at clients
1. No iteration limit
The agent enters a loop: Planner says "execute X", Executor returns an
error, Planner says "try X again", Executor returns the same error. After
200 iterations you have a $47 OpenAI bill and a Cloudflare timeout. Always
set MAX_ITERATIONS. I default to 8.
2. No schema validation
The agent returns "looks good" instead of JSON. The parser throws. The code breaks. Every agent output must be validated (Pydantic in Python, Zod in TypeScript). Without it you do not know whether the bug is in the agent, the prompt, the parser, or the data.
3. Too many agents from the start
A client wants "a chatbot that does research, writes reports, manages a calendar and books flights". These are four different products, not one. Start with one agent doing one thing well. Add a second only when the user really needs both capabilities at the same time.
4. No observability
A multi-agent system in production without logs is a black box. When the user says "it did not work", you have no idea why. Minimum:
- Every LLM call: timestamp, model, prompt, output, token count, latency
- Every orchestrator decision: why it called agent X not Y
- Every tool call: input, output, execution time
Without these you do not debug, you guess.
5. Hallucinations cascade
Agent A hallucinates that the user wants X. Agent B takes it for granted. Agent C builds on that. None of the three knows A was wrong. Solution: a Reviewer agent (pattern above) or grounding in data β the agent must cite the source, otherwise its answer is rejected.
When multi-agent does NOT make sense
Let us be honest. In 60% of cases where people deploy multi-agent, they would be better off with:
- A good prompt + one GPT-4o model
- Function calling for 3-4 tools
- RAG with good retrieval
Multi-agent makes sense when:
- The task naturally splits into roles (research β plan β execute β review)
- A single agent regularly overflows the context (long conversation history)
- You need different models for different tasks (e.g. GPT-4o for planning, GPT-4o-mini for simple classifications β 80% cost savings)
- You have an auditability requirement (each step has its own agent = own log)
If none of these fit β do not build a multi-agent. Stay with one agent and function calling. It is less "impressive" but 10x easier to maintain.
What is next
In upcoming posts I will expand on specific topics:
- OpenAI API in practice: function calling, embeddings, RAG
- GEO vs SEO β how to write content that AI cites
- AI search engines vs Google
If you are building a multi-agent system and you are stuck β get in touch. I help with architecture, code review and production debugging.
NajczΔΕciej zadawane pytania
What is a multi-agent system in AI?
Do I need LangChain or autogen to build multi-agent systems?
How many agents is 'multi-agent' and when is it overkill?
How do you debug a multi-agent system in production?
Related posts
- aiAI
OpenAI API in practice: function calling, embeddings and RAG
Production code for OpenAI API: function calling, embeddings, vector database, RAG pipeline. Concrete examples, real pitfalls, costs. For developers, not marketers.
7 min - aiAI
How AI search engines rank content differently than Google β and what to do
Ranking algorithms of ChatGPT, Perplexity, Gemini and Google AI Overview β what they share, how they differ, how to optimize for them. Data from 12 months of testing.
6 min