npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hedera-agent-kit-archive

v2.0.0

Published

Build LLM-powered applications that interact with the Hedera Network. Create conversational agents that can understand user requests in natural language and execute Hedera transactions, or build backend systems that leverage AI for on-chain operations.

Readme

hedera-agent-kit

Build LLM-powered applications that interact with the Hedera Network. Create conversational agents that can understand user requests in natural language and execute Hedera transactions, or build backend systems that leverage AI for on-chain operations.

Key Features

  • Conversational Hedera: Easily build chat-based interfaces for Hedera actions.
  • Flexible Transaction Handling:
    • Direct Execution: For autonomous agents or backend control.
    • Provide Bytes: For user-centric apps where users sign with their own wallets (e.g., HashPack via WalletConnect).
    • Scheduled Transactions: Built-in support for "human-in-the-loop" workflows, where AI prepares transactions for user review and approval.
  • Comprehensive Toolset: Pre-built tools for HTS, HCS, HBAR transfers, account management, files, and smart contracts.
  • Token Usage Tracking: Real-time tracking of LLM token usage with accurate cost calculation based on dynamic pricing.
  • Extensible: Add your own custom tools with the plugin system.
  • Simplified SDK Interaction: Abstracts away much of the Hedera SDK boilerplate.

Table of Contents

Installation

npm install hedera-agent-kit
# or
yarn add hedera-agent-kit

For frontend integration with WalletConnect:

npm install @hashgraph/hedera-wallet-connect
# or
yarn add @hashgraph/hedera-wallet-connect

(Ensure you have dotenv for environment variable management if you use .env files.)

Quick Start: Your First Conversational Hedera Agent

This example demonstrates setting up the HederaConversationalAgent for a user-centric scenario where the user signs scheduled transactions. The agent's operator account will pay to create the schedule, and the user's account will be set to pay for the actual scheduled transaction when it's signed and submitted by the user.

1. Set up your .env file:

OPENAI_API_KEY="sk-..."
HEDERA_ACCOUNT_ID="0.0.YOUR_AGENT_OPERATOR_ID"
HEDERA_PRIVATE_KEY="your_agent_operator_private_key"
HEDERA_NETWORK="testnet"
USER_ACCOUNT_ID="0.0.YOUR_USER_ACCOUNT_ID"
USER_PRIVATE_KEY="your_user_private_key"

2. Run the interactive demo:

npm install
npm run demo:langchain

3. Example Interaction:

User > Schedule a transfer of 0.1 HBAR from my account to 0.0.34567
Agent > Okay, I have scheduled a transfer of 0.1 HBAR from your account (0.0.USER_ACCOUNT_ID) to 0.0.34567. The Schedule ID is 0.0.xxxxxx.
Agent > Transaction bytes received. Do you want to sign and execute this with YOUR account 0.0.USER_ACCOUNT_ID? (y/n): y
Agent > Transaction executed with your key. Receipt: { ... }

4. Demo Source Reference:

The demo code is in examples/langchain-demo.ts. Here is a simplified excerpt:

import * as dotenv from 'dotenv';
dotenv.config();
import { ServerSigner } from 'hedera-agent-kit';
import { HederaConversationalAgent } from 'hedera-agent-kit';

async function main() {
  const operatorId = process.env.HEDERA_ACCOUNT_ID;
  const operatorKey = process.env.HEDERA_PRIVATE_KEY;
  const network = process.env.HEDERA_NETWORK || 'testnet';
  const openaiApiKey = process.env.OPENAI_API_KEY;
  const userAccountId = process.env.USER_ACCOUNT_ID;
  const userPrivateKey = process.env.USER_PRIVATE_KEY;

  if (!operatorId || !operatorKey)
    throw new Error(
      'HEDERA_ACCOUNT_ID and HEDERA_PRIVATE_KEY must be set in .env'
    );

  const agentSigner = new ServerSigner(operatorId, operatorKey, network);
  const conversationalAgent = new HederaConversationalAgent(agentSigner, {
    operationalMode: 'provideBytes',
    userAccountId: userAccountId,
    verbose: false,
    openAIApiKey: openaiApiKey,
  });
  await conversationalAgent.initialize();
  // ... (see examples/langchain-demo.ts for full interactive loop)
}
main().catch(console.error);

