How to Use Server-Side Tools

Last verified 17 Jun 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.

Server-side tools are capabilities you attach to an inference request that the Inference platform runs for you during the model turn. When the model decides to use a tool, the platform executes it and folds the result back into the conversation. Server-side tools differ from client-side tools, where the model returns which tool to call and with which arguments, and your app runs the function and sends the result back in a follow-up request.

We support server-side integrations that extend the model’s capabilities during inference. Instead of managing tool orchestration yourself, you add tool definitions in your API request and the platform handles discovery, execution, and response integration automatically. You can use the following server-side tools with serverless inference, dedicated inference, and inference routers:

Supported Tool Use For
Web Search (Public Preview) Search the web for real-time information.
We use a third-party web search service (Exa.ai) for all models.
Web Fetch (Public Preview) Fetch URLs and PDF content from the web.
We use a third-party web fetch service (Exa.ai) for non-Anthropic models. For Anthropic models, requests pass through to Anthropic’s web fetch service.
Knowledge Base Retrieval Query your private data sources during inference using retrieval-augmented generation (RAG).
MCP Enable the model to access remote MCP servers and orchestrate calls across them.
Tool Search (For Anthropic and OpenAI models only) Search the tools catalog to use during inference.
Computer Use (For Anthropic and OpenAI models only) UI action harness for interacting with the local system.
Bash/Local Shell (For Anthropic and OpenAI models only) Run commands in the local shell.
Web Fetch (For Anthropic models only) Fetch URL/PDF content from the web.
Text Editor (For Anthropic models only) Edit or view text files in the local workspace.
Apply Patch (For OpenAI models only) Apply a structured code patch.
Function Calling (For Anthropic and OpenAI models only) App-defined calls.

Web Search, Knowledge Base Retrieval, MCP, and Web Fetch for non-Anthropic models are DigitalOcean-hosted server-side tools. Passthrough tools to the provider include Tool Search, Computer Use, Bash, Local Shell, Web Fetch, and Text Editor.

For pricing information, see Tools Usage Pricing.

Get Started

Server-side tools work with both the Chat Completions API and the Responses API, and with the Messages API for Anthropic models. To use server-side tools, add the tool definitions to the tools array in your API request. Set tool_choice to auto to let the model decide when to query a tool, or required to always query it before responding.

To use tools with an inference router and dedicated inference deployments, set the model field to the name of your router or dedicated inference and model slug, respectively.

To use tools with dedicated inference and inference routers, update the model field, as described in Use Dedicated Inference and Use Inference Router.

The following example sends a Responses API request with knowledge base retrieval and web search tools enabled for serverless inference:

import os
from pydo import Client

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

resp = client.responses.create(
    model="deepseek-v4-pro",
    input="What is actions infrastructure? Answer using the knowledge base and search the web for real-time information.",
    tools=[
        {
            "type": "knowledge_base_retrieval",
            "knowledge_base_id": "09d65da1-5225-11f1-b074-4e013e2xxxx",
        },
        {
            "type": "web_search",
            "max_uses": 3,
            "max_results": 5,
        },
    ],
    stream=False,
    max_output_tokens=1024,
)

print(resp)
import { InferenceClient } from "@digitalocean/dots";

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

const resp = await client.responses.create({
    model: "deepseek-v4-pro",
    input: "What is actions infrastructure? Answer using the knowledge base and search the web for real-time information.",
    tools: [
        {
            type: "knowledge_base_retrieval",
            knowledge_base_id: "09d65da1-5225-11f1-b074-4e013e2xxxx",
        },
        {
            type: "web_search",
            max_uses: 3,
            max_results: 5,
        },
    ],
    stream: false,
    max_output_tokens: 1024,
});

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": "deepseek-v4-pro",
    "input": "What is actions infrastructure? Answer using the knowledge base and search the web for real-time information.",
    "tools": [
      {
        "type": "knowledge_base_retrieval",
        "knowledge_base_id": "09d65da1-5225-11f1-b074-4e013e2xxxx"
      },
      {
        "type": "web_search",
        "max_uses": 3,
        "max_results": 5
      }
    ],
    "stream": false,
    "max_output_tokens": 1024
  }'

Web search is a built-in tool that gives the model access to real-time web content during inference. When you add web search in your API request, the model decides when a web search is needed, and the results are incorporated into the model’s response.

We use a third-party web search service (Exa.ai) for all models.

To enable web search, include a tool object with type set to web_search in the tools array of your request. When the model determines that a prompt benefits from web search, it searches for relevant information and incorporates the results into its response.

The following examples send Responses API requests with web search enabled:

import os
from pydo import Client

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

resp = client.responses.create(
    model="openai-gpt-4o",
    input="What are the latest pricing changes for DigitalOcean Droplets?",
    tools=[
        {
            "type": "web_search",
            "max_uses": 3,
            "max_results": 5,
        }
    ],
    max_output_tokens=1024,
    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-4o",
    input: "What are the latest pricing changes for DigitalOcean Droplets?",
    tools: [
        {
            type: "web_search",
            max_uses: 3,
            max_results: 5,
        },
    ],
    max_output_tokens: 1024,
    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-4o",
    "input": "What are the latest pricing changes for DigitalOcean Droplets?",
    "tools": [
      {
        "type": "web_search",
        "max_uses": 3,
        "max_results": 5
      }
    ],
    "max_output_tokens": 1024,
    "stream": false
  }'

Alternatively, specify model: <model_name>:web to enable model access to web search and web fetch. This is particularly useful in coding agents where you can only change the model name.

You can optionally limit the number of searches the model performs per request from 1 to 5 with max_uses and the number of results each search returns from 1 to 10 with max_results (defaults to 5). When the request reaches the limit, the model produces a final response using the results collected so far. For the full set of web search parameters, see the Serverless Inference API reference.

The response looks similar to the following:

{
  ...
  "output": [
    {
      "action": {
        "queries": [
          "DigitalOcean AI platform features"
        ],
        "query": "DigitalOcean AI platform features",
        "type": "search"
      },
      "id": "ws_call_t7eyYNbAWQOcEln1Ns2TxuOv",
      "status": "completed",
      "type": "web_search_call"
    },
    {
      "content": [
        {
          "annotations": [
            {
              "end_index": 1501,
              "start_index": 1439,
              "title": "DigitalOcean AI Platform Features | DigitalOcean Documentation",
              "type": "url_citation",
              "url": "https://docs.digitalocean.com/products/inference/details/features"
            },
            {
              "end_index": 1800,
              "start_index": 1729,
              "title": "DigitalOcean Inference Details | DigitalOcean Documentation",
              "type": "url_citation",
              "url": "https://docs.digitalocean.com/products/inference/details"
            },
            {
              "end_index": 2085,
              "start_index": 2028,
              "title": "Agent Platform | Build AI Agents with DigitalOcean",
              "type": "url_citation",
              "url": "https://www.digitalocean.com/products/inference/platform"
            }
          ],
          "logprobs": [],
          "text": "The DigitalOcean AI Platform offers a variety of features:\n\n1. **AI Agent Development**: Build fully-managed AI ...",
          "type": "output_text"
        }
      ],
...
  }
}

Use Web Fetch public

Web fetch is a built-in tool that retrieves the full content of specific web pages and PDF documents during inference. When you add web fetch to your API request, the model fetches URLs referenced in the conversation and incorporates the content into its response.

We use a third-party web fetch service (Exa.ai) for non-Anthropic models. For Anthropic models, requests pass through to Anthropic’s web fetch service.

To enable web fetch, include a tool object with type set to web_fetch in the tools array of your request. The following example sends a Responses API request with web fetch enabled:

import os
from pydo import Client

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

resp = client.responses.create(
    model="openai-gpt-4o",
    input="Summarize the content at https://docs.digitalocean.com/products/inference/",
    tools=[
        {
            "type": "web_fetch",
            "max_uses": 3,
        }
    ],
    max_output_tokens=1024,
    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-4o",
    input: "Summarize the content at https://docs.digitalocean.com/products/inference/",
    tools: [
        {
            type: "web_fetch",
            max_uses: 3,
        },
    ],
    max_output_tokens: 1024,
    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-4o",
    "input": "Summarize the content at https://docs.digitalocean.com/products/inference/",
    "tools": [
      {
        "type": "web_fetch",
        "max_uses": 3
      }
    ],
    "max_output_tokens": 1024,
    "stream": false
  }'

You can optionally limit the number of fetches the model performs per request from 1 to 5 with max_uses. When the request reaches the limit, the model produces a final response using the content collected so far.

Alternatively, specify model: <model_name>:web to give the model access to web fetch and web search. This is particularly useful for coding agents where you can only change the model name.

Retrieve Knowledge Base

Knowledge base retrieval lets the model query your private data sources during inference using retrieval-augmented generation (RAG). You add the knowledge_base_retrieval tool to your API request and the inference API handles retrieval and incorporates the results into the model’s response automatically.

To use knowledge base retrieval, send a POST request with your knowledge base ID. You can find the ID in the DigitalOcean Control Panel or by querying the API. For example, use the Chat Completions API with knowledge base retrieval:

import os
from pydo import Client

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

resp = client.chat.completions.create(
    model="openai-gpt-4o",
    messages=[
        {"role": "user", "content": "What are some features of DigitalOcean Inference?"},
    ],
    tools=[
        {
            "type": "knowledge_base_retrieval",
            "knowledge_base_id": "<your-knowledge-base-id>",
        }
    ],
    tool_choice="auto",
    stream=False,
    max_tokens=1024,
)

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: "openai-gpt-4o",
    messages: [
        { role: "user", content: "What are some features of DigitalOcean Inference?" },
    ],
    tools: [
        {
            type: "knowledge_base_retrieval",
            knowledge_base_id: "<your-knowledge-base-id>",
        },
    ],
    tool_choice: "auto",
    stream: false,
    max_tokens: 1024,
});

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": "openai-gpt-4o",
    "messages": [
      {
        "role": "user",
        "content": "What are some features of DigitalOcean Inference?"
      }
    ],
    "tools": [
      {
        "type": "knowledge_base_retrieval",
        "knowledge_base_id": "<your-knowledge-base-id>"
      }
    ],
    "tool_choice": "auto",
    "stream": false,
    "max_tokens": 1024
  }'

For the full set of parameters, see the Serverless Inference API reference. The response looks like the following:

{
    "choices": [
        {
            "finish_reason": "stop",
            "index": 0,
            "logprobs": null,
            "message": {
                "annotations": [
                    {
                        "type": "tool_use",
                        "tool_use": {
                            "name": "knowledge_base_retrieval",
                            "call_id": "call_y6aBCI2IrnS8ZgPR6DKjXl9T",
                            "arguments": "{\"query\":\"features of DigitalOcean Inference\"}",
                            "status": "completed",
                            "output": "{\"knowledge_base_id\":\"e7651dee-da73-11ef-bf8f-4e013e2dxxxx\",\"query\":\"features of DigitalOcean Inference\",\"results\":[{\"metadata\":{\"chunk_category\":\"CompositeElement\",\"ingested_timestamp\":\"2026-05-11T18:15:46.532085+00:00\",\"item_name\":\"https://docs.digitalocean.com/\",\"page_number\":null},\"text_content\":\"### 1 May 2026 [ ](https://docs.digitalocean.com/#1-may-2026) * The following DeepSeek model is now available on DigitalOcean Inference for [serverless inference](https://docs.digitalocean.com/products/inference/how-to/use-serverless-inference/), [Agent Development Kit](https://docs.digitalocean.com/products/inference/how-to/build-agents-using-adk/) and [agents](https://docs.digitalocean.com/products/inference/how-to/create-agents/): For more information, see the [Available Models page](https://docs.digitalocean.com/products/inference/details/models/).\"},{\"metadata\":{\"chunk_category\":\"CompositeElement\",\"ingested_timestamp\":\"2026-05-11T18:15:46.532085+00:00\",\"item_name\":\"https://docs.digitalocean.com/\",\"page_number\":null},\"text_content\":\"### 5 May 2026 [ ](https://docs.digitalocean.com/#5-may-2026) ....\"}],\"total_results\":3}"
                        }
                    }
                ],
                "content": "DigitalOcean Inference includes several features designed to support serverless inference and facilitate the development and deployment of AI models and agents. ...",
                "reasoning_content": null,
                "refusal": null,
                "role": "assistant"
            }
        }
    ],
    ...
    }
}

