Eliza📦 包agent 包

🤖 智能体包

概述

智能体包(@eliza/agent)为 Eliza 提供了高级编排层,负责管理智能体的生命周期、角色加载、客户端初始化以及运行时协调。

架构

主要职责

Agent 包(@eliza/agent)作为 Eliza 的编排层,负责以下内容:

  • 角色和插件的加载。
  • 运行时的初始化和管理。
  • 数据库适配器的选择。
  • 客户端的初始化和协调。
  • 令牌和环境管理。

安装

pnpm add @eliza/agent

快速入门

import { loadCharacters, startAgents } from '@eliza/agent'
 
// 使用默认或自定义角色启动智能体
const args = parseArguments()
const characters = await loadCharacters(args.characters)
 
// 初始化智能体
await startAgents()

核心组件

智能体创建

export async function createAgent(character: Character, db: IDatabaseAdapter, token: string): Promise<AgentRuntime> {
  return new AgentRuntime({
    databaseAdapter: db,
    token,
    modelProvider: character.modelProvider,
    character,
    plugins: [
      bootstrapPlugin,
      nodePlugin,
      // 条件插件
      character.settings.secrets.WALLET_PUBLIC_KEY ? solanaPlugin : null,
    ].filter(Boolean),
    providers: [],
    actions: [],
    services: [],
    managers: [],
  })
}

角色加载

export async function loadCharacters(charactersArg: string): Promise<Character[]> {
  // 解析角色路径
  let characterPaths = charactersArg
    ?.split(',')
    .map(path => path.trim())
    .map(path => normalizePath(path))
 
  const loadedCharacters = []
 
  // 加载每个角色文件
  for (const path of characterPaths) {
    try {
      const character = JSON.parse(fs.readFileSync(path, 'utf8'))
 
      // 如果指定了插件,则加载插件
      if (character.plugins) {
        character.plugins = await loadPlugins(character.plugins)
      }
 
      loadedCharacters.push(character)
    } catch (error) {
      console.error(`从 ${path} 加载角色时出错: ${error}`)
    }
  }
 
  // 如果没有加载任何角色,则回退到默认角色
  if (loadedCharacters.length === 0) {
    loadedCharacters.push(defaultCharacter)
  }
 
  return loadedCharacters
}

客户端初始化

export async function initializeClients(character: Character, runtime: IAgentRuntime) {
  const clients = []
  const clientTypes = character.clients?.map(str => str.toLowerCase()) || []
 
  if (clientTypes.includes(Clients.DISCORD)) {
    clients.push(await DiscordClientInterface.start(runtime))
  }
  if (clientTypes.includes(Clients.TELEGRAM)) {
    clients.push(await TelegramClientInterface.start(runtime))
  }
  if (clientTypes.includes(Clients.TWITTER)) {
    clients.push(await TwitterClientInterface.start(runtime))
  }
  if (clientTypes.includes(Clients.DIRECT)) {
    clients.push(await AutoClientInterface.start(runtime))
  }
 
  return clients
}

数据库管理

function initializeDatabase(): IDatabaseAdapter {
  // 如果提供了 URL,则使用 PostgreSQL
  if (process.env.POSTGRES_URL) {
    return new PostgresDatabaseAdapter({
      connectionString: process.env.POSTGRES_URL,
    })
  }
 
  // 回退到 SQLite
  return new SqliteDatabaseAdapter(new Database('./db.sqlite'))
}

令牌管理

export function getTokenForProvider(provider: ModelProviderName, character: Character) {
  switch (provider) {
    case ModelProviderName.OPENAI:
      return character.settings?.secrets?.OPENAI_API_KEY || settings.OPENAI_API_KEY
 
    case ModelProviderName.ANTHROPIC:
      return (
        character.settings?.secrets?.ANTHROPIC_API_KEY ||
        character.settings?.secrets?.CLAUDE_API_KEY ||
        settings.ANTHROPIC_API_KEY
      )
 
    // 处理其他提供商...
  }
}

智能体生命周期管理

启动智能体

