How Semantica's AgnoSharedContext Manages Multi-Agent Shared Context: Architecture and Implementation

The AgnoSharedContext class coordinates multi-agent teams by instantiating a single shared ContextGraph and VectorStore, then providing thread-safe, role-scoped memory views to each agent through the bind_agent() method.

Managing shared knowledge across multiple AI agents requires careful coordination to prevent race conditions while preserving individual agent perspectives. In the semantica-agi/semantica repository, the Agno integration solves this through a centralized shared context architecture. This article examines how AgnoSharedContext enables concurrent agents to read from and write to a unified knowledge base while maintaining isolated, role-specific memory scopes.

Core Architecture of AgnoSharedContext

Located in [integrations/agno/shared_context.py](https://github.com/semantica-agi/semantica/blob/main/integrations/agno/shared_context.py), the AgnoSharedContext class serves as the central coordinator for Agno agent teams. It eliminates data silos by ensuring all agents operate on the same underlying knowledge structures rather than maintaining separate memory instances.

Single Shared Knowledge Graph

During initialization, AgnoSharedContext creates exactly one ContextGraph instance (or accepts a user-provided one) and stores it as self._knowledge_graph. This graph is wrapped in a shared AgentContext object (self._context) that every bound agent references.

By funneling all memory operations through this single AgentContext, Semantica guarantees that agent discoveries, decisions, and retrieved facts persist in a common state accessible to the entire team. The vector store operates similarly—one VectorStore instance backs all agents, enabling semantic search across the collective memory pool.

Thread-Safe Coordination with RLock

Concurrent multi-agent systems risk race conditions when multiple agents simultaneously update shared state. AgnoSharedContext protects all mutations with a re-entrant lock initialized as self._lock = threading.RLock().

This locking mechanism serializes critical operations including agent binding, memory upserts, and decision recording. Agents can safely execute in parallel without corrupting the shared knowledge graph or losing decision history, as the lock ensures atomic updates to the underlying ContextGraph and VectorStore.

Role-Scoped Memory Views

While agents share a single knowledge base, they require isolated perspectives to prevent contradictory actions and maintain clear audit trails. Semantica implements this through scoped memory stores that tag entries by agent role.

The bind_agent() Method

The bind_agent(role) method creates a role-specific interface to the shared context. When called, it returns an instance of _AgentScopedStore (defined in [integrations/agno/context_store.py](https://github.com/semantica-agi/semantica/blob/main/integrations/agno/context_store.py)), which inherits from AgnoContextStore.

Each scoped store receives the parent AgentContext (self._context = shared._context) but modifies its session_id by prefixing it with the agent's role using the format f"{shared.session_id}::{role}". This tagging mechanism ensures that while all agents write to the same physical storage, every memory entry carries metadata identifying its originator.

_AgentScopedStore Implementation

The _AgentScopedStore class delegates all memory operations (upsert_memory, read_memories, delete_memory) to the shared context while automatically appending role labels. When the researcher agent upserts a memory, the store tags it with the researcher role; when the analyst queries memories, it can retrieve the full shared pool including entries from other agents.

This architecture prevents agents from overwriting each other's work while still allowing cross-agent context retrieval. The scoped store maintains a reference to the parent shared context (self._shared), enabling agents to access self._shared._shared_memories for global insights when needed.

Decision Tracking and Graph Analytics

Beyond raw memory storage, AgnoSharedContext provides sophisticated decision tracking and graph traversal capabilities that enhance multi-agent coordination.

Automatic Decision Recording

When initialized with decision_tracking=True, the shared context automatically logs every memory operation as a structured decision. Each call to upsert_memory triggers self._context.record_decision with a category label formatted as f"memory:{self._role}", creating an immutable audit trail of which agent contributed what knowledge and when.

The shared context also exposes a global record_decision method that agents can call directly to log high-level strategic choices, optionally specifying an explicit agent_role parameter for team-wide decision tracking.

Graph Expansion for Context Retrieval

Setting graph_expansion=True enables one-hop neighbor retrieval in the knowledge graph. When an agent calls read_memories, the underlying AgnoContextStore enriches vector search results with related entities from the ContextGraph, providing context-aware retrieval that surfaces connections the agent might not have explicitly queried.

This feature allows agents to benefit from the team's collective reasoning—even if one agent stores a fact and another asks a related question later, the graph expansion surfaces the connection automatically.

Practical Implementation Example

The following example demonstrates initializing a shared context for a research team and binding role-scoped stores:

from semantica.vector_store import VectorStore
from semantica.context import ContextGraph
from integrations.agno import AgnoSharedContext, AgnoKGToolkit, AgnoDecisionKit

# Initialize shared infrastructure

shared = AgnoSharedContext(
    vector_store=VectorStore(backend="faiss"),
    knowledge_graph=ContextGraph(advanced_analytics=True),
    decision_tracking=True,
    graph_expansion=True,
)

# Create role-scoped memory interfaces

researcher_mem = shared.bind_agent("researcher")
analyst_mem = shared.bind_agent("analyst")

# Configure agents with shared context

from agno.agent import Agent
from agno.team import Team

researcher = Agent(
    name="Researcher",
    memory=researcher_mem,
    tools=[AgnoKGToolkit(context=shared)],
)

analyst = Agent(
    name="Analyst",
    memory=analyst_mem,
    tools=[AgnoDecisionKit(context=shared)],
)

team = Team(agents=[researcher, analyst], mode="coordinate")

Upserting memories automatically records decisions with role attribution:

researcher_mem.upsert_memory({"memory": "Quantum computing breakthroughs in 2024"})

# Stored with category="memory:researcher" in shared graph

Retrieving shared insights across all agents:

insights = shared.get_shared_insights()
print(insights)  # Analytics over full decision graph

Reading combined memories from the shared pool:

all_memories = analyst_mem.read_memories(limit=10)
for m in all_memories:
    print(m.memory)  # Includes entries from both researcher and analyst

Summary

  • AgnoSharedContext acts as a central coordinator in integrations/agno/shared_context.py, maintaining one ContextGraph and VectorStore for the entire agent team.
  • Thread safety is enforced through threading.RLock(), allowing concurrent agent operations without race conditions.
  • Role isolation is achieved via bind_agent(), which returns _AgentScopedStore instances that tag memories with agent roles while writing to shared storage.
  • Decision tracking automatically logs memory operations and explicit decisions with role labels when decision_tracking=True.
  • Graph expansion enriches retrievals with one-hop neighbors from the shared knowledge graph for context-aware responses.
  • Analytics methods like get_shared_insights() and find_precedents() expose the full decision graph for debugging and higher-level reasoning.

Frequently Asked Questions

How does AgnoSharedContext prevent agents from overwriting each other's memories?

AgnoSharedContext uses the _AgentScopedStore class to tag every memory entry with the agent's role via the session_id prefix format f"{shared.session_id}::{role}". While all agents write to the same physical VectorStore and ContextGraph, the role metadata preserves attribution and prevents logical overwrites. The underlying storage appends rather than replaces entries, maintaining a complete history of each agent's contributions to the shared knowledge base.

Can multiple agents safely write to the shared context simultaneously?

Yes. The AgnoSharedContext class initializes self._lock = threading.RLock() in its constructor, protecting all mutation operations including bind_agent(), upsert_memory(), and record_decision(). This re-entrant lock ensures that even when agents execute concurrently in separate threads, updates to the shared ContextGraph and VectorStore occur atomically without data corruption or lost writes.

What is the difference between AgnoSharedContext and AgnoContextStore?

AgnoSharedContext (in shared_context.py) is the high-level coordinator that owns the shared AgentContext, ContextGraph, and VectorStore. AgnoContextStore (in context_store.py) implements the Agno MemoryDb protocol for individual agent memory operations. AgnoSharedContext creates scoped instances of _AgentScopedStore (a subclass of AgnoContextStore) via bind_agent(), allowing multiple agents to share infrastructure while maintaining distinct memory views.

How does graph expansion improve multi-agent collaboration?

When graph_expansion=True, the read_memories method in AgnoContextStore retrieves not only vector-similar memories but also one-hop neighbors from the shared ContextGraph. This means if the researcher agent stores a fact about "quantum computing" and the analyst later queries "qubits," the graph expansion surfaces the connection even if the analyst's query doesn't vector-match the researcher's exact wording. This feature enables implicit knowledge sharing where agents benefit from each other's contributions without explicit cross-referencing.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →