JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 688
  • Score
    100M100P100Q87364F
  • License Apache-2.0

Official TypeScript SDK for the COHESION Judgment Independence Score API. Real-time oversight scoring for AI-assisted human decisions, per EU AI Act Article 14, Colorado SB 205, and NYC Local Law 144.

Package Exports

  • @cohesionauth/sdk
  • @cohesionauth/sdk/package.json

Readme

@cohesionauth/sdk

Save humanity by keeping judgment alive in the age of AI.

Official TypeScript SDK for the COHESION API. COHESION measures whether human oversight of AI is real, durable, and reviewable. The SDK wraps the live scoring, routing, audit-chain, and compliance-rollup endpoints; pair it with an OpenAI, Anthropic, Azure OpenAI, Bedrock, Vertex, or in-house model to instrument every human-AI interaction.

Reference scopes a buyer typically maps the evidence model to: EU AI Act Article 14, Colorado SB 205, Colorado SB 26-189 ADMT, NYC Local Law 144, SR 11-7.

  • npm: @cohesionauth/sdk
  • License: Apache-2.0
  • Requires: Node.js 20 or later
  • Base URL: https://api.cohesionauth.com (human-readable docs at https://cohesionauth.com/api)

Evaluate COHESION in 30 minutes

The canonical buyer-engineer evaluation path. Each step has a runnable artifact.

  1. Curl the unauthenticated root: curl -s https://api.cohesionauth.com/v1 | jq.
  2. Get a key at https://cohesionauth.com/pricing (Starter self-serve; FDP fit-call gated).
  3. npm install @cohesionauth/sdk.
  4. Score one decision (see Quickstart below).
  5. Replay it via curl against the live endpoint: curl https://api.cohesionauth.com/v1/decision/replay/$AI_DECISION_LOG_ID -H "X-API-Key: $COHESION_API_KEY" (no SDK wrapper).
  6. Pull a compliance rollup: await cohesion.complianceReport().
  7. Verify the audit chain via curl (admin-only, master-key auth, no SDK wrapper): curl https://api.cohesionauth.com/v1/admin/audit/verify-chain -H "X-API-Key: $COHESION_ADMIN_API_KEY".
  8. Open https://dashboard.cohesionauth.com and search by request_id.

If any step stalls, email peyton@cohesionauth.com with the failing step and the requestId from the SDK error.

JIS vs DRS, when to use each

Engine Question it answers Subject of measurement Primary endpoint
JIS (Judgment Independence Score) Is the reviewer still exercising independent judgment? The reviewer, scored against their own history POST /v1/score
DRS (Decision Risk Score) Is this particular decision risky enough to require a human, an async review, or a block? The individual decision, scored against policy POST /v1/decision/score

DRS routes the decision; JIS scores whether the reviewer is a trustworthy router.

Pilot workflow: score one AI decision end-to-end

The same loop every production integration runs.

  1. Operator opens a task; your app records session_id + operator_id.
  2. Your app calls the AI provider.
  3. Your UI presents the AI recommendation; the SDK instruments the interaction in the background.
  4. The operator commits a decision.
  5. Your app calls cohesion.score(...); SDK attaches Idempotency-Key automatically.
  6. The engine returns the JIS envelope under 100ms p50.
  7. Your app stores request_id from the response against the decision. If you are using the DRS gate (cohesion.decisionScore() / gate()), also store the ai_decision_log_id it returns. That is the identifier GET /v1/decision/replay/{ai_decision_log_id} accepts.

Generate an oversight evidence packet

The artifact a design partner gets at pilot close. Two SDK calls plus one curl assemble it. The audit-chain verifier is admin-only (master-key auth) and is not wrapped by the SDK; call it directly with curl.

const report  = await cohesion.complianceReport();
const profile = await cohesion.operatorProfile("analyst-42");
# Admin-only -- uses the scoped master key, NOT the customer scoring key.
curl https://api.cohesionauth.com/v1/admin/audit/verify-chain \
  -H "X-API-Key: $COHESION_ADMIN_API_KEY"

Contents: org-level oversight band distribution, reviewer-level JIS band over time, dimension breakdowns, decay projection, and a tamper-evident audit chain.

