Shared Memory and State
Agents that share context and knowledge — the difference between a team and a group of strangers.
What You'll Learn
- Why isolated agents produce inconsistent results
- Three models for shared state: context passing, shared memory, and vector stores
- How to design state schemas that scale
- Preventing state corruption in multi-agent systems
Agents Without Shared Memory Are Goldfish
Agent A researches a customer's history. Agent B handles the customer's complaint. But Agent B doesn't know what Agent A found. So it asks the customer to repeat everything. Sound familiar? It's the same frustration you feel when a company transfers your call and you have to start over.
Without shared memory, each agent operates in isolation. The system has knowledge, but no individual agent can access the full picture. Shared state fixes this.
Context Passing: The Relay Baton
The simplest approach: each agent receives the accumulated context from all previous agents in its prompt. Agent A's output becomes part of Agent B's input, which becomes part of Agent C's input.
Pros: Simple to implement. No external infrastructure. Every agent has full history.
Cons: Context windows fill up fast. By agent 5 or 6, you're running out of room for the actual task. Doesn't scale.
def pipeline_with_context(task: str, agents: list) -> str:
# Each agent sees ALL previous outputs (context grows with each step)
context = f"Original task: {task}\n"
for name, system_prompt in agents:
result = call_agent(system_prompt, context)
context += f"\n--- {name} output ---\n{result}\n" # accumulate
return context
# Problem: by agent 5, the context might be 50,000+ tokens
# That leaves little room for the agent's own reasoning
Shared Memory Store: The Team Database
All agents read from and write to a central store — a database, a key-value store, or even a structured document. Each agent queries only what it needs instead of carrying everything.
Pros: Scales to many agents. Each agent gets relevant context without bloat. Persists across sessions.
Cons: Requires infrastructure. Agents need to know what to query. Stale data is a risk if updates lag.
from supabase import create_client
db = create_client(SUPABASE_URL, SUPABASE_KEY)
class SharedMemory:
def __init__(self, task_id: str):
self.task_id = task_id
def write(self, agent: str, key: str, value: any):
# Each agent writes to its own namespace
db.table("agent_memory").upsert({
"task_id": self.task_id,
"agent": agent, "key": key, "value": value
}).execute()
def read(self, key: str) -> any:
# Any agent can read any key
row = db.table("agent_memory").select("value").eq(
"task_id", self.task_id
).eq("key", key).single().execute()
return row.data["value"]
# Usage: agents share state without carrying it in their context
mem = SharedMemory("content-042")
mem.write("researcher", "findings", research_output) # researcher writes
findings = mem.read("findings") # writer reads
Vector Store: The Semantic Brain
Store agent outputs as embeddings in a vector database. When an agent needs context, it performs a semantic search — "find everything related to customer billing issues" — and gets the most relevant pieces, regardless of when or which agent produced them.
Pros: Handles massive amounts of context. Agents retrieve only what's relevant. Gets smarter as more data accumulates.
Cons: More complex to set up. Embedding quality matters. Results can be unpredictable.
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-MiniLM-L6-v2") # free, runs locally
def store_memory(text: str, agent: str, task_id: str):
# Convert text to a vector and store in Supabase with pgvector
embedding = model.encode(text).tolist()
db.table("agent_vectors").insert({
"task_id": task_id, "agent": agent,
"content": text, "embedding": embedding
}).execute()
def recall(query: str, task_id: str, limit: int = 3) -> list:
# Semantic search: find the most relevant agent memories
query_vec = model.encode(query).tolist()
result = db.rpc("match_agent_memory", {
"query_embedding": query_vec,
"filter_task": task_id,
"match_count": limit
}).execute()
return [r["content"] for r in result.data]
# Editor agent needs billing context — semantic search finds it
relevant = recall("customer billing history", "support-099")
# → Returns the 3 most relevant memories from ANY agent
A State Schema That Works
Shared State Object
{
"task_id": "content-pipeline-042",
"status": "in_progress",
"current_stage": "editing",
"artifacts": {
"research": { "agent": "researcher", "completed": true, "output_ref": "..." },
"draft": { "agent": "writer", "completed": true, "output_ref": "..." },
"review": { "agent": "editor", "completed": false }
},
"shared_context": {
"target_audience": "technical managers",
"tone": "professional but approachable",
"word_limit": 1500
},
"flags": ["needs_fact_check", "client_mentioned_deadline"]
}
Every agent reads shared_context. Each updates its own artifact. Flags communicate cross-cutting concerns.
This lesson is for Pro members
Unlock all 520+ lessons across 52 courses with Academy Pro.
Already a member? Sign in to access your lessons.