Private beta

Request beta access

Interagentic is in private beta. Leave your email and we'll send you an access key when there's room.

Interagentic
SDK

SDK

@interagentic/sdk — an agent identity, signed tokens and authenticated requests from Node.js.

@interagentic/sdk is the library the interagentic CLI is built on. It gives a Node.js process an identity on a broker, keeps that identity's key fresh, and produces the credential that proves who is calling.

npm install @interagentic/sdk

The package ships ESM and CommonJS builds with type declarations. It keeps its state on disk through node:fs, so it runs in Node.js, not in a browser.

Quick start

import { InteragenticClient } from "@interagentic/sdk";

const client = new InteragenticClient();

// The first call registers a namespace and stores its key.
// Later calls rotate the key before it goes stale.
const res = await client.fetch("https://api.example.com/v1/items");
console.log(res.status, await res.json());

For a script that needs nothing else, interagenticFetch(url, init) does the same through a shared default client:

import { interagenticFetch } from "@interagentic/sdk";

const res = await interagenticFetch("https://api.example.com/v1/items");

new InteragenticClient(options?)

Every option is optional. An option passed to the constructor wins over the environment variable.

OptionEnvironment variableDefaultPurpose
serverUrlINTERAGENTIC_SERVER_URLhttps://id.interagentic.devIdentity broker
stateDirINTERAGENTIC_STATE_DIR~/.interagenticWhere the identity and keys live
proxyUrlINTERAGENTIC_PROXY_URLhttps://keychains.devCredential proxy used by fetch
algorithm—"EdDSA"Key type for new keys: "EdDSA" (Ed25519) or "ES256"
rotationTTL—15Minutes a key stays fresh before it must be rotated
inviteTokenINTERAGENTIC_INVITE_TOKEN—Used on first registration: register under an inviting namespace, or join an organization

The state directory holds the same files as the CLI's — see state on disk — so a program and the CLI on one machine share one identity. A stable API key is read from INTERAGENTIC_STABLE_API_KEY, or from credentials.json in the state directory.

client.fetch(url, init?)

Takes the same arguments as the global fetch and returns a standard Response.

  • The request is sent through the credential proxy: url is rewritten to <proxyUrl>/<host><path>?<query>, and the token from generateToken() is sent in X-Proxy-Authorization: Bearer …. Your own headers and body pass through unchanged.
  • A 401 with code KEY_STALE rotates the key and retries once.
  • A 403 with code wrong_proxy retries once through the proxy the response names.
  • Approval, permission, link, payment and lock responses are thrown as typed errors. Any other status is returned for you to handle.

client.generateToken(claims?)

Returns the credential for this agent, as a string ready for Authorization: Bearer … on a service that accepts it directly.

  • With a stable API key configured, it returns that key unchanged.
  • Otherwise it registers a namespace if the state directory has none, completes a rotation that was interrupted, rotates the key when it is within a minute of going stale, and returns a JWT signed with the agent's private key. The token expires after five minutes, carries the key id in its kid header, and includes any claims you pass.
const token = await client.generateToken();

await fetch("https://api.example.com/v1/items", {
  headers: { Authorization: `Bearer ${token}` },
});

client.getCredits({ cursor?, limit? })

Reads the linked human's balance and this agent's own spending from GET /api/v1/payments/credits on the broker.

const { credits, ledger } = await client.getCredits({ limit: 25 });

console.log(`${credits} credits available`);
for (const entry of ledger.data) {
  console.log(entry.createdAt, entry.service, entry.description);
}
FieldMeaning
namespaceThe agent the ledger belongs to
creditsBalance of the linked human account, in credits
balanceAtomicThe same balance in integer units — one credit is 1,000,000
cashEquivalent{ amount, currency: "USD" } — the usage equivalent of the balance
accountWideAlways true: every agent linked to the account shares the balance
ledger.dataThis agent's debits, newest first, with amounts in integer units
ledger.pagination{ cursor, hasMore } — pass cursor back to read the next page

limit is between 1 and 100 and defaults to 25. An agent that is not linked to a human gets an error that tells it to run interagentic link.

Errors

Every error the SDK throws for a protocol response extends InteragenticError, which carries code, message, statusCode and, when a person has to act, actionUrl.

ClassThrown when
NamespaceLockedErrorThe namespace is locked (423); actionUrl is the unlock page
PaymentRequiredErrorPayment is required (402); also carries amount and service
InsufficientPermissionErrorA permission or scope is missing (403); also carries missingScopes
LinkRequiredErrorA human has to link the agent or approve a credential
import { InteragenticClient, LinkRequiredError } from "@interagentic/sdk";

try {
  await new InteragenticClient().fetch("https://api.example.com/v1/items");
} catch (err) {
  if (err instanceof LinkRequiredError) console.log("Open:", err.actionUrl);
  else throw err;
}

Everything else

The client also covers what the CLI does:

AreaMethods
Identityregister, ensureRegistered, whoami, info, link, destroy, reset
Keysclient.keys.list, add, update, rotate, invalidate, delete, and client.key(id)
Stable API keyscreateApiKey, listApiKeys, revokeApiKey
OrganizationslistOrgs, createOrg, setActAs, createOrgInvite, redeemOrgInvite, listOrgMembers, updateMemberRole, removeOrgMember, quitOrg, deleteOrg
ServicesfetchServiceIndex, fetchServiceAction, executeServiceAction

On this page