Ana içeriğe geç

Groundedness Guard Policy

General Information​

Policy Types​

ai-groundedness-guard

Response-phase only, non-streaming responses only. Always judge-based — there is no cheap deterministic check for "is this text supported by that text", so a judge configuration is required.

Endpoints​

List Policies​

GET /apiops/projects/{projectName}/apiProxies/{apiProxyName}/policies/

Add Policy​

POST /apiops/projects/{projectName}/apiProxies/{apiProxyName}/policies/{policyName}/

Update Policy​

PUT /apiops/projects/{projectName}/apiProxies/{apiProxyName}/policies/{policyName}/

Delete Policy​

DELETE /apiops/projects/{projectName}/apiProxies/{apiProxyName}/policies/{policyName}/

Scope​

This policy only checks the response against the RAG context your own Apinizer proxy retrieved and injected in the same request/response cycle — it is not a general "is this fact true" check against outside knowledge, and it produces no per-claim citations. It only detects the retrieved context when the RAG Injection policy on the same proxy uses injectionMode=TEMPLATE (the default template, or a custom one that still contains the <CONTEXT>...</CONTEXT> markers). When no RAG context is detectable — including a request the RAG Injection policy did not touch at all — this policy is a silent no-op, not an error.

Fields​

FieldTypeRequiredDescription
actionstringNoFLAG (monitoring-only, default) or BLOCK.
failModestringNoFAIL_OPEN or FAIL_CLOSED — behaviour when the judge call itself errors or times out. Default FAIL_CLOSED: the response is blocked rather than let an unverified answer through.
latencyModestringNoINLINE, ASYNC or SHADOW. Default INLINE — this is a response-blocking security check, so it does not default to fire-and-forget the way some other AI guardrails do.
maxWaitMsintegerNoBounded max wait (ms) for ASYNC/INLINE. Default 3000.
externalGuardrailobjectYesThe judge configuration. See Judge fields. Always required — this policy has no builtin, non-judge leg.
maxContextCharsintegerNoTruncation cap (chars) for the retrieved context before it is composed into the judge's input. Default 6000.
maxResponseCharsintegerNoTruncation cap (chars) for the response text before it is composed into the judge's input. Default 4000.

Judge fields​

externalGuardrail is always type: "llm-judge" for this policy — there is no http-dlp option, unlike the DLP-family guardrails.

FieldTypeRequiredDescription
typestringYesMust be llm-judge.
llmProviderNamestringYesName of the LLM connection to call as the judge. Resolved server-side; an unknown name is rejected with 400. Apinizer looks for the name in the project of the API proxy first, then in the admin project (shared providers). A provider in the own project wins when both have the same name.
modelIdstringNoJudge model identifier.
promptTemplatestringConditionalThe judge's prompt template. Required for a chat judge. Unlike the Prompt Guard policy, a blank template is rejected, not defaulted — a blank template falls back to a generic safety-taxonomy judge that does not answer a groundedness question at all (error key prompttemplaterequired). Not required when decisionQuestion (TypeSafe Jev) or unsafeLabels (TEI) is set.
jsonModebooleanNoWhether the judge is asked to respond in JSON mode.
maxOutputTokensintegerNoJudge max output tokens.
timeoutMsintegerNoHTTP call timeout (ms).
maxInputCharsintegerNoMax input characters sent to the judge.
decisionModestringNoSTANDARD or REASONING. Unset is STANDARD. llm-judge only, chat judge. STANDARD: temperature 0, small output limit, default timeoutMs 2000, default maxOutputTokens 64. REASONING: for thinking models; no temperature is sent, maxOutputTokens is the budget for thinking and verdict together, default timeoutMs 15000 (up to 60000), default maxOutputTokens 1024. A value that you set always wins over the default
decisionThresholdnumberNoVerdict threshold for TypeSafe Jev and TEI judges. Range 0.05 to 0.99. Default 0.5. A value outside the range is set to the nearest limit. Jev: unsafe when the probability is at or above the value. TEI: unsafe when a selected label scores at or above the value
unsafeLabelsarray[string]ConditionalTEI judge only. Labels that mean unsafe, for example INJECTION and JAILBREAK. Matching is not case-sensitive. Required for a TEI judge: at least one label (error key unsafelabelsrequired).
decisionQuestionstringConditionalTypeSafe Jev judge only. The yes/no question that Jev answers about the text. yes means unsafe. Required for a TypeSafe Jev judge on this policy (error key decisionquestionrequired). Default question in the Manager UI: Is the answer not supported by the given context? Answer yes when it states facts, numbers or names that the context does not contain.

Judge providers. llmProviderName can name an OpenAI-compatible chat provider, an Anthropic provider, a TypeSafe Jev provider (decision model), or a TEI provider (guard classifier). AWS Bedrock, Google Vertex AI, Cohere, the native Gemini wire format, embedding-only providers, and custom providers without an adapter family cannot judge. The provider must use credentials held by the AI gateway (Provided by AI gateway). TypeSafe Jev and TEI make decisions only: they do not use promptTemplate, jsonMode, or maxOutputTokens, and they cannot be a routing target, a pool member, a failover target, or an embedding provider.

