ADK.js PluginManager教程:扩展Agent功能的插件系统

【免费下载链接】adk-js An open-source, code-first Typescript toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control. 【免费下载链接】adk-js 项目地址: https://gitcode.com/GitHub_Trending/ad/adk-js

ADK.js是一个开源的、代码优先的TypeScript工具包,用于构建、评估和部署复杂的AI代理,具有灵活性和控制力。PluginManager作为ADK.js的核心组件,提供了强大的插件系统,让开发者能够轻松扩展AI Agent的功能,实现自定义日志记录、性能监控、请求拦截等高级特性。

什么是PluginManager?

PluginManager是ADK.js中负责插件注册和执行的核心类,它能够在SDK执行生命周期的关键节点协调插件回调的调用。通过PluginManager,开发者可以注册多个插件,实现对Agent行为的全局干预和扩展。

PluginManager的核心特性包括:

  • 插件注册与管理:支持添加、检索插件,确保插件名称的唯一性
  • 生命周期回调:在Agent运行、工具调用、模型请求等关键阶段触发插件回调
  • 短路执行策略:如果某个插件回调返回非undefined值,后续插件将停止执行

PluginManager的核心功能

插件注册机制

PluginManager通过registerPlugin方法管理插件,确保每个插件名称的唯一性。当尝试注册重复名称的插件时,将抛出错误:

// 插件注册逻辑 [core/src/plugins/plugin_manager.ts]
registerPlugin(plugin: BasePlugin): void {
  if (this.plugins.has(plugin)) {
    throw new Error(`Plugin '${plugin.name}' already registered.`);
  }
  if (Array.from(this.plugins).some(p => p.name === plugin.name)) {
    throw new Error(`Plugin with name '${plugin.name}' already registered.`);
  }
  this.plugins.add(plugin);
  logger.info(`Plugin '${plugin.name}' registered.`);
}

生命周期回调系统

PluginManager提供了丰富的生命周期回调,覆盖了从用户消息处理到Agent运行、工具调用和模型请求的完整流程。主要回调包括:

  • 用户消息处理onUserMessageCallback - 在收到用户消息时触发
  • Agent运行beforeRunCallbackafterRunCallback - 在Agent运行前后执行
  • 工具调用beforeToolCallbackafterToolCallback - 在工具调用前后执行
  • 模型请求beforeModelCallbackafterModelCallback - 在模型请求前后执行
  • 错误处理onModelErrorCallbackonToolErrorCallback - 处理模型和工具调用错误

插件执行流程

PluginManager采用"短路执行"策略,当某个插件回调返回非undefined值时,将停止后续插件的执行并返回该值。这种机制允许插件拦截和修改执行流程,实现诸如缓存、权限控制等高级功能。

执行逻辑如下:

// 插件执行核心逻辑 [core/src/plugins/plugin_manager.ts]
private async runCallbacks(
    plugins: Set<BasePlugin>,
    callback: (plugin: BasePlugin) => Promise<unknown>,
    callbackName: string,
): Promise<unknown> {
  for (const plugin of plugins) {
    try {
      const result = await callback(plugin);
      if (result !== undefined) {
        logger.debug(
            `Plugin '${plugin.name}' returned a value for callback '${
                callbackName}', exiting early.`);
        return result;
      }
    } catch (e) {
      const errorMessage = `Error in plugin '${
          plugin.name}' during '${callbackName}' callback: ${e}`;
      logger.error(errorMessage);
      throw new Error(errorMessage);
    }
  }
  return undefined;
}

如何创建自定义插件

创建自定义插件非常简单,只需继承BasePlugin类并实现所需的回调方法。以下是创建一个简单日志插件的步骤:

1. 创建插件类

import { BasePlugin } from '../core/src/plugins/base_plugin.ts';
import { BaseTool } from '../core/src/tools/base_tool.ts';
import { ToolContext } from '../core/src/tools/tool_context.ts';

export class ToolLoggerPlugin extends BasePlugin {
  constructor() {
    super('tool_logger');
  }

  override async beforeToolCallback({ tool, toolArgs, toolContext }: {
    tool: BaseTool;
    toolArgs: Record<string, unknown>;
    toolContext: ToolContext;
  }): Promise<Record<string, unknown> | undefined> {
    console.log(`[${this.name}] Calling tool '${tool.name}' with args: ${JSON.stringify(toolArgs)}`);
    return undefined;
  }

  override async afterToolCallback({ tool, result }: {
    tool: BaseTool;
    toolArgs: Record<string, unknown>;
    toolContext: ToolContext;
    result: Record<string, unknown>;
  }): Promise<Record<string, unknown> | undefined> {
    console.log(`[${this.name}] Tool '${tool.name}' finished with result: ${JSON.stringify(result)}`);
    return undefined;
  }
}

2. 注册插件到Runner

import { Runner } from '../core/src/runner/runner.ts';
import { ToolLoggerPlugin } from './tool_logger_plugin.ts';

// 创建Runner实例并注册插件
const runner = new Runner({
  // ...其他配置
  plugins: [new ToolLoggerPlugin()],
});

内置插件介绍

ADK.js提供了一些实用的内置插件,可以直接使用:

LoggingPlugin

日志插件,用于记录Agent执行过程中的关键事件和数据。源码位于[core/src/plugins/logging_plugin.ts]。

SecurityPlugin

安全插件,提供输入验证和权限检查功能,保护Agent免受恶意输入的影响。源码位于[core/src/plugins/security_plugin.ts]。

插件开发最佳实践

1. 单一职责原则

每个插件应专注于单一功能,如日志记录、性能监控或缓存。这使得插件更易于维护和复用。

2. 避免副作用

插件应尽量避免修改外部系统状态,保持功能的纯粹性和可预测性。

3. 错误处理

插件应妥善处理内部错误,避免影响整个Agent的执行:

async beforeToolCallback({ tool, toolArgs }: {
  tool: BaseTool;
  toolArgs: Record<string, unknown>;
  toolContext: ToolContext;
}): Promise<Record<string, unknown> | undefined> {
  try {
    // 插件逻辑
  } catch (error) {
    logger.error(`Plugin error: ${error}`);
    // 返回undefined继续执行
    return undefined;
  }
}

4. 文档注释

为插件和回调方法提供清晰的文档注释,说明功能、参数和返回值。

常见问题解答

Q: 插件执行顺序如何确定?

A: 插件按照注册顺序执行,先注册的插件先执行。如果需要控制执行顺序,可以调整插件注册的顺序。

Q: 如何在插件中共享数据?

A: 可以使用InvocationContextToolContext来在插件之间共享数据,这些上下文对象在整个执行过程中保持不变。

Q: 插件可以修改Agent的行为吗?

A: 是的,通过在回调中返回非undefined值,可以修改Agent的输入、工具参数或模型响应,甚至可以短路执行流程。

总结

ADK.js的PluginManager提供了一个灵活而强大的插件系统,让开发者能够轻松扩展AI Agent的功能。通过本文介绍的PluginManager核心概念、使用方法和最佳实践,你可以开始创建自己的插件,为ADK.js Agent添加日志记录、性能监控、安全验证等各种功能。

无论是构建简单的工具调用日志插件,还是复杂的模型请求缓存系统,PluginManager都能为你提供所需的基础设施和灵活性,帮助你构建更强大、更可靠的AI Agent应用。

【免费下载链接】adk-js An open-source, code-first Typescript toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control. 【免费下载链接】adk-js 项目地址: https://gitcode.com/GitHub_Trending/ad/adk-js

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