@hashgraphonline/standards-agent-kit
Version:
A modular SDK for building on-chain autonomous agents using Hashgraph Online Standards, including HCS-10 for agent discovery and communication. https://hol.org
245 lines (244 loc) • 9.94 kB
JavaScript
import { AIAgentCapability } from "@hashgraphonline/standards-sdk";
import { z } from "zod";
import { BaseHCS10TransactionTool } from "./standards-agent-kit.es10.js";
import { NaturalLanguageMapper } from "./standards-agent-kit.es22.js";
const RegisterAgentZodSchema = z.object({
name: z.string().min(1).max(50).describe("A unique name for the agent (1-50 characters)"),
description: z.string().max(500).optional().describe("Optional bio description for the agent (max 500 characters)"),
alias: z.string().optional().transform((val) => {
if (!val || val.toLowerCase().includes("random")) {
const timestamp = Date.now().toString(36);
const randomChars = Math.random().toString(36);
return `bot${timestamp}${randomChars}`;
}
return val;
}).describe(
'Optional custom username/alias for the agent. Use "random" to generate a unique alias'
),
type: z.enum(["autonomous", "manual"]).optional().describe("Agent type (default: autonomous)"),
model: z.string().optional().describe("AI model identifier (default: agent-model-2024)"),
capabilities: z.union([
z.array(z.nativeEnum(AIAgentCapability)),
z.array(z.string()),
z.string()
]).optional().transform((val) => {
if (!val) {
return void 0;
}
if (typeof val === "string") {
return NaturalLanguageMapper.parseCapabilities(val);
}
if (Array.isArray(val) && val.length > 0 && typeof val[0] === "string") {
return NaturalLanguageMapper.parseTagsOrCapabilities(val);
}
return val;
}).describe('Agent capabilities - can be capability names (e.g. "ai", "data processing"), capability enum values, or array of either. Common values: "ai"/"text" (TEXT_GENERATION), "data" (DATA_INTEGRATION), "analytics" (TRANSACTION_ANALYTICS)'),
tags: z.union([
z.array(z.string()),
z.string()
]).optional().transform((val) => {
if (!val) {
return void 0;
}
if (typeof val === "string") {
return NaturalLanguageMapper.parseCapabilities(val);
}
return NaturalLanguageMapper.parseTagsOrCapabilities(val);
}).describe('Tags for the agent (alternative to capabilities) - e.g. "ai", "data", "analytics". Will be converted to appropriate capabilities.'),
creator: z.string().optional().describe("Creator attribution for the agent"),
socials: z.record(
z.enum([
"twitter",
"github",
"discord",
"telegram",
"linkedin",
"youtube",
"website",
"x"
]),
z.string()
).optional().describe(
'Social media links (e.g., {"twitter": "@handle", "discord": "username"})'
),
properties: z.record(z.unknown()).optional().describe("Custom metadata properties for the agent"),
profilePicture: z.union([
z.string().describe("URL or local file path to profile picture"),
z.object({
url: z.string().optional(),
path: z.string().optional(),
filename: z.string().optional()
})
]).optional().describe(
"Optional profile picture as URL, file path, or object with url/path/filename"
),
existingProfilePictureTopicId: z.string().optional().describe(
"Topic ID of an existing profile picture to reuse (e.g., 0.0.12345)"
),
initialBalance: z.number().positive().optional().describe(
"Optional initial HBAR balance for the new agent account (will create new account if provided)"
),
userAccountId: z.string().optional().describe(
"Optional account ID (e.g., 0.0.12345) to use as the agent account instead of creating a new one"
),
hbarFee: z.number().positive().optional().describe(
"Optional HBAR fee amount to charge per message on the inbound topic"
),
tokenFees: z.array(
z.object({
amount: z.number().positive(),
tokenId: z.string()
})
).optional().describe("Optional token fees to charge per message"),
exemptAccountIds: z.array(z.string()).optional().describe("Optional account IDs to exempt from fees"),
setAsCurrent: z.boolean().optional().describe("Whether to set as current agent (default: true)"),
persistence: z.object({
prefix: z.string().optional()
}).optional().describe("Optional persistence configuration")
});
class RegisterAgentTool extends BaseHCS10TransactionTool {
constructor(params) {
super(params);
this.name = "register_agent";
this.description = 'Creates and registers the AI agent on the Hedera network. Returns JSON string with agent details (accountId, privateKey, topics) on success. Supports natural language for capabilities/tags like "ai", "data processing", "analytics". Note: This tool requires multiple transactions and cannot be used in returnBytes mode. If alias is set to "random" or contains "random", a unique alias will be generated.';
this.specificInputSchema = RegisterAgentZodSchema;
this.neverScheduleThisTool = true;
this.requiresMultipleTransactions = true;
}
async callBuilderMethod(builder, specificArgs) {
const hcs10Builder = builder;
this.specificArgs = specificArgs;
const params = {
name: specificArgs.name
};
if (specificArgs.description !== void 0) {
params.bio = specificArgs.description;
}
if (specificArgs.alias !== void 0) {
params.alias = specificArgs.alias;
} else {
const randomSuffix = Date.now().toString(36);
params.alias = `${specificArgs.name}${randomSuffix}`;
}
if (specificArgs.type !== void 0) {
params.type = specificArgs.type;
}
if (specificArgs.model !== void 0) {
params.model = specificArgs.model;
}
if (specificArgs.tags !== void 0) {
params.capabilities = specificArgs.tags;
} else if (specificArgs.capabilities !== void 0) {
params.capabilities = specificArgs.capabilities;
}
if (specificArgs.creator !== void 0) {
params.creator = specificArgs.creator;
}
if (specificArgs.socials !== void 0) {
params.socials = specificArgs.socials;
}
if (specificArgs.properties !== void 0) {
params.properties = specificArgs.properties;
}
if (specificArgs.profilePicture !== void 0) {
if (typeof specificArgs.profilePicture === "string") {
params.profilePicture = specificArgs.profilePicture;
} else {
const profilePicObj = {};
if (specificArgs.profilePicture.url !== void 0) {
profilePicObj.url = specificArgs.profilePicture.url;
}
if (specificArgs.profilePicture.path !== void 0) {
profilePicObj.path = specificArgs.profilePicture.path;
}
if (specificArgs.profilePicture.filename !== void 0) {
profilePicObj.filename = specificArgs.profilePicture.filename;
}
params.profilePicture = profilePicObj;
}
}
if (specificArgs.existingProfilePictureTopicId !== void 0) {
params.existingProfilePictureTopicId = specificArgs.existingProfilePictureTopicId;
}
if (specificArgs.userAccountId !== void 0) {
params.userAccountId = specificArgs.userAccountId;
}
if (specificArgs.hbarFee !== void 0) {
params.hbarFee = specificArgs.hbarFee;
}
if (specificArgs.tokenFees !== void 0) {
params.tokenFees = specificArgs.tokenFees;
}
if (specificArgs.exemptAccountIds !== void 0) {
params.exemptAccountIds = specificArgs.exemptAccountIds;
}
if (specificArgs.initialBalance !== void 0) {
params.initialBalance = specificArgs.initialBalance;
}
await hcs10Builder.registerAgent(params);
}
/**
* Override _call to intercept the result and save agent to state if needed
*/
async _call(args, runManager) {
const result = await super._call(args, runManager);
const shouldSetAsCurrent = this.specificArgs?.setAsCurrent !== false;
if (this.specificArgs && shouldSetAsCurrent) {
try {
const parsed = JSON.parse(result);
if (parsed.rawResult) {
this._handleRegistrationResult(parsed.rawResult);
} else if (parsed.state || parsed.accountId || parsed.metadata) {
this._handleRegistrationResult(parsed);
}
} catch (e) {
}
}
return result;
}
/**
* Extract agent data from registration result and save to state
*/
_handleRegistrationResult(rawResult) {
let accountId = rawResult.accountId || rawResult.metadata?.accountId;
if (!accountId && rawResult.state?.createdResources) {
const accountResource = rawResult.state.createdResources.find(
(r) => r.startsWith("account:")
);
if (accountResource) {
accountId = accountResource.split(":")[1];
}
}
const inboundTopicId = rawResult.inboundTopicId || rawResult.metadata?.inboundTopicId || rawResult.state?.inboundTopicId;
const outboundTopicId = rawResult.outboundTopicId || rawResult.metadata?.outboundTopicId || rawResult.state?.outboundTopicId;
const profileTopicId = rawResult.profileTopicId || rawResult.metadata?.profileTopicId || rawResult.state?.profileTopicId;
const privateKey = rawResult.privateKey || rawResult.metadata?.privateKey;
if (accountId && inboundTopicId && outboundTopicId && this.specificArgs) {
const registeredAgent = {
name: this.specificArgs.name,
accountId,
inboundTopicId,
outboundTopicId,
profileTopicId,
privateKey
};
const hcs10Builder = this.getServiceBuilder();
const stateManager = hcs10Builder.getStateManager();
if (stateManager) {
stateManager.setCurrentAgent(registeredAgent);
if (stateManager.persistAgentData) {
const prefix = this.specificArgs.persistence?.prefix || this.specificArgs.name.toUpperCase().replace(/[^A-Z0-9]/g, "_");
stateManager.persistAgentData(registeredAgent, {
type: "env-file",
prefix
}).catch(() => {
});
}
}
}
}
}
export {
RegisterAgentTool
};
//# sourceMappingURL=standards-agent-kit.es11.js.map