Skip to content
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c74d07e
feat: introduce policy enforcement framework and examples
skurzyp-blockydevs Jan 16, 2026
b57a31b
feat: add `ImmutabilityPolicy` and `NoInfiniteSupplyPolicy`, enforce …
skurzyp-blockydevs Jan 16, 2026
465c34e
refactor: use Zod schemas for runtime validation in `ImmutabilityPolicy`
skurzyp-blockydevs Jan 16, 2026
21e95b1
refactor: simplify `TokenAllowlistPolicy` by removing unused tools
skurzyp-blockydevs Jan 16, 2026
f771452
feat: refactor tools to implement base class and policy enforcement h…
skurzyp-blockydevs Jan 16, 2026
9aa1fb2
Merge branch 'feat/refactor-to-implement-hooks' into feat/poc-policies
skurzyp-blockydevs Jan 16, 2026
447f486
refactor: remove direct policy enforcement calls from tools and add `…
skurzyp-blockydevs Jan 16, 2026
88b4793
chore: mark unsupported tools in policies with FIXME comments
skurzyp-blockydevs Jan 16, 2026
65d4919
refactor: update policy framework to introduce `PolicyValidationParam…
skurzyp-blockydevs Jan 16, 2026
f9da5cc
refactor: update policy framework to introduce `PolicyValidationParam…
skurzyp-blockydevs Jan 16, 2026
4420bbb
refactor: update `handleError` to exclude unused `context` parameter …
skurzyp-blockydevs Jan 16, 2026
9835984
feat: migrate core-account-plugin tools to `BaseTool` class and enhan…
skurzyp-blockydevs Feb 6, 2026
faa960c
feat: migrate rest of the tools to `BaseTool` class
skurzyp-blockydevs Feb 6, 2026
dbe669b
refactor: replace `BasePolicy` with `Hook` and update tool lifecycle …
skurzyp-blockydevs Feb 9, 2026
f141d35
feat: enhance `policy-example` with additional policies and tools
skurzyp-blockydevs Feb 9, 2026
1f4fb56
refactor: migrate integration test to new Base Tool approach
skurzyp-blockydevs Feb 9, 2026
13a182d
refactor: replace `Hook` with `AbstractHook`, improve policy enforcem…
skurzyp-blockydevs Feb 10, 2026
42911cf
feat: add unit tests for policy enforcement across all implemented po…
skurzyp-blockydevs Feb 10, 2026
b2b4215
Merge branch 'main' into feat/poc-policies
skurzyp-blockydevs Feb 12, 2026
36124f6
refactor: replace `z.ZodObject` with typed parameter factories across…
skurzyp-blockydevs Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions docs/DEVEXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Try out one or more of the example agents:
* **Option C -** [Example Return Bytes Agent](#option-c-try-the-human-in-the-loop-chat-agent)
* **Option D -** [Example MCP Server](#option-d-try-out-the-mcp-server)
* **Option E -** [Example ElizaOS Agent](#option-e-try-out-the-hedera-agent-kit-with-elizaos)
* **Option F -** [Example Policy Agent](#option-f-run-the-policy-agent-example)

<!-- OR
Try out the create-hedera-app CLI tool to create a new Hedera Agent and a front end application -->
Expand Down Expand Up @@ -264,3 +265,34 @@ import { HederaElizaOSToolkit } from 'hedera-agent-kit/elizaos';
1. Clone the [Hedera ElizaOS Plugin Repository](https://github.com/hedera-dev/eliza-plugin-hedera/tree/feat/rework-v3)
2. Install ElizaOS CLI
3. Follow the [Hedera ElizaOS Plugin Docs](https://github.com/hedera-dev/eliza-plugin-hedera/tree/feat/rework-v3)

### Option F: Run the Policy Agent Example

The Policy Agent example demonstrates how to use the strict policy enforcement system in the Hedera Agent Kit. This agent is configured with several active policies (like `RequiredMemoPolicy` and `MaxHbarTransferPolicy`) that intercept and validate tool usage before execution.

For a deep dive into how policies work, see [docs/POLICIES.md](../docs/POLICIES.md).

#### Usage

1. Go to the example directory:
```bash
cd typescript/examples/policy-example
```

2. Install dependencies:
```bash
npm install
```

3. Create a `.env` file (copy from `.env.example`) and add your `ACCOUNT_ID`, `PRIVATE_KEY`, and `OPENAI_API_KEY`.

4. Run the example:
```bash
npm start
```

5. Interact with the agent. Try commands that trigger policy violations, such as:
- "Transfer 100 HBAR to 0.0.12345" (Should fail due to max limit)
- "Transfer 1 HBAR to 0.0.12345" (Should fail due to missing memo)
- "Transfer 1 HBAR to 0.0.12345 with memo Test" (Should succeed)

40 changes: 40 additions & 0 deletions docs/HEDERATOOLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1129,3 +1129,43 @@ Get the current HBAR exchange rate
What is the HBAR to USD rate?
Get exchange rate at timestamp 1726000000
```

