Hadrian is experimental alpha software. Do not use in production.
Hadrian
Features

Data Sovereignty

Control where AI inference runs with data residency, compliance metadata, and API key enforcement

Hadrian tracks where each provider processes data and can enforce geographic and compliance constraints per API key — ensuring regulated workloads stay within approved boundaries.

Overview

Sovereignty metadata flows through three layers:

  1. Provider-level defaults — set once, inherited by all models from that provider
  2. Model-level overrides — override specific fields for individual models
  3. API key requirements — enforce constraints at request time, rejecting models that don't comply

This lets you configure a provider's general posture (e.g., "Anthropic is US-based, SOC 2 certified") while overriding individual models that differ (e.g., a model served from EU infrastructure).

Provider Configuration

Add a sovereignty section to any provider in hadrian.toml:

[providers.anthropic]
type = "anthropic"
api_key = "${ANTHROPIC_API_KEY}"

[providers.anthropic.sovereignty]
hq_country = "US"
inference_countries = ["US"]
certifications = ["soc2", "hipaa-baa", "gdpr"]
trains_on_data = false
data_retention = "30d"
license = "proprietary"

Fields

FieldTypeDescription
hq_countrystringISO 3166-1 alpha-2 country code of provider headquarters
inference_countriesstring[]Countries where model inference runs
certificationsstring[]Compliance certifications (see below)
on_premboolWhether this runs on your own infrastructure
trains_on_databoolWhether the provider trains on customer data
data_retentionstringData retention policy ("none", "30d", "90d", "1y", "indefinite")
licensestringModel license ("proprietary", "apache-2.0", "mit", etc.)
notesstringFree-form notes for additional context

Well-Known Certifications

Use lowercase identifiers for certifications:

CertificationDescription
gdprEU General Data Protection Regulation
hipaaUS Health Insurance Portability Act
hipaa-baaHIPAA Business Associate Agreement
soc2SOC 2 Type I
soc2-type2SOC 2 Type II
iso27001ISO 27001 Information Security
fedrampUS FedRAMP (Moderate)
fedramp-highUS FedRAMP High
pci-dssPayment Card Industry DSS
c5German BSI C5
ismapJapan ISMAP
ccpaCalifornia Consumer Privacy Act
dpaData Processing Agreement

Model-Level Overrides

Override specific sovereignty fields for individual models. Model values take precedence over provider defaults — Some wins over None, and a non-empty list wins over the provider's list:

[providers.anthropic.sovereignty]
hq_country = "US"
inference_countries = ["US"]
certifications = ["soc2", "hipaa-baa"]

# This model is served from EU infrastructure
[providers.anthropic.models."claude-sonnet-4-20250514".sovereignty]
inference_countries = ["DE", "FR"]
certifications = ["soc2", "hipaa-baa", "gdpr", "c5"]

In this example, claude-sonnet-4-20250514 inherits hq_country = "US" from the provider but uses its own inference_countries and certifications.

Enforcement

Sovereignty requirements are enforced at request time. They can be set in two places:

  1. API key requirements — stored on the key, enforced on every request made with that key
  2. Per-request requirements — passed as a Hadrian extension field on individual requests

When both are present, they are merged using the most restrictive combination: allowed lists are intersected, required lists are unioned, and boolean flags are OR'd.

API Key Requirements

Restrict which models an API key can access:

{
  "name": "eu-only-key",
  "sovereignty_requirements": {
    "allowed_inference_countries": ["DE", "FR", "NL", "IE"],
    "required_certifications": ["gdpr"],
    "blocked_hq_countries": ["CN", "RU"]
  }
}

Per-Request Requirements

Pass sovereignty_requirements as a Hadrian extension field on /v1/chat/completions, /v1/responses, or /v1/completions:

{
  "model": "anthropic/claude-sonnet-4-20250514",
  "messages": [{ "role": "user", "content": "Hello" }],
  "sovereignty_requirements": {
    "allowed_inference_countries": ["DE"],
    "required_certifications": ["gdpr", "c5"]
  }
}

If the resolved model doesn't satisfy the requirements, the request is rejected with a 403 sovereignty_violation error.

Merge Behavior

When an API key has sovereignty_requirements and a request also includes them, the two are merged:

Field typeMerge strategyExample
Allowed listsIntersectionKey allows [DE, FR], request allows [FR, NL][FR]
Required listsUnionKey requires [soc2], request requires [gdpr][soc2, gdpr]
Blocked listsUnionKey blocks [CN], request blocks [RU][CN, RU]
Boolean requiresOREither source requiring truetrue

Requirement Fields

FieldTypeDescription
allowed_inference_countriesstring[]Only allow models with inference in these countries
require_on_premboolOnly allow on-premises providers
required_certificationsstring[]Provider must have all of these certifications
require_open_weightsboolOnly allow open-weight models
blocked_hq_countriesstring[]Block providers headquartered in these countries
allowed_licensesstring[]Only allow models with these licenses

All requirement fields are optional. Only set the constraints you need — unset fields impose no restriction.

Dynamic Providers

User-added providers (via the admin API or self-service) also support sovereignty metadata:

POST /admin/v1/providers
Content-Type: application/json

{
  "name": "eu-llm",
  "type": "open_ai",
  "base_url": "https://eu-llm.example.com/v1",
  "api_key": "sk-...",
  "sovereignty": {
    "hq_country": "DE",
    "inference_countries": ["DE"],
    "certifications": ["gdpr", "c5", "iso27001"],
    "on_prem": true,
    "trains_on_data": false,
    "data_retention": "none"
  }
}

This metadata is stored in the database alongside the provider configuration and appears in the model picker and /v1/models responses.

Model Picker

The Studio UI model picker displays sovereignty metadata and supports filtering:

  • Country filter — dropdown filters models by inference country, populated from all available models' metadata
  • On-Prem filter — chip filter shows only on-premises models
  • Details panel — click the info icon on any model to see its full sovereignty metadata including HQ country, inference locations, certifications, data retention, and license

/v1/models Response

Sovereignty metadata appears on each model in the standard models list:

{
  "id": "anthropic/claude-sonnet-4-20250514",
  "object": "model",
  "sovereignty": {
    "hq_country": "US",
    "inference_countries": ["DE", "FR"],
    "certifications": ["soc2", "hipaa-baa", "gdpr", "c5"],
    "trains_on_data": false,
    "data_retention": "30d",
    "license": "proprietary"
  }
}

The sovereignty field is only present when at least one sovereignty field is set on the provider or model.

Custom Metadata Fields

Beyond the built-in fields, define your own sovereignty metadata fields. Custom fields are defined globally in the config and then set per-provider or per-model.

Define Fields

Add a top-level [sovereignty] section to hadrian.toml:

[[sovereignty.custom_fields]]
key = "data_residency"
title = "Data Residency"
description = "Where customer data is physically stored"

[[sovereignty.custom_fields]]
key = "audit_frequency"
title = "Audit Frequency"
description = "How often security audits are conducted"

[[sovereignty.custom_fields]]
key = "encryption_standard"
title = "Encryption Standard"
description = "Encryption standard used for data at rest"

Set Values

Set custom field values on providers and models using sovereignty.custom:

[providers.eu-llm.sovereignty]
hq_country = "DE"
inference_countries = ["DE"]

[providers.eu-llm.sovereignty.custom]
data_residency = "EU (Frankfurt)"
audit_frequency = "Quarterly"
encryption_standard = "AES-256"

# Model-level override
[providers.eu-llm.models."llama-3.1-70b".sovereignty.custom]
data_residency = "EU (Paris)"

Model custom values override provider custom values for the same key. Provider values are inherited for keys the model doesn't set.

Display

Custom fields appear in the model picker details panel alongside the built-in sovereignty fields. The title from the field definition is used as the label — if no definition matches a key, the raw key is shown.

Custom field values are also included in the /v1/models response:

{
  "sovereignty": {
    "hq_country": "DE",
    "inference_countries": ["DE"],
    "custom": {
      "data_residency": "EU (Frankfurt)",
      "audit_frequency": "Quarterly",
      "encryption_standard": "AES-256"
    }
  }
}

Complete Example

A multi-provider setup with sovereignty enforcement for a European regulated deployment:

[providers.anthropic]
type = "anthropic"
api_key = "${ANTHROPIC_API_KEY}"

[providers.anthropic.sovereignty]
hq_country = "US"
inference_countries = ["US"]
certifications = ["soc2", "hipaa-baa"]
trains_on_data = false
data_retention = "30d"
license = "proprietary"

[providers.eu-llm]
type = "open_ai"
base_url = "https://eu-inference.example.com/v1"
api_key = "${EU_LLM_API_KEY}"

[providers.eu-llm.sovereignty]
hq_country = "DE"
inference_countries = ["DE"]
certifications = ["gdpr", "c5", "iso27001", "soc2"]
on_prem = true
trains_on_data = false
data_retention = "none"

[providers.self-hosted]
type = "open_ai"
base_url = "http://vllm.internal:8000/v1"

[providers.self-hosted.sovereignty]
inference_countries = ["DE"]
on_prem = true
trains_on_data = false
data_retention = "none"
license = "apache-2.0"

Create an API key that only allows EU-based, GDPR-compliant models:

curl -X POST http://localhost:8080/admin/v1/api-keys \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -d '{
    "name": "eu-regulated-workload",
    "sovereignty_requirements": {
      "allowed_inference_countries": ["DE", "FR", "NL", "IE"],
      "required_certifications": ["gdpr"],
      "blocked_hq_countries": ["CN", "RU"]
    }
  }'

With this key, requests to anthropic/claude-sonnet-4-20250514 (US inference) would be rejected, while eu-llm/* and self-hosted/* models would work.

Next Steps

On this page