Use the Responses API with knowledge base retrieval:

curl -X POST https://inference.do-ai.run/v1/responses \
  -H "Authorization: Bearer $MODEL_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4-pro",
    "input": "What is actions infrastructure? Answer using the knowledge base.",
    "tools": [
      {
        "type": "knowledge_base_retrieval",
        "knowledge_base_id": "09d65da1-5225-11f1-b074-4e013e2dxxxx"
      }
    ],
    "stream": false,
    "max_output_tokens": 1024
  }'

The response looks similar to the following:

{
  "background": false,
  "completed_at": 0,
  "created_at": 1779045957,
  "error": {
    "code": "",
    "message": ""
  },
  "frequency_penalty": 0,
  "id": "resp_b999e07cebb3dd7a",
  "incomplete_details": {
    "reason": ""
  },
  "instructions": {
    "OfInputItemList": null,
    "OfString": ""
  },
  "max_output_tokens": 1024,
  "max_tool_calls": 0,
  "metadata": null,
  "model": "deepseek-v4-pro",
  "object": "response",
  "output": [
    {
      "arguments": "{\"query\": \"What is actions infrastructure?\"}",
      "call_id": "chatcmpl-tool-8e9ce86361b0fe64",
      "name": "knowledge_base_retrieval",
      "status": "completed",
      "type": "function_call"
    },
    {
      "call_id": "chatcmpl-tool-8e9ce86361b0fe64",
      "output": "{\"knowledge_base_id\":\"09d65da1-5225-11f1-b074-4e013e2dxxxx\",\"query\":\"What is actions infrastructure?\",\"results\":[{\"metadata\":{\"chunk_category\":\"CompositeElement\",\"ingested_timestamp\":\"2026-05-17T19:23:20.695776+00:00\",\"item_name\":\"example-document.pdf\",\"page_number\":45},\"text_content\":\"Example content retrieved from your knowledge base.\"}],\"total_results\":1}",
      "status": "completed",
      "type": "function_call_output"
    }
  ]
}

Use Model Context Protocol (MCP)

MCP servers expose tools that the model can call, such as fetching account data, managing schedules, or interacting with third-party APIs. The MCP built-in tool connects the model to remote Model Context Protocol (MCP) servers and orchestrates calls to them.

Connect to an Authenticated MCP Server

You can connect to authenticated MCP servers using bearer token authentication. The following example sends a Chat Completions request that connects to the DigitalOcean Accounts MCP server. Replace $DIGITALOCEAN_API_TOKEN with a valid DigitalOcean personal access token.

import os
from pydo import Client

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

resp = client.chat.completions.create(
    model="openai-gpt-4o",
    messages=[
        {"role": "user", "content": "Fetch my DigitalOcean account information and summarize it in 2 bullets."},
    ],
    tools=[
        {
            "type": "mcp",
            "server_label": "digitalocean",
            "server_url": "https://accounts.mcp.digitalocean.com/mcp",
            "authorization": f"Bearer {os.environ.get('DIGITALOCEAN_API_TOKEN')}",
            "allowed_tools": ["account-get-information"],
        }
    ],
    tool_choice="required",
    stream=False,
    max_tokens=512,
)

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: "openai-gpt-4o",
    messages: [
        { role: "user", content: "Fetch my DigitalOcean account information and summarize it in 2 bullets." },
    ],
    tools: [
        {
            type: "mcp",
            server_label: "digitalocean",
            server_url: "https://accounts.mcp.digitalocean.com/mcp",
            authorization: `Bearer ${process.env.DIGITALOCEAN_API_TOKEN}`,
            allowed_tools: ["account-get-information"],
        },
    ],
    tool_choice: "required",
    stream: false,
    max_tokens: 512,
});

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": "openai-gpt-4o",
    "messages": [
      {
        "role": "user",
        "content": "Fetch my DigitalOcean account information and summarize it in 2 bullets."
      }
    ],
    "tools": [
      {
        "type": "mcp",
        "server_label": "digitalocean",
        "server_url": "https://accounts.mcp.digitalocean.com/mcp",
        "authorization": "Bearer $DIGITALOCEAN_API_TOKEN",
        "allowed_tools": ["account-get-information"]
      }
    ],
    "tool_choice": "required",
    "stream": false,
    "max_tokens": 512
  }'

The allowed_tools array restricts which tools from the MCP server the model can call. In this example, only the account-get-information tool is available. When omitted, the model can use any tool the server exposes. For the full set of MCP tool parameters, see the Serverless Inference API reference. The response looks like the following:

{
    "choices": [
        {
            "finish_reason": "stop",
            "index": 0,
            "logprobs": null,
            "message": {
                "annotations": [
                    {
                        "type": "tool_use",
                        "tool_use": {
                            "name": "digitalocean__account-get-information",
                            "call_id": "call_xasb9Xk1HAfT564P3bteZZTT",
                            "arguments": "{}",
                            "status": "completed",
                            "output": "{\n  \"droplet_limit\": 100,\n  \"floating_ip_limit\": 75,\n  \"reserved_ip_limit\": 75,\n  \"volume_limit\": 5000,\n  \"email\": \"[email protected]\",\n  \"name\": \"dev-sammy\",\n  \"uuid\": \"de55ee97-21ab-452d-aaf0-d4046480xxxx\",\n  \"email_verified\": true,\n  \"status\": \"active\",\n  \"team\": {\n    \"name\": \"My Team\",\n    \"uuid\": \"de55ee97-21ab-452d-aaf0-d4046480xxxx\"\n  }\n}"
                        }
                    }
                ],
                "content": "- Your account (\"dev-sammy\") is active with email \"[email protected]\", which is verified. You are part of \"My Team\" with a UUID of \"de55ee97-21ab-452d-aaf0-d4046480xxxx\".\n- You have a resource allocation limit of 100 droplets, 75 floating IPs, 75 reserved IPs, and 5000 volumes.",
                "reasoning_content": null,
                "refusal": null,
                "role": "assistant"
            }
        }
    ],
....    }
}

