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 a string input or user-message text. It does not inspect image, audio, or file contents.
Requests using automatic model selection may have an additional guardrail check. See Auto routing.
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 two fields outside
config:
enabled(defaulttrue) turns the guardrail on or off without removing it from the policy.check_output(off unless set) additionally applies the guardrail to model output.
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 withread: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:
GET /api/v1/llm/guardrails or run mka1 guardrails get.
To view organization and team policies separately, use GET /api/v1/llm/guardrails/policies.
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
Setcheck_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.
You are charged for tokens generated before an output check blocks the response. See Usage and billing.
Classify content using your own policy
Usemode: "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.
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 bothread:guardrails and write:responses:
metadata.guardrail_triggered: "classifier".
Set check_output: true outside config if you also want to classify generated text against the same policy.
Input checks inspect user text, not image, audio, or file contents.
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:
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.
Test your policy
UsePOST /api/v1/llm/guardrails/test to check sample content against your organization and team policies without generating an answer. It evaluates enabled input rules, including those that also have output checking enabled.
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.
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.
What a blocked response looks like
For a foreground Responses API request, a guardrail block returns HTTP 200 withstatus: "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_triggeredholds the mode of the guardrail that matched (classifier,ban_words,prompt_injection, orleakage).outputcontains a single assistant message whose only content part hastype: "refusal", carrying the guardrail’s rejection message.usageis all zeros for an input block because the answering model did not run. Classifier usage is metered separately.
Detect a block in code
Read therefusal 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.
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 sendsresponse.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.
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.
fail_open. Tests without an enabled classifier do not make model calls or require a spend-budget check.
Chat Completions requests
For Chat Completions, checkfinish_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:
finish_reason: "content_filter" and the rejection message in delta.refusal after the text deltas.
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
- Review the Guardrails endpoints in the API reference, including update, delete, and test
- See the authentication deep dive for giving each tenant its own guardrail policy
- See usage auditing for recording guardrail outcomes alongside the rest of your usage events
- See generate a response for the Responses API request workflow