Skip to main content

/docs/quickstart-cip · CIP client / consumer

CIP consumer guide — dispatch a cooperative inference task

Cooperative Inference Profile (CIP) lets a proxy node distribute inference tasks across multiple worker nodes on the mesh — for redundancy, quality comparison, or load spreading. This guide is the client/consumer side: the four API calls needed to dispatch and settle a CIP task.

Setting up your own node as a CIP worker (provider side)? See CIP worker setup.

Heads up: this is an advanced, developer-side guide — the API calls to spread one task across several worker nodes (for redundancy or quality voting). If you just want to use the mesh, iicp-node query or chat() is all you need. The full CIP walkthrough is below.
Prerequisites: You need a registered node with a valid node_token and a non-zero credit balance. Follow node setup first if you haven't registered yet. CIP requires at least one other node in the mesh with allow_remote_inference = true.

Coordinator dispatch gates (spec §2.2)

When CIP coordination is enabled, the four steps below happen automatically on every request. The coordinator evaluates all §2.2 consumer gates (credit check, sensitivity, reputation, trusted peers) on every request and dispatches to an eligible worker when the conditions pass. These are the normative spec §2.2 parameters the coordinator evaluates (shown below in illustrative form) — not a client-SDK config file. The client SDKs have no .toml config; the iicp-node CLI is configured purely with flags and IICP_* environment variables.

# CIP consumer-gate parameters — spec §2.2, evaluated by the coordinator
# (illustrative — these are protocol parameters, not an SDK config file):
enabled                = true          # opt in to consumer dispatch (off by default)
strategy               = "local-first" # "local-first" | "remote-first" | "balanced"
max_credits_per_task   = 10.0          # per-sub-task credit ceiling
session_credit_budget  = 50.0          # session total ceiling; omit for unlimited
min_reputation         = 0.5           # exclude workers below this score (0.0–1.0)
trusted_peers          = []            # restrict to these node IDs; empty = open mesh
send_sensitive_prompts = false         # §10.2: MUST stay false for high-sensitivity tasks
coordinator_timeout_ms = 30000         # §6: total task budget; worker_timeout = 60% (18 s)

session_credit_budget caps total credit spend across all CIP tasks in one proxy session — once exhausted, further tasks are served locally (conformance: CIP-CALL-03). Omit it for unlimited. min_reputation is enforced at dispatch time — workers whose reputation_score is below the threshold are excluded from the eligible pool before any sub-task is sent (conformance: CIP-CALL-02). The score is an evolving routing-history signal rather than an uptime, quality, or fraud certificate. The deployed model currently mixes reported outcomes and latency, so use a non-zero filter only when that evidence basis fits your policy. send_sensitive_prompts defaults to false per the spec and must be explicitly opted in — requests tagged sensitivity: high are always served locally when this is false. coordinator_timeout_ms is the total budget for a CIP task; workers receive 60% of this (18 s at the 30 s default) per the §6 formula. If all workers time out and a local model is available, the proxy falls back automatically — otherwise IICP-E024 is returned.

The steps below show the raw HTTP calls the proxy makes internally — useful if you are building a custom coordinator or want to understand what happens under the hood.

1

Pre-flight: check credits and cost estimate

Before dispatching a CIP task, check whether your credit balance covers the estimated cost. The directory returns both the estimate and your current balance in one call.

curl -s "https://iicp.network/api/v1/credits/quote?intent=urn:iicp:intent:llm:chat:v1&max_tokens=2000" \
  -H "Authorization: Bearer <your_node_token>"
{
  "quote_id": "q_01HWXYZ...",
  "intent": "urn:iicp:intent:llm:chat:v1",
  "max_tokens": 2000,
  "estimated_credits": 2.0,
  "min_credits": 1.0,
  "max_credits": 3.0,
  "price_per_1000_tokens": 1,
  "currency": "iicp_credits",
  "nodes_quoted": 3,
  "consumer_balance": 15.40,
  "effective_balance": 42.00,
  "balance_scope": "operator_wallet",
  "operator_wallet_balance": 42.00,
  "balance_sufficient": true,
  "quote_expires_at": "2026-05-20T00:05:00Z"
}
If balance_sufficient is false, your effective balance is below the estimated cost. Operator-bound nodes use the pooled operator wallet; unbound nodes use node-local credits. You must fall back to local execution — do not dispatch to remote workers. Credits are earned by serving tasks; see why run a node.
2

Discover available CIP workers

