Shared memory blocks
Share memory between agents for real-time coordination without explicit messaging.
Shared memory blocks let multiple agents access and update the same memory. When one agent updates the block, all others see the change immediately. This enables real-time coordination without explicit agent-to-agent messaging.
graph TD
subgraph Supervisor
S[Persona: I am a supervisor]
SS[Organization: Letta]
end
subgraph Worker
W1[Persona: I am a worker]
W1S[Organization: Letta]
end
SS -.->|shared block| W1S
Quick start
Section titled “Quick start”Create a block, then attach it to multiple agents using block_ids:
from letta_client import Lettaimport os
client = Letta(api_key=os.getenv("LETTA_API_KEY"))
# Create a shared blockshared_block = client.blocks.create( label="organization", description="Shared information between all agents.", value="Company policies and procedures...")
# Attach to multiple agentssupervisor = client.agents.create( model="anthropic/claude-haiku-4-5-20251001", memory_blocks=[{"label": "persona", "value": "I am a supervisor"}], block_ids=[shared_block.id])
worker = client.agents.create( model="anthropic/claude-haiku-4-5-20251001", memory_blocks=[{"label": "persona", "value": "I am a worker"}], block_ids=[shared_block.id] # Same block = shared memory)import Letta from "@letta-ai/letta-client";
const client = new Letta({ apiKey: process.env.LETTA_API_KEY });
// Create a shared blockconst sharedBlock = await client.blocks.create({ label: "organization", description: "Shared information between all agents.", value: "Company policies and procedures...",});
// Attach to multiple agentsconst supervisor = await client.agents.create({ model: "anthropic/claude-haiku-4-5-20251001", memoryBlocks: [{ label: "persona", value: "I am a supervisor" }], blockIds: [sharedBlock.id],});
const worker = await client.agents.create({ model: "anthropic/claude-haiku-4-5-20251001", memoryBlocks: [{ label: "persona", value: "I am a worker" }], blockIds: [sharedBlock.id], // Same block = shared memory});Managing blocks
Section titled “Managing blocks”Attach to existing agent
Section titled “Attach to existing agent”client.agents.blocks.attach( agent_id=agent.id, block_id=shared_block.id)await client.agents.blocks.attach(agent.id, { blockId: sharedBlock.id,});Detach from agent
Section titled “Detach from agent”client.agents.blocks.detach( agent_id=agent.id, block_id=shared_block.id)await client.agents.blocks.detach(agent.id, { blockId: sharedBlock.id,});List agents using a block
Section titled “List agents using a block”agents = client.blocks.agents.list(block_id=shared_block.id)for agent in agents: print(f"{agent.name} has access")const agents = await client.blocks.agents.list(sharedBlock.id);for (const agent of agents) { console.log(`${agent.name} has access`);}Update from external sources
Section titled “Update from external sources”Sync data into shared blocks from databases, webhooks, or scheduled jobs:
# Sync CRM data to a shared blockcrm_data = fetch_from_crm()client.blocks.update( block_id=shared_block.id, value=f"Customer list (updated {datetime.now()}):\n{crm_data}")// Sync CRM data to a shared blockconst crmData = await fetchFromCRM();await client.blocks.update(sharedBlock.id, { value: `Customer list (updated ${new Date().toISOString()}):\n${crmData}`,});Read-only blocks
Section titled “Read-only blocks”Protect blocks from agent modification by setting read_only=True:
policy_block = client.blocks.create( label="company_policies", value="Our company policies...", read_only=True)Agents can read the block but memory tools will refuse to modify it. Use this for reference data, policies, or any content that should stay constant.
When to use shared blocks
Section titled “When to use shared blocks”- Multiple agents need the same context (user info, domain knowledge)
- Handoff scenarios where context must persist between agents
- Global config/state that shouldn’t be duplicated
Common patterns
Section titled “Common patterns”Supervisor/Worker State
- Block:
task_queue - Attached to: Supervisor + all workers
- Pattern: Supervisor writes tasks, workers read and update status
Shared Knowledge Base
- Block:
domain_knowledge - Attached to: Multiple specialized agents
- Pattern: Any agent can append learnings, all benefit
User Profile (Multi-Agent)
- Block:
user_preferences - Attached to: All agents serving same user
- Pattern: Agents read for personalization, sleeptime agent curates
Coordination/Handoff
- Block:
handoff_context - Attached to: Agent A + Agent B
- Pattern: Agent A writes before handoff, Agent B reads on pickup
Global Config
- Block:
system_config(read-only) - Attached to: All agents in deployment
- Pattern: Updated externally via API, agents only read
Concurrency
Section titled “Concurrency”| Operation | Use when | Concurrent-safe? |
|---|---|---|
memory_insert | Appending new info | Yes (append-only) |
memory_replace | Targeted edits | Mostly (fails if target string changed) |
memory_rethink | Full rewrites | No (last-writer-wins) |
Troubleshooting
Section titled “Troubleshooting”Agent can’t see updates - Verify both agents have the same block_id attached. Check that updates completed (agent finished its turn). Ensure character limit wasn’t exceeded.
Block limit exceeded - Increase limit with client.blocks.update(block_id=id, limit=10000). Archive old content to a separate block. Have an agent periodically summarize.
Race conditions - Design blocks so each agent updates their own section. Use timestamps and agent IDs in content. Consider separate blocks for high-contention data.