Connect to an Unauthenticated MCP Server

You can also connect to public MCP servers that do not require authentication. The following example sends a Responses API request:

import os
from pydo import Client

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

resp = client.responses.create(
    model="openai-gpt-4o",
    input="Create a scheduling poll called Team Lunch with two time options for tomorrow at noon and the day after at noon.",
    tools=[
        {
            "type": "mcp",
            "server_label": "timergy",
            "server_url": "https://api.timergy.com/mcp",
        }
    ],
    tool_choice="required",
    stream=False,
    max_output_tokens=512,
)

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-4o",
    input: "Create a scheduling poll called Team Lunch with two time options for tomorrow at noon and the day after at noon.",
    tools: [
        {
            type: "mcp",
            server_label: "timergy",
            server_url: "https://api.timergy.com/mcp",
        },
    ],
    tool_choice: "required",
    stream: false,
    max_output_tokens: 512,
});

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-4o",
    "input": "Create a scheduling poll called Team Lunch with two time options for tomorrow at noon and the day after at noon.",
    "tools": [
      {
        "type": "mcp",
        "server_label": "timergy",
        "server_url": "https://api.timergy.com/mcp"
      }
    ],
    "tool_choice": "required",
    "stream": false,
    "max_output_tokens": 512
  }'

The response looks like the following:

{
...
  "model": "openai-gpt-4o",
  "object": "response",
  "output": [
    {
      "arguments": "{\"autoFinalize\":false,\"creatorName\":\"Assistant for Team\",\"deadline\":\"2026-04-08T12:00:00-05:00\",\"description\":\"Scheduling poll for a team lunch\",\"invitees\":[],\"location\":\"Office Cafeteria\",\"options\":[{\"end\":\"2026-04-10T13:00:00-05:00\",\"start\":\"2026-04-10T12:00:00-05:00\"},{\"end\":\"2026-04-11T13:00:00-05:00\",\"start\":\"2026-04-11T12:00:00-05:00\"}],\"title\":\"Team Lunch\"}",
      "call_id": "call_uallF71f2THNYsEvZUubSUhQ",
      "name": "timergy__create_poll",
      "status": "completed",
      "type": "function_call"
    },
    {
      "call_id": "call_uallF71f2THNYsEvZUubSUhQ",
      "output": "{\n  \"pollId\": \"fdc8110b-274d-45b4-b791-0149f6cfc4bc\",\n  \"title\": \"Team Lunch\",\n  \"url\": \"https://timergy.com/en/polls/fdc8110b-274d-45b4-b791-0149f6cfc4bc\",\n  \"passphrase\": \"horse-sword-thumb\",\n  \"options\": [\n    {\n      \"id\": \"c8879755-9136-497d-aedc-81b50fafbb13\",\n      \"start\": \"2026-04-10T17:00:00.000Z\",\n      \"end\": \"2026-04-10T18:00:00.000Z\",\n      \"label\": null\n    },\n    {\n      \"id\": \"58c474c6-12b4-42d5-a96e-c6c977d8a3b2\",\n      \"start\": \"2026-04-11T17:00:00.000Z\",\n      \"end\": \"2026-04-11T18:00:00.000Z\",\n      \"label\": null\n    }\n  ],\n  \"expiresAt\": \"2026-04-21T18:00:00.000Z\",\n  \"autoFinalize\": false,\n  \"inviteesSent\": 0,\n  \"note\": \"Share the URL with participants. The passphrase is saved for finalization. Assistant for Team's \\\"yes\\\" votes have been auto-submitted.\"\n}",
      "status": "completed",
      "type": "function_call_output"
    },
    {
      "content": [
        {
          "annotations": [],
          "logprobs": [],
          "text": "The scheduling poll \"Team Lunch\" has been created. You can share the following URL with participants to vote:\n\n**Poll URL:** [Team Lunch Poll](https://timergy.com/en/polls/fdc8110b-274d-45b4-b791-0149f6cfc4bc)\n\nFor admin access and to finalize the poll, you can use the passphrase:\n\n**Passphrase:** `horse-sword-thumb`\n\nThe poll includes two time slot options:\n- April 10, 2026, from 12:00 PM to 1:00 PM (local time)\n- April 11, 2026, from 12:00 PM to 1:00 PM (local time)",
          "type": "output_text"
        }
      ],
...
  "tool_choice": "auto",
  "tools": [
    {
      "type": "mcp",
      "server_label": "timergy",
      "server_url": "https://api.timergy.com/mcp"
    }
  ],
...
  }
}

Supported Anthropic and OpenAI Tools

Tool search enables searching and loading of tools on demand in the model’s context in agentic workflows. This allows you to avoid loading all tool definitions up front and can reduce overall token usage and cost. Use the passthrough tool search tool on the Messages API for Anthropic models and the Responses API for OpenAI models.

Include a tool search tool by either using regex or BM25 as the type in your tools array:

  • Regex (tool_search_tool_regex_20251119): Allows Claude to construct regex patterns to search for tools using Python re.search() syntax.
  • BM25 (tool_search_tool_bm25_20251119): Allows Claude to use natural language queries to search for tools.

Then, set defer_loading: true on tools that should not load immediately. The model calls the tool search tool when it needs those tools. Both tool search variants search tool names, descriptions, argument names, and argument descriptions. Note the following about tool search:

  • The tool search tool itself must not have "defer_loading": true.
  • Tools without defer_loading load into context immediately while tools with "defer_loading": true load only when Claude discovers them through search.
  • For best performance, keep your 3-5 most frequently used tools non-deferred.

The following example sends a Messages API request with regex tool search enabled.

import os
from pydo import Client

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

resp = client.messages.create(
    model="anthropic-claude-opus-4.8",
    max_tokens=2048,
    messages=[
        {"role": "user", "content": "What is the weather in zip code 94107?"},
    ],
    tools=[
        {
            "type": "tool_search_tool_regex_20251119",
            "name": "tool_search_tool_regex",
        },
        {
            "name": "get_weather_by_zip",
            "description": "Return current weather conditions for a US zip code.",
            "input_schema": {
                "type": "object",
                "properties": {
                    "zip_code": {"type": "string"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                },
                "required": ["zip_code"],
            },
            "defer_loading": True,
        },
        {
            "name": "search_files",
            "description": "Search through files in the workspace",
            "input_schema": {
                "type": "object",
                "properties": {
                    "query": {"type": "string"},
                    "file_types": {"type": "array", "items": {"type": "string"}},
                },
                "required": ["query"],
            },
            "defer_loading": True,
        },
    ],
)

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.8",
    max_tokens: 2048,
    messages: [
        { role: "user", content: "What is the weather in zip code 94107?" },
    ],
    tools: [
        {
            type: "tool_search_tool_regex_20251119",
            name: "tool_search_tool_regex",
        },
        {
            name: "get_weather_by_zip",
            description: "Return current weather conditions for a US zip code.",
            input_schema: {
                type: "object",
                properties: {
                    zip_code: { type: "string" },
                    unit: { type: "string", enum: ["celsius", "fahrenheit"] },
                },
                required: ["zip_code"],
            },
            defer_loading: true,
        },
        {
            name: "search_files",
            description: "Search through files in the workspace",
            input_schema: {
                type: "object",
                properties: {
                    query: { type: "string" },
                    file_types: { type: "array", items: { type: "string" } },
                },
                required: ["query"],
            },
            defer_loading: true,
        },
    ],
});

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.8",
    "max_tokens": 2048,
    "messages": [
      {
        "role": "user",
        "content": "What is the weather in zip code 94107?"
      }
    ],
    "tools": [
      {
        "type": "tool_search_tool_regex_20251119",
        "name": "tool_search_tool_regex"
      },
      {
        "name": "get_weather_by_zip",
        "description": "Return current weather conditions for a US zip code.",
        "input_schema": {
          "type": "object",
          "properties": {
            "zip_code": {"type": "string"},
            "unit": {
              "type": "string",
              "enum": ["celsius", "fahrenheit"]
            }
          },
          "required": ["zip_code"]
        },
        "defer_loading": true
      },
      {
        "name": "search_files",
        "description": "Search through files in the workspace",
        "input_schema": {
          "type": "object",
          "properties": {
            "query": {"type": "string"},
            "file_types": {
              "type": "array",
              "items": {"type": "string"}
            }
          },
          "required": ["query"]
        },
        "defer_loading": true
      }
    ]
  }'

