mcpField
H
Hedera Plugin Creation

Hedera Plugin Creation

github.com/hedera-dev开发2889 次安装8 周前更新
代码仓库

关于 Hedera Plugin Creation

Hedera Plugin Creation 是面向开发者的 Skill,指导为 Hedera Agent Kit 构建自定义插件,涵盖工具定义、生命周期实现和工具包注册,包括 MCP 工具包。

主要功能

  1. 01插件结构与导出方式
  2. 02BaseTool 生命周期指南
  3. 03Zod 参数验证
  4. 04查询与变更工具模式
  5. 05工具包插件注册
  6. 06参考模式与示例

适用场景

  1. 01构建自定义 Hedera 代币工具
  2. 02实现只读 Hedera 查询
  3. 03向 Agent 工具包注册插件

MCP 相关

介绍如何将 Hedera Agent Kit 插件注册到 `@hashgraph/hedera-agent-kit-mcp`。插件通过所选工具包向 AI Agent 提供工具。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/hedera-dev/hedera-skills --skill hedera-plugin-creation

安装后在 Claude Code 中输入/hedera-plugin-creation确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/simple-plugin/
index.ts
examples/simple-plugin/tools/
greeting.ts
examples/token-plugin/
index.ts
examples/token-plugin/tools/
create-token.ts
get-token-info.ts
references/
plugin-interface.md
error-handling.md
prompt-patterns.md
zod-schema-patterns.md

详细介绍

创建 Hedera Agent Kit 插件

本技能提供创建自定义插件的指导,用于扩展 Hedera Agent Kit。插件支持添加与 Hedera 网络交互的新工具,包括代币操作、账户管理、共识服务、智能合约和自定义集成。

快速入门

通过以下 5 个步骤创建 Hedera 插件:

  1. 安装依赖项:使用 @hashgraph/hedera-agent-kit 和 @hiero-ledger/sdk 搭建 TypeScript 项目
  2. 创建插件结构:创建包含插件定义的 index.ts 和 tools/ 目录
  3. 定义工具:每个工具都是一个扩展 BaseTool 的类 — 这样工具即可参与钩子/策略生命周期
  4. 正确导出:导出插件对象和工具名称常量
  5. 向 Agent 注册:导入插件,并将其传入工具包的 configuration.plugins 数组

插件接口

每个 Hedera 插件都实现 @hashgraph/hedera-agent-kit 中的此接口:

import { Plugin } from '@hashgraph/hedera-agent-kit';

export interface Plugin {
  name: string;           // Unique kebab-case identifier
  version?: string;       // Semantic version (e.g., "1.0.0")
  description?: string;   // Brief explanation of plugin purpose
  tools: (context: Context) => Tool[];  // Factory returning tools
}

tools 函数接收一个包含网络配置的 Context 对象,并返回一个 Tool 对象数组。BaseTool 本身实现了 Tool,因此 BaseTool 子类实例是有效的返回值。

BaseTool

工具以扩展 BaseTool 的类来编写。BaseTool 实现了 Tool,并运行一个包含 7 个阶段的生命周期:

[1] preToolExecutionHook
[2] normalizeParams        ← your logic
[3] postParamsNormalizationHook
[4] coreAction             ← your logic
[5] postCoreActionHook
[6] secondaryAction        ← your logic (skipped via shouldSecondaryAction for queries)
[7] postToolExecutionHook

在 Agent Kit 上注册的钩子和策略会在阶段 1、3、5 和 7 自动触发 — 无需手动调用。

子类必须提供:

成员类型说明
methodstring以 _tool 为后缀的蛇形命名标识符
namestring面向用户的显示名称
descriptionstring面向大模型的描述(通常在构造函数中由提示词函数生成)
parametersz.ZodObject用于输入验证的 Zod 架构
normalizeParams(params, context, client)async阶段 2 — 解析默认值、验证格式
coreAction(normalised, context, client)async阶段 4 — 构建交易或执行查询
secondaryAction(request, client, context)async阶段 6 — 签名/提交交易(查询操作无需执行)

可选重写项:outputParser、shouldSecondaryAction(仅查询工具返回 false)、handleError,以及四个钩子方法。

工具类型

变更类工具 — 会更改状态的操作(代币创建/铸造/转账、账户更新、主题提交)。coreAction 构建 Transaction,secondaryAction 调用 handleTransaction()。使用 transactionToolOutputParser。

查询工具 — 只读操作(代币信息、余额、镜像节点获取)。coreAction 直接返回结果。重写 shouldSecondaryAction 并使其返回 false。使用 untypedQueryOutputParser。

文件结构模式

所有 Hedera 插件都遵循以下结构:

my-hedera-plugin/
├── index.ts                    # Plugin definition and exports
└── tools/
    └── category/               # Group related tools
        ├── create-something.ts
        └── get-something.ts

