π€ Agents
Agents are the core components of the Eliza framework that handle autonomous interactions. Each agent runs in a runtime environment and can interact through various clients (Discord, Telegram, etc.) while maintaining consistent behavior and memory.
Overviewβ
The AgentRuntime class is the primary implementation of the IAgentRuntime interface, which manages the agent's core functions, including:
- Message and Memory Processing: Storing, retrieving, and managing conversation data and contextual memory.
- State Management: Composing and updating the agentβs state for a coherent, ongoing interaction.
- Action Execution: Handling behaviors such as transcribing media, generating images, and following rooms.
- Evaluation and Response: Assessing responses, managing goals, and extracting relevant information.
Core Componentsβ
Each agent runtime consists of key components that enable flexible and extensible functionality:
- Clients: Enable communication across platforms such as Discord, Telegram, and Direct (REST API), with features tailored for each platform.
- Providers: Extend the agentβs capabilities by integrating with additional services (e.g., time, wallet, or custom data).
- Actions: Define agent behaviors, such as following rooms, generating images, or processing attachments. Custom actions can be created to tailor behaviors to specific needs.
- Evaluators: Manage agent responses by assessing message relevance, managing goals, extracting facts, and building long-term memory.
AgentRuntime Interfaceβ
The IAgentRuntime
interface defines the main structure of the runtime environment, specifying the configuration and essential components:
interface IAgentRuntime {
// Core identification
agentId: UUID;
serverUrl: string;
token: string;
// Configuration
character: Character;
modelProvider: ModelProviderName;
// Components
actions: Action[];
evaluators: Evaluator[];
providers: Provider[];
// Database & Memory
databaseAdapter: IDatabaseAdapter;
messageManager: IMemoryManager;
descriptionManager: IMemoryManager;
loreManager: IMemoryManager;
}
Each element in the runtime interface plays a crucial role:
- Identification: Agent ID, server URL, and token for authentication and identification.
- Configuration: Character profile and model provider define the agent's personality and language model.
- Components: Actions, evaluators, and providers support extensible behaviors, response evaluation, and service integration.
- Memory Management: Specialized memory managers track conversations, descriptions, and static knowledge to enable contextual and adaptive responses.
Creating an Agent Runtimeβ
This section demonstrates setting up an agent with basic and optional configurations. It provides a working example and sample code that helps users quickly start building:
import { AgentRuntime, ModelProviderName } from "@ai16z/eliza";
// Configuration example
const runtime = new AgentRuntime({
token: "auth-token",
modelProvider: ModelProviderName.ANTHROPIC,
character: characterConfig,
databaseAdapter: new DatabaseAdapter(),
conversationLength: 32,
serverUrl: "http://localhost:7998",
actions: customActions,
evaluators: customEvaluators,
providers: customProviders,
});
State Managementβ
This section should cover how agents manage and update state, with a focus on initial state composition and updating methods. The runtime maintains state through the State interface:
interface State {
userId?: UUID;
agentId?: UUID;
roomId: UUID;
bio: string;
lore: string;
agentName?: string;
senderName?: string;
actors: string;
actorsData?: Actor[];
recentMessages: string;
recentMessagesData: Memory[];
goals?: string;
goalsData?: Goal[];
actions?: string;
actionNames?: string;
providers?: string;
}
State composition and updates are handled through dedicated methods:
// Compose initial state
const state = await runtime.composeState(message, {
additionalContext: "custom-context",
});
// Update message state
const updatedState = await runtime.updateRecentMessageState(state);
Best practices
- Keep state immutable where possible
- Use
composeState
for initial state creation - Use
updateRecentMessageState
for updates - Cache frequently accessed state data
Memory Systemsβ
The Eliza framework uses multiple types of memory to support an agent's long-term engagement, contextual understanding, and adaptive responses. Each type of memory serves a specific purpose:
-
Message History: Stores recent conversations to provide continuity within a session. This helps the agent maintain conversational context and avoid repetitive responses within short-term exchanges.
-
Factual Memory: Holds specific, context-based facts about the user or environment, such as user preferences, recent activities, or specific details mentioned in previous interactions. This type of memory enables the agent to recall user-specific information across sessions.
-
Knowledge Base: Contains general knowledge the agent might need to respond to broader queries or provide informative answers. This memory is more static, helping the agent retrieve pre-defined data, common responses, or static character lore.
-
Relationship Tracking: Manages the agentβs understanding of its relationship with users, including details like user-agent interaction frequency, sentiment, and connection history. It is particularly useful for building rapport and providing a more personalized interaction experience over time.
-
RAG Integration: Uses a vector search to perform contextual recall based on similarity matching. This enables the agent to retrieve relevant memory snippets or knowledge based on the content and intent of the current conversation, making its responses more contextually relevant.
The runtime uses multiple specialized IMemoryManager instances:
messageManager
- conversation messages and responsesdescriptionManager
- user descriptions and profilesloreManager
- static character knowledge
Message Processingβ
The runtime's message processing is handled through the processActions method:
// Process message with actions
await runtime.processActions(message, responses, state, async (newMessages) => {
// Handle new messages
return [message];
});
Services and Memory Managementβ
Services are managed through the getService and registerService methods:
// Register service
runtime.registerService(new TranscriptionService());
// Get service
const service = runtime.getService<ITranscriptionService>(
ServiceType.TRANSCRIPTION,
);
Memory Managementβ
Memory managers are accessed via getMemoryManager:
// Get memory manager
const memoryManager = runtime.getMemoryManager("messages");
// Create memory
await memoryManager.createMemory({
id: messageId,
content: { text: "Message content" },
userId: userId,
roomId: roomId,
});
Best practices
- Use appropriate memory managers for different data types
- Consider memory limits when storing data, regularly clean up memory
- Use the
unique
flag for deduplicated storage - Clean up old memories periodically
- Use immutability in state management.
- Log errors and maintain stability during service failures.
Evaluation Systemβ
The runtime's evaluate method processes evaluations:
// Evaluate message
const evaluationResults = await runtime.evaluate(message, state, didRespond);
Usage Examplesβ
- Message Processing:
await runtime.processActions(message, responses, state, (newMessages) => {
return [message];
});
- State Management:
const state = await runtime.composeState(message, {
additionalContext: "custom-context",
});
- Memory Management:
const memoryManager = runtime.getMemoryManager("messages");
await memoryManager.createMemory({
id: messageId,
content: { text: "Message content" },
userId,
roomId,
});