mcpField
H
Hedera Hook Creation

Hedera Hook Creation

github.com/hedera-devエージェントワークフロー28499 回インストール8 週間前に更新
リポジトリ

Hedera Hook Creation について

Hedera Hook Creationは、Hedera Agent Kit開発者向けに、BaseToolのライフサイクルで動く非ブロッキングフックの作成方法を説明するスキルです。フック段階や型付きパラメーター、Contextの状態、登録方法を扱い、呼び出しを止めるポリシーとの違いも示します。

主な機能

  1. 01BaseToolの4つのフック段階の説明
  2. 02AbstractHookとパラメーター型の解説
  3. 03フック登録とContext状態の例
  4. 04複数ツールの型処理パターン
  5. 05フックとポリシーの役割の区別

活用シーン

  1. 01ツール呼び出しのログと監査記録
  2. 02呼び出し回数やセッション状態の管理
  3. 03ツール実行時間の記録
  4. 04複数のツールメソッド向けフックの作成

インストール

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

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

インストール後、Claude Code で/hedera-hook-creationを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

examples/tx-timing-hook/
index.ts
references/
hook-interface.md
lifecycle.md

詳細

Hedera Agent Kit フックの作成

フックは BaseTool のライフサイクルを取り囲むように動作するノンブロッキングの拡張機能です。フックは実行を観察し、またそれを強化できます。呼び出しのログ記録、監査証跡の書き込み、メトリクスの追跡、Context への状態の永続化などが可能です。フックはツールの実行をブロックしません — それはポリシーの役割です(agent-kit-policy スキルを参照)。

フックは BaseTool を継承するツールに対してのみ発火します。BaseTool を継承せずに Tool インターフェースを直接実装するツールは、フックシステムを完全にバイパスします。

フックとポリシーのどちらを書くべきか

やりたいこと…使うもの
ツールの呼び出しをログ記録/監査/追跡するフック
Context を強化する(カウンター、セッション状態)フック
条件が成立したときに呼び出しを停止するポリシー(agent-kit-policy を参照)
特定のツールメソッドを拒否するポリシー

組み込みフックには HcsAuditTrailHook と HolAuditTrailHook(HCS ベースの監査証跡)があります — どちらも @hashgraph/hedera-agent-kit/hooks にあります。

7 段階のライフサイクル

BaseTool.execute() は次のように実行されます。

[1] preToolExecutionHook        ← hook fires
[2] normalizeParams             (tool internal)
[3] postParamsNormalizationHook ← hook fires
[4] coreAction                  (tool internal)
[5] postCoreActionHook          ← hook fires
[6] secondaryAction             (tool internal)
[7] postToolExecutionHook       ← hook fires

フックが接続するのはステージ 1、3、5、7 です。ステージ 2、4、6 では決して発火しません。

各ステージのパラメータの完全な形については references/lifecycle.md を参照してください。

AbstractHook の契約

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

export abstract class AbstractHook {
  abstract name: string;             // human-readable identifier
  abstract description?: string;     // what the hook does
  abstract relevantTools: string[];  // tool methods this hook cares about

  // Override only the stages you need; defaults are no-ops.
  preToolExecutionHook(params, method): Promise<any>;
  postParamsNormalizationHook(params, method): Promise<any>;
  postCoreActionHook(params, method): Promise<any>;
  postToolExecutionHook(params, method): Promise<any>;
}

重要: メソッドのシグネチャは (params, method) です — params は 4 つの型付きオブジェクトのいずれかであり、context はその内部に存在します(params.context)。独立した第 1 引数ではありません。

ステージパラメータの型注目すべきフィールド
1PreToolExecutionParamscontext、rawParams、client
3PostParamsNormalizationParams+ normalisedParams
5PostCoreActionParams+ coreActionResult
7PostSecondaryActionParams+ toolResult

スケルトン

import {
  AbstractHook,
  Context,
  PreToolExecutionParams,
  PostSecondaryActionParams,
} from '@hashgraph/hedera-agent-kit';

export class MyHook extends AbstractHook {
  name = 'My Hook';
  description = 'What this hook does, in one sentence';
  relevantTools = ['transfer_hbar', 'create_token'];

  async preToolExecutionHook(params: PreToolExecutionParams, method: string) {
    if (!this.relevantTools.includes(method)) return;
    // ... your pre-execution logic ...
    // params.context, params.rawParams, params.client
  }

  async postToolExecutionHook(params: PostSecondaryActionParams, method: string) {
    if (!this.relevantTools.includes(method)) return;
    // params.toolResult is the final tool output
  }
}

