AI Agents · Ai

Multi-Agent Systems — A Field Guide

Multi-Agent Systems — A Field Guide is the work that defines the next phase of enterprise software. ERP systems hold the most valuable business data in the company — customers,.

John Kihiu12 min read

Most teams reach for multiple agents before they need to. A single well-designed agent with a good tool set handles the majority of ERP automation tasks fine. Multi-agent architectures earn their complexity when a task genuinely decomposes into specialties that benefit from separate contexts, separate tool access, or separate failure isolation — not because it sounds more sophisticated in a design doc.

When multiple agents actually help

The honest reasons to split into multiple agents: context isolation (an agent reasoning about AP shouldn't carry the full history of an unrelated AR conversation), tool-surface isolation (a read-only reporting agent should not have write access to post journal entries, enforced structurally rather than by prompt), and parallelism (three independent lookups that don't depend on each other's output can run concurrently instead of serially). None of these require a fancy framework — they require a clear boundary and a defined interface between agents. If your only reason for splitting is "the prompt got long," summarize or prune the context instead; that's a memory problem, not an orchestration problem.

The two topologies that cover most cases

Supervisor-worker: one orchestrating agent routes a task to specialist sub-agents and combines their results. This is the easier pattern to debug because there's a single place that owns the overall plan. Pipeline: agents run in a fixed sequence, each consuming the previous one's output — useful when the steps are genuinely sequential (extract data, validate it, then act on it) and you want each stage to have a narrow, testable responsibility. Fully decentralized "agents negotiating with agents" topologies exist in research but rarely earn their complexity in production ERP workflows; the failure modes (infinite back-and-forth, unclear ownership of the final answer) cost more than they save.

PYTHON · SUPERVISOR-WORKER, MINIMAL
def handle_request(user_query: str) -> str:
    route = classify_intent(user_query)  # cheap model or rules, not the big model
    if route == "invoice_lookup":
        result = invoice_agent.run(user_query)
    elif route == "po_status":
        result = procurement_agent.run(user_query)
    else:
        result = general_agent.run(user_query)
    return supervisor_summarize(user_query, result)  # one final, consistent voice
Routing doesn't need an LLM call

Classifying which specialist should handle a request is often a cheap, deterministic decision — keyword match, a small classifier, or a rules table keyed on the entity type the user mentioned. Spending a full LLM call just to decide "which agent handles this" adds latency and a failure point for no benefit over a lookup table.

Shared state is the hard part

The interesting failures in multi-agent systems aren't in any single agent's reasoning — they're in what gets passed between agents. Pass structured data (a typed result object: order ID, status, amount) between agents, not free-text summaries that the next agent has to re-parse with its own LLM call. Every re-parse is a chance to lose or corrupt a number. If agent A extracts an invoice total and agent B needs it, hand B the number directly in the function call, not embedded in a paragraph B has to read.

Failure containment

A single agent that fails, fails visibly — the whole run stops. A multi-agent system can fail silently if one sub-agent returns a plausible-but-wrong result and the supervisor doesn't validate it before using it. Every sub-agent boundary needs the same deterministic validation you'd put around a single agent's tool calls: check the shape and range of what came back before passing it forward. Treat every sub-agent as untrusted input to the next stage, the same way you'd treat raw LLM output at any other boundary.

Cost and latency compound

Three agents making sequential LLM calls is three times the latency of one, and if each has its own reasoning pass, three times the token cost too. Parallelize what's genuinely independent, and be honest about whether the task decomposition is worth the multiplier. A single agent with a well-scoped tool list often beats a three-agent pipeline on both cost and reliability for tasks that don't actually need separate specialties.

SignalSuggests
Tool list per task exceeds ~10-15 toolsSplit by tool-access domain
Steps are independent and slowParallel sub-agents, supervisor merges
Steps are strictly sequentialPipeline, not supervisor-worker
Only reason to split is prompt lengthDon't split — prune context instead

Wrapping up

Start with one agent and a well-designed tool set. Move to multiple agents only when you can name the specific isolation boundary — context, tool access, or parallelism — that a single agent can't provide. Pass structured data between agents, validate at every boundary the same way you'd validate any other untrusted input, and keep routing decisions as cheap and deterministic as the task allows.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.