[metadata]
apple-mobile-web-app-title: OpenRouter | Documentation
application-name: OpenRouter | Documentation
description: Use tools in your prompts
generator: Mintlify
msapplication-TileColor: #7624F4
msapplication-config: /docs/_mintlify/favicons/openrouter-d02e98a0/EmhfYwFO2tvnkuV-/_generated/favicon/browserconfig.xml
og:description: Use tools (or functions) in your prompts with OpenRouter. Learn how to use tools with OpenAI, Anthropic, and other models that support tool calling.
og:image: https://openrouter.ai/dynamic-og?title=Tool%20&%20Function%20Calling&description=Use%20tools%20with%20OpenRouter
og:image:height: 630
og:image:width: 1200
og:site_name: OpenRouter Documentation
og:title: Tool & Function Calling - Use Tools with OpenRouter
og:type: website
og:url: https://openrouter.ai/docs/guides/features/tool-calling
twitter:card: summary_large_image
twitter:description: Use tools (or functions) in your prompts with OpenRouter. Learn how to use tools with OpenAI, Anthropic, and other models that support tool calling.
twitter:image: https://openrouter.ai/dynamic-og?title=Tool%20&%20Function%20Calling&description=Use%20tools%20with%20OpenRouter
twitter:image:height: 630
twitter:image:width: 1200
twitter:title: Tool & Function Calling - Use Tools with OpenRouter
viewport: width=device-width, initial-scale=1, viewport-fit=cover

[canonical-links]
https://openrouter.ai/docs/guides/features/tool-calling

[document-links]
/docs/llms.txt: /docs/llms.txt
API Reference: /docs/api_reference/overview
Agent SDK: /docs/agent-sdk/overview
Anthropic Agent SDK: /docs/guides/community/anthropic-agent-sdk
App Attribution: /docs/app-attribution
Apps: https://openrouter.ai/apps
Arize AX: /docs/guides/community/arize
Auto Exacto: /docs/guides/routing/auto-exacto
Awesome OpenRouter: /docs/guides/community/awesome-openrouter
Batch Beta: /docs/batch-quickstart
Benchmarks: https://openrouter.ai/benchmarks
Chat: https://openrouter.ai/chat
Client SDKs: /docs/client-sdks/overview
Cookbook: /docs/cookbook/get-started/quickstart
Custom Classifiers: /docs/guides/features/classifiers
Data Collection: /docs/guides/privacy/data-collection
Docs: /docs/quickstart
Docs: https://openrouter.ai/docs
Effect AI SDK: /docs/guides/community/effect-ai-sdk
FAQ: /docs/faq
For Providers: /docs/guides/community/for-providers
Frameworks and Integrations Overview: /docs/guides/community/frameworks-and-integrations-overview
How Tool-Calling Success Rate Is Measured: /docs/guides/routing/auto-exacto#how-tool-calling-success-rate-is-measured
Infisical: /docs/guides/community/infisical
Input & Output Logging: /docs/guides/features/input-output-logging
LangChain: /docs/guides/community/langchain
Langfuse: /docs/guides/community/langfuse
Latency and Performance: /docs/guides/best-practices/latency-and-performance
LiveKit: /docs/guides/community/livekit
MCP: /docs/guides/overview/mcp-server
Mastra: /docs/guides/community/mastra
Message Transforms: /docs/guides/features/message-transforms
Model Fallbacks: /docs/guides/routing/model-fallbacks
Models: /docs/guides/overview/models
Models: https://openrouter.ai/models
OpenAI SDK: /docs/guides/community/openai-sdk
OpenRouter | Documentation home page: https://openrouter.ai
Ori Eval: /docs/guides/ori/eval
Ori Harness: /docs/guides/ori/harness
Overview: /docs/guides/features/server-tools
Presets: /docs/guides/features/presets
Principles: /docs/guides/overview/principles
Private Models: /docs/guides/routing/private-models
Prompt Caching: /docs/guides/best-practices/prompt-caching
Provider Logging: /docs/guides/privacy/provider-logging
Provider Selection: /docs/guides/routing/provider-selection
PydanticAI: /docs/guides/community/pydantic-ai
Quickstart: /docs/quickstart
Rankings: https://openrouter.ai/rankings
Reasoning Tokens: /docs/guides/best-practices/reasoning-tokens
Render: /docs/guides/community/render
Replit: /docs/guides/community/replit
Report Feedback: /docs/guides/overview/report-feedback
Response Caching: /docs/guides/features/response-caching
Router Metadata: /docs/guides/features/router-metadata
SCIM Group Mappings: /docs/guides/features/scim-mappings
Service Tiers: /docs/guides/features/service-tiers
Single Sign-On (SSO): /docs/guides/features/sso
Sovereign AI: /docs/guides/features/sovereign-ai
Stripe Projects: /docs/guides/overview/stripe-projects
Structured Outputs: /docs/guides/features/structured-outputs
Switching Workspaces: /docs/guides/features/workspaces/switching
TanStack AI: /docs/guides/community/tanstack-ai
Tool Calling: /docs/guides/features/tool-calling
Uptime Optimization: /docs/guides/best-practices/uptime-optimization
Vercel AI SDK: /docs/guides/community/vercel-ai-sdk
Where Ori writes files: /docs/guides/ori/files
Workspace Budgets: /docs/guides/features/workspaces/workspace-budgets
Workspaces: /docs/guides/features/workspaces
Xcode: /docs/guides/community/xcode
ZDR: /docs/guides/features/zdr
Zapier: /docs/guides/community/zapier
Zero Completion Insurance: /docs/guides/features/zero-completion-insurance
openrouter.ai/models?supported_parameters=tools: https://openrouter.ai/models?supported_parameters=tools

