Mastering Function Calling: Deep Dive into tools, tool_choice, and parallel_tool_calls for LLMs

This guide explains the three core Function Calling parameters—tools, tool_choice, and parallel_tool_calls—showing how to design tool schemas, control model autonomy, choose parallel execution, and avoid common pitfalls, with concrete Python and JavaScript examples and a cross‑platform comparison.

Qborfy AI
Qborfy AI
Qborfy AI
Mastering Function Calling: Deep Dive into tools, tool_choice, and parallel_tool_calls for LLMs

Function Calling turns LLMs from pure text generators into action‑oriented agents

Without tool calls a model can only generate text based on the prompt. It can describe how to fetch weather data but cannot actually retrieve the data or push results into a system. Function Calling lets the model propose a structured tool_call, which the application executes and feeds the result back, completing a closed‑loop interaction.

The three parameters that control Function Calling

tools – an array of JSON‑schema tool definitions that describe what external capabilities the model may use.

tool_choice – a string or object that controls whether the model may call a tool, and which one.

parallel_tool_calls – a boolean that decides if the model can return multiple tool_calls in a single round.

1. tools – the model’s tool catalog

Each entry is a JSON schema with three important fields:

Name – use a verb‑object pattern (e.g. get_weather, create_order) so the model instantly understands the purpose.

Description – explain both what the tool does and when it should be used; the model relies solely on this text.

Parameters – a strict JSON schema (types, enums, required fields, field‑level descriptions). The tighter the schema, the less the model will hallucinate arguments.

Example of a well‑crafted tool definition:

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "Fetch real‑time weather for a specified city",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {"type": "string", "description": "City name, e.g. 'Beijing' or 'Beijing'"},
        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"], "description": "Temperature unit"}
      },
      "required": ["city"]
    }
  }
}

2. tool_choice – autonomy control

Common values: "auto" – let the model decide whether to call a tool (default for open‑ended assistants). "none" – forbid tool calls, forcing a pure text response. "required" – require the model to call at least one tool before answering (useful for workflow entry points).

Object {"type":"function","function":{"name":"get_weather"}} – force a specific tool (deterministic single‑step tasks).

3. parallel_tool_calls – execution rhythm

Set to true when the tasks are independent (e.g., fetch weather for three cities in one round). Keep false when later steps depend on earlier results, because parallelism can break the logical chain.

Full Function‑Calling flow

The end‑to‑end process consists of four steps:

Step 1: Send request with <code>tools</code>
Step 2: Model returns <code>tool_calls</code>
Step 3: Application executes the tool(s) and sends the result(s) back
Step 4: Model produces the final natural‑language answer

The model never executes the tool itself; it only proposes a structured call.

Minimal Python demo

import json, openai
client = openai.OpenAI()

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Fetch real‑time weather for a city",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string", "description": "City name"}},
            "required": ["city"]
        }
    }
}]

messages = [{"role": "user", "content": "Beijing weather today?"}]
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
    tool_choice="auto"
)
assistant_msg = response.choices[0].message
if assistant_msg.tool_calls:
    for call in assistant_msg.tool_calls:
        args = json.loads(call.function.arguments)
        if call.function.name == "get_weather":
            city = args["city"]
            weather = f"{city} is sunny, 25°C"
            messages.append({"role": "tool", "tool_call_id": call.id, "content": weather})
    final = client.chat.completions.create(model="gpt-4o", messages=messages, tools=tools)
    print(final.choices[0].message.content)
else:
    print(assistant_msg.content)

JavaScript / Vercel AI SDK demo

import { generateText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";

const { text, toolCalls } = await generateText({
  model: openai("gpt-4o"),
  messages: [{ role: "user", content: "Beijing weather?" }],
  tools: {
    get_weather: tool({
      description: "Fetch real‑time weather",
      parameters: z.object({ city: z.string().describe("City name") }),
      execute: async ({ city }) => `${city} is sunny, 25°C`
    })
  },
  toolChoice: "auto",
  maxSteps: 5
});
console.log(text);

Multi‑tool collaboration modes

Parallel – independent tasks (e.g., weather for Beijing, Shanghai, Guangzhou) can be issued in one round with parallel_tool_calls=true.

Sequential – later steps depend on earlier results (e.g., fetch recent order ID then fetch its logistics). Keep parallel_tool_calls=false and let the model call the next tool after receiving the previous result.

Chain – complex multi‑round workflows. Use a loop with a hard maxSteps limit to avoid infinite recursion.

Platform support (summary)

OpenAI – full support for tools, tool_choice (auto/none/required/object), and parallel_tool_calls. Strict schema mode available.

DeepSeek, Kimi, Yi (Zero‑One) – high compatibility with OpenAI‑style APIs; all three parameters work similarly.

Anthropic Claude – supports tool calls but returns tool_use blocks instead of OpenAI’s tool_calls. Requires custom handling of the message structure.

Google Gemini – uses function_declarations for tool definitions; supports auto/none/object choices; parallel support depends on the endpoint.

MiniMax, Meta‑Llama‑based services – support the three parameters with minor differences in response format.

Common pitfalls and how to avoid them

Overly broad tool schemas – vague names and descriptions cause the model to pick the wrong tool. Use precise verb‑object names and detailed field descriptions.

Missing error propagation – if a tool fails, return a clear error message as a tool result so the model can decide to retry, degrade, or inform the user.

Infinite loops – unbounded loops or missing maxSteps lead to runaway calls. Enforce a hard iteration limit and ensure each tool returns a definitive completion signal.

Overusing tools – not every request needs an external call. For pure explanations, summarizations, or translations, keep the model in pure generation mode ( tool_choice="none").

When to use Function Calling

Use it when the user needs real‑time data, side‑effects, or multi‑system orchestration (e.g., fetching weather, creating tickets, querying a database, invoking a rule engine). For simple explanations, summarizations, or rewrites, stick to plain generation.

Key takeaways

tools

defines the capability boundary; high‑quality schemas directly improve call accuracy. tool_choice balances flexibility and control – auto for open assistants, required or explicit objects for deterministic flows. parallel_tool_calls governs execution rhythm; enable it only when tasks are independent.

The interaction loop is a closed feedback cycle: model proposes → application executes → result fed back → model finalizes.

Production failures usually stem from loose schemas, unhandled errors, or missing stop conditions.

Avoid unnecessary tool calls to keep systems simple, cost‑effective, and stable.

Function Calling illustration
Function Calling illustration
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AI AgentsPrompt engineeringTool Integrationfunction callingLLM APIs
Qborfy AI
Written by

Qborfy AI

A knowledge base that logs daily experiences and learning journeys, sharing them with you to grow together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.