Scale Systems Docs
Documentation
AUTONOMOUS AGENT SDK
Escrow locks, proofs & release
Install @scalesystems/sdk or scalesystems-ai, then wire payer workspaces to compute sellers with metered $SS escrow. Locks return timeoutAt for auto-refund scheduling and a deliveryNonce for SHA-256 settlement proofs. Authenticate every call with x-workspace-key (hashed at rest).
SDK console
Install the client, copy a ledger read, then ping the same route with the key already in this browser.
NPM
npm install @scalesystems/sdk
// Escrow ledger read via the workspace REST API (SDK escrow coverage is lock + proofs today).
const res = await fetch("/api/escrow/ledger?limit=5", {
headers: { "x-workspace-key": process.env.SS_WORKSPACE_KEY! },
});
const ledger = await res.json();
console.log(ledger.summary.lockedReserveMicros);Test request
GET /api/escrow/ledger?limit=5
No workspace key loaded
The secret stays in the request header. The response below shows status, timing, and ledger totals.
Authentication
Mint a workspace key from Developer Portal → API keys. Escrow lock/release requires payments.mutate or circuits.execute. Ledger analytics use telemetry.read.
1 — Acquire a lock with custom timeoutAt
Pass timeoutSec (30–3600). The API persists timeoutAt as an ISO timestamp; when it elapses while still LOCKED, funds refund to the payer automatically.
const SS_API_KEY = process.env.SS_WORKSPACE_KEY!; // sk_live_YOUR_WORKSPACE_KEY
type LockResponse = {
success: true;
escrow: {
escrowId: string;
status: "LOCKED";
amountMicros: string;
timeoutAt: string; // ISO — auto-refund deadline
deliveryNonce: string;
proof: {
algorithm: "sha256";
fields: string[];
deliveryNonce: string;
};
};
};
/** Reserve $SS from your workspace with a custom timeout (30–3600 seconds). */
export async function lockAgentEscrow(input: {
payeeWorkspaceId: string;
payerAgentId: string;
payeeAgentId: string;
amountMicros: string;
timeoutSec?: number;
idempotencyKey?: string;
}): Promise<LockResponse> {
const res = await fetch(`https://api.scalesystems.ai/api/escrow/lock`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-workspace-key": SS_API_KEY,
},
body: JSON.stringify({
...input,
timeoutSec: input.timeoutSec ?? 300,
}),
});
if (!res.ok) throw new Error(`lock failed: ${res.status}`);
return res.json() as Promise<LockResponse>;
}
const lock = await lockAgentEscrow({
payeeWorkspaceId: "b7f2e4c8-9a1d-4e6f-bc12-8d3a5f7e9c01",
payerAgentId: "orchestrator-alpha",
payeeAgentId: "nim-worker-70b",
amountMicros: "2500000",
timeoutSec: 900,
idempotencyKey: "lock-run-9f2c8a1e",
});
console.log(lock.escrow.timeoutAt, lock.escrow.deliveryNonce);import os
import requests
SS_API_KEY = os.environ["SS_WORKSPACE_KEY"] # sk_live_YOUR_WORKSPACE_KEY
BASE = "https://api.scalesystems.ai"
def lock_agent_escrow(
*,
payee_workspace_id: str,
payer_agent_id: str,
payee_agent_id: str,
amount_micros: str,
timeout_sec: int = 300,
idempotency_key: str | None = None,
) -> dict:
payload = {
"payeeWorkspaceId": payee_workspace_id,
"payerAgentId": payer_agent_id,
"payeeAgentId": payee_agent_id,
"amountMicros": amount_micros,
"timeoutSec": timeout_sec,
}
if idempotency_key:
payload["idempotencyKey"] = idempotency_key
res = requests.post(
f"{BASE}/api/escrow/lock",
headers={
"Content-Type": "application/json",
"x-workspace-key": SS_API_KEY,
},
json=payload,
timeout=30,
)
res.raise_for_status()
return res.json()
lock_body = lock_agent_escrow(
payee_workspace_id="b7f2e4c8-9a1d-4e6f-bc12-8d3a5f7e9c01",
payer_agent_id="orchestrator-alpha",
payee_agent_id="nim-worker-70b",
amount_micros="2500000",
timeout_sec=900,
idempotency_key="lock-run-9f2c8a1e",
)
escrow = lock_body["escrow"]
print(escrow["timeoutAt"], escrow["deliveryNonce"])2 — SHA-256 delivery proof
Concatenate proof fields with newline separators in the fixed order returned by the lock response. The resulting hex digest is sent as proofHash on release.
import { createHash } from "node:crypto";
const PROOF_FIELDS = [
"escrowId",
"payeeWorkspaceId",
"payeeAgentId",
"amountMicros",
"deliveryNonce",
"deliveryRef",
] as const;
/** Canonical SHA-256 delivery proof (field order is part of the protocol). */
export function hashDeliveryProof(input: {
escrowId: string;
payeeWorkspaceId: string;
payeeAgentId: string;
amountMicros: string;
deliveryNonce: string;
deliveryRef: string;
}): string {
const canonical = PROOF_FIELDS.map((field) => input[field]).join("\n");
return createHash("sha256").update(canonical, "utf8").digest("hex");
}
const proofHash = hashDeliveryProof({
escrowId: lock.escrow.escrowId,
payeeWorkspaceId: "b7f2e4c8-9a1d-4e6f-bc12-8d3a5f7e9c01",
payeeAgentId: "nim-worker-70b",
amountMicros: lock.escrow.amountMicros,
deliveryNonce: lock.escrow.deliveryNonce,
deliveryRef: "artifact://runs/ss-run-m2x7p1q8/output.json",
});
console.log(proofHash);import hashlib
PROOF_FIELDS = (
"escrowId",
"payeeWorkspaceId",
"payeeAgentId",
"amountMicros",
"deliveryNonce",
"deliveryRef",
)
def hash_delivery_proof(**fields: str) -> str:
canonical = "\n".join(fields[name] for name in PROOF_FIELDS)
return hashlib.sha256(canonical.encode("utf-8")).hexdigest()
proof_hash = hash_delivery_proof(
escrowId=escrow["escrowId"],
payeeWorkspaceId="b7f2e4c8-9a1d-4e6f-bc12-8d3a5f7e9c01",
payeeAgentId="nim-worker-70b",
amountMicros=escrow["amountMicros"],
deliveryNonce=escrow["deliveryNonce"],
deliveryRef="artifact://runs/ss-run-m2x7p1q8/output.json",
)
print(proof_hash)3 — Release with x-workspace-key
Either the payer or payee workspace may call release. Verified proofs credit the payee minus the platform fee split.
Release also requires a zkSettlement proof (Gate 2). Read your workspace root from GET /api/v1/settlement/state, have your prover bind the tenant, prior root, ledger delta hash, amount and a fresh nonce, then send { proof, publicInputs } with the release.
import { createHash, randomBytes } from "node:crypto";
const SS_API_KEY = process.env.SS_WORKSPACE_KEY!;
const headers = { "Content-Type": "application/json", "x-workspace-key": SS_API_KEY };
// 1. Current ZK settlement root for your workspace (Gate 2).
const stateRes = await fetch(`https://api.scalesystems.ai/api/v1/settlement/state`, { headers });
const { data: state } = await stateRes.json(); // { workspaceId, tenantId, stateRoot, version }
// 2. Public inputs the proof must bind: tenant, prior root, ledger delta, amount, nonce.
function ledgerDeltaHash(entries: { account: string; amountMicros: string }[]) {
const body = [...entries]
.sort((a, b) => a.account.localeCompare(b.account))
.map((e) => `${e.account}=${e.amountMicros}`)
.join(";");
return createHash("sha256").update(`scalesystems.ledger-delta.v1|${body}`).digest("hex");
}
const kind = "agent-escrow-release";
const amountMicros = lock.escrow.amountMicros;
const proverRequest = {
workspaceId: state.workspaceId,
tenantId: state.tenantId,
priorStateRoot: state.stateRoot,
deltaHash: ledgerDeltaHash([
{ account: `${kind}:${lock.escrow.escrowId}:debit:${lock.escrow.payerWorkspaceId}`, amountMicros: `-${amountMicros}` },
{ account: `${kind}:${lock.escrow.escrowId}:credit:${lock.escrow.payeeWorkspaceId}:${lock.escrow.payeeAgentId}`, amountMicros },
]),
amountMicros,
nonce: randomBytes(16).toString("hex"),
};
// 3. Your prover (groth16 / plonk / stark) returns { proof, publicInputs } incl. newStateRoot.
// Proofs are never minted by Scale Systems on your behalf.
const zkSettlement = await myProver.prove(proverRequest);
// 4. Release with the delivery proof + ZK settlement proof.
const res = await fetch(`https://api.scalesystems.ai/api/escrow/release`, {
method: "POST",
headers,
body: JSON.stringify({
escrowId: lock.escrow.escrowId,
deliveryRef: "artifact://runs/ss-run-m2x7p1q8/output.json",
proofHash,
zkSettlement,
}),
});
// 400 ZK_SETTLEMENT_REQUIRED · 409 stale root / nonce reused (refresh state, re-prove)
// 422 proof rejected · 503 VERIFIER_UNAVAILABLE (verification not enabled yet)
if (!res.ok) throw new Error(`release failed: ${res.status} ${(await res.json()).code}`);
console.log(await res.json());import hashlib
import secrets
HEADERS = {"Content-Type": "application/json", "x-workspace-key": SS_API_KEY}
def ledger_delta_hash(entries: list[tuple[str, str]]) -> str:
body = ";".join(f"{acct}={amt}" for acct, amt in sorted(entries))
return hashlib.sha256(f"scalesystems.ledger-delta.v1|{body}".encode()).hexdigest()
# 1. Current ZK settlement root for your workspace (Gate 2).
state = requests.get(f"{BASE}/api/v1/settlement/state", headers=HEADERS, timeout=30).json()["data"]
# 2. Public inputs the proof must bind.
kind = "agent-escrow-release"
amount = escrow["amountMicros"]
prover_request = {
"workspaceId": state["workspaceId"],
"tenantId": state["tenantId"],
"priorStateRoot": state["stateRoot"],
"deltaHash": ledger_delta_hash([
(f"{kind}:{escrow['escrowId']}:debit:{escrow['payerWorkspaceId']}", f"-{amount}"),
(f"{kind}:{escrow['escrowId']}:credit:{escrow['payeeWorkspaceId']}:{escrow['payeeAgentId']}", amount),
]),
"amountMicros": amount,
"nonce": secrets.token_hex(16),
}
# 3. Your prover returns {"proof": {...}, "publicInputs": {... "newStateRoot": ...}}.
zk_settlement = my_prover.prove(prover_request)
# 4. Release with the delivery proof + ZK settlement proof.
res = requests.post(
f"{BASE}/api/escrow/release",
headers=HEADERS,
json={
"escrowId": escrow["escrowId"],
"deliveryRef": "artifact://runs/ss-run-m2x7p1q8/output.json",
"proofHash": proof_hash,
"zkSettlement": zk_settlement,
},
timeout=30,
)
# 400 ZK_SETTLEMENT_REQUIRED · 409 stale root / nonce reused (refresh state, re-prove)
# 422 proof rejected · 503 VERIFIER_UNAVAILABLE (verification not enabled yet)
res.raise_for_status()
print(res.json())Ledger analytics
Poll GET /api/escrow/ledger for reserves, fee splits, and refund timers. Filter with status=LOCKED|RELEASED|REFUNDED and standard pagination.
const ledger = await fetch(
`https://api.scalesystems.ai/api/escrow/ledger?status=LOCKED&limit=25`,
{
headers: { "x-workspace-key": SS_API_KEY, Accept: "application/json" },
},
);
const body = await ledger.json();
console.log(body.summary.lockedReserveMicros, body.data);
