---
title: Shared memory | Letta Docs
description: Use the Letta API to share memory blocks between agents
---

Shared [memory blocks](/guides/core-concepts/memory/memory-blocks/index.md) 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
```

Shared memory coordinates agents through **shared state** - great for broadcasting information or maintaining consistent context.

## Quickstart

Create a block, then attach it to multiple agents using `block_ids`:

- [Python](#tab-panel-141)
- [TypeScript](#tab-panel-142)

```
from letta_client import Letta
import os


client = Letta(api_key=os.getenv("LETTA_API_KEY"))


# Create a shared block
shared_block = client.blocks.create(
    label="organization",
    description="Shared information between all agents.",
    value="Company policies and procedures..."
)


# Attach to multiple agents
supervisor = 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 block
const sharedBlock = await client.blocks.create({
  label: "organization",
  description: "Shared information between all agents.",
  value: "Company policies and procedures...",
});


// Attach to multiple agents
const 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

### Attach to existing agent

- [Python](#tab-panel-143)
- [TypeScript](#tab-panel-144)

```
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

- [Python](#tab-panel-145)
- [TypeScript](#tab-panel-146)

```
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

- [Python](#tab-panel-147)
- [TypeScript](#tab-panel-148)

```
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

Sync data into shared blocks from databases, webhooks, or scheduled jobs:

- [Python](#tab-panel-149)
- [TypeScript](#tab-panel-150)

```
# Sync CRM data to a shared block
crm_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 block
const crmData = await fetchFromCRM();
await client.blocks.update(sharedBlock.id, {
  value: `Customer list (updated ${new Date().toISOString()}):\n${crmData}`,
});
```

`blocks.update()` **replaces** the entire block content - it does not append. All agents with access see changes immediately.

## 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.

Read-only applies to the entire block, not per-agent. You cannot make a block read-only for some agents but writable for others.

## 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

**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](/guides/agents/architectures/sleeptime/index.md) 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

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

Designate one agent (or [sleeptime](/guides/agents/architectures/sleeptime/index.md)) as the “owner” for heavy edits. Other agents append via `memory_insert`.

**Anti-pattern**: Multiple agents doing `memory_rethink` on the same block simultaneously leads to lost updates.

## 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.
