MCPInstall

hedera policy creation

This skill should be used when the user asks to "create a hedera policy", "block a tool", "limit recipients", "extend AbstractPolicy", "reject a tool", "enforce a threshold", "rate limit a tool", "block transfers over X", "allowlist tools", or needs guidance on writing blocking validation rules for Hedera Agent Kit tools. Policies block tool execution by throwing — for non-blocking observation use the hook skill instead.

Installs
489
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

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

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads hedera policy creation automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Creating Hedera Agent Kit Policies

Policies are blocking validation rules layered on the BaseTool lifecycle. A policy checks the call at one or more stages and throws to abort execution — the error propagates back to the LLM agent. Use them to enforce thresholds, allowlists/blocklists, rate limits, business hours, compliance rules, etc.

Policies fire only for tools that extend BaseTool. A tool that implements the Tool interface directly without extending BaseTool bypasses policies entirely.

Policy vs. hook

GoalUse
Stop a call when a condition holdsPolicy (this skill)
Reject specific tool methodsPolicy
Threshold / rate-limit / allowlist / blocklistPolicy
Log, audit, enrich contextHook (see agent-kit-hook skill)

AbstractPolicy extends AbstractHook, so policies live in the same Context.hooks array and run through the same lifecycle.

Built-in policies live in @hashgraph/hedera-agent-kit/policies:

  • RejectToolPolicy(relevantTools: string[]) — blocks the listed tool methods unconditionally
  • MaxRecipientsPolicy(maxRecipients, additionalTools?, customStrategies?) — caps recipient count for transfer/airdrop tools

How blocking actually works

You never override preToolExecutionHook or any of the other *Hook methods on a policy — those are wired up by the base class to call your shouldBlock... method and throw if it returns true.

Override one or more of these instead:

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>;
}

Defaults all return false (allow). Returning true causes the base class to throw a generic block error. Throwing your own error from shouldBlock... lets you control the message.

Don't override preToolExecutionHook etc. — those are @internal on AbstractPolicy. They drive the block flow. If you override them, your policy will never block.

Picking the stage

StageWhat's availableGood for
shouldBlockPreToolExecutionrawParams onlyallowlist/blocklist by tool method, time-based, rate limits
shouldBlockPostParamsNormalization+ normalisedParamsthresholds on resolved values, recipient counts
shouldBlockPostCoreAction+ coreActionResultinspect the built Transaction before submission
shouldBlockPostSecondaryAction+ toolResultvery rare — call already executed; usually too late to "block"

Most policies live at stage 1 (cheapest) or stage 3 (after defaults are filled in).

Skeleton

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 is informational unless you check it — the kit dispatches your policy for every tool call. Always filter by method first thing in the method.

Registering policies

Policies are AbstractHook instances. They go in the same Context.hooks array as observation 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(),
      ],
    },
  },
});

Policies run in array order at each stage — the first one to return true (or throw) wins.

Common patterns

Threshold

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;
}

Allowlist / Blocklist

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);
}

Time-based

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
}

Rate limiting (uses Context as scratchpad)

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;
}

Strategy map (pluggable for custom tools)

When a single policy needs to support tools the kit doesn't know about, accept a Record<string, (params) => SomeMetric> and validate that every tool added via additionalTools has a strategy. This is the pattern of 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`);
    }
  }
}

Custom error messages

The default block error is generic. To control the message, throw from your shouldBlock... method instead of returning 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;
}

The agent receives the thrown message verbatim — make it informative.

Best practices

  1. Filter by relevantTools at the top of every shouldBlock... method
  2. Pick the earliest stage that has the data you need — stage 1 is cheapest
  3. Throw with a clear message when blocking; the LLM sees this
  4. Don't override *Hook methods — only shouldBlock...
  5. Don't do I/O on the hot path unless you must — policies run synchronously in the lifecycle
  6. Document relevantTools defaults so consumers understand what your policy guards
  7. Tag the error message with [<policy-name>] for easy log correlation

Resources

  • references/policy-interface.md — full AbstractPolicy contract, when each shouldBlock fires
  • examples/max-amount-policy/ — threshold policy that blocks transfers above a cap

Common imports

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';

FAQ

What does the hedera policy creation skill do?

This skill should be used when the user asks to "create a hedera policy", "block a tool", "limit recipients", "extend AbstractPolicy", "reject a tool", "enforce a threshold", "rate limit a tool", "block transfers over X", "allowlist tools", or needs guidance on writing blocking validation rules for Hedera Agent Kit tools. Policies block tool execution by throwing — for non-blocking observation use the hook skill instead.

