Shared memory blocks guide
Guide to sharing memory blocks between multiple agents for collaborative workflows.
Shared memory blocks enable multiple agents to access and update the same memory, creating powerful multi-agent systems with seamless coordination.
Overview
Section titled “Overview”Shared memory blocks allow you to attach the same memory block to multiple agents. When one agent updates the block, all other agents with access immediately see the changes. This enables:
- Real-time coordination without explicit agent-to-agent messaging
- Consistent information across teams and departments
- Hierarchical access control based on roles and responsibilities
- Privacy boundaries for sensitive information
- Knowledge sharing across specialized agents
Core Concepts
Section titled “Core Concepts”What is a Shared Memory Block?
Section titled “What is a Shared Memory Block?”A memory block becomes “shared” when you attach it to multiple agents using the same block_id. All agents with access see the same content in real-time.
from letta_client import Lettaimport os
client = Letta(api_key=os.getenv("LETTA_API_KEY"))
# Step 1: Create a memory blockshared_block = client.blocks.create( label="team_knowledge", description="Shared knowledge base for the team", value="Team policies and procedures...", limit=5000)
# Step 2: Attach to multiple agentsagent1 = client.agents.create( name="Agent_1", block_ids=[shared_block.id], # Attach shared block # ... other config)
agent2 = client.agents.create( name="Agent_2", block_ids=[shared_block.id], # Same block ID = shared memory # ... other config)
# Now agent1 and agent2 share the same memory block!Block Types
Section titled “Block Types”| Type | Description | Use Case |
|---|---|---|
| Read-Only | Agents can read but not modify | Company policies, reference data |
| Read/Write | Agents can read and update | Task queues, shared notes |
| Private | Single agent only | Personal work logs, private notes |
Access Patterns
Section titled “Access Patterns”Letta supports multiple access patterns for organizing shared memory:
- Hierarchical: Tier 1 < Tier 2 < Tier 3 (access increases up the hierarchy)
- Team-Based: All team members share the same blocks
- Overlapping: Each agent has a unique combination of blocks
- Organizational: Department → Cross-Department → Executive levels
Architecture Patterns
Section titled “Architecture Patterns”Pattern 1: Hierarchical Access (Support Tiers)
Section titled “Pattern 1: Hierarchical Access (Support Tiers)”Tier 1 Agents → company_policies [R]Tier 2 Agents → company_policies [R], escalation_procedures [R]Tier 3 Agents → company_policies [R], escalation_procedures [R], team_metrics [R/W]Use Cases:
- Customer support with tier levels
- Knowledge bases with sensitivity levels
- Organizations with clearance levels
Example: Read-Only Organizational Knowledge Tutorial
Pattern 2: Team Coordination (Shared Queues)
Section titled “Pattern 2: Team Coordination (Shared Queues)”All Team Members → task_queue [R/W], completed_work [R/W]Supervisor Only → team_metrics [R/W]Each Worker → private_work_log [R/W]Use Cases:
- Task coordination across workers
- Project management teams
- Shared deliverables tracking
Example: Task Coordination Tutorial
Pattern 3: Specialized Agents (Overlapping Access)
Section titled “Pattern 3: Specialized Agents (Overlapping Access)”Coordinator → ALL blocks (user_profile, preferences, interaction_history, calendar, financial)Email Agent → user_profile, preferences, interaction_history, calendarResearch Agent → user_profile, preferences, interaction_historyCalendar Agent → user_profile, preferences, calendarFinance Agent → user_profile, preferences, financialUse Cases:
- Personal AI assistant networks
- Specialized service agents
- Multi-domain customer support
Example: Multi-Agent User Assistant Tutorial
Pattern 4: Enterprise Hierarchy (Departments)
Section titled “Pattern 4: Enterprise Hierarchy (Departments)”Company-Wide [R] → ALL agents (mission, policies)Department Blocks [R/W] → Department members onlyCross-Dept Block [R/W] → All directors + CEOExecutive Dashboard [R/W] → CEO onlyUse Cases:
- Enterprise organizations
- Multi-department companies
- Regulated industries with compliance requirements
Example: Enterprise Multi-Team Tutorial
Best Practices
Section titled “Best Practices”1. Use Read-Only Blocks for Critical Information
Section titled “1. Use Read-Only Blocks for Critical Information”Protect policies, procedures, and reference data from accidental modification:
company_policies = client.blocks.create( label="company_policies", value="Our company policies...", # Read-only ensures consistency)2. Implement the Principle of Least Privilege
Section titled “2. Implement the Principle of Least Privilege”Only give agents access to blocks they need:
# ❌ Bad: Sales agent with access to HR datasales_agent = client.agents.create( block_ids=[sales_knowledge.id, hr_employee_data.id] # Too much access)
# ✓ Good: Sales agent with only sales datasales_agent = client.agents.create( block_ids=[sales_knowledge.id] # Appropriate access)3. Use Clear Naming Conventions
Section titled “3. Use Clear Naming Conventions”Make block purposes obvious:
# ✓ Good names"company_policies" # Clear scope and content"sales_team_knowledge" # Clear ownership"cross_dept_projects" # Clear purpose"ceo_executive_dashboard" # Clear access level
# ❌ Bad names"data" # Too generic"block1" # Not descriptive"temp" # Purpose unclear4. Set Appropriate Character Limits
Section titled “4. Set Appropriate Character Limits”Balance between enough space and memory constraints:
# Reference data: smallercompany_policies = client.blocks.create( limit=5000 # Policies don't change often)
# Active coordination: largertask_queue = client.blocks.create( limit=10000 # Tasks accumulate over time)
# Detailed logs: largestinteraction_history = client.blocks.create( limit=12000 # Many interactions to track)5. Document Block Access in Agent Personas
Section titled “5. Document Block Access in Agent Personas”Make agents aware of their access:
agent = client.agents.create( memory_blocks=[{ "label": "persona", "value": """I am a Sales Representative.
My access:- company_policies (read-only): Company-wide policies- sales_knowledge (read/write): Shared with sales team- my_leads (private): My personal lead tracking
I do NOT have access to:- engineering_specs (Engineering team only)- hr_employee_data (HR team only)""" }])6. Use Descriptive Block Descriptions
Section titled “6. Use Descriptive Block Descriptions”Help with debugging and management:
block = client.blocks.create( label="sales_knowledge", description="Sales team knowledge base: pricing, playbooks, targets. Read/write access for Sales Director, Rep 1, Rep 2.", # Good description includes: content, access, and purpose)Common Use Cases
Section titled “Common Use Cases”Use Case 1: Customer Support with Tiers
Section titled “Use Case 1: Customer Support with Tiers”Problem: Support agents at different levels need different information.
Solution: Hierarchical blocks with increasing access
support_tier1/ → Basic policiessupport_tier2/ → Advanced troubleshooting + escalation proceduressupport_tier3/ → Full system access + team metricsBenefits:
- Consistent policy information across all tiers
- Sensitive escalation procedures protected
- Supervisors track team performance privately
Use Case 2: Project Management Team
Section titled “Use Case 2: Project Management Team”Problem: Multiple workers need to coordinate on tasks.
Solution: Shared task queue + completion log
task_queue (R/W) → All team members claim and update taskscompleted_work (R/W) → All team members share findingsteam_metrics (R/W) → Supervisor only tracks performanceBenefits:
- Real-time task claiming without conflicts
- Knowledge sharing through completed work
- Supervisor oversight without micromanagement
Use Case 3: Personal AI Assistant Network
Section titled “Use Case 3: Personal AI Assistant Network”Problem: User needs specialized agents that understand full context.
Solution: Overlapping block access with privacy boundaries
Universal: user_profile, user_preferences → All agentsCoordination: interaction_history → Coordinator, Email, ResearchDomain-specific: calendar_data → Calendar, Email agents onlyRestricted: financial_data → Finance agent onlyBenefits:
- Seamless handoffs between specialists
- Consistent user experience
- Privacy protection for sensitive data
Use Case 4: Enterprise Organization
Section titled “Use Case 4: Enterprise Organization”Problem: Large company with departments needs coordination.
Solution: Multi-tier hierarchy with isolation
Company-wide (R) → All employees see mission/policiesDepartment (R/W) → Each dept has private knowledgeCross-dept (R/W) → Directors coordinate projectsExecutive (R/W) → CEO tracks company metricsBenefits:
- Department autonomy and isolation
- Async cross-department coordination
- Executive oversight without bottlenecks
- Compliance with data privacy regulations
API Reference
Section titled “API Reference”Creating Shared Blocks
Section titled “Creating Shared Blocks”block = client.blocks.create( label="block_name", # Required: identifier description="What this is", # Recommended: for management value="Initial content", # Required: starting content limit=5000 # Optional: character limit)Attaching to Agents (at Creation)
Section titled “Attaching to Agents (at Creation)”agent = client.agents.create( name="Agent_Name", block_ids=[block1.id, block2.id], # Attach existing blocks memory_blocks=[ # Create new private blocks {"label": "persona", "value": "..."} ], # ... other config)Attaching to Existing Agents
Section titled “Attaching to Existing Agents”# Attach a block to an existing agentclient.agents.blocks.attach( agent_id=agent.id, block_id=block.id)
# Detach a block from an agentclient.agents.blocks.detach( agent_id=agent.id, block_id=block.id)Listing Blocks
Section titled “Listing Blocks”Find blocks across your project with optional filtering:
# List all blocks in projectall_blocks = client.blocks.list()
# Filter by label
team_blocks = client.blocks.list(label="team_knowledge")
# Search by label text
search_results = client.blocks.list(label_search="sales")// List all blocks in projectconst allBlocks = await client.blocks.list();
// Filter and searchconst teamBlocks = await client.blocks.list({ label: "team_knowledge", labelSearch: "sales",});Retrieving a Block
Section titled “Retrieving a Block”Get complete block information by ID:
{block.label}") print(f"Value: {block.value}") ``` ```typescript TypeScriptconst block = await client.blocks.retrieve(block.id); console.log(`Block: ${block.label}`); console.log(`Value: ${block.value}`); ```
</TabItem></Tabs>
### Modifying Blocks Directly
Update block content without going through an agent. Useful for external scripts syncing data to agents:
<Tabs><TabItem label="Python">
```python Python# Update block content - completely replaces the valueclient.blocks.update( block.id, value="Updated team knowledge: New procedures...")
# Update multiple properties
client.blocks.update(block.id,value="New content",limit=8000,description="Updated description")
# Make block read-only
client.blocks.update(block.id, read_only=True)// Update block content - completely replaces the valueawait client.blocks.update(block.id, { value: "Updated team knowledge: New procedures...",});
// Update multiple propertiesawait client.blocks.update(block.id, { value: "New content", limit: 8000, description: "Updated description",});
// Make block read-onlyawait client.blocks.update(block.id, { read_only: true });Deleting Blocks
Section titled “Deleting Blocks”Remove blocks when no longer needed. This detaches the block from all agents:
python Python client.blocks.delete(block_id=block.id) typescript TypeScript await client.blocks.delete(block.id);
Agent-Scoped Operations
Section titled “Agent-Scoped Operations”List an Agent’s Blocks
Section titled “List an Agent’s Blocks”See all memory blocks attached to a specific agent:
# List all blocks for an agentagent_blocks = client.agents.blocks.list(agent_id=agent.id)
# With pagination
agent_blocks = client.agents.blocks.list(agent_id=agent.id,limit=10,order="asc")
for block in agent_blocks:print(f"{block.label}: {block.value[:50]}...")// List all blocks for an agentconst agentBlocks = await client.agents.blocks.list(agent.id);
// With paginationconst agentBlocksPaginated = await client.agents.blocks.list(agent.id, { limit: 10, order: "asc",});
for (const block of agentBlocks) { console.log(`${block.label}: ${block.value.slice(0, 50)}...`);}Retrieve Agent’s Block by Label
Section titled “Retrieve Agent’s Block by Label”Get a specific block from an agent using its label instead of ID:
# Get agent's human blockhuman_block = client.agents.blocks.retrieve( agent_id=agent.id, block_label="human")print(human_block.value)
# Get shared task queue from specific agent
task_queue = client.agents.blocks.retrieve(agent_id=worker_agent.id,block_label="task_queue")// Get agent's human blockconst humanBlock = await client.agents.blocks.retrieve(agent.id, "human");console.log(humanBlock.value);
// Get shared task queue from specific agentconst taskQueue = await client.agents.blocks.retrieve( workerAgent.id, "task_queue",);Modify Agent’s Block by Label
Section titled “Modify Agent’s Block by Label”Update a specific agent’s block without needing the block ID:
# Update agent's knowledge about the humanclient.agents.blocks.update( agent_id=agent.id, block_label="human", value="Updated user information: Alice, prefers email over chat")
# Update shared block via specific agent
client.agents.blocks.update(agent_id=worker.id,block_label="task_queue",value="Updated task queue with new items...")// Update agent's knowledge about the humanawait client.agents.blocks.update(agent.id, "human", { value: "Updated user information: Alice, prefers email over chat",});
// Update shared block via specific agentawait client.agents.blocks.update(worker.id, "task_queue", { value: "Updated task queue with new items...",});Inspecting Block Usage
Section titled “Inspecting Block Usage”See which agents have a block attached:
# List all agents that use this blockagents_with_block = client.blocks.agents.list(block_id=block.id)print(f"Used by {len(agents_with_block)} agents:")for agent in agents_with_block: print(f" - {agent.name}")
# With pagination
agents_page = client.blocks.agents.list(block_id=block.id,limit=10,order="asc")// List all agents that use this blockconst agentsWithBlock = await client.blocks.agents.list(block.id);console.log(`Used by ${agentsWithBlock.length} agents:`);for (const agent of agentsWithBlock) { console.log(` - ${agent.name}`);}
// With paginationconst agentsPage = await client.blocks.agents.list(block.id, { limit: 10, order: "asc",});Updating Blocks via Agents
Section titled “Updating Blocks via Agents”Agents update blocks using memory tools during conversations:
# Agent updates shared block contentclient.agents.messages.create( agent_id=agent.id, messages=[{ "role": "user", "content": "Update the task queue to mark task-001 as complete" }])
# Agent uses core_memory_replace or core_memory_append tools
# Changes are immediately visible to all agents with access// Agent updates shared block contentawait client.agents.messages.create(agent.id, { messages: [ { role: "user", content: "Update the task queue to mark task-001 as complete", }, ],});
// Agent uses core_memory_replace or core_memory_append tools// Changes are immediately visible to all agents with accessTroubleshooting
Section titled “Troubleshooting”Problem: Agent Can’t See Block Updates
Section titled “Problem: Agent Can’t See Block Updates”Symptoms: Agent reads old content after another agent updated it.
Solutions:
- Verify both agents have the same
block_idattached - Check that updates are being committed (agent finished its turn)
- Ensure character limit hasn’t been exceeded (updates may fail silently)
# Debug: Check which agents share the blockblock_info = client.blocks.retrieve(block_id=block.id)print(f"Agents with access: {block_info.agent_ids}")Problem: Block Character Limit Exceeded
Section titled “Problem: Block Character Limit Exceeded”Symptoms: Updates not applying, content truncated.
Solutions:
- Increase block limit:
client.blocks.update(block_id=block.id, limit=10000) - Archive old content: Move completed items to a separate block
- Summarize content: Have an agent periodically summarize and condense
# Check current usageblock = client.blocks.retrieve(block_id=block.id)print(f"Characters: {len(block.value)} / {block.limit}")Problem: Privacy Violation
Section titled “Problem: Privacy Violation”Symptoms: Agent accessing data it shouldn’t see.
Solutions:
- Review block attachments:
client.agents.retrieve(agent_id).block_ids - Detach inappropriate blocks:
client.agents.blocks.detach() - Update agent persona to clarify access boundaries
- Consider splitting one block into multiple with different access
Problem: Race Conditions on Concurrent Updates
Section titled “Problem: Race Conditions on Concurrent Updates”Symptoms: Two agents try to claim the same task, conflicts occur.
Solutions:
- Design blocks to minimize conflicts (separate sections for each agent)
- Use timestamps and agent IDs in updates
- Implement retry logic for failed updates
- Consider optimistic concurrency control
# Good: Each agent updates their own section"""TASK-001: Status: In Progress Claimed by: Worker_1 Timestamp: 2024-10-08 14:30
TASK-002: Status: In Progress Claimed by: Worker_2 Timestamp: 2024-10-08 14:31"""Performance Considerations
Section titled “Performance Considerations”Block Size and Agent Performance
Section titled “Block Size and Agent Performance”- Smaller blocks (<5Klt;5K chars): Faster loading, more focused context
- Larger blocks (>10Kgt;10K chars): More context but slower processing
- Optimal: Keep blocks focused on single purpose, split large blocks
Number of Blocks per Agent
Section titled “Number of Blocks per Agent”- Recommended: 3-7 blocks per agent
- Each block adds: Context in agent’s working memory
- Too many blocks: May dilute agent focus
- Too few blocks: May limit coordination capabilities
Update Frequency
Section titled “Update Frequency”- High-frequency updates (many agents, frequent changes): Consider separate blocks to reduce contention
- Low-frequency updates (policies, references): Larger consolidated blocks are fine
Security and Compliance
Section titled “Security and Compliance”Data Privacy
Section titled “Data Privacy”Shared memory blocks enable compliance with data privacy regulations:
# GDPR/HIPAA Example: Isolate sensitive datahr_employee_data = client.blocks.create( label="hr_employee_data", description="CONFIDENTIAL - HR Department only. Contains PII.")
# Only attach to authorized agentshr_director = client.agents.create( block_ids=[hr_employee_data.id] # Only HR has access)
# Sales/Engineering agents do NOT get accesssales_agent = client.agents.create( block_ids=[sales_knowledge.id] # No HR data access)Audit Trail
Section titled “Audit Trail”Track block access for compliance:
# Check block usageblock_info = client.blocks.retrieve(block_id=sensitive_block.id)print(f"Accessed by: {block_info.agent_ids}")
# Log all agents with accessfor agent_id in block_info.agent_ids: agent = client.agents.retrieve(agent_id=agent_id) print(f" {agent.name} - {agent.created_at}")Access Revocation
Section titled “Access Revocation”Remove access when no longer needed:
# Employee leaves company - revoke agent accessclient.agents.blocks.detach( agent_id=former_employee_agent.id, block_id=company_confidential.id)
# Or delete the agent entirelyclient.agents.delete(agent_id=former_employee_agent.id)Tutorials
Section titled “Tutorials”Learn shared memory patterns through hands-on tutorials:
Related Guides
Section titled “Related Guides”Key Takeaways
Section titled “Key Takeaways”✓ Shared memory blocks enable seamless multi-agent coordination without explicit messaging ✓ Access patterns range from simple (all agents) to complex (hierarchical organizations) ✓ Privacy boundaries protect sensitive data while enabling collaboration ✓ Real-time sync ensures all agents see updates immediately ✓ Scales from 2 agents to enterprise systems with 10+ agents ✓ Complements agent-to-agent messaging for complete multi-agent systems
Shared memory blocks are a powerful primitive for building sophisticated multi-agent systems. Start with simple patterns (Tutorial 1) and progress to complex architectures (Tutorial 4) as your needs grow.