feat: update documentation and add new tutorials for memory blocks and agent collaboration - Updated navigation paths in docs.yml to reflect new tutorial locations. - Added comprehensive guides on shared memory blocks and attaching/detaching memory blocks. - Enhanced existing documentation for memory blocks with examples and best practices. - Corrected API key references in prebuilt tools documentation. These changes aim to improve user understanding and facilitate multi-agent collaboration through shared memory systems.
838 lines
23 KiB
Plaintext
838 lines
23 KiB
Plaintext
---
|
|
title: Shared Memory Blocks Guide
|
|
subtitle: Complete guide to using shared memory for multi-agent coordination
|
|
slug: guides/agents/shared-memory-blocks
|
|
---
|
|
|
|
Shared memory blocks enable multiple agents to access and update the same memory, creating powerful multi-agent systems with seamless coordination.
|
|
|
|
## 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
|
|
|
|
<Note>
|
|
Shared memory blocks are different from agent-to-agent messaging (like `send_message_to_agent_async`). With shared memory, agents coordinate **asynchronously** through shared state rather than direct communication.
|
|
</Note>
|
|
|
|
## Core Concepts
|
|
|
|
### 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.
|
|
|
|
```python
|
|
from letta import Letta
|
|
|
|
client = Letta()
|
|
|
|
# Step 1: Create a memory block
|
|
shared_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 agents
|
|
agent1 = 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
|
|
|
|
| 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
|
|
|
|
Letta supports multiple access patterns for organizing shared memory:
|
|
|
|
1. **Hierarchical**: Tier 1 < Tier 2 < Tier 3 (access increases up the hierarchy)
|
|
2. **Team-Based**: All team members share the same blocks
|
|
3. **Overlapping**: Each agent has a unique combination of blocks
|
|
4. **Organizational**: Department → Cross-Department → Executive levels
|
|
|
|
## Architecture Patterns
|
|
|
|
### 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](/cookbooks/shared-memory-read-only)
|
|
|
|
### 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](/cookbooks/shared-memory-task-coordination)
|
|
|
|
### Pattern 3: Specialized Agents (Overlapping Access)
|
|
|
|
```
|
|
Coordinator → ALL blocks (user_profile, preferences, interaction_history, calendar, financial)
|
|
Email Agent → user_profile, preferences, interaction_history, calendar
|
|
Research Agent → user_profile, preferences, interaction_history
|
|
Calendar Agent → user_profile, preferences, calendar
|
|
Finance Agent → user_profile, preferences, financial
|
|
```
|
|
|
|
**Use Cases:**
|
|
- Personal AI assistant networks
|
|
- Specialized service agents
|
|
- Multi-domain customer support
|
|
|
|
**Example:** [Multi-Agent User Assistant Tutorial](/cookbooks/shared-memory-user-assistant)
|
|
|
|
### Pattern 4: Enterprise Hierarchy (Departments)
|
|
|
|
```
|
|
Company-Wide [R] → ALL agents (mission, policies)
|
|
Department Blocks [R/W] → Department members only
|
|
Cross-Dept Block [R/W] → All directors + CEO
|
|
Executive Dashboard [R/W] → CEO only
|
|
```
|
|
|
|
**Use Cases:**
|
|
- Enterprise organizations
|
|
- Multi-department companies
|
|
- Regulated industries with compliance requirements
|
|
|
|
**Example:** [Enterprise Multi-Team Tutorial](/cookbooks/shared-memory-enterprise)
|
|
|
|
## Best Practices
|
|
|
|
### 1. Use Read-Only Blocks for Critical Information
|
|
|
|
Protect policies, procedures, and reference data from accidental modification:
|
|
|
|
```python
|
|
company_policies = client.blocks.create(
|
|
label="company_policies",
|
|
value="Our company policies...",
|
|
# Read-only ensures consistency
|
|
)
|
|
```
|
|
|
|
<Warning>
|
|
Even though Letta doesn't currently enforce read-only at the API level, agents will respect read-only semantics and refuse to modify these blocks when instructed not to in their persona.
|
|
</Warning>
|
|
|
|
### 2. Implement the Principle of Least Privilege
|
|
|
|
Only give agents access to blocks they need:
|
|
|
|
```python
|
|
# ❌ Bad: Sales agent with access to HR data
|
|
sales_agent = client.agents.create(
|
|
block_ids=[sales_knowledge.id, hr_employee_data.id] # Too much access
|
|
)
|
|
|
|
# ✓ Good: Sales agent with only sales data
|
|
sales_agent = client.agents.create(
|
|
block_ids=[sales_knowledge.id] # Appropriate access
|
|
)
|
|
```
|
|
|
|
### 3. Use Clear Naming Conventions
|
|
|
|
Make block purposes obvious:
|
|
|
|
```python
|
|
# ✓ 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 unclear
|
|
```
|
|
|
|
### 4. Set Appropriate Character Limits
|
|
|
|
Balance between enough space and memory constraints:
|
|
|
|
```python
|
|
# Reference data: smaller
|
|
company_policies = client.blocks.create(
|
|
limit=5000 # Policies don't change often
|
|
)
|
|
|
|
# Active coordination: larger
|
|
task_queue = client.blocks.create(
|
|
limit=10000 # Tasks accumulate over time
|
|
)
|
|
|
|
# Detailed logs: largest
|
|
interaction_history = client.blocks.create(
|
|
limit=12000 # Many interactions to track
|
|
)
|
|
```
|
|
|
|
<Tip>
|
|
If a block frequently hits its character limit, consider archiving old content or splitting into multiple blocks (e.g., `current_tasks` vs `completed_tasks`).
|
|
</Tip>
|
|
|
|
### 5. Document Block Access in Agent Personas
|
|
|
|
Make agents aware of their access:
|
|
|
|
```python
|
|
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
|
|
|
|
Help with debugging and management:
|
|
|
|
```python
|
|
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
|
|
|
|
### 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 policies
|
|
support_tier2/ → Advanced troubleshooting + escalation procedures
|
|
support_tier3/ → Full system access + team metrics
|
|
```
|
|
|
|
**Benefits:**
|
|
- Consistent policy information across all tiers
|
|
- Sensitive escalation procedures protected
|
|
- Supervisors track team performance privately
|
|
|
|
### 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 tasks
|
|
completed_work (R/W) → All team members share findings
|
|
team_metrics (R/W) → Supervisor only tracks performance
|
|
```
|
|
|
|
**Benefits:**
|
|
- Real-time task claiming without conflicts
|
|
- Knowledge sharing through completed work
|
|
- Supervisor oversight without micromanagement
|
|
|
|
### 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 agents
|
|
Coordination: interaction_history → Coordinator, Email, Research
|
|
Domain-specific: calendar_data → Calendar, Email agents only
|
|
Restricted: financial_data → Finance agent only
|
|
```
|
|
|
|
**Benefits:**
|
|
- Seamless handoffs between specialists
|
|
- Consistent user experience
|
|
- Privacy protection for sensitive data
|
|
|
|
### 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/policies
|
|
Department (R/W) → Each dept has private knowledge
|
|
Cross-dept (R/W) → Directors coordinate projects
|
|
Executive (R/W) → CEO tracks company metrics
|
|
```
|
|
|
|
**Benefits:**
|
|
- Department autonomy and isolation
|
|
- Async cross-department coordination
|
|
- Executive oversight without bottlenecks
|
|
- Compliance with data privacy regulations
|
|
|
|
## API Reference
|
|
|
|
### Creating Shared Blocks
|
|
|
|
```python
|
|
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)
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
# Attach a block to an existing agent
|
|
client.agents.blocks.attach(
|
|
agent_id=agent.id,
|
|
block_id=block.id
|
|
)
|
|
|
|
# Detach a block from an agent
|
|
client.agents.blocks.detach(
|
|
agent_id=agent.id,
|
|
block_id=block.id
|
|
)
|
|
```
|
|
|
|
### Listing Blocks
|
|
|
|
Find blocks across your project with optional filtering:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
# List all blocks in project
|
|
all_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")
|
|
```
|
|
```typescript TypeScript
|
|
// List all blocks in project
|
|
const allBlocks = await client.blocks.list();
|
|
|
|
// Filter and search
|
|
const teamBlocks = await client.blocks.list({
|
|
label: "team_knowledge",
|
|
labelSearch: "sales"
|
|
});
|
|
```
|
|
</CodeGroup>
|
|
|
|
### Retrieving a Block
|
|
|
|
Get complete block information by ID:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
block = client.blocks.retrieve(block.id)
|
|
print(f"Block: {block.label}")
|
|
print(f"Value: {block.value}")
|
|
```
|
|
```typescript TypeScript
|
|
const block = await client.blocks.retrieve(block.id);
|
|
console.log(`Block: ${block.label}`);
|
|
console.log(`Value: ${block.value}`);
|
|
```
|
|
</CodeGroup>
|
|
|
|
### Modifying Blocks Directly
|
|
|
|
Update block content without going through an agent. Useful for external scripts syncing data to agents:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
# Update block content - completely replaces the value
|
|
client.blocks.modify(
|
|
block.id,
|
|
value="Updated team knowledge: New procedures..."
|
|
)
|
|
|
|
# Update multiple properties
|
|
client.blocks.modify(
|
|
block.id,
|
|
value="New content",
|
|
limit=8000,
|
|
description="Updated description"
|
|
)
|
|
|
|
# Make block read-only
|
|
client.blocks.modify(block.id, read_only=True)
|
|
```
|
|
```typescript TypeScript
|
|
// Update block content - completely replaces the value
|
|
await client.blocks.modify(block.id, {
|
|
value: "Updated team knowledge: New procedures..."
|
|
});
|
|
|
|
// Update multiple properties
|
|
await client.blocks.modify(block.id, {
|
|
value: "New content",
|
|
limit: 8000,
|
|
description: "Updated description"
|
|
});
|
|
|
|
// Make block read-only
|
|
await client.blocks.modify(block.id, { readOnly: true });
|
|
```
|
|
</CodeGroup>
|
|
|
|
<Warning>
|
|
**Setting `value` completely replaces the entire block content** - it is not an append operation. When you modify a shared block directly, all agents with access will see the changes immediately.
|
|
|
|
**Race condition risk**: If two processes (agents or external scripts) modify the same block concurrently, the last write wins and completely overwrites all earlier changes. To avoid data loss:
|
|
- Set blocks to **read-only** if you don't want agents or other processes to modify them
|
|
- Only allow direct modifications in controlled scenarios where overwriting is acceptable
|
|
- Ensure your application logic accounts for the fact that block updates are full replacements, not merges
|
|
</Warning>
|
|
|
|
### Deleting Blocks
|
|
|
|
Remove blocks when no longer needed. This detaches the block from all agents:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
client.blocks.delete(block_id=block.id)
|
|
```
|
|
```typescript TypeScript
|
|
await client.blocks.delete(block.id);
|
|
```
|
|
</CodeGroup>
|
|
|
|
### Agent-Scoped Operations
|
|
|
|
#### List an Agent's Blocks
|
|
|
|
See all memory blocks attached to a specific agent:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
# List all blocks for an agent
|
|
agent_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]}...")
|
|
```
|
|
```typescript TypeScript
|
|
// List all blocks for an agent
|
|
const agentBlocks = await client.agents.blocks.list(agent.id);
|
|
|
|
// With pagination
|
|
const 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)}...`);
|
|
}
|
|
```
|
|
</CodeGroup>
|
|
|
|
#### Retrieve Agent's Block by Label
|
|
|
|
Get a specific block from an agent using its label instead of ID:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
# Get agent's human block
|
|
human_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"
|
|
)
|
|
```
|
|
```typescript TypeScript
|
|
// Get agent's human block
|
|
const humanBlock = await client.agents.blocks.retrieve(
|
|
agent.id,
|
|
"human"
|
|
);
|
|
console.log(humanBlock.value);
|
|
|
|
// Get shared task queue from specific agent
|
|
const taskQueue = await client.agents.blocks.retrieve(
|
|
workerAgent.id,
|
|
"task_queue"
|
|
);
|
|
```
|
|
</CodeGroup>
|
|
|
|
#### Modify Agent's Block by Label
|
|
|
|
Update a specific agent's block without needing the block ID:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
# Update agent's knowledge about the human
|
|
client.agents.blocks.modify(
|
|
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.modify(
|
|
agent_id=worker.id,
|
|
block_label="task_queue",
|
|
value="Updated task queue with new items..."
|
|
)
|
|
```
|
|
```typescript TypeScript
|
|
// Update agent's knowledge about the human
|
|
await client.agents.blocks.modify(agent.id, "human", {
|
|
value: "Updated user information: Alice, prefers email over chat"
|
|
});
|
|
|
|
// Update shared block via specific agent
|
|
await client.agents.blocks.modify(worker.id, "task_queue", {
|
|
value: "Updated task queue with new items..."
|
|
});
|
|
```
|
|
</CodeGroup>
|
|
|
|
### Inspecting Block Usage
|
|
|
|
See which agents have a block attached:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
# List all agents that use this block
|
|
agents_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"
|
|
)
|
|
```
|
|
```typescript TypeScript
|
|
// List all agents that use this block
|
|
const 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 pagination
|
|
const agentsPage = await client.blocks.agents.list(block.id, {
|
|
limit: 10,
|
|
order: "asc"
|
|
});
|
|
```
|
|
</CodeGroup>
|
|
|
|
### Updating Blocks via Agents
|
|
|
|
Agents update blocks using memory tools during conversations:
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
# Agent updates shared block content
|
|
client.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
|
|
```
|
|
```typescript TypeScript
|
|
// Agent updates shared block content
|
|
await 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 access
|
|
```
|
|
</CodeGroup>
|
|
|
|
## Troubleshooting
|
|
|
|
### Problem: Agent Can't See Block Updates
|
|
|
|
**Symptoms:** Agent reads old content after another agent updated it.
|
|
|
|
**Solutions:**
|
|
1. Verify both agents have the same `block_id` attached
|
|
2. Check that updates are being committed (agent finished its turn)
|
|
3. Ensure character limit hasn't been exceeded (updates may fail silently)
|
|
|
|
```python
|
|
# Debug: Check which agents share the block
|
|
block_info = client.blocks.retrieve(block_id=block.id)
|
|
print(f"Agents with access: {block_info.agent_ids}")
|
|
```
|
|
|
|
### Problem: Block Character Limit Exceeded
|
|
|
|
**Symptoms:** Updates not applying, content truncated.
|
|
|
|
**Solutions:**
|
|
1. Increase block limit: `client.blocks.update(block_id=block.id, limit=10000)`
|
|
2. Archive old content: Move completed items to a separate block
|
|
3. Summarize content: Have an agent periodically summarize and condense
|
|
|
|
```python
|
|
# Check current usage
|
|
block = client.blocks.retrieve(block_id=block.id)
|
|
print(f"Characters: {len(block.value)} / {block.limit}")
|
|
```
|
|
|
|
### Problem: Privacy Violation
|
|
|
|
**Symptoms:** Agent accessing data it shouldn't see.
|
|
|
|
**Solutions:**
|
|
1. Review block attachments: `client.agents.retrieve(agent_id).block_ids`
|
|
2. Detach inappropriate blocks: `client.agents.blocks.detach()`
|
|
3. Update agent persona to clarify access boundaries
|
|
4. Consider splitting one block into multiple with different access
|
|
|
|
### Problem: Race Conditions on Concurrent Updates
|
|
|
|
**Symptoms:** Two agents try to claim the same task, conflicts occur.
|
|
|
|
**Solutions:**
|
|
1. Design blocks to minimize conflicts (separate sections for each agent)
|
|
2. Use timestamps and agent IDs in updates
|
|
3. Implement retry logic for failed updates
|
|
4. Consider optimistic concurrency control
|
|
|
|
```python
|
|
# 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
|
|
|
|
### Block Size and Agent Performance
|
|
|
|
- **Smaller blocks (<5K chars)**: Faster loading, more focused context
|
|
- **Larger blocks (>10K chars)**: More context but slower processing
|
|
- **Optimal**: Keep blocks focused on single purpose, split large blocks
|
|
|
|
### 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
|
|
|
|
- **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
|
|
|
|
### Data Privacy
|
|
|
|
Shared memory blocks enable compliance with data privacy regulations:
|
|
|
|
```python
|
|
# GDPR/HIPAA Example: Isolate sensitive data
|
|
hr_employee_data = client.blocks.create(
|
|
label="hr_employee_data",
|
|
description="CONFIDENTIAL - HR Department only. Contains PII."
|
|
)
|
|
|
|
# Only attach to authorized agents
|
|
hr_director = client.agents.create(
|
|
block_ids=[hr_employee_data.id] # Only HR has access
|
|
)
|
|
|
|
# Sales/Engineering agents do NOT get access
|
|
sales_agent = client.agents.create(
|
|
block_ids=[sales_knowledge.id] # No HR data access
|
|
)
|
|
```
|
|
|
|
### Audit Trail
|
|
|
|
Track block access for compliance:
|
|
|
|
```python
|
|
# Check block usage
|
|
block_info = client.blocks.retrieve(block_id=sensitive_block.id)
|
|
print(f"Accessed by: {block_info.agent_ids}")
|
|
|
|
# Log all agents with access
|
|
for agent_id in block_info.agent_ids:
|
|
agent = client.agents.retrieve(agent_id=agent_id)
|
|
print(f" {agent.name} - {agent.created_at}")
|
|
```
|
|
|
|
### Access Revocation
|
|
|
|
Remove access when no longer needed:
|
|
|
|
```python
|
|
# Employee leaves company - revoke agent access
|
|
client.agents.blocks.detach(
|
|
agent_id=former_employee_agent.id,
|
|
block_id=company_confidential.id
|
|
)
|
|
|
|
# Or delete the agent entirely
|
|
client.agents.delete(agent_id=former_employee_agent.id)
|
|
```
|
|
|
|
## Tutorials
|
|
|
|
Learn shared memory patterns through hands-on tutorials:
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Part 1: Read-Only Knowledge" icon="lock" href="/cookbooks/shared-memory-read-only">
|
|
Build a hierarchical support team with shared company policies
|
|
</Card>
|
|
|
|
<Card title="Part 2: Task Coordination" icon="list-check" href="/cookbooks/shared-memory-task-coordination">
|
|
Create a data analysis team with shared task queues
|
|
</Card>
|
|
|
|
<Card title="Part 3: User Assistant Network" icon="users" href="/cookbooks/shared-memory-user-assistant">
|
|
Build specialized agents with overlapping block access
|
|
</Card>
|
|
|
|
<Card title="Part 4: Enterprise System" icon="building" href="/cookbooks/shared-memory-enterprise">
|
|
Implement a complete enterprise with departments and hierarchies
|
|
</Card>
|
|
</CardGroup>
|
|
|
|
## Related Guides
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Memory Blocks Overview" icon="database" href="/guides/agents/memory-blocks">
|
|
Understanding memory blocks and core memory
|
|
</Card>
|
|
|
|
<Card title="Multi-Agent Systems" icon="diagram-project" href="/guides/agents/multi-agent">
|
|
Overview of multi-agent architectures in Letta
|
|
</Card>
|
|
|
|
<Card title="Agent-to-Agent Messaging" icon="comments" href="/cookbooks/multi-agent-async">
|
|
Alternative coordination pattern using async messaging
|
|
</Card>
|
|
|
|
<Card title="API Reference" icon="code" href="/api-reference/agents/core-memory">
|
|
Complete API documentation for blocks and memory
|
|
</Card>
|
|
</CardGroup>
|
|
|
|
## 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.
|