Multi-Agent Memory

Share memory context across agents in multi-agent workflows

Multi-Agent Memory gives all agents in a workflow access to shared memory, so knowledge discovered by one agent is available to others.

python
from praisonaiagents import Agent, Task, PraisonAIAgents, MultiAgentMemoryConfig

researcher = Agent(name="Researcher", instructions="Research topics and share findings.")
writer = Agent(name="Writer", instructions="Write based on shared research.")

tasks = [
    Task(description="Research climate change impacts on agriculture", agent=researcher),
    Task(description="Write a policy brief based on the research", agent=writer),
]

workflow = PraisonAIAgents(
    agents=[researcher, writer],
    tasks=tasks,
    memory=MultiAgentMemoryConfig(user_id="project_climate", config={"provider": "rag"}),
)
workflow.start()

The user runs a multi-agent workflow; all agents read and write shared memory under one user id.

Diagram

Shared Memory

🤖 Agent 1\n(Researcher)

🧠 Shared\nMemory

🤖 Agent 2\n(Analyst)

🤖 Agent 3\n(Writer)

Quick Start

  1. Simple Usage
    python
    from praisonaiagents import Agent, Task, PraisonAIAgents, MultiAgentMemoryConfig
    
    agent1 = Agent(name="Gatherer", instructions="Gather and remember information.")
    agent2 = Agent(name="Synthesizer", instructions="Synthesize remembered information.")
    
    tasks = [
        Task(description="Gather key facts about solar energy", agent=agent1),
        Task(description="Create a summary from gathered facts", agent=agent2),
    ]
    
    workflow = PraisonAIAgents(
        agents=[agent1, agent2],
        tasks=tasks,
        memory=MultiAgentMemoryConfig(user_id="solar_project"),
    )
    workflow.start()
  2. With Custom Embedder
    python
    from praisonaiagents import Agent, Task, PraisonAIAgents, MultiAgentMemoryConfig
    
    agents = [
        Agent(name="Expert", instructions="Provide domain expertise."),
        Agent(name="Summarizer", instructions="Summarize expert findings."),
    ]
    
    tasks = [
        Task(description="Analyze cybersecurity vulnerabilities in cloud systems", agent=agents[0]),
        Task(description="Create an executive summary for non-technical stakeholders", agent=agents[1]),
    ]
    
    workflow = PraisonAIAgents(
        agents=agents,
        tasks=tasks,
        memory=MultiAgentMemoryConfig(
            user_id="security_review",
            embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}},
            config={"provider": "rag"},
        ),
    )
    workflow.start()

Configuration Options

MultiAgentMemoryConfig SDK Reference

Full parameter reference for MultiAgentMemoryConfig

Precedence ladder:

python
# Level 1: Bool (enable with defaults)
team = PraisonAIAgents(memory=True)

# Level 2: MultiAgentMemoryConfig (full control)
team = PraisonAIAgents(memory=MultiAgentMemoryConfig(
    user_id="user-123",
    embedder={"provider": "openai"},
))
OptionTypeDefaultDescription
user_id`str \None`NoneScope memory to a specific user or project
embedder`Any \None`NoneEmbedder configuration (e.g., {"provider": "openai"})

How It Works

Diagram
MemoryAgent2Agent1WorkflowUserMemoryAgent2Agent1WorkflowUserStart workflowExecute taskStore findingsTask 1 completeExecute taskRetrieve Agent1’s findingsShared contextTask 2 complete (with context)Combined output
PhaseWhat happens
1. StoreFirst agent saves discoveries to shared memory
2. RetrieveSubsequent agents access all stored context
3. BuildLater agents build on earlier agents’ work

Configuration Options

Card

Full list of options, types, and defaults — MultiAgentMemoryConfig

OptionTypeDefaultDescription
user_id`str \None`NoneShared user/project identifier for scoped memory
embedder`Any \None`NoneEmbedder configuration for semantic memory
config`dict \None`NoneMemory provider configuration

Common Patterns

Pattern 1 — Project-scoped research memory

python
from praisonaiagents import Agent, Task, PraisonAIAgents, MultiAgentMemoryConfig

agents = [
    Agent(name="Researcher", instructions="Research and document findings."),
    Agent(name="Analyst", instructions="Analyze documented findings."),
    Agent(name="Reporter", instructions="Create final reports."),
]