[structured-data]
{"@context":"https://schema.org","@graph":[{"@id":"https://openrouter.ai/#organization","@type":"Organization","logo":{"@type":"ImageObject","url":"https://mintcdn.com/openrouter-d02e98a0/ksNSeB_K7gD-BUDh/assets/logo-v2-light.svg?fit=max&auto=format&n=ksNSeB_K7gD-BUDh&q=85&s=690e45873843519efe02bcbe45795dac"},"name":"OpenRouter | Documentation","url":"https://openrouter.ai"},{"@id":"https://openrouter.ai/docs#website","@type":"WebSite","name":"OpenRouter | Documentation","publisher":{"@id":"https://openrouter.ai/#organization"},"url":"https://openrouter.ai/docs"},{"@id":"https://openrouter.ai/docs/guides/features/tool-calling#webpage","@type":"WebPage","breadcrumb":{"@id":"https://openrouter.ai/docs/guides/features/tool-calling#breadcrumb"},"dateModified":"2026-07-14T17:19:40.439Z","description":"Use tools in your prompts","isPartOf":{"@id":"https://openrouter.ai/docs#website"},"name":"Tool & Function Calling","url":"https://openrouter.ai/docs/guides/features/tool-calling"},{"@id":"https://openrouter.ai/docs/guides/features/tool-calling#breadcrumb","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","item":"https://openrouter.ai/docs/guides/features/workspaces","name":"Features","position":1},{"@type":"ListItem","item":"https://openrouter.ai/docs/guides/features/tool-calling","name":"Tool & Function Calling","position":2}]},{"@id":"https://openrouter.ai/docs/guides/features/tool-calling#article","@type":["Article","TechArticle"],"dateModified":"2026-07-14T17:19:40.439Z","description":"Use tools in your prompts","headline":"Tool & Function Calling","image":"https://openrouter.ai/dynamic-og?title=Tool%20&%20Function%20Calling&description=Use%20tools%20with%20OpenRouter","isPartOf":{"@id":"https://openrouter.ai/docs#website"},"mainEntityOfPage":{"@id":"https://openrouter.ai/docs/guides/features/tool-calling#webpage"},"name":"Tool & Function Calling","publisher":{"@id":"https://openrouter.ai/#organization"},"url":"https://openrouter.ai/docs/guides/features/tool-calling"}]}

