Wassitai
← Playground API reference

Turn messy AI text into clean data.

Large language models answer in free-form text. Wassitai takes that text and hands you back a validated object — the exact fields you asked for, with the right types — so your code can use it directly. No brittle string-parsing, no "sometimes it returns markdown." This guide assumes no prior experience.

The core idea

You give Wassitai two things:

  1. A prompt — what you want, in plain English (e.g. "Extract the invoice from this email").
  2. A schema — the shape of the answer you expect (e.g. a number and a total).

You get back an object that matches your schema, already checked for you. If the model's first answer is slightly malformed (extra markdown, a trailing comma, a number written as text), Wassitai repairs and validates it — and if it still doesn't fit, it asks the model to try again.

Already have the AI's text? You don't need to call a model at all — use Parse to run just the cleanup-and-validate step on text you already have.

Two ways to use it

Both run the exact same engine. The playground you came from is itself built on the REST API.

Quickstart · REST

Send a POST to /v1/generate with your prompt and schema:

curl -X POST $WASSITAI_URL/v1/generate \
  -H "X-Provider-Key: $YOUR_PROVIDER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "groq",
    "prompt": "Extract the invoice from: Invoice A-1, total $9.50 due April.",
    "schema": { "number": "str", "total": "float" }
  }'

Each piece:

To clean up text you already have (no model call, no key), POST to /v1/parse with text instead of prompt.

Quickstart · Python

pip install wassitai
from wassitai import Client
from pydantic import BaseModel

# 1. Describe the shape you want as a normal Python class.
class Invoice(BaseModel):
    number: str
    total: float

# 2. Point at a provider and ask.
client = Client.from_provider("groq", api_key="…")
invoice = client.generate("Extract the invoice: Invoice A-1, total $9.50", schema=Invoice)

print(invoice.number, invoice.total)   # A-1 9.5  — a real, typed object

Already have the text? Skip the model entirely:

from wassitai import parse

invoice = parse('{"number": "A-1", "total": 9.5}', Invoice)

Writing a schema

The schema is just "the fields I want back." You can write it three ways — pick whichever is easiest:

StyleLooks likeUse when
Simple map {"number": "str", "total": "float"} You just want a few fields. Easiest to start with.
JSON Schema {"type": "object", "properties": {…}} You need nested objects, lists, or precise rules.
Python class class Invoice(BaseModel): … You're in Python — you get editor autocomplete and types.

Field types in the simple map: str (text), int (whole number), float (decimal), bool (true/false). An unrecognised type name falls back to text — or is rejected when strict is on.

Reading the response

A successful response gives you more than just the data:

FieldWhat it means
okWhether it succeeded. true → read value; false → read error. (Over REST, failures also map to an HTTP error status — see below.)
valueYour validated object — the actual answer.
renderedPresent only when render is json/xml: the object re-serialised as text.
confidence0–100%. Starts at 100 and drops a little each time the text had to be repaired or the model re-asked. High = clean on the first try.
diagnosticsA short trace of anything the engine had to fix (e.g. "extracted JSON from surrounding text"). Empty means the output was already perfect.
usageHow many tokens the request used (helps you track cost).
errorA human-readable message when ok is false — e.g. which field failed validation.

In the playground, the vertical pipeline spine shows these stages lighting up, and the ring shows the confidence score. A blue ✓ stage passed, gold ↻ means it repaired something, and red ✕ means it failed there.

The options, explained

OptionPlain-language meaning
providerWhich model service to use. Choices: groq, openai, deepseek, openrouter — or any OpenAI-compatible endpoint via a custom base URL. GET /v1/providers returns the live list. (Generate only.)
modelWhich specific model to use. Leave blank for the provider's default.
strictChoices: false (default) or true. On: types must match exactly — the text "3" is rejected where a number is required. Off: close-enough values are converted for you. Off is friendlier while experimenting; on is safer for production data.
strategyHow Wassitai asks the model for structure. Choices: auto (default), native, tool_calling, prompt_repairexplained one by one below. (Generate only.)
renderWhat you get back. Choices: object (default), json, xml. With json/xml the serialised text arrives in the response's rendered field (the object is still in value).
max_retries / “Re-asks”How many times to re-ask the model after a validation failure before giving up. Default 1; use 0 to fail fast, or higher to try harder. (Generate only — parsing never calls a model.)
many / “Expect a list”For a list of items rather than one. In the playground it's a toggle; via the API/library you express it in the schema — REST {"type":"array","items":{…}}, Python List[Invoice].

The four strategies, one by one

A strategy is how Wassitai coaxes structured output out of a model. Providers differ in what they support, so there are three real methods plus auto:

StrategyHow it worksAvailability / notes
auto (default) Lets Wassitai pick the best method the provider actually supports, trying them in order of reliability: nativetool_callingprompt_repair. Leave it here unless you're deliberately testing one method. It will never pick something the provider can't do.
native Uses the provider's built-in structured-output mode: your schema is handed to the model and it is constrained to return JSON that matches. The most reliable method. Only when the provider supports it (OpenAI-style json_schema / structured outputs). Forcing it on a provider that doesn't will fail.
tool_calling Describes your schema as a single "tool" (function) and forces the model to call it — the call's arguments are your object. Providers that support tool / function calling. Returns one object; for a list it falls back to prompt & repair.
prompt_repair The universal fallback: your schema is described in the prompt, then the reply is extracted from any surrounding text, repaired, validated, and — if it still doesn't fit — the model is asked to correct it. Works with any provider, even ones with no structured-output features. The most portable method, and the safety net auto ends on.

Not sure which to pick? Leave it on auto. The manual choices exist for when you want to force or compare a specific mechanism.

What the pipeline does

Every response runs through six small steps. You don't have to think about them — but this is what's happening under the hood:

normalizeTidy whitespace & encoding.
extractPull the data out of any surrounding chatter or markdown.
syntax_repairFix trailing commas, smart quotes, unbalanced brackets.
deserializeTurn the text into a real data structure.
validateCheck it against your schema.
coerceNudge close-enough types into the right ones.

If validation fails, Wassitai shows the model its own failed answer and asks it to correct it — up to a small retry limit — instead of giving up.

When things go wrong

The REST API maps failures to standard HTTP status codes, so you can handle them like any other request:

CodeMeaning
422The model's output couldn't be validated against your schema.
401Missing or invalid provider key.
429The provider rate-limited you — slow down and retry.
502The upstream provider errored.
504The provider took too long.

In Python, a validation failure raises a ParseError that carries the field-level details, so you can see exactly which field didn't fit.

Next steps