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:
- A prompt — what you want, in plain English (e.g. "Extract the invoice from this email").
- A schema — the shape of the answer you expect (e.g. a
numberand atotal).
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
- The REST API — call it over HTTP from any language (JavaScript, Go, Ruby, a shell script…). Best when your app isn't in Python, or you want a hosted service.
- The Python library (
wassitai) — import it and call it directly. Best inside a Python app; you get real typed objects back.
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:
provider— which model service to use (e.g.groq,openai). AskGET /v1/providersfor the list.X-Provider-Key— your API key for that provider. It's sent with the request and never stored.prompt— the plain-English task.schema— the fields you want. Here, a textnumberand a decimaltotal.
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:
| Style | Looks like | Use 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:
| Field | What it means |
|---|---|
ok | Whether it succeeded. true → read value; false → read error. (Over REST, failures also map to an HTTP error status — see below.) |
value | Your validated object — the actual answer. |
rendered | Present only when render is json/xml: the object re-serialised as text. |
confidence | 0–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. |
diagnostics | A short trace of anything the engine had to fix (e.g. "extracted JSON from surrounding text"). Empty means the output was already perfect. |
usage | How many tokens the request used (helps you track cost). |
error | A 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
| Option | Plain-language meaning |
|---|---|
provider | Which 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.) |
model | Which specific model to use. Leave blank for the provider's default. |
strict | Choices: 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. |
strategy | How Wassitai asks the model for structure. Choices: auto (default), native, tool_calling, prompt_repair — explained one by one below. (Generate only.) |
render | What 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:
| Strategy | How it works | Availability / notes |
|---|---|---|
auto (default) |
Lets Wassitai pick the best method the provider actually supports, trying them in order of
reliability: native → tool_calling → prompt_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:
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:
| Code | Meaning |
|---|---|
422 | The model's output couldn't be validated against your schema. |
401 | Missing or invalid provider key. |
429 | The provider rate-limited you — slow down and retry. |
502 | The upstream provider errored. |
504 | The 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
- Open the playground and run a real request — every option above is a control you can try.
- Browse the interactive API reference to see every endpoint and field.
- Click Integrate ↗ in the playground to copy a ready-to-paste cURL or Python snippet for your exact request.