mcpField
H
Hedera Policy Creation

Hedera Policy Creation

github.com/hedera-dev安全28500 次安装8 周前更新
代码仓库

关于 Hedera Policy Creation

Hedera Policy Creation 是面向 Hedera Agent Kit 开发者的技能,介绍如何编写可阻止工具调用的策略。它说明策略生命周期阶段、内置策略、注册方式及阈值、限流和名单控制等实现模式。

主要功能

  1. 01基于 AbstractPolicy 编写阻止规则
  2. 02在工具执行生命周期阶段检查调用
  3. 03实现阈值、名单与时间限制
  4. 04使用 Context 实现会话限流
  5. 05将策略注册到 Context.hooks
  6. 06自定义阻止错误信息

适用场景

  1. 01限制转账或空投的接收者数量
  2. 02按额度阻止工具调用
  3. 03限制指定工具或账户
  4. 04按营业时间或会话调用次数控制操作

安装

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

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

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

附带文件examples/max-amount-policy/index.tsreferences/policy-interface.md

详细介绍

创建 Hedera Agent Kit 策略

策略是在 BaseTool 生命周期中分层应用的阻止型验证规则。策略会在一个或多个阶段检查调用,并通过 抛出异常 中止执行——错误会传回 LLM Agent。可使用策略强制执行阈值、允许列表/阻止列表、速率限制、营业时间、合规规则等。

策略 仅 对扩展 BaseTool 的工具生效。直接实现 Tool 接口而不扩展 BaseTool 的工具会完全绕过策略。

策略与钩子的区别

目标使用
条件成立时停止调用策略(本技能)
拒绝特定工具方法策略
阈值/速率限制/允许列表/阻止列表策略
记录日志、审计、丰富上下文钩子(参见 agent-kit-hook 技能)

AbstractPolicy 扩展了 AbstractHook,因此策略位于同一个 Context.hooks 数组中,并经过相同的生命周期。

内置策略位于 @hashgraph/hedera-agent-kit/policies:

  • RejectToolPolicy(relevantTools: string[]) — 无条件阻止列出的工具方法
  • MaxRecipientsPolicy(maxRecipients, additionalTools?, customStrategies?) — 限制转账/空投工具的收款人数

阻止的实际工作方式

你 不应 在策略中重写 preToolExecutionHook 或任何其他 *Hook 方法——基类会将这些方法接入你的 shouldBlock... 方法,并在其返回 true 时抛出异常。

应改为重写以下一个或多个方法:

abstract class AbstractPolicy extends AbstractHook {
  abstract name: string;
  abstract description?: string;
  abstract relevantTools: string[];

  protected shouldBlockPreToolExecution(params, method): boolean | Promise<boolean>;
  protected shouldBlockPostParamsNormalization(params, method): boolean | Promise<boolean>;
  protected shouldBlockPostCoreAction(params, method): boolean | Promise<boolean>;
  protected shouldBlockPostSecondaryAction(params, method): boolean | Promise<boolean>;
}

默认情况下,这些方法都会返回 false(允许)。返回 true 会导致基类抛出通用阻止错误。从 shouldBlock... 抛出自定义错误,则可以控制错误消息。

不要重写 preToolExecutionHook 等方法。——这些方法在 AbstractPolicy 中标记为 @internal,负责驱动阻止流程。如果重写它们,策略将永远无法阻止调用。

选择阶段

阶段可用内容适用场景
shouldBlockPreToolExecution仅 rawParams按工具方法设置允许列表/阻止列表、基于时间的规则、速率限制
shouldBlockPostParamsNormalization+ normalisedParams对解析后的值进行阈值检查、检查收款人数
shouldBlockPostCoreAction+ coreActionResult在提交前检查构建好的 Transaction
shouldBlockPostSecondaryAction+ toolResult极少使用——调用已执行,通常已来不及“阻止”

大多数策略位于阶段 1(开销最低)或阶段 3(默认值已填充后)。

骨架

import {
  AbstractPolicy,
  PreToolExecutionParams,
  PostParamsNormalizationParams,
} from '@hashgraph/hedera-agent-kit';

export class MyPolicy extends AbstractPolicy {
  name = 'My Policy';
  description = 'What this policy blocks, in one sentence';
  relevantTools = ['transfer_hbar', 'transfer_fungible_token'];

  // Stage 1 — block by raw input or method
  protected shouldBlockPreToolExecution(
    params: PreToolExecutionParams,
    method: string,
  ): boolean {
    if (!this.relevantTools.includes(method)) return false;
    // throw new Error('<custom message>') for tailored errors
    return /* condition */ false;
  }

  // Stage 3 — block on resolved/normalised values
  protected shouldBlockPostParamsNormalization(
    params: PostParamsNormalizationParams,
    method: string,
  ): boolean {
    if (!this.relevantTools.includes(method)) return false;
    return /* condition */ false;
  }
}

