DS DevShelfHub Projects · AI tools
Tutorials / Prompt Engineering / Tool Use & Function Calling
Prompt Engineering Intermediate · 13 min read Page 8 of 10

Tool Use & Function Calling: Prompt LLMs to Act

By DevShelfHub

How function calling works, how to write tool schemas, when tools beat pure prompting, and how to build a reliable tool loop.

Series progress8 / 10
Tool use and function calling tutorial for LLM agents

What is function calling?

Function calling (also called tool use) lets you expose typed functions to the LLM. Instead of asking the model to produce text, you ask it to produce a structured call to one of your functions — with arguments that your code then executes.

Key insight: The LLM does not execute the function. It produces a structured JSON object saying which function to call and with what arguments. Your code runs the function and feeds the result back to the model.
User "What's the weather in Tokyo?"
LLM {"function": "get_weather", "args": {"city": "Tokyo"}}
Your code executes get_weather("Tokyo") → "22°C, cloudy"
LLM "The current weather in Tokyo is 22°C and cloudy."

Writing a tool schema

You describe each tool as a JSON schema — the model uses this to decide when and how to call it. Three parts matter most: the name, the description, and the parameters.

python
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather for a city. "
                           "Use this when the user asks about weather "
                           "or temperature in a specific location.",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "City name, e.g. 'Tokyo' or 'New York'"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "Temperature unit. Default: celsius"
                    }
                },
                "required": ["city"]
            }
        }
    }
]
Name

Use snake_case, descriptive verbs: get_weather, search_products, send_email. The name is the model's primary signal for when to call it.

Description

This is your most important field — explain what the function does AND when to use it. Include example triggers: "Use this when the user asks about…"

Parameters

Describe each parameter clearly. Use enum to constrain values where possible. Mark required vs optional explicitly.

Building the tool loop

Function calling is a multi-turn process. Here's the complete pattern using the OpenAI API:

python
import json
from openai import OpenAI

client = OpenAI()
messages = [{"role": "user", "content": "What's the weather in Tokyo?"}]

while True:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        tools=tools,
        messages=messages,
    )
    msg = response.choices[0].message

    # No tool call — model has final answer
    if not msg.tool_calls:
        print(msg.content)
        break

    # Execute each tool call
    messages.append(msg)  # add assistant message with tool_calls
    for tc in msg.tool_calls:
        args = json.loads(tc.function.arguments)
        result = get_weather(**args)  # your function
        messages.append({
            "role": "tool",
            "tool_call_id": tc.id,
            "content": json.dumps(result),
        })
    # loop continues — model will now generate final answer

Tools vs pure prompting

Situation Use
Need real-time or live data (weather, prices, search)Tools
Need exact arithmetic or guaranteed correct computationTools
Writing, summarisation, content generationPure prompting
Need to take side-effecting actions (send email, write DB)Tools
Reasoning and analysis over provided textPure prompting
Classification, extraction from text in the promptPure prompting

Rule of thumb: use tools when the model needs to do something beyond reasoning over text. Use prompting when it just needs to think about text already in the context.

Writing better tool descriptions

Weak description

python
"description": "Search for products."

No context on when to call it. The model may call it for everything, or never.

Strong description

python
"description": "Search the product catalogue by keyword or
category. Use this when the user is looking for a specific
product, asking what's available, or comparing options.
Do NOT use this for order history or returns."

Tells the model when to call it AND when NOT to. Negative instructions prevent over-calling.

Notes

Parallel tool calls can create race conditions in shared state

GPT-4o and later OpenAI models support parallel tool calls by default. If two of your tools read from and write to shared state (a database row, a file), parallel execution can produce inconsistent results. Set parallel_tool_calls=False in the API call when tools share mutable state.

Tool errors must be returned as tool messages, not raised exceptions

If your tool function raises an uncaught Python exception instead of returning an error string, the API call fails entirely and the model receives no feedback. Always wrap tool function bodies in try/except and return a descriptive error string as the tool result. The model can then reason about the error and decide how to recover.

Enable strict=True to eliminate hallucinated parameters

OpenAI's Structured Outputs for tool calls (strict=True in the tool schema) forces the model to pass only arguments defined in the schema. Without it, the model occasionally passes extra keyword arguments that break your function signature. Enable strict mode in production for all tool schemas.

Each tool definition adds to input token cost on every call

With 10+ tools in the payload, schema definitions alone can add 500–1,000 input tokens to every API request. At scale this is significant. Group related tools into a single tool with a type enum parameter (e.g. one search_product tool with a category enum) to reduce schema size.

Tool Use & Function Calling FAQ

What is function calling in LLMs?

Function calling (also called tool use) lets you expose typed functions to an LLM. The model produces a structured JSON call specifying which function to invoke and with what arguments — your code then executes the function and feeds the result back to the model. The LLM never executes code itself.

How do I write a good tool schema for an LLM?

A good tool schema has three key parts: a descriptive snake_case name (e.g. get_weather), a detailed description that explains what the function does AND when to call it (include trigger phrases like "use this when the user asks about..."), and clearly described parameters with enum constraints where applicable.

What is the difference between tool use and pure prompting?

Use tools when the model needs to act beyond reasoning over text — live data, exact arithmetic, or side-effecting actions like sending email. Use pure prompting when the model just needs to reason, write, summarise, or classify text already in the context window.

How does the tool loop work in a multi-turn conversation?

The tool loop is: (1) send a message with tool definitions, (2) check if the response contains tool_calls, (3) execute each tool call in your code, (4) append the tool result as a tool-role message, (5) call the API again. Repeat until the model returns a response with no tool_calls — that is the final answer.

How do I write better tool descriptions so the LLM uses them correctly?

Include both positive triggers ("use this when the user asks about product availability") and negative exclusions ("do NOT use this for order history"). Without negative instructions, models tend to over-call tools. Describe each parameter's purpose and valid values using enum constraints to reduce invalid arguments.

Quick summary

  • Function calling: LLM produces a structured call → your code executes it → result fed back
  • Tool description is your most important field — include when to call it AND when not to
  • The tool loop: call API → check for tool_calls → execute → append result → repeat
  • Use tools for live data, exact computation, and side effects. Use prompting for reasoning over text
  • Use enum in parameters to constrain values the model can pass