关于 Hedera Policy Creation
Hedera Policy Creation 是面向 Hedera Agent Kit 开发者的技能,介绍如何编写可阻止工具调用的策略。它说明策略生命周期阶段、内置策略、注册方式及阈值、限流和名单控制等实现模式。
主要功能
- 01基于 AbstractPolicy 编写阻止规则
- 02在工具执行生命周期阶段检查调用
- 03实现阈值、名单与时间限制
- 04使用 Context 实现会话限流
- 05将策略注册到 Context.hooks
- 06自定义阻止错误信息
适用场景
- 01限制转账或空投的接收者数量
- 02按额度阻止工具调用
- 03限制指定工具或账户
- 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 会原样收到抛出的消息——请确保消息内容清晰且有帮助。
最佳实践
- 在每个
shouldBlock...方法开头按relevantTools进行筛选 - 选择包含所需数据的最早阶段——阶段 1 的开销最低
- 阻止操作时抛出清晰的错误信息;大模型会看到此信息
- 不要重写
*Hook方法——只重写shouldBlock...方法 - 除非必要,否则不要在关键路径上执行 I/O——策略会在生命周期中同步运行
- 说明
relevantTools的默认值,让使用者了解策略保护的对象 - 在错误信息中添加
[<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';