Node agent tool
A command-line tool for ICRC-1 ledgers that a person or an AI agent runs with
Node 22.18 or newer (node src/cli.ts <command>, no build step). It is
@ic-reactor/core with no React at all, one scenario per file:
- Identity: a fixed
Identityfrom a PEM file (Ed25519 or secp256k1, asicp identity exportprints it) or a hex seed, elseidentity: "anonymous", whose writes the client refuses before sending. Give it an identity of its own that holds little and controls nothing (icp identity new agent-tool --output-seed <file>, which writes the seed phrase to a file instead of printing it, orpnpm exec icpinside the example), never one that controls a canister, and export its key outside the project, readable by you alone. An agent that runs the tool can read its environment, the seed variable included, and so can sign whatever the tool can. - Networks:
--network ic|local|<url>ontocreateClient’snetwork. A root key is fetched only from a replica on this machine; any other URL needs the key given. - Many ledgers, one interface: ICP, ckBTC, ckETH or any ledger id, each
client.canister<Actor>(actor, { id })over one generated module. - Direct calls:
infoandbalancecall the ledger’s methods directly, in parallel;--certifiedreads through{ id, certified: true }. - Writes:
transferreads the amount withparseUnits, pays the ledger’s fee and setscreated_at_time. Every failure goes throughisReactorErrorand akindswitch, with an exit code per kind. After a failure that may have executed, it reads the balance back and prints the command that re-sends the same argument, which the ledger answersDuplicateif the first went through. - JSON for agents:
--jsonon every command, one document per line, bigints as decimal strings, failures as{ ok: false, kind, mayHaveExecuted, message }. - The cache outside React:
watchpolls a balance throughclient.queryClient.fetchQuery(client.queryOptions(...)), prints only changes, and disposes the client on Ctrl-C. - Every failure, narrated:
pnpm demoruns the same commands oncreateTestClient()from@ic-reactor/core/testing, with a mocked ledger: a lost reply and its deduplicated re-send, an HTTP 429 the client re-sends by itself, a canister reject, a signed-out write, and input refused before sending. No network, no funds.
Read The client and
Errors and mayHaveExecuted for the rules it follows, and
Testing for createTestClient().
Give an agent a canister’s tools builds the same
ledger as MCP tools, step by step.
pnpm --filter node-agent-tool democd examples/node-agent-toolnode src/cli.ts info --ledger ckbtcnode src/cli.ts balance rkp4c-7iaaa-aaaaa-aaaca-cai --certified --jsonpnpm testStackBlitz installs the example from npm and runs the demo (npm run demo)
in its terminal, where npm test runs the tests. The demo and the CLI run
their .ts files with Node’s type stripping, so they need Node 22.18 or later,
there as on your machine. The commands that call a ledger on mainnet or on a
local network, and a PEM identity from your disk, are for your own machine.