If the judge provider refuses to answer for safety reasons, the verdict is UNSAFE with the category provider-refusal. FAIL_OPEN does not let this request through. maxWaitMs still limits the whole check, so a slow reasoning judge is cut off by it and failMode decides.


List Policies​

Endpoint​

GET /apiops/projects/{projectName}/apiProxies/{apiProxyName}/policies/

Request​

Headers​

HeaderValue
AuthorizationBearer {token}
Content-Typeapplication/json

Path Parameters​

ParameterTypeRequiredDescription
projectNamestringYesProject name
apiProxyNamestringYesAPI Proxy name

Response​

Success Response (200 OK)​

{
"status": "SUCCESS",
"resultList": [
{
"apiProxy": {
"name": "MyAiProxy",
"requestPolicyList": [],
"responsePolicyList": [
{
"type": "ai-groundedness-guard",
"name": "kb-groundedness-check",
"description": "Flags support-chat answers not grounded in the retrieved KB context",
"active": true,
"action": "FLAG",
"failMode": "FAIL_CLOSED",
"latencyMode": "INLINE",
"maxWaitMs": 3000,
"maxContextChars": 6000,
"maxResponseChars": 4000,
"externalGuardrail": {
"type": "llm-judge",
"llmProviderName": "openai-judge",
"modelId": "gpt-4o-mini",
"promptTemplate": "Task: Determine whether the ASSISTANT RESPONSE is fully grounded in the RETRIEVED CONTEXT...\n\n<<<PROMPT>>>",
"jsonMode": false,
"maxOutputTokens": 200,
"timeoutMs": 8000,
"maxInputChars": 12000
}
}
],
"errorPolicyList": []
}
}
],
"resultCount": 1
}
Masked secrets

The judge's LLM connection carries its own credentials in the LLM provider connection config, not in this policy — there is no secret field on ai-groundedness-guard itself.

cURL Example​

curl -X GET \
"https://demo.apinizer.com/apiops/projects/MyProject/apiProxies/MyAiProxy/policies/" \
-H "Authorization: Bearer YOUR_TOKEN"

Add Policy​

Endpoint​

POST /apiops/projects/{projectName}/apiProxies/{apiProxyName}/policies/{policyName}/

Request​

Headers​

HeaderValue
AuthorizationBearer {token}
Content-Typeapplication/json

Path Parameters​

ParameterTypeRequiredDescription
projectNamestringYesProject name
apiProxyNamestringYesAPI Proxy name
policyNamestringYesPolicy name

Request Body​

Full JSON Body Example​
{
"operationMetadata": {
"targetScope": "ALL",
"targetPipeline": "RESPONSE",
"deploy": true,
"deployTargetEnvironmentNameList": ["production"],
"order": 1
},
"policy": {
"type": "ai-groundedness-guard",
"description": "Flags support-chat answers not grounded in the retrieved KB context",
"active": true,
"action": "FLAG",
"failMode": "FAIL_CLOSED",
"latencyMode": "INLINE",
"maxWaitMs": 3000,
"maxContextChars": 6000,
"maxResponseChars": 4000,
"externalGuardrail": {
"type": "llm-judge",
"llmProviderName": "openai-judge",
"modelId": "gpt-4o-mini",
"promptTemplate": "Task: Determine whether the ASSISTANT RESPONSE is fully grounded in the RETRIEVED CONTEXT...\n\n<<<PROMPT>>>",
"jsonMode": false,
"maxOutputTokens": 200,
"timeoutMs": 8000,
"maxInputChars": 12000
}
}
}
Example — TypeSafe Jev Judge​

With a decision-only judge, promptTemplate is not needed. decisionQuestion is required:

"externalGuardrail": {
"type": "llm-judge",
"llmProviderName": "typesafe-jev",
"modelId": "jev-latest",
"decisionQuestion": "Is the answer not supported by the given context? Answer yes when it states facts, numbers or names that the context does not contain.",
"decisionThreshold": 0.5
}

Body Fields​

See Fields and Judge fields above.

Response​

Success Response (200 OK)​

{
"status": "SUCCESS",
"deploymentResult": {
"success": true,
"deploymentResults": [
{
"environmentName": "production",
"success": true,
"message": "Deployment successful"
}
]
}
}

Error Responses​

CodeReason
400Blank name; maxWaitMs/maxContextChars/maxResponseChars not positive; externalGuardrail missing; externalGuardrail.type blank; externalGuardrail.llmProviderName blank or does not resolve to an existing LLM connection in the project; the judge instruction that matches the provider kind is missing: externalGuardrail.decisionQuestion for a TypeSafe Jev provider, externalGuardrail.unsafeLabels (at least one) for a TEI provider, externalGuardrail.promptTemplate for a chat provider (the error message names the missing field); externalGuardrail.timeoutMs/maxOutputTokens/maxInputChars not positive; proxy not found.
401Missing or invalid token.
403The token's account lacks permission on the project.

