C.W.K.
Stream
Lesson 02 of 04 · published

Defining and Calling Tools

~22 min · tools, schema

Level 0Downloader
0 XP0/41 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

The schema is your prompt

Tool descriptions and parameter descriptions are part of the prompt the model sees. They drive whether the model picks the right tool and supplies correct arguments. A vague description like "get info" gives you bad tool calls; a precise one ("Look up a stock price for a US-listed ticker (e.g. 'AAPL'). Returns current price in USD.") gives you good ones.

Multiple tools — let the model pick

You can pass an array of tools. The model decides which one (if any) to call. It can also call several in sequence or in parallel within a single turn — handle both.

What the response looks like

When the model decides to call a tool, the response message has empty content and a populated tool_calls array. Each tool call has function.name (which tool) and function.arguments (already parsed as a dict — Ollama parses the JSON for you, unlike OpenAI which returns a JSON string).

Code

Multiple tools in one definition·python
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Current weather for a city. Returns temp (number) and condition (string).",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "City name like 'Tokyo' or 'Seoul'"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                },
                "required": ["city"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "search_files",
            "description": "Search for files matching a glob pattern under a directory.",
            "parameters": {
                "type": "object",
                "properties": {
                    "pattern": {"type": "string", "description": "Glob pattern, e.g. '*.py'"},
                    "directory": {"type": "string", "description": "Directory path; default '.'"},
                },
                "required": ["pattern"],
            },
        },
    },
]
Inspect tool_calls and dispatch·python
import httpx, json, glob

def get_weather(city: str, unit: str = "celsius") -> str:
    return json.dumps({"city": city, "temp": 22, "unit": unit, "condition": "sunny"})

def search_files(pattern: str, directory: str = ".") -> str:
    matches = glob.glob(f"{directory}/{pattern}")
    return json.dumps({"files": matches[:10], "count": len(matches)})

REGISTRY = {
    "get_weather": get_weather,
    "search_files": search_files,
}

resp = httpx.post(
    "http://localhost:11434/api/chat",
    json={"model": "qwen2.5:7b", "tools": tools, "stream": False,
          "messages": [{"role": "user", "content": "What's the weather in Tokyo?"}]},
    timeout=120.0,
).json()

assistant_msg = resp["message"]
for call in assistant_msg.get("tool_calls", []):
    name = call["function"]["name"]
    args = call["function"]["arguments"]
    print(f"Model wants: {name}({args})")
    if name in REGISTRY:
        result = REGISTRY[name](**args)
        print(f"  -> {result}")

External links

Exercise

Define three tools: get_time(timezone), calculate(expression), look_up(term). Send a single user message that requires two of them in sequence. Print which tool calls the model produced and dispatch each manually. Don't loop yet — just see the structure.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.