async function startAgent(character: Character, directClient: any) {
  try {
    // 获取提供商令牌
    const token = getTokenForProvider(character.modelProvider, character)
 
    // 初始化数据库
    const db = initializeDatabase()
 
    // 创建运行时
    const runtime = await createAgent(character, db, token)
 
    // 初始化客户端
    const clients = await initializeClients(character, runtime)
 
    // 向直接客户端注册
    directClient.registerAgent(runtime)
 
    return clients
  } catch (error) {
    console.error(`启动角色为 ${character.name} 的智能体时出错:`, error)
    throw error
  }
}

命令行界面

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
})
 
async function handleUserInput(input, agentId) {
  if (input.toLowerCase() === 'exit') {
    rl.close()
    return
  }
 
  try {
    const response = await fetch(`http://localhost:${serverPort}/${agentId}/message`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        text: input,
        userId: 'user',
        userName: 'User',
      }),
    })
 
    const data = await response.json()
    data.forEach(message => console.log(`智能体: ${message.text}`))
  } catch (error) {
    console.error('错误:', error)
  }
}

高级功能

插件管理

async function loadPlugins(pluginPaths: string[]) {
  return await Promise.all(
    pluginPaths.map(async plugin => {
      const importedPlugin = await import(plugin)
      return importedPlugin
    }),
  )
}

角色热重载

async function reloadCharacter(runtime: IAgentRuntime, characterPath: string) {
  // 加载新角色
  const character = JSON.parse(fs.readFileSync(characterPath, 'utf8'))
 
  // 更新运行时
  runtime.character = character
 
  // 重新加载插件
  if (character.plugins) {
    const plugins = await loadPlugins(character.plugins)
    runtime.registerPlugins(plugins)
  }
}

多智能体协调

class AgentCoordinator {
  private agents: Map<string, IAgentRuntime>
 
  async broadcast(message: Memory) {
    const responses = await Promise.all(Array.from(this.agents.values()).map(agent => agent.processMessage(message)))
    return responses
  }
 
  async coordinate(agents: string[], task: Task) {
    // 协调多个智能体完成一项任务
    const selectedAgents = agents.map(id => this.agents.get(id))
 
    return await this.executeCoordinatedTask(selectedAgents, task)
  }
}

最佳实践

角色管理

// 加载角色前验证角色
function validateCharacter(character: Character) {
  if (!character.name) {
    throw new Error('角色必须有一个名称')
  }
 
  if (!character.modelProvider) {
    throw new Error('必须指定模型提供商')
  }
}
 
// 使用角色版本控制
const character = {
  name: '智能体',
  version: '1.0.0',
  //...
}

错误处理

async function handleAgentError(error: Error, character: Character) {
  // 记录带有上下文的错误
  console.error(`智能体 ${character.name} 出错:`, error)
 
  // 尝试恢复
  if (error.code === 'TOKEN_EXPIRED') {
    await refreshToken(character)
  }
 
  // 通知监控
  await notify({
    level: '错误',
    角色: character.name,
    error,
  })
}

资源管理

class ResourceManager {
  async cleanup() {
    // 关闭数据库连接
    await this.db.close()
 
    // 关闭客户端
    await Promise.all(this.clients.map(client => client.stop()))
 
    // 清除缓存
    this.cache.clear()
  }
 
  async monitor() {
    // 监控资源使用情况
    const usage = process.memoryUsage()
    if (usage.heapUsed > 阈值) {
      await this.cleanup()
    }
  }
}

故障排除

常见问题

  1. 角色加载失败
try {
  await loadCharacters(charactersArg)
} catch (error) {
  if (error.code === 'ENOENT') {
    console.error('角色文件未找到')
  } else if (error instanceof SyntaxError) {
    console.error('无效的角色 JSON')
  }
}
  1. 客户端初始化错误
async function handleClientError(error: Error) {
  if (error.message.includes('速率限制')) {
    await等待(exponentialBackoff())
  } else if (error.message.includes('认证')) {
    await刷新认证()
  }
}
  1. 数据库连接问题
async function handleDbError(error: Error) {
  if (error.message.includes('连接')) {
    await重新连接数据库()
  } else if (error.message.includes('锁定')) {
    await等待解锁()
  }
}

相关资源