Fusion
Send one prompt to several models and a judge.
Fusion sends one prompt to several models at once. A judge model then picks the best answer or writes one answer from all of them. Call POST /v1/chat/completions with the model routerplus/fusion.
Request
curl https://dev2-api.routerplus.com/v1/chat/completions \
-H "Authorization: Bearer $TM_API_KEY" -H "content-type: application/json" \
-d '{
"model": "routerplus/fusion",
"messages": [{ "role": "user", "content": "Explain what a mutex is." }],
"fusion": {
"models": ["claude-sonnet-5-5", "gpt-6-luna", "moonshotai/kimi-k3"],
"judge": "claude-opus-5-5",
"mode": "synthesize",
"max_tokens_each": 1024
}
}'| Field | Rule |
|---|---|
fusion.models | 2 to 5 different model ids. These are the candidates. |
fusion.judge | Optional. The model that judges. The default is the first candidate. |
fusion.mode | "synthesize" (default): the judge writes one answer from the candidates. "judge": the judge picks the best candidate, and you get that answer word for word. |
fusion.max_tokens_each | Optional. The output limit for each candidate. Without it, each candidate gets your max_tokens. |
- Each candidate gets your messages and parameters. Candidates do not stream.
- The judge sees the candidate answers as A, B, C and so on, never the model names.
stream: truestreams the answer. Insynthesizemode the judge's answer streams as the judge writes it. Injudgemode the picked answer streams after the judge picks.
Response
The response is an OpenAI chat completion with model: "routerplus/fusion". usage is the sum over every candidate and the judge. usage.cost is present when the calls report a cost. A streamed response carries usage and fusion on its last chunk before [DONE].
{
"model": "routerplus/fusion",
"choices": [{ "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" }],
"usage": { "prompt_tokens": 1830, "completion_tokens": 892, "total_tokens": 2722, "cost": 0.0213 },
"fusion": {
"mode": "synthesize",
"candidates": [
{ "model": "claude-sonnet-5-5", "finish_reason": "stop", "usage": { "prompt_tokens": 20, "completion_tokens": 300, "total_tokens": 320 } },
{ "model": "gpt-6-luna", "finish_reason": null, "usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0 }, "error": "the provider is unavailable" },
{ "model": "moonshotai/kimi-k3", "finish_reason": "stop", "usage": { "prompt_tokens": 20, "completion_tokens": 280, "total_tokens": 300 } }
],
"judge": { "model": "claude-opus-5-5", "usage": { "prompt_tokens": 1790, "completion_tokens": 312, "total_tokens": 2102 } }
}
}In judge mode, fusion.judge also has pick (the letter) and selected (the model whose answer you got).
When a call fails
- RouterPlus leaves out a candidate that fails. Its entry in
fusion.candidateshaserror. - When only one candidate answers, you get its answer with no judge call.
fusion.judge.skippedsays so. - When every candidate fails, you get the first candidate's error.
- When the judge fails, you get the longest candidate answer.
fusion.judge.errorsays why andfusion.judge.fallbacknames the candidate.
Billing
RouterPlus bills each candidate call and the judge call as a direct call to its model. A fusion request costs the sum of those calls.
Errors
| Status | Cause |
|---|---|
400 invalid_request | The fusion object is missing or invalid. The message names the field. |
| 400 | n is above 1. Fusion returns one choice. |
Fusion does not work with server tools.
For agents: /docs/fusion.md and /llms.txt