Skip to content
Docs navigation: System Zero / Decision records

Decision records

RightNow AIRightNow System ZeroDecision records Updated

On this page

Read a stored decision, or its trace, with the API key that created it.

lookup.ts
const key = process.env.SYSTEM_ZERO_API_KEY;
const id = process.env.DECISION_ID;
if (!key || !id) {
  throw new Error("Set SYSTEM_ZERO_API_KEY and DECISION_ID first.");
}

// Use the API key that created the decision.
const headers = { Authorization: `Bearer ${key}` };
const url = `https://api.rightnowai.co/v1/system-zero/decisions/${id}`;

// The stored decision, then its trace.
for (const address of [url, `${url}/trace`]) {
  const response = await fetch(address, { headers });
  const body = await response.json();
  if (!response.ok) {
    throw new Error(JSON.stringify(body));
  }
  console.log(JSON.stringify(body, null, 2));
}

Look up a decision

GET /v1/system-zero/decisions/{id}
The stored decision, byte for byte.
GET /v1/system-zero/decisions/{id}/trace
Metadata about the same decision, without answer content.

Send the active API key that created the decision. Another key in the same workspace cannot read it.

Use the id of a decide reply: szd_ followed by 32 lowercase hexadecimal characters. Any other id returns 404 decision_not_found.

A found decision returns its stored status and reply, exactly as they were first returned. A legacy reply keeps its stored answer shape. Do not use legacy confidence as decision probability.

HEAD returns the same status and headers without a body. Neither read takes a request body or query parameters. There is no list endpoint.

Read the trace

A trace is a JSON object whose object is system_zero.decision_trace. It reads these fields from the stored decision.

id
The decision's id.
created
When the decision was made, in Unix seconds.
model
The model named in the stored reply.
model_version
The stored reply's served_by.
route
The stored reply's context.route.
usage_units
Seven usage counts, each a whole number or null.
refusal_codes
The distinct question refusal codes in the decision, sorted.
refusal_code
The one refusal code when there is exactly one, else null.

These fields are null in this release: request_id, render_id, attachments, timings.queue_ms, timings.node_ms, timings.settle_ms, usage_units.cached_media_tokens, idempotency, stream_id and state_version.

A missing usage count is null, never zero. The trace holds no question names, answer values, probabilities, messages or request content.

trace.json
JSON
{
  "object": "system_zero.decision_trace",
  "id": "szd_7c41f0a9b2d84e6c9a1f3b5d7e9c0a2b",
  "request_id": null,
  "created": 1791100800,
  "model": "system-zero-2.0.0",
  "model_version": "system-zero-2.0.0",
  "render_id": null,
  "route": "direct",
  "attachments": null,
  "timings": {
    "queue_ms": null,
    "node_ms": null,
    "settle_ms": null
  },
  "usage_units": {
    "input_tokens": 214,
    "cached_input_tokens": 0,
    "media_tokens": 0,
    "cached_media_tokens": null,
    "long_input_tokens": 0,
    "media_items": 0,
    "thought_tokens": 0
  },
  "refusal_code": null,
  "refusal_codes": [],
  "idempotency": null,
  "stream_id": null,
  "state_version": null
}

Availability and retention

Send decide with an Idempotency-Key. A lookup finds only decisions stored under an Idempotency-Key; see Idempotency.

Unkeyed decisions, older decisions without a lookup index and replies over the storage limits are unavailable.

A stored decision is kept for up to 24 hours, and its answer or index can be removed earlier. Reading it never extends that time.

A lookup runs no new decision and is not charged. It still counts toward your requests a minute. The lookup index keeps no copy of request or answer content.

A decision id is not a permanent archive. Keep the answers you need in your own storage.

Errors and headers

Both reads can return these refusals.

400 invalid_trace_header
X-Client-Request-Id is blank, not printable ASCII or over 512 characters.
401 invalid_api_key
The key is missing, malformed or unknown.
403 auth_error
The key is revoked.
403 account_suspended
The workspace is suspended or waiting for access.
404 decision_not_found
The id is invalid, or no stored decision matches it for this API key.
405 method_not_allowed
The method is not GET, HEAD or OPTIONS.
429 rate_limit_exceeded
Too many requests from this key, workspace or address.
503 service_unavailable
A store the lookup reads cannot answer right now.
503 limiter_unavailable
Rate limiting cannot answer right now.
decision-not-found.json
JSON
{
  "error": {
    "message": "The requested decision is not available.",
    "type": "not_found_error",
    "param": null,
    "code": "decision_not_found",
    "retryable": false
  },
  "request_id": "request-id-from-response"
}

decision_not_found has error.retryable: false. It does not say whether a decision was never stored, expired, was removed or belongs to another key.

Retry only when error.retryable is true. Wait for Retry-After-Ms, in milliseconds, or Retry-After, in seconds; prefer Retry-After-Ms. See Errors.

Lookups use the same requests a minute as decide. Their X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers report them; see Rate limits.

X-Request-Id identifies the lookup, not the original decision. A valid X-Client-Request-Id you send is echoed back.

Lookups never set X-RightNow-Idempotent-Replay. Every response sends Cache-Control: no-store. A 405 lists Allow: GET, HEAD, OPTIONS.