Data Routing Policies: Controlling Which Providers See Your Data
Keeptrusts controls which providers see your data by filtering provider targets before routing based on declared data_policy metadata. If a provider cannot meet your zero-retention, no-training, retention-window, or local-processing requirements, the gateway removes that target from consideration or blocks the request entirely.
Use this page when
- You need to guarantee that only specific providers can process regulated or sensitive traffic.
- You want provider failover without accidentally sending a restricted request to the wrong vendor.
- You are trying to separate resilience decisions from data-handling decisions instead of mixing them in application code.
Primary audience
- Primary: Technical Engineers
- Secondary: Technical Leaders, compliance owners
The problem
Multi-provider routing is useful right up until the first sensitive workload is involved. The same failover setup that helps with resilience can also send a restricted prompt to a provider that should never have received it. If routing is based only on latency, cost, or fallback order, governance is happening too late.
Many teams try to solve this in application code with conditional logic such as “send healthcare prompts to provider A” or “avoid provider B for European traffic.” That approach does not scale. The rules end up scattered across services, and every new provider integration becomes a policy rewrite.
The other failure mode is documentation drift. One engineer believes a provider is zero-retention. Another knows that only one endpoint is zero-retention. A third assumes training opt-out and zero-data-retention mean the same thing. Without a single declared metadata layer, those assumptions are hard to review and easy to get wrong.
Finally, failover can hide the mistake. A request may succeed technically because a fallback provider answered it, but the successful answer may still be a governance failure if the target was not allowed to handle that class of data.
The solution
Keeptrusts splits the decision in two.
Routing decides among available providers. data-routing-policy decides which providers are even eligible before routing starts. That is the key architectural point.
The policy does not inspect prompt text itself. Instead, it evaluates each providers.targets[] entry against the operator-declared data_policy object. Those declarations can describe whether the target supports zero-data-retention, training opt-out, retention-day limits, in-memory-only processing, tokenized inputs, internet egress, or local-only processing.
That gives you a reviewable contract.
- Provider metadata describes what a target claims.
data-routing-policydescribes what the request requires.- Normal routing strategies such as ordered routing or fallback only run on the filtered set.
If no provider remains after filtering, Keeptrusts can either block with 403 or warn and continue. In a new rollout, warn is useful for discovering metadata gaps. In a production control path, block is usually the correct setting because resilience should not bypass data rules.
Implementation
The documented pattern is to declare data_policy metadata on every provider target, then enable data-routing-policy in the chain.
pack:
name: regulated-routing
version: 1.0.0
enabled: true
providers:
targets:
- id: local-zdr
provider: openai
model: gpt-5.4-mini-mini
secret_key_ref:
env: OPENAI_API_KEY
data_policy:
zero_data_retention: true
training_opt_out: true
retention_days: 0
in_memory_only: true
accepts_tokenized_input: true
allow_internet_egress: false
local_only_processing: true
- id: standard-cloud
provider: openai
model: gpt-5.4-mini
secret_key_ref:
env: OPENAI_API_KEY
data_policy:
zero_data_retention: false
training_opt_out: true
retention_days: 30
allow_internet_egress: true
local_only_processing: false
routing:
strategy: ordered
policies:
chain:
- data-routing-policy
- audit-logger
policy:
data-routing-policy:
require_zero_data_retention: true
require_no_training: true
max_retention_days: 0
require_in_memory_only: true
allow_internet_egress: false
local_only_processing: true
on_no_compliant_provider: block
log_provider_selection: true
audit-logger: {}
Validate the contract before you run it:
kt policy lint --file policy-config.yaml
kt gateway run --policy-config policy-config.yaml --listen 0.0.0.0:41002
This is the practical flow at runtime.
The gateway first evaluates the provider metadata. standard-cloud is excluded because it does not satisfy zero-retention, retention-days, egress, or local-processing requirements. local-zdr remains eligible, so ordered routing continues with the filtered set of one.
If both targets were non-compliant, the result would be a 403 with code: no_compliant_provider because on_no_compliant_provider is block.
For an initial rollout, there is a strong case for using warn first and watching the exclusion logs. That lets you confirm that your metadata is complete before you turn the rule into a hard control. Once you trust the metadata, switch to block and treat missing declarations as a configuration defect, not as something the application should guess around.
This policy also works well with other routing features. You can still use ordered routing, fallback, or model groups, but they operate inside the boundaries set by the data policy. That is exactly what you want. Resilience stays available, but only among providers that are allowed to see the data.
Use content policies alongside it when needed. data-routing-policy is about provider eligibility, not prompt inspection. If you need to redact or tokenize sensitive content before provider dispatch, pair it with DLP Filter or PII Detector rather than expecting routing to do content transformation by itself.
Results and impact
The first operational result is fewer accidental routing mistakes. Teams stop relying on tribal knowledge about which vendor is acceptable for which workflow because the rule lives in the gateway config instead of in memory.
The second result is cleaner audits. You can review the declared provider metadata, the active policy requirements, and the resulting target set without reverse-engineering application code. That matters when someone asks why a certain request was blocked or why only one provider was eligible for a workflow.
The third result is safer multi-provider resilience. You still get failover, but failover only happens inside the compliant pool. A degraded provider no longer creates pressure to send sensitive traffic somewhere you never intended.
This also shortens policy review cycles. Security and privacy reviewers can approve one declarative routing contract instead of reviewing routing conditions in every application that talks to the gateway.
Key takeaways
data-routing-policyfilters providers before routing; it is not just a logging feature.- The policy depends on explicit
providers.targets[].data_policymetadata, not on prompt-text guessing. - Use
warnto audit early rollouts andblockwhen the metadata is trusted. - Provider failover should increase resilience inside policy boundaries, not override those boundaries.
- Pair routing controls with content controls when you also need redaction or tokenization.