The same loop, running locally
The langchain course's tool-calling lessons (13-16) teach a loop: the model reads a question, decides it needs a tool, describes which one and with what arguments, your code actually runs it, and the result goes back so the model can write a final answer. Some models on Ollama support the exact same loop, over the exact same OpenAI-compatible tools format, which means code you write against a local model here transfers almost directly to any cloud provider using that convention.
Not every model on Ollama supports tool calling, it depends on how the model was fine-tuned. llama3.2 does; check a model's Capabilities section in ollama show <model> (Lesson 2) if you're unsure about another one.
The code, piece by piece
def get_weather(city: str) -> str: fake_weather = {"Paris": "18C, cloudy", "Tokyo": "25C, sunny"} return fake_weather.get(city, "unknown city")A plain Python function. It has no idea it's being offered to an AI, that connection is made entirely by the TOOLS description below.
TOOLS = [ { "type": "function", "function": { "name": "get_weather", "description": "Get the current weather for a city", "parameters": {"type": "object", "properties": {...}, "required": [...]}, }, }]A JSON Schema again, same shape as format in Lesson 10, just describing a function's arguments instead of an entire reply.
response = ollama.chat(model="llama3.2", messages=messages, tools=TOOLS)Passing tools=TOOLS tells the model what's available. The model itself never runs anything, it decides whether a tool is needed and, if so, returns a tool_calls list on response.message describing which function and which arguments, instead of writing a normal reply.
call = response.message.tool_calls[0]result = get_weather(**call.function.arguments)Your code is the one that actually calls get_weather, using the arguments the model chose. call.function.arguments is already a plain dict, so **call.function.arguments unpacks it directly into keyword arguments.
messages.append({"role": "tool", "content": result, "tool_name": call.function.name})final_response = ollama.chat(model="llama3.2", messages=messages, tools=TOOLS)The function's return value goes back into the conversation as a "tool" role message. A second call to ollama.chat() lets the model read that result and write a normal, natural-language final answer.
Checkpoint
tools=TOOLS: describes available functions to the model using the same JSON Schema shape as structured output.- The model never runs code: it only ever describes what it wants called, your program executes the actual function.
response.message.tool_calls: how you detect the model wants a tool instead of writing a normal reply.- The
"tool"role message: how a function's result gets back into the conversation so the model can use it in a final answer.
If anything here still feels unclear, ask before moving to Lesson 12.