Documentation Index
Fetch the complete documentation index at: https://hedera-0c6e0218-chore-hide-placeholder-pages.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Summary
Available Third-Party Plugins
- Memejob Plugin provides a streamlined interface to the memejob protocol, exposing the core actions (
create, buy, sell) for interacting with meme tokens on Hedera. See the GitHub repository for more information.
Plugin Architecture
The tools are organized into plugins, each containing a set of functionality related to the Hedera service or project they are created for.
Plugin Interface
Every plugin must implement the Plugin interface:
export interface Plugin {
name: string;
version?: string;
description?: string;
tools: (context: Context) => Tool[];
}
Each tool must implement the Tool interface:
export type Tool = {
method: string;
name: string;
description: string;
parameters: z.ZodObject<any, any>;
execute: (client: Client, context: Context, params: any) => Promise<any>;
// transactionToolOutputParser and untypedQueryOutputParser can be used. If required, define a custom parser
outputParser?: (rawOutput: string) => { raw: any; humanMessage: string };
};
Note: The outputParser is important for LangChain v1 tools. It extracts tool output into { raw, humanMessage } format. Two built-in parsers are available:
transactionToolOutputParser - For transaction tools (handles RETURN_BYTES and EXECUTE_TRANSACTION modes)
untypedQueryOutputParser - For query tools (generic parser)
If not defined, a default parser is used.
See typescript/src/shared/tools.ts for the full definition.
Step-by-Step Guide
Step 1: Create Plugin Directory Structure
my-custom-plugin/
├── index.ts # Plugin definition and exports
├── tools/
│ └── my-service/
│ └── my-tool.ts # Individual tool implementation
Create your tool file (e.g., tools/my-service/my-tool.ts):
import { z } from 'zod';
import { Context, Tool, handleTransaction } from 'hedera-agent-kit';
import { Client, PrivateKey, AccountId } from '@hashgraph/sdk';
import dotenv from 'dotenv';
// Load environment variables
dotenv.config();
// Define parameter schema
const myToolParameters = (context: Context = {}) =>
z.object({
requiredParam: z.string().describe('Description of required parameter'),
optionalParam: z.string().optional().describe('Description of optional parameter'),
});
// Create prompt function
const myToolPrompt = (context: Context = {}) => {
return `
This tool performs a specific operation.
Parameters:
- requiredParam (string, required): Description
- optionalParam (string, optional): Description
`;
};
// Implement tool logic
const myToolExecute = async (
client: Client,
context: Context,
params: z.infer<ReturnType<typeof myToolParameters>>,
) => {
try {
// Your implementation here
const result = await someHederaOperation(params);
return result;
} catch (error) {
if (error instanceof Error) {
return error.message;
}
return 'Operation failed';
}
};
export const MY_TOOL = 'my_tool';
const tool = (context: Context): Tool => ({
method: MY_TOOL,
name: 'My Custom Tool',
description: myToolPrompt(context),
parameters: myToolParameters(context),
execute: myToolExecute,
});
export default tool;
Step 3: Create Plugin Definition
Create your plugin index file (index.ts):
import { Context } from '@/shared';
import { Plugin } from '@/shared/plugin';
import myTool, { MY_TOOL } from './tools/my-service/my-tool';
export const myCustomPlugin: Plugin = {
name: 'my-custom-plugin',
version: '1.0.0',
description: 'A plugin for custom functionality',
tools: (context: Context) => {
return [myTool(context)];
},
};
export const myCustomPluginToolNames = {
MY_TOOL,
} as const;
export default { myCustomPlugin, myCustomPluginToolNames };
Step 4: Register Your Plugin
Add your plugin to the main plugins index (src/plugins/index.ts):
import { myCustomPlugin, myCustomPluginToolNames } from './my-custom-plugin';
export {
// ... existing exports
myCustomPlugin,
myCustomPluginToolNames,
};
Best Practices
Parameter Validation
- Use Zod schemas for robust input validation
- Provide clear descriptions for all parameters
- Mark required vs optional parameters appropriately
Tool Organization
- Group related tools by service type
- Use consistent naming conventions
- Follow the established directory structure
Transaction Handling
- Use handleTransaction() to facilitate human-in-the-loop and autonomous execution flows
- Respect the AgentMode (AUTONOMOUS vs. RETURN_BYTES)
- Implement proper transaction building patterns
Using Your Custom Plugin
LangChain v0.3 (Classic)
import { HederaLangchainToolkit } from "hedera-agent-kit";
import {
myCustomPlugin,
myCustomPluginToolNames,
} from "./plugins/my-custom-plugin";
const toolkit = new HederaLangchainToolkit({
client,
configuration: {
tools: [myCustomPluginToolNames.MY_TOOL],
plugins: [myCustomPlugin],
context: {
mode: AgentMode.AUTONOMOUS,
},
},
});
LangChain v1 (New)
import { HederaLangchainToolkit, ResponseParserService } from "hedera-agent-kit";
import {
myCustomPlugin,
myCustomPluginToolNames,
} from "./plugins/my-custom-plugin";
// Initialize toolkit
const toolkit = new HederaLangchainToolkit({
client,
configuration: {
tools: [myCustomPluginToolNames.MY_TOOL],
plugins: [myCustomPlugin],
context: {
mode: AgentMode.AUTONOMOUS,
},
},
});
// Initialize response parser
const responseParsingService = new ResponseParserService(toolkit.getTools());
// ... inside your agent loop ...
const response = await agent.invoke({ messages: [/* ... */] });
// Parse tool outputs
const parsedToolData = responseParsingService.parseNewToolMessages(response);
const toolCall = parsedToolData[0]; // assuming only one tool was called
if (toolCall) {
console.log('Human Message:', toolCall.parsedData.humanMessage);
console.log('Raw Data:', toolCall.parsedData.raw);
}
Publish and Register Your Plugin
See How To: Publish & Register Your Plugin for instructions on creating, publishing, and registering your plugin with the Hedera Agent Kit ecosystem.
Examples and References