cURL Example​

curl -X POST \
"https://demo.apinizer.com/apiops/projects/MyProject/apiProxies/MyAiProxy/policies/kb-groundedness-check/" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"operationMetadata": {
"targetScope": "ALL",
"targetPipeline": "RESPONSE",
"deploy": true,
"deployTargetEnvironmentNameList": ["production"],
"order": 1
},
"policy": {
"type": "ai-groundedness-guard",
"description": "Flags ungrounded support-chat answers",
"active": true,
"action": "FLAG",
"externalGuardrail": {
"type": "llm-judge",
"llmProviderName": "openai-judge",
"promptTemplate": "Task: Determine whether the ASSISTANT RESPONSE is fully grounded in the RETRIEVED CONTEXT...\n\n<<<PROMPT>>>"
}
}
}'

Update Policy​

Endpoint​

PUT /apiops/projects/{projectName}/apiProxies/{apiProxyName}/policies/{policyName}/

Request​

The body is the same shape as Add Policy. The update replaces the policy, so send the full externalGuardrail block, not just the field you are changing.

Full JSON Body Example — Switching to BLOCK​
{
"operationMetadata": {
"targetScope": "ALL",
"targetPipeline": "RESPONSE",
"deploy": true,
"deployTargetEnvironmentNameList": ["production"],
"order": 1
},
"policy": {
"type": "ai-groundedness-guard",
"active": true,
"action": "BLOCK",
"failMode": "FAIL_CLOSED",
"externalGuardrail": {
"type": "llm-judge",
"llmProviderName": "openai-judge",
"modelId": "gpt-4o-mini",
"promptTemplate": "Task: Determine whether the ASSISTANT RESPONSE is fully grounded in the RETRIEVED CONTEXT...\n\n<<<PROMPT>>>",
"timeoutMs": 8000
}
}
}

Response​

Success Response (200 OK)​

{
"status": "SUCCESS",
"deploymentResult": {
"success": true,
"deploymentResults": [
{
"environmentName": "production",
"success": true,
"message": "Deployment successful"
}
]
}
}

cURL Example​

curl -X PUT \
"https://demo.apinizer.com/apiops/projects/MyProject/apiProxies/MyAiProxy/policies/kb-groundedness-check/" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"operationMetadata": {
"targetScope": "ALL",
"targetPipeline": "RESPONSE",
"deploy": true,
"deployTargetEnvironmentNameList": ["production"]
},
"policy": {
"type": "ai-groundedness-guard",
"active": true,
"action": "BLOCK",
"externalGuardrail": {
"type": "llm-judge",
"llmProviderName": "openai-judge",
"promptTemplate": "Task: Determine whether the ASSISTANT RESPONSE is fully grounded in the RETRIEVED CONTEXT...\n\n<<<PROMPT>>>"
}
}
}'

Delete Policy​

Endpoint​

DELETE /apiops/projects/{projectName}/apiProxies/{apiProxyName}/policies/{policyName}/

Request​

Headers​

HeaderValue
AuthorizationBearer {token}

Path Parameters​

ParameterTypeRequiredDescription
projectNamestringYesProject name
apiProxyNamestringYesAPI Proxy name
policyNamestringYesPolicy name

Response​

Success Response (200 OK)​

{
"status": "SUCCESS"
}

cURL Example​

curl -X DELETE \
"https://demo.apinizer.com/apiops/projects/MyProject/apiProxies/MyAiProxy/policies/kb-groundedness-check/" \
-H "Authorization: Bearer YOUR_TOKEN"

Notes and Warnings​

  • A missing or unresolvable judge follows failMode. If the judge configuration cannot be resolved at runtime and the request has injected RAG context, FAIL_CLOSED (default) blocks the response. FAIL_OPEN forwards the response unchecked and records a skip attribute — check your traffic reports for it. SHADOW never blocks.
  • A judge call failure defaults to blocking the response. failMode=FAIL_CLOSED (default) rejects the response when the judge itself errors or times out, so a hallucination can never slip through just because the judge was unreachable. Set FAIL_OPEN only if letting an unverified response through is preferable to blocking it for your use case — the platform still logs a warning either way.
  • The context comes from the RAG Injection policy of the same request. The RAG Injection policy publishes the context it injected, for every injectionMode. A <CONTEXT> text that the client writes itself is not used. A request without injected context is not evaluated, and the policy does not block or flag it.
  • Streaming responses are not checked. This policy only evaluates non-streaming (unary) responses.
  • Run PII Mask and DLP Guard before this policy in the response pipeline. The judge call is itself an egress of response content to an external LLM provider, so it must only ever see already-masked/scrubbed text.
  • A blank judge prompt template is rejected outright, not defaulted to a generic safety judge — a generic safety-taxonomy prompt does not answer a groundedness question and would produce meaningless verdicts.