Implementing Shared vs Non-Shared Context in Multi-Agent Systems: A Complete Guide
Shared context gives all agents access to a common knowledge base via a single Context object, while non-shared context isolates each agent's state with separate Context instances.
The bojieli/ai-agent-book repository provides production-ready patterns for both strategies. Understanding when to use each approach—and how to combine them—is essential for building reliable multi-agent systems.
Shared Context: A Common Knowledge Base
Shared context preserves a single mutable state that every agent can read and write. This pattern works best when agents must collaborate on common facts, experiment metadata, or global coordination signals.
The Core Context Class
The foundation is the Context class in chapter9/gaia-experience/AWorld/aworld/core/context/base.py. This mutable store can be injected into any number of agents:
from aworld.core.context.base import Context
from aworld.core.agent.base import Agent
# One mutable Context that both agents will see
shared_ctx = Context()
agent_a = Agent(name="A", context=shared_ctx)
agent_b = Agent(name="B", context=shared_ctx)
# Both agents read/write the same keys
shared_ctx["global_fact"] = "The sky is blue"
print(agent_a.context["global_fact"]) # → The sky is blue
print(agent_b.context["global_fact"]) # → The sky is blue
The shared Bucket Pattern
For static site generation and document processing, the repository uses a designated __shared__ bucket. In scripts/split_search_index.py, pages under this bucket are merged into every edition's search index:
SHARED = "__shared__"
shared = buckets.pop(SHARED, [])
size = write(index_path.with_name(f"search_index.{slug}.json"),
shared + entries) # shared pages added to each edition
This merging happens at lines 143-151, where shared + entries ensures global documentation appears in all agent views.
Shared Memory for Large Data
When context data grows large, Python's multiprocessing.shared_memory prevents excessive copying. The multi_proc_mem.py implementation shows the pattern:
import multiprocessing.shared_memory as shm
# Create a shared block named "shared_ctx" (size in bytes)
buffer = shm.SharedMemory(name="shared_ctx", create=True, size=1024)
# Write a JSON string into the buffer
json_bytes = b'{"counter":0}'
buffer.buf[:len(json_bytes)] = json_bytes
# In another process, attach to the same block
other = shm.SharedMemory(name="shared_ctx")
payload = bytes(other.buf[:len(json_bytes)]).decode()
print(payload) # {"counter":0}
The buffer is created, read, and deleted in lines 26-41 of multi_proc_mem.py.
Non-Shared Context: Agent Isolation
Non-shared context gives each agent its own Context instance. This prevents reasoning leakage and simplifies debugging for independent sub-tasks.
Creating Private Contexts
Simply instantiate fresh Context() objects without shared data:
agent_a = Agent(name="A", context=Context())
agent_b = Agent(name="B", context=Context())
# Each agent gets its own isolated state
agent_a.context["secret"] = "Alice's note"
print(agent_b.context.get("secret")) # → None
No merging occurs. Each agent's writes remain invisible to others.
Verification in Test Suite
The repository validates isolation through tests/test_split_search_index.py. Lines 98-108 confirm that only intended shared pages appear in each edition's index, proving private contexts stay untouched:
- Tests verify bucket separation before merging
- Assertions check that
__shared__content appears everywhere - Per-edition entries remain scoped to their specific agents
When to Use Each Pattern
| Use Case | Recommended Approach | Reasoning |
|---|---|---|
| Global experiment documentation | Shared context | Single source of truth, deterministic reproduction |
| Privacy-sensitive user sessions | Non-shared context | Data encapsulation prevents cross-contamination |
| Collaborative reasoning on facts | Shared context | Coordinated behavior through common state |
| Independent sub-task execution | Non-shared context | Self-contained state simplifies debugging |
| Large immutable datasets | Shared memory | Avoids memory duplication across processes |
Combining Both Patterns
The repository's architecture supports hybrid designs. A typical setup:
- Shared layer: Global configuration, common knowledge graph, approval workflows
- Private layer: Per-agent working memory, intermediate reasoning scratchpads
- Synchronization points: Explicit merges when agents need to share findings
The scripts/split_search_index.py pattern demonstrates this explicitly—shared + entries combines global and local context at well-defined boundaries.
Summary
- Shared context uses a single
Contextobject,__shared__buckets, andmultiprocessing.shared_memoryfor collaborative agent behavior - Non-shared context instantiates isolated
Context()objects per agent to guarantee encapsulation - The
bojieli/ai-agent-bookrepository implements both inchapter9/gaia-experience/AWorld/aworld/core/context/base.pyandscripts/split_search_index.py - Choose shared context for common knowledge and coordination; choose non-shared for isolation and debuggability
- Test isolation rigorously—
tests/test_split_search_index.pyprovides a validation template
Frequently Asked Questions
How does the Context class handle concurrent writes from multiple agents?
The Context class in base.py provides mutable state without built-in locking. For thread safety, the repository recommends read-only sections for shared data or explicit synchronization mechanisms. Race conditions are mitigated through deterministic merge ordering in the __shared__ bucket pattern.
Can agents switch between shared and non-shared context during execution?
Yes. Agents can be initialized with private contexts and later receive shared state through explicit assignment. The repository's context_manager.py provides tracing utilities that propagate context across asynchronous calls, enabling dynamic context sharing when coordination becomes necessary.
What are the memory implications of large shared datasets?
Large objects should use multiprocessing.shared_memory as shown in multi_proc_mem.py. Without this, each agent receives a copy of large context data, causing memory bloat. Shared memory blocks exist outside process boundaries and are accessed by reference rather than value.
How do I test that my context isolation works correctly?
Follow the pattern in tests/test_split_search_index.py: create buckets with both shared and private entries, run your split/merge logic, then assert that only expected shared content appears in each agent's view. Verify that private keys remain absent from other agents' contexts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →