How to Implement Multi-Agent Shared Context and Team Memory in Semantica

Instantiate AgnoSharedContext to create a single source of truth, bind each agent with bind_agent(role) to get role-scoped memory stores, and use built-in toolkits like AgnoDecisionKit to let agents read and write team-wide knowledge.

Multi-agent systems fail when agents work in isolation. Semantica solves this through a team-wide memory layer that lets Agno agents share context while maintaining private namespaces. This article walks through the architecture and implementation based on the actual source code in semantica-agi/semantica.

Architecture of Semantica's Shared Context System

The multi-agent shared context system centers on three components: a unified storage backend, role-scoped access controls, and thread-safe concurrent operations.

Single Source of Truth with AgnoSharedContext

In integrations/agno/shared_context.py, the AgnoSharedContext class creates one AgentContext and ContextGraph instance for the entire team. All agents read from and write to the same vector store and knowledge graph.

from semantica.vector_store import VectorStore
from semantica.context import ContextGraph
from integrations.agno import AgnoSharedContext

vector_store = VectorStore(backend="faiss")
knowledge_graph = ContextGraph(advanced_analytics=True)

shared = AgnoSharedContext(
    vector_store=vector_store,
    knowledge_graph=knowledge_graph,
    decision_tracking=True,
    graph_expansion=True,
)

This design eliminates data silos. Every memory, decision, and insight persists in shared infrastructure.

Role-Scoped Memory Views

The bind_agent(role) method returns an _AgentScopedStore that subclasses AgnoContextStore. This store forwards all operations to the shared context but tags every entry with the agent's role using session_id = f"{team_session}::{role}".

This architecture delivers two benefits:

  • Isolation: Each agent has a private namespace for its own memories
  • Transparency: All agents can read the global memory pool through read_memories

The scoped store merges its private cache with the shared pool during reads, then applies optional filtering and sorting.

Thread-Safe Concurrent Operations

A re-entrant lock protects binding and decision-recording:

self._lock = threading.RLock()

This allows agents to run concurrently without race conditions when accessing shared memory.

Core Capabilities for Team Memory

Automatic Decision Tracking

When decision_tracking=True, every upsert_memory call automatically inserts a lightweight decision entry with category="memory:<role>". The global record_decision API also adds a role tag (category:agent_role).

This creates an audit trail connecting every memory to its originating agent.

Graph-Expanded Context Retrieval

With graph_expansion=True, the base AgnoContextStore.read_memories() can enrich results with one-hop neighbors from the knowledge graph. Agents receive context-aware recall that surfaces related concepts even when not explicitly queried.

Team-Level Query APIs

AgnoSharedContext exposes three public methods for orchestration:

  • find_precedents(scenario, limit) — Searches for similar past decisions
  • get_shared_insights() — Returns analytics across all team contributions
  • knowledge_graph — Direct access to the full decision graph

Complete Implementation Example

Step 1: Create Shared Infrastructure

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

vector_store = VectorStore(backend="faiss")
knowledge_graph = ContextGraph(advanced_analytics=True)

shared = AgnoSharedContext(
    vector_store=vector_store,
    knowledge_graph=knowledge_graph,
    decision_tracking=True,
    graph_expansion=True,
)

Step 2: Bind Agents to Shared Context

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

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

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")

Step 3: Store and Retrieve Shared Knowledge


# Researcher contributes knowledge

researcher.memory.upsert_memory(
    {"memory": "Quantum computing reduces cryptographic safety.", "user_id": "u1"}
)

# Analyst accesses combined knowledge pool

all_memories = analyst.memory.read_memories()
print([m["memory"] for m in all_memories])

Step 4: Record Structured Decisions

researcher.memory.record_decision(
    category="strategy",
    scenario="Should we invest in post-quantum crypto?",
    reasoning="Market analysis + technical risk assessment",
    outcome="invest",
    confidence=0.93,
    entities=["Quantum computing", "cryptography"]
)

Step 5: Inject Shared Context into Prompts


# General team insights

prompt_prefix = shared.get_shared_insights()

# Specific scenario search

context_snippet = shared.find_precedents(
    scenario="Secure communications after quantum breakthrough",
    limit=3,
)

Source File Reference

File Purpose
integrations/agno/shared_context.py AgnoSharedContext — team coordinator and binding logic
integrations/agno/context_store.py AgnoContextStore and _AgentScopedStore — storage implementation
integrations/agno/decision_kit.py AgnoDecisionKit — decision intelligence tools
integrations/agno/kg_toolkit.py AgnoKGToolkit — knowledge graph search tools
semantica/context.py Core AgentContext and ContextGraph classes
semantica/vector_store.py Vector storage backends (FAISS, Qdrant, etc.)

Summary

  • AgnoSharedContext creates a single vector store and knowledge graph for the entire team
  • bind_agent(role) returns scoped stores that isolate private memories while allowing global read-through
  • Thread-safe design with RLock enables concurrent agent execution
  • Automatic decision tracking links every memory to its source agent for auditability
  • Graph expansion enriches retrievals with related concepts from the knowledge graph
  • Built-in toolkits (AgnoDecisionKit, AgnoKGToolkit) expose team memory as Agno tools

Frequently Asked Questions

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

Role-scoped stores use composite session IDs (f"{team_session}::{role}") to tag every entry. While all agents read from the shared pool, writes are tagged with the originating role. The _AgentScopedStore class in integrations/agno/shared_context.py handles this transparently without requiring changes to agent code.

Can I use a different vector store backend with AgnoSharedContext?

Yes. The VectorStore class in semantica/vector_store.py abstracts the backend. Pass any supported backend—"faiss", "qdrant", or others—to VectorStore() before injecting it into AgnoSharedContext. The rest of the multi-agent shared context system remains unchanged.

What happens when two agents call read_memories() simultaneously?

The re-entrant lock (self._lock = threading.RLock()) in AgnoSharedContext protects critical sections. Multiple agents can read concurrently since reads don't conflict. The lock ensures atomic binding operations and prevents interleaving during decision recording, maintaining consistency of the team memory state.

How do I query decisions made by a specific agent role?

Use find_precedents() with filters, or access the knowledge graph directly through shared.knowledge_graph. Decision entries are tagged with category:agent_role, allowing targeted queries. The AgnoDecisionKit also provides search_decisions() which accepts role filters as parameters.

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 →