创建工具

步骤 1:定义工具常量
export const MY_TOOL_NAME = 'my_tool_name_tool';

常量使用带 _TOOL 后缀的 UPPER_SNAKE_CASE 命名。其值应采用小写蛇形命名。

步骤 2:创建提示词函数
const myToolPrompt = (context: Context = {}) => {
  return `This tool does X on Hedera.
Parameters:
- param1 (str, required): Description of param1
- param2 (int, optional): Description of param2, defaults to 0`;
};
步骤 3:使用 Zod 定义参数
import { z } from 'zod';

const myToolParameters = (_context: Context = {}) => {
  return z.object({
    param1: z.string().describe('Description of param1'),
    param2: z.number().optional().describe('Description of param2'),
  });
};

type MyToolParams = z.infer<ReturnType<typeof myToolParameters>>;

常见的 Hedera 参数模式请参阅 references/zod-schema-patterns.md。

步骤 4:实现 BaseTool 子类(变更类示例)
import { Client, Status } from '@hiero-ledger/sdk';
import {
  BaseTool,
  Context,
  handleTransaction,
  RawTransactionResponse,
  transactionToolOutputParser,
} from '@hashgraph/hedera-agent-kit';

const postProcess = (response: RawTransactionResponse) =>
  `Operation completed.
Transaction ID: ${response.transactionId}`;

export class MyTool extends BaseTool<MyToolParams, MyToolParams> {
  method = MY_TOOL_NAME;
  name = 'My Tool Display Name';
  description: string;
  parameters: ReturnType<typeof myToolParameters>;
  outputParser = transactionToolOutputParser;

  constructor(context: Context) {
    super();
    this.description = myToolPrompt(context);
    this.parameters = myToolParameters(context);
  }

  // Stage 2 — resolve defaults
  async normalizeParams(params: MyToolParams) {
    return params;
  }

  // Stage 4 — build the transaction (do not sign here)
  async coreAction(params: MyToolParams, _context: Context, _client: Client) {
    // return new SomeTransaction()...;
    return undefined as any;
  }

  // Stage 6 — sign and submit
  async secondaryAction(transaction: any, client: Client, context: Context) {
    return handleTransaction(transaction, client, context, postProcess);
  }

  async handleError(error: unknown) {
    const message = 'Failed to execute' + (error instanceof Error ? `: ${error.message}` : '');
    console.error(`[${MY_TOOL_NAME}]`, message);
    return { raw: { status: Status.InvalidTransaction, error: message }, humanMessage: message };
  }
}
步骤 5:导出工厂函数
const tool = (context: Context): BaseTool => new MyTool(context);
export default tool;

工厂模式使插件的 tools(context) 函数能够为每个请求实例化一个绑定了相应上下文的新工具。

查询工具变体 — 跳过阶段 6

对于只读工具,重写 shouldSecondaryAction,使生命周期在 coreAction 后停止,并让 secondaryAction 原样传递结果:

export class MyQueryTool extends BaseTool<MyToolParams, MyToolParams> {
  // ... method/name/description/parameters as above ...
  outputParser = untypedQueryOutputParser;

  async normalizeParams(params: MyToolParams) {
    return params;
  }

  async coreAction(params: MyToolParams, _context: Context, client: Client) {
    return await someHederaQuery(params, client);
  }

  async shouldSecondaryAction() {
    return false;
  }

  async secondaryAction(result: any) {
    return result;
  }
}

创建插件索引

import { Context, Plugin } from '@hashgraph/hedera-agent-kit';
import myTool, { MY_TOOL_NAME } from './tools/category/my-tool';

export const myPlugin: Plugin = {
  name: 'my-hedera-plugin',
  version: '1.0.0',
  description: 'A plugin for custom Hedera operations',
  tools: (context: Context) => {
    return [
      myTool(context),
    ];
  },
};

export const myPluginToolNames = {
  MY_TOOL_NAME,
} as const;

export default { myPlugin, myPluginToolNames };

后处理结果

secondaryAction 通常会委托给 handleTransaction,后者使用原始交易响应调用 postProcess 函数:

const postProcess = (response: RawTransactionResponse) => {
  if (response.scheduleId) {
    return `Scheduled transaction created.
Transaction ID: ${response.transactionId}
Schedule ID: ${response.scheduleId.toString()}`;
  }
  return `Operation completed.
Transaction ID: ${response.transactionId}`;
};

RETURN_BYTES 模式 — raw.bytes 是 Uint8Array

当工具以 RETURN_BYTES 模式运行时,ResponseParserService 返回的 raw.bytes 在 Node.js 和浏览器环境中始终是普通的 Uint8Array。直接将其传递给 Transaction.fromBytes() 即可,无需手动转换。

