Skip to main content

Summary

The Hedera Agent Kit provides a comprehensive set of tools organized into plugins, which can be installed alongside the Hedera Agent Kit and used to extend the core functionality of the Hedera Agent Kit SDK. These tools can be used both by the conversational agent and when you are building with the SDK. The Hedera services built into this agent toolkit are also implemented as plugins. You can see a description of each plugin in the HEDERAPLUGINS.md file, as well as a list of the individual tools for each Hedera service that are included in each plugin.

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

Tool Interface

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

Step 2: Implement Your Tool

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):
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