Overview
Actions are executable behaviors that agents can perform. They define what the agent can do, from sending messages to interacting with external APIs. The elizaOS action system includes parameter extraction, validation, and result chaining.
Action Type
interface Action {
name: string;
description: string;
handler: Handler;
validate: Validator;
similes?: string[];
examples?: ActionExample[][];
priority?: number;
tags?: string[];
parameters?: ActionParameter[];
}
Action name (uppercase recommended, e.g., “SEND_MESSAGE”)
Detailed description for LLM to understand when to use this action
Function that executes the action
Function that validates if action should run in current context
Alternative names for the action (e.g., [“message”, “dm”, “chat”])
Conversation examples showing when to use this action
Action ordering priority (higher = earlier in prompt)
Tags for categorization and filtering
Input parameters that LLM extracts from conversation
Handler Type
type Handler = (
runtime: IAgentRuntime,
message: Memory,
state?: State,
options?: HandlerOptions,
callback?: HandlerCallback,
responses?: Memory[]
) => Promise<ActionResult | undefined>
Agent runtime instance with access to all agent capabilities
Incoming message that triggered this action
Current state with provider data and values
Handler options including parameters, action context, and streaming
Callback for sending responses during action execution
Array of response memories from the agent
ActionResult Type
interface ActionResult {
success: boolean;
text?: string;
values?: Record<string, ProviderValue>;
data?: ProviderDataRecord;
error?: string | Error;
continueChain?: boolean;
cleanup?: () => void | Promise<void>;
}
Whether the action succeeded
Optional text description of the result
values
Record<string, ProviderValue>
Values to merge into state for subsequent actions
Structured data payload with action-specific results
Error information if action failed
Whether to continue executing chained actions
Optional cleanup function to execute after action completion
ActionParameter Type
interface ActionParameter {
name: string;
description: string;
required?: boolean;
schema: ActionParameterSchema;
examples?: ActionParameterExampleValue[];
}
Parameter name (used as key in parameters object)
Human-readable description for LLM guidance
Whether this parameter is required (default: false)
schema
ActionParameterSchema
required
JSON Schema for validation
Example values shown to model
ActionParameterSchema Type
interface ActionParameterSchema {
type: "string" | "number" | "boolean" | "array" | "object";
default?: JsonValue | null;
enum?: string[];
enumValues?: string[];
minimum?: number;
maximum?: number;
pattern?: string;
properties?: Record<string, ActionParameterSchema>;
items?: ActionParameterSchema;
}
Default value if not provided
Allowed values (for string parameters)
Minimum value (for number parameters)
Maximum value (for number parameters)
Regex pattern (for string parameters)
Nested properties (for object parameters)
Item schema (for array parameters)
Registering Actions
registerAction
runtime.registerAction(action: Action): void
Register an action with the runtime.
Example:
runtime.registerAction({
name: "SEND_MESSAGE",
description: "Send a message to a user on a platform",
parameters: [
{
name: "recipient",
description: "Username or ID of the recipient",
required: true,
schema: { type: "string" }
},
{
name: "platform",
description: "Platform to send on",
required: false,
schema: {
type: "string",
enum: ["telegram", "discord", "twitter"],
default: "telegram"
}
}
],
handler: async (runtime, message, state, options) => {
const { recipient, platform } = options.parameters || {};
// Send message logic here
await sendMessageToPlatform(platform, recipient, text);
return {
success: true,
text: `Sent message to ${recipient} on ${platform}`
};
},
validate: async (runtime, message) => {
// Check if user has permission, etc.
return true;
},
similes: ["message", "dm", "send"],
examples: [
[
{
name: "user",
content: { text: "Send a message to @alice saying hello" }
},
{
name: "agent",
content: {
text: "I'll send that message to Alice",
actions: ["SEND_MESSAGE"]
}
}
]
]
});
Action Parameters
Actions can define parameters that the LLM extracts from conversation:
runtime.registerAction({
name: "BOOK_FLIGHT",
description: "Book a flight for the user",
parameters: [
{
name: "origin",
description: "Departure city or airport code",
required: true,
schema: { type: "string" },
examples: ["SFO", "San Francisco", "JFK"]
},
{
name: "destination",
description: "Arrival city or airport code",
required: true,
schema: { type: "string" }
},
{
name: "departureDate",
description: "Departure date (YYYY-MM-DD)",
required: true,
schema: { type: "string", pattern: "\\d{4}-\\d{2}-\\d{2}" }
},
{
name: "passengerCount",
description: "Number of passengers",
required: false,
schema: { type: "number", minimum: 1, maximum: 10, default: 1 }
}
],
handler: async (runtime, message, state, options) => {
const params = options.parameters || {};
// Parameters are already validated
const { origin, destination, departureDate, passengerCount } = params;
const booking = await bookFlight({
origin,
destination,
departureDate,
passengerCount
});
return {
success: true,
text: `Booked flight from ${origin} to ${destination}`,
data: { bookingId: booking.id }
};
},
validate: async () => true
});
The LLM will extract parameters from the conversation:
User: Book me a flight from San Francisco to New York on March 15th for 2 passengers
Extracted parameters:
- origin: "San Francisco"
- destination: "New York"
- departureDate: "2024-03-15"
- passengerCount: 2
Action Chaining
Actions can return values for subsequent actions:
runtime.registerAction({
name: "LOOKUP_USER",
handler: async (runtime, message) => {
const user = await database.findUser(username);
return {
success: true,
values: {
userId: user.id,
userEmail: user.email
},
data: { user }
};
},
validate: async () => true
});
runtime.registerAction({
name: "SEND_EMAIL",
handler: async (runtime, message, state, options) => {
// Access values from previous LOOKUP_USER action
const userEmail = state.values?.userEmail;
await sendEmail(userEmail, subject, body);
return { success: true };
},
validate: async () => true
});
Streaming Responses
Actions can stream responses during execution:
runtime.registerAction({
name: "GENERATE_REPORT",
handler: async (runtime, message, state, options) => {
const { onStreamChunk } = options;
if (onStreamChunk) {
await onStreamChunk("Generating report...\n");
// Stream progress updates
for (let i = 0; i < 10; i++) {
await processSection(i);
await onStreamChunk(`Section ${i + 1} complete\n`);
}
}
return {
success: true,
text: "Report generation complete"
};
},
validate: async () => true
});
Example: Complete Action
import { Action } from "@elizaos/core";
export const weatherAction: Action = {
name: "GET_WEATHER",
description: "Get current weather for a location",
parameters: [
{
name: "location",
description: "City name or zip code",
required: true,
schema: { type: "string" },
examples: ["San Francisco", "94102", "London"]
},
{
name: "units",
description: "Temperature units",
required: false,
schema: {
type: "string",
enum: ["celsius", "fahrenheit"],
default: "celsius"
}
}
],
similes: ["weather", "forecast", "temperature"],
examples: [
[
{
name: "user",
content: { text: "What's the weather in San Francisco?" }
},
{
name: "agent",
content: {
text: "Let me check the weather for you",
actions: ["GET_WEATHER"]
}
}
]
],
handler: async (runtime, message, state, options) => {
const { location, units } = options.parameters || {};
try {
const apiKey = runtime.getSetting("WEATHER_API_KEY");
const response = await fetch(
`https://api.weather.com/v1/current?location=${location}&units=${units}&key=${apiKey}`
);
const data = await response.json();
return {
success: true,
text: `Weather in ${location}: ${data.temperature}°${units === 'fahrenheit' ? 'F' : 'C'}, ${data.conditions}`,
data: {
location,
temperature: data.temperature,
conditions: data.conditions,
units
}
};
} catch (error) {
return {
success: false,
error: `Failed to get weather: ${error.message}`
};
}
},
validate: async (runtime, message) => {
// Only allow if API key is configured
return runtime.getSetting("WEATHER_API_KEY") !== null;
}
};