AI Policy Synthesis
Writing a policy JSON by hand is tedious and error-prone. The policy synthesizer lets operators describe the policy in English and returns a structured draft.
Request
curl -X POST https://us-central1.api.nexastudio.io/policies/synthesize \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "For MAD business and first class, 4+ star only, within 15 km, must have 24-hour reception and airport shuttle. No budget chains.",
"context": { "airport": "MAD", "airline": "XX" }
}'
Response
{
"draftUrn": "urn:nexa:policy-draft:abc",
"source": "ai",
"modelVersion": "nexa-policy-synthesizer-v2",
"confidence": 0.92,
"policy": {
"name": "MAD — VIP tiers (AI draft)",
"context": { "airport": "MAD", "airline": "XX" },
"tiers": ["BUSINESS", "FIRST"],
"constraints": {
"minStars": 4,
"maxDistanceKm": 15,
"requiredAmenities": ["24H_RECEPTION", "AIRPORT_SHUTTLE"],
"excludedChains": ["BUDGETCHAIN_PLACEHOLDER"]
},
"mode": "ON_DEMAND",
"autoApproveDemand": false
},
"warnings": [
"Could not resolve 'budget chains' to specific chain IDs — review excludedChains before activating."
]
}
What the synthesizer does (and doesn't)
It does:
- Map English tier names to Nexa's enum (
business→BUSINESS,VIP→BUSINESS + FIRST). - Infer numeric constraints (
4+ star→minStars: 4,within 15 km→maxDistanceKm: 15). - Map amenity phrases to the normalized amenity tags.
- Attach
contextfrom the request. - Emit
warningsfor anything ambiguous or not fully resolvable.
It doesn't:
- Activate the policy. A draft is just a draft.
- Look up specific hotel chain IDs for exclusion — it flags them in
warningsfor the operator to resolve. - Override explicit operator input. If you pass
confidence < threshold, Nexa returns the draft but marks it for review.
Review flow
- Operator submits a description → receives a draft.
- Ops console renders a diff against the currently-active policy for the same context.
- Operator edits fields where warnings exist.
- Operator calls
POST /policieswith the edited payload (orPOST /policies/drafts/:urn/promote). - Activation is a separate explicit step — the existing policy stays active until the new one is activated.
How it's powered
The synthesizer is a Nexa Trained Model on Google. Strong at structured JSON output, deployed in the regional residency the tenant is pinned to, and metered as part of the platform subscription — there is no third-party LLM API for the customer to provision.
Prompt structure
Internally the synthesizer is split into:
- System — policy schema, valid enums (tiers, amenities, payment methods), and strict output rules (JSON only, no prose).
- Tools — a single
emitPolicytool with the policy JSON schema; the model is forced to call it. - User — the operator's description + optional context.
The schema part is large and static → it caches across requests, keeping latency and cost low.
Confidence scoring
Confidence comes from two signals:
- Schema match rate — did the model produce a draft that validates cleanly against the policy schema?
- Warning count — per-warning penalty on the confidence score.
Below 0.7, Nexa returns the draft but sets requiresReview: true and disables any one-click "promote" actions.
Cost
Synthesis is part of the platform subscription. There is no per-token bill from the customer's side — call it as often as your operators need.
Audit
Every synthesis call writes an audit entry:
- Operator URN
- Input description (verbatim)
- Model version + prompt hash
- Generated draft URN
- Confidence + warnings
If an operator promotes the draft without editing, audit ties the promotion back to the originating synthesis call.