Track AI decisions
Score a single interaction or up to 100 at once. The core telemetry pattern.
Every AI-assisted decision your operators make is one interaction. Score each one. That is how a Judgment Independence Score is built up.
What this is
POST /v1/score accepts one scored interaction. POST /v1/score/batch accepts up to 100. Both return the updated JIS, per-dimension breakdown, decay projection, compliance flags, and a maintenance recommendation.
When to use
- Single: real-time scoring inside a middleware wrapper around your AI provider.
- Batch: end-of-shift backfill, nightly import, or historical replay.
Single score
Python
from cohesion import Client
client = Client(api_key="ck_live_...")
resp = client.score(
session_id="sess-2026-04-22-001",
operator_id="analyst-42",
domain="financial",
interaction={
"ai_recommendation_presented": True,
"time_to_decision_ms": 2400,
"decision": "modified",
"modification_extent": 0.25,
"ai_available": True,
"scenario_type": "standard",
"outcome_correct": None,
"hover_events": 3,
"scroll_depth": 0.85,
"alternative_views_checked": 2,
},
)
print(resp.jis, resp.band, resp.dimensions)
TypeScript
import { Cohesion } from "@cohesionauth/sdk";
const client = new Cohesion({ apiKey: process.env.COHESION_API_KEY! });
const resp = 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: 2400,
decision: "modified",
modification_extent: 0.25,
ai_available: true,
scenario_type: "standard",
outcome_correct: null,
hover_events: 3,
scroll_depth: 0.85,
alternative_views_checked: 2,
},
});
Batch score
Up to 100 interactions per call, 5 MB body cap. All interactions in one call must share the same operator_id.
resp = client.score_batch(
operator_id="analyst-42",
domain="financial",
interactions=[interaction_1, interaction_2, interaction_3],
)
for r in resp.results:
print(r.session_id, r.jis)
Middleware pattern
Wrap your AI provider once. Score every call.
def completion_with_cohesion(prompt: str, operator_id: str, session_id: str):
started = time.time()
ai_output = openai_client.chat.completions.create(...)
elapsed_ms = int((time.time() - started) * 1000)
# ... operator reviews ai_output, you capture their decision ...
cohesion.score(
session_id=session_id,
operator_id=operator_id,
domain="financial",
interaction={
"ai_recommendation_presented": True,
"time_to_decision_ms": elapsed_ms,
"decision": operator_decision,
"modification_extent": edit_distance_ratio,
"ai_available": True,
"scenario_type": "standard",
"outcome_correct": None,
"hover_events": hover_count,
"scroll_depth": max_scroll,
"alternative_views_checked": alt_view_count,
},
)
return ai_output
See integration patterns for batch, event-driven, and retry strategies.
Field reference
| Field | Type | Constraint |
|---|---|---|
ai_recommendation_presented | boolean | required |
time_to_decision_ms | number | >= 0 |
decision | enum | accepted | modified | rejected | independent |
modification_extent | number | 0.0 - 1.0 |
ai_available | boolean | required |
scenario_type | enum | standard | independent | trap | split |
outcome_correct | boolean | null | null if ground truth unknown |
hover_events | number | >= 0 |
scroll_depth | number | 0.0 - 1.0 |
alternative_views_checked | number | >= 0 |
Errors you might see
| Status | Meaning | Fix |
|---|---|---|
400 | Invalid JSON | Check payload encoding |
413 | Body too large | Single is 1 MB cap, batch is 5 MB |
422 | Validation (enum, range) | Check error catalog |
429 | Rate limit | Back off, read rate limits |
Next step
- Profile a single operator over time: monitor operator judgment
- Full endpoint details: POST /v1/score, POST /v1/score/batch