Skip to content

EventsCompactionConfig fails with 'RuntimeError: Event loop is closed' during LLM summarization #4282

@darshanvalia

Description

@darshanvalia

🔴 Required Information

Describe the Bug:
When using EventsCompactionConfig with LlmEventSummarizer, the compaction triggers correctly after the configured compaction_interval but fails during the async LLM summarization call with RuntimeError: Event loop is closed. The error occurs during HTTP connection cleanup after the summarization LLM request. The compaction attempts to run but never completes, resulting in no CompactedEvent being created and the full conversation history being retained.

Steps to Reproduce:

  1. Configure an ADK App with EventsCompactionConfig:
from google.adk.apps.app import App, EventsCompactionConfig
from google.adk.apps.llm_event_summarizer import LlmEventSummarizer
from google.adk.models import Gemini

compaction_summarizer = LlmEventSummarizer(
    llm=Gemini(model="gemini-2.5-flash")
)

adk_app = App(
    name="my_agent",
    root_agent=my_agent,
    events_compaction_config=EventsCompactionConfig(
        summarizer=compaction_summarizer,
        compaction_interval=5,
        overlap_size=1,
    ),
)
  1. Deploy to Vertex AI Agent Engine using vertexai.agent_engines.create()
  2. Send 5+ messages in a conversation
  3. Observe error in logs after the 5th message

Expected Behavior:
After compaction_interval events, the LlmEventSummarizer should successfully call the LLM to summarize older events and create a CompactedEvent, reducing the conversation context size.

Observed Behavior:
The compaction triggers (stack trace shows _run_compaction_for_sliding_window is called) but fails during HTTP connection cleanup with:

RuntimeError: Event loop is closed

The conversation history remains intact with all messages, and no summarization occurs.

Environment Details:

  • ADK Library Version: >=1.23.0
  • Desktop OS: Deployed on Google Cloud (Vertex AI Agent Engine)
  • Python Version: 3.10

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: gemini-2.5-flash (for summarization), gemini-2.0-flash (for agent)

🟡 Optional Information

Regression:
N/A - First time using EventsCompactionConfig

Logs:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.10/threading.py", line 953, in run
    self._target(*self._args, **self._kwargs)
  File ".../google/adk/runners.py", line 436, in _asyncio_thread_main
    asyncio.run(_invoke_run_async())
  File "/usr/local/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File ".../google/adk/runners.py", line 429, in _invoke_run_async
    async for event in agen:
  File ".../google/adk/runners.py", line 562, in run_async
    async for event in agen:
  File ".../google/adk/runners.py", line 557, in _run_with_trace
    await _run_compaction_for_sliding_window(
  File ".../google/adk/apps/compaction.py", line 194, in _run_compaction_for_sliding_window
    await app.events_compaction_config.summarizer.maybe_summarize_events(
  File ".../google/adk/apps/llm_event_summarizer.py", line 107, in maybe_summarize_events
    async for llm_response in self._llm.generate_content_async(
  File ".../google/adk/models/google_llm.py", line 241, in generate_content_async
    response = await self.api_client.aio.models.generate_content(
  File ".../google/genai/models.py", line 7042, in generate_content
    response = await self._generate_content(
  File ".../google/genai/models.py", line 5848, in _generate_content
    response = await self._api_client.async_request(
  File ".../google/genai/_api_client.py", line 1432, in async_request
    result = await self._async_request(
  File ".../google/genai/_api_client.py", line 1365, in _async_request
    return await self._async_retry(
  File ".../tenacity/asyncio/__init__.py", line 111, in __call__
    do = await self.iter(retry_state=retry_state)
  File ".../tenacity/asyncio/__init__.py", line 153, in iter
    result = await action(retry_state)
  File ".../tenacity/_utils.py", line 99, in inner
    return call(*args, **kwargs)
  File ".../tenacity/__init__.py", line 420, in exc_check
    raise retry_exc.reraise()
  File ".../tenacity/__init__.py", line 187, in reraise
    raise self.last_attempt.result()
  File "/usr/local/lib/python3.10/concurrent/futures/_base.py", line 451, in result
    return self.__get_result()
  File "/usr/local/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
    raise self._exception
  File ".../tenacity/asyncio/__init__.py", line 114, in __call__
    result = await fn(*args, **kwargs)
  File ".../google/genai/_api_client.py", line 1338, in _async_request_once
    client_response = await self._async_httpx_client.request(
  File ".../httpx/_client.py", line 1540, in request
    return await self.send(request, auth=auth, follow_redirects=follow_redirects)
  File ".../httpx/_client.py", line 1629, in send
    response = await self._send_handling_auth(
  File ".../httpx/_client.py", line 1657, in _send_handling_auth
    response = await self._send_handling_redirects(
  File ".../httpx/_client.py", line 1694, in _send_handling_redirects
    response = await self._send_single_request(request)
  File ".../httpx/_client.py", line 1730, in _send_single_request
    response = await transport.handle_async_request(request)
  File ".../httpx/_transports/default.py", line 394, in handle_async_request
    resp = await self._pool.handle_async_request(req)
  File ".../httpcore/_async/connection_pool.py", line 256, in handle_async_request
    raise exc from None
  File ".../httpcore/_async/connection_pool.py", line 229, in handle_async_request
    await self._close_connections(closing)
  File ".../httpcore/_async/connection_pool.py", line 345, in _close_connections
    await connection.aclose()
  File ".../httpcore/_async/connection.py", line 173, in aclose
    await self._connection.aclose()
  File ".../httpcore/_async/http11.py", line 258, in aclose
    await self._network_stream.aclose()
  File ".../httpcore/_backends/anyio.py", line 53, in aclose
    await self._stream.aclose()
  File ".../anyio/streams/tls.py", line 241, in aclose
    await self.transport_stream.aclose()
  File ".../anyio/_backends/_asyncio.py", line 1329, in aclose
    self._transport.close()
  File "/usr/local/lib/python3.10/asyncio/selector_events.py", line 706, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 753, in call_soon
    self._check_closed()
  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 515, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

Additional Context:

  • This occurs when deployed to Vertex AI Agent Engine (ReasoningEngine)
  • The compaction runs in a separate thread (_asyncio_thread_main in runners.py)
  • The LLM request appears to complete, but the error occurs during HTTP connection cleanup
  • The event loop seems to be closed before the httpx/httpcore connection pool can properly close its connections

Minimal Reproduction Code:

from google.adk.apps.app import App, EventsCompactionConfig
from google.adk.apps.llm_event_summarizer import LlmEventSummarizer
from google.adk.models import Gemini
from google.adk.agents import Agent
from vertexai import agent_engines
from vertexai.preview import reasoning_engines

# Create a simple agent
agent = Agent(
    name="test_agent",
    model="gemini-2.0-flash",
    instruction="You are a helpful assistant.",
)

# Configure compaction
summarizer = LlmEventSummarizer(llm=Gemini(model="gemini-2.5-flash"))
app = App(
    name="test_app",
    root_agent=agent,
    events_compaction_config=EventsCompactionConfig(
        summarizer=summarizer,
        compaction_interval=5,
        overlap_size=1,
    ),
)

# Deploy to Agent Engine
adk_app = reasoning_engines.AdkApp(app=app, enable_tracing=False)
deployed = agent_engines.create(
    agent_engine=adk_app,
    requirements=["google-adk>=1.23.0"],
    display_name="test-compaction",
)

# Send 5+ messages to trigger compaction -> Error occurs

How often has this issue occurred?:

  • Always (100%) - Occurs every time compaction_interval is reached

Metadata

Metadata

Assignees

No one assigned

    Labels

    services[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions