Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions dspy/adapters/types/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,17 @@ def _run_async_in_sync(self, coroutine):
except RuntimeError:
return asyncio.run(coroutine)

if loop and loop.is_running():
try:
import nest_asyncio

nest_asyncio.apply()
except ImportError:
raise ImportError(
"nest_asyncio is required to call async tools from within a running event loop. "
"Install it with: pip install nest-asyncio"
)

return loop.run_until_complete(coroutine)

@with_callbacks
Expand Down
13 changes: 9 additions & 4 deletions dspy/utils/syncify.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ def run_async(coro):
loop = None

if loop and loop.is_running():
# If we're in a running event loop (e.g., Jupyter), use asyncio.create_task and run until done
import nest_asyncio

nest_asyncio.apply()
try:
import nest_asyncio

nest_asyncio.apply()
except ImportError:
raise ImportError(
"nest_asyncio is required to call async functions from within a running event loop. "
"Install it with: pip install nest-asyncio"
)
return asyncio.get_event_loop().run_until_complete(coro)
else:
return asyncio.run(coro)
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ dev = [
"build>=1.0.3",
"litellm>=1.64.0; sys_platform == 'win32' or python_version == '3.14'",
"litellm[proxy]>=1.64.0; sys_platform != 'win32' and python_version < '3.14'", # Remove 3.14 condition once uvloop supports
"nest-asyncio>=1.6.0",
]
test_extras = [
"mcp; python_version >= '3.10'",
Expand Down
12 changes: 10 additions & 2 deletions tests/adapters/test_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,16 @@ def test_async_tool_call_in_sync_mode():
assert result == "hello 1"


@pytest.mark.asyncio
@pytest.mark.filterwarnings("ignore::DeprecationWarning:pytest_asyncio")
async def test_async_tool_call_from_running_event_loop():
tool = Tool(async_dummy_function)

with dspy.context(allow_tool_async_sync_conversion=True):
result = tool(x=42, y="test")
assert result == "test 42"


TOOL_CALL_TEST_CASES = [
([], {"tool_calls": []}),
(
Expand Down Expand Up @@ -542,8 +552,6 @@ def test_tool_convert_input_schema_to_tool_args_lang_chain():
}




def test_tool_call_execute():
def get_weather(city: str) -> str:
return f"The weather in {city} is sunny"
Expand Down
19 changes: 15 additions & 4 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading