🔴 Required Information
Describe the Bug:
EventsCompactionConfig.compaction_interval and overlap_size are declared as plain required ints with no value constraints, unlike their sibling fields token_threshold (Field(gt=0)) and event_retention_size (Field(ge=0)).
As a result, compaction_interval=0 (or a negative value) is silently accepted and makes the sliding-window compaction trigger fire on every invocation. In _run_compaction_for_sliding_window (src/google/adk/apps/compaction.py) the guard
if len(new_invocation_ids) < config.compaction_interval:
return None # Not enough new invocations to trigger compaction.
can never be true when compaction_interval <= 0, so compaction runs after every invocation instead of being throttled.
This is also confusing because 0 means different things for the two sliding-window fields: overlap_size=0 is a valid "no overlap", but compaction_interval=0 is a degenerate "fire every time" (not "disable").
Steps to Reproduce:
pip install google-adk
- Run the snippet below (or construct an
App with events_compaction_config=EventsCompactionConfig(compaction_interval=0, overlap_size=0, summarizer=...)).
- Observe that construction succeeds with
compaction_interval=0.
- With such a config, sliding-window compaction fires on every invocation.
Expected Behavior:
compaction_interval=0 (and negative values) should be rejected at construction time with a ValidationError, consistent with token_threshold (gt=0) and event_retention_size (ge=0). overlap_size should allow 0 (no overlap) but reject negatives.
Observed Behavior:
EventsCompactionConfig(compaction_interval=0, overlap_size=0) is accepted with no error, and downstream causes compaction to run on every invocation.
Environment Details:
- ADK Library Version (pip show google-adk): 2.4.0
- Desktop OS: macOS
- Python Version (python -V): 3.10
Model Information:
- Are you using LiteLLM: No
- Which model is being used: N/A (configuration-validation bug, model-agnostic)
🟡 Optional Information
Regression:
N/A — appears to have been present since EventsCompactionConfig was introduced.
Additional Context:
Suggested fix (small, mirrors the existing validated sibling fields):
compaction_interval: int = Field(gt=0)
overlap_size: int = Field(ge=0) (0 = no overlap, still valid)
Happy to send a PR with tests.
Separately (tracked as a feature request, not this bug): because compaction_interval / overlap_size are required, there is currently no clean way to enable only the token-threshold trigger without setting compaction_interval to a large sentinel value.
Minimal Reproduction Code:
from google.adk.apps.app import EventsCompactionConfig
# Accepted today (no error); makes sliding-window compaction fire every invocation.
cfg = EventsCompactionConfig(compaction_interval=0, overlap_size=0)
print(cfg.compaction_interval) # -> 0
# Negative is also accepted today.
EventsCompactionConfig(compaction_interval=-1, overlap_size=0)
How often has this issue occurred?:
🔴 Required Information
Describe the Bug:
EventsCompactionConfig.compaction_intervalandoverlap_sizeare declared as plain requiredints with no value constraints, unlike their sibling fieldstoken_threshold(Field(gt=0)) andevent_retention_size(Field(ge=0)).As a result,
compaction_interval=0(or a negative value) is silently accepted and makes the sliding-window compaction trigger fire on every invocation. In_run_compaction_for_sliding_window(src/google/adk/apps/compaction.py) the guardcan never be true when
compaction_interval <= 0, so compaction runs after every invocation instead of being throttled.This is also confusing because
0means different things for the two sliding-window fields:overlap_size=0is a valid "no overlap", butcompaction_interval=0is a degenerate "fire every time" (not "disable").Steps to Reproduce:
pip install google-adkAppwithevents_compaction_config=EventsCompactionConfig(compaction_interval=0, overlap_size=0, summarizer=...)).compaction_interval=0.Expected Behavior:
compaction_interval=0(and negative values) should be rejected at construction time with aValidationError, consistent withtoken_threshold(gt=0) andevent_retention_size(ge=0).overlap_sizeshould allow0(no overlap) but reject negatives.Observed Behavior:
EventsCompactionConfig(compaction_interval=0, overlap_size=0)is accepted with no error, and downstream causes compaction to run on every invocation.Environment Details:
Model Information:
🟡 Optional Information
Regression:
N/A — appears to have been present since
EventsCompactionConfigwas introduced.Additional Context:
Suggested fix (small, mirrors the existing validated sibling fields):
compaction_interval: int = Field(gt=0)overlap_size: int = Field(ge=0)(0 = no overlap, still valid)Happy to send a PR with tests.
Separately (tracked as a feature request, not this bug): because
compaction_interval/overlap_sizeare required, there is currently no clean way to enable only the token-threshold trigger without settingcompaction_intervalto a large sentinel value.Minimal Reproduction Code:
How often has this issue occurred?: