Azure OpenAI Just Turned OpenClaw's Safety Envelope Into a Refusal Machine

Azure OpenAI Just Turned OpenClaw's Safety Envelope Into a Refusal Machine

Azure OpenAI did not break OpenClaw by rejecting a dangerous request. It broke OpenClaw by rejecting hello. That is the interesting part.

A fresh OpenClaw issue, #79570, reports that the platform’s openai-responses adapter is effectively unusable against Azure OpenAI’s OpenAI-v1 surface. The gateway boots, the credentials validate, the deployment exists, and a trivial user message comes back as the generic refusal: “I’m sorry, but I cannot assist with that request.” More tellingly, the captured session shows usage.totalTokens == 0. The model did not read the prompt and decide to be cautious. Something upstream refused the request before normal inference even began.

The same Azure deployment works when the model entry is switched from api: "openai-responses" to api: "openai-completions". A direct call to Azure’s /openai/v1/responses endpoint with a bare envelope also succeeds, returning HTTP 200, real token usage, and a normal greeting. That narrows the failure to a specific intersection: OpenClaw’s assembled Responses payload shape and Azure’s prompt-stage filtering.

The safety wrapper became the suspicious payload

The likely trigger is OpenClaw’s inbound sender envelope. OpenClaw routes messages from Slack, Telegram, Discord, web chat, and other surfaces where sender identity, channel metadata, and quoted context need to be handled carefully. Its runtime labels inbound context with a trusted system block and emits a fenced user-visible block containing strings like Sender (untrusted metadata):. The implementation pointer in the issue is src/auto-reply/reply/inbound-meta.ts, specifically buildInboundUserContextPrefix paired with buildInboundMetaSystemPrompt.

That design is reasonable in an agent runtime. Metadata from a chat adapter should not be treated as user intent. A Slack display name, Telegram sender field, or quoted message can be attacker-controlled. Naming the boundary explicitly is the right instinct.

But the bug exposes the awkward truth: security semantics written as natural-language prompt text are still prompt text. Azure’s content shield does not necessarily know that OpenClaw’s “untrusted metadata” block is defensive scaffolding. It may see a structured prompt that appears to contain indirect prompt-injection material, role-like context, and fenced metadata being passed into the model. From the filter’s perspective, refusing before token usage may look safer than letting the request through.

That is not Azure being silly, and it is not OpenClaw being careless. It is provider compatibility becoming an instruction-layer security problem.

Why zero-token refusals deserve their own runbook

For operators, the most useful debugging clue is the token count. A normal model refusal consumes input tokens because the model evaluates the request. A zero-token refusal suggests the request was blocked before the model path, by policy, validation, safety shields, or adapter translation. Those are different failure classes and should be monitored differently.

If you run OpenClaw against Azure OpenAI and suddenly every harmless prompt returns the generic refusal, do not spend an afternoon rewriting your assistant persona. First, check the adapter path. Test the same deployment with openai-completions. Then send a minimal direct Responses API call to Azure. If the direct call works and OpenClaw’s Responses call does not, you likely have a payload-shape compatibility issue, not a broken model or bad credential.

The practitioner action is simple: log adapter choice, provider, token usage, refusal text, and request class in health checks. A refusal with totalTokens == 0 should page a different part of your brain than a model-level refusal after reading 3,000 input tokens. One means policy mediation blocked the path. The other means the model participated.

There is also an architecture lesson here for agent platforms. Operational metadata should not be smuggled through visible prompt text unless the model truly needs to reason over it. The Responses API and provider runtimes increasingly have structured fields, metadata channels, and message item types. If sender metadata is for auditing, routing, policy, or delivery, keep it in runtime metadata. If some portion must be exposed to the model, minimize it, make it stable, and test it across provider safety filters.

This matters more in enterprise environments because Azure OpenAI is often chosen precisely for governance, policy enforcement, and compliance. The same controls that make it attractive to large organizations can reject prompt shapes that pass elsewhere. Agent vendors need to treat those controls as part of the deployment target, not an implementation detail behind an OpenAI-compatible URL.

The right fix is not obviously “turn the envelope off everywhere.” The issue itself suggests more careful options: a senderEnvelope: "off" escape hatch for trusted single-tenant deployments, moving sender data into API metadata or non-text items, or documenting Azure compatibility and recommending openai-completions until a safer Responses path lands. ClawSweeper’s review reportedly kept the issue open while asking for live Azure proof before changing prompt-injection metadata handling. That caution is appropriate. Removing a security wrapper because one provider dislikes it is how platforms trade one bug for another.

The editorial take: this is a small issue with a large category warning. Agent security is no longer only about defending against malicious users. It is also about expressing runtime boundaries in forms that model providers, enterprise filters, and orchestration layers can all interpret consistently. “Trusted” and “untrusted” are not magic words. They are a contract. Right now, too much of that contract is being carried as prose.

Sources: OpenClaw issue #79570, Microsoft Azure OpenAI content filtering docs, OpenAI Responses API docs