← Blog

When the model says no

November 7, 2026 · Inside OnePress

This week our error reporting flagged a class of refusals we hadn't accounted for: on historically or politically sensitive topics, the model provider's API answers with a content-policy rejection instead of a completion — even when the request is plainly legitimate. The refusal is the provider's own layer, not ours, and the user sees a raw error body in a language they almost certainly don't read.

Two filters, not one

Every prompt on OnePress goes through our own input screening first — a contractual requirement of our payment processor, and a reasonable one. These requests pass it, correctly: plainly legitimate work is exactly the kind of traffic that should sail through.

The refusal comes from a second filter neither we nor the user controls: the model provider's own platform-level content screening, which inspects traffic on top of the model itself. Requests that touch politically sensitive subject matter sit in territory one jurisdiction's compliance layer treats as unsafe. The same request is completely ordinary work everywhere else.

The useful discovery: the filter isn't in the model

Here is the part that changed our architecture. We sent a similar request of our own — same class of content — to the exact same model weights, but served through a different host: OpenRouter, routed to US inference providers. Same weights, same class of prompt. Full generation, no refusal.

So the refusal never lived in the model. It lives in the serving layer — the compliance wrapper a provider puts around its API. Which means it can be routed around, cleanly and openly, without touching the model at all.

What we changed

  • Every model now exists twice in the picker. The default set routes via OpenRouter to non-mainland-China inference providers; the same four models remain available on their home APIs, labelled (CN), for anyone who prefers them.
  • OpenRouter requests carry an upstream allowlist. We pin requests to named providers and disable fallback — if the pinned list can't serve, the call fails loudly instead of silently landing back on a filtered path.
  • Provider refusals now produce a readable message. A content-policy decline explains itself in plain language and points at the model picker — no more raw error blobs in a language the user doesn't read. Error frames embedded mid-stream, which were previously swallowed and looked like an empty reply, surface properly too.
  • Background tasks moved too. Title and summary generation reads the same conversation content, so it rides the same OpenRouter endpoint.

The honest edges

Two compromises worth naming. First, not every model has a non-filtered path: Qwen's hosted flash tier only exists behind Alibaba's own upstream, so the OpenRouter slot for Qwen runs the open-weight 27B variant instead — a different model, and we label it honestly. Second, pinning means a fully-failed allowlist returns an error rather than degrading to a filtered path. That is a deliberate choice: a visible failure beats an invisible change of venue.

The bigger one is philosophical. For an international product, the default path probably shouldn't inherit any single jurisdiction's editorial line at all — not because the filter is malicious, but because its definition of "sensitive" was written for a different audience. The defaults now assume the user's context, not the provider's.

Reading this and have thoughts?

Spot a mistake, disagree, or want a follow-up? Tell us — a human reads it.

Inside OnePress — the build log

More posts like this, plus the weekly AI digest, straight to your inbox.

Get the build log in your inbox →