How do I install hedera policy creation?

Run npx skills add https://github.com/hedera-dev/hedera-skills --skill hedera-policy-creation in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/hedera-policy-creation/ (personal) or .claude/skills/hedera-policy-creation/ (project).

Which AI agents can use hedera policy creation?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is hedera policy creation safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains hedera policy creation?

It is published by hedera-dev in hedera-dev/hedera-skills. It has 489 recorded installs.

More from hedera-dev/hedera-skills

View all →

This skill should be used when the user wants to validate, review, or score their Hedera hackathon submission before submitting. Triggered by phrases like "validate hackathon submission", "review my hackathon project", "hackathon scorecard", "check submission readiness", "score my hackathon", "submission review", "judge my project", "hackathon submission quality", or "improve hackathon score".

hedera hackathon prd

hedera-dev/hedera-skills

This skill should be used when the user wants to plan a Hedera hackathon project, create a PRD, write a project spec, brainstorm a hackathon idea, or structure their hackathon submission. Triggered by phrases like "hackathon project plan", "hackathon PRD", "plan my hackathon project", "hedera hackathon idea", "write a hackathon spec", "hackathon project structure", "prepare for hackathon", or "build for hackathon".

hedera-token-service

hedera-dev/hedera-skills

How to create, manage, and transfer tokens on Hedera using the Hiero JavaScript SDK (@hiero-ledger/sdk). Use this skill whenever the user wants to work with fungible tokens, NFTs, token creation, minting, burning, transfers, token association, custom fees (fixed, fractional, royalty), airdrops, KYC/freeze/wipe/pause operations, or any HTS (Hedera Token Service) operation in JavaScript or TypeScript. Also trigger when users mention @hashgraph/sdk token operations, ERC-20/ERC-721 equivalents on Hedera, or tokenization on the Hedera network.

hedera-consensus-service

hedera-dev/hedera-skills

How to create topics, submit messages, and subscribe to real-time message streams on Hedera using the Hiero JavaScript SDK (@hiero-ledger/sdk). Use this skill whenever the user wants to work with Hedera Consensus Service (HCS), including topic creation, message submission, pub/sub messaging, mirror node subscriptions, chunked large messages, topic fees, or any consensus-related operation in JavaScript or TypeScript. Also trigger when users mention @hashgraph/sdk topic operations, event logging on Hedera, decentralized messaging, audit trails, or ordered message streams.

DevOps & Cloud551 installs

project scaffolding

hedera-dev/hedera-skills

This skill should be used when the user wants to set up Claude for a project, create a CLAUDE.md file, scaffold the .claude directory, initialize an AI workflow, configure a project for Claude, set up dev intelligence, initialize a new project, or do a new project setup. Triggered by phrases like "set up claude for this project", "create CLAUDE.md", "scaffold .claude directory", "init AI workflow", "configure project for claude", "set up dev intelligence", "initialize project", "new project setup".

session management

hedera-dev/hedera-skills

This skill should be used when the user wants to resume previous work, continue from a last session, check what was being worked on, track completed work, log session activity, manage tech debt, review pending items, view session history, or maintain a work log. Triggered by phrases like "resume work", "continue from last session", "what was I working on", "track this work", "log what we did", "tech debt", "what's pending", "session history", "work log".

Popular docs & writing skills

View category →

grill-with-docs

mattpocock/skills

A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.

Docs & Writing1.2M installs

lark-markdown

open.feishu.cn

飞书 Markdown:查看、创建、上传、编辑和比较飞书中的原生 Markdown 文件。当用户要操作飞书 Markdown 文件,或比较其远端版本及本地草稿时使用。纯本地 Markdown 文件操作不触发本 skill。不负责将 Markdown 导入为飞书在线文档,也不负责文件搜索、权限、评论、移动、删除等云空间管理操作。

Docs & Writing778.7K installs

writing-beats

mattpocock/skills

Writing, exploit; assemble raw material into a journey of beats, grounding each term before a beat leans on it.

Docs & Writing490.7K installs

writing-shape

mattpocock/skills

Writing, exploit: shape raw material into an article, paragraph by paragraph.

Docs & Writing490.2K installs

writing-fragments

mattpocock/skills

Writing, explore: mine raw fragments, no structure yet.

Docs & Writing489.6K installs

writing-for-agents

mattpocock/skills

Writing documents for agents. Use when creating or editing skills, or modifying AGENTS.md or CLAUDE.md.

Docs & Writing479.3K installs