Skip to main content
Use guardrails to set content policies for requests to the MKA1 API. You can block specific words, detect prompt-injection attempts, or describe your own policy for a model to evaluate. Guardrails check user text before the answering model runs. You can also enable checks on generated text. They apply to Responses API requests, agent runs, Chat Completions, and batch requests when they execute. When a guardrail blocks a request, your application receives a refusal message. A block returns HTTP 200; an evaluation failure can return an error. Read the refusal to explain the block to your user, as shown in Detect a block in code.

How guardrails are applied

Your requests can have an organization-wide policy and a team policy. When both exist, both are enforced. A team policy adds rules on top of the organization-wide policy; it never replaces or weakens it. These policies apply to everyone in the organization or team. X-On-Behalf-Of does not create a separate policy for an end user. Enabled guardrails check request input. To check generated text too, enable output checks on each rule you want to apply. The input check reads enabled input_sources (for example user, retrieval, or tool text; and when available, image and audio text). It does not inspect raw image, audio, or file bytes. Requests using automatic model selection may have an additional guardrail check. See Auto routing. In addition to organization and team policies, your cluster can enforce a cluster default policy beneath them. Organization admins can add rules on top of it, but cannot weaken or remove it.
API keys need read:guardrails to view or test policies and write:guardrails to change them. Tests that include an enabled classifier also require write:responses because they invoke a model. Guardrails still apply to your response requests even if your key cannot view or change the policy.

Guardrail modes

Every guardrail also takes fields outside config:
  • enabled (default true) turns the guardrail on or off without removing it from the policy.
  • check_output (off unless set) additionally applies the guardrail to model output.
  • input_sources (when set) chooses which input sources to check (for example user, retrieval, tool, and when available image and audio). If unset, the default set of sources is checked.
Each mode has a default rejection_message. Set a custom message to explain the restriction and suggest what the user can ask instead. For example, banning secret also matches secrets; matching is not limited to whole words. Prompt-injection and leakage checks use pattern detection, not a comparison against your actual system prompt. If a pattern check cannot run, it does not block the request. For classifiers, you can choose what happens when evaluation fails.

Configure guardrails

PUT /api/v1/llm/guardrails replaces a policy, so include every guardrail you want to keep. Omit team_id or pass null to set the organization-wide policy (organization admin or owner only). Pass a team_id to set that team’s additional policy. With the required scope, team members can manage their own team’s policy; organization admins can manage any team in their organization. Rules that team members must not be able to remove belong in the organization-wide policy.

Before you start

Use an API key with read:guardrails, write:guardrails, and write:responses for the examples below, and a model available to your organization. Try the examples with a test team. Replace <team-id> with its ID and use that team’s API key for test and response requests. Before changing an existing team policy, save a copy from GET /api/v1/llm/guardrails/policies. This lets you restore it when you finish testing. GET /guardrails returns combined organization and team rules, so use the policies endpoint for your backup. This example bans a word on both input and output, with a custom rejection message, and enables input checks for prompt injection and leakage:
To see the combined policy that applies to your requests, call GET /api/v1/llm/guardrails or run mka1 guardrails get. The response also includes any cluster default rules enforced beneath your org/team policies. To view organization and team policies separately, use GET /api/v1/llm/guardrails/policies. The response also includes the cluster default rules enforced beneath them. Organization admins see all policies in their organization; other callers see the organization-wide policy and their own team’s policy. When you finish testing, restore the saved team policy with PUT, or delete the team’s policy with DELETE /api/v1/llm/guardrails?team_id=<team-id> if none existed before. Deleting a team policy leaves organization-wide rules enforced.

Check model output too

Set check_output: true to apply a guardrail to the model’s generated text. For example, an output check can block a banned term that the model includes even though it was absent from the request. It also covers Responses API output that would otherwise finish as incomplete, such as when a token limit is reached. A block returns a completed response containing a refusal. Generated tokens still count toward usage.
Live streaming text can reach your client before the output check runs. If you must withhold unchecked output, buffer it until the terminal event or use a non-streaming request. See Streaming.
You are charged for tokens generated before an output check blocks the response. See Usage and billing.

