feat: Universal Policy System for Hedera Agent Kit#476
feat: Universal Policy System for Hedera Agent Kit#476skurzyp-blockydevs wants to merge 20 commits intomainfrom
Conversation
- Added standard policies like `MaxHbarTransferPolicy`, `TokenAllowlistPolicy`, and `RequiredMemoPolicy`. - Integrated policy checks in `CREATE_ACCOUNT_TOOL` and `TRANSFER_HBAR_TOOL`. - Added example configuration and setup for policies in the new `policy-example` directory. Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
…policies in relevant tools - Introduced two new policies: `ImmutabilityPolicy` to block modifications/deletions of specific accounts and tokens, and `NoInfiniteSupplyPolicy` to prevent creating tokens with infinite supply. - Integrated policy enforcement into `UPDATE_ACCOUNT_TOOL`, `DELETE_ACCOUNT_TOOL`, `CREATE_FUNGIBLE_TOKEN_TOOL`, `CREATE_NON_FUNGIBLE_TOKEN_TOOL`, and `UPDATE_TOKEN_TOOL`. - Updated documentation with descriptions of the new policies and their applicable tools. Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
- Replaced manual runtime checks for `accountId` and `tokenId` with Zod schemas. - Simplified and improved type safety for `shouldBlock` logic. Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
- Removed tools: `burn_token_tool`, `wipe_token_tool`, `pause_token_tool`, `unpause_token_tool`, `freeze_token_tool`, `unfreeze_token_tool`, `grant_token_kyc_tool`, and `revoke_token_kyc_tool`. - Improved clarity and maintainability of the allowlist. Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
…ooks Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
# Conflicts: # typescript/src/plugins/core-account-plugin/tools/account/transfer-hbar.ts # typescript/src/shared/configuration.ts # typescript/src/shared/policy.ts
…affectedPoints` to policies - Simplified tools by removing inline policy checks. - Introduced the `affectedPoints` attribute in policies to standardize enforcement integration. - Adjusted relevant policy implementations to utilize `ToolExecutionPoint.PostParamsNormalization`. Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
- Added FIXME comments to indicate policies referencing tools that currently lack policy support. - Commented out unused tools in policy definitions for clarity. - Adjusted `policy-example` to reflect limitations in functional policies. Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
…s` and enhance hook implementations - Added `PolicyValidationParams` for consistent parameter handling across policies. - Refactored `ToolExecutionPoint` to improve clarity and add support for `PostCoreAction` and `PostSecondaryAction`. - Updated all policies to use `validationParams`, providing access to context-specific data like raw and normalized parameters. - Renamed `action` to `coreAction` and `submit` to `secondaryAction` in tools to improve semantic clarity. - Adjusted tool execution flow to incorporate new hooks and parameter structure. Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
…s` and enhance hook implementations - Added `PolicyValidationParams` for consistent parameter handling across policies. - Refactored `ToolExecutionPoint` to improve clarity and add support for `PostCoreAction` and `PostSecondaryAction`. - Updated all policies to use `validationParams`, providing access to context-specific data like raw and normalized parameters. - Renamed `action` to `coreAction` and `submit` to `secondaryAction` in tools to improve semantic clarity. - Adjusted tool execution flow to incorporate new hooks and parameter structure. Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
…in `TRANSFER_HBAR_TOOL` Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
|
Love this! Looks awesome. And really clean |
Adding in this design decision doc:Approach 1: Single Function InjectionThis approach involves injecting a single, user-defined validation function into the tool execution flow immediately after parameter normalization. It relies on a lightweight interface where users define blocking logic based on the normalized parameters of the tool. Pros:
Cons:
Detailed Technical Implementation1. Context & Solution 2. The Policy Interface export interface Policy {
name: string;
description?: string;
relevantTools: string[]; // List of tool names this applies to
shouldBlock: (params: any) => boolean | Promise<boolean>;
}3. Tool Integration Pattern // src/plugins/core-account-plugin/tools/transfer-hbar.ts
const transferHbar = async (client: Client, context: Context, params: any) => {
// 1. Normalisation
const normalisedParams = await HederaParameterNormaliser.normaliseTransferHbarParams(params, context, client);
// 2. Policy Check (The Injection Point)
if (context.policies) {
await enforcePolicies(context.policies, 'transfer_hbar', normalisedParams);
}
// 3. Execution
const tx = HederaBuilder.transferHbar(normalisedParams);
return await handleTransaction(tx, client, context);
};4. Known Limitations (Typing & Complexity) // Example of the complexity required to handle multiple tools
if (params.hbarTransfers) { /* check transfer array */ }
if (params.initial_balance) { /* check balance field */ }Approach 2: Lifecycle Hooks (Tools V2)This approach refactors the tool architecture to be modular, introducing a "Tools V2" specification. The Pros:
Cons:
Detailed Technical Implementation1. Context & Architecture 2. Lifecycle Execution Points
3. BaseTool Logic // Abstract BaseTool logic
async execute(context: Context, params: any) {
// Hook 1: Pre-Execution
await this.preToolExecutionHook(context, params);
const normalisedParams = await this.normalizeParams(params, context);
// Hook 2: Post-Normalization (Primary Policy Point)
await this.postParamsNormalizationHook(context, params, normalisedParams);
const coreActionResult = await this.coreAction(normalisedParams, context);
// Hook 3: Post-Action
await this.postCoreActionHook(context, params, normalisedParams, coreActionResult);
return coreActionResult;
}4. Policy Configuration Example export class MaxHbarAmountPolicy implements Policy {
name = 'Max HBAR Amount';
relevantTools = ['transfer_hbar_tool', 'create_account_tool'];
affectedPoints = [ToolExecutionPoint.PostParamsNormalization];
// Implementation...
}5. Migration Strategy
Summary & RecommendationI recommend Approach 2, as it provides significantly greater flexibility and follows a clean, modular design. While the implementation effort is not minimal, it is reasonable and well-justified by the long-term benefits. |
|
Option 2 does make the most sense. It stinks that it adds complexity, but we will be able to create better policies - e.g. stop a bad input, but also stop a transaction that violates limits. |
|
Yes, we’ll have to redefine each tool, but the impact shouldn’t be too big. We mainly need to split the current logic of each tool into steps and add hooks between them. And for each tool the process will be mostly the same.
These are the main points I can see for now. Additional ideas may come up during development, as this architecture opens up a lot of new possibilities. |
…ce policy hook support Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
…management Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
…ent approach Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
…licies - Added comprehensive unit test coverage for the following policies: - `RequiredMemoPolicy` - `TokenAllowlistPolicy` - `NoInfiniteSupplyPolicy` - `ImmutabilityPolicy` - `MaxHbarTransferPolicy` - Enhanced policy validation logic to ensure edge case handling. - Updated `policy-hooks` test to include additional hook coverage. Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
|
@skurzyp-blockydevs please resolve |
# Conflicts: # docs/DEVEXAMPLES.md # typescript/examples/langchain-v1/package-lock.json
piotrswierzy
left a comment
There was a problem hiding this comment.
Also, should we maybe want to be able to turn on a policy only for the given tool?
typescript/src/plugins/core-account-plugin/tools/account/transfer-hbar-with-allowance.ts
Outdated
Show resolved
Hide resolved
| export class ImmutabilityPolicy extends Policy { | ||
| name = 'Immutability Policy'; | ||
| description = 'Prevents modification or deletion of specific Accounts and Tokens'; | ||
| relevantTools = ['update_account_tool', 'delete_account_tool', 'update_token_tool']; |
There was a problem hiding this comment.
Why don't you use the declared tool constants instead of string literals?
| if (t.amount instanceof Hbar) { | ||
| const hbarAmount = t.amount.toBigNumber().toNumber(); | ||
| if (hbarAmount > 0 && hbarAmount > this.maxAmount) return true; |
There was a problem hiding this comment.
Don't we care about the total transaction value?
| export class NoInfiniteSupplyPolicy extends Policy { | ||
| name = 'No Infinite Supply Policy'; | ||
| description = 'Prevents the creation of tokens with Infinite supply type'; | ||
| relevantTools = ['create_fungible_token_tool', 'create_non_fungible_token_tool']; |
… all tools Signed-off-by: skurzyp-blockydevs <stanislaw.kurzyp@blockydevs.com>
|
Hello @walkerlj0. @piotrswierzy did the final review and I changed the requested things. There is a final decision to be made - what polices do we want to offer. Those which are currently implemented are just examples that I made for the PoC purposes. Do you have any specific on your mind? We should probably remove those examples and implement those you would like to have. The whole Universal Policy System logic is ready. I would suggest merging it with one example Policy and then creating a separate tasks for other Policies. We should think of all possible edgecases and other potential problems while developing them and adding extensive tests for each one of them would also be recommended. |
Description:
PR: Universal Policy System for Hedera Agent Kit
Overview
This PR introduces a flexible, "DIY" policy system that allows users to define and enforce custom validation logic for on-chain transactions executed by the Hedera Agent Kit. The system is built upon the new "Multistep Tool" architecture, leveraging lifecycle hooks to inject policy checks at precise execution points.
Changes
Core Policy Infrastructure
src/shared/policy.ts: Defines thePolicyinterface,ToolExecutionPointenum, andenforcePolicieshelper function.src/shared/configuration.ts: ExtendedContexttype with optionalpolicies?: Policy[]field.src/shared/tools.ts:BaseToolnow implements a lifecycle with hooks:preToolExecutionHookpostParamsNormalizationHookpostCoreActionHookpostToolExecutionHookPolicy Execution Points
The
Policyinterface now includes an optionalaffectedPointsarray, allowing policies to target specific lifecycle stages.PreToolExecutionPostParamsNormalizationPostCoreActionPostSecondaryActionExample Policies (Reference Implementations)
All shared policies have been explicitly configured to run at
ToolExecutionPoint.PostParamsNormalization.MaxHbarTransferPolicyanyRequiredMemoPolicyanyTokenAllowlistPolicyanyImmutabilityPolicyNoInfiniteSupplyPolicyanyTool Integration
Policy enforcement is now automatic for all tools inheriting from
BaseTool. TheBaseToolinvokesenforcePolicieswithin its default hook implementations. Subclasses don't need to manually callenforcePolicies—they just implementnormalizeParams,coreAction,secondaryAction, etc.Example Application
typescript/examples/policy-example/: LangChain-based interactive demoImportant Notes for Reviewers
1. Hook-Based Architecture
The previous manual insertion of
enforcePoliciesis replaced by theBaseTooltemplate method pattern. This ensures consistent enforcement across all tools:2. Explicit Policy Configuration
Policies now explicitly state where they apply:
3. Testing Requirements
Warning
Before merging, we need to add:
4. Documentation Needed
Important
A comprehensive tutorial is required covering:
Files Changed
New Files
src/shared/policy.tssrc/shared/policies/*.ts(Policy implementations)examples/policy-example/(entire directory)Modified Files
src/shared/tools.ts-BaseToolupdated with hookssrc/shared/configuration.ts- Addedpoliciesto Contextsrc/shared/index.ts- ExportsHow to Test
typescript/examples/policy-example.envnpm install && npm startRelated issue(s):
Fixes #416
Notes for reviewer:
Checklist