API docs

One endpoint for Kev and Strands Decider. Requests and answers follow the TypeSafe SystemOne shapes.

Base URL
https://api.decider.cloud
Authentication
None during the public preview
Format
JSON over HTTPS

Quickstart

Request
curl https://api.decider.cloud/v1/systemone \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "kev-4b",
    "state": "Our payment service has been down for three hours.",
    "questions": {
      "urgent": {
        "type": "noul",
        "instructions": "Is this urgent?"
      }
    }
  }'
Response
{
  "model": "kev-4b",
  "answers": {
    "urgent": {
      "type": "noul",
      "noul": 0.68235
    }
  },
  "usage": {
    "input_tokens": 23,
    "output_tokens": 19
  },
  "latency_ms": 143.59
}

The first request after the API has been idle can take about 30 seconds while the models load. Later requests return in well under a second.

Public preview

The hosted API is free while it is in public preview. It runs on a single shared GPU with a fixed monthly compute budget, so treat it as a place to prototype, evaluate, and research, not as production infrastructure.

  • No uptime guarantee. Availability is best-effort. The API can be slow, busy, or down, and there is no SLA.
  • Shared capacity. One inference runs at a time across all users. Expect 429 responses when it is busy.
  • Fixed budget. If the monthly compute budget runs out, the API stops responding until it resets.
  • Things can change. Models, limits, and the preview itself can change or end.
  • Your data. Request content is never stored. Decider logs only the model name and timing of each request. Requests do pass through Cloudflare and Modal, so don’t send personal or confidential data.

Both models are open source: Kev and Strands Decider.

Need guaranteed capacity or a private deployment? Message me on X about running Decider on your own compute.

Request

POST/v1/systemone

FieldTypeDescription
modelstringkev-4b or strands-decider-2b.
statestring, object, or arrayThe context every question is asked about. Can’t be empty.
questionsobjectOne to eight questions, keyed by names you choose. Answers come back under the same keys.

Every question has a type, instructions(string, object, or array), and, depending on the type,criteria. Unknown fields are rejected.

Question types

noul

Returns noul, the probability that the answer is true. Optional criteria describe what true andfalse mean.

Question
{
  "urgent": {
    "type": "noul",
    "instructions": "Is this urgent?",
    "criteria": {
      "true": "Customers are blocked right now",
      "false": "Nothing is blocked"
    }
  }
}

choice

criteria maps 1 to 255 option names to descriptions, or tonull. Returns the choice, a probability for every option, and a confidence. Ties go to the first option listed.

Question
{
  "route": {
    "type": "choice",
    "instructions": "Which team should handle this?",
    "criteria": {
      "engineering": "Production outages and technical failures",
      "billing": "Invoices and payment questions",
      "sales": null
    }
  }
}
Answer
{
  "probabilities": {
    "engineering": 0.91147,
    "billing": 0.082139,
    "sales": 0.006391
  },
  "confidence": 0.867204,
  "type": "choice",
  "choice": "engineering"
}

score

criteria is an ordered list of 2 to 10 level descriptions. Returns score, the expected zero-based level, which can fall between levels. Also returns per-level probabilities, aconfidence, and a legend.

Question
{
  "severity": {
    "type": "score",
    "instructions": "How severe is this incident?",
    "criteria": [
      "Minor inconvenience",
      "Service is degraded",
      "Customers cannot make payments"
    ]
  }
}
Answer
{
  "probabilities": {
    "0": 0.125318,
    "1": 0.128191,
    "2": 0.746491
  },
  "confidence": 0.43176,
  "type": "score",
  "score": 1.621173,
  "legend": {
    "0": "Minor inconvenience",
    "1": "Service is degraded",
    "2": "Customers cannot make payments"
  }
}

Response

FieldDescription
modelThe model that answered.
answersOne answer per question, under the question’s key.
usageinput_tokens counts rendered model tokens;output_tokens counts the serialized answers.
latency_msTime spent on the GPU, including tokenization. Excludes network time and cold starts.

Probabilities, noul, confidence, andscore have up to six decimal places. Each distribution sums to exactly 1, and the selected choice is computed before rounding.

Models and limits

Limitkev-4bstrands-decider-2b
Context per question12,288 tokens4,096 tokens
State8,192 tokensMust fit beside the longest question
Single questionWithin the context limit3,072 tokens
Warm runtime, p5086 ms45 ms

Both models accept up to 8 questions per request, 255 options per choice, 10 score levels, and a 256 KiB request body. Token counts include each model’s prompt formatting, so an input can fit Kev and still be too long for Strands. Inputs are never truncated; oversized context returns 422.

Errors

Error body
{
  "error": {
    "code": "busy",
    "message": "GPU is busy; retry shortly"
  }
}
StatusCodeWhat to do
404model_not_foundCheck the model field.
413body_too_largeKeep the request body under 256 KiB.
422invalid_requestFix the fields listed in error.fields, or shorten input that exceeds the model’s context.
429busyAnother request is running. Retry with backoff.
500inference_failedRetry once. If it repeats, the input may be the cause.
503not_readyThe models are still loading. Retry shortly.

429 and 503 responses includeRetry-After: 1. Validation errors list the failing field paths but never echo your input back.

Other endpoints

GET/v1/models

Lists the available models and their limits.

Response
{
  "models": [
    {
      "id": "kev-4b",
      "provider": "kev",
      "context_tokens": 12288,
      "question_types": [
        "noul",
        "choice",
        "score"
      ],
      "max_questions": 8,
      "max_choice_options": 255,
      "max_score_levels": 10
    },
    {
      "id": "strands-decider-2b",
      "provider": "strands",
      "context_tokens": 4096,
      "question_types": [
        "noul",
        "choice",
        "score"
      ],
      "max_questions": 8,
      "max_choice_options": 255,
      "max_score_levels": 10
    }
  ]
}

GET/health

Returns {"status": "ok"} when both models are loaded, or 503 while they load. Calling it wakes the GPU, so don’t poll it continuously.

Compatibility

Request and answer shapes follow TypeSafe SystemOne. Decider is an independent implementation: predictions and confidence thresholds are not guaranteed to match TypeSafe, or each other across models.

Choice and score confidence use the TypeSafe reference formulas for both models. Choice confidence is(n × max(p) − 1) / (n − 1), or 1 for a single option. Strands rounds probabilities to four decimal places before Decider normalizes them.