Is Sequential Tool Calling possible?

Hi, I was wondering if sequential tool calling is possible. I have these 2 functions below:

$tools = [
    [
        'name' => 'user_attendance_data',
        'type' => 'function',
        'function' => [
            'name' => 'get_user_attendance_data',
            'description' => "Get user's attendance records ONLY for clock-in/clock-out and lates. Does NOT include filed absences, leaves, or approved time off.",
            'parameters' => [
                'type' => 'object',
                'properties' => [
                    'year' => [
                        'type' => 'number',
                        'description' => 'Optional: The year to filter attendance dates. Defaults to current year.'
                    ],
                    'month' => [
                        'type' => 'number',
                        'description' => 'Optional: Specific month to retrieve attendance from.'
                    ],
                    // 'date' => [
                    //     'type' => 'string',
                    //     'description' => 'Optional: Specific date to retrieve attendance from.',
                    //     'default' => $today
                    // ],
                ],
                'required' => [],
                'additionalProperties' => false,
            ],
        ],
    ],

    [
    'name' => 'get_filed_absences',
    'type' => 'function',
    'function' => [
        'name' => 'get_filed_absences',
        'description' => "Get user's FILED absences and leaves ONLY (VL, SL, etc). Does NOT include lates, missing logs, or attendance records.",
        'parameters' => [
            'type' => 'object',
            'properties' => [
                'year' => [
                    'type' => ['number', 'string'],
                    'description' => 'Optional: The year to filter absence dates. Can be a number or "oldest". Defaults to current year.'
                ],
                'month' => [
                    'type' => 'number',
                    'description' => 'Optional: Specific month to retrieve absence from.'
                ],
                'include_archived' => [
                    'type' => 'boolean',
                    'description' => 'Optional: If true, include archived absences. Defaults to false.'
                ]
            ],
            'required' => [],
            'additionalProperties' => false,
        ],
    ],
],

]

I have encountered this problem where the user prompts “My lates and absences this month” which requires 2 sequentials functions to complete. It instead tried to call the 2 functions in one call by appending the function names. Please see the log below.

[2025-12-22 13:57:45] local.INFO: Iteration number: 1  
[2025-12-22 13:57:47] local.INFO: result: {"type":"tool_call","tool_call":{"id":"call_ztSyfV91MoXHcwqqA7jDqtJb","name":"get_user_attendance_dataget_filed_absences","arguments":null},"text":""}  
[2025-12-22 13:57:47] local.INFO: Iteration number: 2  
[2025-12-22 13:57:49] local.INFO: result: {"type":"tool_call","tool_call":{"id":"call_bFjdz6BYD9IdNbkL5rBEJUE6","name":"get_user_attendance_dataget_filed_absences","arguments":null},"text":""}  
[2025-12-22 13:57:49] local.INFO: Iteration number: 3  
[2025-12-22 13:57:50] local.INFO: result: {"type":"tool_call","tool_call":{"id":"call_zvpKrtlFS4eSGjYFsV8Hooqj","name":"get_user_attendance_dataget_filed_absences","arguments":null},"text":""}  
[2025-12-22 13:57:50] local.INFO: Iteration number: 4  
[2025-12-22 13:57:51] local.INFO: result: {"type":"tool_call","tool_call":{"id":"call_llq9xJNp83QbKxb6I9J9g2xM","name":"get_user_attendance_dataget_filed_absences","arguments":null},"text":""}  
[2025-12-22 13:57:51] local.WARNING: Exited tool loop after reaching max iterations. 

Hello, We do not support sequential calling yet—in today’s Function‑Calling you get exactly one tool call (or one parallel group) per model invocation. You must orchestrate multi‑step flows yourself. Hope that helps. Thank you!

2 Likes

Parallel function calling is possible, depending on the model used (not original gpt-4, seemingly not on reasoning models). The shape of the function you offered us is for Chat Completions it seems, where that is supported and a default “helper tool wrapper” that OpenAI injects.

Your function call handler is going to be the sequential part - you can’t expect the AI to base its next tool call on a past function return of yours until you return it!

If prompted well, especially with the function descriptions themselves describing the need to call another function first, you can have the AI perform what you’d desire.

That is simply a cognitive failure, or a failure in enforcing any kind of logit grammar on the AI by OpenAI. The AI did not necessarily have intention to “make two tool calls”.

"name":"get_user_attendance_dataget_filed_absences"

The AI should have closed the function name and continued to writing parameters. Instead, it sampled and wrote a different token than what was required by the backend, and thus immediately damaged any chance of succeeding in making a function call with that name.

Then, you returned something to the AI, continuing to call to allow it to iterate like that. Or you returned nothing and re-called with only the user input, creating a fresh chance for the AI to write to the function the same way again. The correct return to the tool ID should have been “invalid/nonexisting function method! Try again”, which might have broken the AI out of retrying the same.

Besides an informative corrective return when your code iterates, you might add at least one “required” field to encourage the AI writing the shape of the function correctly.

1 Like