Core Concepts

Understanding these concepts will help you make the most of the Hedera Agent Kit:

  • HederaConversationalAgent: The primary interface for building chat-based applications. It combines the power of an LLM with the Hedera-specific tools provided by HederaAgentKit.
  • HederaAgentKit: The core engine that bundles tools, manages network clients, and holds the signer configuration. It's used internally by HederaConversationalAgent but can also be used directly for more programmatic control.
  • Signers (AbstractSigner): Determine how transactions are signed and paid for:
    • ServerSigner: Holds a private key directly. Useful for backend agents where the agent's account pays for transactions it executes.
    • BrowserSigner (Conceptual for this README): Represents integrating with a user's browser wallet (e.g., HashPack). The agent prepares transaction bytes, and the user signs and submits them via their wallet.
  • Operational Modes: Configure how the agent handles transactions:
    • operationalMode: 'directExecution': Agent signs and submits all transactions using its signer. The agent's operator account pays.
    • operationalMode: 'provideBytes': Agent returns transaction bytes. Your application (and the user, via their wallet) is responsible for signing and submitting. This is key for user-centric apps.
    • scheduleUserTransactionsInBytesMode: boolean (Default: true): When operationalMode is 'provideBytes', this flag makes the agent automatically schedule transactions initiated by the user (e.g., "transfer my HBAR..."). The agent's operator account pays to create the schedule entity, and the user pays for the actual scheduled transaction when they sign the ScheduleSignTransaction.
    • metaOptions: { schedule: true }: Allows the LLM to explicitly request scheduling for any tool call, overriding defaults.
  • Human-in-the-Loop Flow: The Quick Start example demonstrates this. The agent first creates a schedule (agent pays). Then, after user confirmation, it prepares a ScheduleSignTransaction (user pays to sign and submit this, triggering the original scheduled transaction).

Handling User Prompts

When building applications with HederaConversationalAgent, it's important to establish a proper flow for handling user prompts and agent responses. This section explains how to process user inputs, manage conversation history, and handle the various response types from the agent.

Processing User Prompts

To send a user's message to the agent and receive a response:

// Initialize the agent as shown in the Quick Start example
const conversationalAgent = new HederaConversationalAgent(agentSigner, {
  operationalMode: 'provideBytes',
  userAccountId: userAccountId,
  openAIApiKey: openaiApiKey,
});
await conversationalAgent.initialize();

// Create a chat history array to maintain conversation context
const chatHistory: Array<{ type: 'human' | 'ai'; content: string }> = [];

// Process a user message
async function handleUserMessage(userInput: string) {
  // Add the user's message to chat history
  chatHistory.push({ type: 'human', content: userInput });

  // Process the message using the agent
  const agentResponse = await conversationalAgent.processMessage(
    userInput,
    chatHistory
  );

  // Add the agent's response to chat history
  chatHistory.push({ type: 'ai', content: agentResponse.output });

  // Return the full response to handle any transaction data
  return agentResponse;
}

Understanding Agent Responses

The processMessage method returns an AgentResponse object with these key properties:

interface AgentResponse {
  output: string; // The text response to show to the user
  transactionBytes?: string; // Base64-encoded transaction bytes (when in 'provideBytes' mode)
  scheduleId?: ScheduleId; // The schedule ID when a transaction was scheduled
  error?: string; // Error message if something went wrong
}

Handling Different Response Types

Depending on your operational mode, you'll need to handle different response types:

1. Text-only Responses

Simple informational responses require no special handling:

const response = await handleUserMessage("What's my HBAR balance?");
console.log(response.output); // Display to the user

2. Transaction Bytes (provideBytes mode)

When the agent generates transaction bytes, you'll need to present them to the user for signing:

const response = await handleUserMessage('Transfer 10 HBAR to 0.0.12345');

if (response.transactionBytes) {
  // Option 1: Using Hashinal WalletConnect SDK
  import { DAppConnector } from '@hashgraph/hedera-wallet-connect';
  import { Transaction } from '@hashgraph/sdk';

  const sdk = HashinalsWalletConnectSDK.getInstance();
  await sdk.init(projectId, metadata);
  await sdk.connect();

  // Sign and submit the transaction
  const txBytes = Buffer.from(response.transactionBytes, 'base64');
  const transaction = Transaction.fromBytes(txBytes);
  const receipt = await sdk.executeTransaction(transaction);
  console.log('Transaction executed:', receipt);

  // Option 2: If you have the user's key in your app
  const userSigner = new ServerSigner(userAccountId, userPrivateKey, network);
  const txBytes = Buffer.from(response.transactionBytes, 'base64');
  const transaction = Transaction.fromBytes(txBytes);
  const signedTx = await transaction.sign(userSigner.getOperatorPrivateKey());
  const txResponse = await signedTx.execute(userSigner.getClient());
}

3. Schedule IDs (scheduled transactions)

When the agent creates a scheduled transaction:

const response = await handleUserMessage(
  'Schedule a transfer of 5 HBAR from my account to 0.0.12345'
);

if (response.scheduleId) {
  const scheduleIdStr = response.scheduleId.toString();
  console.log(`Transaction scheduled with ID: ${scheduleIdStr}`);

  // Ask the user if they want to sign the scheduled transaction
  const userWantsToSign = await askUserForConfirmation();

  if (userWantsToSign) {
    // Ask the agent to prepare the ScheduleSign transaction
    const signResponse = await handleUserMessage(
      `Sign the scheduled transaction with ID ${scheduleIdStr}`
    );

    // Handle the resulting transaction bytes as shown above
    if (signResponse.transactionBytes) {
      // Present to wallet or sign with user key
    }
  }
}

Working with Chat History

The chat history is crucial for giving the agent context of the conversation. Some best practices:

  1. Format: Each entry should have a type ('human' or 'ai') and content (string).
  2. Memory Management: Limit history length to avoid token limits:
// Trim history if it gets too long
if (chatHistory.length > 20) {
  // Keep the most recent 15 messages
  chatHistory.splice(0, chatHistory.length - 15);
}
  1. Preserving Context: For better results, make sure to include important context:
// Special initialization message to set context
chatHistory.push({
  type: 'system',
  content: 'The user's account ID is 0.0.12345. They are interested in NFTs.'
});

Example: Complete Prompt Handling Flow

Here's a complete example bringing all the concepts together:

async function handleHederaConversation() {
  // Initialize agent
  const agent = new HederaConversationalAgent(agentSigner, {
    operationalMode: 'provideBytes',
    userAccountId: userAccountId,
    openAIApiKey: openaiApiKey,
  });
  await agent.initialize();

  const chatHistory = [];

  // Initialize with context
  chatHistory.push({
    type: 'system',
    content: `User account: ${userAccountId}. Network: ${network}.`,
  });

  // Simulated chat loop
  while (true) {
    const userInput = await getUserInput(); // Your UI input function
    if (userInput.toLowerCase() === 'exit') break;

    chatHistory.push({ type: 'human', content: userInput });

    const response = await agent.processMessage(userInput, chatHistory);
    displayToUser(response.output);
    chatHistory.push({ type: 'ai', content: response.output });

    // Handle special responses
    if (response.transactionBytes) {
      const shouldSign = await askUserToSign();
      if (shouldSign) {
        await signAndSubmitTransaction(response.transactionBytes);
      }
    }

    if (response.scheduleId) {
      displayToUser(
        `Transaction scheduled! ID: ${response.scheduleId.toString()}`
      );
      // Handle schedule signing if needed
    }

    // Trim history if needed
    if (chatHistory.length > 20) chatHistory.splice(0, chatHistory.length - 15);
  }
}

Scheduled Transaction Implementation

When working with scheduled transactions, you can check their status and handle approvals programmatically:

import { DAppConnector } from '@hashgraph/hedera-wallet-connect';
import { ScheduleSignTransaction } from '@hashgraph/sdk';
import { HederaMirrorNode } from '../src/services/mirror-node';
import { TransactionParser } from '../src/utils/transaction-parser';

