Skip to content

Support async tool functions #125

@wu-changxing

Description

@wu-changxing

Problem

Tool executor (tool_executor.py:195) only supports sync functions:

result = tool_func(**tool_args)

This blocks us from using async libraries as tools (browser-use CDP, async HTTP clients, async database drivers, etc). Currently the only workaround is wrapping every async call with asyncio.run() inside each tool method — ugly and error-prone.

Proposed Change

One line change in execute_single_tool():

import asyncio, inspect

if inspect.iscoroutinefunction(tool_func):
    result = asyncio.run(tool_func(**tool_args))
else:
    result = tool_func(**tool_args)

No changes needed in agent.py, tool_factory.py, or tool_registry.py. The agent loop stays sync — we just bridge to async at the execution point.

Why

Immediate use case: wrap browser-use BrowserSession as a ConnectOnion tool (useful_tools/browser_use.py). browser-use is fully async CDP-based. With async tool support, we can write clean tools like:

class BrowserUse:
    async def navigate(self, url: str) -> str:
        event = self.session.event_bus.dispatch(NavigateToUrlEvent(url=url))
        await event
        return f"Navigated to {url}"

Instead of wrapping every method with asyncio.run().

Scope

  • connectonion/core/tool_executor.py — detect coroutine, run with asyncio.run()
  • connectonion/core/tool_factory.py — no change needed (signature inspection works the same for async functions)
  • Tests: add one test with an async tool function

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions