Structured Decisions

Models that return a typed decision rather than prose. Send a state and a set of questions in one POST and get, per question, a choice, a true/false probability or a score. Built for classification, routing and guardrails: anything where the shape of the answer is known in advance. Responses are synchronous and billed at a flat price per request.

Models & pricing

Every model has its own endpoint and bills a flat price per accepted request. The limits (request body size and question count) are fixed server-side, and the flat price is set against them:

ModelSpecLimitsPriceEndpoint
TypeSafe Jev 1.13
typesafe/jev-1.13
32,000-token context · choice / noul / scoreup to 8,192 bytes · 16 questions$0.00064 / decision/v1/decisions/jev-1-13

The endpoint decides the model. Omit `model` from the body, or send exactly the model id from the table.

POST
/v1/decisions/jev-1-13

Ask for a decision

`state` carries the material to decide on (a string, an object or an array); `questions` is an object keyed by question name. Each question has a `type` (choice / noul / score), `instructions` (what to decide) and `criteria` (what to decide it by). Answers come back under the same keys as the questions.

Request
curl https://api.fastmetal.ai/v1/decisions/jev-1-13 \
  -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d {
    "state": "Customer wrote: my order never arrived and I want a refund.",
    "questions": {
      "intent": {
        "type": "choice",
        "instructions": "What does the customer want?",
        "criteria": {
          "refund": "they want their money back",
          "track_order": "they want to know where the order is",
          "other": "anything else"
        }
      },
      "is_angry": {
        "type": "noul",
        "instructions": "Is the customer expressing anger?",
        "criteria": { "true": "hostile or frustrated tone", "false": "neutral or polite" }
      }
    }
  }
Response (200)
{
  "id": "gen-dec-1789761592-hJ9ahabHqfnukm1bqQ4M",
  "model": "typesafe/jev-1.13-20260917",
  "answers": {
    "intent": {
      "type": "choice",
      "choice": "refund",
      "probabilities": { "refund": 1, "track_order": 0, "other": 0 },
      "confidence": 1
    },
    "is_angry": { "type": "noul", "noul": 0.86 }
  },
  "usage": { "input_tokens": 347, "output_tokens": 39 }
}

Question types

The three types can be mixed in one request. The shape of `criteria` depends on the type.

  • choice — Pick one of several options. `criteria` is an object of option name → description; the answer carries `choice`, per-option `probabilities` and a `confidence`.
  • noul — A true/false judgement. `criteria` is an object keyed `true` and `false`; the answer's `noul` is the probability (0 to 1) that the answer is true.
  • score — A graded score. `criteria` is an array describing the levels from lowest to highest, and `score` is returned on that array's index scale (0 to 2 for three levels, fractional). The answer carries `score`, a `legend` mapping each level to its description, per-level `probabilities` and a `confidence`.

Billing

  • Each model's flat price is deducted from your key's balance once per accepted request (HTTP 200). The number of questions and the length of the body do not change it.
  • Rejected requests (HTTP 4xx/5xx) are not billed. An oversized body, a field that is not allowed, or a malformed question comes back as HTTP 400.
  • If you never received a response (timeout, dropped connection) the outcome is unknown. Decisions return in about a second, so wait briefly before retrying.
  • Because the price is per accepted request, asking every question that fits in one call is the cheapest way to use it. Adding questions does not change the price.

From an agent (MCP)

The same decision is available as the decide tool on the FastMetal MCP server: same models, same flat price, billed to your own key. It is the shape an agent can branch on directly, without parsing prose, which is what makes it useful for classifying and routing inside an agent’s own logic.

Limits

  • Request body size and question count are fixed per model (see the table). Size is counted on the request as it is sent upstream: compact JSON, including the pinned model name. Anything larger is rejected with HTTP 400.
  • The body may contain only `state`, `questions` and `model`.
  • Decisions are rate-limited platform-wide; HTTP 429 means retry shortly.