Package Exports
- @iicp/client
- @iicp/client/cli
Readme
iicp-client · TypeScript / JavaScript SDK
Official TypeScript client library for the IICP protocol — route AI agent tasks by intent across a self-organising mesh of provider nodes. No central broker. No hardcoded endpoints.
Works in Node.js ≥ 18, Deno, Bun, and modern browsers with the native Fetch API.
urn:iicp:intent:llm:chat:v1 → discover → select → submitInstall
npm install iicp-client
# yarn add iicp-client
# pnpm add iicp-clientUpgrade note (0.5.3) — if you operate a node and use the native IICP TCP transport on port 9484, upgrade to
^0.5.3. Releases 0.5.0–0.5.2 emitted a non-standard CBOR dialect that does not interoperate with the Python or Rust SDK on the binary transport. The HTTP/v1/taskpath is unaffected. SeeCHANGELOG.mdfor details.
Quickstart
import { IicpClient } from "iicp-client";
const client = new IicpClient({ directory_url: "https://iicp.network" });
// chat() discovers, selects the best node, and submits in one call
const response = await client.chat(
[{ role: "user", content: "Hello from IICP!" }],
);
console.log(response.choices[0].message.content);For more control over node selection:
const nodes = await client.discover("urn:iicp:intent:llm:chat:v1");
if (!nodes.length) throw new Error("No nodes available");
const result = await client.submit({
intent: "urn:iicp:intent:llm:chat:v1",
payload: { messages: [{ role: "user", content: "Hello!" }] },
});Configuration
import { IicpClient } from "iicp-client";
const client = new IicpClient({
directory_url : "https://iicp.network", // IICP directory
timeout_ms : 30_000, // max 120 000 (SDK-04)
region : "eu-central", // prefer nodes in region
api_token : "your-token", // optional auth token
});| Option | Default | Description |
|---|---|---|
directory_url |
"https://iicp.network" |
IICP directory endpoint |
timeout_ms |
30000 |
Request timeout — max 120 000 ms |
region |
undefined |
Preferred node region |
api_token |
undefined |
Bearer token for authenticated nodes |
Discover options
const nodes = await client.discover("urn:iicp:intent:llm:chat:v1", {
region : "eu-central",
model : "phi3:mini",
min_reputation: 0.7,
limit : 5,
});Error handling
import { IicpClient, IicpError } from "iicp-client";
const client = new IicpClient();
try {
const response = await client.chat([{ role: "user", content: "hi" }]);
} catch (e) {
if (e instanceof IicpError) {
console.error(`[${e.code}] ${e.message} (HTTP ${e.status_code})`);
}
}Error codes match the IICP error reference — e.g. task_timeout, capacity_exceeded, no_nodes_available.
Serving as a provider node
import { IicpNode } from "iicp-client";
const node = new IicpNode({
nodeId : "my-node-001",
endpoint: "http://my.public.host:8020",
intent : "urn:iicp:intent:llm:chat:v1",
model : "llama3:8b",
});
const token = await node.register();
const stop = node.serve(async (task) => {
// Return the inner result value — serve() wraps it in {result: ...}
return { choices: [{ message: { role: "assistant", content: "Hello!" } }] };
}, { port: 8020, nodeToken: token });
process.on("SIGINT", () => { stop(); });NAT traversal — v0.7.0
IICP nodes pick the best available NAT path automatically (ADR-041):
| Tier | Method | Requirement |
|---|---|---|
| 0 | Direct — publicly routable | Open port 8020 |
| 1 | UPnP/IGD port mapping | Home router with UPnP |
| 2 | IPv6 firewall pinhole | IPv6 + UPnP/IGD2 |
| 3 | Relay-as-last-resort | A relay operator in the mesh |
Relay-as-last-resort lets a node behind CGNAT stay reachable by binding an outbound channel to a public relay node that forwards inbound tasks down it.
Running a relay-capable node (relay operator)
const node = new IicpNode({
nodeId : "relay-eu-01",
endpoint : "http://relay.example.com:8020",
intent : "urn:iicp:intent:llm:chat:v1",
relayCapable : true, // accept RELAY_BIND on TCP port 9485
relayAcceptPort: 9485,
enableMesh : true, // gossip relayCapable=true to peers
});Node behind CGNAT (connects outbound to relay)
const node = new IicpNode({
nodeId : "cgnat-worker-001",
endpoint : "http://placeholder", // overwritten on bind
intent : "urn:iicp:intent:llm:chat:v1",
relayWorkerEndpoint : "relay.example.com:9485", // outbound target
// or: env IICP_RELAY_WORKER_ENDPOINT=relay.example.com:9485
});When the worker binds it re-registers with the relay's public address
(transport_method: "turn_relay"), making it discoverable.
SDK conformance
| Rule | Description | Status |
|---|---|---|
| SDK-01 | discover → select → submit pipeline with node retry | ✓ |
| SDK-02 | task_id auto-generated (UUID v4) |
✓ |
| SDK-03 | Intent URN pattern validation | ✓ |
| SDK-04 | timeout_ms capped at 120 000 ms |
✓ |
| SDK-05 | Retry on 429 / 503 with exponential back-off | ✓ |
| SDK-06 | W3C traceparent propagation |
✓ |
Conformance tier: iicp:sdk:v1 (spec S.14) · Request a badge
Development
npm install # install deps
npm run typecheck # tsc strict
npm test # 184 unit tests
npm run build # emit to dist/Links
- Protocol spec — full IICP specification
- Node setup guide — run your own node
- Error reference — all error codes
- iicp-client-python — Python SDK
- iicp-client-rust — Rust SDK
Apache 2.0 · iicp.network