Human oversight evidence model

What the SDK produces, conceptually:

  1. Observable telemetry from the human-AI interaction (latency, hover, scroll, alternative views, decision class, modification extent).
  2. A decision-level score (DRS) that routes the decision BEFORE it reaches the end-user.
  3. A reviewer-level score (JIS) that scores whether the reviewer is still functioning as an oversight signal over time.
  4. A tamper-evident audit chain that connects telemetry, scores, and the resulting routing into one verifiable record per decision.
  5. An evidence packet assembled from the rollup endpoints.

Invisible-by-design: no extension, no survey, no offline assessment.

Example: healthcare intake workflow

A clinical intake nurse uses an AI scribe to draft the chief complaint.

await cohesion.score({
  operator_id: "rn-22871",
  session_id: "intake_2026_05_27_0094",
  domain: "healthcare",
  interaction: {
    ai_recommendation_presented: true,
    time_to_decision_ms: 41200,
    decision: "modified",
    modification_extent: 0.45,
    ai_available: true,
    scenario_type: "standard",
    outcome_correct: null,
    hover_events: 6,
    scroll_depth: 0.92,
    alternative_views_checked: 2,
  },
});

Example: lending decision workflow

A loan officer reviews an AI-recommended credit decision. DRS gates first, then JIS scores the reviewer interaction.

import { gate } from "@cohesionauth/sdk";

const pre = await gate(cohesion, request, null);
if (pre.routing_decision !== "auto") {
  return routeToReviewer(pre);
}
const aiOutput = await provider.complete(request);
await gate(cohesion, request, aiOutput); // post-AI strict gate

// Then JIS-score the reviewer's commit.
await cohesion.score({
  operator_id: "officer-104",
  session_id: "loan_8821",
  domain: "financial",
  interaction: { /* ... */ },
});

Example: HR screening workflow

A recruiter screens AI-shortlisted resumes under NYC Local Law 144. Every accept/reject is logged as an oversight event.

await cohesion.score({
  operator_id: "recruiter-58",
  session_id: "screen_2026_05_27_0044",
  domain: "general",
  interaction: {
    ai_recommendation_presented: true,
    time_to_decision_ms: 27800,
    decision: "rejected",
    modification_extent: 0,
    ai_available: true,
    scenario_type: "standard",
    outcome_correct: null,
    hover_events: 4,
    scroll_depth: 0.7,
    alternative_views_checked: 3,
  },
});

When the city audit window opens, cohesion.complianceReport() returns the aggregate; the admin-only GET /v1/admin/audit/verify-chain endpoint (curl, master-key auth) proves the chain is unbroken.

Install

npm install @cohesionauth/sdk

Quickstart

Get a key:

  • New customer: start at https://cohesionauth.com/pricing. Starter (Self-Reported, $25,000/yr) is self-serve; the Founding Design Partner cohort ($10,000 one-time) is founder-reviewed via a brief fit call. Audited and Enterprise are scoped procurement, set up with the founder. Self-serve and fit-call-cleared checkouts both provision an org and deliver your API key by email on completed checkout. Key shown once, then rotate from your dashboard.
  • Existing customer rotating a key: https://cohesionauth.com/dashboard/api-keys
import { Cohesion } from "@cohesionauth/sdk";

const client = new Cohesion({ apiKey: process.env.COHESION_API_KEY! });

const result = await client.score({
  session_id: "sess_2026_04_22_001",
  operator_id: "analyst-42",
  domain: "financial",
  interaction: {
    ai_recommendation_presented: true,
    time_to_decision_ms: 3400,
    decision: "modified",
    modification_extent: 0.25,
    ai_available: true,
    scenario_type: "standard",
    outcome_correct: null,
    hover_events: 4,
    scroll_depth: 0.9,
    alternative_views_checked: 1,
  },
});

console.log(`JIS ${result.jis} (${result.band})`);

DRS gate -- the Authorized Inference Gateway

cohesion.gate() wraps a regulated AI call with the Decision Risk Score engine. The contract is strict-gate, fail-closed: the SDK refuses to surface a final AI output unless DRS returned a clean routing_decision envelope.

import {
  Cohesion,
  gate,
  CohesionPolicyBlockedError,
  CohesionRequiresHumanReviewError,
  CohesionMalformedDecisionError,
} from "@cohesionauth/sdk";

const client = new Cohesion({ apiKey: process.env.COHESION_API_KEY! });

// 1. Pre-AI pass: ask DRS whether the input is admissible at all.
const preDecision = await gate(client, request, null);

if (preDecision.routing_decision !== "auto") {
  // must_review / async_review / forced_escalation -- route to a human reviewer
  // BEFORE calling the AI provider. preDecision.review_queue_id is the handle.
  return routeToReviewer(preDecision);
}

// 2. Call the AI provider.
const aiOutput = await provider.complete(request);

// 3. Post-AI pass: ask DRS whether to surface the AI output.
try {
  const postDecision = await gate(client, request, aiOutput);
  // routing_decision === 'auto', no forced escalation -- safe to surface.
  return aiOutput;
} catch (e) {
  if (e instanceof CohesionPolicyBlockedError) {
    // Hard block: never surface this AI output. e.decision.drs_reason_codes
    // and e.decision.policy_evaluation.hard_failures explain why.
    return blockResponse(e);
  }
  if (e instanceof CohesionRequiresHumanReviewError) {
    // Route to reviewer; e.decision.review_queue_id is the handle.
    return routeToReviewer(e.decision);
  }
  if (e instanceof CohesionMalformedDecisionError) {
    // Fail-closed sentinel: DRS returned 2xx but the envelope was malformed.
    // Treat as a hard block. Contact support with e.requestId.
    return blockResponse(e);
  }
  // Network / 5xx / retry-exhausted -> caller MUST treat as fail-closed.
  // Do NOT surface the AI output. The plain `CohesionError`, `ServerError`,
  // `NetworkError` types preserve `requestId` for incident tracing.
  return blockResponse(e);
}

The fail-closed contract on transport failure: if DRS does not return a 2xx envelope (network error, 5xx after retries, abort), gate() re-throws the underlying error unchanged. The caller MUST NOT surface the AI output. Treat any non-resolution as a hard block.

Error class taxonomy:

Error Thrown on Carries
CohesionPolicyBlockedError routing_decision === 'policy_blocked' on either pass decision.drs_reason_codes, decision.policy_evaluation.hard_failures, decision.ai_decision_log_id
CohesionRequiresHumanReviewError Post-AI must_review / async_review / non-empty forced_escalation_rules_triggered decision.review_queue_id
CohesionMalformedDecisionError 2xx with missing or unrecognized envelope fields (fail-CLOSED) observedKeys, missingFields
ServerError / NetworkError retry-exhausted transport failure requestId

Pre-AI must_review / async_review / forced escalation return the envelope without throwing -- that branch is the caller's signal to route to a reviewer before the AI call.

See examples/07-live-gate.ts for a runnable end-to-end demonstration.

Side-by-side

The same request in three forms.

cURL

curl https://api.cohesionauth.com/v1/score \
  -H "X-API-Key: $COHESION_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d @payload.json

Python

from cohesion import Client

client = Client(api_key=os.environ["COHESION_API_KEY"])
result = client.score(
    session_id="sess_...",
    operator_id="analyst-42",
    domain="financial",
    interaction={...},
)

TypeScript

import { Cohesion } from "@cohesionauth/sdk";

const client = new Cohesion({ apiKey: process.env.COHESION_API_KEY! });
const result = await client.score({ /* ... */ });

5-minute integrations (1.3.0)

Three drop-in patterns. Pick the one that fits your stack.

Express

import express from "express";
import { Cohesion, cohesionExpress } from "@cohesionauth/sdk";

const cohesion = new Cohesion({ apiKey: process.env.COHESION_API_KEY! });
const app = express();

app.use(
  cohesionExpress({
    client: cohesion,
    domain: "financial",
    operatorIdResolver: (req) => String(req.headers["x-user-id"] ?? "anon"),
  }),
);

Next.js (App Router route handler)

import { Cohesion, cohesionNextRoute } from "@cohesionauth/sdk";

const cohesion = new Cohesion({ apiKey: process.env.COHESION_API_KEY! });

export const POST = cohesionNextRoute(
  async (req) => Response.json({ ok: true }),
  {
    client: cohesion,
    domain: "general", // SOC alert-triage maps here per the v1.2 spec
    operatorIdResolver: (req) => req.headers.get("x-user-id") ?? "anon",
  },
);

Decorator (any function -- class method or HOF wrap)

import { measure } from "@cohesionauth/sdk";

const handle = measure({
  client: cohesion,
  domain: "financial",
  operatorIdResolver: ([req]: [{ userId: string }]) => req.userId,
})(originalHandle);

domain is one of healthcare | aviation | financial | legal | pharmaceutical | general. SOC use cases map to general per v1.2 §4 Option A.

For chat-completion patterns (OpenAI / Anthropic / LangChain / Vercel AI), see Provider integrations below or import the chat namespace:

import { chat } from "@cohesionauth/sdk";
const wrapped = chat.wrapOpenAI(openai, cohesion, ctx);

Six full integration examples live under examples/.

Client options

new Cohesion({
  apiKey: string,                                  // required
  baseUrl?: string,        // default "https://api.cohesionauth.com"
  timeout?: number,        // default 30000 ms
  maxRetries?: number,     // default 3
  logger?: Logger,         // default createDefaultLogger()
  enableTelemetry?: boolean, // default false (opt-in Sentry)
});

Method reference

Method HTTP Notes
client.score(req) POST /v1/score Idempotency-Key auto-generated
client.scoreBatch(req) POST /v1/score/batch up to 100 interactions
client.operatorProfile(operatorId) GET /v1/operator/:id/profile includes JIS history
client.organizationDashboard() GET /v1/organization/dashboard aggregate metrics
client.maintenanceRecommend(req) POST /v1/maintenance/recommend judgment-maintenance exercises
client.complianceReport() GET /v1/compliance/report EU AI Act Article 14 rollup
client.adminKeyRotate() POST /v1/admin/key/rotate returns new key ONCE
client.adminKeyRevoke() POST /v1/admin/key/revoke sets org inactive
client.adminAuditLog(opts?) GET /v1/admin/audit-log own-org events only

AI-provider wrappers

Instrument OpenAI, Anthropic, Azure OpenAI, Vercel AI SDK, or LangChain.

import OpenAI from "openai";
import { Cohesion, wrapOpenAI } from "@cohesionauth/sdk";

const cohesion = new Cohesion({ apiKey: process.env.COHESION_API_KEY! });
const openai = wrapOpenAI(new OpenAI(), cohesion, {
  operatorId: "analyst-42",
  sessionId: "sess_...",
  domain: "financial",
});

const { response, recordDecision } = await openai.chat.completions.create({
  model: "gpt-4",
  messages: [{ role: "user", content: "Draft SAR narrative" }],
});

// Present `response` to the human. After they decide:
const score = await recordDecision({
  decision: "modified",
  modificationExtent: 0.3,
});

Equivalent helpers: wrapAnthropic, wrapAzureOpenAI, vercelAIMiddleware, langChainHandler.

Errors

Every SDK error carries requestId and nextStep.

Class HTTP Extra fields nextStep example
AuthenticationError 401 "Check the 8-character prefix of your key. New customers start at cohesionauth.com/pricing; existing customers rotate at cohesionauth.com/dashboard/api-keys."
RateLimitError 429 retryAfter: number "Retry after 7 seconds."
ValidationError 400, 413, 422 field, allowedValues "scenario_type must be one of: standard, independent, trap, split."
ServerError 5xx populated only when actionable
NetworkError transport cause "Check connectivity to api.cohesionauth.com and ensure TLS 1.3 egress is permitted from your environment."
CohesionError base hierarchy root
import { RateLimitError } from "@cohesionauth/sdk";

try {
  await client.score(req);
} catch (err) {
  if (err instanceof RateLimitError) {
    console.log(`Retry in ${err.retryAfter}s. Hint: ${err.nextStep}`);
  } else {
    throw err;
  }
}

CLI

