Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.hitheo.ai/llms.txt

Use this file to discover all available pages before exploring further.

Routing Studio is Theo’s per-customer routing layer. You describe how your users phrase requests, and Theo’s routing engine biases the classifier toward the right mode — without you ever having to manage a separate “preference” object. Rules live directly on each API key: open the key, add the words that should fire a rule, pick the destination, and save. A routing rule maps a list of keywords (or, for power users, a raw regex) to a Theo engine. Rules run BEFORE Theo’s global intent classifier so your domain wins on ambiguity. The routing engine layers them on top of its global cascade and never lets them escape Theo’s safety locks (stealth, agentic) or leak upstream vendor names into your customers’ surfaces. Alongside rules you can also configure:
  • Few-shot examples — prompt / expected-mode pairs injected into the classifier’s system prompt (up to 8 per request).
  • Confidence-floor overrides — per-mode replacements for Theo’s global 0.85 promotion floor. Lower a floor to make intent promotion easier; raise it to be conservative.
Most teams will only ever edit rules on the keys page. Shared rule sets are a power-user feature for one rule list that needs to span many keys or act as a team default.

Edit rules on a key

Open api.hitheo.ai/dashboard/keys, find the API key you want to tune, and click the Routing pill. The panel inlines everything you need:
  • Inherited context — if no per-key rules are set, the panel tells you whether the key currently inherits the team default, your personal default, or nothing.
  • Rules — one row per rule. Each row has a keyword chip input, a destination combobox, and a Gentle / Balanced / Strict toggle. The empty state offers a few one-click starter templates (Pricing questions, Customer complaints, Legal review, Photo & image requests) and a Blank rule chip for power users.
  • More options — a small caret on each row reveals a note field, a raw regex textarea, an optional Theo engine pin, and a raw confidence slider for fine-grained control.
  • Try a prompt — a compact input appears once you’ve started editing. Type a sample customer prompt and the panel renders a one-line diff (baseline mode → with-rules mode) so you can see exactly what would change before saving.
Click Save changes to write the rules to the key. Click Clear per-key rules to drop them entirely and fall back to inherited defaults.

Advanced: hand-written regex

The chip editor projects keywords down to the same pattern string the API uses internally. To author a rule with a raw ECMAScript regex (lookaheads, anchors, capturing groups), expand the row’s More options caret and edit the pattern textarea. Pasting a regex switches the row to Advanced mode automatically so we never silently rewrite your pattern; loading a key whose pattern doesn’t round-trip through the chip editor opens that row in Advanced mode by default.

ContractIQ — a complete walkthrough

ContractIQ is a fictional legal-tech tool. Their users paste contract clauses and ask Theo to analyze them. Without any rules, “look at this clause” routes to fast (a short reply); with one rule on the key, it routes to think (deep analysis).

1. Set rules on the API key

curl -X PUT https://www.hitheo.ai/api/v1/keys/$KEY_ID/routing-rules \
  -H "Authorization: Bearer $THEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "rules": [
      {
        "pattern": "\\\\b(clause|provision|indemnity|warranty)\\\\b",
        "target_mode": "think",
        "confidence": 0.92,
        "description": "Contract terms get the analytical engine."
      }
    ],
    "examples": [
      { "prompt": "Look at this clause", "expected_mode": "think" },
      { "prompt": "Compare these two indemnity sections", "expected_mode": "think" }
    ]
  }'
The response confirms the rules are active on the key:
{
  "key_id": "22222222-2222-4222-8222-222222222222",
  "rules": [
    {
      "id": "r_a4b8c01x9y",
      "pattern": "\\\\b(clause|provision|indemnity|warranty)\\\\b",
      "target_mode": "think",
      "confidence": 0.92,
      "description": "Contract terms get the analytical engine."
    }
  ],
  "examples": [...],
  "active": true,
  "shared_binding": null
}
The active: true field confirms the rules are driving completions on this key right now. To drop the rules and fall back to inherited defaults, send a DELETE to the same endpoint (or call theo.routingRules.clear(keyId) from the SDK).

2. Send a completion

curl -X POST https://www.hitheo.ai/api/v1/completions \
  -H "Authorization: Bearer $THEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "prompt": "Look at this indemnity clause", "mode": "auto", "stream": true }'
The SSE meta event now carries a customer_preference field that confirms a rule fired:
{
  "routing": {
    "requested_mode": "auto",
    "resolved_mode": "think",
    "promoted": true,
    "reason": "customer_preference",
    "explanation": "Routing Studio rule matched: \"indemnity clause\".",
    "customer_preference": {
      "rule_matched": "r_a4b8c01x9y",
      "examples_injected": 2
    }
  }
}
The playground renders a green chip next to the routing receipt’s promotion reason whenever your rules drove the decision.

3. Test changes before they ship