---

## Standard Policies

The Hedera Agent Kit includes standard policies to enforce safety rules on agent actions. These policies can be configured in the `Context`.

### MaxHbarTransferPolicy
Limits the maximum amount of HBAR that can be transferred in a single transaction.

**Relevant Tools:**
- `TRANSFER_HBAR_TOOL`
- `TRANSFER_HBAR_WITH_ALLOWANCE_TOOL`

### TokenAllowlistPolicy
Restricts the agent to only interact with a specific set of Token IDs.

**Relevant Tools:**
- Most Token Tools (`TRANSFER_NON_FUNGIBLE_TOKEN_TOOL`, `MINT_FUNGIBLE_TOKEN_TOOL`, etc.)

### RequiredMemoPolicy
Ensures that every transaction (where applicable) includes a non-empty memo.

**Relevant Tools:**
- `TRANSFER_HBAR_TOOL`, `CREATE_ACCOUNT_TOOL`, `CREATE_TOPIC_TOOL`, and many others.

### ImmutabilityPolicy
Prevents modification or deletion of specific Accounts and Tokens.

**Relevant Tools:**
- `UPDATE_ACCOUNT_TOOL`
- `DELETE_ACCOUNT_TOOL`
- `UPDATE_TOKEN_TOOL`

### NoInfiniteSupplyPolicy
Prevents the creation of tokens with Infinite supply type.

**Relevant Tools:**
- `CREATE_FUNGIBLE_TOKEN_TOOL`
- `CREATE_NON_FUNGIBLE_TOKEN_TOOL`
126 changes: 126 additions & 0 deletions docs/POLICIES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Policies in Hedera Agent Kit

Policies are a powerful mechanism in the Hedera Agent Kit that allow you to enforce rules, validate actions, and control the execution flow of tools. They are built upon a flexible hook system, enabling you to intercept and inspect tool execution at various stages.

## Overview

A **Policy** is essentially a specialized **Hook** that can block the execution of a tool if certain conditions are not met. All policies extend the `AbstractHook` class (and specifically the `Policy` abstract class) and are registered in the agent's configuration.

### How Policies Work

When a tool is executed, it goes through several lifecycle stages:
1. **Pre-Tool Execution**: Before any logic runs.
2. **Post-Params Normalization**: After input parameters have been validated and normalized.
3. **Post-Core Action**: After the main action (e.g., transaction creation) has occurred.
4. **Post-Secondary Action**: After any secondary steps (e.g., signing/submission) are complete.

A single Policy can implement hooks for **all** of these stages if needed. If a Policy determines that an action violates its rules, it throws an error, effectively blocking the tool execution.

## Creating a Policy

To create a new policy, extend the `Policy` class and implement the abstract properties and any of the `shouldBlock...` methods.

### The `Policy` Class

The `Policy` class simplifies the hook implementation by providing specific methods for validation:

- `shouldBlockPreToolExecution`
- `shouldBlockPostParamsNormalization`
- `shouldBlockPostCoreAction`
- `shouldBlockPostSecondaryAction`

**Note:** You should only override these `shouldBlock...` methods. The underlying hook methods (e.g., `preToolExecutionHook`) are handled internally to ensure consistent error handling.

### Example: Token Allowlist Policy

