Lesson 12 of 21Track 2

State management

Shared state vs isolated state

Tradeoffs in multi-agent state.

Video lesson ~10 min

Video coming soon

Two state philosophies

Once you have multiple agents, you have to decide what they remember together and what they remember separately. Two ends of the spectrum:

  • Shared state. All agents read and write the same blob of data. Whatever one agent learns, everyone else sees on their next turn.
  • Isolated state. Each agent has its own private state. Nothing leaks between them except through explicit handoffs.

Most real systems sit somewhere in between, and the design choice is mostly about which slices of state are shared and which are isolated. Get this wrong and you get one of two problems: agents that constantly contradict each other (too much isolation), or agents whose context is poisoned by everyone else's noise (too much sharing).

Why fully shared is bad

The naive multi-agent design gives every agent access to one big state object: full conversation history, all tool results, all intermediate findings. Sounds like the most "informed" setup, but in practice:

  • Every agent's context grows linearly with system activity. Tokens balloon.
  • Agents are biased by other agents' reasoning, even when they should reason independently.
  • Debugging is a nightmare. A change in one agent shows up in every agent's behavior, and there is no clear ownership.

This is the multi-agent equivalent of context pollution. It is also why the structured handoff schema from Module 2 exists: to break the assumption that agents share everything by default.

Why fully isolated is also bad

The opposite extreme: each agent operates with zero knowledge of the others. The orchestrator dispatches handoffs but never carries information from one worker's result into the next worker's handoff. Each agent reasons in a vacuum.

Failure modes:

  • The same investigative work happens twice because agent B does not know agent A already looked.
  • Cross-cutting facts (the user's preferences, environment, constraints) have to be re-derived in each agent.
  • Conflicting decisions: agent A picks plan X, agent B picks plan Y, and the orchestrator has to reconcile them at the end.

Pure isolation also tends to produce systems where the orchestrator becomes a giant translator, copying summaries from every agent into every other agent. Now your orchestrator is the bottleneck.

What to share and what to isolate

Three categories help reason about this:

1. Universal facts (shared)

User identity, current time, environment (prod vs staging), language preferences, brand guidelines. These do not change during a session and apply to every agent. Make them shared, ideally as a small read-only "context" object that every agent gets at construction.

2. Domain-specific working memory (isolated)

The code agent's understanding of which file does what. The ops agent's mental model of the deploy pipeline. The comms agent's draft history. These are intermediate scratch space for one agent's reasoning. Sharing them with other agents is what causes pollution.

3. Findings worth telling others (shared, on commit)

When an agent has a reportable conclusion ("the bug is in retries.py at line 42"), that fact should flow into shared state so other agents can see it. The key word is commit: this is a finalized output, not in-progress reasoning.

The pattern is: keep working memory isolated, expose committed findings to a shared blackboard, let the orchestrator decide what to forward.

The blackboard pattern

A useful design from classical AI: a shared "blackboard" that any agent can write to and read from, plus a coordinator that decides what to do based on what is on the blackboard.

@dataclass
class Blackboard:
    user_request: str
    facts: dict           # committed findings, keyed by agent
    artifacts: dict       # typed pieces of data
    next_step: str | None
 
    def commit(self, agent_name, fact):
        self.facts[agent_name] = fact

Each agent's loop only sees:

  • Its own private working memory (messages, scratch).
  • The blackboard's facts and artifacts.
  • A handoff with the current step's intent.

When it finishes, it commits a finding to the blackboard and returns. The orchestrator reads the blackboard and decides what comes next.

This is a clean middle ground. Agents work in isolation but have visibility into committed cross-agent state. The blackboard is the explicit shared API.

State boundaries match agent boundaries

The single best rule for designing multi-agent state: an agent's private state should be exactly what the agent reasons over. Anything that crosses the agent boundary should be a structured artifact on the blackboard, not a leak from one agent's working memory.

This is also why Module 2's handoff schema and Module 3's outer/inner loop split are foundations: they enforce the same rule from different angles.

LayerVisibility
Agent's message historyPrivate
Agent's tool resultsPrivate
Agent's intermediate scratch / chain of thoughtPrivate
Findings committed to blackboardShared (read-only after commit)
Universal facts (user, environment, time)Shared (read-only)
Handoff payloadsPairwise (sender to receiver)

If your design doesn't match this table, it is probably leaking somewhere.

Concurrent writes: race conditions in state

If two agents can write the same state slice concurrently, you have a coordination problem. Options:

Single-writer per slice

Only one agent owns each blackboard key. The code agent writes code_findings; nobody else does. Simple and effective.

Versioned writes

Every write includes the version it expected to find. If the version differs, the write is rejected. The agent has to re-read and try again.

Append-only

Nobody overwrites; everyone appends. Conflicts disappear, but you have to reason about ordering when reading back.

For most agent systems, single-writer is enough. Versioning matters more in long-lived stateful agents (week-long workflows, research projects), which lean on the patterns in the next lesson.

When isolation produces 'amnesia'

A common bug: an agent re-asks for information another agent already retrieved, because it does not see the other's state. Fix by promoting the relevant fact to the blackboard, not by sharing the originating agent's full working memory. The handoff schema and the blackboard exist precisely to surface what should be shared without sharing the rest.

A concrete recipe

For a typical supervisor/worker system, the state design is:

  1. One blackboard object with user_request, facts: dict, artifacts: dict, step_history: list.
  2. Each worker has its own message list, never serialized to the blackboard.
  3. Handoffs read from the blackboard, write the worker's finding back to the blackboard on completion.
  4. The supervisor reads the blackboard, plans the next step, dispatches.

If this is your design, you have isolation where it matters and sharing where it matters. The next lesson formalizes this further by modeling the orchestration loop as a state machine.

Key takeaway

Shared state pollutes; isolated state amnesias. The right answer is to share committed findings through an explicit blackboard while keeping each agent's working memory private. Match state boundaries to agent boundaries. The next lesson treats the orchestration loop itself as a state machine: PLANNING, EXECUTING, OBSERVING, REFLECTING, COMPLETE, FAILED. That formalism is what the rest of this module and Track 4's reliability discussion rest on.

Done with this lesson?