Quick answer: Tool calling (also called function calling) is a mechanism where a language model, instead of answering directly, outputs a structured request to run a function you defined. Your code executes it, returns the result, and the model continues with that result in hand. It is how models reach outside their own weights to fetch data, run code, or take actions. The model never runs anything itself: it asks, you execute, you report back.
Tool calling is the single feature that turns a chatbot into something that can actually do work. Without it, a model can only talk. With it, a model can look things up, call your APIs, and act on the world. Here is exactly how the loop works.
The Core Idea
You give the model a menu of tools. Each tool has a name, a description, and a schema describing its inputs. When the model decides a tool would help, it does not produce prose. It produces a structured object naming the tool and filling in the arguments.
That is the key mental shift: the model does not call your function. It emits a request to call your function, in a format your code can parse. You are the one who runs the code. This separation is deliberate and it is what makes tool calling safe to reason about, because you decide what actually executes.
The description matters more than people expect. The model chooses tools based almost entirely on the name and description you write, so a vague description leads to a tool that gets ignored or misused. Be specific about when to call it, not just what it does.
The Request-Response Loop
A single tool-calling turn has a clear shape. Walk through it once and the whole thing clicks.
| Step | Who acts | What happens |
|---|---|---|
| 1 | You | Send the user message plus the list of available tools |
| 2 | Model | Responds with a tool_use request: tool name and arguments |
| 3 | You | Parse the request, run the actual function |
| 4 | You | Send the result back as a tool_result |
| 5 | Model | Reads the result and either answers or calls another tool |
Steps 2 through 5 repeat until the model stops asking for tools and produces a final answer. That repeating cycle is the agent loop, and tool calling is the primitive underneath it.
One detail worth internalizing: you must send the result back with the ID from the request so the model can match them. And if the model asks for several tools at once, you run them all and return every result before continuing. Dropping one confuses the model into thinking the call failed.
A Web-Fetch Tool, Concretely
The most valuable tool you can give a model is web access, because it is the one thing the weights cannot provide. Let me build a fetch tool backed by link.sc.
First, the tool definition. This is the schema the model reads to decide when and how to call it:
{
"name": "fetch_url",
"description": "Fetch the full text content of a web page as clean markdown. Call this whenever the user references a specific URL or you need the current contents of a known page.",
"input_schema": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The absolute URL to fetch, including https://"
}
},
"required": ["url"]
}
}
Next, the handler. When the model requests fetch_url, your code calls link.sc and returns clean markdown:
import requests
def fetch_url(url: str) -> str:
resp = requests.post(
"https://link.sc/v1/fetch",
headers={"Authorization": "Bearer lsc_..."},
json={"url": url, "format": "markdown"},
)
resp.raise_for_status()
return resp.json()["content"]
Now the full loop with the Anthropic SDK. Notice how the model's request and your result pass back and forth:
import anthropic
client = anthropic.Anthropic()
tools = [FETCH_TOOL] # the JSON schema above
messages = [{"role": "user", "content": "Summarize https://example.com/pricing"}]
while True:
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
tools=tools,
messages=messages,
)
if response.stop_reason != "tool_use":
break
messages.append({"role": "assistant", "content": response.content})
results = []
for block in response.content:
if block.type == "tool_use" and block.name == "fetch_url":
content = fetch_url(block.input["url"])
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": content,
})
messages.append({"role": "user", "content": results})
print(response.content[0].text)
The model reads the request, sees it needs the page, asks for fetch_url, your handler calls link.sc, the clean markdown comes back, and the model summarizes it. The model provided the reasoning and the decision to fetch. link.sc provided the content. For the framework version of this same pattern, see give LangChain agents a web fetch tool.
Function Calling vs Tool Calling: Same Thing
You will see both terms. "Function calling" is the older name popularized when the feature first shipped, and "tool calling" is the more common name now, partly because tools can be more than plain functions (they can be server-hosted actions, retrieval, or code execution). For everyday purposes they mean the same mechanism: the model emits a structured request, you execute, you return the result.
MCP: The Standard for Tool Calling
Here is the problem tool calling creates at scale. Every model provider has its own slightly different way of declaring tools, and every tool you build is wired to one app. If you want the same fetch tool available in Claude, in Cursor, and in your own agent, you end up reimplementing it three times.
The Model Context Protocol (MCP) fixes this. It is an open standard for exposing tools, so a tool defined once against an MCP server works with any MCP-compatible client. Instead of hardcoding a fetch_url function into each app, you point the app at an MCP server and the tools show up.
link.sc runs an MCP server at mcp.link.sc exposing search and fetch as standard tools. Any MCP client, Claude included, can use them without you writing a handler at all: the tool calling, the schema, and the execution are handled by the server. If you want the full picture of why this matters, read what is the Model Context Protocol and why it matters.
The Short Version
Tool calling is the model asking your code to run a function and continuing once you return the result. You define tools with a name, description, and schema; the model emits structured requests; you execute and report back; the loop repeats until it answers. A web-fetch tool backed by link.sc is the highest-value tool you can add, and MCP is the standard that lets you define it once and use it everywhere.
Ready to give your model a web-fetch and search tool without building the plumbing? link.sc ships an MCP server and a plain HTTP API for both. Start free.