stateset-nsr
v0.9.1
Published
TypeScript SDK for the Stateset NSR AI platform — neuro-symbolic recursive reasoning
Maintainers
Readme
Stateset NSR TypeScript SDK
TypeScript client for the Stateset NSR AI platform — neuro-symbolic recursive reasoning.
Install
npm install stateset-nsrThe package is ESM-only ("type": "module", an import-only exports
map). Use import from ESM or await import('stateset-nsr') from
CommonJS; a bare require() will not resolve it.
Quick Start
import { NSRClient } from 'stateset-nsr'
const nsr = new NSRClient({
apiKey: 'nsr_your_api_key',
orgId: 'org_your_org_id',
})
// Send a customer message
const response = await nsr.chat('I want to cancel my subscription')
console.log(response.completion.reply)
// "We offer the option to pause your subscription..."
console.log(response.analysis.categories[0].category)
// "subscription_management"
// Execute ready tool calls
const ready = NSRClient.readyToolCalls(response)
for (const tc of ready) {
console.log(`${tc.function}() — rule: ${tc.policy.rule_name}`)
// offer_pause() — rule: offer_pause_before_cancel
}Knowledge Base
// Add products
await nsr.addEntity({
name: 'Pro Plan',
entity_type: 'product',
properties: { price: '99.00', billing: 'monthly' },
})
// Add business rules
await nsr.addRule({
name: 'offer_pause_before_cancel',
head_predicate: 'offer_pause',
head_args: ['?subscription'],
body: [{ predicate: 'cancel_request', args: ['?subscription'] }],
confidence: 0.95,
})
// Check stats
const stats = await nsr.kbStats()
console.log(`${stats.entity_count} entities, ${stats.rule_count} rules`)NSR Machine
// Provision with GSS seed rules
await nsr.provisionMachine(true)
// Train
await nsr.trainMachine([
{ input: 'cancel my plan', expected_category: 'subscription_management' },
{ input: 'where is my order', expected_category: 'order_management' },
{ input: 'is this safe during pregnancy', expected_category: 'medical_safety' },
])
// Check status
const status = await nsr.machineStatus()
console.log(`Vocabulary: ${status.vocabulary_size}, Programs: ${status.programs_learned}`)Multi-Turn Conversation
const turn1 = await nsr.chat('I want to cancel my subscription')
const turn2 = await nsr.chat('OK, pause it for 3 months', {
sessionId: turn1.session_id ?? undefined,
history: [
{ role: 'user', content: 'I want to cancel my subscription' },
{ role: 'assistant', content: turn1.completion.reply },
],
})Advanced Reasoning
const res = await nsr.chat('Is this safe during pregnancy?')
if (res.completion.needs_human_review) {
console.log('Route to human agent')
}
const ar = res.completion.grounding.advanced_reasoning
if (ar) {
console.log(`Strategy: ${ar.recommended_strategy}`)
console.log(`Confidence: ${ar.machine_confidence}`)
console.log(`Thoughts: ${ar.thought_count}`)
console.log(`Features: ${ar.enabled_features.join(', ')}`)
if (ar.uncertainty) {
console.log(`Epistemic: ${ar.uncertainty.epistemic}`)
console.log(`Calibration: ${ar.uncertainty.calibration_score}`)
}
}Reasoning
// Symbolic reasoning
await nsr.reason('Is the customer eligible for a refund?')
// Forward chaining
await nsr.forwardChain(10)
// Backward chaining proof search
await nsr.backwardChain('eligible_for_return', ['order_123'])Verified Decisions
// One auditable decision: approved | denied | refused, with a cited proof chain.
const decision = await nsr.decide('Can order A1 be refunded?', {
action: 'issue_refund',
})
// Score a whole portfolio in one call — each item metered independently.
const batch = await nsr.decideBatch([
{ query: 'Can order A1 be refunded?', action: 'issue_refund' },
{ query: 'Can order A2 be returned?' },
])
// Items past the server's time budget return error code
// "batch_deadline_exceeded" — never evaluated, never billed. Retry those
// in a smaller batch.
// Independently verify an approved decision's proof — no trust in the server.
if (decision.verifiable_bundle) {
const check = await nsr.verifyProof(decision.verifiable_bundle)
console.log(check.verified) // true, or { verified: false, reason }
}
// Close the outcome loop: record what actually happened…
await nsr.recordOutcome(decision.decision_id, 'honored')
await nsr.recordOutcomeByRef('order-9412', 'reversed') // …or by your own ref
// …and read the reliability curve + integration roadmap it powers.
const cal = await nsr.calibration()
console.log(cal.expected_calibration_error, cal.bins)
const roadmap = await nsr.refusalRoadmap()
// Compliance export (NDJSON on the wire, parsed records here; needs DB persistence).
const records = await nsr.exportDecisions({ since: '2026-08-01T00:00:00Z', limit: 5000 })Metering & marketplace onboarding
await nsr.linkEntitlement('org_acme', token, { kind: 'stripe', stripe_subscription_item: 'si_123' })
await nsr.getEntitlement('org_acme')
await nsr.awsMarketplaceRegister('org_acme', amznMarketplaceToken)
await nsr.azureMarketplaceRegister('org_acme', msMarketplaceToken)Billing
const usage = await nsr.usage()
console.log(`Outcomes: ${usage.outcomes.outcomes_month}/${usage.outcomes.outcomes_included}`)
console.log(`Estimated bill: $${usage.outcomes.estimated_total.toFixed(2)}`)Error Handling
import { NSRClient, NSRError } from 'stateset-nsr'
try {
await nsr.chat('test')
} catch (err) {
if (err instanceof NSRError) {
// Transport failures (DNS, connection reset, timeout) surface as
// NSRError too, with status 0 and code 'network_error' | 'timeout'.
console.error(`API error ${err.status} (${err.code ?? 'unknown'}): ${err.body}`)
}
}The client retries transport errors, 429 (honoring Retry-After, capped at
60s), and 5xx with jittered exponential backoff, under an overall per-call
deadline (deadlineMs, default 5 minutes). Every mutating request carries an
auto-generated Idempotency-Key, stable across retries of the same logical
call, so retries replay rather than re-execute.
Types
The core surfaces — chat, verified decisions (decide/batch/outcomes/
calibration/export), proof verification, KB entities/rules, machines,
metering, and billing — return typed responses. A few auxiliary methods
(sessions, conversations, flywheel, NSR-L, agents) still return unknown;
see Coverage below. Import any type you need:
import type {
ChatResponse,
DecisionResponse,
BatchDecisionResponse,
Calibration,
ProofVerifyResponse,
ToolCall,
MachineStatus,
BillingUsage,
} from 'stateset-nsr'Coverage
The SDK covers the platform's core surface, not every route. Covered: chat
(sync/stream/completions/messages), verified decisions (single, batch,
analytics, outcomes, calibration, refusal roadmap, NDJSON export), proof
verification, KB entities (CRUD/search/batch-create) and rules (CRUD),
triples (create/batch/read/update/delete + evidence attach/detach), NSR
symbols/stats/features, machines + brand-machine onboarding, webhooks,
templates, flywheel basics, metering & marketplace onboarding
(AWS/Azure/entitlements), billing, health (/health, /ready).
Route groups NOT yet covered (call them with your own HTTP client): macros,
answer/replies, policy sandbox & evaluation, NSR programs/validation,
/api/v1/nsr/chat/execute-actions, recursive chat, /v1/messages/count_tokens,
entity batch-delete and soft-delete, /api/v1/query, /api/v1/kb/graph,
/health/deep, the Postman collection / status / audit-export routes,
graph-of-thoughts, VSA, auth key management, decisions impact replay, and
the GCP Pub/Sub push endpoint (server-inbound, not client-called).
Verifying webhooks
import { verifyWebhookSignature } from 'stateset-nsr'
// In your handler: raw request body + the X-NSR-Signature header.
if (!verifyWebhookSignature(signingSecret, rawBody, signatureHeader)) {
return res.status(400).end()
}Constant-time comparison with a 5-minute replay window by default
(pass null as the fourth argument to disable the timestamp check).
Audit & observability lookups
await nsr.getDecision('dec_abc123') // resolve a decision_id from a response/webhook
await nsr.gssSeedInfo() // { grounded: true, source: 'embedded', ... }Brand machine onboarding
The full GSS lifecycle for your org — see BRAND_MACHINE_ONBOARDING.md:
const seed = await nsr.seedMachinePack({ catalog: [], policies: [] })
const spec = await nsr.compileMachinePack({ seed_id: seed.id })
await nsr.evaluateMachineSeed({ compiled_id: spec.id })
await nsr.activateMachinePack({ compiled_id: spec.id })Webhooks & templates
const hook = await nsr.createWebhook('https://yourapp.com/hook', ['outcome.produced'])
store(hook.signing_secret) // shown ONLY at creation
await nsr.webhookDeliveries(hook.id) // delivery log (status, attempts)
await nsr.applyTemplate('ecommerce-returns') // one-call KB seeding