@spoolis/accept
v0.1.1
Published
Turn acceptance policy and delivered work into a verified Spoolis Outcome in one call.
Maintainers
Readme
Accept work with Spoolis
@spoolis/accept turns your acceptance policy and delivered work into a verified Spoolis Outcome. It is a small, dependency-free client for the canonical agreement, judgment, and Outcome path.
Install
npm install @spoolis/acceptNode 20 or later is required.
Make one call
import * as spoolis from '@spoolis/accept'
const criteria = 'Every row must have status done'
const evidence = { rows: [{ id: 1, status: 'done' }] }
const judge = {
meta: {
evaluator_id: 'my-evaluator',
kind: 'buyer_owned',
evaluator_version: '1',
proof_requirement: 'declared',
},
async run({ evidence }) {
return { pass: evidence.rows.every((row) => row.status === 'done') }
},
}
const outcome = await spoolis.accept({ criteria, evidence, judge }, {
baseUrl: 'https://spoolis.com',
apiKey: process.env.SPOOLIS_API_KEY,
})
console.log(outcome.status, outcome.receiptId)Use policy when you need pricing, thresholds, or uncertainty behavior:
import * as spoolis from '@spoolis/accept'
const outcome = await spoolis.accept({
policy: {
criteria: [{
description: 'Every row includes status',
check: { checker: 'completeness', required_fields: ['status'] },
}],
units: 100,
unitValueCents: 500,
},
evidence: { rows },
}, {
baseUrl: 'https://spoolis.com',
apiKey: process.env.SPOOLIS_API_KEY,
})
console.log(outcome)
// {
// status: 'partial',
// accepted: 82,
// rejected: 18,
// uncertain: 0,
// earnedCents: 41000,
// spoolId: 'spl_example',
// receiptId: 'ocr_example',
// receiptUrl: 'https://spoolis.com/r/ocr_example',
// receipt: { id: 'ocr_example', result: 'partial', amounts: { earned_cents: 41000 } }
// }The API response uses earned_cents. The SDK exposes the same server-authored value as earnedCents; it does not recompute economics.
Request options
Every request has a 30-second timeout. Set timeoutMs to a positive integer to choose a different timeout.
Set retry: true to allow one retry after a short delay for requests that are safe to repeat. The SDK retries network errors, HTTP 429 responses, and HTTP 5xx responses. It never retries other HTTP 4xx responses, Spool creation, or evidence submission.
For the one-shot accept() path, set idempotencyKey to a stable string of 1–128 characters. The SDK sends it as idempotency_key. Supplying this key makes one-shot retries safe, so the SDK retries that request only when both retry: true and idempotencyKey are set. Reuse the same key when replaying the same operation across process restarts.
Accept purchased work
Use acceptPurchase({ criteria | policy, purchase, result, judge? }, options) when a result came from a paid tool or service. The optional purchase context is carried with the evidence, not added to the canonical Outcome. The returned nextAction maps accepted-only work to continue, rejected work to retry, and any uncertain work to hold.
evidenceFromLangSmithRun(run) converts a plain LangSmith run object without fetching or adding a dependency. spoolisAcceptanceNode(config) returns a plain async LangGraph-compatible node. It writes acceptance data to state.spoolis; a rejected Outcome is returned as data rather than thrown.
Define a policy
An AcceptancePolicy has these fields:
criteria: A nonempty description or 1–50 descriptions paired with deterministic checks.unitsandunitValueCents: Optional positive integers that must appear together. Their product is the maximum amount unless you also provide the same value asmaxAmountCents.maxAmountCents: An optional positive integer cap.acceptIf: Optional quality and consensus thresholds from 0–100. These are for an external scored judge.onUncertain: Optional and currently limited tohold.
Evidence must provide exactly one of rows, payload, or url. Every call requires exactly one of top-level criteria or policy. The criteria shorthand is equivalent to policy: { criteria }; use policy for all other policy fields.
Bring your own judge
Use your own evaluator without computing agreement or evidence hashes, as shown in the first example.
For per-unit evaluation, add units and unitValueCents in policy, then return { units: [{ id, pass }] }. Spoolis passes the exact unitIds to judge.run. For scored evaluation, set acceptIf and meta.schemaId, then return either { quality, consensus } or scored units. acceptWithJudge exposes the same lifecycle directly and accepts either { criteria, evidence, judge } or { policy, evidence, judge }.
The helper creates a unilateral Spool, submits evidence, reads the server-authored binding, runs your evaluator, submits its normalized result, verifies the Spool, and returns the same AcceptOutcome shape as accept. Server binding checks remain mandatory.
Fail safely
An uncertain result never becomes accepted. Missing fields, contradictory counts and receipt status, unknown receipt status, or any nonzero uncertain count map to status: 'uncertain'. Rejected and uncertain units do not become earned value. The SDK preserves the server's earned_cents value and does not author a replacement.
Verify the receipt
Use @spoolis/receipt-verifier to verify the signed Outcome Receipt offline before a consequential next action.
Exports
The package exports accept, acceptWithJudge, acceptPurchase, nextActionFor, evidenceFromLangSmithRun, spoolisAcceptanceNode, acceptancePolicySchema, AcceptancePolicyError, ExternalJudgeLifecycleError, JudgeAdapterError, toOneShotBody, deterministicChecker, scoredJudge, binaryJudge, toExternalJudgeDeclaration, and version. TypeScript users also receive AcceptancePolicy and the related input, outcome, judge, and check types.