npx cohesion score --operator-id analyst-42 --from-file payload.json
# or via stdin:
cat payload.json | npx cohesion score --operator-id analyst-42 --from-file -

Retry and idempotency

  • Exponential backoff with full jitter. Default max 3 retries.
  • Retries only on 429 and 5xx. All 4xx (except 429) fail fast.
  • Honors Retry-After header (integer seconds or HTTP-date).
  • Every POST auto-populates Idempotency-Key with a UUIDv4 so retries are safe to replay.

SDK parity matrix

Every documented endpoint is reachable from the TypeScript SDK, the Python SDK, and the dashboard. Operator-only paths (key rotation, audit log inspection) are read-write in the SDKs and read in the dashboard.

Endpoint TypeScript Python Dashboard
POST /v1/score client.score() client.score() read
POST /v1/score/batch client.scoreBatch() client.score_batch() read
POST /v1/decision/score client.decisionScore() / gate() client.decision_score() / gate() read
GET /v1/decision/:id client.getDecision() client.get_decision() read
GET /v1/decision/queue client.decisionQueue() client.decision_queue() read
GET /v1/decision/replay/:id curl (no SDK wrapper) curl (no SDK wrapper) read
GET /v1/operator/:id/profile client.operatorProfile() client.operator_profile() read
GET /v1/organization/dashboard client.organizationDashboard() client.organization_dashboard() read
POST /v1/maintenance/recommend client.maintenanceRecommend() client.maintenance_recommend() read
GET /v1/compliance/report client.complianceReport() client.compliance_report() read + export
POST /v1/telemetry/ai-call-observed client.telemetryAiCallObserved() client.telemetry_ai_call_observed() n/a
GET /v1/admin/audit/verify-chain curl (master-key, no SDK wrapper) curl (master-key, no SDK wrapper) read
POST /v1/admin/key/rotate client.adminKeyRotate() client.admin_key_rotate() read + rotate
POST /v1/admin/key/revoke client.adminKeyRevoke() client.admin_key_revoke() read
GET /v1/admin/audit-log client.adminAuditLog() client.admin_audit_log() read

Full 50-endpoint catalog at the OpenAPI schema.

Endpoint status classification

Every endpoint is tagged with one of four maturity classifications.

Class Meaning Backward compatibility
Production Stable contract. SLA-backed. 12-month deprecation notice via Sunset response header.
Beta Public, intentionally exposed, contract may change. Notice via release notes; no Sunset guarantee.
Admin Org-scoped, owner-only. Key rotation, revocation, audit log. Production-grade backward compatibility.
Internal Reserved for the dashboard + SDK. No external contract.

The Production class covers the entire surface listed in the parity matrix above. Beta endpoints are documented in release notes; Admin endpoints are tagged in the OpenAPI schema with x-cohesion-class: admin.

Errors and recovery

Every failure mode has a documented recovery path. Catch by class, never by string match.

Failure HTTP SDK class Caller next step
Missing or wrong key 401 AuthenticationError Check the key prefix. Rotate at dashboard.cohesionauth.com/api-keys.
Bad payload field 400 / 413 / 422 ValidationError Inspect err.field and err.allowedValues.
Rate limit hit 429 RateLimitError SDK auto-retries with backoff + jitter; honor err.retryAfter if surfaced after retries.
Upstream model unavailable (5xx) 503 / 504 ServerError SDK retries on 5xx; after retries, fail-closed (do NOT surface the AI output).
Network down / DNS / TLS transport NetworkError Verify egress to api.cohesionauth.com. Fail-closed.
DRS envelope malformed 2xx CohesionMalformedDecisionError Treat as hard block. Contact support with err.requestId.

Every error carries requestId and nextStep. The CohesionError base is the safe fallback catch.

Compliance boundaries

What the SDK helps customers prove, and what it does NOT prove.

The SDK measures:

  • Whether a named human reviewer was present at the moment of decision.
  • Whether the reviewer exercised independent judgment, or rubber-stamped.
  • Whether the decision was risky enough to require an additional human, an async review, or a hard block.
  • Whether the reviewer's oversight quality is degrading over time.
  • Whether the entire interaction is reconstructable from a tamper-evident audit chain.