除非你主动检查,否则 relevantTools 仅供参考——工具包会针对每次工具调用分派策略。务必在方法开头先按 method 进行筛选。

注册策略

策略是 AbstractHook 实例。它们与观察钩子一样,放入同一个 Context.hooks 数组中:

import { AgentMode } from '@hashgraph/hedera-agent-kit';
import { allCorePlugins } from '@hashgraph/hedera-agent-kit/plugins';
import { RejectToolPolicy, MaxRecipientsPolicy } from '@hashgraph/hedera-agent-kit/policies';
import { HederaLangchainToolkit } from '@hashgraph/hedera-agent-kit-langchain';
import { MyPolicy } from './my-policy';

const toolkit = new HederaLangchainToolkit({
  client,
  configuration: {
    plugins: allCorePlugins,
    context: {
      mode: AgentMode.AUTONOMOUS,
      hooks: [
        new RejectToolPolicy(['delete_account', 'freeze_token']),
        new MaxRecipientsPolicy(5),
        new MyPolicy(),
      ],
    },
  },
});

策略在每个阶段按数组顺序运行——第一个返回 true(或抛出异常)的策略会生效。

常见模式

阈值
protected shouldBlockPostParamsNormalization(
  params: PostParamsNormalizationParams,
  method: string,
): boolean {
  if (!this.relevantTools.includes(method)) return false;
  const p = params.normalisedParams as { amount?: number };
  return (p.amount ?? 0) > this.maxAmount;
}
允许列表/阻止列表
protected shouldBlockPreToolExecution(
  params: PreToolExecutionParams,
  method: string,
): boolean {
  if (!this.relevantTools.includes(method)) return false;
  const accountId = (params.rawParams as { accountId?: string }).accountId;
  return accountId !== undefined && this.blockedAccounts.has(accountId);
}
基于时间
protected shouldBlockPreToolExecution(
  _params: PreToolExecutionParams,
  method: string,
): boolean {
  if (!this.relevantTools.includes(method)) return false;
  const hour = new Date().getUTCHours();
  return hour < 9 || hour > 17;  // outside business hours
}
速率限制(使用 Context 作为临时存储)
protected shouldBlockPreToolExecution(
  params: PreToolExecutionParams,
  method: string,
): boolean {
  if (!this.relevantTools.includes(method)) return false;
  const counters = ((params.context as any).__rateCounts ??= {} as Record<string, number>);
  counters[method] = (counters[method] ?? 0) + 1;
  return counters[method] > this.maxCallsPerSession;
}
策略映射(可插拔地支持自定义工具)

如果单个策略需要支持工具包不了解的工具,可接受一个 Record<string, (params) => SomeMetric>,并验证通过 additionalTools 添加的每个工具都有对应策略。这是 MaxRecipientsPolicy 使用的模式:

constructor(
  private maxRecipients: number,
  additionalTools: string[] = [],
  private customStrategies: Record<string, (p: any) => number> = {},
) {
  super();
  this.relevantTools = [...DEFAULT_TOOLS, ...additionalTools];
  for (const tool of additionalTools) {
    if (!this.customStrategies[tool]) {
      throw new Error(`Custom tool "${tool}" requires a strategy function`);
    }
  }
}

自定义错误消息

默认的阻止错误较为通用。要控制错误消息,请在 shouldBlock... 方法中 抛出异常,而不是返回 true:

protected shouldBlockPostParamsNormalization(
  params: PostParamsNormalizationParams,
  method: string,
): boolean {
  if (!this.relevantTools.includes(method)) return false;
  const p = params.normalisedParams as { amount?: number };
  if ((p.amount ?? 0) > this.maxAmount) {
    throw new Error(
      `[max-amount-policy] Refusing ${method}: amount ${p.amount} exceeds limit ${this.maxAmount}`,
    );
  }
  return false;
}

Agent 会原样收到抛出的消息——请确保消息内容清晰且有帮助。

最佳实践

  1. 在每个 shouldBlock... 方法开头按 relevantTools 进行筛选
  2. 选择包含所需数据的最早阶段——阶段 1 的开销最低
  3. 阻止操作时抛出清晰的错误信息;大模型会看到此信息
  4. 不要重写 *Hook 方法——只重写 shouldBlock... 方法
  5. 除非必要,否则不要在关键路径上执行 I/O——策略会在生命周期中同步运行
  6. 说明 relevantTools 的默认值,让使用者了解策略保护的对象
  7. 在错误信息中添加 [<policy-name>] 标签,便于关联日志

资源

  • references/policy-interface.md — 完整的 AbstractPolicy 契约,以及各个 shouldBlock 方法的触发时机
  • examples/max-amount-policy/ — 超过上限时阻止转账的阈值策略

常见导入

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

// Built-in implementations live in the /policies subpath
import { RejectToolPolicy, MaxRecipientsPolicy } from '@hashgraph/hedera-agent-kit/policies';

评论

支持 Markdown