agents/base: Agent.process_message_sync() uses deprecated asyncio.get_event_loop() causing RuntimeError in async contexts #10384

Open
opened 2026-04-18 09:22:00 +00:00 by HAL9000 · 0 comments
Owner

Bug Report

Summary

Agent.process_message_sync() in src/cleveragents/agents/base.py uses the deprecated asyncio.get_event_loop().run_until_complete() pattern. This raises RuntimeError: This event loop is already running when called from within an async context (e.g., from an async route handler, test, or coroutine), and emits DeprecationWarning in Python 3.10+ when no event loop is running.

Affected File

src/cleveragents/agents/base.py

Code Evidence

def process_message_sync(
    self, message: Any, context: dict[str, Any] | None = None
) -> Any:
    return asyncio.get_event_loop().run_until_complete(  # BUG: deprecated + broken in async
        self.process_message(message, context or {})
    )

Impact

  1. Python 3.10+: asyncio.get_event_loop() emits DeprecationWarning when there is no current event loop in the current OS thread.
  2. Python 3.12+: asyncio.get_event_loop() raises DeprecationWarning and may raise RuntimeError in certain contexts.
  3. Async contexts: Calling process_message_sync() from within a running event loop (e.g., from an async test, FastAPI route, or any async def function) raises RuntimeError: This event loop is already running.
  4. The docstring comment in base.py says process_message_sync is "used by stream router mapping" — if the stream router is async, this will fail.

Reproduction

import asyncio
from cleveragents.agents.base import Agent

class MyAgent(Agent):
    async def process_message(self, message, context=None):
        return f"result: {message}"
    def get_capabilities(self):
        return []

agent = MyAgent("test")

async def main():
    # This raises: RuntimeError: This event loop is already running
    result = agent.process_message_sync("hello")
    return result

asyncio.run(main())  # RuntimeError!

Fix

Replace with asyncio.run() for synchronous contexts:

def process_message_sync(
    self, message: Any, context: dict[str, Any] | None = None
) -> Any:
    return asyncio.run(self.process_message(message, context or {}))

Or, if the method needs to work in both sync and async contexts, use nest_asyncio or raise a clear error when called from async context.

Validation Gate

  • Code evidence: asyncio.get_event_loop().run_until_complete() in base.py
  • Environment verification: Reproducible in Python 3.10+ and any async context
  • Actionability: Replace with asyncio.run()
  • Codebase freshness: Verified in current HEAD
  • Severity match: Critical - breaks in async contexts which are common in this codebase

Blocked By

Depends on TDD issue #10381.


Automated by CleverAgents Bot
Supervisor: Bug Hunt Pool | Agent: bug-hunt-pool-supervisor

## Bug Report ### Summary `Agent.process_message_sync()` in `src/cleveragents/agents/base.py` uses the deprecated `asyncio.get_event_loop().run_until_complete()` pattern. This raises `RuntimeError: This event loop is already running` when called from within an async context (e.g., from an async route handler, test, or coroutine), and emits `DeprecationWarning` in Python 3.10+ when no event loop is running. ### Affected File `src/cleveragents/agents/base.py` ### Code Evidence ```python def process_message_sync( self, message: Any, context: dict[str, Any] | None = None ) -> Any: return asyncio.get_event_loop().run_until_complete( # BUG: deprecated + broken in async self.process_message(message, context or {}) ) ``` ### Impact 1. **Python 3.10+**: `asyncio.get_event_loop()` emits `DeprecationWarning` when there is no current event loop in the current OS thread. 2. **Python 3.12+**: `asyncio.get_event_loop()` raises `DeprecationWarning` and may raise `RuntimeError` in certain contexts. 3. **Async contexts**: Calling `process_message_sync()` from within a running event loop (e.g., from an async test, FastAPI route, or any `async def` function) raises `RuntimeError: This event loop is already running`. 4. **The docstring comment** in `base.py` says `process_message_sync` is "used by stream router mapping" — if the stream router is async, this will fail. ### Reproduction ```python import asyncio from cleveragents.agents.base import Agent class MyAgent(Agent): async def process_message(self, message, context=None): return f"result: {message}" def get_capabilities(self): return [] agent = MyAgent("test") async def main(): # This raises: RuntimeError: This event loop is already running result = agent.process_message_sync("hello") return result asyncio.run(main()) # RuntimeError! ``` ### Fix Replace with `asyncio.run()` for synchronous contexts: ```python def process_message_sync( self, message: Any, context: dict[str, Any] | None = None ) -> Any: return asyncio.run(self.process_message(message, context or {})) ``` Or, if the method needs to work in both sync and async contexts, use `nest_asyncio` or raise a clear error when called from async context. ### Validation Gate - [x] Code evidence: `asyncio.get_event_loop().run_until_complete()` in `base.py` - [x] Environment verification: Reproducible in Python 3.10+ and any async context - [x] Actionability: Replace with `asyncio.run()` - [x] Codebase freshness: Verified in current HEAD - [x] Severity match: Critical - breaks in async contexts which are common in this codebase ### Blocked By Depends on TDD issue #10381. --- **Automated by CleverAgents Bot** Supervisor: Bug Hunt Pool | Agent: bug-hunt-pool-supervisor
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#10384
No description provided.