async function handleScheduledTransaction(
  scheduleId: string,
  network: 'mainnet' | 'testnet'
) {
  // Initialize WalletConnect SDK
  const sdk = HashinalsWalletConnectSDK.getInstance();
  await sdk.init(projectId, metadata);
  await sdk.connect();

  // Create mirror node instance
  const mirrorNode = new HederaMirrorNode(network);

  // Fetch schedule information
  const scheduleInfo = await mirrorNode.getScheduleInfo(scheduleId);

  if (!scheduleInfo) {
    throw new Error('Schedule not found');
  }

  // Check if already executed
  if (scheduleInfo.executed_timestamp) {
    console.log(
      'Transaction already executed at:',
      scheduleInfo.executed_timestamp
    );
    return { status: 'executed', timestamp: scheduleInfo.executed_timestamp };
  }

  // Parse transaction details
  const transactionDetails = TransactionParser.parseScheduleResponse({
    transaction_body: scheduleInfo.transaction_body,
    memo: scheduleInfo.memo,
  });

  console.log('Transaction Details:', {
    type: transactionDetails.humanReadableType,
    transfers: transactionDetails.transfers,
    memo: transactionDetails.memo,
    expirationTime: scheduleInfo.expiration_time,
  });

  // Create and execute the ScheduleSign transaction
  const scheduleSignTx = new ScheduleSignTransaction().setScheduleId(
    scheduleId
  );

  try {
    // For scheduled transactions, disable signer since it's already configured
    const receipt = await sdk.executeTransaction(scheduleSignTx, false);
    console.log('Schedule signed successfully:', receipt);
    return { status: 'signed', receipt };
  } catch (error) {
    console.error('Failed to sign schedule:', error);
    throw error;
  }
}

// Usage with HederaConversationalAgent
async function exampleScheduledTransactionFlow() {
  const agent = new HederaConversationalAgent(agentSigner, {
    operationalMode: 'provideBytes',
    userAccountId: userAccountId,
    scheduleUserTransactionsInBytesMode: true, // Auto-schedule user transactions
  });

  // User requests a scheduled transaction
  const response = await agent.processMessage(
    'Schedule a transfer of 10 HBAR from my account to 0.0.12345 for tomorrow'
  );

  if (response.scheduleId) {
    console.log(
      'Transaction scheduled with ID:',
      response.scheduleId.toString()
    );

    // Handle the scheduled transaction approval
    const result = await handleScheduledTransaction(
      response.scheduleId.toString(),
      'testnet'
    );

    console.log('Schedule handling result:', result);
  }
}

// Polling example - check schedule status periodically
async function pollScheduleStatus(
  scheduleId: string,
  network: 'mainnet' | 'testnet'
) {
  const mirrorNode = new HederaMirrorNode(network);

  const checkStatus = async () => {
    const scheduleInfo = await mirrorNode.getScheduleInfo(scheduleId);

    if (scheduleInfo?.executed_timestamp) {
      console.log('Schedule executed!');
      clearInterval(intervalId);

      // Get the executed transaction details
      const executedTx = await mirrorNode.getTransactionByTimestamp(
        scheduleInfo.executed_timestamp
      );
      console.log('Executed transaction:', executedTx);
    } else if (scheduleInfo?.deleted_timestamp) {
      console.log('Schedule was deleted');
      clearInterval(intervalId);
    } else {
      console.log('Schedule still pending...');
    }
  };

  // Check immediately and then every 5 seconds
  await checkStatus();
  const intervalId = setInterval(checkStatus, 5000);

  // Return cleanup function
  return () => clearInterval(intervalId);
}

Available Tools

The Hedera Agent Kit provides a comprehensive set of tools organized by service type. These tools can be used both by the conversational agent and programmatically.

Account Management Tools

