Architecting Agent-Based Systems
The previous chapters built up one agentic workflow: roles, tools, memory, reflection, revision, and versioning. This chapter changes scale.
An agent-based system is not one large assistant with a bigger prompt. It is a collection of components that divide responsibility, communicate through explicit channels, use shared or separate state, and preserve enough identity that you can tell which part did what.
The design question is:
Which responsibilities belong together,
which should be separated,
and how should the separated parts coordinate?
Architecture begins when those boundaries have to be chosen deliberately.
When One Agent Is Not Enough
A single agent is often the right starting point. It is cheaper, easier to inspect, and easier to debug.
Start from the failure, not from the architecture diagram. If one role keeps mixing research with judgment, separation may help. If a single prompt is losing track of state, explicit memory may help. If a tool call can change something important, an approval boundary may help. But every extra agent adds latency, cost, state synchronization, and another place for responsibility to blur.
Multiple agents become useful when the task benefits from separation:
| Need | Why multiple agents may help |
|---|---|
| Specialized context | each role sees only the information it needs |
| Specialized tools | risky tools can be exposed only to bounded roles |
| Parallel work | research, drafting, and checking can happen separately |
| Independent review | a critic can evaluate without owning generation |
| Clear accountability | outputs can be traced to named roles |
| Cross-domain work | bridge agents can translate between systems |
The cost is real:
handoff errors
duplicated work
inconsistent state
latency
more tokens
role confusion
harder debugging
Do not add agents because the diagram looks more impressive. Add them when a responsibility boundary earns its cost.
Coordination Models
There is no single correct shape for a multi-agent system. The control structure should match the work.
Centralized
A centralized system has one manager, planner, or orchestrator that assigns work and decides what happens next.
manager
โโ researcher
โโ writer
โโ critic
Centralized systems are good for early prototypes, sequential workflows, tight control, and cases where one component should own the final decision. They are easier to understand because the route through the system is concentrated in one place.
They can also bottleneck. If the manager has weak instructions, poor state, or too much authority, the whole system inherits that weakness.
Decentralized
A decentralized system lets agents coordinate through messages, shared state, event logs, or task queues without one permanent central controller.
researcher <-> shared memory <-> critic
writer <-> shared memory <-> reviewer
This can support parallel work, resilience, and dynamic routing. It is useful when no single role has enough context to control everything.
It is also harder to debug. Without strong identity, schemas, permissions, and conflict rules, decentralized systems become noisy quickly.
Hybrid
A hybrid system combines direction with local autonomy.
manager sets goal and constraints
โ
specialized agents act within scope
โ
manager or reviewer integrates results
Most practical agent systems become hybrid. A manager sets the frame; specialized roles decide how to perform their bounded part; a reviewer or policy layer decides what to accept.
flowchart LR
subgraph Centralized
P[Planner]
P --> C1[Researcher]
P --> C2[Writer]
P --> C3[Critic]
end
subgraph Hybrid
L[Lead agent]
L --> H1[Researcher]
L --> H2[Writer]
L --> H3[Reviewer]
H1 <--> H2
H2 <--> H3
end
subgraph Decentralized
D1[Agent]
D2[Agent]
D3[Agent]
D4[Agent]
M[(Shared memory)]
D1 <--> M
D2 <--> M
D3 <--> M
D4 <--> M
D1 <--> D2
D3 <--> D4
end
The choice is less about philosophy than operational need.
| Model | Best when | Watch out for |
|---|---|---|
| Centralized | you need simplicity and control | bottlenecks, single point of failure |
| Decentralized | work is parallel or distributed | inconsistent state, hard debugging |
| Hybrid | roles need autonomy under oversight | unclear handoffs, duplicated authority |
Shared Memory as a Coordination Layer
Agents can coordinate by passing messages directly, but many systems need a shared record.
Shared memory might be:
JSONL event log
database table
document store
vector index
task board
artifact repository
The important property is not the storage technology. It is that the system has a place where roles can leave structured traces for other roles to read.
A simple shared-memory log might look like this:
{"role":"planner","type":"plan","task_id":"t1","summary":"Summarize article in three stages"}
{"role":"researcher","type":"finding","task_id":"t1","claim":"The article's core claim is X","evidence":"paragraph 4"}
{"role":"writer","type":"draft","task_id":"t1","artifact":"draft-v1"}
{"role":"critic","type":"review","task_id":"t1","decision":"revise","reason":"missing limitation"}
This record helps in three ways. It decouples roles, so a critic can read the draft entry instead of interrupting a writer. It improves auditability, because you can inspect what happened instead of relying on a final answer. It also enables asynchronous work: agents can run at different times and still share context.
Shared memory is not automatically a source of truth. It can contain drafts, mistakes, stale facts, and conflicting claims. Treat it as a coordination surface unless a particular entry has been verified.
Freshness belongs in the memory contract. A market price, file status, calendar slot, or policy rule may be true when observed and false when acted on. For high-impact actions, record observation time, decision time, and commit time separately. If the state changed between those moments, the system should re-check before acting.
Interfaces Matter More Than Agent Names
Large systems fail when agents communicate in vague blobs.
Weak handoff:
I researched it. Looks good.
Useful handoff:
role: researcher
task_id: urban-transport-001
claim: "Micromobility is increasingly regulated through city-level safety rules."
evidence_type: background
source_status: unverified
open_questions:
- Which cities changed policy in the last 12 months?
recommended_next_role: policy_researcher
An interface does not have to be complex. It has to make responsibility visible.
For every agent role, define:
name
version
purpose
inputs
outputs
allowed tools
memory access
authority
failure modes
handoff format
This turns a group of prompts into a system that can be inspected, tested, and changed.
Separate capability from authority. A component may know how to call a payment API, edit a file, or message a customer, but that does not mean it should be allowed to do so in every context. Capability says what the component can technically perform. Authority says what it is permitted to perform for this task, under these conditions, with this evidence and approval state.
For larger systems, also record the decision event:
decision_id
run_id
actor
input_state_id
proposed_action
authority_check
evidence_used
accepted_or_rejected
output_state_id
This is the minimum trace that lets you answer later: who decided, from which state, using what evidence, and what changed?
flowchart LR
M[Model proposal] --> A{Authority check}
A -->|allowed| E[Execute tool]
A -->|needs review| H[Human or policy review]
A -->|rejected| R[Recorded rejection]
H -->|approved| E
H -->|denied| R
E --> O[Observation]
O --> S[Updated state]
Tagging and Versioning
Agent behavior is shaped by many moving parts:
model
prompt / instructions
tools
memory policy
retrieval configuration
temperature and decoding settings
output schema
coordination role
evaluation criteria
If one changes, behavior may change. Versioning gives you a way to discuss that change precisely.
A minimal role record might be:
name: critic
version: 1.3.0
model: recorded_at_runtime
prompt_id: critic_prompt_v4
input_schema: candidate_summary_v2
output_schema: critique_v1
tools:
- citation_checker
memory_access:
- current_task_log
authority: recommend_only
status: production
Versioning is not bureaucracy. It is how you answer the practical question:
Which version produced this decision?
Without that answer, regression becomes guesswork.
From COM to Modular Agent Systems
The older software world already solved parts of this problem.
Microsoft’s Component Object Model, COM, was a way to build systems from addressable components with known interfaces. COM components had identity. They could be registered, discovered, invoked through interfaces, versioned, and replaced without every caller knowing their internals.
Agent systems are different, but the analogy is useful.
| COM idea | Agent-system equivalent |
|---|---|
| Component identity | named role with version |
| Registry | agent catalog or metadata store |
| Interface | input/output schema and tool contract |
| Loose coupling | handoffs through messages or shared state |
| Late binding | choose a role implementation at runtime |
| Versioning | compare, roll back, deprecate, replace |
The value of the analogy is restraint. It reminds us that modularity is not new. What is new is that some components contain probabilistic model behavior.
That makes interfaces more important, not less.
An agent registry can be simple:
agents:
- name: researcher
version: 1.0.0
purpose: gather evidence
outputs: finding_v1
tools: [search, document_reader]
- name: critic
version: 1.1.0
purpose: review candidate artifacts
outputs: critique_v1
tools: [checklist]
- name: bridge_agent
version: 0.4.0
purpose: translate between legal and finance schemas
outputs: transfer_review_request_v1
Once roles are registered, the system can swap implementations, route tasks by capability, and keep old versions available for rollback.
Bridge Agents
Bridge agents are one of the most distinctive ideas in this book.
A bridge agent connects two systems that do not share the same language, schema, assumptions, or workflow. It does not merely summarize. It translates between contexts.
For example, a finance system may produce:
portfolio exposure
risk category
counterparty
asset class
A legal system may need:
contract obligation
jurisdiction
consent requirement
review status
A bridge agent sits between them:
finance output
โ
bridge agent
โ
legal review request
The bridge should not silently invent compatibility. It should map fields, identify missing information, preserve uncertainty, and escalate when the translation is unsafe.
In larger organizations, this pattern becomes important because agent systems will not all be built by the same team. They will have different models, policies, schemas, logs, and definitions of success.
Bridge agents make collaboration possible across boundaries, but they also create risk. A bad bridge can convert a careful statement in one domain into an overconfident action in another.
The bridge should therefore separate content from control. A document received from another organization can supply facts to inspect; it should not silently supply instructions about which internal tools to call, which permissions to grant, or which approval rules to skip. The receiving system should treat outside material as untrusted content until its own policy layer decides otherwise.
Good bridge design therefore needs:
source schema
target schema
mapping rules
unknown / missing field behavior
validation
audit log
human escalation path
Interorganizational Coordination
Consider two companies coordinating a complex transaction.
Company A has an internal data agent that can assemble an asset bundle. Company B has a compliance agent that can review the bundle. A bridge agent translates Company A’s package into Company B’s intake format. A risk agent flags missing consent documents. A human reviewer approves or rejects the final transfer.
The architecture might look like this:
Company A data system
โ
Data Custodian Agent
โ
Bridge Agent
โ
Company B Compliance Agent
โ
Risk Review
โ
Human approval
Such transfers should not run without oversight. As coordination becomes more automated, boundaries, logs, schemas, and authority become more important.
The promise is speed and clarity. The danger is misplaced trust.
Interorganizational agents need contracts, authentication, permissions, audit trails, revocation, and human accountability. Otherwise the system can move faster than anyone can understand.
Designing Your Own Agent Framework
You can design a small framework before writing much code. Start with the architecture.
- Identify the roles.
planner
researcher
writer
critic
reviewer
memory manager
bridge
- Define the communication model.
sequential chain
central manager
shared memory
event log
hybrid
- Define each interface.
input schema
output schema
allowed tools
memory access
authority
error behavior
- Add versioning.
role version
prompt version
tool version
memory policy version
model recorded at runtime
- Add evaluation and rollback.
what counts as success?
who can accept a candidate?
what happens when a new version is worse?
A micro-agent article summarizer might have only three roles:
Planner:
split article into sections
Summarizer:
produce section summaries
Critic:
check accuracy, missing context, and clarity
All three can read and write a shared task log. That is enough to practice the architecture without pretending you have built a full platform.
Learning From Experience
Agent systems can use experience, but the word “learning” needs care.
A system can log past interactions, score outputs, compare versions, store accepted examples, retrieve useful memories, and change future prompts. That is experience at the system level.
The model’s weights usually have not changed.
Useful experience loops include:
| Pattern | Mechanism |
|---|---|
| Reflection | review an output and propose a change |
| Grading loop | score against explicit criteria |
| Memory anchor | store a useful example or preference |
| Version comparison | decide whether a candidate beats the baseline |
| Pause threshold | stop and ask for help when confidence or evidence is insufficient |
The last pattern is especially important. A capable system should know when not to continue.
repeated failures
missing evidence
tool unavailable
low confidence
high-risk action
policy boundary
Any of those should be able to trigger a pause, fallback, or human review.
This is control logic, not self-awareness. It is what makes agent systems safer and more useful.
What Chapter 6 Adds
Chapter 3 explained the mechanisms of agent behavior. Chapter 6 turns those mechanisms into system architecture.
The core ideas are:
separate responsibilities
define interfaces
choose a coordination model
share memory carefully
register agents as components
version behavior
bridge domains explicitly
preserve human authority where stakes require it
The future of agent systems is not one giant agent doing everything. It is many bounded components, some deterministic and some model-driven, working through clear contracts.
Once a system has those contracts, the next pressure appears: a human still has to work with it. The architecture may contain roles, tools, memory, bridge agents, and authority checks, but the person at the edge needs a way to express intent, inspect what will happen, and steer the system without learning every internal interface.
That is where natural language becomes more than a prompt. It becomes the surface through which people coordinate with the architecture.