The response includes additional block types before any client tool call:

  • server_tool_use: Indicates that Claude is calling the tool search tool.
  • tool_search_tool_result: Contains search results with a nested tool_search_tool_search_result object.
  • tool_use: Claude calling a discovered tool.
  • tool_references: Points to discovered tools.

The response looks similar to the following:

{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "I'll search for tools to help with the weather information."
    },
    {
      "type": "server_tool_use",
      "id": "srvtoolu_01ABC123",
      "name": "tool_search_tool_regex",
      "input": {
        "query": "weather"
      }
    },
    {
      "type": "tool_search_tool_result",
      "tool_use_id": "srvtoolu_01ABC123",
      "content": {
        "type": "tool_search_tool_search_result",
        "tool_references": [{ "type": "tool_reference", "tool_name": "get_weather_by_zip" }]
      }
    },
    {
      "type": "text",
      "text": "I found a weather tool. Let me get the weather for zip code 94107."
    },
    {
      "type": "tool_use",
      "id": "toolu_01XYZ789",
      "name": "get_weather_by_zip",
      "input": { "zip_code": "94107", "unit": "fahrenheit" }
    }
  ],
  "stop_reason": "tool_use"
}

Tool search tool usage is tracked in the usage object in the response:

{
  "usage": {
    "input_tokens": 1024,
    "output_tokens": 256,
    "server_tool_use": {
      "tool_search_requests": 2
    }
  }
}

For more information on how to use tool search with MCP integration and best practices, see the Anthropic tool search documentation.

Only GPT-5.4 and later models support tool search. To enable tool search, add a tool object with "type": "tool_search" to the tools array. Then, mark tools to defer with "defer_loading": true. The following example sends a Responses API request with hosted tool search enabled.

import os
from pydo import Client

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

resp = client.responses.create(
    model="openai-gpt-5.5",
    input="Compare the current weather in zip code 94107 and 10001.",
    tools=[
        {
            "type": "namespace",
            "name": "weather",
            "description": "Weather lookup tools for US zip codes.",
            "tools": [
                {
                    "type": "function",
                    "name": "get_weather_by_zip",
                    "description": "Return current weather conditions for a US zip code.",
                    "defer_loading": True,
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "zip_code": {"type": "string"},
                        },
                        "required": ["zip_code"],
                        "additionalProperties": False,
                    },
                }
            ],
        },
        {"type": "tool_search"},
    ],
    parallel_tool_calls=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.5",
    input: "Compare the current weather in zip code 94107 and 10001.",
    tools: [
        {
            type: "namespace",
            name: "weather",
            description: "Weather lookup tools for US zip codes.",
            tools: [
                {
                    type: "function",
                    name: "get_weather_by_zip",
                    description: "Return current weather conditions for a US zip code.",
                    defer_loading: true,
                    parameters: {
                        type: "object",
                        properties: {
                            zip_code: { type: "string" },
                        },
                        required: ["zip_code"],
                        additionalProperties: false,
                    },
                },
            ],
        },
        { type: "tool_search" },
    ],
    parallel_tool_calls: 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.5",
    "input": "Compare the current weather in zip code 94107 and 10001.",
    "tools": [
      {
        "type": "namespace",
        "name": "weather",
        "description": "Weather lookup tools for US zip codes.",
        "tools": [
          {
            "type": "function",
            "name": "get_weather_by_zip",
            "description": "Return current weather conditions for a US zip code.",
            "defer_loading": true,
            "parameters": {
              "type": "object",
              "properties": {
                "zip_code": { "type": "string" }
              },
              "required": ["zip_code"],
              "additionalProperties": false
            }
          }
        ]
      },
      {
        "type": "tool_search"
      }
    ],
    "parallel_tool_calls": false
  }'