| Tool Name | Description | Example Usage | | ----------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------- | | hedera-account-create | Creates a new Hedera account | Create an account with initial balance and key | | hedera-account-update | Updates properties of an existing account | Change account memo, auto-renew period, etc. | | hedera-account-delete | Deletes an account and transfers remaining balance | Delete an account and transfer funds to another account | | hedera-transfer-hbar | Transfers HBAR between accounts | Send HBAR from one account to another | | hedera-approve-hbar-allowance | Approves an HBAR allowance for a spender account | Grant permission for another account to spend your HBAR | | hedera-approve-fungible-token-allowance | Approves a fungible token allowance | Grant permission for another account to spend your tokens | | hedera-approve-token-nft-allowance | Approves an NFT allowance | Grant permission for another account to spend your NFTs | | hedera-revoke-hbar-allowance | Revokes an HBAR allowance | Remove permission for an account to spend your HBAR | | hedera-revoke-fungible-token-allowance | Revokes a fungible token allowance | Remove permission for an account to spend your tokens | | hedera-sign-and-execute-scheduled-transaction | Signs and executes a scheduled transaction | User signs a transaction prepared by the agent |

HBAR Transaction Tools

| Tool Name | Description | Example Usage | | ------------------------------ | ------------------------------------- | --------------------------------------------------- | | hedera-account-transfer-hbar | Transfers HBAR between accounts | Send HBAR with memo support and detailed parameters | | hedera-account-balance-hbar | Retrieves HBAR balance for an account | Check your HBAR balance |

HTS Token Service Tools

| Tool Name | Description | Example Usage | | -------------------------------------- | ------------------------------------------- | ------------------------------------------------------- | | hedera-hts-create-fungible-token | Creates a new fungible token | Create a custom token with name, symbol, decimals, etc. | | hedera-hts-create-nft | Creates a new NFT collection | Create an NFT collection with configurable properties | | hedera-hts-mint-fungible-token | Mints additional supply of a fungible token | Add more tokens to circulation | | hedera-hts-mint-nft | Mints a new NFT within a collection | Create a new NFT with metadata | | hedera-hts-transfer-tokens | Transfers fungible tokens between accounts | Send tokens from one account to another | | hedera-hts-transfer-nft | Transfers NFT ownership | Send an NFT to another account | | hedera-hts-associate-token | Associates a token to an account | Enable an account to receive a token | | hedera-hts-dissociate-tokens | Removes token associations | Remove a token from your account | | hedera-hts-reject-tokens | Rejects automatically associated tokens | Reject tokens you don't want | | hedera-hts-burn-fungible-token | Burns fungible tokens (reduces supply) | Remove tokens from circulation | | hedera-hts-burn-nft | Burns an NFT (destroys it) | Destroy an NFT permanently | | hedera-hts-update-token | Updates token properties | Modify token name, symbol, or other properties | | hedera-hts-delete-token | Deletes a token | Remove a token completely | | hedera-hts-pause-token | Pauses a token (prevents transfers) | Temporarily freeze all transfers of a token | | hedera-hts-unpause-token | Unpauses a token | Resume transfers for a paused token | | hedera-hts-freeze-token-account | Freezes a token for a specific account | Prevent an account from transferring a specific token | | hedera-hts-unfreeze-token-account | Unfreezes a token for an account | Allow transfers for a previously frozen account | | hedera-hts-grant-kyc-token | Grants KYC for a token to an account | Approve KYC for an account to use a token | | hedera-hts-revoke-kyc-token | Revokes KYC for a token from an account | Remove KYC approval for an account | | hedera-hts-wipe-token-account | Wipes tokens from an account | Remove tokens from an account | | hedera-hts-token-fee-schedule-update | Updates token fee schedule | Modify fees for a token | | hedera-airdrop-token | Airdrops tokens to multiple recipients | Send tokens to many accounts at once | | hedera-claim-airdrop | Claims an airdrop | Claim tokens sent to you |

HCS Consensus Service Tools

| Tool Name | Description | Example Usage | | ----------------------------- | ------------------------------ | --------------------------------------- | | hedera-create-topic | Creates a new HCS topic | Create a topic for message consensus | | hedera-delete-topic | Deletes an HCS topic | Remove a topic you created | | hedera-submit-topic-message | Submits a message to a topic | Send a message to be recorded on Hedera | | hedera-get-topic-messages | Gets messages from a topic | Retrieve messages from a topic | | hedera-get-topic-info | Gets information about a topic | Retrieve topic details |

