JSON Schema Validation
AgentWatch validates request and response bodies against JSON Schema definitions using AJV (Another JSON Validator — draft-07/2020-12). Schema rules are attached to individual gateway routes, enabling per-route payload enforcement without touching application code.
How It Works
Section titled “How It Works”Inbound Request │ ▼┌─────────────────────────────────────────────────────┐│ Schema Validation Layer (if rule enabled for route) ││ ││ 1. Look up all enabled schema rules for this route ││ 2. For each matching rule (direction: request/both):││ a. Run AJV validation against the request body ││ b. On failure → apply onFailure action ││ • reject → 400 Bad Request (stop here) ││ • warn → add warning header, continue ││ • log → record violation, continue │└─────────────────────────────────────────────────────┘ │ ▼ (request forwarded upstream) │ ▼┌─────────────────────────────────────────────────────┐│ Response Validation (if direction: response/both) ││ Same AJV check on the upstream response body │└─────────────────────────────────────────────────────┘Multiple schemas can be attached to the same route — each is evaluated independently.
Schema Rule Fields
Section titled “Schema Rule Fields”| Field | Required | Description |
|---|---|---|
| Name | Yes | Human-readable identifier (e.g., Validate Chat Request) |
| Description | No | Optional notes about what the schema enforces |
| Gateway Route | Yes | Select the gateway route to protect from the dropdown — lists all configured routes by name and path |
| Validate Direction | Yes | When to validate: Request only, Response only, or Both |
| On Failure | Yes | What to do when validation fails (see below) |
| Enabled | Yes | Toggle the rule on/off without deleting it |
| JSON Schema | Yes | Standard JSON Schema draft-07, validated with AJV |
Validate Direction Options
Section titled “Validate Direction Options”| Option | When Validation Runs |
|---|---|
| Request only | Validates the inbound request body before forwarding to the LLM |
| Response only | Validates the upstream LLM response before returning to the client |
| Both | Validates both the request and the response |
Use Request only to enforce correct API structure from callers. Use Response only to catch unexpected LLM outputs. Use Both for strict end-to-end contracts.
On Failure Options
Section titled “On Failure Options”| Option | HTTP Behavior | Use Case |
|---|---|---|
| Reject request (400) | Returns 400 Bad Request with detailed errors. Request is not forwarded. |
Strict enforcement — reject malformed payloads |
| Warn (pass through) | Request proceeds normally. Adds X-Schema-Validation: failed response header. |
Gradual rollout — monitor without breaking clients |
| Log only | Request proceeds silently. Violation is recorded internally for later review. | Audit mode — understand traffic before enforcing |
Step-by-Step: Adding a Schema Validation Rule
Section titled “Step-by-Step: Adding a Schema Validation Rule”Step 1: Navigate to Schema Validation
- In the left sidebar, click Schema Validation (listed under Gateway Routes, Gateway Analytics, Tenant Routing Rules)
- Click + New Schema — a modal opens
Step 2: Fill in the Fields
- Name: A descriptive name, e.g.,
Validate Chat Request - Description: Optional notes, e.g.,
Ensure messages array is present and non-empty - Gateway Route: Select the route to protect from the dropdown — all configured Gateway Routes are listed by name and path (e.g.
My LLM Route (/v1/chat/completions)) - Validate Direction: Choose when validation runs (see options below)
- On Failure: Choose what happens on failure (see options below)
- Enabled: Leave checked to activate immediately
Step 4: Choose Validate Direction
- Request only — validates the inbound request before forwarding to the LLM
- Response only — validates the LLM response before returning to the caller
- Both — validates both
Start with Request only unless you specifically need to validate LLM output structure.
Step 5: Choose On Failure Behavior
Start with Log only or Warn to understand real traffic before switching to Reject.
Step 6: Write the JSON Schema
Use the JSON Schema (draft-07) format. Click Format JSON to auto-indent your schema. Example schemas:
Validate a standard chat completion request:
{ "type": "object", "required": ["model", "messages"], "properties": { "model": { "type": "string" }, "messages": { "type": "array", "minItems": 1, "items": { "type": "object", "required": ["role", "content"], "properties": { "role": { "type": "string", "enum": ["system", "user", "assistant"] }, "content": { "type": "string" } } } }, "max_tokens": { "type": "integer", "minimum": 1, "maximum": 4096 }, "temperature": { "type": "number", "minimum": 0, "maximum": 2 } }, "additionalProperties": false}Validate max token limit is always specified:
{ "type": "object", "required": ["max_tokens"], "properties": { "max_tokens": { "type": "integer", "minimum": 1 } }}Validate that temperature is within a safe range:
{ "type": "object", "properties": { "temperature": { "type": "number", "minimum": 0, "maximum": 1 } }}Step 7: Save
- Click Save Schema — the rule is active immediately with no restart required
- The rule appears in the Schema Validation table showing the route name, direction, mode, and violation count
Violation Tracking
Section titled “Violation Tracking”Every failed validation is recorded in memory (up to 10,000 violations, newest first) with:
| Field | Description |
|---|---|
timestamp |
When the violation occurred |
schemaId |
Which schema rule was violated |
schemaName |
Human-readable schema name |
routeId |
Which gateway route was targeted |
direction |
Whether it was a request or response failure |
errors |
Array of AJV error objects with path, message, and keyword |
action |
What was done: rejected, warned, or logged |
clientIp |
IP address of the caller |
Query violations via the admin API:
GET /api/admin/gateway/schemas/:id/violations?limit=50Test a Schema Without Saving
Section titled “Test a Schema Without Saving”Use the validate endpoint to test a schema against sample data before creating a rule:
POST /api/admin/gateway/schemas/validate{ "schema": "{\"type\":\"object\",\"required\":[\"model\"]}", "data": { "messages": [] }}Response:
{ "success": true, "valid": false, "errors": [ { "path": "/", "message": "must have required property 'model'", "keyword": "required", "params": { "missingProperty": "model" } } ]}Rejection Response Example
Section titled “Rejection Response Example”When On Failure is set to Reject and a request fails validation:
HTTP 400 Bad Request{ "error": { "message": "Request body failed schema validation", "type": "schema_validation_error", "code": "SCHEMA_INVALID", "violations": [ { "path": "/messages/0/content", "message": "must be string", "keyword": "type" }, { "path": "/", "message": "must have required property 'model'", "keyword": "required" } ] }}Verifying Schema Validation in the UI
Section titled “Verifying Schema Validation in the UI”After saving a schema rule you can confirm it is working end-to-end entirely through the Admin Panel.
Step 1: Confirm the rule is listed
- Click Schema Validation in the sidebar
- Your rule appears in the table columns: Name · Route · Direction · Mode · Violations · Status · Actions
- Confirm the Status column shows Enabled
Step 2: Test using the API (no coding required)
Use the validate endpoint to test your schema against a sample payload before sending real traffic. You can run this from the Admin Panel’s browser console or from any API client:
POST /api/admin/gateway/schemas/validateAuthorization: Bearer <your-admin-token>Content-Type: application/json
{ "schema": "{\"type\":\"object\",\"required\":[\"model\",\"messages\"]}", "data": { "messages": [] }}Response — invalid (missing model):
{ "success": true, "valid": false, "errors": [{ "path": "/", "message": "must have required property 'model'", "keyword": "required" }] }Response — valid:
{ "success": true, "valid": true, "errors": [] }Step 3: Trigger a real violation through the gateway
- Send a request to the gateway route path with a deliberately invalid payload, e.g. omit
model:Terminal window curl -X POST http://your-gateway/v1/chat/completions \-H "Authorization: Bearer <tenant-key>" \-H "Content-Type: application/json" \-d '{"messages":[{"role":"user","content":"hello"}]}' - Expected responses based on On Failure setting:
- Reject → HTTP
400 Bad Requestwithschema_validation_errorand full AJV error list - Warn → Request proceeds normally, response includes header
X-Schema-Validation: failed - Log only → Request proceeds silently, violation is recorded internally
- Reject → HTTP
Step 4: Check the Violations count in the table
- Return to Schema Validation in the sidebar
- The Violations column on your rule row increments with each failure
- Click the violations count to open the violations log showing:
- Timestamp of each failure
- Direction (request / response)
- AJV error details (path + message + keyword)
- Action taken (rejected / warned / logged)
- Client IP
Step 5: Toggle the rule to confirm it is enforcing
- In the Actions column, use the Enable/Disable toggle to turn the rule off
- Re-send the same invalid payload — it passes through without error (rule is off)
- Re-enable — the rule enforces again immediately with no restart needed
- The Status column updates instantly
API Reference
Section titled “API Reference”| Method | Endpoint | Description |
|---|---|---|
| GET | /api/admin/gateway/schemas |
List all schema rules |
| GET | /api/admin/gateway/schemas/:id |
Get a single schema rule |
| POST | /api/admin/gateway/schemas |
Create a new schema rule |
| PUT | /api/admin/gateway/schemas/:id |
Update a schema rule |
| DELETE | /api/admin/gateway/schemas/:id |
Delete a schema rule |
| POST | /api/admin/gateway/schemas/validate |
Test a schema against sample data (no rule required) |
| GET | /api/admin/gateway/schemas/:id/violations |
List violations for a schema |