Find nodes that have opted in to cooperative inference and meet your quality bar. Filter by min_reputation to exclude low-trust nodes.

curl -s "https://iicp.network/api/v1/discover?view=public&intent=urn:iicp:intent:llm:chat:v1&min_reputation=0.5" \
  -H "Authorization: Bearer <your_node_token>"
{
  "nodes": [
    {
      "node_id": "550e8400-...",
      "endpoint": "https://node.example.com",
      "region": "eu-central",
      "reputation_score": 0.72,
      "reputation_tier": "gold",
      "cip_conformance_level": "CIP-Provider",
      "cip_policy": {
        "allow_remote_inference": true
      },
      "available": true
    }
  ],
  "count": 1
}
Only nodes with cip_conformance_level: "CIP-Provider" (or cip_policy.allow_remote_inference = true) accept CIP sub-tasks. Filter your candidate list to those nodes before dispatching. Prefer reputation_tier of silver, gold, or platinum for reliable results.
3

Dispatch the CIP task to a worker

Send the CALL directly to the worker adapter. The cip envelope carries cip_role: "worker" so the adapter enforces its CIP policy gate (S.12 §2.1). The trace object carries cip_role: "coordinator" (S.12 §4.2 MUST) so the worker knows the request originates from a CIP coordinator. Supply cip_parent_task_id and cip_session_key for audit traceability and session binding (§10.4).

curl -s -X POST "https://node.example.com/v1/task" \
  -H "Authorization: Bearer <worker_node_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "task_id": "t_01HWXYZ...",
    "intent": "urn:iicp:intent:llm:chat:v1",
    "payload": {
      "messages": [{"role": "user", "content": "Summarise the IICP protocol in one paragraph."}]
    },
    "constraints": { "timeout_ms": 30000 },
    "auth": { "node_token": "<worker_node_token>" },
    "trace": {
      "trace_id": "trace_XYZ...",
      "cip_role": "coordinator"
    },
    "cip": {
      "cip_role": "worker",
      "cip_parent_task_id": "t_PARENT...",
      "cip_session_key": "sess_ABC123"
    }
  }'
{
  "task_id": "t_01HWXYZ...",
  "status": "success",
  "result": {
    "content": "IICP is an open protocol for intent-based routing..."
  },
  "metrics": { "latency_ms": 1240, "tokens_used": 312 },
  "trace": {
    "cip_role": "worker",
    "cip_session_key": "sess_ABC123"
  },
  "cip_receipt": {
    "task_id": "t_01HWXYZ...",
    "worker_node_id": "550e8400-...",
    "tokens_used": 312,
    "cip_parent_task_id": "t_PARENT...",
    "cip_session_key": "sess_ABC123",
    "nonce": "a3f8c2d1-...",
    "issued_at": "2026-05-22T00:00:00Z",
    "expires_at": "2026-05-22T00:05:00Z",
    "signature": "<HMAC-SHA256 hex, 64 chars>"
  }
}
The outbound CALL carries two role fields: trace.cip_role = "coordinator" (S.12 §4.2 MUST — set by the proxy) and cip.cip_role = "worker" (S.12 §4.1 MUST — tells the adapter to execute as a CIP worker). The worker RESPONSE echoes trace.cip_role = "worker" and trace.cip_session_key unchanged (§10.4 session binding). The proxy enforces this automatically (CIP-BIND-01): if the echoed key is missing or does not match, the response is discarded and the next candidate is tried — no manual check required. The cip_receipt is the signed HMAC proof the coordinator forwards to the directory for credit settlement.
4

Forward the credit receipt

The worker RESPONSE contains a signed cip_receipt. The coordinator(your proxy) extracts this receipt and forwards it to the directory to credit the worker. The worker itself never contacts the directory — it only includes the receipt in its RESPONSE. The proxy's submit_award() function handles this automatically.

# Forwarded by the coordinator proxy after receiving the worker RESPONSE
curl -s -X POST "https://iicp.network/api/v1/credits/award" \
  -H "Authorization: Bearer <worker_node_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "node_id": "550e8400-...",
    "task_id": "t_01HWXYZ...",
    "tokens_used": 312,
    "amount": 0.312,
    "cip_parent_task_id": "t_PARENT...",
    "cip_session_key": "sess_ABC123",
    "nonce": "a3f8c2d1-...",
    "expires_at": "2026-05-22T00:05:00Z",
    "response_hash": "<64-char hex SHA-256 of the worker response>",
    "signature": "<HMAC-SHA256 of canonical message>"
  }'
{
  "node_id": "550e8400-...",
  "awarded": 0.312,
  "balance": 0.312,
  "spent": 0.312,
  "spend_reason": null
}
Canonical HMAC message format (S.12 §10.3): task_id:tokens_used:cip_parent_task_id:cip_session_key:nonce:response_hash(base form). When querying_node_id is present (CIP v0.6.11+), appended as …:response_hash:querying_node_id. Signed with node_hmac_key (returned at registration). The adapter signs this automatically — no manual signing needed unless you are building a custom adapter.

