@zero-agents/core
v0.1.2
Published
ENS-native self-evolving agent framework with persistent 0G tool memory
Maintainers
Readme
@zero-agents/core
ENS-native self-evolving agent framework with persistent tool memory.
@zero-agents/core is the reusable TypeScript framework package for building agents that can discover existing tools, generate new tools, test generated code, store approved tools, remember task outcomes, publish identity metadata, and coordinate with other agents.
This README documents the core package only.
Status
- Package version:
0.1.2 - Runtime: Node.js
>=20 - Module format: ESM only
- Main entry:
@zero-agents/core - Secondary entry:
@zero-agents/core/storage/zero-g - Maturity: alpha; APIs may change before a stable release
Alpha Readiness
The package is ready for external alpha developers. The zero-wallet path includes ToolSandbox, local-mode ToolRegistry, deterministic reflection, experience memory, and local validation.
The full self-evolving agent path requires at least one LLM provider for new tool generation: 0G Compute through ZERO_G_PRIVATE_KEY or OpenAI fallback through OPENAI_API_KEY. Real permanent tool persistence requires 0G Storage credentials. ENS publishing and AXL collaboration are opt-in live integrations that must be validated in the developer's environment.
Repository validation command:
pnpm validate:frameworkCore-package validation command:
pnpm --filter @zero-agents/core validate:installInstall
npm install @zero-agents/coreisolated-vm is a native dependency. If a prebuilt binary is unavailable for your environment, Node native build tooling is required.
Package Exports
Root import:
import {
SelfEvolvingAgent,
ToolRegistry,
ToolSandbox,
ToolEvaluator,
ToolGenerator,
EvolutionEngine,
ExperienceMemory,
StrategyAdapter,
ReflectionEngine,
ToolImprover,
ENSIdentityManager,
AXLClient,
AgentCoordinator,
} from '@zero-agents/core';Default export:
import SelfEvolvingAgent from '@zero-agents/core';0G Storage subpath:
import { uploadToZeroG, downloadFromZeroG } from '@zero-agents/core/storage/zero-g';Main Flow
SelfEvolvingAgent is the reference composition for the framework.
TaskRequest
-> ToolRegistry.searchTools()
-> ExperienceMemory.findSimilarExperiences()
-> StrategyAdapter.selectStrategy()
-> reuse existing tool OR generate new tool OR improve failed tool OR reject
-> ToolSandbox.run()
-> ReflectionEngine.reflect()
-> ExperienceMemory.saveExperience()
-> TaskResultWhen no reusable tool exists, the agent uses EvolutionEngine:
generate tool
-> sandbox smoke run
-> evaluate
-> retry with feedback up to maxGenerationAttempts
-> save passing toolQuickstart
Zero-Wallet Sandbox Smoke Test
This does not require 0G, ENS, AXL, or an LLM key.
import { ToolSandbox } from '@zero-agents/core';
const sandbox = new ToolSandbox({ allowUnsafeNodeVmFallback: true });
const result = await sandbox.run(
`async function execute(params) {
return { sum: params.a + params.b };
}`,
{ a: 2, b: 3 }
);
if (!result.success) {
throw new Error(result.error);
}
console.log(result.output); // { sum: 5 }allowUnsafeNodeVmFallback is only for development. Node's vm module is not a hard security boundary.
To validate both the built package import and local registry behavior from this repository, run pnpm validate:framework.
Agent With Tool Evolution
This example requires 0G Compute or OpenAI fallback for first-time tool generation. It also requires ZERO_G_PRIVATE_KEY for real 0G Storage persistence. Without those credentials, use the zero-wallet smoke test or the demo agent's offline fallback.
import { SelfEvolvingAgent } from '@zero-agents/core';
const agent = new SelfEvolvingAgent({
name: 'research-agent.eth',
description: 'Research agent that learns reusable tools',
capabilities: ['research', 'summarization'],
zeroGPrivateKey: process.env.ZERO_G_PRIVATE_KEY!,
openAiKey: process.env.OPENAI_API_KEY,
axlEnabled: false,
});
agent.on('step', (event) => {
console.log(`[${event.type}] ${event.message}`);
});
const result = await agent.handleTask({
description: 'Fetch the current ETH price and return it as a number',
});
console.log(result.output);
console.log(result.toolUsed);
console.log(result.wasGenerated);
console.log(result.strategy);
console.log(result.reflection?.memoryNote);
agent.dispose();You can also call run() with either a string or a full task object:
await agent.run('Fetch the current ETH price and return it as a number');
await agent.run({ description: 'Fetch ETH price', params: { symbol: 'ETH' } });Environment Variables Used By Core
Core source code reads only these environment variables directly:
| Variable | Used by | Purpose |
|---|---|---|
| ZERO_G_PRIVATE_KEY | ToolRegistry, ToolGenerator, uploadToZeroG | 0G Storage uploads and 0G Compute broker wallet |
| OPENAI_API_KEY | ToolGenerator, ToolEvaluator | OpenAI gpt-4o-mini fallback for tool generation and test-case generation |
Core does not directly read ENS_PRIVATE_KEY, ENS_NAME, or SEPOLIA_RPC_URL. Pass ENS values explicitly to ENSIdentityManager.
Core Agent API
SelfEvolvingAgent
new SelfEvolvingAgent(config: SelfEvolvingAgentConfig | AgentConfig)Full config with 0G and optional identity/AXL:
interface SelfEvolvingAgentConfig {
name: string;
description?: string;
capabilities?: string[];
identity?: AgentIdentityProvider;
zeroGPrivateKey: string;
openAiKey?: string;
axlPort?: number;
registryPath?: string;
axlEnabled?: boolean;
maxGenerationAttempts?: number;
evolutionTimeoutMs?: number;
axlPollIntervalMs?: number;
testCaseTimeoutMs?: number;
allowUnsafeNodeVmFallback?: boolean;
zeroGBlockchainRpc?: string;
zeroGIndexerRpc?: string;
indexCacheTtlMs?: number;
experienceMemoryPath?: string;
registry?: ToolRegistryOptions;
sandbox?: ToolSandboxOptions;
toolGeneration?: ToolGeneratorOptions;
reflection?: ReflectionEngineOptions;
shouldExecute?: (task: TaskRequest) => boolean | Promise<boolean>;
directResponse?: (task: TaskRequest, agent: SelfEvolvingAgent) => unknown | Promise<unknown>;
hooks?: SelfEvolvingAgentHooks;
}Minimal/offline config:
interface AgentConfig {
name: string;
description?: string;
axlPort?: number;
registryPath?: string;
axlEnabled?: boolean;
axlPollIntervalMs?: number;
experienceMemoryPath?: string;
allowUnsafeNodeVmFallback?: boolean;
registry?: ToolRegistryOptions;
sandbox?: ToolSandboxOptions;
toolGeneration?: ToolGeneratorOptions;
reflection?: ReflectionEngineOptions;
shouldExecute?: (task: TaskRequest) => boolean | Promise<boolean>;
directResponse?: (task: TaskRequest, agent: SelfEvolvingAgent) => unknown | Promise<unknown>;
hooks?: SelfEvolvingAgentHooks;
}Extension Points
Applications can customize the framework without monkey-patching prototypes:
const agent = new SelfEvolvingAgent({
name: 'pan-agent',
registry: {
storageMode: 'local',
indexPointerPath: '.pan-tool-index.json',
localStorePath: '.pan-tools.json',
},
toolGeneration: {
systemPromptAppend: 'Handle missing params and API failures safely.',
runtimeHints: [
'Use fetch instead of Node APIs.',
'Do not use require, process, fs, net, or child_process.',
'Return { error: string } for recoverable API failures.',
],
},
sandbox: {
timeoutMs: 15000,
errorOutputKeys: ['error'],
},
reflection: {
errorOutputKeys: ['error'],
},
shouldExecute: (task) => !['hi', 'hello'].includes(task.description.toLowerCase()),
hooks: {
shouldCreateTool: (task) => task.description.trim().length > 8,
afterSandboxRun: (result) => {
console.log('sandbox result', result.success);
},
},
});ToolGenerator accepts tolerant LLM output shapes such as { tool: ... }, { generatedTool: ... }, { result: ... }, arrays, functionCode, and execute. For stricter app-specific behavior, pass toolGeneration.normalizeGeneratedTool or hooks.normalizeGeneratedTool.
ToolSandbox treats returned objects like { error: 'API failed' } as failed executions by default. Set sandbox.errorOutputKeys: [] to disable this semantic failure check.
The built-in agent gate answers trivial greetings and capability questions directly so they do not create useless tools. Override with shouldExecute and directResponse for product-specific routing.
Defaults:
| Option | Default |
|---|---|
| axlPort | 9002 |
| axlEnabled | false |
| maxGenerationAttempts | 3 |
| evolutionTimeoutMs | 120000 |
| axlPollIntervalMs | 500 |
| testCaseTimeoutMs | 30000 |
| allowUnsafeNodeVmFallback | false |
| indexCacheTtlMs | 60000 |
| experienceMemoryPath | .zero-agent-experiences.json in the current working directory |
Methods:
agent.getName(): string
agent.getDescription(): string
agent.getState(): AgentState
agent.evolve(): Promise<void>
agent.publishProfile(toolRegistryHash?: string): Promise<void>
agent.handleTask(task: TaskRequest): Promise<TaskResult>
agent.run(task: string | TaskRequest): Promise<TaskResult>
agent.collaborateWith(otherAgentEnsName: string, task: TaskRequest): Promise<TaskResult>
agent.getRegistry(): ToolRegistry
agent.getEvolutionEngine(): EvolutionEngine
agent.getExperienceMemory(): ExperienceMemory
agent.getStrategyAdapter(): StrategyAdapter
agent.getToolImprover(): ToolImprover
agent.getCoordinator(): AgentCoordinator | null
agent.dispose(): voidEvents:
agent.on('step', (event: AgentStepEvent) => {
console.log(event.type, event.message, event.data);
});Step event types:
searchmissstrategygeneratingsandboxingevaluatingsavingexecutingreflectingdoneerror
Task Types
interface TaskRequest {
description: string;
params?: object;
context?: string;
}
interface TaskResult {
output: unknown;
toolUsed: string;
wasGenerated: boolean;
executionTimeMs: number;
strategy?: StrategyName;
strategyReason?: string;
confidence?: number;
reflection?: ReflectionResult;
experienceId?: string;
wasImproved?: boolean;
}Tools
Generated and imported tools use this shape:
interface Tool {
id: string;
name: string;
description: string;
code: string;
schema: {
input: object;
output: object;
};
tags: string[];
successRate: number;
usageCount: number;
createdAt: number;
rootHash?: string;
}code must be an async JavaScript function expression or declaration named/usable as execute, for example:
async function execute(params) {
return { ok: true, input: params };
}Tool Registry
ToolRegistry stores tools and a metadata index.
new ToolRegistry(options?: ToolRegistryOptions)
new ToolRegistry(indexPointerPath?: string)Options:
interface ToolRegistryOptions {
indexPointerPath?: string;
zeroGPrivateKey?: string;
storageMode?: 'auto' | 'zero-g' | 'local';
localStorePath?: string;
indexCacheTtlMs?: number;
zeroGBlockchainRpc?: string;
zeroGIndexerRpc?: string;
}Storage mode behavior:
autouses 0G when a private key is available, otherwise local JSON.zero-grequireszeroGPrivateKeyorZERO_G_PRIVATE_KEY.localstores JSON blobs locally.- Passing a string constructor argument is treated as an index pointer path and uses local storage.
Default files:
.zero-agent-index.jsonstores the current index root hash pointer..zero-agent-tools.jsonstores local JSON blobs when local mode is active.- Local blob root hashes are deterministic SHA-256 strings prefixed with
local-.
Methods:
registry.saveTool(tool: Tool): Promise<string>
registry.getTool(rootHash: string): Promise<Tool>
registry.getToolByName(name: string): Promise<Tool | null>
registry.getIndexRootHash(): Promise<string | null>
registry.getToolHistory(name: string): Promise<ToolHistory>
registry.searchTools(query: string): Promise<Tool[]>
registry.exportTools(): Promise<Tool[]>
registry.importTool(tool: Tool): Promise<string>
registry.updateIndex(tool: Tool): Promise<string>
registry.updateToolStats(tool: Tool): Promise<string>
registry.loadIndex(): Promise<Map<string, string>>Search behavior:
- Searches name, description, and tags.
- Uses a cached metadata index before loading matched tool blobs.
- Filters weak matches below the internal threshold.
- Sorts by match score and then success rate.
Write behavior:
- Saves are serialized internally to avoid conflicting index writes.
- Tool stats updates require a
rootHash. - One previous root hash per tool name is preserved in index history.
0G Storage Helpers
Subpath:
import { uploadToZeroG, downloadFromZeroG } from '@zero-agents/core/storage/zero-g';interface ZeroGStorageOptions {
privateKey?: string;
blockchainRpc?: string;
indexerRpc?: string;
}Functions:
uploadToZeroG(data: object, options?: ZeroGStorageOptions): Promise<string>
downloadFromZeroG(rootHash: string, options?: Pick<ZeroGStorageOptions, 'indexerRpc'>): Promise<object>Defaults:
| Endpoint | Default |
|---|---|
| 0G EVM RPC | https://evmrpc-testnet.0g.ai |
| 0G indexer | https://indexer-storage-testnet-turbo.0g.ai |
Uploads and downloads retry up to three attempts with exponential backoff.
Tool Generation
ToolGenerator creates tool objects from natural-language task descriptions.
new ToolGenerator(options?: ToolGeneratorOptions)
new ToolGenerator(fallbackToOpenAI?: boolean)
generator.generateTool(taskDescription: string): Promise<Tool>Options:
interface ToolGeneratorOptions {
fallbackToOpenAI?: boolean;
zeroGPrivateKey?: string;
openAiKey?: string;
zeroGBlockchainRpc?: string;
}Provider order:
- 0G Compute through
@0glabs/0g-serving-brokerwhen a 0G private key is available. - OpenAI
gpt-4o-miniwhen fallback is enabled and an OpenAI key is available.
The model must return JSON with:
namedescriptioncodeschema.inputschema.outputtags
The returned tool has successRate: 0, usageCount: 0, and createdAt set. It is not saved by ToolGenerator itself.
Evolution Engine
EvolutionEngine generates, tests, evaluates, retries, and saves tools.
new EvolutionEngine(
generator?: ToolGenerator,
sandbox?: ToolSandbox,
evaluator?: ToolEvaluator,
registry?: ToolRegistry,
evolutionTimeoutMs?: number,
maxGenerationAttempts?: number
)Methods:
engine.evolve(taskDescription: string, sampleParams?: object): Promise<Tool>
engine.generateTool(taskDescription: string, sampleParams?: object): Promise<Tool>Events:
generatingsandboxingevaluatingsaving
Defaults:
maxGenerationAttempts:3evolutionTimeoutMs:120000- evaluation pass threshold:
score >= 0.7
If all attempts fail, ToolGenerationError is thrown with an attempts count.
Sandbox
ToolSandbox executes generated JavaScript tools.
new ToolSandbox(options?: ToolSandboxOptions)
sandbox.run(toolCode: string, params: object, timeoutMs?: number): Promise<SandboxResult>Options:
interface ToolSandboxOptions {
allowUnsafeNodeVmFallback?: boolean;
allowedFetchHostnames?: string[];
maxFetchResponseBytes?: number;
}Result:
interface SandboxResult {
success: boolean;
output: unknown;
error?: string;
executionTimeMs: number;
}Behavior:
- Prefers
isolated-vmwith a 16 MB isolate memory limit. - Default execution timeout is
3000msunless overridden per run. - Fails closed if
isolated-vmis unavailable andallowUnsafeNodeVmFallbackis not enabled. - Provides
fetchthrough a limited bridge. - Supports optional hostname allowlisting for
fetch. - Limits fetched response bodies to
1 MiBby default. - Shadows dangerous globals such as
require,process,Function,eval,fs,child_process,net, andhttp.
Security note: allowUnsafeNodeVmFallback uses Node's vm module and should not be treated as a production sandbox for hostile code.
Tool Evaluation
ToolEvaluator scores a tool by running test cases through ToolSandbox.
new ToolEvaluator(sandbox?: ToolSandbox, openAiKey?: string, testCaseTimeoutMs?: number)
evaluator.evaluate(tool: Tool, testCases?: TestCase[]): Promise<EvalResult>Types:
interface TestCase {
input: object;
expectedOutput?: unknown;
description: string;
}
interface TestCaseResult {
testCase: TestCase;
passed: boolean;
result: SandboxResult;
}
interface EvalResult {
score: number;
passed: boolean;
testResults: TestCaseResult[];
feedback: string;
}Behavior:
- If test cases are provided, those are used directly.
- Otherwise, OpenAI
gpt-4o-miniis used to generate two basic test cases when an OpenAI key is available. - Without an OpenAI key, one schema-derived smoke test is used.
- If
expectedOutputis present, output must exactly match by JSON serialization. - If
expectedOutputis absent, output must match the declared output schema. - Empty output schemas do not pass without explicit expected output.
- Pass threshold is
score >= 0.7.
Experience Memory
ExperienceMemory stores task outcomes separately from executable tools.
new ExperienceMemory(options?: ExperienceMemoryOptions)Options:
interface ExperienceMemoryOptions {
filePath?: string;
zeroG?: ZeroGStorageOptions;
persistToZeroG?: boolean;
}Record shape:
interface ExperienceRecord {
id: string;
agentName: string;
task: string;
strategy: string;
toolUsed?: string;
resultSummary?: string;
success: boolean;
qualityScore: number;
reflection?: ReflectionResult;
createdAt: number;
storageHash?: string;
metadata?: Record<string, unknown>;
}Methods:
memory.saveExperience(experience): Promise<ExperienceRecord>
memory.listExperiences(agentName?: string): Promise<ExperienceRecord[]>
memory.findSimilarExperiences(task: string, limit?: number): Promise<ExperienceRecord[]>
memory.clearExperiences(): Promise<void>Defaults and behavior:
- Default file:
.zero-agent-experiences.jsonin the current working directory. - Similarity is deterministic term matching.
qualityScoreis clamped to0..100.- 0G persistence is opt-in with
persistToZeroG;SelfEvolvingAgentuses local JSON by default.
Strategy Adapter
StrategyAdapter chooses what the agent should try before execution.
new StrategyAdapter()
strategy.selectStrategy(input: StrategyAdapterInput): StrategyDecisionStrategies:
reuse_existing_toolgenerate_new_toolimprove_existing_toolask_another_agentreject_task
Input and output:
interface StrategyAdapterInput {
task: string;
agentName?: string;
availableTools?: Tool[];
similarExperiences?: ExperienceRecord[];
}
interface StrategyDecision {
strategy: StrategyName;
confidence: number;
reason: string;
selectedToolName?: string;
selectedToolId?: string;
}Current deterministic behavior:
- High-quality similar success with a tool prefers reuse.
- Relevant existing tool prefers reuse.
- Similar failure with the same relevant tool prefers improvement.
- No useful tool or experience prefers generation.
The strategy type includes ask_another_agent and reject_task, but the current adapter does not actively select them.
Reflection Engine
ReflectionEngine creates post-task learning data without an external API call.
new ReflectionEngine()
reflection.reflect(input: ReflectionInput): ReflectionResultResult:
interface ReflectionResult {
success: boolean;
qualityScore: number;
whatWorked: string;
whatFailed: string;
improvementNeeded: boolean;
memoryNote: string;
recommendedStrategy: RecommendedStrategy;
}Scoring behavior:
- Failed result:
0 - Successful result: starts at
80 - Adds
10when a tool was used - Adds
5when execution time is<= 5000ms - Caps at
100
Tool Improver
ToolImprover asks a configured generator to produce an improved candidate for a failed or low-quality tool.
new ToolImprover(options?: ToolImproverOptions)
improver.improveTool(input: ToolImproverInput): Promise<ImprovedToolCandidate>Important behavior:
- Requires a generator with
generateTool(taskDescription). - Does not save or evaluate by itself.
SelfEvolvingAgentevaluates and saves an improved tool only when the improved candidate passes evaluation.- Version bumps patch versions like
1.0.0 -> 1.0.1; unknown versions become<version>.1.
ENS Identity
ENSIdentityManager implements AgentIdentityProvider with Sepolia ENS text records.
new ENSIdentityManager({
ensName?: string,
privateKey: string,
rpcUrl?: string,
})Default RPC:
https://sepolia.drpc.orgText records:
descriptioncapabilitieszeroagent.toolRegistryzeroagent.axlPeerIdurl
Methods:
ENSIdentityManager.autoDetect(privateKey: string, rpcUrl?: string): Promise<ENSIdentityManager | null>
identity.detectPrimaryName(): Promise<string | null>
identity.resolveAllNames(): Promise<string[]>
identity.getWalletAddress(): string
identity.hasEnsNameConfigured(): boolean
identity.resolveAddress(): Promise<string | null>
identity.getCapabilities(): Promise<string[]>
identity.getToolRegistryHash(): Promise<string | null>
identity.getAXLPeerId(): Promise<string | null>
identity.getAXLPeerIdForName(ensName: string): Promise<string | null>
identity.getProfile(): Promise<AgentProfile | null>
identity.setProfile(profile: AgentProfile): Promise<void>
identity.setToolRegistryHash(rootHash: string): Promise<void>
identity.setAXLPeerId(peerId: string): Promise<void>
identity.setAgentProfile(profile: AgentProfile): Promise<void>
identity.discoverAgentsByCapability(capability: string, knownAgentNames: string[]): Promise<string[]>SelfEvolvingAgent can auto-detect an ENS identity when no identity provider is passed and a 0G private key is available. This uses reverse ENS lookup for the wallet's primary name.
ENS writes require:
- A private key for the wallet that controls the ENS resolver.
- Sepolia ETH for gas.
- A resolver configured for the ENS name.
AXL Communication
AXLClient talks to a local Gensyn AXL HTTP node.
new AXLClient(config?: AXLClientConfig)Options:
interface AXLClientConfig {
axlPort?: number;
taskTimeoutMs?: number;
pollIntervalMs?: number;
}Defaults:
- Base URL:
http://localhost:9002 - Task timeout:
30000ms - Poll interval:
500ms
Methods:
axl.getPeerId(): Promise<string>
axl.sendMessage(toPeerId: string, message: AgentMessage): Promise<void>
axl.startListening(onMessage: (msg: AgentMessage, fromPeerId: string) => void): Promise<void>
axl.stopListening(onMessage): void
axl.stop(): void
axl.sendTask(toPeerId: string, task: TaskRequest): Promise<TaskResult>Endpoint behavior:
- Peer lookup tries
/info, then/topology. - Polling tries
/messages, then/recv. - Sending uses
POST /sendwithX-Destination-Peer-Id.
Message types:
interface AgentMessage {
type: 'task_request' | 'task_result' | 'tool_share' | 'ping';
requestId: string;
payload: unknown;
fromAgent?: string;
timestamp: number;
}AgentCoordinator routes AXL messages to a local agent.
new AgentCoordinator({ agent, registry, axlClient? })
coordinator.start(): Promise<void>
coordinator.stop(): void
coordinator.shareToolLibrary(toPeerId: string): Promise<void>Inbound behavior:
task_requestcalls localagent.handleTask()and sends atask_result.tool_sharevalidates the payload and imports the tool into the registry.- Tool-share import rejects code with dangerous patterns such as
require,process,eval, dynamicimport,new Function,Proxy,Reflect,__proto__, and prototype mutation helpers.
SelfEvolvingAgent starts AXL only when axlEnabled: true. If AXL initialization fails, it emits an error step and continues without P2P.
Custom Identity Providers
You can provide your own identity backend by implementing AgentIdentityProvider.
interface AgentIdentityProvider {
getProfile(): Promise<AgentProfile | null>;
setProfile(profile: AgentProfile): Promise<void>;
getToolRegistryHash(): Promise<string | null>;
setToolRegistryHash(rootHash: string): Promise<void>;
setAXLPeerId?(peerId: string): Promise<void>;
getAXLPeerIdForName?(ensName: string): Promise<string | null>;
}
interface AgentProfile {
description: string;
capabilities: string[];
toolRegistryHash: string;
axlPeerId?: string;
url?: string;
}Errors
Custom error classes exported by the package:
class ZeroAgentError extends Error {
readonly code: string;
}
class ToolGenerationError extends ZeroAgentError {
readonly attempts: number;
}
class SandboxError extends ZeroAgentError {}
class EvaluationError extends ZeroAgentError {}
class StorageError extends ZeroAgentError {}
class AXLError extends ZeroAgentError {}Codes:
| Error | Code |
|---|---|
| ToolGenerationError | TOOL_GENERATION_ERROR |
| SandboxError | SANDBOX_ERROR |
| EvaluationError | EVALUATION_ERROR |
| StorageError | STORAGE_ERROR |
| AXLError | AXL_ERROR |
Not every thrown error is currently a custom ZeroAgentError. Some validation, ENS, and orchestration failures throw plain Error.
Type Exports
Agent types:
SelfEvolvingAgentConfigAgentConfigAgentStateAgentStepEventTaskRequestTaskResult
Tool and storage types:
ToolToolHistoryToolRegistryOptionsZeroGStorageOptions
Generation, sandbox, and evaluation types:
ToolGeneratorOptionsToolSandboxOptionsSandboxResultEvalResultTestCaseTestCaseResult
Memory, strategy, reflection, and improvement types:
ExperienceRecordStrategyAdapterInputStrategyDecisionStrategyNameReflectionInputReflectionResultRecommendedStrategyImprovedToolCandidateOriginalToolForImprovementToolImproverInputToolImproverOptions
Identity and communication types:
AgentIdentityProviderAgentProfileENSIdentityManagerConfigAgentMessageAXLClientConfigAgentCoordinatorConfig
Local Development Notes
The package is designed to work without live sponsor infrastructure for local framework development.
- No 0G key:
ToolRegistrycan use local JSON storage. - No OpenAI key:
ToolEvaluatoruses schema-derived smoke tests. - No ENS identity:
publishProfile()is a no-op unless an identity provider is configured or auto-detected. - No AXL node: AXL is not started unless
axlEnabled: true; failed AXL initialization does not stop the agent.
Minimal local agent example:
const agent = new SelfEvolvingAgent({
name: 'local-agent',
allowUnsafeNodeVmFallback: true,
axlEnabled: false,
});This can reuse locally stored tools, but it cannot generate new tools unless 0G Compute or OpenAI credentials are available.
Important Limitations
- Tools are stored as 0G Storage blobs or local JSON blobs, not as Ethereum contract state.
- Experience memory is local JSON by default; 0G experience persistence is opt-in only when using
ExperienceMemorydirectly. ask_another_agentandreject_taskexist in the strategy type, but the current deterministic adapter does not actively select them.- AXL delegation through
collaborateWith()requires an identity provider that can resolvezeroagent.axlPeerIdfor the target name. ToolGeneratordepends on 0G Compute or OpenAI availability and model output quality.ToolEvaluatoris a basic approval gate, not a formal verifier.isolated-vmis the intended sandbox path; Nodevmfallback is development-only.- For production use with hostile generated code, add process/container isolation and strict network policy around tool execution.
- ENS auto-detection depends on reverse ENS lookup and a Sepolia-compatible RPC.
Build From Source
pnpm --filter @zero-agents/core build
pnpm --filter @zero-agents/core test:unitPublished Files
The npm package publishes:
dist/README.mdLICENSE
Tests and TypeScript source files are not included in the published package.
Repository
https://github.com/Amirjaved-dev/zero-agents
License
MIT
