×
Community Blog Seamless AI Safety: Integrating Qwen3Guard into Higress with Zero Code Changes

Seamless AI Safety: Integrating Qwen3Guard into Higress with Zero Code Changes

This article introduces integrating Qwen3Guard into the Higress gateway via a Wasm plugin for centralized AI content moderation.

By Wang Jianwei (Zhengji)

Generative AI is moving beyond the question of "whether it can be used" toward "how to use it safely at scale."

The Higress project has now integrated Qwen3Guard-Gen as a Wasm plugin. Here is what it does in three points:

  • Zero changes to business applications: No changes to application code or upstream model services; applications continue to use the familiar Chat Completions protocol;
  • Full coverage of inputs, outputs, and streaming: User input is moderated before the request reaches the model, and non-streaming JSON or SSE streaming output is moderated after the model responds;
  • Self-hosted safety model: Qwen3Guard is deployed and scaled independently using the official approach, without relying on any cloud-based content safety service. Risk thresholds and refusal messages are configured centrally at the gateway.

This belongs at the gateway because risks flow in both directions: they may originate in user input or appear in model output. If each application maintains its own moderation SDK, risk thresholds, and refusal logic, safety policies will soon be scattered across multiple code repositories. Every model change or policy upgrade then requires another round of application modifications.

Start with a diagram to understand this integration:

1

This is not a safety demo attached to the side of the gateway and disconnected from traffic. Instead, content extraction, outbound safety calls, risk decisions, streaming buffering, and refusal response shaping are placed in the actual data-plane path traversed by requests and responses. Higress translates model judgments into gateway actions.

01 Qwen3Guard Makes the Judgment; Higress Executes It

According to the official Qwen3Guard repository, official model cards, and technical report, Qwen3Guard is a family of safety moderation models built on Qwen3, trained on over 119 × 10,000 safety-annotated prompts and responses. It comes in three sizes, 0.6B, 4B, and 8B, and follows two technical approaches:

Official Model How It Works Directly Integrated by This Plugin?
Qwen3Guard-Gen Receives complete user input or "input + response" and generates structured safety judgments Yes
Qwen3Guard-Stream Monitors safety token by token using dedicated classification heads and streaming state No

By default, the plugin calls Qwen/Qwen3Guard-Gen-4B, for a straightforward reason: Qwen3Guard-Gen can use vLLM or SGLang to expose an OpenAI-compatible POST /v1/chat/completions endpoint, fitting naturally into existing AI gateway protocols.

Qwen3Guard reports three risk levels:

2

The plugin maps the three official result levels to two gateway policy settings:

riskLevelBar Blocking Scope Policy Meaning
Unsafe, the default Block only Unsafe Controversial is allowed under a permissive policy
Controversial Block Controversial and Unsafe Apply a strict policy to controversial content as well

Qwen3Guard's official safety policy covers categories including violence, non-violent illegal acts, sexual content, personally identifiable information, suicide and self-harm, unethical acts, politically sensitive topics, and copyright infringement. Input moderation also includes Jailbreak detection. The current plugin can parse Safety, Categories, and, in response moderation, Refusal, but the only fields that actually determine whether traffic is allowed are Safety and riskLevelBar. The current version does not yet support configuring different actions by category, and this article does not present that as an existing capability.

The official materials also state support for 119 languages and dialects and report results on English, Chinese, and multilingual safety benchmarks. These describe the Qwen3Guard model's publicly stated capabilities, not a guarantee of production results for any particular business. Production integration still requires evaluation against your own language distribution, real risk samples, and the cost of false positives.

02 How an End-to-End Call Is Protected

The gateway is an unavoidable point on the path between callers and model services. Placing safety controls in Higress lets multiple applications reuse the same moderation integration and thresholds without copying the logic into every application.

The following sequence diagram reflects the actual call order in the current code:

3

Request Side: Moderate First, Then Decide Whether to Call the Original Model

The plugin enables checkRequest by default. Once the request body arrives, it uses maxBodyBytes to set the buffer limit and the default GJSON Path messages.@reverse.0.content to retrieve the last message's content.

After successfully extracting the text, the plugin constructs a request using Qwen3Guard-Gen's official Prompt Moderation format:

{
  "model": "Qwen/Qwen3Guard-Gen-4B",
  "messages": [
    {
      "role": "user",
      "content": "<Pending Input>"
    }
  ],
  "max_tokens": 128
}

When the risk reaches the threshold, the plugin returns a refusal directly without calling the original large language model. Only when the threshold is not reached does it resume the request and continue forwarding it. This both centralizes safety enforcement and prevents blocked requests from consuming inference resources on the original model.

Response Side: Assess the Question and Answer Together

The plugin also enables checkResponse by default. For non-streaming responses with HTTP 200, it buffers the complete JSON, extracts the response through choices[0].message.content, and submits it using the official Response Moderation structure:

{
  "model": "Qwen/Qwen3Guard-Gen-4B",
  "messages": [
    {
      "role": "user",
      "content": "<Original User Input>"
    },
    {
      "role": "assistant",
      "content": "<Model Response>"
    }
  ],
  "max_tokens": 128
}

As long as the user text is successfully retrieved during the request phase, response moderation preserves the conversational relationship between the "question + answer." If request text extraction fails, the plugin does not invent context; it moderates only the assistant response. Response checking handles only HTTP 200; other status codes are passed through directly. When response checking is enabled, the plugin also removes Accept-Encoding from the request to prevent compressed responses from making direct text extraction impossible.

03 How SSE Streaming Responses Are Moderated

AI conversations commonly use streaming output. The current plugin recognizes Content-Type: text/event-stream, parses SSE event boundaries and data: payloads, and collects newly added text through choices[0].delta.content.

4

The plugin maintains two states:

  • The complete accumulated response: Every check submits all text accumulated up to that point for moderation;
  • New text since the previous check: The next check is triggered when it reaches streamBufferChars.

By default, a check is triggered for every 1000 new Unicode characters, counted as UTF-8 runes rather than bytes. A smaller window means more frequent checks and less content awaiting moderation, but also more Qwen3Guard calls and repeated computation. A larger window reduces the number of calls, but keeps more content buffered before each check. The specific value must be determined through testing with real traffic, time to first token, and inference resources.

Once a risk is detected, the plugin can only discard data that has not yet been released and append a refusal SSE. Status codes and earlier chunks already sent to the client cannot be retracted, so denyCode has no effect when blocking a streaming response.

This point bears repeating:

The current implementation is "gateway-side segmented buffering of SSE, with repeated calls to Qwen3Guard-Gen to moderate accumulated text," not Qwen3Guard-Stream's native token-by-token classification.

The official technical report notes that repeatedly processing accumulated text with the Gen model creates redundant computation, whereas the Stream model uses dedicated classification heads and streaming state to avoid reprocessing historical tokens. These must not be conflated as the same performance capability.

04 Four Service Discovery Options, with Independent Scaling of Model Services

The Qwen3Guard inference service is not embedded in the gateway process. The plugin builds Envoy clusters for outbound calls through the Higress Wasm Go SDK and currently supports four values for serviceSource:

5

serviceSource Required Information Code Behavior
k8s serviceName, servicePort; namespace defaults to default Build a Kubernetes service cluster
nacos serviceName, servicePort, namespace Build a Nacos service cluster
ip serviceName, servicePort Build a Static IP cluster
dns serviceName, servicePort, domain Build a DNS cluster

This means Qwen3Guard can be deployed and scaled independently; the gateway depends only on a reachable OpenAI-compatible HTTP service. Note, however, that "the service has started" does not mean "the gateway data plane can reach it." DNS, cluster names, Kubernetes namespaces, outbound networking, allowlists, and authentication still need to be verified from the network where Envoy runs.

05 Installation and Enablement: Compile, Mount, and Distribute Configuration

Users must compile and mount Higress's open-source Wasm plugins themselves; the project does not provide a prebuilt qwen3guard plugin image. The process has three steps: Compile the Wasm artifact → Make the artifact accessible to the data plane → Distribute configuration through WasmPlugin.

6

Step 1: Compile the Wasm Artifact

The simplest option is to compile locally, producing main.wasm:

cd plugins/wasm-go
PLUGIN_NAME=qwen3guard make local-build
# Produce:plugins/wasm-go/extensions/qwen3guard/main.wasm

The equivalent manual commands are:

cd plugins/wasm-go/extensions/qwen3guard
go test ./...
GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o main.wasm .

To pin down the build environment, use the container build provided by the repository, which produces plugin.wasm:

cd plugins/wasm-go
PLUGIN_NAME=qwen3guard make build
# Produce:plugins/wasm-go/extensions/qwen3guard/plugin.wasm

For production, build your own OCI image and push it to your own registry:

cd plugins/wasm-go
PLUGIN_NAME=qwen3guard \
REGISTRY=<your-registry>/ \
PLUGIN_VERSION=1.0.0 \
make build-push

Note that REGISTRY must end with /; the final image address is ${REGISTRY}${PLUGIN_NAME}:${PLUGIN_VERSION}. If PLUGIN_VERSION is not specified, the tag falls back to "build-time-commit," which makes rollback and canary deployment harder. Specify it explicitly in production.

Step 2: Make the Artifact Accessible to the Data Plane

Choose one of two approaches to suit your scenario:

Approach url Format Applicable Scenarios Prerequisites
File mount file:///opt/plugins/wasm-go/extensions/qwen3guard/plugin.wasm Local development and self-managed testing Enable global.volumeWasmPlugins=true during Helm installation and place the artifact at the corresponding path in the gateway container
OCI image oci://<your-registry>/qwen3guard:1.0.0 Production deployment Run make build-push first and ensure the data plane can pull from that registry

The repository's make install-dev-wasmplugin uses the file-mount approach: it sets the Helm variable global.volumeWasmPlugins=true and mounts the locally compiled artifact into the gateway container, making it suitable for rapid iteration during development.

Step 3: Distribute Configuration Through WasmPlugin

Enable globally:

apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
  name: qwen3guard
  namespace: higress-system
spec:
  phase: UNSPECIFIED_PHASE
  priority: 300
  url: oci://<your-registry>/qwen3guard:1.0.0
  defaultConfig:
    serviceSource: k8s
    serviceName: qwen3guard
    servicePort: 8000
    namespace: ai-security
    requestPath: /v1/chat/completions
    model: Qwen/Qwen3Guard-Gen-4B
    timeoutMs: 3000
    checkRequest: true
    checkResponse: true
    riskLevelBar: Unsafe

To apply the plugin only to specific AI routes, disable the default configuration and use matchRules instead, so that non-AI traffic is not buffered and moderated as well:

spec:
  phase: UNSPECIFIED_PHASE
  priority: 300
  url: oci://<your-registry>/qwen3guard:1.0.0
  defaultConfigDisable: true
  matchRules:
    - configDisable: false
      ingress:
        - default/my-ai-route
      config:
        serviceSource: k8s
        serviceName: qwen3guard
        servicePort: 8000
        namespace: ai-security
        riskLevelBar: Unsafe

Execution Phase and Priority: Ordering the Plugin Alongside ai-proxy

phase and priority are determined by the WasmPlugin resource, not declared in the plugin code itself, so they must be specified explicitly in the CR; do not rely on defaults.

The rule is simple: phases are ordered first; within the same phase, a higher priority value means earlier execution. The repository's e2e tests include a comment that relies on this rule: custom-response uses priority: 200 to ensure it runs before basic-auth at priority: 100.

For reference, existing AI plugins use the following values:

Plugin Phase Priority
ai-proxy Default phase 100
ai-statistics Default phase 200
ai-security-guard Default phase 300

We therefore recommend configuring qwen3guard with the default phase + priority: 300, maintaining the same relative order as similar safety plugins. This setting addresses content extraction on both sides:

  • Request side: qwen3guard runs before ai-proxy and sees the original OpenAI-format request body sent by the application, so the default path messages.@reverse.0.content matches directly;
  • Response side: Envoy's response path traverses filters in reverse order. qwen3guard runs after ai-proxy and sees a response already normalized to the OpenAI format, so the default paths choices[0].message.content and choices[0].delta.content also match directly.

If you change the relative order—for example, by having qwen3guard process requests after ai-proxy—you must also adjust the three GJSON Paths to match the message structure actually visible at that layer.

Complete Configuration Fields

serviceSource: k8s
serviceName: qwen3guard
servicePort: 8000
namespace: ai-security

requestPath: /v1/chat/completions
apiKey: EMPTY
model: Qwen/Qwen3Guard-Gen-4B
timeoutMs: 3000

checkRequest: true
checkResponse: true

requestContentJsonPath: messages.@reverse.0.content
responseContentJsonPath: choices.0.message.content
streamingResponseContentJsonPath: choices.0.delta.content
streamBufferChars: 1000

riskLevelBar: Unsafe
denyCode: 200
denyMessage: Sorry, I cannot answer your question
maxBodyBytes: 10485760

A few points to note: the three fields whose names contain JsonPath actually use GJSON Path syntax; do not add a $ prefix. apiKey should contain only the raw value; the plugin automatically adds the Bearer prefix. In the current implementation, an unconfigured key still uses the default value EMPTY and sends Authorization: Bearer EMPTY; omitting the Authorization request header entirely is not yet supported.

In addition, the plugin artifact exports Proxy-Wasm ABI 0.2.100, so a Higress data-plane image supporting that ABI is required. A standard Envoy build supporting only other ABI versions cannot load it.

06 Deploy the Safety Service and Verify the Request Path

Start Qwen3Guard-Gen with vLLM

The official model card provides the following OpenAI-compatible deployment method:

pip install "vllm>=0.9.0"

vllm serve Qwen/Qwen3Guard-Gen-4B \
  --port 8000 \
  --max-model-len 32768

First verify the safety service directly, rather than attributing every issue to the gateway from the outset:

curl -sS http://127.0.0.1:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "Qwen/Qwen3Guard-Gen-4B",
    "messages": [
      {
        "role": "user",
        "content": "Please introduce Hangzhou West Lake."
      }
    ],
    "max_tokens": 128
  }'

The officially defined generated content uses a structure similar to the following:

Safety: Safe
Categories: None

If the service is actually deployed in Kubernetes, a container, or on another machine, 127.0.0.1:8000 refers only to the host running the current command. It does not establish that the Higress gateway can reach the service.

Verify Safe Input

curl -i 'http://<YOUR_GATEWAY>/v1/chat/completions' \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "your-upstream-model",
    "messages": [
      {
        "role": "user",
        "content": "Please introduce Hangzhou West Lake."
      }
    ],
    "stream": false
  }'

Expected request path:

Client
  → Higress extracts user input
  → Qwen3Guard returns below threshold
  → Request proceeds to base LLM
  → Response re-audited
  → Returns original model result

This article does not assume what content the original model will return. What the code confirms is that the plugin continues forwarding when the threshold is not reached.

Verify Input Blocking

Send the same request using a risk sample that complies with your organization's safety testing standards. If Qwen3Guard returns Safety: Unsafe and the threshold is Unsafe, the original large language model is not called, and the client receives a Chat Completions-style refusal generated by the plugin:

{
  "object": "chat.completion",
  "model": "from-security-guard",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "很抱歉,我无法回答您的问题"
      },
      "finish_reason": "stop"
    }
  ]
}

The actual response also includes dynamic id, created, usage, and logprobs fields. The default denyCode is 200, so clients cannot identify refusals solely through HTTP error codes.

Verify SSE Streaming Blocking

curl -N 'http://<YOUR_GATEWAY>/v1/chat/completions' \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "your-upstream-model",
    "messages": [
      {
        "role": "user",
        "content": "<Streaming audit samples compliant with testing specifications
>"
      }
    ],
    "stream": true
  }'

When risk is detected in streaming output, the plugin appends a refusal in the following form:

data: {"object":"chat.completion.chunk","choices":[{"delta":{"role":"assistant","content":"Sorry, I cannot answer your question"}}]}

data: {"object":"chat.completion.chunk","choices":[{"delta":{},"finish_reason":"stop"}]}

data: [DONE]

Only the key fields are shown above for readability; actual events also include dynamic id, created, model, index, and logprobs fields.

Optional Practice: Connect to Qwen3Guard Outside the Cluster Through DNS

If the safety service is not in the same Kubernetes cluster as Higress, you can use serviceSource: dns. The current SDK generates an Envoy cluster name in this format:

outbound|<servicePort>||<serviceName>.dns

For example, if the logical service name is qwen3guard-api, the corresponding ServiceEntry host should be qwen3guard-api.dns. Note that serviceName must not include another .dns suffix, or the cluster name will end in .dns.dns.

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: qwen3guard-api
  namespace: higress-system
spec:
  hosts:
    - qwen3guard-api.dns
  ports:
    - name: http
      number: 80
      protocol: HTTP
  resolution: DNS
  endpoints:
    - address: qwen3guard.example.com
      ports:
        http: 80

On the plugin side, change the settings to serviceSource: dns, serviceName: qwen3guard-api, servicePort: 80, and domain: qwen3guard.example.com. Both objects must be correct: ServiceEntry ensures that Envoy has the target cluster, while the plugin configuration selects the cluster of the same name and sets the actual HTTP Host. A domain resolving on a development machine does not prove that it can also be resolved and accessed from the network where the gateway Pod runs.

Acceptance Criteria That Do Not Guess Model Results

The safety model's judgment of a specific sample must be based on its actual response; this article does not predict which label a particular sentence will receive. Use a reviewed test set or a controllable Qwen3Guard response stub in a test environment to verify gateway logic against "model return value → plugin action":

Request Type Qwen3Guard Condition Plugin Configuration Expected Action
Non-streaming request Safety: Controversial riskLevelBar: Unsafe The request proceeds to the original model
Non-streaming request Safety: Controversial riskLevelBar: Controversial The original model is not called; a non-streaming refusal is returned
Non-streaming request Safety: Unsafe Any valid threshold The original model is not called; a non-streaming refusal is returned
Non-streaming response Safety: Unsafe checkResponse: true The original response is replaced with a non-streaming refusal
SSE response Moderation of accumulated text returns Unsafe checkResponse: true Discard unreleased data and append refusal SSE events and [DONE]
Non-streaming or SSE The safety service times out or returns a status other than 200 Currently fail-open Log a warning and allow traffic through

Three further boundary cases deserve separate coverage: when Safety is an unknown string, parsing should fail and the plugin should fail open, rather than guessing a risk result from an unknown label; when the accumulated stream exceeds maxBodyBytes, the buffer should be released and processing should switch to passthrough; when the upstream returns a status other than 200, output moderation should be skipped and traffic passed through directly. See the plugin README for the full list of test cases.

During acceptance testing, observe the client response, whether the original model receives the request, the number of Qwen3Guard calls, and Wasm warning logs together. A client response of 200 alone does not prove the request went through the original model, because the default refusal status code is also 200.

Parameter Tuning: Understand the Effects First, Then Decide Through Load Testing

The code provides defaults but does not claim that they suit every business. The table below lists the direct engineering effects of changes to each key parameter. Final values should be determined jointly by actual response lengths, concurrency, safety-service latency, and risk tolerance:

Parameter Current Default Effect of Decreasing or Disabling Effect of Increasing
timeoutMs 2000 Fail-open occurs sooner, leaving a shorter time window for the safety service Tolerates slower inference, but requests or streaming releases wait longer
streamBufferChars 1000 More frequent moderation and more repeated inference over accumulated text Fewer checks, but more text buffered before each check
maxBodyBytes 10485760 Streaming passthrough starts earlier, making full moderation of very long requests or responses harder Allows longer content while increasing the potential buffer size per request
checkRequest true Disabling stops user-input blocking, but request context may still be read for output moderation Boolean field; "increasing" does not apply
checkResponse true Disabling stops buffering or checking the original model's response Boolean field; "increasing" does not apply
riskLevelBar Unsafe Changing to Controversial applies a stricter policy Only the two settings Unsafe and Controversial are supported
denyCode 200 Can be changed to another positive-integer status code agreed upon by the application; applies only to request blocking and non-streaming response blocking Has no effect after SSE has already sent the status code
denyMessage Default refusal message in Chinese Can be replaced with the application's own safety message Changes only the returned wording, not the risk judgment

The recommended tuning order is to first verify content paths and network connectivity, then confirm the threshold policy, test streamBufferChars and maxBodyBytes against real length distributions, and finally adjust timeoutMs in line with availability targets. Changing all parameters at once from the outset makes it hard to identify the responsible layer when unexpected passthrough or latency occurs.

07 Pre-Production Checks: Verify Each Layer from Networking to Policy

Check the four layers sequentially—"safety service → outbound gateway calls → plugin policy → application protocol"—rather than trying to diagnose every issue with the final business request from the outset.

