docs: Improve examples page (#5442)

* Fix VoiceAgent to use run_manager instead of job_manager

VoiceAgent.__init__() was incorrectly using job_manager parameter
when ToolExecutionManager expects run_manager. This was causing
the error: "VoiceAgent.__init__() got an unexpected keyword
argument 'run_manager'".

Changes:
- Update VoiceAgent to accept and use run_manager instead of job_manager
- Update VoiceSleeptimeAgent to accept run_manager parameter
- Update imports to use RunManager instead of JobManager
- Pass run_manager to ToolExecutionManager in VoiceAgent._execute_tool

* docs: Add new examples to documentation

- Introduced "Your First Agent" example to guide users in creating a Letta agent and understanding its memory capabilities.
- Added "Attaching and Detaching Memory Blocks" example to demonstrate dynamic memory management for agents.
- Updated navigation in docs.yml to include links to the new examples.

These additions enhance the learning resources available for users working with Letta agents.
This commit is contained in:
Cameron Pfiffer
2025-10-14 16:47:56 -07:00
committed by Caren Thomas
parent bcfc94846d
commit 4a86bf6e4c
6 changed files with 954 additions and 11 deletions

View File

@@ -605,6 +605,10 @@ navigation:
contents:
- page: Overview
path: pages/cookbooks_simple.mdx
- page: Your First Agent
path: pages/examples/hello_world.mdx
- page: Attaching and Detaching Memory Blocks
path: pages/examples/attaching_detaching_blocks.mdx
- section: Multi-Agent
contents:
- page: Async Multi-Agent

View File

@@ -0,0 +1,513 @@
---
title: "Attaching and Detaching Memory Blocks"
subtitle: Dynamically control agent memory with attachable blocks
slug: examples/attaching-detaching-blocks
---
## Overview
Memory blocks are structured sections of an agent's context window that persist across all interactions. They're always visible to the agent while they are attached. This makes them perfect for storing information that agents need constant access to, like organizational policies, user preferences, or working memory.
One of the most powerful features of memory blocks is that they can be created independently and attached to or detached from agents at any time.
This allows you to:
- **Dynamically control** what information an agent has access to
- **Share memory** across multiple agents by attaching the same block to different agents
- **Temporarily grant access** to sensitive information, then revoke it when no longer needed
- **Switch contexts** by swapping out blocks as an agent moves between different tasks
By the end of this guide, you'll understand how to create standalone memory blocks, attach them to agents, detach them to remove access, and re-attach them when needed.
<Note>
For a comprehensive overview of memory blocks and their capabilities, see the [memory blocks guide](/guides/agents/memory-blocks).
</Note>
<Note>
**This example uses Letta Cloud.** Generate an API key at [app.letta.com/api-keys](https://app.letta.com/api-keys) and set it as `LETTA_API_KEY` in your environment. Self-hosted servers only need an API key if authentication is enabled. You can learn more about self-hosting [here](/guides/selfhosting).
</Note>
## What You'll Learn
- Creating standalone memory blocks
- Attaching blocks to agents
- Testing agent access to attached blocks
- Detaching blocks to revoke access
- Re-attaching blocks to restore access
## Prerequisites
You will need to install `letta-client` to interface with a Letta server:
<CodeGroup>
```bash TypeScript
npm install @letta-ai/letta-client
```
```bash Python
pip install letta-client
```
</CodeGroup>
## Steps
### Step 1: Initialize Client and Create Agent
<CodeGroup>
```typescript TypeScript
import { LettaClient } from '@letta-ai/letta-client';
// Initialize the Letta client using LETTA_API_KEY environment variable
const client = new LettaClient({ token: process.env.LETTA_API_KEY });
// If self-hosting, specify the base URL:
// const client = new LettaClient({ baseUrl: "http://localhost:8283" });
// Create agent
// API Reference: https://docs.letta.com/api-reference/agents/create
const agent = await client.agents.create({
name: "hello_world_assistant",
model: "openai/gpt-4o-mini",
// embedding: "openai/text-embedding-3-small", // Only set this if self-hosting
});
console.log(`Created agent: ${agent.id}\n`);
```
```python Python
from letta_client import Letta
import os
# Initialize the Letta client using LETTA_API_KEY environment variable
client = Letta(token=os.getenv("LETTA_API_KEY"))
# If self-hosting, specify the base URL:
# client = Letta(base_url="http://localhost:8283")
# Create agent
# API Reference: https://docs.letta.com/api-reference/agents/create
agent = client.agents.create(
name="hello_world_assistant",
model="openai/gpt-4o-mini",
# embedding="openai/text-embedding-3-small", # Only set this if self-hosting
)
print(f"Created agent: {agent.id}\n")
```
</CodeGroup>
<Accordion title="Expected Output">
```
Created agent: agent-a1b2c3d4-e5f6-7890-abcd-ef1234567890
```
</Accordion>
### Step 2: Create a Standalone Memory Block
Memory blocks can be created independently of any agent. This allows you to share the same block across multiple agents or attach/detach blocks as needed.
In this example, we'll create a standalone memory block storing information about Letta. We'll include a code that you can use to get the agent to respond to indicate that it has access to information in the block.
When the block is attached, writing "The code is TimberTheDog1234!" will cause the agent to respond with "Access granted". If the block is not attached, the agent will not have access to any content in the block and will likely be confused by the code.
<CodeGroup>
```typescript TypeScript
// Create memory block storing information about Letta
// API Reference: https://docs.letta.com/api-reference/blocks/create
const block = await client.blocks.create({
label: "organization",
value: `Organization: Letta
Website: https://www.letta.com
Description: Letta is a platform for building and running stateful agents.
Code: TimberTheDog1234!
When users provide a code, you should check if it matches the code you have
available. If it matches, you should respond with "Access granted".`
});
console.log(`Created block: ${block.id}\n`);
```
```python Python
# Create memory block storing information about Letta
# API Reference: https://docs.letta.com/api-reference/blocks/create
block = client.blocks.create(
label="organization",
value="""Organization: Letta
Website: https://www.letta.com
Description: Letta is a platform for building and running stateful agents.
Code: TimberTheDog1234!
When users provide a code, you should check if it matches the code you have
available. If it matches, you should respond with "Access granted".""",
)
print(f"Created block: {block.id}\n")
```
</CodeGroup>
<Accordion title="Expected Output">
```
Created block: block-a1b2c3d4-e5f6-7890-abcd-ef1234567890
```
</Accordion>
### Step 3: Attach Block to Agent
Now let's attach the block to our agent. Attached blocks are injected into the agent's context window and are available to the agent to use in its responses.
<CodeGroup>
```typescript TypeScript
// Attach memory block to agent
// API Reference: https://docs.letta.com/api-reference/agents/blocks/attach
await client.agents.blocks.attach(agent.id, { blockId: block.id });
console.log(`Attached block ${block.id} to agent ${agent.id}\n`);
```
```python Python
# Attach memory block to agent
# API Reference: https://docs.letta.com/api-reference/agents/blocks/attach
agent = client.agents.blocks.attach(
agent_id=agent.id,
block_id=block.id,
)
print(f"Attached block {block.id} to agent {agent.id}\n")
```
</CodeGroup>
### Step 4: Test Agent Access to Block
The agent can now see what's in the block. Let's ask it about Letta to verify that it can see the general information in the block -- the description, website, and organization name.
<CodeGroup>
```typescript TypeScript
// Send a message to test the agent's knowledge
// API Reference: https://docs.letta.com/api-reference/agents/messages/create
const response = await client.agents.messages.create(agent.id, {
messages: [{ role: "user", content: "What is Letta?" }]
});
for (const msg of response.messages) {
if (msg.messageType === "assistant_message") {
console.log(`Agent response: ${msg.content}\n`);
}
}
```
```python Python
# Send a message to test the agent's knowledge
# API Reference: https://docs.letta.com/api-reference/agents/messages/create
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "What is Letta?"}],
)
for msg in response.messages:
if msg.message_type == "assistant_message":
print(f"Agent response: {msg.content}\n")
```
</CodeGroup>
The agent will respond with general information about Letta:
> **Agent response**: Letta is a platform designed for building and running stateful
> agents. You can find more information about it on their website:
> https://www.letta.com
### Step 5: Detach Block from Agent
Blocks can be detached from an agent, removing them from the agent's context window. Detached blocks are not deleted and can be re-attached to an agent later.
<CodeGroup>
```typescript TypeScript
// Detach the block from the agent
// API Reference: https://docs.letta.com/api-reference/agents/blocks/detach
await client.agents.blocks.detach(agent.id, block.id);
console.log(`Detached block ${block.id} from agent ${agent.id}\n`);
```
```python Python
# Detach the block from the agent
# API Reference: https://docs.letta.com/api-reference/agents/blocks/detach
agent = client.agents.blocks.detach(
agent_id=agent.id,
block_id=block.id,
)
print(f"Detached block {block.id} from agent {agent.id}\n")
```
</CodeGroup>
### Step 6: Verify Block is Detached
Let's test the code that was in the block. The agent should no longer have access to it.
<CodeGroup>
```typescript TypeScript
// Test that the agent no longer has access to the code
const response2 = await client.agents.messages.create(agent.id, {
messages: [{ role: "user", content: "The code is TimberTheDog1234!" }]
});
for (const msg of response2.messages) {
if (msg.messageType === "assistant_message") {
console.log(`Agent response: ${msg.content}\n`);
}
}
```
```python Python
# Test that the agent no longer has access to the code
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "The code is TimberTheDog1234!"}],
)
for msg in response.messages:
if msg.message_type == "assistant_message":
print(f"Agent response: {msg.content}\n")
```
</CodeGroup>
<Accordion title="Expected Output">
```
Agent response: It seems like you've provided a code or password. If this is
sensitive information, please ensure you only share it with trusted parties and
in secure environments. Let me know how I can assist you further!
```
</Accordion>
<Note>
The agent doesn't recognize the code because the block containing that information has been detached.
</Note>
### Step 7: Re-attach Block and Test Again
Let's re-attach the block to restore the agent's access to the information.
<CodeGroup>
```typescript TypeScript
// Re-attach the block to the agent
await client.agents.blocks.attach(agent.id, { blockId: block.id });
console.log(`Re-attached block ${block.id} to agent ${agent.id}\n`);
// Test the code again
const response3 = await client.agents.messages.create(agent.id, {
messages: [{ role: "user", content: "The code is TimberTheDog1234!" }]
});
for (const msg of response3.messages) {
if (msg.messageType === "assistant_message") {
console.log(`Agent response: ${msg.content}\n`);
}
}
```
```python Python
# Re-attach the block to the agent
agent = client.agents.blocks.attach(
agent_id=agent.id,
block_id=block.id,
)
print(f"Re-attached block {block.id} to agent {agent.id}\n")
# Test the code again
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "The code is TimberTheDog1234!"}],
)
for msg in response.messages:
if msg.message_type == "assistant_message":
print(f"Agent response: {msg.content}\n")
```
</CodeGroup>
<Accordion title="Expected Output">
```
Agent response: Access granted. How can I assist you further?
```
</Accordion>
<Note>
The agent now recognizes the code because we've re-attached the block containing that information.
</Note>
## Complete Example
Here's the full code in one place that you can run:
<CodeGroup>
```typescript TypeScript
import { LettaClient } from '@letta-ai/letta-client';
// Initialize client
const client = new LettaClient({ token: process.env.LETTA_API_KEY });
// Create agent
const agent = await client.agents.create({
name: "hello_world_assistant",
model: "openai/gpt-4o-mini",
});
console.log(`Created agent: ${agent.id}\n`);
// Create standalone memory block
const block = await client.blocks.create({
label: "organization",
value: `Organization: Letta
Website: https://www.letta.com
Description: Letta is a platform for building and running stateful agents.
Code: TimberTheDog1234!
When users provide a code, you should check if it matches the code you have
available. If it matches, you should respond with "Access granted".`
});
console.log(`Created block: ${block.id}\n`);
// Attach block to agent
await client.agents.blocks.attach(agent.id, { blockId: block.id });
console.log(`Attached block to agent\n`);
// Test agent with block attached
let response = await client.agents.messages.create(agent.id, {
messages: [{ role: "user", content: "What is Letta?" }]
});
console.log(`Agent response: ${response.messages[0].content}\n`);
// Detach block
await client.agents.blocks.detach(agent.id, block.id);
console.log(`Detached block from agent\n`);
// Test agent without block
response = await client.agents.messages.create(agent.id, {
messages: [{ role: "user", content: "The code is TimberTheDog1234!" }]
});
console.log(`Agent response: ${response.messages[0].content}\n`);
// Re-attach block
await client.agents.blocks.attach(agent.id, { blockId: block.id });
console.log(`Re-attached block to agent\n`);
// Test agent with block re-attached
response = await client.agents.messages.create(agent.id, {
messages: [{ role: "user", content: "The code is TimberTheDog1234!" }]
});
console.log(`Agent response: ${response.messages[0].content}\n`);
```
```python Python
from letta_client import Letta
import os
# Initialize client
client = Letta(token=os.getenv("LETTA_API_KEY"))
# Create agent
agent = client.agents.create(
name="hello_world_assistant",
model="openai/gpt-4o-mini",
)
print(f"Created agent: {agent.id}\n")
# Create standalone memory block
block = client.blocks.create(
label="organization",
value="""Organization: Letta
Website: https://www.letta.com
Description: Letta is a platform for building and running stateful agents.
Code: TimberTheDog1234!
When users provide a code, you should check if it matches the code you have
available. If it matches, you should respond with "Access granted".""",
)
print(f"Created block: {block.id}\n")
# Attach block to agent
agent = client.agents.blocks.attach(
agent_id=agent.id,
block_id=block.id,
)
print(f"Attached block to agent\n")
# Test agent with block attached
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "What is Letta?"}],
)
print(f"Agent response: {response.messages[0].content}\n")
# Detach block
agent = client.agents.blocks.detach(
agent_id=agent.id,
block_id=block.id,
)
print(f"Detached block from agent\n")
# Test agent without block
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "The code is TimberTheDog1234!"}],
)
print(f"Agent response: {response.messages[0].content}\n")
# Re-attach block
agent = client.agents.blocks.attach(
agent_id=agent.id,
block_id=block.id,
)
print(f"Re-attached block to agent\n")
# Test agent with block re-attached
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "The code is TimberTheDog1234!"}],
)
print(f"Agent response: {response.messages[0].content}\n")
```
</CodeGroup>
## Key Concepts
<CardGroup cols={2}>
<Card title="Standalone Blocks" icon="cube">
Memory blocks can be created independently and shared across multiple agents
</Card>
<Card title="Dynamic Access Control" icon="key">
Attach and detach blocks to control what information an agent can access
</Card>
<Card title="Block Persistence" icon="database">
Detached blocks are not deleted and can be re-attached at any time
</Card>
<Card title="Shared Memory" icon="share-nodes">
The same block can be attached to multiple agents, enabling shared knowledge
</Card>
</CardGroup>
## Use Cases
<AccordionGroup>
<Accordion title="Temporary Access to Sensitive Information">
Attach a block with credentials or sensitive data only when needed, then detach it to prevent unauthorized access.
</Accordion>
<Accordion title="Shared Knowledge Across Agents">
Create a single block with organizational knowledge and attach it to multiple agents to ensure consistency.
</Accordion>
<Accordion title="Context Switching">
Detach blocks related to one task and attach blocks for another, allowing an agent to switch contexts efficiently.
</Accordion>
<Accordion title="Role-Based Access">
Give different agents access to different blocks based on their roles or permissions.
</Accordion>
</AccordionGroup>
## Next Steps
<Card title="Memory Blocks Guide" icon="database" href="/guides/agents/memory-blocks">
Learn more about memory blocks, including how to update them and manage their lifecycle
</Card>

View File

@@ -0,0 +1,426 @@
---
title: "Your First Letta Agent"
subtitle: Create an agent, send messages, and understand basic memory
slug: examples/hello-world
---
This example walks you through creating your first Letta agent from scratch. Unlike traditional chatbots that forget everything between conversations, Letta agents are **stateful** - they maintain persistent memory and can learn about you over time.
By the end of this guide, you'll understand how to create an agent, send it messages, and see how it automatically updates its memory based on your interactions.
<Note>
**This example uses Letta Cloud.** Generate an API key at [app.letta.com/api-keys](https://app.letta.com/api-keys) and set it as `LETTA_API_KEY` in your environment. Self-hosted servers only need an API key if authentication is enabled. You can learn more about self-hosting [here](/guides/selfhosting).
</Note>
## What You'll Learn
- Initializing the Letta client
- Creating an agent with [memory blocks](/guides/agents/memory-blocks)
- Sending messages and receiving responses
- How agents update their own memory
- Inspecting memory tool calls and block contents
## Prerequisites
You will need to install `letta-client` to interface with a Letta server:
<CodeGroup>
```bash TypeScript
npm install @letta-ai/letta-client
```
```bash Python
pip install letta-client
```
</CodeGroup>
## Steps
### Step 1: Initialize Client
A __client__ is a connection to a Letta server. It's used to create and interact with agents, as well as any of Letta's other features.
<CodeGroup>
```typescript TypeScript
import { LettaClient } from '@letta-ai/letta-client';
// Initialize the Letta client using LETTA_API_KEY environment variable
const client = new LettaClient({ token: process.env.LETTA_API_KEY });
// If self-hosting, specify the base URL:
// const client = new LettaClient({ baseUrl: "http://localhost:8283" });
```
```python Python
from letta_client import Letta
import os
# Initialize the Letta client using LETTA_API_KEY environment variable
client = Letta(token=os.getenv("LETTA_API_KEY"))
# If self-hosting, specify the base URL:
# client = Letta(base_url="http://localhost:8283")
```
</CodeGroup>
### Step 2: Create Agent
Now that we have a client, let's create an agent with memory blocks that define what the agent knows about itself and you. Memory blocks can be used for any purpose, but we're building a simple chatbot that stores information about its personality (`persona`) and you (`human`).
<CodeGroup>
```typescript TypeScript
// Create your first agent
// API Reference: https://docs.letta.com/api-reference/agents/create
const agent = await client.agents.create({
name: "hello_world_assistant",
// Memory blocks define what the agent knows about itself and you.
// Agents can modify these blocks during conversations using memory
// tools like memory_replace, memory_insert, memory_rethink, and memory.
memoryBlocks: [
{
label: "persona",
value: "I am a friendly AI assistant here to help you learn about Letta."
},
{
label: "human",
value: "Name: User\nFirst interaction: Learning about Letta"
}
],
// Model configuration
model: "openai/gpt-4o-mini",
// embedding: "openai/text-embedding-3-small", // Only set this if self-hosting
});
console.log(`Created agent: ${agent.id}`);
```
```python Python
# Create your first agent
# API Reference: https://docs.letta.com/api-reference/agents/create
agent = client.agents.create(
name="hello_world_assistant",
# Memory blocks define what the agent knows about itself and you
memory_blocks=[
{
"label": "persona",
"value": "I am a friendly AI assistant here to help you learn about Letta."
},
{
"label": "human",
"value": "Name: User\nFirst interaction: Learning about Letta"
}
],
# Model configuration
model="openai/gpt-4o-mini",
# embedding="openai/text-embedding-3-small", # Only set this if self-hosting
)
print(f"Created agent: {agent.id}")
```
</CodeGroup>
<Accordion title="Expected Output">
```
Created agent: agent-a1b2c3d4-e5f6-7890-abcd-ef1234567890
```
</Accordion>
<Note>
**Memory blocks** are the foundation of Letta agents. The `persona` block defines the agent's identity and behavior, while the `human` block stores information about the user. Learn more in the [Memory Blocks guide](/guides/agents/memory-blocks).
</Note>
### Step 3: Send Your First Message
Now let's send a message to the agent to see what it can do.
<CodeGroup>
```typescript TypeScript
// Send a message to your agent
// API Reference: https://docs.letta.com/api-reference/agents/messages/create
const response = await client.agents.messages.create(agent.id, {
messages: [{
role: "user",
content: "Hello! What's your purpose?"
}]
});
// Extract and print the assistant's response
for (const message of response.messages) {
if (message.messageType === "assistant_message") {
console.log(`Assistant: ${message.content}`);
}
}
```
```python Python
# Send a message to your agent
# API Reference: https://docs.letta.com/api-reference/agents/messages/create
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{
"role": "user",
"content": "Hello! What's your purpose?"
}]
)
# Extract and print the assistant's response
for message in response.messages:
if message.message_type == "assistant_message":
print(f"Assistant: {message.content}")
```
</CodeGroup>
<Accordion title="Expected Output">
```
Assistant: Hello! I'm here to help you learn about Letta and answer any questions
you might have. Letta is a framework for building stateful AI agents with long-term
memory. I can explain concepts, provide examples, and guide you through using the
platform. What would you like to know?
```
</Accordion>
### Step 4: Provide Information for the Agent to Remember
Now let's give the agent some information about yourself. If prompted correctly, the agent can add this information to a relevant memory block using one of its default memory tools. Unless tools are modified during creation, new agents usually have `memory_insert` and `memory_replace` tools.
<CodeGroup>
```typescript TypeScript
// Send information about yourself
const response2 = await client.agents.messages.create(agent.id, {
messages: [{
role: "user",
content: "My name is Cameron. Please store this information in your memory."
}]
});
// Print out tool calls and the assistant's response
for (const msg of response2.messages) {
if (msg.messageType === "assistant_message") {
console.log(`Assistant: ${msg.content}\n`);
}
if (msg.messageType === "tool_call_message") {
console.log(`Tool call: ${msg.toolCall.name}(${JSON.stringify(msg.toolCall.arguments)})`);
}
}
```
```python Python
# Send information about yourself
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "My name is Cameron. Please store this information in your memory."}]
)
# Print out tool calls and the assistant's response
for msg in response.messages:
if msg.message_type == "assistant_message":
print(f"Assistant: {msg.content}\n")
if msg.message_type == "tool_call_message":
print(f"Tool call: {msg.tool_call.name}({msg.tool_call.arguments})")
```
</CodeGroup>
<Accordion title="Expected Output">
```
Tool call: memory_replace({"block_label": "human", "old_content": "Name: User", "new_content": "Name: Cameron"})
Assistant: Got it! I've updated my memory with your name, Cameron. How can I assist you today?
```
</Accordion>
<Note>
Notice the `tool_call_message` showing the agent using the `memory_replace` tool to update the `human` block. This is how Letta agents manage their own memory.
</Note>
### Step 5: Inspect Agent Memory
Let's see what the agent remembers. We'll print out both the summary and the full content of each memory block:
<CodeGroup>
```typescript TypeScript
// Retrieve the agent's current memory blocks
// API Reference: https://docs.letta.com/api-reference/agents/blocks/list
const blocks = await client.agents.blocks.list(agent.id);
console.log("Current Memory:");
for (const block of blocks) {
console.log(` ${block.label}: ${block.value.length}/${block.limit} chars`);
console.log(` ${block.value}\n`);
}
```
```python Python
# Retrieve the agent's current memory blocks
# API Reference: https://docs.letta.com/api-reference/agents/blocks/list
blocks = client.agents.blocks.list(agent_id=agent.id)
print("Current Memory:")
for block in blocks:
print(f" {block.label}: {len(block.value)}/{block.limit} chars")
print(f" {block.value}\n")
```
</CodeGroup>
The `persona` block should have:
> I am a friendly AI assistant here to help you learn about Letta.
The `human` block should have something like:
> Name: Cameron
<Note>
Notice how the `human` block now contains "Name: Cameron" instead of "Name: User". The agent used the `memory_replace` tool to update its memory based on the information you provided.
</Note>
## Complete Example
Here's the full code in one place that you can run:
<CodeGroup>
```typescript TypeScript
import { LettaClient } from '@letta-ai/letta-client';
// Initialize client using LETTA_API_KEY environment variable
const client = new LettaClient({ token: process.env.LETTA_API_KEY });
// If self-hosting, specify the base URL:
// const client = new LettaClient({ baseUrl: "http://localhost:8283" });
// Create agent
const agent = await client.agents.create({
name: "hello_world_assistant",
memoryBlocks: [
{
label: "persona",
value: "I am a friendly AI assistant here to help you learn about Letta."
},
{
label: "human",
value: "Name: User\nFirst interaction: Learning about Letta"
}
],
model: "openai/gpt-4o-mini",
// embedding: "openai/text-embedding-3-small", // Only set this if self-hosting
});
console.log(`Created agent: ${agent.id}\n`);
// Send first message
let response = await client.agents.messages.create(agent.id, {
messages: [{ role: "user", content: "Hello! What's your purpose?" }]
});
for (const msg of response.messages) {
if (msg.messageType === "assistant_message") {
console.log(`Assistant: ${msg.content}\n`);
}
}
// Send information about yourself
response = await client.agents.messages.create(agent.id, {
messages: [{ role: "user", content: "My name is Cameron. Please store this information in your memory." }]
});
// Print out tool calls and the assistant's response
for (const msg of response.messages) {
if (msg.messageType === "assistant_message") {
console.log(`Assistant: ${msg.content}\n`);
}
if (msg.messageType === "tool_call_message") {
console.log(`Tool call: ${msg.toolCall.name}(${JSON.stringify(msg.toolCall.arguments)})`);
}
}
// Inspect memory
const blocks = await client.agents.blocks.list(agent.id);
console.log("Current Memory:");
for (const block of blocks) {
console.log(` ${block.label}: ${block.value.length}/${block.limit} chars`);
console.log(` ${block.value}\n`);
}
```
```python Python
from letta_client import Letta
import os
# Initialize client using LETTA_API_KEY environment variable
client = Letta(token=os.getenv("LETTA_API_KEY"))
# If self-hosting, specify the base URL:
# client = Letta(base_url="http://localhost:8283")
# Create agent
agent = client.agents.create(
name="hello_world_assistant",
memory_blocks=[
{
"label": "persona",
"value": "I am a friendly AI assistant here to help you learn about Letta."
},
{
"label": "human",
"value": "Name: User\nFirst interaction: Learning about Letta"
}
],
model="openai/gpt-4o-mini",
# embedding="openai/text-embedding-3-small", # Only set this if self-hosting
)
print(f"Created agent: {agent.id}\n")
# Send first message
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "Hello! What's your purpose?"}]
)
for msg in response.messages:
if msg.message_type == "assistant_message":
print(f"Assistant: {msg.content}\n")
# Send information about yourself
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "My name is Cameron. Please store this information in your memory."}]
)
# Print out tool calls and the assistant's response
for msg in response.messages:
if msg.message_type == "assistant_message":
print(f"Assistant: {msg.content}\n")
if msg.message_type == "tool_call_message":
print(f"Tool call: {msg.tool_call.name}({msg.tool_call.arguments})")
# Inspect memory
blocks = client.agents.blocks.list(agent_id=agent.id)
print("Current Memory:")
for block in blocks:
print(f" {block.label}: {len(block.value)}/{block.limit} chars")
print(f" {block.value}\n")
```
</CodeGroup>
## Key Concepts
<CardGroup cols={2}>
<Card title="Stateful Agents" icon="brain">
Letta agents maintain memory across conversations, unlike stateless chat APIs
</Card>
<Card title="Memory Blocks" icon="cube">
Modular memory components that agents can read and update during conversations
</Card>
<Card title="Persistent Context" icon="clock">
Agents remember user preferences, conversation history, and learned information
</Card>
<Card title="Automatic Updates" icon="rotate">
Agents intelligently update their memory as they learn more about you
</Card>
</CardGroup>
## Next Steps
<Card title="Memory Blocks Guide" icon="database" href="/guides/agents/memory-blocks">
Learn how to work with memory blocks, update them, and control agent knowledge
</Card>

View File

@@ -36,9 +36,9 @@ from letta.server.rest_api.utils import (
)
from letta.services.agent_manager import AgentManager
from letta.services.block_manager import BlockManager
from letta.services.job_manager import JobManager
from letta.services.message_manager import MessageManager
from letta.services.passage_manager import PassageManager
from letta.services.run_manager import RunManager
from letta.services.summarizer.enums import SummarizationMode
from letta.services.summarizer.summarizer import Summarizer
from letta.services.tool_executor.tool_execution_manager import ToolExecutionManager
@@ -63,7 +63,7 @@ class VoiceAgent(BaseAgent):
message_manager: MessageManager,
agent_manager: AgentManager,
block_manager: BlockManager,
job_manager: JobManager,
run_manager: RunManager,
passage_manager: PassageManager,
actor: User,
):
@@ -73,7 +73,7 @@ class VoiceAgent(BaseAgent):
# Summarizer settings
self.block_manager = block_manager
self.job_manager = job_manager
self.run_manager = run_manager
self.passage_manager = passage_manager
# TODO: This is not guaranteed to exist!
self.summary_block_label = "human"
@@ -99,7 +99,7 @@ class VoiceAgent(BaseAgent):
agent_manager=self.agent_manager,
actor=self.actor,
block_manager=self.block_manager,
job_manager=self.job_manager,
run_manager=self.run_manager,
passage_manager=self.passage_manager,
target_block_label=self.summary_block_label,
),
@@ -444,7 +444,7 @@ class VoiceAgent(BaseAgent):
message_manager=self.message_manager,
agent_manager=self.agent_manager,
block_manager=self.block_manager,
job_manager=self.job_manager,
run_manager=self.run_manager,
passage_manager=self.passage_manager,
sandbox_env_vars=sandbox_env_vars,
actor=self.actor,

View File

@@ -14,9 +14,9 @@ from letta.schemas.tool_rule import ChildToolRule, ContinueToolRule, InitToolRul
from letta.schemas.user import User
from letta.services.agent_manager import AgentManager
from letta.services.block_manager import BlockManager
from letta.services.job_manager import JobManager
from letta.services.message_manager import MessageManager
from letta.services.passage_manager import PassageManager
from letta.services.run_manager import RunManager
from letta.services.summarizer.enums import SummarizationMode
from letta.services.summarizer.summarizer import Summarizer
from letta.types import JsonDict
@@ -34,7 +34,7 @@ class VoiceSleeptimeAgent(LettaAgent):
message_manager: MessageManager,
agent_manager: AgentManager,
block_manager: BlockManager,
job_manager: JobManager,
run_manager: RunManager,
passage_manager: PassageManager,
target_block_label: str,
actor: User,
@@ -44,7 +44,7 @@ class VoiceSleeptimeAgent(LettaAgent):
message_manager=message_manager,
agent_manager=agent_manager,
block_manager=block_manager,
job_manager=job_manager,
job_manager=run_manager,
passage_manager=passage_manager,
actor=actor,
)

View File

@@ -25,9 +25,9 @@ from letta.schemas.usage import LettaUsageStatistics
from letta.server.server import SyncServer
from letta.services.agent_manager import AgentManager
from letta.services.block_manager import BlockManager
from letta.services.job_manager import JobManager
from letta.services.message_manager import MessageManager
from letta.services.passage_manager import PassageManager
from letta.services.run_manager import RunManager
from letta.services.summarizer.enums import SummarizationMode
from letta.services.summarizer.summarizer import Summarizer
from letta.services.tool_manager import ToolManager
@@ -378,7 +378,7 @@ async def test_summarization(disable_e2b_api_key, voice_agent, server_url):
agent_manager=agent_manager,
actor=actor,
block_manager=BlockManager(),
job_manager=JobManager(),
run_manager=RunManager(),
passage_manager=PassageManager(),
target_block_label="human",
)
@@ -457,7 +457,7 @@ async def test_voice_sleeptime_agent(disable_e2b_api_key, voice_agent):
agent_manager=agent_manager,
actor=actor,
block_manager=BlockManager(),
job_manager=JobManager(),
run_manager=RunManager(),
passage_manager=PassageManager(),
target_block_label="human",
)