#Getting Multiple Function Calls to Work Reliably

1 messages · Page 1 of 1 (latest)

rotund radish
#

I'm having trouble getting multiple function calls to work reliably.

Problem Description

When I ask the model to perform multiple tasks that should each trigger a separate function call, it only calls one function instead of both. For example, with this user message:

What's the weather like in London today and can you send that information to weather@example.com?

I expect the model to:

  1. Call get_weather to get the weather in London
  2. Call send_email to send that information to the email address

However, the model only calls the get_weather function and then returns None as the final response, instead of incorporating the weather information into an email or explicitly calling the email function.

What I've Tried

  • Setting tool_choice="required" to force function calls
  • Setting parallel_tool_calls=True to explicitly enable multiple function calls
  • Using different model versions
  • Adding detailed function descriptions
  • Rewriting the user query to be more explicit

Nothing seems to work consistently. The model either calls just one function or occasionally returns a text response without any function calls.

Minimal Reproducible Example

I've attached a simple script that demonstrates the issue. It's a minimal version that defines two functions (weather and email) and tries to get the model to use both in sequence.

Questions

  1. Is there something wrong with my implementation of function calling?
  2. Should I be using a different approach entirely for multi-step tasks like this?

I'm missing something fundamental so any help/pointers would be greatly appreciated!

Code to reproduce is attached. Feel free to correct it or add comments.

odd path
# rotund radish I'm having trouble getting multiple function calls to work reliably. ### Proble...

It is because second_completion.choices[0].message.content does not exist.

"choices": [
{
"finish_reason": "tool_calls",
"index": 0,
"logprobs": null,
"message": {
"content": null,
"refusal": null,
"role": "assistant",
"annotations": [],
"audio": null,
"function_call": null,
"tool_calls": [
{
"id": "call_KWbkxqpRyM6YF05YDhgwYx8B",
"function": {
"arguments": "{"to":"weather@example.com","subject":"Today's Weather in London","body":"The current weather in London, UK is 15\u00b0C and partly cloudy."}",
"name": "send_email"
},
"type": "function"
}
]
}
}
],

#

This is the final response/second response.
I didn't get a good look at it but i think it is because the handling of multiple functions is done incorrectly.

rotund radish
odd path
odd path
rotund radish
# odd path
# First completion to trigger function calls
    print("\n=== First API Call ===")
    completion = client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
        tools=tools,
        # Force tool calls 
        tool_choice="required",
        parallel_tool_calls=True
    )
    
    assistant_message = completion.choices[0].message
    tool_calls = assistant_message.tool_calls
    
    # Add the assistant message to conversation
    messages.append(assistant_message)

I thought my code already has the correct tool handling sequence you've highlighted. The issue, is that the model itself is not returning multiple calls .

So i only ever see

tool call get_weather to get the weather in London

but I expect tool calls get_weather AND send_email in the first response.

odd path
#

To see what the response is you just print the entire reponse.

odd path
#

print(json.dumps(response.model_dump(), indent=4))

#

in your case print(json.dumps(assistant_message.model_dump(), indent=4))