Fixes https://github.com/google/adk-python/issues/3174
The event compaction process, configured via `EventsCompactionConfig`, was
previously scheduled as a background task using `asyncio.create_task`.
Because Python's `asyncio.create_task` only holds a weak reference to
the created task and no strong reference was maintained by ADK, the
compaction task could be garbage-collected before it finished executing.
This resulted in event compaction failing silently or only partially
running, preventing session history from being summarized.
### Approaches Considered
Two approaches were considered to fix this:
1. **`asyncio.create_task` + Reference:** Create the task with `create_task` and store a strong reference to it (e.g., in a `set` on the [Runner](http://_vscodecontentref_/0) instance), removing it only when complete via `task.add_done_callback()`.
* **Pros:** The [run_async](http://_vscodecontentref_/1) async generator finishes immediately after yielding the last agent event.
* **Cons:** Adds complexity to the Runner state; background task failures are silent to the [run_async](http://_vscodecontentref_/2) caller; requires enhancement to `runner.close()` to correctly manage pending tasks on shutdown.
2. **`await`:** Directly `await` the compaction coroutine at the end of [run_async](http://_vscodecontentref_/3) after all agent events have been yielded.
* **Pros:** Simple to implement; ensures compaction runs to completion; failures during compaction propagate immediately to the [run_async](http://_vscodecontentref_/4) caller, making them visible and easier to debug.
* **Cons:** The `async for` loop iterating over [run_async](http://_vscodecontentref_/5) will not terminate until compaction finishes.
### Decision
This change implements the `await` approach. Although it means the `async for` loop takes longer to terminate when compaction occurs, it was chosen for its **simplicity and robustness**. Ensuring that compaction either succeeds or fails visibly is preferable to silent background failures.
All agent response events are yielded *before* compaction starts, so there is **no user-perceived delay in receiving the agent's answer** for the current turn.
### Integration Note for Users
Because compaction is now awaited, code consuming events via `async for event in runner.run_async(...)` will only finish iterating *after* compaction is complete (if compaction is triggered for that invocation).
If your application only needs the agent's response to proceed (e.g., displaying a message in a UI and allowing the user to reply), you can process events as they arrive and initiate the next turn without waiting for the `async for` loop to fully terminate. A new call to [run_async](http://_vscodecontentref_/6) for the next user query can be made immediately and will execute concurrently.
**Example:**
```python
async def handle_agent_turn(runner, message):
print("Agent is thinking...")
async for event in runner.run_async(user_id='...', session_id='...', new_message=message):
# Stream events to UI, log, etc.
if event.author == 'model' and event.content and event.content.parts[0].text:
print(f"Agent response: {event.content.parts[0].text}")
# The agent has provided a text response.
# The application can now enable user input for the next turn,
# even though this async for loop might not finish immediately
# if compaction is running.
print("Invocation complete (including compaction if any).")
# In your application:
# A new call to handle_agent_turn(runner, next_message) can be made
# as soon as the user provides the next input, without waiting for
# the previous call's generator to be exhausted.
Co-authored-by: Hangfei Lin <hangfei@google.com>
PiperOrigin-RevId: 833885375
this creates service_factory to handle .adk folder changes (including per-agent .adk defaults and in-memory/custom URI handling)
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 833875524
This change loads the agent or app from the specified directory before creating the session. This allows using the correct application name (from the `App` object if applicable) when initializing the session, rather than always defaulting to the folder name. The variable `root_agent` is also renamed to `agent_or_app` to better reflect that it can be either an Agent or an App
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 833839070
Currently logic to check for a disconnected session only checks for certain headers but doesn't detect all cases, leading to situations where it tries to connect to a session that is down. This adds logic so that we ping the server to check if it is disconnected. Fixes https://github.com/google/adk-python/issues/3321.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 833487825
Updates type annotations to use built-in types like `list` and `dict`, and uses `| None` for optional types, along with adding `from __future__ import annotations`
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 832522395
Currently logic to check for a disconnected session only checks for certain headers but doesn't detect all cases, leading to situations where it tries to connect to a session that is down. This adds logic so that we ping the server to check if it is disconnected. Fixes https://github.com/google/adk-python/issues/3321.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 832460068
This update enhances the BigQuery agent analytics plugin:
* **Schema Field Descriptions:** The recommended BigQuery table schema now includes descriptions for each field, improving data understandability.
* **Optimized Table Structure:** The plugin now creates the table with daily partitioning on `timestamp` and clustering on `event_type`, `agent`, and `user_id` by default.
* **Truncation Flag:** A new boolean field `is_truncated` is added to the schema to show if the `content` was truncated.
PiperOrigin-RevId: 832436799
In order to make evals more resilient to temporary model failures, we add retry options to llm_requests that are made during evals.
Note that this is a fall back option, if the developer has already specified their own retry options, then those will be honored.
Co-authored-by: Ankur Sharma <ankusharma@google.com>
PiperOrigin-RevId: 832383755