```typescript
import { Policy, PostParamsNormalizationParams, Context } from 'hedera-agent-kit';

export class TokenAllowlistPolicy extends Policy {
public name = 'Token Allowlist';
public description = 'Only allows interactions with specific Token IDs';

// Define which tools this policy applies to
public relevantTools = [
'transfer_fungible_token_tool',
'mint_non_fungible_token_tool',
// ... add other relevant tool names
];

private allowedTokens: Set<string>;

constructor(allowedTokens: string[]) {
super();
this.allowedTokens = new Set(allowedTokens);
}

// Override the specific validation step you need
protected shouldBlockPostParamsNormalization(
_context: Context,
validationParams: PostParamsNormalizationParams,
): boolean {
const params = validationParams.normalisedParams;

// Check if the token ID in params is allowed
if (params.tokenId && !this.allowedTokens.has(params.tokenId.toString())) {
return true; // Return true to BLOCK the execution
}

return false; // Return false to ALLOW
}
}
```

## Advanced Usage

### 1. `AbstractHook` and Future Flexibility

Policies extend `AbstractHook`. Currently, `AbstractHook` serves as the base for all interception logic. In the future, a more generalized `Hook` class may be introduced to allow for even greater flexibility, such as modifying execution flow without just blocking it, or injecting custom logic that isn't strictly a "policy".

### 2. Communication Between Hooks

Hooks are stateless by default, but you can share data between different hooks (or even different execution stages of the same hook) using the `Context` object.

The `Context` is passed to every hook method. You can attach custom properties to it if you need to persist information across the lifecycle of a single tool execution.

```typescript
// Example: Storing a timestamp in Pre-Exec and checking it in Post-Exec
protected async shouldBlockPreToolExecution(context: Context, ...): Promise<boolean> {
context.customData = { startTime: Date.now() };
return false;
}

protected async shouldBlockPostCoreAction(context: Context, ...): Promise<boolean> {
const duration = Date.now() - context.customData.startTime;
console.log(`Tool took ${duration}ms`);
return false;
}
```

### 3. Handling Types with Zod

One challenge with generic policies is handling the `params` object, which can vary significantly between tools. Since `params` is often `any` or a loose type in the hook signature, it's highly recommended to use **Zod** schemas to inspect and validate the structure of parameters safely at runtime.

```typescript
import { z } from 'zod';

const TransferParamsSchema = z.object({
amount: z.number().max(100),
recipientId: z.string(),
}).passthrough(); // Allow other properties

// In your policy:
const result = TransferParamsSchema.safeParse(params);
if (result.success) {
// Validated typed access
if (result.data.amount > 50) return true;
}
```

## Example Usage

You can find a complete, runnable example of using various policies in the examples directory:

- **File**: `typescript/examples/policy-example/index.ts`

This example demonstrates how to configure an agent with multiple policies like `RequiredMemoPolicy`, `MaxHbarTransferPolicy`, and `ImmutabilityPolicy`.
2 changes: 1 addition & 1 deletion typescript/examples/langchain-v1/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions typescript/examples/policy-example/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ACCOUNT_ID=
PRIVATE_KEY= # you can use either testnet key type (ECDSA or ED25519) with our agent kit. To use our examples use ECDSA
# head over to https://portal.hedera.com/dashboard to get your testnet keys. We recommend using the DER encoded private key
OPENAI_API_KEY= # this is only required if you want to run the examples
45 changes: 45 additions & 0 deletions typescript/examples/policy-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Hedera Agent Kit - LangChain Policy System Example

This example demonstrates how to use the "DIY" Policy System with a **LangChain agent**.

## Overview

The example initializes a `HederaLangchainToolkit` with two policies:
1. **RequiredMemoPolicy**: Blocks any transaction that does not have a memo.
2. **MaxHbarTransferPolicy**: Blocks any HBAR transfer greater than 5 HBAR.

The agent uses `gpt-4o-mini` to interpret natural language commands and execute Hedera tools. If the agent attempts an action that violates a policy, the tool execution will fail, and the error will be returned to the agent (and logged).

## Setup

1. Install dependencies:
```bash
npm install
```

2. Configure environment:
```bash
cp .env.example .env
```
Fill in your:
- Hedera Testnet Account ID
- Hedera Testnet Private Key
- OpenAI API Key

3. Run the demo:
```bash
npm start
```

## Usage

Try asking the agent:

> "Transfer 1 HBAR to 0.0.12345"
*(This should fail and show an error about missing memo)*

> "Transfer 10 HBAR to 0.0.12345 with memo 'Too much'"
*(This should fail and show an error about max amount)*

> "Transfer 1 HBAR to 0.0.12345 with memo 'Valid transaction'"
*(This should succeed)*
Loading