Skip to content

Support sequential or dependency-aware execution of parallel tool calls #6399

Description

@PrinceGupta1999

Feature Type

Would make my life easier

Feature Description

When an LLM returns multiple tool calls, LiveKit currently starts each call as a separate asyncio task and waits for them together:

task = asyncio.create_task(
_traceable_fnc_tool(function_callable, fnc_call),
name=f"func_exec_{fnc_call.name}", # task name is used for logging when the task is cancelled
)
_set_activity_task_info(
task, speech_handle=speech_handle, function_call=fnc_call, inline_task=True
)
tasks.append(task)
task.add_done_callback(lambda task: tasks.remove(task))
except Exception as e:
# catching exceptions here because even though the function is asynchronous,
# errors such as missing or incompatible arguments can still occur at
# invocation time.
logger.exception(
"exception occurred while executing tool",
extra={
"function": fnc_call.name,
"speech_id": speech_handle.id,
},
)
_tool_completed(make_tool_output(fnc_call=fnc_call, output=None, exception=e))
continue
await asyncio.shield(asyncio.gather(*tasks, return_exceptions=True))

This works for independent tools, but in many real life workloads tools depend on others, due to shared dependencies.

For example, in a hotel booking flow, the LLM may return save_room_preference and save_meal_preference together. However, the runtime must execute save_room_preference first because the available meal options may depend on the selected room package.

It would be helpful to support an optional execution policy such as:

  • parallel: current behavior.
  • Custom dependency ordering: run independent calls in parallel while waiting for prerequisites.

The model should still be able to return multiple calls in one response. The ordering should happen locally during tool execution. Existing parallel behavior should remain the default.

Workarounds / Alternatives

  • Setting parallel_tool_calls=False forces separate model turns between tools
  • Applications can also build a wrapper tool or coordinate with locks, but this requires custom orchestration and does not have a clean view of all calls in the current batch.
  • TaskGroup supports ordered conversational tasks, but not ordering ordinary tool calls returned together.

Additional Context

A related request exists for conditional TaskGroup workflows: #5697

This request is specifically about execution ordering for function tool calls within the same model turn.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions