FifeRouter

Quickstart & reference

Docs

The API is OpenAI-shaped, so any OpenAI client works. Point the base URL at api.fiferouter.com/v1, send "model": "auto", and let the concept decide.

Quickstart

curl https://api.fiferouter.com/v1/chat/completions \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer $FIFEROUTER_API_KEY' \
  -d '{
    "model": "auto",
    "messages": [{"role":"user","content":"verify this refund path"}]
  }'

The response is OpenAI-shaped, with one difference that matters: the model field names the model that actually served the request, not the one you asked for. A router that echoes the request back cannot be audited.

With the OpenAI SDK

from openai import OpenAI

client = OpenAI(
    base_url="https://api.fiferouter.com/v1",
    api_key=os.environ["FIFEROUTER_API_KEY"],
)

resp = client.chat.completions.create(
    model="auto",
    messages=[{"role": "user", "content": "summarise this thread"}],
    extra_headers={"x-fife-session": "conv-42"},
)
print(resp.model)  # the model that actually ran

Routing headers

Routing signals travel as headers, so the request body stays a plain OpenAI payload.

HeaderEffect
x-fife-conceptName the concept explicitly. Always beats classification — you know what you asked for.
x-fife-sessionKeep one conversation on one model across turns, while it still passes every filter.
x-fife-criticalValue-bearing work. Pins residency to in_infra, whatever the ranking prefers.
x-fife-residencyRequire a residency without claiming criticality.

What comes back

HeaderMeaning
x-fife-modelThe model that served it.
x-fife-conceptThe concept it was routed as.
x-fife-rungWhich classifier rung decided: explicit, cache, embedding, llm or default.
x-fife-attemptsHow many models were tried. Above 1 means the fallback chain fired.

Explaining a request

POST /v1/explain returns the routing decision without calling a provider. It spends no tokens and consumes no credit, so you can run it in CI over a corpus of real phrasing before shipping a concept or policy change.

curl https://api.fiferouter.com/v1/explain \
  -H 'content-type: application/json' \
  -d '{"text":"can this retry double-charge the customer?","critical":true}'

{
  "concept": "moneypath.verify",
  "confidence": 1.0,
  "classifier_rung": "embedding",
  "objective": "quality",
  "eliminated": { "vendor-frontier": "residency" },
  "chain": ["infra-large"],
  "chosen": "infra-large"
}

A request no model can serve is explained, not refused: 200 with chosen: null and a refused block naming the constraint. Explaining is not serving, so it does not adopt serving's 422.

Errors

Refusals are typed and never silent. A spend cap in particular is never a quiet downgrade to something cheaper: the caller cannot tell the difference between "we saved you money" and "your results got worse", so the router refuses instead.

StatusTypeMeans
402spend_cap_exceededThe configured cap would be exceeded. Top up, or raise the cap.
422no_compliant_candidateEvery candidate was eliminated by a hard filter. The message names which.
502all_candidates_failedThe whole fallback chain was exhausted. Each attempt is named.

Discovery

EndpointReturns
GET /v1/modelsThe pool, with each model's residency, tier, context window and capabilities.
GET /v1/conceptsThe catalogue, so you can name a concept explicitly.
GET /healthzLiveness. Answers without touching the pool.
GET /readyzReadiness: the four artifacts loaded and agreeing with each other.

Self-hosting

The router is open source and runs as a single container. The four artifacts are config files, validated against each other at startup — a dangling model id is a failed deploy, not a 3am outage.

docker run -p 8080:8080 \
  -e ANTHROPIC_API_KEY=... \
  -v $PWD/config:/app/config:ro \
  ghcr.io/tech-res-group/fiferouter:latest

Source, and the product graph behind it →