"cost-optimized" routing strategy never looks at cost (or latency)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 38/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- go
- Domain
- api, backend, performance
Research direction
Start with internal/routing/costopt.go and compare its Select implementation with internal/routing/latency.go and the sibling LeastLatencyStrategy. Read internal/routing/target.go and internal/modeldb/litellm.go, then run go build ./... to understand the existing data flow. Done means cost-optimized routing uses real per-token pricing while respecting the existing latency/SLO signal instead of only static priority.
Written by the indexing model from the issue text.
Description
What happened?
The cost-optimized routing strategy doesn't use cost data at all, despite the name and the
documented behavior ("Route to the cheapest provider that meets your SLO" — README.md's routing
strategies table).
CostOptimizedStrategy.Select() (internal/routing/costopt.go) only looks at each target's
static, manually-configured Priority int (internal/routing/target.go) and round-robins within
whichever targets share the lowest one. It never touches internal/modeldb, which already parses
real per-model, per-provider pricing (InputPerToken/OutputPerToken, from a LiteLLM-sourced
pricing table) — that data exists and is used elsewhere, just not here.
It also never touches the SLO half of the claim: every Strategy.Select(targets, tracker *LatencyTracker) implementation receives a live EWMA-latency tracker (internal/routing/ latency.go), and costopt.go takes it as _ and discards it. The sibling LeastLatencyStrategy
in the same package shows the intended usage pattern (tracker.Get(providerID)) that
cost-optimized never calls.
Net effect: default_strategy: cost-optimized in the gateway config produces a priority-tier
round robin with zero live cost or latency signal — not "cheapest provider that meets your SLO."
Steps to reproduce
- Configure two targets for the same model with different real per-token pricing but an inverted
priority(cheaper provider given the higher priority number):routing: default_strategy: cost-optimized targets: my-model: - provider: expensive-provider # e.g. a $30/1M-token model priority: 0 - provider: cheap-provider # e.g. a $0.50/1M-token model priority: 1 - Send requests for
my-modelthrough the gateway. - Every request routes to
expensive-provider(priority 0), regardless of the real price
difference.
I verified this directly rather than just from reading the source: calling
CostOptimizedStrategy.Select() 200 times against exactly this two-target setup sent all 200
requests to the priority: 0 target and 0 to the other, regardless of which one is actually
cheaper — the function has no path by which a real price difference could change the outcome.
Expected behavior
The strategy should select among healthy targets using their actual per-token cost (via
modeldb's pricing data, estimated against the request's token count) subject to a latency/SLO
constraint (via the existing LatencyTracker) — not a static, manually-set priority number.
Deployment
Self-hosted (Docker Compose)
Version
dev (2026-09-29)
Environment
N/A — verified directly against internal/routing: built the module clean (go build ./..., Go 1.27.1) and ran CostOptimizedStrategy.Select() 200 times against a {expensive: priority 0, cheap: priority 1} target set; 200/200 selections went to expensive, 0/200 to cheap, regardless of any cost signal. Also confirmed by reading internal/modeldb/litellm.go that the pricing data costopt.go never touches does exist and is already parsed elsewhere in the binary.
Relevant logs
Checks
- I searched existing issues and didn't find a duplicate
- I redacted any secrets, PII, or customer data from logs/screenshots
- Dominant language
- Python
- Stars
- 2k
- Forks
- 628
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 259
Getting set up
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from future-agi/future-agi
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
future-agi/future-agi#4092 · 1 comment ·
Maintainers usually reply within 1 day
-
accepted backend bug evaluations
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
future-agi/future-agi#4090 ·
Maintainers usually reply within 1 day
-
Trace view hides LLM output when the input renders as a conversationPossibly taken A pull request linked to this issue is open or already merged. Openaccepted
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
future-agi/future-agi#3770 ·
Maintainers usually reply within 1 day
-
[Bug] : The "Ask AI" Button Cover the "Security" text in the footer Section in the right cornerMay be free again @prabhtheone claimed this 12 days ago, and no pull request is open. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
future-agi/future-agi#3690 · 2 comments ·
Maintainers usually reply within 1 day
-
Observe onboarding code example still calls gpt-3.5-turbo, which OpenAI shut down on 2026-10-23Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
future-agi/future-agi#3618 · 2 comments ·
Maintainers usually reply within 1 day
All issues in future-agi/future-agi
Similar issues
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 78/100
splunk/security_content#4418 ·
Maintainers usually reply within 1 day
-
[Bug / Enhancement]: Improve teleop_robot CLI with configurable timeout, robust input validation, and clean ROS shutdownPossibly taken @muskan-creates352 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 3 days
-
bug(pipelines): shortcode stripping deletes text between a {{< >}} shortcode and the next {{% %}}Possibly taken @Ashborne-lab claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
kubeflow/docs-agent#293 ·
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Imbad0202/academic-research-skills#1093 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
pierreaubert/gpui-toolkit#114 ·
Maintainers usually reply within 1 day