[content]
Tool & Function Calling - Use Tools with OpenRouter
Documentation Index
Fetch the complete documentation index at:
/docs/llms.txt
Use this file to discover all available pages before exploring further.
Skip to main content
OpenRouter | Documentation
home page
Search...
⌘
K
Ask Assistant
Models
Benchmarks
Chat
Rankings
Apps
Docs
Search...
Navigation
Features
Tool & Function Calling
Docs
API Reference
Client SDKs
Agent SDK
Cookbook
Overview
Quickstart
Batch
Beta
Principles
Models
MCP
Multimodal
Authentication
Stripe Projects
FAQ
Report Feedback
Models & Routing
Model Fallbacks
Provider Selection
Auto Exacto
Private Models
Model Variants
Routers
Features
Workspaces
Workspace Budgets
Switching Workspaces
Single Sign-On (SSO)
SCIM Group Mappings
Presets
Custom Classifiers
Response Caching
Tool Calling
Server Tools
Plugins
Structured Outputs
Message Transforms
Zero Completion Insurance
ZDR
App Attribution
Guardrails
Service Tiers
Sovereign AI
Router Metadata
Input & Output Logging
Broadcast
Ori
Ori Eval
Ori Harness
Where Ori writes files
Privacy
Data Collection
Provider Logging
Best Practices
Latency and Performance
Prompt Caching
Uptime Optimization
Reasoning Tokens
Community
For Providers
Frameworks and Integrations Overview
Awesome OpenRouter
Effect AI SDK
Arize AX
LangChain
LiveKit
Langfuse
Mastra
OpenAI SDK
Anthropic Agent SDK
PydanticAI
Render
Replit
TanStack AI
Vercel AI SDK
Xcode
Zapier
Infisical
On this page
Request Body Examples
Step 1: Inference Request with Tools
Step 2: Tool Execution (Client-Side)
Step 3: Inference Request with Tool Results
Tool Calling Example
Define the Tool
Tool use and tool results
Interleaved Thinking
How Interleaved Thinking Works
Example: Multi-Step Research with Reasoning
Best Practices for Interleaved Thinking
Implementation Considerations
A Simple Agentic Loop
Best Practices and Advanced Patterns
Function Definition Guidelines
Streaming with Tool Calls
Tool Choice Configuration
Parallel Tool Calls
Multi-Tool Workflows
Reliability Tracking
Features
Tool & Function Calling
Copy page
Copy page
Use tools in your prompts
Copy page
Copy page
Tool calls (also known as function calls) give an LLM access to external tools. The LLM does not call the tools directly. Instead, it suggests the tool to call. The user then calls the tool separately and provides the results back to the LLM. Finally, the LLM formats the response into an answer to the user’s original question.
OpenRouter standardizes the tool calling interface across models and providers, making it easy to integrate external tools with any supported model.
Supported Models
: You can find models that support tool calling by filtering on
openrouter.ai/models?supported_parameters=tools
.
If you prefer to learn from a full end-to-end example, keep reading.
​
Request Body Examples
Tool calling with OpenRouter involves three key steps. Here are the essential request body formats for each step:
​
Step 1: Inference Request with Tools
{
"model"
:
"google/gemini-3-flash-preview"
,
"messages"
: [
{
"role"
:
"user"
,
"content"
:
"What are the titles of some James Joyce books?"
}
],
"tools"
: [
{
"type"
:
"function"
,
"function"
: {
"name"
:
"search_gutenberg_books"
,
"description"
:
"Search for books in the Project Gutenberg library"
,
"parameters"
: {
"type"
:
"object"
,
"properties"
: {
"search_terms"
: {
"type"
:
"array"
,
"items"
: {
"type"
:
"string"
},
"description"
:
"List of search terms to find books"
}
},
"required"
: [
"search_terms"
]
}
}
}
]
}
See all 29 lines
​
Step 2: Tool Execution (Client-Side)
After receiving the model’s response with
tool_calls
, execute the requested tool locally and prepare the result:
// Model responds with tool_calls, you execute the tool locally
const
toolResult
=
await
searchGutenbergBooks
([
"James"
,
"Joyce"
]);
​
Step 3: Inference Request with Tool Results
{
"model"
:
"google/gemini-3-flash-preview"
,
"messages"
: [
{
"role"
:
"user"
,
"content"
:
"What are the titles of some James Joyce books?"
},
{
"role"
:
"assistant"
,
"content"
:
null
,
"tool_calls"
: [
{
"id"
:
"call_abc123"
,
"type"
:
"function"
,
"function"
: {
"name"
:
"search_gutenberg_books"
,
"arguments"
:
"{
\"
search_terms
\"
: [
\"
James
\"
,
\"
Joyce
\"
]}"
}
}
]
},
{
"role"
:
"tool"
,
"tool_call_id"
:
"call_abc123"
,
"content"
:
"[{
\"
id
\"
: 4300,
\"
title
\"
:
\"
Ulysses
\"
,
\"
authors
\"
: [{
\"
name
\"
:
\"
Joyce, James
\"
}]}]"
}
],
"tools"
: [
{
"type"
:
"function"
,
"function"
: {
"name"
:
"search_gutenberg_books"
,
"description"
:
"Search for books in the Project Gutenberg library"
,
"parameters"
: {
"type"
:
"object"
,
"properties"
: {
"search_terms"
: {
"type"
:
"array"
,
"items"
: {
"type"
:
"string"
},
"description"
:
"List of search terms to find books"
}
},
"required"
: [
"search_terms"
]
}
}
}
]
}
See all 48 lines
Note
: The
tools
parameter must be included in every request (Steps 1 and 3) so the router can validate the tool schema on each call.
​
Tool Calling Example
Here is Python code that gives LLMs the ability to call an external API — in this case Project Gutenberg, to search for books.
First, let’s do some basic setup:
​
Define the Tool
Next, we define the tool that we want to call. Remember, the tool is going to get
requested
by the LLM, but the code we are writing here is ultimately responsible for executing the call and returning the results to the LLM.
Note that the “tool” is just a normal function. We then write a JSON “spec” compatible with the OpenAI function calling parameter. We’ll pass that spec to the LLM so that it knows this tool is available and how to use it. It will request the tool when needed, along with any arguments. We’ll then marshal the tool call locally, make the function call, and return the results to the LLM.
​
Tool use and tool results
Let’s make the first OpenRouter API call to the model:
The LLM responds with a finish reason of
tool_calls
, and a
tool_calls
array. In a generic LLM response-handler, you would want to check the
finish_reason
before processing tool calls, but here we will assume it’s the case. Let’s keep going, by processing the tool call:
The messages array now has:
Our original request
The LLM’s response (containing a tool call request)
The result of the tool call (a json object returned from the Project Gutenberg API)
Now, we can make a second OpenRouter API call, and hopefully get our result!
The output will be something like:
Here are some books by James Joyce:
* *Ulysses*
* *Dubliners*
* *A Portrait of the Artist as a Young Man*
* *Chamber Music*
* *Exiles: A Play in Three Acts*
We did it! We’ve successfully used a tool in a prompt.
​
Interleaved Thinking
Interleaved thinking allows models to reason between tool calls, enabling more sophisticated decision-making after receiving tool results. This feature helps models chain multiple tool calls with reasoning steps in between and make nuanced decisions based on intermediate results.
Important
: Interleaved thinking increases token usage and response latency. Consider your budget and performance requirements when enabling this feature.
​
How Interleaved Thinking Works
With interleaved thinking, the model can:
Reason about the results of a tool call before deciding what to do next
Chain multiple tool calls with reasoning steps in between
Make more nuanced decisions based on intermediate results
Provide transparent reasoning for its tool selection process
​
Example: Multi-Step Research with Reasoning
Here’s an example showing how a model might use interleaved thinking to research a topic across multiple sources:
Initial Request:
{
"model"
:
"anthropic/claude-sonnet-4.5"
,
"messages"
: [
{
"role"
:
"user"
,
"content"
:
"Research the environmental impact of electric vehicles and provide a comprehensive analysis."
}
],
"tools"
: [
{
"type"
:
"function"
,
"function"
: {
"name"
:
"search_academic_papers"
,
"description"
:
"Search for academic papers on a given topic"
,
"parameters"
: {
"type"
:
"object"
,
"properties"
: {
"query"
: {
"type"
:
"string"
},
"field"
: {
"type"
:
"string"
}
},
"required"
: [
"query"
]
}
}
},
{
"type"
:
"function"
,
"function"
: {
"name"
:
"get_latest_statistics"
,
"description"
:
"Get latest statistics on a topic"
,
"parameters"
: {
"type"
:
"object"
,
"properties"
: {
"topic"
: {
"type"
:
"string"
},
"year"
: {
"type"
:
"integer"
}
},
"required"
: [
"topic"
]
}
}
}
]
}
See all 41 lines
Model’s Reasoning and Tool Calls:
Initial Thinking
: “I need to research electric vehicle environmental impact. Let me start with academic papers to get peer-reviewed research.”
First Tool Call
:
search_academic_papers({"query": "electric vehicle lifecycle environmental impact", "field": "environmental science"})
After First Tool Result
: “The papers show mixed results on manufacturing impact. I need current statistics to complement this academic research.”
Second Tool Call
:
get_latest_statistics({"topic": "electric vehicle carbon footprint", "year": 2024})
After Second Tool Result
: “Now I have both academic research and current data. Let me search for manufacturing-specific studies to address the gaps I found.”
Third Tool Call
:
search_academic_papers({"query": "electric vehicle battery manufacturing environmental cost", "field": "materials science"})
Final Analysis
: Synthesizes all gathered information into a comprehensive response.
​
Best Practices for Interleaved Thinking
Clear Tool Descriptions
: Provide detailed descriptions so the model can reason about when to use each tool
Structured Parameters
: Use well-defined parameter schemas to help the model make precise tool calls
Context Preservation
: Maintain conversation context across multiple tool interactions
Error Handling
: Design tools to provide meaningful error messages that help the model adjust its approach
​
Implementation Considerations
When implementing interleaved thinking:
Models may take longer to respond due to additional reasoning steps
Token usage will be higher due to the reasoning process
The quality of reasoning depends on the model’s capabilities
Some models may be better suited for this approach than others
​
A Simple Agentic Loop
In the example above, the calls are made explicitly and sequentially. To handle a wide variety of user inputs and tool calls, you can use an agentic loop.
Here’s an example of a simple agentic loop (using the same
tools
and initial
messages
as above):
​
Best Practices and Advanced Patterns
​
Function Definition Guidelines
When defining tools for LLMs, follow these best practices:
Clear and Descriptive Names
: Use descriptive function names that clearly indicate the tool’s purpose.
// Good: Clear and specific
{
"name"
:
"get_weather_forecast"
}
// Avoid: Too vague
{
"name"
:
"weather"
}
Comprehensive Descriptions
: Provide detailed descriptions that help the model understand when and how to use the tool.
{
"description"
:
"Get current weather conditions and 5-day forecast for a specific location. Supports cities, zip codes, and coordinates."
,
"parameters"
: {
"type"
:
"object"
,
"properties"
: {
"location"
: {
"type"
:
"string"
,
"description"
:
"City name, zip code, or coordinates (lat,lng). Examples: 'New York', '10001', '40.7128,-74.0060'"
},
"units"
: {
"type"
:
"string"
,
"enum"
: [
"celsius"
,
"fahrenheit"
],
"description"
:
"Temperature unit preference"
,
"default"
:
"celsius"
}
},
"required"
: [
"location"
]
}
}
​
Streaming with Tool Calls
When using streaming responses with tool calls, handle the different content types appropriately:
const
stream
=
await
fetch
(
'/api/chat/completions'
, {
method:
'POST'
,
headers:
{
'Content-Type'
:
'application/json'
},
body:
JSON
.
stringify
({
model:
'anthropic/claude-sonnet-4.5'
,
messages:
messages
,
tools:
tools
,
stream:
true
})
});
const
reader
=
stream
.
body
.
getReader
();
let
toolCalls
=
[];
while
(
true
) {
const
{
done
,
value
}
=
await
reader
.
read
();
if
(
done
) {
break
;
}
const
chunk
=
new
TextDecoder
().
decode
(
value
);
const
lines
=
chunk
.
split
(
'
\n
'
).
filter
(
line
=>
line
.
trim
());
for
(
const
line
of
lines
) {
if
(
line
.
startsWith
(
'data: '
)) {
const
data
=
JSON
.
parse
(
line
.
slice
(
6
));
if
(
data
.
choices
[
0
].
delta
.
tool_calls
) {
toolCalls
.
push
(
...
data
.
choices
[
0
].
delta
.
tool_calls
);
}
if
(
data
.
choices
[
0
].
delta
.
finish_reason
===
'tool_calls'
) {
await
handleToolCalls
(
toolCalls
);
}
else
if
(
data
.
choices
[
0
].
delta
.
finish_reason
===
'stop'
) {
// Regular completion without tool calls
break
;
}
}
}
}
See all 40 lines
​
Tool Choice Configuration
Control tool usage with the
tool_choice
parameter:
// Let model decide (default)
{
"tool_choice"
:
"auto"
}
// Disable tool usage
{
"tool_choice"
:
"none"
}
// Force specific tool
{
"tool_choice"
: {
"type"
:
"function"
,
"function"
: {
"name"
:
"search_database"
}
}
}
​
Parallel Tool Calls
Control whether multiple tools can be called simultaneously with the
parallel_tool_calls
parameter (default is true for most models):
// Disable parallel tool calls - tools will be called sequentially
{
"parallel_tool_calls"
:
false
}
When
parallel_tool_calls
is
false
, the model will only request one tool call at a time instead of potentially multiple calls in parallel.
​
Multi-Tool Workflows
Design tools that work well together:
{
"tools"
: [
{
"type"
:
"function"
,
"function"
: {
"name"
:
"search_products"
,
"description"
:
"Search for products in the catalog"
}
},
{
"type"
:
"function"
,
"function"
: {
"name"
:
"get_product_details"
,
"description"
:
"Get detailed information about a specific product"
}
},
{
"type"
:
"function"
,
"function"
: {
"name"
:
"check_inventory"
,
"description"
:
"Check current inventory levels for a product"
}
}
]
}
See all 25 lines
This allows the model to naturally chain operations: search → get details → check inventory.
​
Reliability Tracking
OpenRouter tracks how reliably each provider completes tool calls and surfaces this as the
Tool Call Error Rate
on the Performance tab of every model page. The same signal drives
Auto Exacto
provider ordering on tool-calling requests. For the exact validator, JSON Schema draft, regex semantics, and per-tool-call classification, see
How Tool-Calling Success Rate Is Measured
.
For more details on OpenRouter’s message format and tool parameters, see the
API Reference
.
Response Caching
Overview
⌘
I
Assistant
Responses are generated using AI and may contain mistakes.
