mcpField
H
Hedera Hook Creation

Hedera Hook Creation

github.com/hedera-devAgent 工作流28499 次安装8 周前更新
代码仓库

关于 Hedera Hook Creation

Hedera Hook Creation 是面向 Hedera Agent Kit 开发者的技能,指导创建围绕 BaseTool 生命周期运行的非阻塞钩子。内容涵盖生命周期阶段、类型化参数、Context 状态和注册方式,并区分钩子与用于阻止调用的策略。

主要功能

  1. 01说明 BaseTool 的四个钩子阶段
  2. 02介绍 AbstractHook 接口与参数类型
  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 skill)。

钩子仅对扩展 BaseTool 的工具触发。直接实现 Tool 接口而不扩展 BaseTool 的工具会完全绕过钩子系统。

何时编写钩子,何时编写策略

如果你想……使用
记录/审计/跟踪工具调用钩子
丰富 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 是四种类型化对象之一,而 context 位于其中(params.context)。它不是单独的第一个参数。

阶段参数类型重要字段
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. 通用逻辑

当钩子与参数无关时(例如统计调用次数、将整个负载记录为 JSON):

async postToolExecutionHook(params: PostSecondaryActionParams, method: string) {
  console.log(`[${method}]`, JSON.stringify(params.rawParams));
}
2. 类型守卫(少量已知集合)

根据 method 使用 switch 分支,并通过类型断言或守卫缩小类型范围:

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 上的状态

整个 Agent 运行期间,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 调用),以便策略作者/Agent 操作者了解钩子的作用
  7. 为日志行添加标签 [<hook-name>],便于使用 grep 查找

资源

  • references/hook-interface.md — 完整的参数类型定义,以及全部四个钩子阶段
  • 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';

评论

支持 Markdown