Router & Dispatch

Blocking load balancer with reservation-based scheduling, health monitoring, and async queuing.

The router is a blocking load balancer. Requests wait until a model is free — no skipping, no rejecting, no timeouts from contention. All plugins get served. Models are shared infrastructure.

Synchronous Dispatch

The simplest way to call an LLM. The router selects the best model for the task automatically.

engine.dispatch(messages, task, max_tokens, temperature) → str
Returns the model's response text. Blocks until a model is available and the response is complete.
response = engine.dispatch(
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Analyze this text..."},
    ],
    task="extraction",              # determines which model gets picked
    max_tokens=2048,
    temperature=0.7,
)
print(response)  # model's response text

Reservation-Based Scheduling Rust

The canonical path for model selection. Atomically sweeps expired reservations, checks capacity, scores candidates, and reserves.

Select and Reserve

engine.select_and_reserve(task_desc) → dict | None
Atomic operation: sweep expired, hard-gate at capacity, score, reserve. Returns {"model": "...", "reservation_id": N} or None if no model available.
sel = engine.select_and_reserve({
    "task_class": "extraction",     # extraction|reasoning|synthesis|generation|evaluation
    "min_tier": "small",            # small|medium|large
    "min_context": 4096,
    "thinking": False,
    "execution": "stateless",       # stateless|session|exclusive
    "latency": "medium",            # low|medium|high
    "determinism": False,
    "typical_tokens": 1024,
    "priority": 2,                  # 0=critical, 1=high, 2=normal, 3=bulk
    "plugin_id": "research",
})

if sel:
    print(f"Reserved {sel['model']} (id={sel['reservation_id']})")
else:
    print("No model available")

Task Descriptor Fields

FieldValuesDescription
task_classextraction, reasoning, synthesis, generation, evaluationWhat kind of work
min_tiersmall, medium, largeMinimum model size
min_contextintMinimum context window needed
thinkingboolWhether thinking/chain-of-thought is needed
executionstateless, session, exclusiveExecution semantics
latencylow, medium, highLatency sensitivity
determinismboolWhether deterministic output is needed
typical_tokensintExpected output length
priority0-30=critical, 1=high, 2=normal, 3=bulk
plugin_idstrCalling plugin for fairness tracking

Record Result (preferred release path)

engine.record_result_v2(reservation_id, success, latency_ms) → None
Releases the reservation first (frees capacity), then feeds health metrics. Always use this to complete a request.
engine.record_result_v2(sel["reservation_id"], success=True, latency_ms=250.0)

Release Without Result (fallback)

engine.release_reservation(reservation_id) → None
Idempotent release by ID. Safe to call multiple times or after record_result_v2.

Sweep Expired Reservations

engine.sweep_expired() → int
Cleans leaked reservations. Call periodically (5-10s) or the Rust core calls it opportunistically. Returns count of expired reservations freed.

Health Management

The router tracks model health automatically based on request results.

Health State Transitions

FromToCondition
HealthyDegradedp95 latency > 30s OR error rate > 5%
DegradedQuarantinedError rate > 15% OR 5 consecutive failures
DegradedHealthySuccess rate > 95% over last 20 requests
QuarantinedRecoveringManual mark_model_recovering()
RecoveringHealthySuccess rate > 90% over last 10 requests

Timeouts never disable models. Only billing/auth failures disable immediately. Connection failures need 5 strikes. Timeouts are expected for shared models.

engine.update_model_online(model_key, online) → None
engine.mark_model_recovering(model_key) → None
engine.get_model_health() → list[dict]
Returns per-model health: key, health, success_rate, error_rate, p50_latency, p95_latency, total_calls, total_errors, consecutive_failures.

Async Queue

For bulk work, use the async queue. Tasks are submitted and processed in the background across all available models.

Submit

engine.queue_submit(prompt, task, priority, system_prompt?, max_tokens?) → str
Non-blocking. Returns a task ID immediately.
task_id = engine.queue_submit(
    prompt="Extract beliefs from this document...",
    task="extraction",
    priority=2,                     # 0=critical, 1=high, 2=normal, 3=bulk
    system_prompt="You are a belief extraction engine.",
    max_tokens=4096,
)

Poll Result

engine.queue_result(task_id) → dict
result = engine.queue_result(task_id)
# {
#     "status": "pending" | "running" | "complete" | "error",
#     "response": "...",        # only when complete
#     "latency_ms": 1234,       # only when complete
#     "error": "...",            # only when error
# }

Queue Status

engine.queue_status() → dict
status = engine.queue_status()
# {
#     "depth": 5,               # items waiting
#     "active": 2,              # currently processing
#     "completed": 47,          # total completed
#     "workers": 3,             # background worker count
#     "by_priority": {0: 0, 1: 1, 2: 3, 3: 1},
# }

Model Info

engine.get_model_status() → list[dict]
Returns status for all configured models.
models = engine.get_model_status()
for m in models:
    print(f"{m['name']}: {m['health']} ({m['in_flight']} in-flight)")
    print(f"  {m['tokens_per_second']} tok/s, p95={m['p95_latency']}ms")

Plugin Scoping & Fairness

Control which models a plugin can use and ensure fair access across plugins.

engine.set_plugin_scope(plugin_id, allowed?, preferred?, blocked?) → None
engine.set_plugin_scope(
    "research",
    allowed=["local-*", "cloud-*"],
    preferred=["local-primary"],
    blocked=["small-*"],
)
engine.set_active_plugin_count(count) → None
Updates the plugin count for fairness calculations.

Exclusive Locks & Session Stickiness

For workflows requiring model consistency:

engine.lock_model(model_key) → None
engine.unlock_model(model_key) → None
engine.set_session_model(session_id, model_key) → None
engine.clear_session(session_id) → None

Embeddings

Vector embedding utilities for semantic operations.

engine.embed(text) → list[float]
Returns an embedding vector (384 dimensions for MiniLM).
engine.batch_embed(texts) → list[list[float]]
Batch embedding for efficiency.
engine.cosine_similarity(vector_a, vector_b) → float
Returns similarity score between 0.0 and 1.0.