Tool calling is the capability model. Function calling is the dominant API contract used by OpenAI-compatible chat models: you send tools, the model may return tool_calls, you execute, then you send role: tool messages. This lecture is the practical wire format every AI engineer should be able to implement without a heavy framework.
Frameworks you met in Vol. 14—LangChain, CrewAI, PydanticAI—wrap this contract. Module 15.3 MCP tools will sit beside it as a discovery/transport layer, not a replacement for understanding the round-trip.
Learning Objectives
By the end of this lesson, students should be able to:
- Describe the OpenAI-style round-trip: tools → tool_calls → tool results → final text.
- Write JSON Schema parameters and parse arguments with
json.loads. - Handle parallel tool calls and missing/invalid arguments.
- Contrast native function calling with “please emit JSON” prompting.
- Use
tool_choice(auto / required / none / specific) deliberately. - Wire function calling into the upcoming agent loop.
Function calling is an API feature where the model is given JSON Schema tool definitions and may respond with one or more structured function invocations (name + arguments) instead of—or before—a natural-language answer. The host executes those functions and returns results as subsequent messages.
The Round-Trip
| Turn | Who | Payload |
|---|---|---|
| 0 | You | messages + tools schemas |
| 1 | Model | message.tool_calls[] (id, name, arguments JSON string) |
| 2 | You | For each id: {"role":"tool","tool_call_id":...,"content":...} |
| 3 | Model | Final content or more tool_calls |
Complete OpenAI-Style Example
API Knobs Engineers Actually Use
tool_choice
auto— model decidesrequired— must call somethingnone— force a final answer- Named tool — force one function
Parallel calls
- Multiple
tool_callsin one turn - Independent lookups in parallel
- Still one result per
id
Strict schemas
additionalProperties: false- Pydantic / JSON Schema
- Reject extra hallucinated keys
Strengths
- Reliable structured invocations
- Better than regexing chat JSON
- Works across many providers
- Fits thin custom loops
Tradeoffs
- Arguments still can be wrong types
- Must always match
tool_call_id - Provider quirks / legacy
functionsAPI - Token cost of schemas every turn
“Function calling is just prompting the model to print JSON.” Native tool_calls are a separate message channel with ids the API validates. Prompted JSON is easier to break, harder to parallelize, and easier to confuse with user-visible text. Use native calling when the provider supports it.
Knowledge Check
- Short Answer: What must you send back for each tool call? Answer: A
role: toolmessage with the matchingtool_call_idand result content. - True/False:
function.argumentsarrives as a JSON string you must parse. Answer: True. - Multiple Choice:
tool_choice="none"means: (a) crash, (b) force a final natural-language answer, (c) train LoRA. Answer: (b). - Short Answer: Why set
additionalProperties: false? Answer: Reject extra hallucinated keys; stricter validation. - True/False: You should use
eval()to parse arguments. Answer: False—usejson.loads. - Multiple Choice: Parallel tool calls require: (a) one result per call id, (b) a single merged blob, (c) CSS. Answer: (a).
- Short Answer: How does this differ from tool calling as a concept? Answer: Function calling is the API/wire format; tool calling is the broader capability pattern.
- Short Answer: Name a Vol. 14 framework that wraps this contract. Answer: LangChain, CrewAI, or PydanticAI (any).
- Multiple Choice: Legacy OpenAI
functionsvs moderntools: (a) unrelated to models, (b) older vs current parameter shape, (c) CNN layers. Answer: (b). - True/False: After tools return, the model may call tools again. Answer: True—that is why you need an agent loop.
Key Takeaways
- Function calling is the structured round-trip: schemas, tool_calls, tool results, final text.
- Parse JSON safely, match ids, validate types, fail closed on unknown names.
- Use
tool_choiceto force, forbid, or allow calls; cap parallel work. - Prefer native calling over prompted JSON; frameworks wrap this same contract.
- Next: the agent loop that repeats this round-trip until halt.
Whiteboard: Draw four boxes for the round-trip. Label where auth, logging, and HITL sit (host side, never in the model).
Lab: Add a second tool get_weather(city) and a user question that needs both tools in one turn (parallel) or two sequential turns.
Recap: Function calling is the wire format for tools. Continue with Agent Loop.