Agents / Intermediate

Build a local tool-calling assistant

Give Qwen3 a single safe function, inspect its tool request, return a result, and confirm the final answer stays in a local Ollama session.

Verified sourceSource checked 9/23/2026
LOCALRENTED GPU

Before you begin

Difficulty
Intermediate
Software
Ollama, Python
Hardware
The Qwen3 8B Ollama package is 5.2 GB. Allow additional memory for the runtime, tool schema, and conversation history.
View the setup source

Sources and files

Official Qwen3 8B package Official single-tool request and response example

Choose a model for this task

The steps below use the recommended model. Alternatives have their own package and command; open their model pages before switching.

The workflow

1

Install Ollama and Qwen3

Start Ollama on your machine and download the publisher-listed 8B package. The tool calls below use the qwen3 model family.

ollama run qwen3:8b
2

Install the local Python client

Create a Python environment for your small tool runner and install the official Ollama client.

pip install ollama -U
3

Define one bounded function

Create a function that reads a small, explicit local lookup table, such as the sample city-to-temperature dictionary in the official guide. Avoid shell execution or arbitrary file access in the first version.

4

Send a request with that tool

Save this source-derived example as tool_agent.py, then run python tool_agent.py. It keeps the allowed function in your own process and checks the requested name before calling it.

from ollama import chat def get_temperature(city: str) -> str: return {"New York": "22°C", "London": "15°C"}.get(city, "Unknown") messages = [{"role": "user", "content": "What is the temperature in New York?"}] response = chat(model="qwen3:8b", messages=messages, tools=[get_temperature], think=True) messages.append(response.message) if not response.message.tool_calls: raise RuntimeError("No tool call returned") call = response.message.tool_calls[0] if call.function.name != "get_temperature": raise ValueError("Unapproved tool name") result = get_temperature(**call.function.arguments) messages.append({"role": "tool", "tool_name": "get_temperature", "content": result}) print(chat(model="qwen3:8b", messages=messages, tools=[get_temperature], think=True).message.content)
5

Inspect and execute the requested call

Read response.message.tool_calls, check the function name and arguments against your allowlist, run your one function, then append its result as a role="tool" message. Do not execute an unrecognized tool name.

6

Ask for a final response and verify

Call chat again with the original messages, assistant tool call, and tool result. Confirm the final answer includes the value from your lookup table and that no network or shell tool was granted.

When it doesn’t go to plan

The model replies without calling the tool

Check the tools argument and function signature, then ask a question that explicitly needs your lookup value. The official guide includes a complete single-tool example.

The final answer lacks the tool result

Append both the assistant tool-call message and the role="tool" result before the second chat call, matching the official message sequence.

The model behind this workflow

Qwen3 8B
MY HARDWARE

Will it run on your machine?

Save your machine to see a personalized rating and its reasoning.

Add my hardware

Keep exploring