The SDK does NOT:

  • Render legal opinions or determine regulatory conformance on a customer's behalf.
  • Replace internal model-risk-management or model-validation processes.
  • Score the underlying AI model's correctness or bias.
  • Operate as a certification body.

Buyers and their counsel are responsible for mapping the evidence model to specific regulatory obligations.

Data handling and retention

  • Transport: TLS 1.3 from your environment to api.cohesionauth.com.
  • Storage region: Cloudflare D1 in the customer's contracted region (EU customers on EU edge; US customers on US edge).
  • Retention windows: Telemetry and score envelopes: 13 months default, configurable per contract. Audit chain: indefinite (a chain cannot be truncated without breaking proof).
  • Redaction: The default logger redacts API keys (pattern ck_live_*) and operator_id values before emit. Free-text prompt content is NEVER stored by the engine.
  • Export: client.complianceReport() + client.adminAuditLog() are SDK-callable and downloadable.

Audit trail example

A synthetic but realistic excerpt of the chain returned by GET /v1/admin/audit/verify-chain (admin-only, master-key auth, curl-only -- not wrapped by the SDK). Three consecutive decisions; the chain head proves none were silently dropped or rewritten.

{
  "chain_head": "sha256:a13c…f902",
  "verified": true,
  "entries": [
    {
      "request_id": "req_01HXG7K9Z2W4M6P8B0A2C4E6F8",
      "timestamp": "2026-05-27T14:08:42.318Z",
      "operator_id_hash": "h_e2a9…",
      "decision_class": "modified",
      "drs_routing": "auto",
      "jis_band": "Strong",
      "prev_hash": "sha256:9b71…a004",
      "this_hash": "sha256:c84d…ee19"
    },
    {
      "request_id": "req_01HXG7KCV4Y2T8M0R6E3K1Q9P2",
      "timestamp": "2026-05-27T14:10:01.044Z",
      "operator_id_hash": "h_e2a9…",
      "decision_class": "rejected",
      "drs_routing": "must_review",
      "jis_band": "Strong",
      "prev_hash": "sha256:c84d…ee19",
      "this_hash": "sha256:1f02…7733"
    },
    {
      "request_id": "req_01HXG7KFM8N0Q3D5W2A8H6Y1B6",
      "timestamp": "2026-05-27T14:11:55.610Z",
      "operator_id_hash": "h_e2a9…",
      "decision_class": "accepted",
      "drs_routing": "auto",
      "jis_band": "Adequate",
      "prev_hash": "sha256:1f02…7733",
      "this_hash": "sha256:a13c…f902"
    }
  ]
}

Each entry's this_hash derives from its content plus the previous entry's hash. The chain head is the cryptographic summary of every decision in-window.

Changelog and versioning policy

Semver. The /v1 prefix is the major-version contract; breaking changes ship under /v2 with a 12-month overlap and Deprecation plus Sunset response headers per RFC 8594.

  • Backward-compatible additions (new endpoints, new optional fields) ship in minor releases, no advance notice required.
  • Deprecations ship with Deprecation and Sunset response headers, minimum 12 months before removal.
  • SDK versioning follows API versioning. Patch releases for engine fixes; minor releases for new endpoints; major releases only when the API major changes.
  • Full release notes: cohesionauth.com/changelog.

Environment variables

Name Purpose
COHESION_API_KEY API key. Required for the CLI.
COHESION_BASE_URL Override the base URL (staging, self-hosted).
COHESION_LOG_FORMAT Set to json for structured logs.
COHESION_LOG_LEVEL debug, info, warn, or error.
COHESION_TEST_API_KEY Enables the live integration test.
COHESION_SENTRY_DSN or SENTRY_DSN Opt-in telemetry, only when enableTelemetry: true.

Logging and redaction

The default logger redacts API keys (ck_live_*) and operator_id values before emit. Set COHESION_LOG_FORMAT=json for structured output suitable for Datadog, Sentry, or Cloudflare Logpush.

License

Apache License 2.0. See LICENSE and NOTICE.

The COHESION Judgment Independence Score methodology, scoring engine, and intervention protocol are subject to the provisional patent filed 2026-04-13.