
agent-kit-plugin
This skill should be used when the user asks to "create a hedera plugin", "build a hedera agent kit plugin", "extend hedera agent kit", "create custom hedera tools", "add hedera functionality", "write a hedera tool", "implement hedera tool", or needs guidance on Hedera Agent Kit plugin architecture, tool definitions, mutation tools, query tools, or parameter schemas using Zod.
- Installs
- 477
- 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 agent-kit-plugin- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads agent-kit-plugin automatically when relevant.
- 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 Plugins
This skill provides guidance for creating custom plugins that extend the Hedera Agent Kit. Plugins allow adding new tools for Hedera network interactions—token operations, account management, consensus service, smart contracts, and custom integrations.
Quick Start
To create a Hedera plugin in 5 steps:
- Install dependencies: Set up a TypeScript project with
@hashgraph/hedera-agent-kitand@hiero-ledger/sdk - Create plugin structure: Create an
index.tswith the plugin definition and atools/directory - Define tools: Each tool is a class extending
BaseTool— this opts the tool into the hooks/policies lifecycle - Export properly: Export the plugin object and tool name constants
- Register with agent: Import and pass the plugin in the toolkit
configuration.pluginsarray
Plugin Interface
Every Hedera plugin implements this interface from @hashgraph/hedera-agent-kit:
import { Plugin } from '@hashgraph/hedera-agent-kit';
export interface Plugin {
name: string; // Unique kebab-case identifier
version?: string; // Semantic version (e.g., "1.0.0")
description?: string; // Brief explanation of plugin purpose
tools: (context: Context) => Tool[]; // Factory returning tools
}
The tools function receives a Context object containing network configuration and returns an array of Tool objects. BaseTool itself implements Tool, so a BaseTool subclass instance is a valid return value.
BaseTool
Tools are written as classes extending BaseTool, which implements Tool and runs a 7-stage lifecycle:
[1] preToolExecutionHook
[2] normalizeParams ← your logic
[3] postParamsNormalizationHook
[4] coreAction ← your logic
[5] postCoreActionHook
[6] secondaryAction ← your logic (skipped via shouldSecondaryAction for queries)
[7] postToolExecutionHook
Hooks and policies registered on the agent kit fire at stages 1, 3, 5, and 7 automatically — you never call them manually.
A subclass must provide:
| Member | Type | Notes |
|---|---|---|
method | string | Snake-case identifier with _tool suffix |
name | string | Human-readable display name |
description | string | LLM-facing description (typically built in the constructor from a prompt function) |
parameters | z.ZodObject | Zod schema for input validation |
normalizeParams(params, context, client) | async | Stage 2 — resolve defaults, validate format |
coreAction(normalised, context, client) | async | Stage 4 — build the transaction or perform the query |
secondaryAction(request, client, context) | async | Stage 6 — sign/submit the transaction (no-op for queries) |
Optional overrides: outputParser, shouldSecondaryAction (return false for query-only tools), handleError, and the four hook methods.
Tool Types
Mutation tools — state-changing operations (token create/mint/transfer, account update, topic submit). coreAction builds the Transaction, secondaryAction calls handleTransaction(). Use transactionToolOutputParser.
Query tools — read-only operations (token info, balances, mirror-node fetches). coreAction returns the result directly. Override shouldSecondaryAction to return false. Use untypedQueryOutputParser.
File Structure Pattern
Follow this structure for all Hedera plugins:
my-hedera-plugin/
├── index.ts # Plugin definition and exports
└── tools/
└── category/ # Group related tools
├── create-something.ts
└── get-something.ts
Creating a Tool
Step 1: Define the Tool Constant
export const MY_TOOL_NAME = 'my_tool_name_tool';
Use UPPER_SNAKE_CASE with _TOOL suffix for the constant. The value should be lowercase snake_case.
Step 2: Create the Prompt Function
const myToolPrompt = (context: Context = {}) => {
return `This tool does X on Hedera.
Parameters:
- param1 (str, required): Description of param1
- param2 (int, optional): Description of param2, defaults to 0`;
};
Step 3: Define Parameters with Zod
import { z } from 'zod';
const myToolParameters = (_context: Context = {}) => {
return z.object({
param1: z.string().describe('Description of param1'),
param2: z.number().optional().describe('Description of param2'),
});
};
type MyToolParams = z.infer<ReturnType<typeof myToolParameters>>;
See references/zod-schema-patterns.md for common Hedera parameter patterns.
Step 4: Implement the BaseTool subclass (mutation example)
import { Client, Status } from '@hiero-ledger/sdk';
import {
BaseTool,
Context,
handleTransaction,
RawTransactionResponse,
transactionToolOutputParser,
} from '@hashgraph/hedera-agent-kit';
const postProcess = (response: RawTransactionResponse) =>
`Operation completed.
Transaction ID: ${response.transactionId}`;
export class MyTool extends BaseTool<MyToolParams, MyToolParams> {
method = MY_TOOL_NAME;
name = 'My Tool Display Name';
description: string;
parameters: ReturnType<typeof myToolParameters>;
outputParser = transactionToolOutputParser;
constructor(context: Context) {
super();
this.description = myToolPrompt(context);
this.parameters = myToolParameters(context);
}
// Stage 2 — resolve defaults
async normalizeParams(params: MyToolParams) {
return params;
}
// Stage 4 — build the transaction (do not sign here)
async coreAction(params: MyToolParams, _context: Context, _client: Client) {
// return new SomeTransaction()...;
return undefined as any;
}
// Stage 6 — sign and submit
async secondaryAction(transaction: any, client: Client, context: Context) {
return handleTransaction(transaction, client, context, postProcess);
}
async handleError(error: unknown) {
const message = 'Failed to execute' + (error instanceof Error ? `: ${error.message}` : '');
console.error(`[${MY_TOOL_NAME}]`, message);
return { raw: { status: Status.InvalidTransaction, error: message }, humanMessage: message };
}
}
Step 5: Export a Factory
const tool = (context: Context): BaseTool => new MyTool(context);
export default tool;
The factory pattern lets the plugin's tools(context) function instantiate a fresh tool per request with the right context bound.
Query-tool variant — skip stage 6
For read-only tools, override shouldSecondaryAction so the lifecycle stops after coreAction, and have secondaryAction pass the result through unchanged:
export class MyQueryTool extends BaseTool<MyToolParams, MyToolParams> {
// ... method/name/description/parameters as above ...
outputParser = untypedQueryOutputParser;
async normalizeParams(params: MyToolParams) {
return params;
}
async coreAction(params: MyToolParams, _context: Context, client: Client) {
return await someHederaQuery(params, client);
}
async shouldSecondaryAction() {
return false;
}
async secondaryAction(result: any) {
return result;
}
}
Creating the Plugin Index
import { Context, Plugin } from '@hashgraph/hedera-agent-kit';
import myTool, { MY_TOOL_NAME } from './tools/category/my-tool';
export const myPlugin: Plugin = {
name: 'my-hedera-plugin',
version: '1.0.0',
description: 'A plugin for custom Hedera operations',
tools: (context: Context) => {
return [
myTool(context),
];
},
};
export const myPluginToolNames = {
MY_TOOL_NAME,
} as const;
export default { myPlugin, myPluginToolNames };
Post-Processing Results
secondaryAction typically delegates to handleTransaction, which calls a postProcess function with the raw transaction response:
const postProcess = (response: RawTransactionResponse) => {
if (response.scheduleId) {
return `Scheduled transaction created.
Transaction ID: ${response.transactionId}
Schedule ID: ${response.scheduleId.toString()}`;
}
return `Operation completed.
Transaction ID: ${response.transactionId}`;
};
RETURN_BYTES mode — raw.bytes is a Uint8Array
When a tool runs in RETURN_BYTES mode, raw.bytes returned by ResponseParserService is always a plain Uint8Array in both Node.js and browser environments. Pass it directly to Transaction.fromBytes() — no manual conversion is needed.
const bytes = toolCall.parsedData.raw.bytes;
const tx = Transaction.fromBytes(bytes);
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Plugin name | kebab-case | my-token-plugin |
| Plugin variable | camelCase | myTokenPlugin |
| Tool class | PascalCase + Tool | CreateTokenTool |
| Tool constant | UPPER_SNAKE_CASE + _TOOL | CREATE_TOKEN_TOOL |
| Tool method value | snake_case + _tool | create_token_tool |
| Tool file | kebab-case | create-token.ts |
| Tool names export | camelCase + ToolNames | myTokenPluginToolNames |
Common Imports
// From @hashgraph/hedera-agent-kit (core)
import {
Context,
Plugin,
BaseTool,
handleTransaction,
RawTransactionResponse,
transactionToolOutputParser,
untypedQueryOutputParser,
} from '@hashgraph/hedera-agent-kit';
// Built-in plugins live in the /plugins subpath
import { coreTokenPlugin, coreAccountPlugin } from '@hashgraph/hedera-agent-kit/plugins';
// Hedera SDK is a peer dependency
import { Client, Status } from '@hiero-ledger/sdk';
// For parameter validation
import { z } from 'zod';
Additional Resources
Reference Files
For detailed patterns and techniques, consult:
references/plugin-interface.md- Plugin interface,BaseToollifecycle in depthreferences/zod-schema-patterns.md- Common Zod schemas for Hedera parametersreferences/prompt-patterns.md- Prompt generation patterns for tool descriptionsreferences/error-handling.md- Error handling and output parsing patterns
Example Files
Working examples in examples/:
examples/simple-plugin/- MinimalBaseToolquery (starter template)examples/token-plugin/- Mutation (CreateTokenTool) and query (GetTokenInfoTool)BaseToolsubclasses
Best Practices
- One file per tool, named after the tool in kebab-case
- Group related tools under category directories in
tools/ - Stable class names:
<DoesWhat>Tool(e.g.,CreateTokenTool) - Resolve defaults in
normalizeParams, not incoreAction— keeps the build step pure - Build, don't submit, in
coreAction— submission belongs insecondaryActionwhere hooks can react - Override
handleErrorso logs are tagged with the tool method - Validate with Zod's
.describe()— every field; descriptions guide the agent - Export tool name constants so consumers can reference tools programmatically
Registering a Plugin with a Toolkit
Plugins are passed explicitly to the toolkit you choose. Toolkits live in dedicated packages — pick the one that matches your framework:
| Framework | Toolkit package |
|---|---|
| LangChain | @hashgraph/hedera-agent-kit-langchain |
| Vercel AI SDK | @hashgraph/hedera-agent-kit-ai-sdk |
| ElizaOS | @hashgraph/hedera-agent-kit-elizaos |
| MCP | @hashgraph/hedera-agent-kit-mcp |
Empty
pluginsarray means zero tools. List every plugin you need explicitly, or useallCorePluginsfrom the/pluginssubpath to load every built-in core plugin at once.
import { Client, PrivateKey } from '@hiero-ledger/sdk';
import { AgentMode } from '@hashgraph/hedera-agent-kit';
import { coreTokenPlugin, coreAccountPlugin } from '@hashgraph/hedera-agent-kit/plugins';
import { HederaLangchainToolkit } from '@hashgraph/hedera-agent-kit-langchain';
import { myPlugin } from './my-hedera-plugin';
const client = Client.forTestnet().setOperator(
process.env.ACCOUNT_ID!,
PrivateKey.fromStringECDSA(process.env.PRIVATE_KEY!),
);
const toolkit = new HederaLangchainToolkit({
client,
configuration: {
plugins: [coreTokenPlugin, coreAccountPlugin, myPlugin],
context: { mode: AgentMode.AUTONOMOUS },
},
});
const tools = toolkit.getTools();
To load every built-in core plugin at once, import allCorePlugins:
import { allCorePlugins } from '@hashgraph/hedera-agent-kit/plugins';
// ...
plugins: [...allCorePlugins, myPlugin],
Workflow Summary
- Create plugin directory with
index.tsandtools/subdirectory - For each tool, write a
BaseToolsubclass and a factory function in its own file - Export tools from
index.tsalong with tool name constants - Pass the plugin in the toolkit's
configuration.pluginsarray - Tools become available to the AI agent
For complete working examples, see the examples/ directory.
FAQ
What does the agent-kit-plugin skill do?
This skill should be used when the user asks to "create a hedera plugin", "build a hedera agent kit plugin", "extend hedera agent kit", "create custom hedera tools", "add hedera functionality", "write a hedera tool", "implement hedera tool", or needs guidance on Hedera Agent Kit plugin architecture, tool definitions, mutation tools, query tools, or parameter schemas using Zod.
How do I install agent-kit-plugin?
Run npx skills add https://github.com/hedera-dev/hedera-skills --skill agent-kit-plugin 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/agent-kit-plugin/ (personal) or .claude/skills/agent-kit-plugin/ (project).
Which AI agents can use agent-kit-plugin?
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 agent-kit-plugin 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 agent-kit-plugin?
It is published by hedera-dev in hedera-dev/hedera-skills. It has 477 recorded installs.
More from hedera-dev/hedera-skills
hedera hackathon submission validator
hedera-dev/hedera-skills
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.
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 code quality & workflow skills
grill-me
mattpocock/skills
A relentless interview to sharpen a plan or design.
improve-codebase-architecture
mattpocock/skills
Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.
handoff
mattpocock/skills
Compact the current conversation into a handoff document for another agent to pick up.
domain-modeling
mattpocock/skills
Build and sharpen a project's domain model. Use when discussing codebase terminology, writing or editing a GLOSSARY.md, or recording or editing an ADR.
codebase-design
mattpocock/skills
Shared vocabulary for designing deep modules. Use when the user wants to design or improve a module's interface, find deepening opportunities, decide where a seam goes, make code more testable or AI-navigable, or when another skill needs the deep-module vocabulary.
diagnosing-bugs
mattpocock/skills
Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.