Skip to content

feat: add dry-run route trace/explain endpoint #238

Description

@gr3enarr0w

Context

Pi is being moved to use Ferro Gateway as the only model routing plane while retiring SynapseRouter as a runtime router. Pi can already call Ferro through the OpenAI-compatible API, but a Pi-side router UX needs a safe way to ask Ferro why a request would route to a model/provider without actually spending tokens.

Ferro already has routing strategies, request logging, cost metadata, OTel spans, and health checks. This issue is specifically for a client-facing route explanation surface.

Proposal

Add an authenticated dry-run endpoint, for example:

POST /v1/route/trace

Input should accept a chat/completions-shaped request or a reduced route probe:

{
  "model": "qwen3.5:397b-cloud",
  "messages": [{"role": "user", "content": "..."}],
  "stream": false,
  "metadata": {
    "client": "pi-ferro-router"
  }
}

Response should explain the selected target without calling the provider:

{
  "strategy": "conditional",
  "requested_model": "qwen3.5:397b-cloud",
  "selected_target_key": "ollama-cloud",
  "selected_model": "qwen3.5:397b-cloud",
  "candidate_targets": [
    {
      "target_key": "ollama-cloud",
      "matched": true,
      "reason": "model condition matched",
      "healthy": true,
      "circuit_open": false,
      "estimated_cost_usd": null
    }
  ],
  "catalog": {
    "model_found": true,
    "priced": false,
    "context_window": 128000
  }
}

Acceptance Criteria

  • Endpoint performs no upstream model call and consumes no provider quota.
  • Returns selected target/model and ordered candidate explanations.
  • Includes provider health/circuit/retry-relevant state when available.
  • Includes model-catalog pricing/capability match state when available.
  • Emits normal auth, audit, and OTel/request IDs like other admin/client-visible routes.
  • Works for conditional, fallback, cost-optimized, least-latency, and single routing modes.

Non-goals

  • Do not add Pi-specific logic to Ferro.
  • Do not reintroduce SynapseRouter as a routing dependency.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions