Gateway
How harness traffic reaches models: public URL, auth, model aliases and upstreams.
Generated from schemas/gateway.schema.json; do not edit. Nested fields use dotted paths, [] marks array items and .* map values.
| Field | Type | Required | Default | Allowed values | Constraints | Description |
|---|---|---|---|---|---|---|
apiVersion |
string | yes | const halos.dev/v1 | Document version. | ||
auth |
object | yes | How clients obtain a credential for the auth gateway. | |||
auth.helperCommand |
string | Command that prints a short-lived token (Claude apiKeyHelper, Codex env_key source, …). | ||||
auth.identityHeader |
string | Header the auth gateway sets with the verified user id. | ||||
auth.ttlSeconds |
integer | minimum 0 | Token lifetime in seconds. | |||
baseURL |
string | yes | format uri | What clients are pointed at (Kong’s public listener). | ||
budgets |
array of object | Spend caps enforced by halo-proxy, with halo-server holding the counters (ADR-0017). | ||||
budgets[] |
object | One budget: a limit in USD and/or tokens per scope key over a window. | ||||
budgets[].action |
string | warn, enforce | When exhausted: warn (response header and metric; the request passes) or enforce (HTTP 429 with Retry-After at the window reset). Default warn. | |||
budgets[].alertAt |
array of number | Soft thresholds as fractions of the limit (default [0.8]): a header and a metric when crossed. | ||||
budgets[].alertAt[] |
number | |||||
budgets[].groups |
array of string | Scope group: the groups that each get a counter (required). Other scopes: count only callers in one of these groups. | ||||
budgets[].groups[] |
string | |||||
budgets[].limitTokens |
integer | minimum 0 | Token cap for the window (input + output + cache reads and writes). | |||
budgets[].limitUSD |
number | minimum 0 | Spend cap in USD for the window, priced from pricing. | |||
budgets[].name |
string | yes | pattern ^[a-z0-9][a-z0-9._-]{0,62}$ | Unique budget name. | ||
budgets[].period |
string | pattern ^([0-9]+(.[0-9]+)?(h|m|s))+$ | Rolling window length as a Go duration between 1h and 2160h, e.g. 24h. Rolling only. | |||
budgets[].rings |
array of string | Count only callers routed to these rings (default every ring). | ||||
budgets[].rings[] |
string | |||||
budgets[].scope |
string | yes | user, group, ring, org | Counter key: user (per verified subject), group (per listed group), ring (per ring) or org (one shared counter). | ||
budgets[].window |
string | yes | day, week, month, rolling | day, week (from Monday) or month: calendar windows in UTC. rolling: the last period. | ||
dlp |
object | Data-loss prevention and prompt-injection defense on model calls (ADR-0033). halo-proxy and halo-kong scan request bodies; halo-proxy also scans streamed responses for echoed secrets (monitor only). | ||||
dlp.injection |
object | Prompt-injection scoring of tool results and documents entering the model. Model content is never modified. | ||||
dlp.injection.action |
string | off, monitor, block | monitor (count and audit, default), block (refuse at or above threshold) or off. | |||
dlp.injection.threshold |
integer | minimum 1; maximum 20 | Score at which a tool result counts as an injection (default 4: two independent signals). | |||
dlp.maxScanBytes |
integer | minimum 0; maximum 6.7108864e+07 | Bytes of one request body scanned (default 4 MiB); the rest passes unscanned and is counted as truncated. | |||
dlp.rules |
array of object | Per ring and org unit action overrides; the first rule whose rings and units match the caller wins. | ||||
dlp.rules[] |
object | |||||
dlp.rules[].injection |
string | off, monitor, block | Injection action for matching callers. | |||
dlp.rules[].rings |
array of string | Callers routed to these rings (default any). | ||||
dlp.rules[].rings[] |
string | |||||
dlp.rules[].secrets |
string | off, monitor, redact, block | Secret action for matching callers. | |||
dlp.rules[].units |
array of string | Callers in these org units or their descendants (default any). | ||||
dlp.rules[].units[] |
string | |||||
dlp.scanResponses |
boolean | Scan streamed responses for echoed secrets (monitor only, halo-proxy). Default true. | ||||
dlp.secrets |
object | Outbound secret detection on request content (user text, tool results, files). | ||||
dlp.secrets.action |
string | off, monitor, redact, block | monitor (count and audit, default), redact (replace each secret with [REDACTED:<detector>:<hash8>]), block (refuse with HTTP 400) or off. | |||
dlp.secrets.disable |
array of string | Built-in detectors to turn off. | ||||
dlp.secrets.disable[] |
string | anthropic-api-key, aws-access-key-id, gcp-service-account, generic-secret, github-token, gitlab-token, jwt, openai-api-key, private-key, slack-token, slack-webhook, stripe-key | ||||
dlp.secrets.patterns |
array of object | Org detectors (RE2). The whole match is the secret, or the first capture group when there is one. | ||||
dlp.secrets.patterns[] |
object | |||||
dlp.secrets.patterns[].id |
string | yes | pattern ^[a-z0-9][a-z0-9._-]{0,62}$ | Stable detector id, used in metrics, audit and redaction markers. | ||
dlp.secrets.patterns[].regex |
string | yes | minLength 1; maxLength 1024 | RE2 regular expression (no backreferences or lookaround). | ||
engine |
string | halo-proxy, kong, external | Data plane enforcing this policy (default halo-proxy). external is a gateway Halos does not run (your own API gateway): clients are rendered with each alias’s provider model id. Multi-target routes (weights, failover) run only in halo-proxy; halo-kong and external use each route’s first target. | |||
kind |
string | yes | const Gateway | Document kind. | ||
labels |
object | Free-form labels. | ||||
labels.* |
string | |||||
models |
object | yes | Stable alias (what clients request) to upstream target. | |||
models.* |
object | Route for a model alias: either upstream+model, or an ordered/weighted list of targets (not both). | ||||
models.*.model |
string | Provider model id or Bedrock inference profile ARN. | ||||
models.*.targets |
array of object | minItems 1 | Provider targets in routing order. | |||
models.*.targets[] |
object | One provider target. Targets sharing a priority form a tier: weights split traffic within it (sticky per identity+session) and the rest of the tier is the failover order; later tiers are tried only after earlier ones fail (connect error, 5xx or 429, before any response byte). | ||||
models.*.targets[].model |
string | yes | Provider model id, Bedrock inference profile ARN, or Azure deployment name. | |||
models.*.targets[].priority |
integer | minimum 0 | Failover tier, lowest first (default 0). | |||
models.*.targets[].timeoutSeconds |
integer | minimum 0 | Connect plus response-header timeout for this target; streams are not time-limited afterwards. | |||
models.*.targets[].upstream |
string | Name of an entry in gateway.upstreams. Required unless engine is external. | ||||
models.*.targets[].weight |
number | minimum 0 | Relative share of traffic within the priority tier. | |||
models.*.upstream |
string | Name of an entry in gateway.upstreams. Required unless engine is external. | ||||
name |
string | yes | pattern ^[a-z0-9][a-zA-Z0-9._-]*$ | Unique name within its kind. | ||
pricing |
object | USD per million tokens, keyed by provider model id (the model a route target names). Costs gateway usage for budgets; a routed model without a price counts tokens but $0. | ||||
pricing.* |
object | Price of one provider model. | ||||
pricing.*.cacheReadPerMTok |
number | minimum 0 | Prompt-cache reads (default: inputPerMTok). | |||
pricing.*.cacheWritePerMTok |
number | minimum 0 | Prompt-cache writes (default: inputPerMTok). | |||
pricing.*.inputPerMTok |
number | yes | minimum 0 | Uncached input tokens. | ||
pricing.*.outputPerMTok |
number | yes | minimum 0 | Output tokens, including reasoning or thinking tokens. | ||
protocols |
object | Wire protocol per harness name. | ||||
protocols.* |
string | anthropic-messages, bedrock-invoke, openai-responses, gemini | ||||
upstreams |
object | Named backends. | ||||
upstreams.* |
object | A backend. | ||||
upstreams.*.apiVersion |
string | api-version query for kind azure-openai; empty uses the versionless /openai/v1 surface. | ||||
upstreams.*.credential |
object | Where halo-proxy reads the provider key (kinds openai, azure-openai): an environment variable name or a file path, never the secret itself. | ||||
upstreams.*.credential.env |
string | Environment variable on the halo-proxy host. | ||||
upstreams.*.credential.file |
string | Secret file path on the halo-proxy host. | ||||
upstreams.*.credential.scheme |
string | api-key, bearer | Header style: api-key (default for azure-openai) or bearer (default for openai). | |||
upstreams.*.kind |
string | yes | orchestrator, anthropic, bedrock, vertex, openai, azure-openai, gemini | Backend type. vertex: Anthropic models on Google Vertex AI (ADC auth). azure-openai: Azure OpenAI Responses (credential required). | ||
upstreams.*.project |
string | Google Cloud project id (kind vertex). | ||||
upstreams.*.region |
string | pattern ^([a-z]{2}(-[a-z]+)+-[0-9]+|[a-z]+-[a-z]+[0-9]+|global)$ | AWS SigV4 region for kind bedrock (default: parsed from a bedrock-runtime.<region>.amazonaws.com host); Google Cloud region (e.g. us-east5, or global) for kind vertex. | |||
upstreams.*.serves |
array | Kind orchestrator only: the client wires this upstream answers. Validate warns about a harness routed to an orchestrator that does not declare its wire. | ||||
upstreams.*.serves[] |
anthropic-messages, bedrock-invoke, openai-responses, gemini | |||||
upstreams.*.url |
string | format uri | Base URL of the backend (optional for kind vertex: derived from region). |
Constraints
Section titled “Constraints”models.*: exactly one ofmodelortargetsupstreams.*.credential: exactly one ofenvorfile