Want to run a CIP worker and earn credits?

Every coordinator above dispatches to your node if you opt in. Set one environment variable and restart — the directory promotes you to CIP-Provider automatically. Same for the Python, TypeScript, and Rust iicp-node CLI.

export IICP_CIP_ALLOW_WORKER=true   # opt in to CIP Provider mode
export IICP_MAX_CONCURRENT=4         # cap simultaneous tasks (default 4)

iicp-node serve

Restart your node — it will re-register as a CIP Provider. Coordinators discover you via cip_conformance_level: "CIP-Provider" in the discover response. Credits appear in your balance after each sub-task. Full CIP worker setup guide →

Common error cases

IICP-E022HTTP 503

When: No eligible CIP workers found — either no nodes have allow_remote_inference = true, all candidates are below the proxy's min_reputation threshold, trusted_peers excludes all discovered nodes, or session_credit_budget is exhausted (tasks silently fall back to local when budget is spent — this error appears only for remote-first strategy with no fallback)

Fix: Fall back to local execution. Check /api/v1/discover to see which nodes have CIP enabled. If you set a min_reputation filter, lower it or verify that discovered nodes meet the threshold. If a session credit budget is set, check the remaining balance.

IICP-E036HTTP 402

When: Pre-dispatch credit check — consumer S-Credit balance is below the computed routing cost before any worker is contacted. The proxy aborts without dispatching.

Fix: Check your balance: iicp-node credits or GET /api/v1/credits/balance. Earn credits by enabling CIP worker mode (allow_remote_inference = true). If a session_credit_budget cap is set, verify remaining budget via the proxy status endpoint.

capacity_exceededHTTP 429

When: Worker's general task slots are full (max_concurrent reached — applies to all tasks, not CIP-specific)

Fix: Try a different worker from the discover results. The proxy switches nodes automatically on this error.

capacity_exhaustedHTTP 503

When: IICP-E021 — CIP worker is at max_concurrent_remote capacity (the slot reserved exclusively for inbound CIP sub-tasks is full). The node rejects immediately without queuing.

Fix: Dispatch to a different worker, or wait briefly and retry. The proxy's fallback chain tries the next ranked node automatically. Operators can raise IICP_MAX_CONCURRENT (env var) on their node to allow more simultaneous tasks.

invalid_hmacHTTP 422

When: Credit receipt signature does not match

Fix: Verify the canonical message format and that node_hmac_key is the one issued at registration.

IICP-E022HTTP 503

When: Fewer eligible workers exist than the requested cip.replicas count — the coordinator will not dispatch to a reduced replica set (CIP-CALL-04, S.12 §2.2)

Fix: Lower cip.replicas to match the number of available CIP-enabled nodes, or wait for more nodes to join. Check /api/v1/discover?cip_capable=1 to see how many workers are currently reachable. With strategy=local-first (default), the task falls back to local instead of erroring.

IICP-E024HTTP 503

When: All dispatched workers failed to respond within worker_timeout (= coordinator_timeout × 0.6, default 18 s for a 30 s budget). Zero usable results were received.

Fix: The coordinator falls back to local execution automatically when a local model is available (the default). If no local model exists this error is returned. Try reducing cip.replicas, choosing nodes with lower latency, or raising the coordinator timeout in your client config to give workers more time.

IICP-E028HTTP 422

When: Invalid cip.policy (not best_of_n/majority_vote/map_reduce), cip.replicas outside [1, 10], or cip.quorum exceeds cip.replicas

Fix: Check all three cip fields: policy must be one of the three normative values, replicas must be 1–10, and quorum (if set) must be a positive integer ≤ replicas.

IICP-E025HTTP 422

When: majority_vote policy with even or < 3 replicas

Fix: Use an odd replica count ≥ 3 for majority_vote (minimum 3, maximum 9). Even replica counts cannot reach a strict majority.