Skip to content
Docs

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.

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.

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
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.

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

  1. In the left sidebar, click Schema Validation (listed under Gateway Routes, Gateway Analytics, Tenant Routing Rules)
  2. 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

  1. Click Save Schema — the rule is active immediately with no restart required
  2. The rule appears in the Schema Validation table showing the route name, direction, mode, and violation count

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:

Terminal window
GET /api/admin/gateway/schemas/:id/violations?limit=50

Use the validate endpoint to test a schema against sample data before creating a rule:

Terminal window
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" }
}
]
}

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"
}
]
}
}

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

  1. Click Schema Validation in the sidebar
  2. Your rule appears in the table columns: Name · Route · Direction · Mode · Violations · Status · Actions
  3. 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:

Terminal window
POST /api/admin/gateway/schemas/validate
Authorization: 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

  1. 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"}]}'
  2. Expected responses based on On Failure setting:
    • Reject → HTTP 400 Bad Request with schema_validation_error and full AJV error list
    • Warn → Request proceeds normally, response includes header X-Schema-Validation: failed
    • Log only → Request proceeds silently, violation is recorded internally

Step 4: Check the Violations count in the table

  1. Return to Schema Validation in the sidebar
  2. The Violations column on your rule row increments with each failure
  3. 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

  1. In the Actions column, use the Enable/Disable toggle to turn the rule off
  2. Re-send the same invalid payload — it passes through without error (rule is off)
  3. Re-enable — the rule enforces again immediately with no restart needed
  4. The Status column updates instantly

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