mcpField
H
Hedera Plugin Creation

Hedera Plugin Creation

github.com/hedera-dev開発2889 回インストール8 週間前に更新
リポジトリ

Hedera Plugin Creation について

Hedera Plugin Creation は、Hedera Agent Kit 向けのカスタムプラグイン開発を支援するスキルです。ツールの定義やライフサイクルの実装、MCP ツールキットを含むツールキットへの登録方法を説明します。

主な機能

  1. 01プラグイン構成とエクスポート
  2. 02BaseTool のライフサイクルガイド
  3. 03Zod によるパラメーター検証
  4. 04クエリと変更ツールのパターン
  5. 05ツールキットへのプラグイン登録
  6. 06参考パターンとサンプル

活用シーン

  1. 01カスタム Hedera トークンツールの作成
  2. 02読み取り専用 Hedera クエリの実装
  3. 03エージェントツールキットへのプラグイン登録

MCP 対応

`@hashgraph/hedera-agent-kit-mcp` への Hedera Agent Kit プラグインの登録方法を説明します。選択したツールキットを通じて、プラグインのツールを AI エージェントに提供します。

インストール

コマンドをコピーしてターミナルで実行します。

$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. エージェントに登録する:プラグインをインポートし、ツールキットの 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

ツールは Tool を実装する BaseTool を拡張したクラスとして記述し、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

エージェントキットに登録されたフックとポリシーは、ステージ 1、3、5、7 で自動的に実行されます。手動で呼び出す必要はありません。

サブクラスでは、次の項目を定義する必要があります。

メンバー型説明
methodstring_tool サフィックスが付いたスネークケースの識別子
namestring人が読める表示名
descriptionstringLLM 向けの説明(通常はコンストラクターでプロンプト関数から作成します)
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、および 4 つのフックメソッド。

ツールの種類

ミューテーションツール — 状態を変更する操作(トークンの作成/ミント/転送、アカウントの更新、トピックへの送信)。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 スキーマ
  • references/prompt-patterns.md - ツールの説明向けプロンプト生成パターン
  • references/error-handling.md - エラー処理と出力解析のパターン
サンプルファイル

examples/ にある実用的なサンプル:

  • examples/simple-plugin/ - 最小構成の BaseTool クエリ(スターターテンプレート)
  • examples/token-plugin/ - 変更(CreateTokenTool)およびクエリ(GetTokenInfoTool)の BaseTool サブクラス

ベストプラクティス

  1. ツールごとにファイルを1つ作成し、ツール名に基づいた kebab-case で命名します
  2. 関連するツールはグループ化し、tools/ 内のカテゴリーディレクトリにまとめます
  3. クラス名は安定した形式にします:<DoesWhat>Tool(例:CreateTokenTool)
  4. デフォルト値は coreAction ではなく normalizeParams で解決します — ビルドステップを純粋に保てます
  5. coreAction では送信せず、ビルドします — 送信は、フックが反応できる secondaryAction で行います
  6. handleError をオーバーライドし、ログにツールメソッドのタグが付くようにします
  7. Zod の .describe() で検証します — すべてのフィールドに設定し、説明がエージェントの指針となるようにします
  8. ツール名の定数をエクスポートし、利用側がツールをプログラムから参照できるようにします

ツールキットへのプラグインの登録

プラグインは、選択したツールキットに明示的に渡します。ツールキットは専用パッケージとして提供されています。使用するフレームワークに合ったものを選んでください。

フレームワークツールキットパッケージ
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 配列が空の場合、ツールは1つもありません。 必要なプラグインをすべて明示的に指定するか、/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. ツールキットの configuration.plugins 配列にプラグインを渡します
  5. ツールが AI エージェントから利用できるようになります

実用的なサンプル全体については、examples/ ディレクトリを参照してください。

コメント