Classify content using your own policy

Use mode: "classifier" when your policy depends on meaning rather than specific words. You supply config.prompt to describe which content to allow and which to block. The classifier evaluates the content against your policy and returns allow or block. You do not need prompt placeholders or JSON formatting instructions. For example, keep a support assistant focused on orders, products, and returns.
Use a key with write:guardrails to configure the policy. PUT replaces the team’s policy, so include any existing rules you want to keep. To apply the policy across your organization, omit team_id and use an organization admin or owner account.

Choose a classifier model

Replace <classifier-model-id> with the exact ID of a model available to your organization. Choose a non-reasoning model that supports structured JSON output through the Responses API. auto is not supported for the classifier. You can use a different model to answer requests. The classifier has a 1,024-token output limit for its decision. Its context window must fit your policy prompt, the full content being checked, and that output allowance. Content is not shortened automatically. If a request exceeds the context window, shorten it or select a larger-context classifier; retrying the same request will not help. The MKA1 API checks model availability and suitability when you save an enabled classifier. An unsuitable model returns HTTP 400 with code: "invalid_classifier_model" and a field such as param: "guardrails[0].config.model". Your existing policy stays unchanged. Model access is checked again when the classifier runs. If the model becomes unavailable, the API follows your failure setting rather than switching to another model.

Test an allow or block decision

Use the configured team’s API key with both read:guardrails and write:responses:
An example block result is:
A question such as “My order arrived damaged. Can I get a replacement?” should pass this policy. Test examples that should pass, examples that should be blocked, and ambiguous requests. Refine your prompt if the results do not match your policy. Once saved, the policy applies to your response requests without additional request fields. A classifier block uses the standard refusal response with metadata.guardrail_triggered: "classifier". Set check_output: true outside config if you also want to classify generated text against the same policy.

Choose what happens when evaluation fails

Use fail_closed when requests must pass the classifier before proceeding. Use fail_open when requests should continue if the classifier cannot run. This setting covers unavailable models, revoked model access, rate limits, provider failures, timeouts, refusals from the classifier model, and invalid decisions. An actual block decision always blocks, even with fail_open. Each evaluation can take up to 30 seconds. Your policy prompt must be nonblank and contain no more than 16,000 characters. Requests that exceed the classifier’s context window also follow this failure setting. If the model is removed or becomes inaccessible, a foreground non-streaming request with fail_closed returns HTTP 503:
Other evaluation failures return guardrail_evaluation_failed. For a temporary failure, retry the request. If it persists, ask your organization administrator to check model access, rate limits, and context-window requirements. An evaluation error means the classifier could not finish checking the content. For background Responses requests or streams whose HTTP response has started, inspect the terminal response.failed event or retrieved response’s error.code and error.message. Chat Completions streams surface an error frame. An output evaluation runs after generation, so it cannot recall text already streamed to your client. With fail_open, a test can return passed: true even when a classifier was skipped. Check details.skipped_evaluations to see which checks did not complete:
The failure setting controls classifier evaluations. If the API cannot load your policies, requests currently continue without guardrail checks. Requests also continue when no policy is configured.
Classifier checks add latency and are billed separately, including policy tests and checks that block a request. See Usage and billing.

Test your policy