File Service Tools

| Tool Name | Description | Example Usage | | -------------------- | ----------------------------------- | ------------------------------ | | hedera-create-file | Creates a new file on Hedera | Store immutable data on Hedera | | hedera-append-file | Appends content to an existing file | Add more data to a file | | hedera-update-file | Updates a file's contents | Replace file contents | | hedera-delete-file | Deletes a file | Remove a file |

Smart Contract Service Tools

| Tool Name | Description | Example Usage | | ------------------------- | ---------------------------- | ---------------------------------------- | | hedera-create-contract | Deploys a smart contract | Deploy Solidity contract bytecode | | hedera-update-contract | Updates a contract | Update contract properties | | hedera-delete-contract | Deletes a contract | Remove a deployed contract | | hedera-execute-contract | Executes a contract function | Call functions on your deployed contract |

Advanced Usage

Using HederaAgentKit Directly

For more programmatic control, you can use HederaAgentKit directly instead of the conversational agent:

import { HederaAgentKit, ServerSigner } from 'hedera-agent-kit';
import { Hbar } from '@hashgraph/sdk';

async function useKitDirectly() {
  const signer = new ServerSigner(
    process.env.HEDERA_ACCOUNT_ID!,
    process.env.HEDERA_PRIVATE_KEY!,
    'testnet'
  );
  const kit = new HederaAgentKit(signer, undefined, 'directExecution');
  await kit.initialize();

  // Transfer HBAR
  const transferResult = await kit
    .accounts()
    .transferHbar({
      transfers: [
        { accountId: '0.0.RECIPIENT', amount: new Hbar(1) },
        { accountId: signer.getAccountId().toString(), amount: new Hbar(-1) },
      ],
      memo: 'Direct kit HBAR transfer',
    })
    .execute();
  console.log('Transfer result:', transferResult);

  // Create a token
  const createTokenResult = await kit
    .hts()
    .createFungibleToken({
      name: 'My Token',
      symbol: 'TKN',
      decimals: 2,
      initialSupply: 1000,
      maxSupply: 10000,
      memo: 'My first token',
    })
    .execute();
  console.log('Token created:', createTokenResult);
}

Tool Filtering

You can control which tools are available to the conversational agent by providing a toolFilter function. This is useful when you want to:

  • Limit the agent's capabilities for security reasons
  • Create specialized agents focused on specific tasks
  • Implement role-based access control
  • Reduce the token count sent to the LLM by filtering out unnecessary tools
import { HederaConversationalAgent } from 'hedera-agent-kit';
import { StructuredTool } from '@langchain/core/tools';

// Example 1: Allow only read operations (no state changes)
const readOnlyAgent = new HederaConversationalAgent(agentSigner, {
  openAIApiKey: process.env.OPENAI_API_KEY,
  toolFilter: (tool: StructuredTool) => {
    const readOnlyTools = [
      'get-',
      'query',
      'account-balance',
      'account-info',
      'topic-info',
      'token-info',
    ];
    return readOnlyTools.some((pattern) => tool.name.includes(pattern));
  },
});

// Example 2: Disable specific high-risk operations
const restrictedAgent = new HederaConversationalAgent(agentSigner, {
  openAIApiKey: process.env.OPENAI_API_KEY,
  toolFilter: (tool: StructuredTool) => {
    const blockedTools = [
      'hedera-account-delete',
      'hedera-hts-wipe-token-account',
      'hedera-hts-burn-nft',
      'hedera-delete-contract',
    ];
    return !blockedTools.includes(tool.name);
  },
});

// Example 3: Create an NFT-focused agent
const nftAgent = new HederaConversationalAgent(agentSigner, {
  openAIApiKey: process.env.OPENAI_API_KEY,
  userAccountId: userAccountId,
  toolFilter: (tool: StructuredTool) => {
    const nftTools = [
      'hedera-hts-create-nft',
      'hedera-hts-mint-nft',
      'hedera-hts-transfer-nft',
      'hedera-hts-burn-nft',
      'hedera-hts-associate-token',
      'hedera-account-get-nfts',
      'hedera-account-transfer-hbar', // For paying fees
      'hedera-account-get-balance',
    ];
    return nftTools.includes(tool.name);
  },
});

// Example 4: Dynamic filtering based on user roles
async function createRoleBasedAgent(userRole: 'admin' | 'user' | 'viewer') {
  const agent = new HederaConversationalAgent(agentSigner, {
    openAIApiKey: process.env.OPENAI_API_KEY,
    toolFilter: (tool: StructuredTool) => {
      switch (userRole) {
        case 'viewer':
          // Only allow read operations
          return tool.name.includes('get-') || tool.name.includes('query');
        case 'user':
          // Allow most operations except account management
          return (
            !tool.name.includes('account-delete') &&
            !tool.name.includes('account-create')
          );
        case 'admin':
          // Allow all tools
          return true;
        default:
          return false;
      }
    },
  });

  await agent.initialize();
  return agent;
}

Token Usage Tracking and Cost Calculation

The Hedera Agent Kit now includes comprehensive token usage tracking and cost calculation for OpenAI API calls. This feature enables:

  • Accurate billing based on actual LLM token consumption
  • Real-time cost monitoring
  • Usage history tracking
  • Dynamic pricing from OpenRouter API (300+ models)
import { HederaConversationalAgent, formatCost } from 'hedera-agent-kit';

// Initialize agent with token tracking
const agent = new HederaConversationalAgent(signer, {
  openAIApiKey: process.env.OPENAI_API_KEY,
  operationalMode: 'provideBytes',
});

await agent.initialize();

// Process a message - token usage is automatically tracked
const response = await agent.processMessage(
  'Create a new token called TestToken'
);

// Access token usage for this request
if (response.tokenUsage && response.cost) {
  console.log(`Tokens used: ${response.tokenUsage.totalTokens}`);
  console.log(`Cost: ${formatCost(response.cost)}`);
  console.log(`  - Prompt tokens: ${response.tokenUsage.promptTokens}`);
  console.log(`  - Completion tokens: ${response.tokenUsage.completionTokens}`);
}

// Get cumulative usage across all requests
const totalUsage = agent.getTotalTokenUsage();
console.log(`Total tokens used: ${totalUsage.totalTokens}`);
console.log(`Total cost: ${formatCost(totalUsage.cost)}`);

// Get detailed usage history
const history = agent.getTokenUsageHistory();
history.forEach((usage, index) => {
  console.log(
    `Request ${index + 1}: ${usage.totalTokens} tokens, ${formatCost(
      usage.cost
    )}`
  );
});

// Integration with credits/billing systems
const costUSD = response.cost?.totalCost || 0;
const hbarPrice = 0.05; // Get current HBAR price
const hbarEquivalent = costUSD / hbarPrice;
const creditsToDeduct = Math.ceil(hbarEquivalent * 1000); // 1 credit = 0.001 HBAR

console.log(`Credits to deduct: ${creditsToDeduct}`);

// Reset tracking for new billing session
agent.resetTokenUsageTracking();

Key Features:

  • Automatic Tracking: Token usage is tracked automatically for every API call
  • Dynamic Pricing: Fetches live pricing data from OpenRouter API with 24-hour caching
  • Cost Breakdown: Separate costs for prompt and completion tokens
  • Session Management: Reset tracking for new billing periods
  • Model Support: Supports all OpenAI models plus 300+ models from OpenRouter

Response Structure:

interface AgentResponse {
  output: string;
  tokenUsage?: {
    promptTokens: number;
    completionTokens: number;
    totalTokens: number;
    modelName?: string;
    timestamp?: Date;
  };
  cost?: {
    promptCost: number;
    completionCost: number;
    totalCost: number;
    currency: string; // 'USD'
  };
  // ... other fields
}

Plugin System

Extend the agent's capabilities with custom plugins:

import { HederaAgentKit, ServerSigner } from 'hedera-agent-kit';

