Skip to main content

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[];
}
name
string
required
Action name (uppercase recommended, e.g., “SEND_MESSAGE”)
description
string
required
Detailed description for LLM to understand when to use this action
handler
Handler
required
Function that executes the action
validate
Validator
required
Function that validates if action should run in current context
similes
string[]
Alternative names for the action (e.g., [“message”, “dm”, “chat”])
examples
ActionExample[][]
Conversation examples showing when to use this action
priority
number
Action ordering priority (higher = earlier in prompt)
tags
string[]
Tags for categorization and filtering
parameters
ActionParameter[]
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>
runtime
IAgentRuntime
required
Agent runtime instance with access to all agent capabilities
message
Memory
required
Incoming message that triggered this action
state
State
Current state with provider data and values
options
HandlerOptions
Handler options including parameters, action context, and streaming
callback
HandlerCallback
Callback for sending responses during action execution
responses
Memory[]
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>;
}
success
boolean
required
Whether the action succeeded
text
string
Optional text description of the result
values
Record<string, ProviderValue>
Values to merge into state for subsequent actions
data
ProviderDataRecord
Structured data payload with action-specific results
error
string | Error
Error information if action failed
continueChain
boolean
Whether to continue executing chained actions
cleanup
function
Optional cleanup function to execute after action completion

ActionParameter Type

interface ActionParameter {
  name: string;
  description: string;
  required?: boolean;
  schema: ActionParameterSchema;
  examples?: ActionParameterExampleValue[];
}
name
string
required
Parameter name (used as key in parameters object)
description
string
required
Human-readable description for LLM guidance
required
boolean
Whether this parameter is required (default: false)
schema
ActionParameterSchema
required
JSON Schema for validation
examples
array
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;
}
type
string
required
Parameter type
default
JsonValue
Default value if not provided
enum
string[]
Allowed values (for string parameters)
minimum
number
Minimum value (for number parameters)
maximum
number
Maximum value (for number parameters)
pattern
string
Regex pattern (for string parameters)
properties
object
Nested properties (for object parameters)
items
ActionParameterSchema
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;
  }
};

Build docs developers (and LLMs) love