すべてのフックメソッドの最初の行では relevantTools でフィルタリングするべきです。キットはすべてのツール呼び出しに対してすべてのフックをディスパッチします — relevantTools は、それに基づいて動作しない限りは情報提供に過ぎません。

フックの登録

フックは Context.hooks に設定します。ツールキットはそのコンテキストを BaseTool.execute() まで引き渡し、そこでライフサイクルがフックをディスパッチします。

import { AgentMode } from '@hashgraph/hedera-agent-kit';
import { allCorePlugins } from '@hashgraph/hedera-agent-kit/plugins';
import { HederaLangchainToolkit } from '@hashgraph/hedera-agent-kit-langchain';
import { MyHook } from './my-hook';

const toolkit = new HederaLangchainToolkit({
  client,
  configuration: {
    plugins: allCorePlugins,
    context: {
      mode: AgentMode.AUTONOMOUS,
      hooks: [new MyHook()],
    },
  },
});

複数のフックを共存させることができます — それらは各ステージで配列の順序に従って実行されます。ポリシー(agent-kit-policy を参照)も AbstractHook のインスタンスであり、同じ配列に入ります。

複数ツールの型付けパターン

フックのパラメータはジェネリック(any)です — 1 つのフックが異なるスキーマを持つ多くのツールを対象にできるため、キットはツールごとの型を推論できません。3 つのパターンがあります。

1. 汎用ロジック

フックがパラメータに依存しない場合(呼び出し回数のカウント、ペイロード全体を JSON としてログ記録するなど)。

async postToolExecutionHook(params: PostSecondaryActionParams, method: string) {
  console.log(`[${method}]`, JSON.stringify(params.rawParams));
}
2. 型ガード(既知の小さな集合)

method で分岐し、キャストまたはガードで絞り込みます。

async postParamsNormalizationHook(
  params: PostParamsNormalizationParams,
  method: string,
) {
  switch (method) {
    case 'transfer_hbar':
    case 'transfer_hbar_with_allowance': {
      const p = params.normalisedParams as { transfers: Array<{ amount: number }> };
      const total = p.transfers.reduce((s, t) => s + t.amount, 0);
      console.log(`[${method}] total HBAR: ${total}`);
      break;
    }
  }
}
3. ストラテジーマップ(プラグイン可能、サードパーティ製ツール)

コンストラクタで Record<string, (params: any) => SomeResult> を受け取ります。各 additionalTool にストラテジーがあることを検証し、欠けている場合は構築時にスローします。これは MaxRecipientsPolicy で使われているパターンです。

Context 上の状態

params.context はエージェントの実行全体を通じて同じ Context インスタンスです。これをセッションごとのスクラッチパッドとして使います。

async preToolExecutionHook(params: PreToolExecutionParams, method: string) {
  if (!this.relevantTools.includes(method)) return;
  const counts = ((params.context as any).callCounts ??= {} as Record<string, number>);
  counts[method] = (counts[method] ?? 0) + 1;
}

(Context は構造的に型付けされています。アドホックな状態を付加するにはキャストします。フックを公開する場合は、書き込むキーを文書化してください。)

ベストプラクティス

  1. すべてのメソッドの先頭で relevantTools によりフィルタリングする — 低コストで慣用的です
  2. フックが I/O(HCS 書き込み、HTTP)を行う場合は try/catch で包む — フックがスローするとツール呼び出し全体が中断されます
  3. フックは軽量に保つ — ホットパス上に位置します
  4. ブロックしない — 実行を停止する必要がある場合は、ポリシーを書いてください
  5. 本当に意図しない限り rawParams や normalisedParams を変更しない — 後続のフックはあなたの変更を目にします
  6. description を使って副作用(HCS トピックへの書き込み、外部 API 呼び出し)を文書化する — ポリシーの作者やエージェントの運用者がフックの動作を把握できるようにします
  7. ログ行に [<hook-name>] のタグを付ける — grep しやすくなります

リソース

  • references/hook-interface.md — パラメータ型の完全な定義、4 つすべてのフックステージ
  • references/lifecycle.md — BaseTool の normalizeParams/coreAction/secondaryAction の前後で、何がいつ発火するか
  • examples/tx-timing-hook/ — ツールの実行時間を計測し、所要時間をログに記録する最小限のフック

一般的なインポート

import {
  AbstractHook,
  Context,
  PreToolExecutionParams,
  PostParamsNormalizationParams,
  PostCoreActionParams,
  PostSecondaryActionParams,
} from '@hashgraph/hedera-agent-kit';

// Built-in implementations live in the /hooks subpath
import { HcsAuditTrailHook, HolAuditTrailHook } from '@hashgraph/hedera-agent-kit/hooks';

コメント