async function useCustomPlugin() {
  const signer = new ServerSigner(
    process.env.HEDERA_ACCOUNT_ID!,
    process.env.HEDERA_PRIVATE_KEY!,
    'testnet'
  );

  // Create the kit with plugin configuration
  const kit = new HederaAgentKit(
    signer,
    {
      directories: ['./plugins'], // Local plugin directory
      packages: ['@my-org/my-hedera-plugin'], // NPM package plugin
      appConfig: { customSetting: 'value' }, // Custom config passed to plugins
    },
    'directExecution'
  );

  await kit.initialize();

  // Now the kit has all your plugin tools available
  const tools = kit.getAggregatedLangChainTools();
  console.log(
    'Available tools including plugins:',
    tools.map((t) => t.name)
  );
}

API Reference

HederaConversationalAgent Options

interface HederaConversationalAgentOptions {
  // LLM Configuration
  llm?: BaseChatModel; // Provide your own LLM instance
  openAIApiKey?: string; // Or provide just the API key

  // Agent Configuration
  userAccountId?: string; // User's account ID for user-centric operations
  operationalMode?: AgentOperationalMode; // 'directExecution' or 'provideBytes'
  scheduleUserTransactionsInBytesMode?: boolean; // Auto-schedule user transactions

  // Plugin Configuration
  pluginConfig?: PluginConfig; // Configure plugins

  // Tool Filtering
  toolFilter?: (tool: StructuredTool) => boolean; // Filter which tools are available to the agent

  // Debug Options
  verbose?: boolean; // Enable verbose logging
  disableLogging?: boolean; // Disable all logging output
}

Architecture Diagram

graph TD;
    UserInput["User via Application UI"] --> AppCode["Application Logic (e.g., demo.ts)"];
    AppCode -- "Sends user prompt to" --> ConversationalAgent["HederaConversationalAgent"];

    subgraph AgentCore ["HederaConversationalAgent Internals"]
        ConversationalAgent -- "Manages" --> LLM["LLM (e.g., GPT-4o)"];
        ConversationalAgent -- "Uses" --> AgentKit["HederaAgentKit Instance"];
        LLM -- "Decides to use a tool" --> Tools[Aggregated LangChain Tools];
    end

    AgentKit -- "Provides tools to" --> Tools;
    AgentKit -- "Configured with" --> Signer["AbstractSigner (ServerSigner/BrowserSigner)"];
    AgentKit -- "Configured with" --> OpModes["Operational Modes"];

    Tools -- "Calls e.g., kit.accounts()" --> AgentKit;
    Tools -- "Invokes e.g., accountBuilder.prepareTransferHbar()" --> ServiceBuilders["Service Builders (AccountBuilder, etc.)"];
    ServiceBuilders -- "Prepares SDK Transaction" --> SDKTx["@hashgraph/sdk Transaction"];

    subgraph ExecutionPath ["Transaction Execution / Byte Generation"]
        ServiceBuilders -- "Based on OpModes & Tool Logic" --> DecisionPoint["Execute or GetBytes?"];
        DecisionPoint -- "Execute (Agent Pays/Signs via ServerSigner)" --> Signer;
        DecisionPoint -- "ProvideBytes (User Pays/Signs)" --> TxBytes["Transaction Bytes"];
        DecisionPoint -- "Schedule (Agent Pays for CreateSchedule)" --> Signer;
        TxBytes -- "Returned to AppCode --> User Wallet" --> UserWallet["User Wallet (HashPack, etc)"];
        Signer -- "Uses SDK Client" --> HederaNetwork["Hedera Network"];
        UserWallet -- "Submits to" --> HederaNetwork;
    end

Local Development

  1. Clone the repo:
git clone https://github.com/hedera-dev/hedera-agent-kit.git
  1. Install dependencies:
cd hedera-agent-kit
npm install
  1. Configure environment variables (e.g., OPENAI_API_KEY, HEDERA_ACCOUNT_ID, HEDERA_PRIVATE_KEY) in a .env file based on the sample.env template.

  2. Test the kit:

npm run test
  1. Run the demo:
npm run demo:langchain

Contributing

We welcome contributions! Please see our CONTRIBUTING.md for details on our process, how to get started, and how to sign your commits under the DCO.

License

Apache 2.0