Google let Gemini 4 Argon run unattended for 11 hours on its Agent Development Kit, a Python codebase of about 205,000 lines. Two of its six proposed optimizations shipped in ADK 2.12.0 on 13 October, in a 22-file commit that says "Argon generated these changes". Maintainers cut the other four in review.
I benchmarked 2.11.0 against 2.12.0 on an M2 Pro. With the in-memory session store, ADK's overhead before the model call at turn 150 dropped from 51 to 25 milliseconds. With the SQLite-backed DatabaseSessionService, it stayed at about 45 milliseconds. Before the change, the in-memory store was the slower of the two.
The faster import holds up too: from google.adk.agents import LlmAgent went from 474 to 357 milliseconds. A fresh process still reached its first model request in 579 and 584 milliseconds, because the deferred modules load on the first turn. Your local evals got faster, and the gap between them and production got wider.
What Argon actually changed
The Google Developers Blog post from 13 October, written up by InfoQ on 24 October, is unusually candid about the run. Round one got a one-paragraph prompt and no repository guidance. Argon wrote a benchmark script seven minutes in and spent 70 minutes measuring before it edited a line. It also changed the public JSON schema of ADK's auth model and ran only 216 of the roughly 17,000 tests.
Round two added the maintainers' rules as files under .agents/skills, plus Antigravity's /goal mode so the objective survived context compaction. That run read 12 guideline files, set baselines on four workloads, opened one pull request touching 32 files, and reran all 16,892 unit tests three minutes before it stopped.
The two changes that shipped:
InMemorySessionServiceused to deep-copy the whole stored session on every read, then throw away the events the caller didn't ask for. It now filters first and copies only what it returns, andEventandSessionget a hand-written__deepcopy__that skips Pydantic's generic path.list_sessionscopies no events at all.import google.adkno longer pulls in OpenTelemetry, FastAPI, Starlette and the LLM flow modules up front. They load through lazy module accessors on first use.
The four that got cut are the more useful part of the write-up. A multi-agent event cache gained 17 percent on a synthetic benchmark but keyed on a weak reference that could serve stale data if Python reused a memory address. A telemetry shortcut read a private attribute inside OpenTelemetry. A rewrite of history formatting made a core path harder to read and moved nothing on Google's holdout benchmark. A replay index only helped synthetic replay tests. The blog's summary line: "the agent explores, the maintainer subtracts."
The numbers on my machine
I built two benchmarks against the published wheels, Python 3.12.2, Pydantic 2.14.1, SQLAlchemy 2.1.6 and aiosqlite.
The first one runs a real Runner with a fake model that returns instantly. Every invocation sends a user message, the model asks for four parallel calls to a local tool that returns eight rows of about 120 characters each, and then it answers. I timed how long ADK took from run_async to the model call at invocations 50 and 150, with garbage collection off, three runs per configuration:
| Store | Version | Turn 50 | Turn 150 | 151 turns total |
|---|---|---|---|---|
| In-memory | 2.11.0 | 18 to 20 ms | 51 to 52 ms | 5.4 to 5.9 s |
| In-memory | 2.12.0 | 8 to 11 ms | 25 to 26 ms | 3.3 to 3.9 s |
| SQLite | 2.11.0 | 17 to 23 ms | 44 to 51 ms | 6.1 to 6.9 s |
| SQLite | 2.12.0 | 20 to 22 ms | 42 to 47 ms | 6.3 to 8.2 s |
The second one skips the runner and times get_session alone on a session holding 600 such events. In-memory went from 26 to 27 milliseconds down to 8 to 9. SQLite read in 22 to 25 milliseconds on both versions.
My in-memory gain is larger than Google's 40 percent, likely because my tool payloads make each event heavier to copy. The direction is the same, and so is the part Google states plainly: database, SQLite, Gemini platform, Firestore and Redis session stores deserialize from storage instead of deep-copying in memory, so "their read times don't change here." What the blog doesn't show is the before picture. On 2.11.0 the in-memory store, the one you'd assume is the fast baseline, was slower to read than a SQLite file on disk.
Where this bites
ADK's in-memory store is what InMemoryRunner uses, and the blog lists where that runs: local evaluation loops, CI test suites, and default Cloud Run or GKE deployments that never set a database URI. The first two are where most teams measure latency. The production deployments that persist sessions are on one of the stores the change doesn't reach.
On 2.11.0 those two numbers happened to sit close together, so a latency budget set from local evals roughly held in production. On 2.12.0 the local number halved and the production number didn't move. At turn 150 my in-memory run spent 25 milliseconds per invocation before the model saw anything, and the SQLite run spent 45. Against Postgres or Firestore over a network, I'd expect that gap to grow, though I didn't measure it.
The import win has the same shape. Bare import google.adk loaded 67 modules on both versions, because the package root was already lazy before this change. The win shows up on the import people actually write: from google.adk.agents import LlmAgent loaded 727 modules on 2.11.0 and 540 on 2.12.0, and OpenTelemetry, FastAPI and Starlette dropped out of the list. By the time my fake model received its first request, both versions had loaded over 1,100 modules, OpenTelemetry included. CLI commands and test discovery get the 117 milliseconds. A cold container serving its first user doesn't. Google's own advice is to send a warm-up request before taking traffic.
What to do
Upgrade to 2.12.0 or later if you use the in-memory store anywhere. The gain is real and the tests are thorough. The same file kept getting fixes afterwards: on 26 October a contributor's patch made create_session copy the initial state dict instead of storing the caller's reference.
Then rerun your latency benchmark against the session store you deploy with. If your evals use InMemoryRunner and production uses DatabaseSessionService, add one eval job that points at a SQLite file or a disposable Postgres, so the overhead you budget for is the one your users get.
And read the four rejections before you run your own overnight agent. A weak-reference cache that could hand back another session's data under the right garbage-collection timing made it into a pull request that had just run the full test suite. A human caught it by reading. That is the job the 11-hour run didn't remove.