> ## Documentation Index
> Fetch the complete documentation index at: https://openrouter.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Fusion

> Multi-model deliberation as a server tool

export const Template = ({children, data}) => {
  const replace = s => s.replace(/\{\{(\w+)\}\}/g, (_, k) => (k in data) ? data[k] : `{{${k}}}`);
  const leafText = node => typeof node === 'string' ? node : node?.$$typeof && typeof node.props?.children === 'string' ? node.props.children : null;
  const collapseTokens = nodes => {
    const out = [];
    let i = 0;
    while (i < nodes.length) {
      const ta = leafText(nodes[i]);
      const tb = leafText(nodes[i + 1]);
      const tc = leafText(nodes[i + 2]);
      if (ta != null && tb != null && tc != null) {
        const m = (ta + tb + tc).match(/^([\s\S]*)\{\{(\w+)\}\}([\s\S]*)$/);
        if (m && (m[2] in data)) {
          out.push(m[1] + data[m[2]] + m[3]);
          i += 3;
          continue;
        }
      }
      out.push(nodes[i]);
      i++;
    }
    return out;
  };
  const process = node => {
    if (typeof node === 'string') return replace(node);
    if (Array.isArray(node)) return collapseTokens(node.map(process));
    if (node && typeof node === 'object') {
      if (node.$$typeof) return {
        ...node,
        props: process(node.props)
      };
      return Object.fromEntries(Object.entries(node).map(([k, v]) => [k, process(v)]));
    }
    return node;
  };
  return <>{process(children)}</>;
};

export const API_KEY_REF = '<OPENROUTER_API_KEY>';

<Badge color="blue">Beta</Badge>

<Note>
  **Beta**

  Server tools are currently in beta. The API and behavior may change.
</Note>

The `openrouter:fusion` server tool gives any model access to multi-model deliberation. When your model decides a prompt benefits from multiple perspectives, it invokes this tool — a panel of models answers in parallel, an analyst compares their responses, and the structured analysis comes back to your model for the final answer.

This is the same pipeline behind the [`openrouter/fusion` model alias](/docs/guides/routing/routers/fusion-router) and the [`fusion` plugin](/docs/guides/features/plugins/fusion). Using the server tool directly gives you the most control: choose your own outer model, combine it with other tools, and configure the panel and analyst independently.

## Quick start

<Template
  data={{
API_KEY_REF,
MODEL: '~anthropic/claude-opus-latest',
}}
>
  <CodeGroup>
    ```typescript title="TypeScript" expandable lines theme={null}
    const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
      method: 'POST',
      headers: {
        Authorization: 'Bearer {{API_KEY_REF}}',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        model: '{{MODEL}}',
        messages: [
          {
            role: 'user',
            content: 'Survey the strongest arguments for and against a carbon tax. Where do experts disagree?',
          },
        ],
        tools: [
          { type: 'openrouter:fusion' },
        ],
      }),
    });

    const data = await response.json();
    console.log(data.choices[0].message.content);
    ```

    ```python title="Python" expandable lines theme={null}
    import requests

    response = requests.post(
      "https://openrouter.ai/api/v1/chat/completions",
      headers={
        "Authorization": f"Bearer {{API_KEY_REF}}",
        "Content-Type": "application/json",
      },
      json={
        "model": "{{MODEL}}",
        "messages": [
          {
            "role": "user",
            "content": "Survey the strongest arguments for and against a carbon tax. Where do experts disagree?",
          },
        ],
        "tools": [
          {"type": "openrouter:fusion"},
        ],
      },
    )
    print(response.json()["choices"][0]["message"]["content"])
    ```
  </CodeGroup>
</Template>

<Note title="Chat Completions support is in beta">
  Fusion in the `tools` array works on `/chat/completions` today, but it's slower there than on the [Responses API](/docs/api_reference/responses/overview). For latency-sensitive use, send the same `tools: [{ type: "openrouter:fusion" }]` payload to the Responses API instead.
</Note>

## When does the model invoke it?

The tool's description tells the model to call `openrouter:fusion` only when a task genuinely benefits from multiple perspectives — research questions, multi-domain critique, "compare and contrast" prompts, or anything where being wrong is expensive. Simple tactical prompts won't trigger it.