Use the test endpoint to replay a fixture prompt with vs. without the preference:
curl -X POST "https://www.hitheo.ai/api/v1/routing-preferences/$PREF_ID/test" \
  -H "Authorization: Bearer $THEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "prompt": "Compare these two warranty sections", "mode": "auto" }'
Both blobs match the same routing telemetry shape your production callers receive — the diff is a precise, deterministic preview of what your tuning does.

Testing an unsaved draft

The dashboard test bench replays the draft you’re currently editing — it never makes you save first. If you’re building your own UI on top of the API, hit the no-id POST /api/v1/routing-preferences/test route with the full draft body. Same response shape as the by-id route; nothing is persisted.
curl -X POST https://www.hitheo.ai/api/v1/routing-preferences/test \
  -H "Authorization: Bearer $THEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Look at this clause",
    "mode": "auto",
    "draft": {
      "name": "ContractIQ Legal (draft)",
      "rules": [
        { "pattern": "\\b(clause|provision)\\b", "target_mode": "think", "confidence": 0.92 }
      ],
      "examples": []
    }
  }'

Order of precedence

Routing Studio sits inside Theo’s broader routing engine. The full cascade, first match wins:
  1. Agentic locks (insurance_*, data_extraction) — never promoted.
  2. Attachments → vision — image attachments on a non-media caller route to vision.
  3. Skill exclusive override — a skill with intensity: 100 and a modelPreference wins.
  4. Routing Studio rule — your rules fire here.
  5. Intent classifier — runs with your few-shot examples injected and uses your per-mode confidence-floor overrides.
  6. Stealth family preservation — promotions from a stealth_* caller stay inside the stealth family.
  7. Conversation hint — falls back to the prior-turn artifact type when the caller used auto.
  8. Requested mode — default.
Your rules cannot escape agentic family locks (legal/healthcare/data-extraction modes) and cannot escape stealth-family isolation. A rule that targets a stealth-incompatible mode for a stealth caller is silently remapped to the stealth equivalent.

Confidence-floor overrides

The classifier won’t promote a caller’s mode unless its confidence is ≥ 0.85 (PROMOTION_CONFIDENCE_FLOOR). For specialist domains where the classifier is often correct at lower confidence, lower the floor:
{
  "name": "Legal Default",
  "confidence_floor_overrides": {
    "think": 0.65
  }
}
For domains where false promotions are expensive, raise it:
{
  "name": "Cost-Sensitive",
  "confidence_floor_overrides": {
    "image": 0.95,
    "video": 0.95
  }
}
All values are clamped server-side to [0.5, 0.99] — neither end of the range can disable the floor entirely.

Brand-safety contract

Every customer-authored field — name, description, rule pattern, rule description, example prompt — is scanned for upstream vendor names (Claude, OpenAI, Anthropic, Gemini, fal.ai, etc.) and rejected at validation time. Theo’s surfaces always read as Theo. Your customers never see the underlying model providers. The same scan runs on Routing Studio’s outputs — the customer_preference block your callers receive is guaranteed to be free of vendor names.

Limits

LimitValue
Rules per preference50
Examples per preference30
Examples injected into classifier8 (highest-priority first)
Pattern length512 chars
Example prompt length1024 chars
Confidence range[0.5, 0.99] (clamped)
Test prompt length4096 chars
Cache TTL5 minutes (Redis)

Team vs. personal scope

Pass scope: "team" on create to scope the preference to your active org. Team preferences become candidates for org defaults; team admins (with the team config permission) can manage them. Without a team binding, a key inherits its scope’s default → the user’s personal default → no preference.
await theo.routingPreferences.create({
  name: "ACME Legal Default",
  scope: "team",
  is_default: true,
  rules: [...],
});
Setting is_default: true on a second team preference returns 409 conflict — at most one default per scope.

Common patterns

  • Domain vocabulary biasing. Use rules for hard keywords (“policy”, “claim”, “rune”), use examples for phrasings (“draft me a response to this complaint” → think).
  • Cost containment. Raise floors on image/video for personal keys; let team keys keep the defaults.
  • Speed bias. Lower the fast floor and add examples like { prompt: "thanks!", expected_mode: "fast" } so short replies don’t escalate to think.

Per-key vs. shared sets — when to use which

If you’re tuning one or two keys, edit rules directly on the keys page. The dashboard hides everything but the rule editor itself — no “preference” to create, no binding to wire up. Reach for shared sets when:
  • You want one rule list to span many API keys (e.g. every key on your team uses the same legal vocabulary).
  • You want a team default that new keys inherit automatically.
  • You’re scripting bulk changes and would rather author rules in source control once than mirror them across keys.
Under the hood the per-key endpoint and the shared-set endpoints write to the same routing_preferences table; the only thing that differs is whether the row is named for a specific key (hidden from the shared list) or carries a customer-chosen name.

Next steps