Published Build3 min read
ADK 2.6.3 Deleted a 187-Line Monkey Patch. Two of Its Three Jobs Came With It
A Gemini Live project on google-adk 1.27.2 could only talk to a 3.1 model because a patch file rewrote three call sites at import time. Upstream now does two of those three things.
Written for builders.See today for builders
What happened
- A dev.to write-up by xbill states that deleting 187 lines of monkey patch was the single biggest benefit of moving to ADK 2.x, but that it was not the only benefit and not the last thing that needed fixing.
- The project described is a biometric security scanner built to exercise parts of the Gemini Live API that a text chatbot never touches: a browser captures webcam and microphone, streams both to a FastAPI backend over a single WebSocket, and the backend forwards them to Gemini 3.1 Flash Live through the Agent Development Kit; the model watches the video feed, counts the fingers being held up, and calls a tool.
- Three tools are registered: report_digit(count), the detected finger count that drives the UI; trigger_system_error(), fired on an offensive gesture, which terminates the session; and trigger_heavy_metal_mode(), fired on the Devil's Horns gesture as a secret override.
- The transport uses binary WebSocket frames with a 1-byte type prefix, 1 for audio and 2 for JPEG, with 16 kHz PCM going up and 24 kHz PCM coming back, played through an AudioWorklet so the main thread stays free.
- The project runs locally with make run, or on Cloud Run with make deploy, and the code is at github.com/xbill9/way-back-home, where level_3 is the original design and level_3_new is the current one.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
The single biggest benefit of moving to Google's Agent Development Kit 2.x was deleting 187 lines of monkey patch, according to a dev.to write-up by xbill on a Gemini Live project [1]. The same post is explicit that this was neither the only benefit nor the last thing that needed fixing, which is the part worth planning around [1].
The workload matters here because it exercises the bidirectional path rather than the text one. The project is a biometric security scanner: a browser captures webcam and microphone, streams both to a FastAPI backend over a single WebSocket, and the backend forwards them to Gemini 3.1 Flash Live through the ADK, where the model watches the feed, counts fingers held up, and calls a tool [2]. Three tools are registered, including report_digit(count) for the detected count and trigger_system_error() for an offensive gesture, which ends the session [3]. The transport is deliberately unclever: binary frames with a 1-byte type prefix, 1 for audio and 2 for JPEG, 16 kHz PCM up, 24 kHz PCM back through an AudioWorklet [4].
On google-adk 1.27.2, that ran only because a file named patch_adk.py, 187 lines long, was applied at import time before anything else could execute [7]. The cause was a shape change: Gemini 3.1 deprecated media_chunks, the field 1.x ADK used to send realtime media, so a 1.x client talking to a 3.1 Live model sent the old shape and got nothing useful back [8]. The patch wrapped three call sites: live.AsyncSession.send_realtime_input, to unroll media_chunks into the new typed keywords; GeminiLlmConnection.send_realtime, to route each blob to audio=, video= or text= by mime type; and AudioCacheManager.cache_audio, to guard against a NoneType blob that would otherwise raise [9]. The author's own case against keeping it is the honest one: a patch either becomes redundant, becomes wrong, or silently stops applying because the wrapped method was renamed [10].
In google-adk 2.6.3 the framework detects the model generation and dispatches itself, and patch_adk.py was deleted outright [11]. In send_realtime(), a Blob on a 3.x Live connection goes to send_realtime_input(audio=) for audio mime types and video= for image mime types, with everything else logged as "Blob not sent" and discarded [12]. Single-part text Content is routed to send_realtime_input(text=) rather than going out as client content, which matches the Live API's guidance that send_client_content is only for seeding history [14].
Read the third branch as the new failure mode. A blob with a missing or unexpected mime type is not guessed at, it is dropped, and the only evidence is a log line [13]. Under the old patch, mime-type routing was code you owned in your repo; now it is upstream behaviour that fails without an exception. That is one of three patch responsibilities that changed hands cleanly; the third did not. Upstream still calls len(audio_blob.data) unguarded, so the NoneType guard was not carried over, and it stays deleted because no path in this application produces a blob with data=None [15]. That is a decision resting on a code audit of one app, not on a framework guarantee [17].
The jump also crossed a major version boundary, 1.27.2 to 2.6.3, so nothing about the surrounding API surface should be assumed stable [16].
Claim ledger
Ranked by verification strength, evidence, and original report placement.
- [1]
A dev.to write-up by xbill states that deleting 187 lines of monkey patch was the single biggest benefit of moving to ADK 2.x, but that it was not the only benefit and not the last thing that needed fixing.
- [2]
The project described is a biometric security scanner built to exercise parts of the Gemini Live API that a text chatbot never touches: a browser captures webcam and microphone, streams both to a FastAPI backend over a single WebSocket, and the backend forwards them to Gemini 3.1 Flash Live through the Agent Development Kit; the model watches the video feed, counts the fingers being held up, and calls a tool.
- [3]
Three tools are registered: report_digit(count), the detected finger count that drives the UI; trigger_system_error(), fired on an offensive gesture, which terminates the session; and trigger_heavy_metal_mode(), fired on the Devil's Horns gesture as a secret override.
- [4]
The transport uses binary WebSocket frames with a 1-byte type prefix, 1 for audio and 2 for JPEG, with 16 kHz PCM going up and 24 kHz PCM coming back, played through an AudioWorklet so the main thread stays free.
- [5]
The project runs locally with make run, or on Cloud Run with make deploy, and the code is at github.com/xbill9/way-back-home, where level_3 is the original design and level_3_new is the current one.
- [7]
The original build ran on google-adk 1.27.2 and worked only because a file named patch_adk.py, 187 lines long, sat next to it and was applied at import time before anything else could run.
Sources & coverage · 1 publisher
The reporting this story was synthesized from, earliest first. Every link goes to the original.
- dev.toxbillAug 12Do I Still Need a Monkey Patch for Gemini Live?
Cited in this coverage: xbill, dev.to
Cited in this coverage: xbill, dev.to, quoting google-adk source
Cited in this coverage: xbill, dev.to (text truncated)

