This feature is in public preview. To use it, opt in from the Feature Preview page.
How to Use the Model Synthesis Toolpublic
Last verified 24 Aug 2026
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.
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 and web fetch within limits you configure.
The model synthesis tool runs three server-side steps:
- Analyze: Panel models receive the same task and answer in parallel.
- Judge: A judge model compares panel results, evidence, gaps, and conflicts.
- 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, 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, the Responses API, and the Messages API for Anthropic models. You can use the model synthesis tool with serverless inference, dedicated inference, and inference routers 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 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 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:
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:
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
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)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 -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.
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)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 -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.
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)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 -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 and web tool rates.
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_reasonsuch asall_panels_failed,rate_limited, orinsufficient_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: 0but a model emits tool calls, the inner model call fails as empty content and follows the partial or total failure paths above. Settingmax_tool_callsto0also 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.