const bytes = toolCall.parsedData.raw.bytes;
const tx = Transaction.fromBytes(bytes);

命名约定

元素约定示例
插件名称kebab-casemy-token-plugin
插件变量camelCasemyTokenPlugin
工具类PascalCase + ToolCreateTokenTool
工具常量UPPER_SNAKE_CASE + _TOOLCREATE_TOKEN_TOOL
工具方法值snake_case + _toolcreate_token_tool
工具文件kebab-casecreate-token.ts
工具名称导出项camelCase + ToolNamesmyTokenPluginToolNames

常见导入

// From @hashgraph/hedera-agent-kit (core)
import {
  Context,
  Plugin,
  BaseTool,
  handleTransaction,
  RawTransactionResponse,
  transactionToolOutputParser,
  untypedQueryOutputParser,
} from '@hashgraph/hedera-agent-kit';

// Built-in plugins live in the /plugins subpath
import { coreTokenPlugin, coreAccountPlugin } from '@hashgraph/hedera-agent-kit/plugins';

// Hedera SDK is a peer dependency
import { Client, Status } from '@hiero-ledger/sdk';

// For parameter validation
import { z } from 'zod';

其他资源

参考文件

如需了解详细模式和技巧,请参阅:

  • references/plugin-interface.md - 插件接口,以及 BaseTool 生命周期的深入介绍
  • references/zod-schema-patterns.md - Hedera 参数的常用 Zod schema
  • references/prompt-patterns.md - 工具描述的提示词生成模式
  • references/error-handling.md - 错误处理和输出解析模式
示例文件

examples/ 中的可运行示例:

  • examples/simple-plugin/ - 最简 BaseTool 查询(入门模板)
  • examples/token-plugin/ - 修改操作(CreateTokenTool)和查询(GetTokenInfoTool)的 BaseTool 子类

最佳实践

  1. 每个工具对应一个文件,文件名使用工具名称的 kebab-case
  2. 将相关工具分组到 tools/ 下的类别目录中
  3. 使用稳定的类名:<DoesWhat>Tool(例如,CreateTokenTool)
  4. 在 normalizeParams 中解析默认值,而不是在 coreAction 中——确保构建步骤保持纯粹
  5. 在 coreAction 中构建,不要提交——提交操作应放在 secondaryAction 中,以便钩子做出响应
  6. 重写 handleError,使日志带有工具方法标记
  7. 使用 Zod 的 .describe() 进行验证——每个字段都要验证;描述可为 Agent 提供指引
  8. 导出工具名称常量,以便使用方通过编程方式引用工具

向 Toolkit 注册插件

插件会显式传递给你选择的 toolkit。Toolkit 位于专用软件包中——请选择与你的框架匹配的软件包:

框架Toolkit 软件包
LangChain@hashgraph/hedera-agent-kit-langchain
Vercel AI SDK@hashgraph/hedera-agent-kit-ai-sdk
ElizaOS@hashgraph/hedera-agent-kit-elizaos
MCP@hashgraph/hedera-agent-kit-mcp

plugins 数组为空意味着没有任何工具。 显式列出所需的每个插件,或使用 /plugins 子路径中的 allCorePlugins 一次性加载所有内置核心插件。

import { Client, PrivateKey } from '@hiero-ledger/sdk';
import { AgentMode } from '@hashgraph/hedera-agent-kit';
import { coreTokenPlugin, coreAccountPlugin } from '@hashgraph/hedera-agent-kit/plugins';
import { HederaLangchainToolkit } from '@hashgraph/hedera-agent-kit-langchain';
import { myPlugin } from './my-hedera-plugin';

const client = Client.forTestnet().setOperator(
  process.env.ACCOUNT_ID!,
  PrivateKey.fromStringECDSA(process.env.PRIVATE_KEY!),
);

const toolkit = new HederaLangchainToolkit({
  client,
  configuration: {
    plugins: [coreTokenPlugin, coreAccountPlugin, myPlugin],
    context: { mode: AgentMode.AUTONOMOUS },
  },
});

const tools = toolkit.getTools();

若要一次性加载所有内置核心插件,请导入 allCorePlugins:

import { allCorePlugins } from '@hashgraph/hedera-agent-kit/plugins';
// ...
plugins: [...allCorePlugins, myPlugin],

工作流概要

  1. 创建插件目录,其中包含 index.ts 和 tools/ 子目录
  2. 为每个工具在单独的文件中编写一个 BaseTool 子类和工厂函数
  3. 在 index.ts 中导出工具及其工具名称常量
  4. 将插件传递到 toolkit 的 configuration.plugins 数组中
  5. 工具即可供 AI Agent 使用

完整的可运行示例请参阅 examples/ 目录。

评论

支持 Markdown