7

  • The safety service itself: The model name matches the actual deployment; /v1/chat/completions returns HTTP 200, choices[0].message.content contains a parsable Safety: field, and both Prompt and Response messages structures can be handled.
  • Envoy-to-safety-service connectivity: serviceSource, serviceName, and servicePort match the actual service; the namespace or DNS domain is correct; and reachability is verified from the gateway's network, not the development machine. If the target service has an IP allowlist, add the gateway's actual outbound IP. Receiving 401 or 403 at least establishes connectivity; for connection timeouts, check networking and allowlists first.
  • Plugin extraction and policy: The three GJSON Paths can extract input, non-streaming responses, and incremental SSE text, respectively; riskLevelBar matches the application's required strictness; checkRequest and checkResponse have not been disabled accidentally; and timeoutMs, streamBufferChars, and maxBodyBytes have been evaluated against real traffic.
  • Client protocol behavior: Existing Chat Completions clients can parse non-streaming refusals; SSE refusals contain a terminating chunk and [DONE]; and clients can identify safety responses through refusal content or model: from-security-guard. Do not rely on HTTP status codes other than 200 to identify blocking, because the default denyCode is 200.

Common Issues at a Glance

Symptom Possible Cause Consistent with the Current Implementation Check First
All requests quickly reach the original model Fail-open after outbound dispatch failure, or failure to extract request text Wasm warning logs, GJSON Path, Envoy cluster
The plugin's outbound call returns 503 The target cluster does not exist or the backend is unreachable Cluster name, ServiceEntry, Service, endpoint
Qwen3Guard returns 401 apiKey is missing or incorrect, or includes a duplicate Bearer Configure only the raw key and check server-side authentication
SSE data is never released to the client The character window has not been reached, or the outbound safety call is still in progress streamBufferChars, Qwen3Guard latency, plugin logs
Controversial is not blocked The threshold is still the default Unsafe Set riskLevelBar to Controversial and retest
HTTP 200 is returned, but the response is a refusal The default denyCode is 200 Check the response model and assistant content
Standalone Envoy cannot load the plugin The data plane does not support the Proxy-Wasm ABI required by the plugin Use a data-plane image matching the current Higress version

For more failure scenarios—such as unmoderated non-streaming responses, moderation stopping after SSE becomes too long, or test routes not receiving request-body callbacks—see the FAQ section of the plugin README.

Safety configuration may contain apiKey. Do not commit real keys to the repository. The current README also warns that the underlying HTTP wrapper may print outbound headers at certain log levels. In production, configure log redaction or keep the relevant components' log level at warn to prevent Authorization information from entering logs.

08 fail-open: Protect Availability While Monitoring the Risk Window

The safety service may time out, become unreachable, or return an unexpected format. The current plugin chooses fail-open: it logs a warning and allows the current request or response through, preventing a Qwen3Guard failure from directly blocking all AI applications.

8

The following situations trigger fail-open:

Scenario Current Action
Network connection failure or exceeding timeoutMs Log and allow traffic through
Qwen3Guard returns a status other than 200 Log and allow traffic through
Unexpected JSON, empty choices, or missing Safety Log and allow traffic through
The GJSON Path extracts no content Skip the corresponding moderation check
Accumulated streaming content exceeds maxBodyBytes Release the buffer and switch subsequent processing to passthrough

The default maxBodyBytes is 10 MiB. fail-open reduces the safety service's impact on application availability, but no blocking occurs during the failure window. Production must therefore monitor Qwen3Guard availability, call latency, responses other than 200, and plugin warning logs. The current version cannot be described as already satisfying compliance scenarios that require mandatory fail-close.

Conclusion: Turn Model Safety Capabilities into Gateway Enforcement

Qwen3Guard provides a publicly available, deployable safety judgment capability: three risk levels, prompt and response moderation, structured results, multilingual coverage, and the Gen and Stream technical approaches. The Higress Qwen3Guard Wasm plugin handles the other half: extracting content from real OpenAI-compatible traffic, calling Qwen3Guard-Gen, mapping results to gateway actions, and handling protocol details in non-streaming and SSE streaming responses.

The result is not a moderation function exclusive to one application, but a reusable safety path:

User Input
  → Gateway Pre-audit
  → Base LLM
  → Gateway Output Audit
  → Safe Response or Protocol-compliant Refusal

It does not require applications to change protocols, duplicate safety logic in every application, or repackage Qwen3Guard-Gen's capabilities as Qwen3Guard-Stream. It connects model judgments, business policies, and traffic enforcement, bringing AI safety into the gateway's main request path.

References

0 1 0
Share on

You may also like

Comments