---
title: How to Use the Model Synthesis Tool (public)
description: Run multiple models on the same task with the model synthesis server-side tool, then return one synthesized answer from DigitalOcean Inference.
product: Inference
url: https://docs.digitalocean.com/products/inference/how-to/use-server-side-tools/use-model-synthesis-tool/
last_updated: "2026-08-24"
---

> **For AI agents:** The documentation index is at [https://docs.digitalocean.com/llms.txt](https://docs.digitalocean.com/llms.txt). Markdown versions of pages use the same URL with `index.html.md` in place of the HTML page (for example, append `index.html.md` to the directory path instead of opening the HTML document).

# How to Use the Model Synthesis Tool (public)

Inference provides a single control plane for managing inference workflows. It includes a Model Catalog where you can view available foundation models, including both DigitalOcean-hosted and third-party commercial models, compare model capabilities and pricing, use routing to match inference requests to the best-fit model, and run inference using serverless or dedicated deployments.

**Note**:

  This feature is in [public preview](https://docs.digitalocean.com/platform/product-lifecycle/index.html.md#public-preview). To use it, opt in from the [**Feature Preview** page](https://cloud.digitalocean.com/account/feature-preview).

The model synthesis tool (API only) is a multi-model tool that runs multiple models on the same task and returns one synthesized answer. You can choose up to eight analysis models that work independently in parallel, plus a top-level model that produces the final completion returned to your application. Each panel model can answer from its training knowledge and, when useful, call server-side [web search](https://docs.digitalocean.com/products/inference/how-to/use-server-side-tools/use-web-search/index.html.md) and [web fetch](https://docs.digitalocean.com/products/inference/how-to/use-server-side-tools/use-web-fetch/index.html.md) within limits you configure.

The model synthesis tool runs three server-side steps:

1. **Analyze:** Panel models receive the same task and answer in parallel.
2. **Judge:** A judge model compares panel results, evidence, gaps, and conflicts.
3. **Synthesize:** The top-level request model writes the final user-facing answer.

The top-level `model` in your API request is the outer model that returns the final completion. By default, it also acts as the judge. Set `model` on the model synthesis tool object to designate a different judge.

The model synthesis tool differs from [Inference Router](https://docs.digitalocean.com/products/inference/how-to/use-inference-router/index.html.md), which routes a request to a single best-fit model. The model synthesis tool intentionally asks several models to address the same problem, then judges and synthesizes their work. Use the model synthesis tool when multiple perspectives justify additional time and cost. Use a single model or a router when you need low latency, deterministic workflows, or routine extraction and classification.

The model synthesis tool works with the [Chat Completions API](https://docs.digitalocean.com/products/inference/how-to/use-chat-completions-api/index.html.md), the [Responses API](https://docs.digitalocean.com/products/inference/how-to/use-responses-api/index.html.md), and the [Messages API](https://docs.digitalocean.com/products/inference/how-to/use-messages-api/index.html.md) for Anthropic models. You can use the model synthesis tool with [serverless inference](https://docs.digitalocean.com/products/inference/how-to/use-serverless-inference/index.html.md), [dedicated inference](https://docs.digitalocean.com/products/inference/how-to/use-dedicated-inference/index.html.md), and [inference routers](https://docs.digitalocean.com/products/inference/how-to/use-inference-router/index.html.md) by setting the top-level `model` field accordingly. Add a tool object with `type` set to `model_synthesis` in the `tools` array. Existing `pydo` and `@digitalocean/dots` clients pass the model synthesis tool object through without SDK changes.

The application receives a normal completion from the top-level model. You do not need a separate multi-agent response format or client-side orchestration code.

## When to Use the Model Synthesis Tool

Use the model synthesis tool for consequential comparisons, ambiguous research, technical or strategic decisions, complex troubleshooting, architecture and vendor evaluations, policy analysis, and incident retrospectives. Tasks where missed considerations are costly benefit from independent panel attempts and disciplined synthesis.

The model synthesis tool is not intended for every request. Text rewriting, data extraction, label classification, and interactions with strict latency or cost limits are usually better served by a single model.

## Configure the Model Synthesis Tool

You can configure the model synthesis tool with a DigitalOcean `preset`, or set the synthesizer, panel, judge, and reasoning settings yourself. Use model slugs from the [available models](https://docs.digitalocean.com/products/inference/details/models/index.html.md) page for `analysis_models`, the model synthesis tool `model` field (judge), and the top-level request `model`.

Any model available for DigitalOcean Inference can act as a panel member or judge. Commercial models from OpenAI and Anthropic follow the same [third-party model access restrictions](https://docs.digitalocean.com/products/inference/details/limits/index.html.md) as other inference features. When you configure the panel directly, tune it for the workload: a high-quality panel for critical analysis, a lower-cost panel for routine research, or a diverse mix to reduce shared reasoning gaps. More panel models increase cost and may increase latency. Start with a small, task-relevant panel and add models only when evaluation shows measurable value.

## Use a Preset

Use DigitalOcean presets for common quality and cost tradeoffs without selecting panel models yourself:

| Preset | Description |
|---|---|
| `budget` | The lowest-cost configuration, using a smaller model panel and lighter reasoning settings. |
| `balanced` | A mid-size panel with moderate reasoning depth, balancing quality and cost. |
| `quality` | The largest model panel and deepest reasoning configuration, at higher cost and latency. |

DigitalOcean Inference resolves each preset to a validated synthesizer, model panel, and reasoning configuration. As models, pricing, and performance improve, the underlying configuration can be updated without requiring changes to your integration.

When you set `preset`, omit `analysis_models`. Specifying both returns HTTP `400`. You can still set `reasoning_effort`, `max_tokens`, and `max_tool_calls` on the tool object to override the preset defaults for those fields.

The following Chat Completions example uses the `balanced` preset:

```bash
curl -X POST https://inference.do-ai.run/v1/chat/completions \
  -H "Authorization: Bearer $MODEL_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm-5.2",
    "messages": [
      {
        "role": "user",
        "content": "Your research question here"
      }
    ],
    "tools": [
      {
        "type": "model_synthesis",
        "preset": "balanced"
      }
    ]
  }'
```

## Configure Directly

When you configure the model synthesis tool directly, the top-level `model` is the synthesizer that returns the final completion. The `analysis_models` list on the tool object is the panel. Set `model` on the tool object to designate a judge that differs from the synthesizer; when omitted, the judge defaults to the top-level request model.

Set `reasoning_effort` in two places when you need separate control: the top-level value applies to the synthesizer, and the value on the tool object applies to panel models and the judge.

The following Chat Completions example sets the synthesizer, panel, judge, and reasoning effort directly:

```bash
curl -X POST https://inference.do-ai.run/v1/chat/completions \
  -H "Authorization: Bearer $MODEL_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm-5.2",
    "messages": [
      {
        "role": "user",
        "content": "Your research question here"
      }
    ],
    "reasoning_effort": "high",
    "tools": [
      {
        "type": "model_synthesis",
        "model": "glm-5.2",
        "analysis_models": [
          "glm-5.2",
          "kimi-k2.6"
        ],
        "reasoning_effort": "high"
      }
    ]
  }'
```

| Field | Required | Description |
|---|---|---|
| `type` | Yes | Set to `model_synthesis`. |
| `preset` | No | One of `budget`, `balanced`, or `quality`. Resolves a validated synthesizer, model panel, and reasoning configuration. Mutually exclusive with `analysis_models`. Specifying both returns HTTP `400`. |
| `analysis_models` | Conditional | Slugs for one to eight unique panel models. Each model receives the same task in parallel. Required when you omit `preset`. Do not include this field when `preset` is set. |
| `model` | No | Slug for the judge model. Defaults to the top-level request model. |
| `max_tool_calls` | No | Maximum web search and web fetch steps per participant. Defaults to `8` when omitted. Allowed range is `0` to `15`. Set to `0` to disable web search and web fetch on all model synthesis tool sub-calls and on any web tools the outer model might call after the model synthesis tool completes. Applies independently to each panel model, the judge, and the outer synthesis model. Within each participant’s turn, that budget is shared across `web_search` and `web_fetch`, not doubled per tool. The total web tool budget in one request can reach `max_tool_calls` multiplied by the number of panel models plus one judge for inner calls, plus up to another `max_tool_calls` on the outer synthesis step when `max_tool_calls` is greater than `0`. For example, three panel models, one judge, and `max_tool_calls: 5` allow up to 25 inner web tool calls and up to 5 more during synthesis. |
| `max_tokens` | No | Maximum output tokens for each inner model synthesis tool stage (panel, judge, and synthesis) on all endpoints, including reasoning tokens where the provider reports them. For research-style prompts, use `10000` to `16000`; `16000` is a practical default for comprehensive answers. Values below `4000` risk truncating a stage. |
| `allowed_domains` | No | Restrict web fetch and web search to these domains for panel and judge calls. |
| `blocked_domains` | No | Block web fetch and web search for these domains on panel and judge calls. |
| `reasoning_effort` | No | Reasoning effort forwarded to panel models and the judge. Unsupported values are dropped for models that do not accept them. See accepted values below. |

Set `reasoning_effort` on the model synthesis tool object for all APIs. Chat Completions accepts `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Responses accepts `none`, `low`, `medium`, `high`, and `xhigh`. Messages uses the same field on the tool object. The value is forwarded to each panel and judge sub-call. On Chat Completions, you can also set top-level `reasoning_effort` for the synthesizer. If a target model’s catalog metadata does not support the effort you set, the value is dropped silently. Anthropic maps `minimal` to `low` and `xhigh` to `max`. Accepted values are ultimately per model from catalog metadata, not a fixed list per provider.

## Send a Model Synthesis Tool Request

The following examples send model synthesis tool requests on the Chat Completions, Responses, and Messages APIs. In each case, the top-level model synthesizes the final answer after the panel models and judge complete their work.

**Chat Completions API**

### Python

```python
import os
from pydo.inference import Client

client = Client(token=os.environ.get("MODEL_ACCESS_KEY"))

resp = client.chat.completions.create(
    model="anthropic-claude-opus-4.8",
    messages=[
        {
            "role": "user",
            "content": (
                "Compare Kubernetes and Nomad for a small platform team running "
                "20 internal services. Give a concise recommendation with tradeoffs."
            ),
        },
    ],
    tools=[
        {
            "type": "model_synthesis",
            "analysis_models": [
                "openai-gpt-5.5",
                "deepseek-v4-pro",
            ],
            "max_tool_calls": 8,
            "max_tokens": 16000,
        }
    ],
    tool_choice="required",
    max_tokens=16000,
    stream=False,
)

print(resp.choices[0].message.content)
```

### JavaScript

```javascript
import { InferenceClient } from "@digitalocean/dots";

const client = new InferenceClient({
    apiKey: process.env.MODEL_ACCESS_KEY,
});

const completion = await client.chat.completions.create({
    model: "anthropic-claude-opus-4.8",
    messages: [
        {
            role: "user",
            content:
                "Compare Kubernetes and Nomad for a small platform team running " +
                "20 internal services. Give a concise recommendation with tradeoffs.",
        },
    ],
    tools: [
        {
            type: "model_synthesis",
            analysis_models: ["openai-gpt-5.5", "deepseek-v4-pro"],
            max_tool_calls: 8,
            max_tokens: 16000,
        },
    ],
    tool_choice: "required",
    max_tokens: 16000,
    stream: false,
});

console.log(completion.choices[0].message.content);
```

### cURL

```shell
curl -X POST https://inference.do-ai.run/v1/chat/completions \
  -H "Authorization: Bearer $MODEL_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic-claude-opus-4.8",
    "messages": [
      {
        "role": "user",
        "content": "Compare Kubernetes and Nomad for a small platform team running 20 internal services. Give a concise recommendation with tradeoffs."
      }
    ],
    "tools": [
      {
        "type": "model_synthesis",
        "analysis_models": [
          "openai-gpt-5.5",
          "deepseek-v4-pro"
        ],
        "max_tool_calls": 8,
        "max_tokens": 16000
      }
    ],
    "tool_choice": "required",
    "max_tokens": 16000,
    "stream": false
  }'
```

**Responses API**

The following example sends a Responses API request with the model synthesis tool enabled. Set `input` instead of `messages` and use `max_output_tokens` at the top level. The model synthesis tool object always uses `max_tokens` on all endpoints.

### Python

```python
import os
from pydo.inference import Client

client = Client(token=os.environ.get("MODEL_ACCESS_KEY"))

resp = client.responses.create(
    model="openai-gpt-5.2",
    input=(
        "What are the tradeoffs between RAG and fine-tuning "
        "for domain-specific QA?"
    ),
    max_output_tokens=4096,
    tools=[
        {
            "type": "model_synthesis",
            "model": "openai-gpt-5.2",
            "analysis_models": [
                "anthropic-claude-opus-4.6",
                "google-gemini-3.1-pro",
            ],
            "max_tool_calls": 5,
            "max_tokens": 2048,
            "reasoning_effort": "high",
        }
    ],
    tool_choice={"type": "function", "name": "model_synthesis"},
    stream=False,
)

print(resp)
```

### JavaScript

```javascript
import { InferenceClient } from "@digitalocean/dots";

const client = new InferenceClient({
    apiKey: process.env.MODEL_ACCESS_KEY,
});

const resp = await client.responses.create({
    model: "openai-gpt-5.2",
    input:
        "What are the tradeoffs between RAG and fine-tuning " +
        "for domain-specific QA?",
    max_output_tokens: 4096,
    tools: [
        {
            type: "model_synthesis",
            model: "openai-gpt-5.2",
            analysis_models: [
                "anthropic-claude-opus-4.6",
                "google-gemini-3.1-pro",
            ],
            max_tool_calls: 5,
            max_tokens: 2048,
            reasoning_effort: "high",
        },
    ],
    tool_choice: { type: "function", name: "model_synthesis" },
    stream: false,
});

console.log(resp);
```

### cURL

```shell
curl -X POST https://inference.do-ai.run/v1/responses \
  -H "Authorization: Bearer $MODEL_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai-gpt-5.2",
    "input": "What are the tradeoffs between RAG and fine-tuning for domain-specific QA?",
    "max_output_tokens": 4096,
    "tools": [
      {
        "type": "model_synthesis",
        "model": "openai-gpt-5.2",
        "analysis_models": [
          "anthropic-claude-opus-4.6",
          "google-gemini-3.1-pro"
        ],
        "max_tool_calls": 5,
        "max_tokens": 2048,
        "reasoning_effort": "high"
      }
    ],
    "tool_choice": { "type": "function", "name": "model_synthesis" },
    "stream": false
  }'
```

**Messages API**

The following example sends a Messages API request with the model synthesis tool enabled. Set `max_tokens` at the top level. The model synthesis tool object always uses `max_tokens` on all endpoints.

### Python

```python
import os
from pydo.inference import Client

client = Client(token=os.environ.get("MODEL_ACCESS_KEY"))

resp = client.messages.create(
    model="anthropic-claude-opus-4.6",
    max_tokens=4096,
    messages=[
        {
            "role": "user",
            "content": (
                "What are the tradeoffs between RAG and fine-tuning "
                "for domain-specific QA?"
            ),
        },
    ],
    tools=[
        {
            "type": "model_synthesis",
            "model": "anthropic-claude-opus-4.6",
            "analysis_models": [
                "openai-gpt-5.2",
                "google-gemini-3.1-pro",
            ],
            "max_tool_calls": 5,
            "max_tokens": 2048,
            "reasoning_effort": "high",
        }
    ],
    tool_choice={"type": "tool", "name": "model_synthesis"},
)

print(resp)
```

### JavaScript

```javascript
import { InferenceClient } from "@digitalocean/dots";

const client = new InferenceClient({
    apiKey: process.env.MODEL_ACCESS_KEY,
});

const resp = await client.messages.create({
    model: "anthropic-claude-opus-4.6",
    max_tokens: 4096,
    messages: [
        {
            role: "user",
            content:
                "What are the tradeoffs between RAG and fine-tuning " +
                "for domain-specific QA?",
        },
    ],
    tools: [
        {
            type: "model_synthesis",
            model: "anthropic-claude-opus-4.6",
            analysis_models: ["openai-gpt-5.2", "google-gemini-3.1-pro"],
            max_tool_calls: 5,
            max_tokens: 2048,
            reasoning_effort: "high",
        },
    ],
    tool_choice: { type: "tool", name: "model_synthesis" },
});

console.log(resp);
```

### cURL

```shell
curl -X POST https://inference.do-ai.run/v1/messages \
  -H "Authorization: Bearer $MODEL_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic-claude-opus-4.6",
    "max_tokens": 4096,
    "messages": [
      {
        "role": "user",
        "content": "What are the tradeoffs between RAG and fine-tuning for domain-specific QA?"
      }
    ],
    "tools": [
      {
        "type": "model_synthesis",
        "model": "anthropic-claude-opus-4.6",
        "analysis_models": [
          "openai-gpt-5.2",
          "google-gemini-3.1-pro"
        ],
        "max_tool_calls": 5,
        "max_tokens": 2048,
        "reasoning_effort": "high"
      }
    ],
    "tool_choice": { "type": "tool", "name": "model_synthesis" }
  }'
```

Set `tool_choice` to `required` on the Chat Completions API to run the model synthesis tool on every request. On the Responses API, use `{"type": "function", "name": "model_synthesis"}`. On the Messages API, use `{"type": "tool", "name": "model_synthesis"}` or `any` to require the model synthesis tool. Set `tool_choice` to `auto` on any endpoint to let the top-level model invoke the model synthesis tool only when the prompt benefits from multiple perspectives. Simple prompts such as greetings usually complete without invoking the model synthesis tool.

## Streaming

Panel model calls are always non-streaming. When you set `stream` to `true` at the top level, only the outer model’s final synthesis streams back to your application. `stream_options.include_usage` behaves as it does for other inference requests.

## Latency and Timeouts

The model synthesis tool is a long-running call. Plan for long client read timeouts in your application.

Research-style model synthesis tool requests typically take 3 to 6 minutes end-to-end while panel models run in parallel, the judge compares results, and the outer model synthesizes the final answer. Web-heavy prompts, more or larger panel models, or higher `reasoning_effort` can increase latency to as much as 8 to 10 minutes.

The main latency settings are the number and size of panel models, web search volume (`max_tool_calls`), and `reasoning_effort`.

Panel sub-calls time out after 12 minutes. Judge sub-calls time out after 8 minutes. Sub-call timeouts are not retried. The inference gateway terminates long requests at 20 minutes (1200 seconds). Set your client read timeout to at least 20 minutes. Treat an HTTP `504` from the gateway as retryable, not a hard failure.

## Usage and Cost

Panel models run concurrently, which is faster than calling each model sequentially. The model synthesis tool still waits for panel, judge, and tool work before the outer model writes the final answer, so a model synthesis tool request generally costs more and takes longer than a single-model completion.

One model synthesis tool API request is not one model call. Usage reflects token consumption and tool calls for every panel model, the judge, the outer model, and any web search or web fetch steps those models perform. The model synthesis tool does not add a separate charge. You are billed at the existing [per-model token rates](https://docs.digitalocean.com/products/inference/details/pricing/index.html.md#serverless-inference-pricing) and [web tool rates](https://docs.digitalocean.com/products/inference/details/pricing/index.html.md#tools-usage).

The response includes per-model usage throughout the request. The final usage message aggregates token counts across all participating models. To inspect individual model consumption, review usage on each model response in the stream or completion payload, not only the final aggregate.

## Failure and Degradation

The model synthesis tool returns HTTP `200` for most partial failures and lets the outer model produce a final answer when possible. The result depends on which stage fails:

- If some panel models fail or return empty output, the model synthesis tool continues. The summary it sends to the outer model includes failure details. The outer model may mention gaps only when they affect the final answer.
- If all panel models fail, the summary reports that the model synthesis tool failed. The outer model answers from its own knowledge. The response may include a `failure_reason` such as `all_panels_failed`, `rate_limited`, or `insufficient_credits`.
- If the judge fails or returns bad or truncated JSON, panel responses are retained, but structured analysis is omitted. The summary notes that judge comparison is unavailable.
- If web tools are disabled with `max_tool_calls: 0` but a model emits tool calls, the inner model call fails as empty content and follows the partial or total failure paths above. Setting `max_tool_calls` to `0` also disables web tools on the outer synthesis step.

Failed panel or judge models may appear in a `failed_models` list when orchestration continues with other participants.

## Use the Model Synthesis Tool with Other Server-Side Tools

You can include the model synthesis tool in the `tools` array with other server-side tools such as `web_search` in the same request. In one turn, the model synthesis tool and other built-in tools can all execute. Results from other tools are included in the summary the model synthesis tool sends to the outer model.

The model synthesis tool runs at most once per turn. Duplicate model synthesis tool entries in the same request are ignored after the first invocation. Nested model synthesis tool calls are blocked.

After the model synthesis tool executes, it is unavailable for the rest of that turn. Other tools remain available. On the Chat Completions and Responses APIs, `tool_choice` set to `required` or a named function choice is changed to `auto` after the first built-in tool executes so the follow-up turn is not forced to call another tool. On the Messages API, `any` or a specific tool choice is changed to `auto` after a built-in call.