To **force** fusion on every request, set `tool_choice: "required"`. See [Forcing fusion on every request](/docs/guides/routing/routers/fusion-router#forcing-fusion-on-every-request).

## Parameters

Pass an optional `parameters` object on the tool entry to override defaults:

```json lines theme={null}
{
  "tools": [
    {
      "type": "openrouter:fusion",
      "parameters": {
        "analysis_models": [
          "~google/gemini-flash-latest",
          "deepseek/deepseek-v3.2",
          "~moonshotai/kimi-latest"
        ],
        "model": "~anthropic/claude-opus-latest"
      }
    }
  ]
}
```

| Field                   | Default                                                                                             | Description                                                                                                                                                               |
| ----------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `analysis_models`       | Quality preset (`~anthropic/claude-opus-latest`, `~openai/gpt-latest`, `~google/gemini-pro-latest`) | Models that form the panel. Each runs in parallel with `openrouter:web_search` and `openrouter:web_fetch` enabled. 1–8 models allowed.                                    |
| `model`                 | Your outer model                                                                                    | The analyst that produces the structured analysis JSON. Defaults to the same model handling your request.                                                                 |
| `max_tool_calls`        | `8`                                                                                                 | Max tool-calling steps each panel model and the analyst may take in their `openrouter:web_search` / `openrouter:web_fetch` loop before they must return text. Range 1–16. |
| `max_completion_tokens` | Provider default                                                                                    | Max output tokens (including reasoning) per inner panel/analyst call. Keeps reasoning-heavy models from exhausting their budget before producing visible text.            |
| `reasoning`             | Provider default                                                                                    | Reasoning config forwarded to the panel and analyst calls — an object with optional `effort` and `max_tokens`.                                                            |
| `temperature`           | Provider default                                                                                    | Temperature (`0`–`2`) forwarded to the panel calls. The analyst always runs at temperature 0.                                                                             |

## What the tool returns

On success, the tool result contains the structured analysis and the raw panel responses:

```json expandable lines theme={null}
{
  "status": "ok",
  "analysis": {
    "consensus": ["Points all or most panel models agreed on"],
    "contradictions": [
      { "topic": "...", "stances": [{ "model": "...", "stance": "..." }] }
    ],
    "partial_coverage": [
      { "models": ["..."], "point": "Only some models covered this" }
    ],
    "unique_insights": [
      { "model": "...", "insight": "Something only one model raised" }
    ],
    "blind_spots": ["Topics no panel model addressed"]
  },
  "responses": [
    { "model": "anthropic/claude-opus-4.5", "content": "..." },
    { "model": "openai/gpt-4.1", "content": "..." },
    { "model": "google/gemini-2.5-pro", "content": "..." }
  ]
}
```

When some panel models error but at least one succeeds, the result still has `status: "ok"` and adds a `failed_models` array describing which ones failed and why.

### Analyst degradation

If the **panel** succeeds but the **analyst** fails — an upstream error, an empty completion, or output that isn't valid analysis JSON — the tool does **not** error. It returns `status: "ok"` with the raw panel `responses` and simply **omits** `analysis`. Your model can still write the final answer from the panel responses:

```json lines theme={null}
{
  "status": "ok",
  "responses": [
    { "model": "anthropic/claude-opus-4.5", "content": "..." }
  ]
}
```

### Hard failures

The tool only returns `status: "error"` when it can't produce any useful output. In that case it includes a typed `failure_reason`:

```json lines theme={null}
{
  "status": "error",
  "error": "all panel models failed",
  "failure_reason": "all_panels_failed"
}
```

| Reason                     | Meaning                                                                         |
| -------------------------- | ------------------------------------------------------------------------------- |
| `all_panels_failed`        | Every panel model returned an error.                                            |
| `insufficient_credits`     | Every panel model failed and at least one was due to insufficient credits.      |
| `rate_limited`             | Every panel model failed and at least one was rate-limited.                     |
| `fusion_invocation_capped` | Fusion was already invoked earlier in the same turn; a second call is rejected. |
| `unexpected_error`         | An unexpected error interrupted the fusion run.                                 |

The calling model can fall back to answering without the analysis whenever fusion fails or degrades.

## Web tools

`openrouter:web_search` and `openrouter:web_fetch` are enabled on both the **panel** and the **analyst** calls, so models can pull fresh sources while they answer and analyze. The analyst compares the panel responses rather than merging them: it treats what all or most models agree on as higher-confidence consensus, surfaces contradictions, preserves unique insights from individual models, and flags blind spots none of them addressed. The outer model writes the final answer from that analysis — so the result isn't a simple majority vote.

## Recursion protection

Inner fusion calls carry an `x-openrouter-fusion-depth` header. Panel and analyst models cannot recursively invoke `openrouter:fusion` — the plugin refuses to inject the tool a second time, keeping deliberation bounded to a single level.

## Related

* [Fusion Router (`openrouter/fusion`)](/docs/guides/routing/routers/fusion-router)
* [Fusion plugin](/docs/guides/features/plugins/fusion)
* [Web Search server tool](/docs/guides/features/server-tools/web-search)
* [Web Fetch server tool](/docs/guides/features/server-tools/web-fetch)
* [`/labs/fusion`](https://openrouter.ai/fusion/) — interactive playground