For MCP servers, set defer_loading: true on the MCP server tool definition (or on individual tools within the server). For maximum token savings, group deferred functions into namespaces or MCP servers with clear, high-level descriptions so that the model can effectively search and load only the relevant functions. For other best practices, see the OpenAI tool search documentation.

If the model needs a deferred tool, the response includes two additional output items before the eventual function call: tool_search_call which records the hosted search step, and tool_search_output, which contains the loaded subset that becomes callable. The response looks similar to the following:

[
  {
    "type": "tool_search_call",
    "execution": "server",
    "call_id": null,
    "status": "completed",
    "arguments": {
      "paths": ["weather"]
    }
  },
  {
    "type": "tool_search_output",
    "execution": "server",
    "call_id": null,
    "status": "completed",
    "tools": [
  ....
  },
  {
    "type": "function_call",
    "name": "get_weather_by_zip",
    "namespace": "weather",
    "call_id": "call_abc123",
    "arguments": "{\"zip_code\":\"94107\"}"
  }
]

Computer Use

With the computer use tool, you can interact with computer environments for autonomous desktop interaction such as screenshots, mouse and keyboard control, and desktop automation. You can use the computer use tool in combination with other tools such as bash and text editor for more comprehensive automation workflows.

Add the computer use tool to the model using the Messages API. The tool requires the anthropic-beta: computer-use-2025-11-24 header. Set display_width_px and display_height_px to match the resolution of the environment the model controls. The following example sends a Messages API request with the computer use tool enabled:

import os
from pydo import Client

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

resp = client.messages.create(
    model="anthropic-claude-opus-4.8",
    max_tokens=1024,
    tools=[
        {
            "type": "computer_20251124",
            "name": "computer",
            "display_width_px": 1024,
            "display_height_px": 768,
            "display_number": 1,
        }
    ],
    messages=[
        {"role": "user", "content": "Save a picture of a cat to my desktop."}
    ],
    headers={"anthropic-beta": "computer-use-2025-11-24"},
)

print(resp)
curl -X POST https://inference.do-ai.run/v1/messages \
  -H "Authorization: Bearer $MODEL_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -H "anthropic-beta: computer-use-2025-11-24" \
  -d '{
    "model": "anthropic-claude-opus-4.8",
    "max_tokens": 1024,
    "tools": [
      {
        "type": "computer_20251124",
        "name": "computer",
        "display_width_px": 1024,
        "display_height_px": 768,
        "display_number": 1
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "Save a picture of a cat to my desktop."
      }
    ]
  }'

Computer use runs as an agent loop. The model does not control the environment directly. Instead, it returns a tool_use block with an action such as screenshot, left_click, or type, and your application runs that action in a sandboxed environment (such as a virtual machine or container). Your application then returns the result, often a new screenshot, in a tool_result block and continues the conversation. The model evaluates the result and either requests another action or returns a final response when the task is complete.

Because the model can control a real environment, run computer use only in an isolated, low-privilege sandbox, keep sensitive data and credentials out of reach, and require human confirmation for consequential actions. For the full set of actions, response handling, and security guidance, see the Anthropic computer use tool documentation.

Provide the computer use tool to the model using the Responses API. Add a tool object with "type": "computer" to the tools array and then describe the task in plain language. The following example sends a Responses API request with the computer use tool enabled:

import os
from pydo import Client

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

resp = client.responses.create(
    model="openai-gpt-5.5",
    input="Check whether the Filters panel is open. If it is not open, click Show filters. Then type penguin in the search box. Use the computer tool for UI interaction.",
    tools=[
        {"type": "computer"}
    ],
)

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.5",
    input: "Check whether the Filters panel is open. If it is not open, click Show filters. Then type penguin in the search box. Use the computer tool for UI interaction.",
    tools: [
        { type: "computer" },
    ],
});

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.5",
    "input": "Check whether the Filters panel is open. If it is not open, click Show filters. Then type penguin in the search box. Use the computer tool for UI interaction.",
    "tools": [
      {
        "type": "computer"
      }
    ]
  }'

Computer use runs as a built-in loop that your harness drives. Inspect the returned computer_call and run every action in its actions[] array, in order. The first turn often requests a screenshot before the model commits to UI actions. Then, capture the updated screen and send it back as a computer_call_output item that references the call_id. Repeat until the model stops returning computer_call items and returns a final response.

Because the model can control a real environment, run computer use only in an isolated, low-privilege sandbox (such as a dedicated browser or container), keep an allowlist of permitted domains and actions, and require human confirmation for purchases, authenticated flows, and other consequential actions. For the full action set, screenshot handling, and security guidance, see the OpenAI computer use tool documentation.

Local Shell/Bash

Use the local shell tool to execute shell commands in a persistent session, allowing system operations, script execution, access to environment variables, and command-line automation. Use the bash tool with the Messages API for Anthropic models and the local shell tool with the Responses API for OpenAI models:

Provide the bash tool to the model using the Messages API. Use the bash_20250124 tool type with the name bash. The following example sends a Messages API request with the bash tool enabled:

import os
from pydo import Client

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

resp = client.messages.create(
    model="anthropic-claude-opus-4.8",
    max_tokens=1024,
    tools=[
        {"type": "bash_20250124", "name": "bash"}
    ],
    messages=[
        {"role": "user", "content": "List all Python files in the current directory."}
    ],
)

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.8",
    max_tokens: 1024,
    tools: [
        { type: "bash_20250124", name: "bash" },
    ],
    messages: [
        { role: "user", content: "List all Python files in the current directory." },
    ],
});

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.8",
    "max_tokens": 1024,
    "tools": [
      {
        "type": "bash_20250124",
        "name": "bash"
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "List all Python files in the current directory."
      }
    ]
  }'

The bash tool runs as an agent loop against a persistent session that your application maintains. The model returns a tool_use block with a command to run (for example, ls -la *.py), your application runs that command in a bash shell and returns the combined stdout and stderr in a tool_result block, and the conversation continues. Session state, such as the working directory and environment variables, persists between commands, so the model can chain steps like installing a package, writing a script, and running it. To reset the session, the model can send {"restart": true} instead of a command.