Use POST /api/v1/llm/guardrails/test to check sample content against your organization and team policies (and any enforced cluster default rules) without generating an answer. It evaluates enabled input rules, including those that also have output checking enabled. Pass source to test content as a specific input source (user, retrieval, tool, and when available image and audio). If omitted, the API treats it as user content. Use the API key for the team you want to test; this endpoint does not accept team_id. The key needs read:guardrails. If an enabled classifier applies, it also needs write:responses and must pass the spend-budget check. Classifier tests invoke the configured model and incur usage charges. Note: cluster default classifier guardrails are not run by this test endpoint (they are still enforced on real requests). When present, the test result reports how many were skipped in details.cluster_classifiers_not_tested.
The result reports whether the content passed, and on a failure it names the guardrail and the message a real request would get back:
details can explain why the content was blocked: label and reason for classifier, matched_word for ban_words, and a score or reason when provided by prompt_injection and leakage detection. When you pass source, it can also be reported back as details.source.

What a blocked response looks like

For a foreground Responses API request, a guardrail block returns HTTP 200 with status: "completed" and error: null. For a background request, inspect the terminal response after polling or streaming; the initial response can still be queued or in_progress. Check these fields to identify a block:
  • metadata.guardrail_triggered holds the mode of the guardrail that matched (classifier, ban_words, prompt_injection, or leakage).
  • output contains a single assistant message whose only content part has type: "refusal", carrying the guardrail’s rejection message.
  • usage is all zeros for an input block because the answering model did not run. Classifier usage is metered separately.
Here is a blocked response to the request from the examples above, showing the relevant fields:
Do not rely only on output_text to display a response. It is empty or absent when a request is blocked. Read the refusal content part so you can show the user an explanation.

Detect a block in code

Read the refusal content part to show the caller a rejection message, and use metadata.guardrail_triggered to identify a platform guardrail block. The SDK clients below use the same credentials as the configuration example. For the OpenAI SDK, initialize openai with your MKA1 API key and baseURL: 'https://apigw.mka1.com/api/v1/llm/', as shown in Generate a response.
The refusal content part also appears when a model declines a request on its own, without a guardrail. Read refusal parts before falling back to output_text; use metadata.guardrail_triggered to label a platform guardrail block. There is no top-level response.refusal field in the current MKA1 API.

Streaming

For a foreground input block, the API sends response.created and response.completed, with the blocked response. Background streams can include earlier status events. No response.output_text.delta events arrive, and there are no per-token refusal events. Handle the final response event to display the refusal. These examples wait for that event before displaying any text, so unchecked output stays hidden. response.completed, response.incomplete, and response.failed each mark the end of a response.
If you display text as it arrives, an output check may block it after the user has already seen part of the answer. Replace the displayed text with the refusal from response.completed. For stored responses, the retrieved response also contains the refusal.

Usage and billing

  • Input blocks prevent the answering model from running, so its response reports zero tokens.
  • Classifier checks are billed separately from the answering model. Their usage is not included in the main response’s usage. This applies to policy tests and checks that block a request.
  • Output checks run after generation. If they block a response, you are still charged for the generated tokens. Enabling classifier output checks adds another model call.
Pattern-based rules run before classifiers. If a pattern rule blocks the content, no classifier call is made. Each classifier call counts toward the configured model’s rate limits. If you use that same model to answer requests, both calls share its quota. Allow for this additional usage when choosing your model and rate limits. Policy tests with an enabled classifier return HTTP 403 if a blocking spend limit has been reached, even with fail_open. Tests without an enabled classifier do not make model calls or require a spend-budget check.

Chat Completions requests

For Chat Completions, check finish_reason and the refusal message to identify a block. A blocked request returns HTTP 200 with finish_reason: "content_filter" and the rejection message in message.refusal instead of message.content:
The usage rules match the Responses API: zeros for an input block, real token counts for an output-stage block. On a streamed chat completion, an output-stage block appends a final chunk with finish_reason: "content_filter" and the rejection message in delta.refusal after the text deltas. An input block on a streamed chat completion arrives the same way: a single chunk with the rejection message in delta.refusal and finish_reason: "content_filter", followed by the [DONE] terminator. Cached Chat Completions are checked against your current output policy before they are returned. If blocked, the cached text is withheld, including in streams. If a streamed Chat Completion fails, handle its error frame even if the connection closes normally.

Next steps