Loading...
Loading...
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.
npx skill4agent add hedera-dev/hedera-skills agent-kit-plugin@hashgraph/hedera-agent-kit@hiero-ledger/sdkindex.tstools/BaseToolconfiguration.plugins@hashgraph/hedera-agent-kitimport { 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
}toolsContextToolBaseToolToolBaseToolBaseToolBaseToolTool[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| Member | Type | Notes |
|---|---|---|
| | Snake-case identifier with |
| | Human-readable display name |
| | LLM-facing description (typically built in the constructor from a prompt function) |
| | Zod schema for input validation |
| async | Stage 2 — resolve defaults, validate format |
| async | Stage 4 — build the transaction or perform the query |
| async | Stage 6 — sign/submit the transaction (no-op for queries) |
outputParsershouldSecondaryActionfalsehandleErrorcoreActionTransactionsecondaryActionhandleTransaction()transactionToolOutputParsercoreActionshouldSecondaryActionfalseuntypedQueryOutputParsermy-hedera-plugin/
├── index.ts # Plugin definition and exports
└── tools/
└── category/ # Group related tools
├── create-something.ts
└── get-something.tsexport const MY_TOOL_NAME = 'my_tool_name_tool';_TOOLconst 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`;
};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>>;references/zod-schema-patterns.mdimport { 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 };
}
}const tool = (context: Context): BaseTool => new MyTool(context);
export default tool;tools(context)shouldSecondaryActioncoreActionsecondaryActionexport 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;
}
}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 };secondaryActionhandleTransactionpostProcessconst 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_BYTESraw.bytesUint8ArrayRETURN_BYTESraw.bytesResponseParserServiceUint8ArrayTransaction.fromBytes()const bytes = toolCall.parsedData.raw.bytes;
const tx = Transaction.fromBytes(bytes);| Element | Convention | Example |
|---|---|---|
| Plugin name | kebab-case | |
| Plugin variable | camelCase | |
| Tool class | PascalCase + | |
| Tool constant | UPPER_SNAKE_CASE + | |
| Tool method value | snake_case + | |
| Tool file | kebab-case | |
| Tool names export | camelCase + | |
// 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';references/plugin-interface.mdBaseToolreferences/zod-schema-patterns.mdreferences/prompt-patterns.mdreferences/error-handling.mdexamples/examples/simple-plugin/BaseToolexamples/token-plugin/CreateTokenToolGetTokenInfoToolBaseTooltools/<DoesWhat>ToolCreateTokenToolnormalizeParamscoreActioncoreActionsecondaryActionhandleError.describe()| Framework | Toolkit package |
|---|---|
| LangChain | |
| Vercel AI SDK | |
| ElizaOS | |
| MCP | |
Emptyarray means zero tools. List every plugin you need explicitly, or usepluginsfrom theallCorePluginssubpath to load every built-in core plugin at once./plugins
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();allCorePluginsimport { allCorePlugins } from '@hashgraph/hedera-agent-kit/plugins';
// ...
plugins: [...allCorePlugins, myPlugin],index.tstools/BaseToolindex.tsconfiguration.pluginsexamples/