The bash tool provides direct system access, so run it only in an isolated environment (such as a container or virtual machine), restrict commands with an allowlist, set resource limits, run with minimal permissions, and log every command. For the full parameter set, response handling, and security guidance, see the Anthropic bash tool documentation.

Provide the shell tool to the model using the Responses API. Add a tool object with "type": "shell" to the tools array and set environment to local to run commands in your own runtime. The following example sends a Responses API request with the shell tool enabled for local execution:

import os
from pydo import Client

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

resp = client.responses.create(
    model="openai-gpt-5.5",
    instructions="The local bash shell environment is on Linux.",
    input="List all Python files in the current directory.",
    tools=[
        {
            "type": "shell",
            "environment": {
                "type": "local",
            },
        }
    ],
)

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.5",
    instructions: "The local bash shell environment is on Linux.",
    input: "List all Python files in the current directory.",
    tools: [
        {
            type: "shell",
            environment: {
                type: "local",
            },
        },
    ],
});

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.5",
    "instructions": "The local bash shell environment is on Linux.",
    "input": "List all Python files in the current directory.",
    "tools": [
      {
        "type": "shell",
        "environment": {
          "type": "local"
        }
      }
    ]
  }'

For the full parameter set and response handling, see the OpenAI shell tool documentation.

Web Fetch

(For Anthropic models) Using an Anthropic-schema web fetch tool, the model can retrieve the full content of specific web pages and PDF documents to augment its context with live web content. The model fetches and reads the URL within a single request instead of running a multi-step agent loop.

Provide the web fetch tool to the model using the Messages API. Use the web_fetch_20250910 tool type with the name web_fetch. Optionally set max_uses to cap the number of fetches per request and allowed_domains or blocked_domains to restrict which sites the model can fetch. The following example sends a Messages API request with the web fetch tool enabled:

import os
from pydo import Client

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

resp = client.messages.create(
    model="anthropic-claude-opus-4.8",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "Please analyze the content at https://docs.digitalocean.com/products/inference/",
        }
    ],
    tools=[
        {
            "type": "web_fetch_20250910",
            "name": "web_fetch",
            "max_uses": 5,
        }
    ],
)

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.8",
    max_tokens: 1024,
    messages: [
        {
            role: "user",
            content: "Please analyze the content at https://docs.digitalocean.com/products/inference/",
        },
    ],
    tools: [
        {
            type: "web_fetch_20250910",
            name: "web_fetch",
            max_uses: 5,
        },
    ],
});

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.8",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "user",
        "content": "Please analyze the content at https://docs.digitalocean.com/products/inference/"
      }
    ],
    "tools": [
      {
        "type": "web_fetch_20250910",
        "name": "web_fetch",
        "max_uses": 5
      }
    ]
  }'

The response includes additional block types before the model’s final answer:

  • server_tool_use: Indicates that the model is fetching a URL.
  • web_fetch_tool_result: Contains the fetched page as a web_fetch_result object with a document block.

The response looks similar to the following:

{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "I'll fetch the content from the page to analyze it."
    },
    {
      "type": "server_tool_use",
      "id": "srvtoolu_01234567890abcdef",
      "name": "web_fetch",
      "input": {
        "url": "https://docs.digitalocean.com/products/inference/"
      }
    },
    {
      "type": "web_fetch_tool_result",
      "tool_use_id": "srvtoolu_01234567890abcdef",
      "content": {
        "type": "web_fetch_result",
        "url": "https://docs.digitalocean.com/products/inference/",
        "content": {
          "type": "document",
          "source": {
            "type": "text",
            "media_type": "text/plain",
            "data": "DigitalOcean Inference provides serverless and dedicated access to foundation models..."
          },
          "title": "Inference | DigitalOcean Documentation"
        },
        "retrieved_at": "2025-08-25T10:30:00Z"
      }
    },
    {
      "type": "text",
      "text": "Based on the documentation, DigitalOcean Inference is a managed AI platform that provides access to foundation models through serverless and dedicated endpoints..."
    }
  ],
  ....
  }
}

For PDF documents, the document block uses base64-encoded data in source.data instead of plain text. Web fetch usage is tracked in usage.server_tool_use.web_fetch_requests.

The model decides when to fetch based on the prompt and the URLs available in the conversation. For security, the model can only fetch URLs that already appear in the conversation, such as a URL in a user message or one returned by a previous web search or web fetch result. The model then analyzes the fetched content and returns its answer, with optional citations when you set "citations": {"enabled": true} on the tool.

Because the model processes external web content, enable web fetch only in trusted environments or when handling non-sensitive data, and use max_uses, allowed_domains, and max_content_tokens to limit exposure and token usage. For the full parameter set, response handling, and security guidance, see the Anthropic web fetch tool documentation.

Code Editing

Both Anthropic and OpenAI models can edit files in your codebase. Anthropic models use the text editor tool with the Messages API, and OpenAI models use the apply patch tool with the Responses API:

Using an Anthropic-schema text editor tool, you can directly view and modify text files, and interact with them to debug, refactor, and write tests to improve your code or other text documents.

Provide the text editor tool (named str_replace_based_edit_tool) to the model using the Messages API. Use the text_editor_20250728 tool type, and optionally set max_characters to control truncation when the model views large files. The following example sends a Messages API request with the text editor tool enabled:

import os
from pydo import Client

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

resp = client.messages.create(
    model="anthropic-claude-opus-4.8",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "There's a syntax error in my primes.py file. Can you help me fix it?",
        }
    ],
    tools=[
        {
            "type": "text_editor_20250728",
            "name": "str_replace_based_edit_tool",
            "max_characters": 10000,
        }
    ],
)

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.8",
    max_tokens: 1024,
    messages: [
        {
            role: "user",
            content: "There's a syntax error in my primes.py file. Can you help me fix it?",
        },
    ],
    tools: [
        {
            type: "text_editor_20250728",
            name: "str_replace_based_edit_tool",
            max_characters: 10000,
        },
    ],
});

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.8",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "user",
        "content": "There'\''s a syntax error in my primes.py file. Can you help me fix it?"
      }
    ],
    "tools": [
      {
        "type": "text_editor_20250728",
        "name": "str_replace_based_edit_tool",
        "max_characters": 10000
      }
    ]
  }'

