Session 5· 13· 20 min
Execute Tool & Return Result
What you'll learn
- ▸Call a local Python function with the model-provided arguments
- ▸Send the result back as a tool message
- ▸Get a final natural-language answer from the model
The full three-step dance
Call 1
user + tools
tool_calls
from the model
Run function
your code
Call 2
+ tool message
Final answer
plain text
13_execute_single_tool_and_return.py
# 1. First call — model returns tool_calls
first = client.chat.completions.create(model=model, messages=messages, tools=tools)
assistant_msg = first.choices[0].message
messages.append(assistant_msg) ①
# 2. Run the function locally
call = assistant_msg.tool_calls[0]
args = json.loads(call.function.arguments)
result = cancel_ticket(**args) ②
# 3. Send the result back as a tool message
messages.append({ ③
"role": "tool", ④
"tool_call_id": call.id, ⑤
"content": json.dumps(result), ⑥
})
# 4. Second call — model turns the result into a human reply
second = client.chat.completions.create(model=model, messages=messages, tools=tools)
print(second.choices[0].message.content)①Crucial: append the assistant message (which contains tool_calls) to history before the tool result.
②Unpack the args dict straight into your Python function with **args.
③Tool result is a NEW message appended to history.
④Role is literally "tool" — this is a special role just for tool results.
⑤tool_call_id must match the id on the tool_call — it links the result back to the request.
⑥content must be a JSON string, so json.dumps() the result dict.
$ python 13_execute_single_tool_and_return.py
Why two API calls?
The first call decides WHICH tool to use. The second call interprets the tool's result into a human-friendly answer. This pattern is at the heart of every agent.
Code Check
What goes into the "content" field of the tool message?
Knowledge Check
Why must tool_call_id match the id from the tool_call?
Recap — what you just learned
- ✓Three steps: get tool_calls → run function → send tool message → call API again
- ✓Append the assistant tool_call message to history BEFORE the tool result
- ✓tool_call_id links the result to the request
- ✓content is a JSON string, not a dict