Important: This guide covers advanced breaking changes for evaluators, services, and runtime methods. Read the main migration guide first for actions, providers, and basic migrations.

Table of Contents


Evaluators Migration

Evaluator Interface Changes

Evaluators remain largely unchanged in their core structure, but their integration with the runtime has evolved:

// v0 Evaluator usage remains the same
export interface Evaluator {
  alwaysRun?: boolean;
  description: string;
  similes: string[];
  examples: EvaluationExample[];
  handler: Handler;
  name: string;
  validate: Validator;
}

Key Changes:

  1. Evaluation Results: The evaluate() method now returns Evaluator[] instead of string[]:
// v0: Returns string array of evaluator names
const evaluators: string[] = await runtime.evaluate(message, state);

// v1: Returns Evaluator objects
const evaluators: Evaluator[] | null = await runtime.evaluate(message, state);
  1. Additional Parameters: The evaluate method accepts new optional parameters:
// v1: Extended evaluate signature
await runtime.evaluate(
    message: Memory,
    state?: State,
    didRespond?: boolean,
    callback?: HandlerCallback,
    responses?: Memory[]  // NEW: Can pass responses for evaluation
);

Services & Clients Migration

Service Registration Changes

Services have undergone significant architectural changes:

// v0: Service extends abstract Service class
export abstract class Service {
  static get serviceType(): ServiceType {
    throw new Error('Service must implement static serviceType getter');
  }

  public static getInstance<T extends Service>(): T {
    // Singleton pattern
  }

  abstract initialize(runtime: IAgentRuntime): Promise<void>;
}

// v1: Service is now a class with static properties
export class Service {
  static serviceType: ServiceTypeName;

  async initialize(runtime: IAgentRuntime): Promise<void> {
    // Implementation
  }
}

Migration Steps:

  1. Remove Singleton Pattern:
// v0: Singleton getInstance
class MyService extends Service {
  private static instance: MyService | null = null;

  public static getInstance(): MyService {
    if (!this.instance) {
      this.instance = new MyService();
    }
    return this.instance;
  }
}

// v1: Direct instantiation
class MyService extends Service {
  static serviceType = ServiceTypeName.MY_SERVICE;
  // No getInstance needed
}
  1. Update Service Registration:
// v0: Register instance
await runtime.registerService(MyService.getInstance());

// v1: Register class
await runtime.registerService(MyService);
  1. Service Type Enum Changes:
// v0: ServiceType enum
export enum ServiceType {
  IMAGE_DESCRIPTION = 'image_description',
  TRANSCRIPTION = 'transcription',
  // ...
}

// v1: ServiceTypeName (similar but may have new values)
export enum ServiceTypeName {
  IMAGE_DESCRIPTION = 'image_description',
  TRANSCRIPTION = 'transcription',
  // Check for any renamed or new service types
}

Runtime Method Changes

1. State Management

The updateRecentMessageState method has been removed:

// v0: Separate method for updating state
currentState = await runtime.updateRecentMessageState(currentState);

// v1: Use composeState with specific keys
currentState = await runtime.composeState(message, ['RECENT_MESSAGES']);

2. Memory Manager Access

Memory managers are no longer directly accessible:

// v0: Direct access to memory managers
runtime.messageManager.getMemories({...});
runtime.registerMemoryManager(manager);
const manager = runtime.getMemoryManager("messages");

// v1: Use database adapter methods
await runtime.getMemories({
    roomId,
    count,
    unique: false,
    tableName: "messages",
    agentId: runtime.agentId
});

3. Model Usage

Complete overhaul of model interaction:

// v0: generateText with ModelClass
import { generateText, ModelClass } from '@elizaos/core';

const result = await generateText({
  runtime,
  context: prompt,
  modelClass: ModelClass.SMALL,
});

// v1: useModel with ModelTypeName
const result = await runtime.useModel(ModelTypeName.TEXT_SMALL, {
  prompt,
  stopSequences: [],
});

4. Settings Management

Global Settings Object Removed

The global settings object is no longer exported from @elizaos/core:

// v0: Import and use global settings
import { settings } from '@elizaos/core';

const charityAddress = settings[networkKey];
const apiKey = settings.OPENAI_API_KEY;

// v1: Use runtime.getSetting()
// Remove the settings import
import { elizaLogger, type IAgentRuntime } from '@elizaos/core';

const charityAddress = runtime.getSetting(networkKey);
const apiKey = runtime.getSetting('OPENAI_API_KEY');

New Settings Methods

// v0: Only getSetting through runtime
const value = runtime.getSetting(key);

// v1: Both get and set
const value = runtime.getSetting(key);
runtime.setSetting(key, value, isSecret);

Migration Example

// v0: utils.ts using global settings
import { settings } from '@elizaos/core';

export function getCharityAddress(network: string): string | null {
  const networkKey = `CHARITY_ADDRESS_${network.toUpperCase()}`;
  const charityAddress = settings[networkKey];
  return charityAddress;
}

