Skip to content

Support native async tool calls to remove sync wrappers #1043

@ajbozarth

Description

@ajbozarth

Follow-up to #1032.

Context

Mellea's tool-call dispatch (_acall_tools)
is already async. The sync-wrapping friction is one layer down: ModelToolCall.call_func()
and MelleaTool.run() are both sync. When a tool wraps an async callable — such as
the MCP tool callables proposed in #1042, or user async functions wrapped via
from_callable per #1041 — the async function has to be re-entered from sync code
via _run_async_in_thread.

Feature

Give MelleaTool a native async call path (e.g., an arun coroutine method and
an async-capable counterpart to ModelToolCall.call_func) so _acall_tools can
await the tool directly when its underlying callable is async.

Outcomes

  • Async callables wrapped via MelleaTool.from_callable can be awaited without
    a thread hop; the _run_async_in_thread wrap added in feat: allow async functions as tools #1041 becomes unnecessary.
  • The MCP module's _make_sync_call shim around _execute_tool (proposed in feat: add MCP tool integration #1042)
    becomes unnecessary; the async _execute_tool can be awaited directly.
  • Sync tool callables keep working unchanged — the async path wraps them trivially.

Expected touchpoints

  • MelleaTool / AbstractMelleaTool: new async call method.
  • ModelToolCall.call_func: async counterpart, or make the existing one async.
  • _acall_tools: await the tool instead of calling call_func() synchronously.
  • MelleaTool.from_callable: drop the _run_async_in_thread wrap for async funcs
    once arun exists.
  • mellea/stdlib/tools/mcp.py: drop _make_sync_call, expose the async closure
    through the new async path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions