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 lets you bias Theo’s routing engine for your domain. The SDK exposes three namespaces:
  • theo.routingPreferences — shared preference objects (one rule set, many keys).
  • theo.routingRules — per-key rule editing without an explicit preference object.
  • theo.keys.getRoutingPreference / setRoutingPreference — bind a shared preference to a key.
See the Routing Studio guide for the full ContractIQ walkthrough and the API reference for the underlying HTTP shapes.

Shared preferences

List

const prefs = await theo.routingPreferences.list();

Get

const pref = await theo.routingPreferences.get(prefId);

Create

scope: "team" requires an active org and the team-config permission. Idempotent via the Idempotency-Key header.
const pref = await theo.routingPreferences.create({
  name: "ContractIQ Legal",
  description: "Contract terms get the analytical engine.",
  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" },
  ],
  confidence_floor_overrides: { think: 0.65 },
});

Update

await theo.routingPreferences.update(pref.id, { enabled: false });
Sending rules or examples replaces the entire collection.

Delete

Cascade-removes every key binding pointing at the preference.
await theo.routingPreferences.delete(pref.id);

Test (replay against the routing engine)

Replays a prompt twice — once without the preference (baseline) and once applied — so you can render a side-by-side diff.
const diff = await theo.routingPreferences.test(pref.id, {
  prompt: "Compare these two warranty sections",
  mode: "auto",
});
console.log(diff.baseline.resolved_mode);        // "fast"
console.log(diff.with_preference.resolved_mode); // "think"
Both blobs match the routing telemetry your callers receive on a real completion.

Per-key routing rules

The preference-free shortcut: the server find-or-creates a hidden per-key preference under the hood and ensures the binding row points at it. Reach for this when you’re tuning a single key.

Get

const snap = await theo.routingRules.get(keyId);
console.log(snap.active);          // true if these rules drive completions today
console.log(snap.shared_binding);  // populated when the key is bound to a shared preference

Effective

The snapshot that will actually drive completions for the key right now, plus a source enum so you can render inherited context.
const eff = await theo.routingRules.effective(keyId);
console.log(eff.source);          // "key" | "org_default" | "user_default" | "none"
console.log(eff.preference_name); // "This key's rules" | "ACME Legal Default" | null

Set

Replaces the per-key rules / examples / overrides and ensures the binding points at the hidden row.
await theo.routingRules.set(keyId, {
  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" }],
});

Clear

Drops the binding (the key falls back to org default → user default → none) and deletes the hidden preference row. Existing bindings to a shared preference are left alone.
await theo.routingRules.clear(keyId);

Key bindings (shared preferences)

Bind an existing shared preference to a key, or clear the binding.
// Read the current binding
const { preference_id, inherits_default } =
  await theo.keys.getRoutingPreference(keyId);

// Bind a preference
await theo.keys.setRoutingPreference(keyId, pref.id);

// Clear the binding (key falls back to org default → user default → none)
await theo.keys.setRoutingPreference(keyId, null);

Types

The SDK exports first-class types for every shape — switch and if blocks narrow without as any:
  • RoutingPreferenceSummary — full preference row.
  • RoutingRuleInput — single keyword/regex rule (pattern, target_mode, optional target_engine, confidence, optional description).
  • RoutingExampleInput — few-shot example (prompt, expected_mode, optional expected_engine).
  • RoutingPreferenceTestResult{ baseline, with_preference } envelope returned by test.
  • KeyRoutingRulesSnapshot — per-key snapshot with active + shared_binding.
  • KeyEffectiveRouting — effective routing snapshot with the source enum.

Telemetry

When a preference contributes to a completion’s routing decision, the meta and done SSE events surface a customer_preference block:
{
  "routing": {
    "reason": "customer_preference",
    "explanation": "Routing Studio rule matched: \"clause\".",
    "customer_preference": {
      "id": "1f4f2c1a-22ce-4b07-9c0b-9c4f4b9b1d2e",
      "name": "ContractIQ Legal",
      "rule_matched": "r_a4b8c01x9y",
      "examples_injected": 2
    }
  }
}
Point your SDK at the meta event’s routing field to render the same affordance in your product.