// v1: Pass runtime to access settings
export function getCharityAddress(runtime: IAgentRuntime, network: string): string | null {
  const networkKey = `CHARITY_ADDRESS_${network.toUpperCase()}`;
  const charityAddress = runtime.getSetting(networkKey);
  return charityAddress;
}

Common Settings Migration Patterns

  1. Environment Variables: Both v0 and v1 read from environment variables, but access patterns differ
  2. Dynamic Settings: v1 allows runtime setting updates with setSetting()
  3. Secret Management: v1 adds explicit secret handling with the isSecret parameter

Real-World Fix: Coinbase Plugin

The Coinbase plugin’s getCharityAddress function needs updating:

// v0: Current broken code
import { settings } from '@elizaos/core'; // ERROR: 'settings' not exported

export function getCharityAddress(network: string, isCharitable = false): string | null {
  const networkKey = `CHARITY_ADDRESS_${network.toUpperCase()}`;
  const charityAddress = settings[networkKey]; // ERROR: Cannot use settings
  // ...
}

// v1: Fixed code - runtime parameter added
export function getCharityAddress(
  runtime: IAgentRuntime, // Add runtime parameter
  network: string,
  isCharitable = false
): string | null {
  const networkKey = `CHARITY_ADDRESS_${network.toUpperCase()}`;
  const charityAddress = runtime.getSetting(networkKey); // Use runtime.getSetting
  // ...
}

// Update all callers to pass runtime
const charityAddress = getCharityAddress(runtime, network);

5. Event System

New event-driven architecture:

// v1: Register and emit events
runtime.registerEvent('custom-event', async (params) => {
  // Handle event
});

await runtime.emitEvent('custom-event', { data: 'value' });

Entity System Migration

The most significant change is the shift from User/Participant to Entity/Room/World:

User → Entity

// v0: User-based methods
await runtime.ensureUserExists(userId, userName, name, email, source);
const account = await runtime.getAccountById(userId);

// v1: Entity-based methods
await runtime.ensureConnection({
  entityId: userId,
  roomId,
  userName,
  name,
  worldId,
  source,
});
const entity = await runtime.getEntityById(entityId);

Participant → Room Membership

// v0: Participant methods
await runtime.ensureParticipantExists(userId, roomId);
await runtime.ensureParticipantInRoom(userId, roomId);

// v1: Simplified room membership
await runtime.ensureParticipantInRoom(entityId, roomId);

New World Concept

v1 introduces the concept of “worlds” (servers/environments):

// v1: World management
await runtime.ensureWorldExists({
  id: worldId,
  name: serverName,
  type: 'discord', // or other platform
});

// Get all rooms in a world
const rooms = await runtime.getRooms(worldId);

Connection Management

// v0: Multiple ensure methods
await runtime.ensureUserExists(...);
await runtime.ensureRoomExists(roomId);
await runtime.ensureParticipantInRoom(...);

// v1: Single connection method
await runtime.ensureConnection({
    entityId,
    roomId,
    worldId,
    userName,
    name,
    source,
    channelId,
    serverId,
    type: 'user',
    metadata: {}
});

Client Migration

Clients now have a simpler interface:

// v0: Client with config
export type Client = {
  name: string;
  config?: { [key: string]: any };
  start: (runtime: IAgentRuntime) => Promise<ClientInstance>;
};

// v1: Client integrated with services
// Clients are now typically implemented as services
class MyClient extends Service {
  static serviceType = ServiceTypeName.MY_CLIENT;

  async initialize(runtime: IAgentRuntime): Promise<void> {
    // Start client operations
  }

  async stop(): Promise<void> {
    // Stop client operations
  }
}

Quick Reference

Removed Methods

  • updateRecentMessageState() → Use composeState(message, ['RECENT_MESSAGES'])
  • registerMemoryManager() → Not needed, use database adapter
  • getMemoryManager() → Use database adapter methods
  • registerContextProvider() → Use registerProvider()

Removed Exports

  • settings object → Use runtime.getSetting(key) instead

Changed Methods

  • evaluate() → Now returns Evaluator[] instead of string[]
  • getAccountById()getEntityById()
  • ensureUserExists()ensureConnection()
  • generateText()runtime.useModel()

New Methods

  • setSetting()
  • registerEvent()
  • emitEvent()
  • useModel()
  • registerModel()
  • ensureWorldExists()
  • getRooms()

Migration Checklist

  • Update all evaluator result handling to expect Evaluator[] objects
  • Remove singleton patterns from services
  • Update service registration to pass classes instead of instances
  • Replace updateRecentMessageState with composeState
  • Migrate from generateText to runtime.useModel
  • Update user/participant methods to entity/room methods
  • Add world management for multi-server environments
  • Convert clients to service-based architecture
  • Update any direct memory manager access to use database adapter
  • Replace import { settings } with runtime.getSetting() calls
  • Update functions to accept runtime parameter where settings are needed

Need Help?

If you encounter issues not covered in this guide:

  1. Check the main migration guide for basic migrations
  2. Review the v1.x examples in the ElizaOS repository for reference implementations
  3. Join our Discord community for support