The model first responds with a tool_use block containing a view command to examine the file. Your application reads the file, returns its contents in a tool_result block, and continues the conversation. The model then issues commands such as str_replace, insert, or create to make edits. For the full set of commands and the request and response flow, see the Anthropic text editor tool documentation.

Using the apply patch tool, you can create, update (refactor, fix bugs, test files), and delete files in your codebase using structured diffs. The model emits patch operations that your application applies and then reports back on, enabling iterative, multi-step code editing workflows.

Provide the apply patch tool to the model using the Responses API. Add a tool object with "type": "apply_patch" to the tools array and give the model context about the relevant files in your input (or provide tools for exploring the file system). The following example sends a Responses API request with the apply patch tool enabled:

import os
from pydo import Client

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

resp = client.responses.create(
    model="openai-gpt-5.5",
    input="The file lib/fib.py defines a function fib(n). Rename the fib() function to fibonacci() and update any references.",
    tools=[
        {"type": "apply_patch"}
    ],
)

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.5",
    input: "The file lib/fib.py defines a function fib(n). Rename the fib() function to fibonacci() and update any references.",
    tools: [
        { type: "apply_patch" },
    ],
});

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.5",
    "input": "The file lib/fib.py defines a function fib(n). Rename the fib() function to fibonacci() and update any references.",
    "tools": [
      {
        "type": "apply_patch"
      }
    ]
  }'

The apply patch tool runs as an agent loop that your application maintains. The model returns one or more apply_patch_call output items, each describing a single file operation (create_file, update_file, or delete_file) with a diff and path. Your application applies each patch in its working directory, then sends the result back as an apply_patch_call_output item that references the call_id, with a status of completed or failed and an optional output string. Pass the results back using previous_response_id (or by including the items in input) and keep the apply patch tool enabled so the model can continue editing or explain its changes. If a patch fails, set status to failed and include a helpful output message so the model can recover.

The apply patch tool modifies files in your codebase, so apply patches only in an isolated working directory or version-controlled repository, review the diffs before applying them, and keep a human in the loop for consequential changes. For the full operation set and response handling, see the OpenAI apply patch tool documentation.

Function (Tool) Calling

Using function calling, models can interface with external systems and access data outside their training data. Unlike the hosted server-side tools on this page, function calling is client-side: you define your own functions, the model decides when to call them and returns the arguments. Your application runs the function and returns the result. Anthropic models define functions with the Messages API, and OpenAI models define functions with the Responses API:

Define each function in the tools array with a name, description, and input_schema to describe its parameters. The following example sends a Messages API request with a single get_weather function defined:

import os
from pydo import Client

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

resp = client.messages.create(
    model="anthropic-claude-opus-4.8",
    max_tokens=1024,
    tools=[
        {
            "name": "get_weather",
            "description": "Get the current weather for a location.",
            "input_schema": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, for example San Francisco, CA",
                    }
                },
                "required": ["location"],
            },
        }
    ],
    messages=[
        {"role": "user", "content": "What is the weather in San Francisco?"}
    ],
)

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.8",
    max_tokens: 1024,
    tools: [
        {
            name: "get_weather",
            description: "Get the current weather for a location.",
            input_schema: {
                type: "object",
                properties: {
                    location: {
                        type: "string",
                        description: "The city and state, for example San Francisco, CA",
                    },
                },
                required: ["location"],
            },
        },
    ],
    messages: [
        { role: "user", content: "What is the weather in San Francisco?" },
    ],
});

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.8",
    "max_tokens": 1024,
    "tools": [
      {
        "name": "get_weather",
        "description": "Get the current weather for a location.",
        "input_schema": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The city and state, for example San Francisco, CA"
            }
          },
          "required": ["location"]
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "What is the weather in San Francisco?"
      }
    ]
  }'

When the model decides to call a function, it returns a tool_use block with the function name and an input object containing the arguments. Your application runs the function, then continues the conversation by sending a tool_result block that references the tool_use_id and contains the function output. The model uses that result to produce its final response. For the full request and response flow, see the Anthropic tool use documentation.

Define each function in the tools array with "type": "function", name, description, and parameters JSON schema. The following example sends a Responses API request with a single get_horoscope function defined:

import os
from pydo import Client

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

resp = client.responses.create(
    model="openai-gpt-5.5",
    input="What is my horoscope? I am an Aquarius.",
    tools=[
        {
            "type": "function",
            "name": "get_horoscope",
            "description": "Get today's horoscope for an astrological sign.",
            "parameters": {
                "type": "object",
                "properties": {
                    "sign": {
                        "type": "string",
                        "description": "An astrological sign like Taurus or Aquarius",
                    }
                },
                "required": ["sign"],
            },
        }
    ],
)

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.5",
    input: "What is my horoscope? I am an Aquarius.",
    tools: [
        {
            type: "function",
            name: "get_horoscope",
            description: "Get today's horoscope for an astrological sign.",
            parameters: {
                type: "object",
                properties: {
                    sign: {
                        type: "string",
                        description: "An astrological sign like Taurus or Aquarius",
                    },
                },
                required: ["sign"],
            },
        },
    ],
});

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.5",
    "input": "What is my horoscope? I am an Aquarius.",
    "tools": [
      {
        "type": "function",
        "name": "get_horoscope",
        "description": "Get today'\''s horoscope for an astrological sign.",
        "parameters": {
          "type": "object",
          "properties": {
            "sign": {
              "type": "string",
              "description": "An astrological sign like Taurus or Aquarius"
            }
          },
          "required": ["sign"]
        }
      }
    ]
  }'

When the model decides to call a function, it returns a function_call output item with the function name, a call_id, and an arguments JSON string. Your application runs the function, then sends the result back as a function_call_output item that references the call_id (using previous_response_id or by including the items in input). The model uses that result to produce its final response. For the full request and response flow, see the OpenAI function calling documentation.

We can't find any results for your search.

Try using different keywords or simplifying your search terms.