Supply application state
State is context your application supplies alongside a request. Use it for facts that the model should not have to infer from a user's message: available choices, a current status, a balance or a set of permissions.
State is optional. It is a snapshot for this request, not a database managed by Struct. Omitting it adds no state content to the model's prompt.
You can use the same snapshot in three ways:
| Need | Guide |
|---|---|
| Help the model interpret known facts | The context example below |
| Restrict available values or whether a field may appear | State in schema conditions |
| Repeat a decision for each supplied item | For-each loops |
| Enforce a rule involving the answer and application facts | State in OPA rules |
Input, state and parameters
| Request field | Purpose |
|---|---|
input | The material to interpret or the task to perform. It can be text or JSON. |
state | Facts about the application or user that should inform this answer. |
parameters | Optional named context values. They do not substitute placeholders in your schema. |
user_context | Optional verified permission names in scopes and application-defined user facts in attributes. |
Use input and state unless you have a reason to keep a separate set of parameters. The names within a state object are yours to choose; describe how the model should use them.
Example: use an account fact
A message says what the user needs. The account's plan is already known by the application. Here the field description tells the model to use state.plan when choosing a queue. This demonstrates contextual guidance, not a mandatory permission rule.
Save these two files. The schema defines the answer; the state file supplies the known fact.
{
"type": "object",
"properties": {
"queue": {
"type": "string",
"enum": ["business_billing", "billing", "technical"],
"description": "Use business_billing for billing issues when state.plan is business, billing for other billing issues, and technical for product faults."
}
},
"required": ["queue"],
"additionalProperties": false
}
{"plan": "business", "preferred_language": "en"}
Attach the state
The request sends the message and the two files together:
Before you run this example
Call https://api.blatent.ai from your server. Set your API key in the same terminal where you run the example:
export BLATENT_API_KEY='YOUR_SERVICE_KEY'
Python requires Python 3.10+ and HTTPX:
python -m pip install "httpx>=0.28,<1"
TypeScript requires Node.js 24+ and uses its built-in fetch. The cURL examples require curl and jq.
Save the displayed files and the selected client in one directory. Run the client there with python example.py, node example.ts or bash example.sh. Downloads use the example's name in place of example.
- Python
- TypeScript
- cURL
import json
import os
from pathlib import Path
import httpx
request = {
"input": "Which queue should handle my duplicate invoice charge?",
"schema": json.loads(Path("account-routing.schema.json").read_text(encoding="utf-8")),
"state": json.loads(Path("account.state.json").read_text(encoding="utf-8")),
}
with httpx.Client(
base_url="https://api.blatent.ai",
headers={"Authorization": f"Bearer {os.environ['BLATENT_API_KEY']}"},
timeout=195,
) as client:
response = client.post("/v1/resolve", json=request)
response.raise_for_status()
print(json.dumps(response.json()["output"]))
import { readFileSync } from "node:fs";
const request = {
"input": "Which queue should handle my duplicate invoice charge?",
"schema": JSON.parse(readFileSync("account-routing.schema.json", "utf8")),
"state": JSON.parse(readFileSync("account.state.json", "utf8")),
};
const response = await fetch(
"https://api.blatent.ai" + "/v1/resolve",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BLATENT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(request),
signal: AbortSignal.timeout(195_000),
},
);
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(JSON.stringify((await response.json()).output));
set -eu
body=$(jq -n --argjson body '{"input":"Which queue should handle my duplicate invoice charge?"}' \
--slurpfile f0 'account-routing.schema.json' \
--slurpfile f1 'account.state.json' \
'$body | setpath(["schema"]; $f0[0]) | setpath(["state"]; $f1[0])')
curl --fail-with-body --silent --show-error \
"https://api.blatent.ai/v1/resolve" \
-H "Authorization: Bearer $BLATENT_API_KEY" \
-H 'Content-Type: application/json' \
--data-binary "$body"
Illustrative output: {"queue":"business_billing"}. The same schema can receive a different account snapshot on the next request.
When context must become a restriction
A description helps the model use state, but does not enforce a relationship with it. For a mandatory restriction on available choices, use eligibleWhen in the schema. For richer rules comparing answers with state, use OPA and read the snapshot through input.state.
The separate schema conditions and OPA state rules guides each contain a complete example. Permission context shows how application-supplied OAuth scopes can restrict permitted outcomes. Build such facts in your backend rather than taking permission claims from the user’s message.