tasks = [
    Task(description="Research market trends in renewable energy", agent=agents[0]),
    Task(description="Identify key investment opportunities from research", agent=agents[1]),
    Task(description="Write an investment recommendation report", agent=agents[2]),
]

result = PraisonAIAgents(
    agents=agents,
    tasks=tasks,
    memory=MultiAgentMemoryConfig(user_id="renewable_energy_2025"),
).start()
print(result)

Best Practices

Always set user_id for project isolation

Set user_id to a unique project or session identifier to prevent memory from bleeding between unrelated workflows. Without user_id, all workflows share the same memory namespace.

Use semantic memory for related topics

Configure the embedder when agents need to find semantically related information (not just exact matches). OpenAI’s text-embedding-3-small is a good default — fast and cost-effective.

Order tasks to build context

Tasks run in order by default. Place information-gathering tasks first and synthesis/writing tasks later so downstream agents have full context from upstream agents.


Isolating collections per agent

When several agents share one rag_db_path, give each a distinct collection_name so they coexist and can be reset independently.

python
from praisonaiagents import Agent

researcher = Agent(
    name="Researcher",
    memory={
        "provider": "rag",
        "rag_db_path": "./chroma_db",
        "collection_name": "researcher_ltm",
    },
)

writer = Agent(
    name="Writer",
    memory={
        "provider": "rag",
        "rag_db_path": "./chroma_db",
        "collection_name": "writer_ltm",
    },
)

# researcher.memory.reset_long_term() no longer wipes writer's memory.

collection_name defaults to "memory_store". See Memory Configuration.


Per-agent isolation across backends

Two agents in one process no longer share one on-disk store by default. As of PraisonAI #4203, Agent(memory="sqlite" | "chroma" | {"provider": "mongodb"} | {"provider": "mem0"} | {"learn": True}) inherits the same per-agent isolation that FileMemory already had — each agent gets a per-instance agent-<uuid> id and its own default store when no explicit user_id is given.

python
from praisonaiagents import Agent

support = Agent(name="Support", memory="sqlite", instructions="Handle customer A's private ticket.")
sales   = Agent(name="Sales",   memory="sqlite", instructions="Draft outreach for customer B.")
# Distinct default files per agent — private data no longer crosses agents:
#   short_term_agent-<uuidA>.db / long_term_agent-<uuidA>.db  (Support)
#   short_term_agent-<uuidB>.db / long_term_agent-<uuidB>.db  (Sales)

Each backend derives per-user defaults from the scoping user_id:

DefaultBare store (no user_id)Scoped store (user_id="team-x")
Short-term DBshort_term.dbshort_term_team-x.db
Long-term DBlong_term.dblong_term_team-x.db
Chroma pathchroma_db/chroma_db_team-x/
Collectionmemory_storememory_store_team-x
Diagram

🤖 Agent A
memory=’sqlite’

💾 short_term_agent-abc123.db

🤖 Agent B
memory=’sqlite’

💾 short_term_agent-def456.db

🤖 Agent C
memory=’sqlite’
user_id=’team-x’

💾 short_term_team-x.db

Explicit values always win — user_id, short_db, long_db, rag_db_path, or collection_name in the caller’s dict bypass the auto-defaults. A bare store with no user_id keeps the original shared defaults, so existing single-store setups are unchanged.

Two agents can share memory by pointing both at the same db_path instead of isolating via short_db / long_db — the inverse of the isolation above. This is the opt-in shared-memory escape hatch, not the default; per-agent isolation still applies unless you set it. See the writer/reader walkthrough in Advanced Memory.

When to pass an explicit user_id:

Diagram

No — keep them separate

Yes — share by project/tenant

Do two agents need
to share one store?

✅ rely on auto-isolation
(no user_id needed)

✅ pass user_id=’project-x’
to both agents

Concurrency and shared user_id

When multiple agents share the same user_id and back FileMemory (or the file-backed learn store) on the same paths, concurrent writes are now merge-safe: each mutation re-reads the on-disk state under the instance lock before appending, so two agents recording facts against the same user_id no longer overwrite each other’s entries. This applies to add_short_term, add_long_term, add_entity, auto-promotion to long-term memory, and learn/stores.py BaseStore.add.

This is a bug fix, not a new API — no configuration change is required. If you previously worked around lost writes by serializing agent runs or by giving agents distinct user_ids, you can remove that workaround where sharing was actually the goal.

For hierarchical runs that share memory, see how the hierarchical process surfaces the final worker task’s output.


Related