<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Çalgan Aygün</title>
    <description>The latest articles on DEV Community by Çalgan Aygün (@calganaygun).</description>
    <link>https://dev.to/calganaygun</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F389991%2F259e54a7-492e-4848-b98e-950b56893521.jpg</url>
      <title>DEV Community: Çalgan Aygün</title>
      <link>https://dev.to/calganaygun</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/calganaygun"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Wed, 12 Aug 2026 06:31:58 +0000</pubDate>
      <link>https://dev.to/calganaygun/-47ei</link>
      <guid>https://dev.to/calganaygun/-47ei</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/calganaygun/i-hacked-every-dumb-screen-in-my-house-into-one-dashboard-3e8f" class="crayons-story__hidden-navigation-link"&gt;I hacked every dumb screen in my house into one dashboard&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/calganaygun" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F389991%2F259e54a7-492e-4848-b98e-950b56893521.jpg" alt="calganaygun profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/calganaygun" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Çalgan Aygün
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Çalgan Aygün
                
              
              &lt;div id="story-author-preview-content-4283081" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/calganaygun" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F389991%2F259e54a7-492e-4848-b98e-950b56893521.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Çalgan Aygün&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/calganaygun/i-hacked-every-dumb-screen-in-my-house-into-one-dashboard-3e8f" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 31&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/calganaygun/i-hacked-every-dumb-screen-in-my-house-into-one-dashboard-3e8f" id="article-link-4283081"&gt;
          I hacked every dumb screen in my house into one dashboard
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gadget"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gadget&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/automation"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;automation&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/calganaygun/i-hacked-every-dumb-screen-in-my-house-into-one-dashboard-3e8f" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/calganaygun/i-hacked-every-dumb-screen-in-my-house-into-one-dashboard-3e8f#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Agent Sandboxes: Giving AI Agents Their Own Little Linux Box (And Why You Should Care)</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Fri, 07 Aug 2026 09:38:40 +0000</pubDate>
      <link>https://dev.to/gde/agent-sandboxes-giving-ai-agents-their-own-little-linux-box-and-why-you-should-care-jl4</link>
      <guid>https://dev.to/gde/agent-sandboxes-giving-ai-agents-their-own-little-linux-box-and-why-you-should-care-jl4</guid>
      <description>&lt;p&gt;&lt;strong&gt;Sourced from:&lt;/strong&gt; &lt;a href="https://docs.cloud.google.com/kubernetes-engine/docs/concepts/machine-learning/agent-sandbox" rel="noopener noreferrer"&gt;GKE Agent Sandbox docs&lt;/a&gt;, &lt;a href="https://github.com/kubernetes-sigs/agent-sandbox" rel="noopener noreferrer"&gt;kubernetes-sigs/agent-sandbox&lt;/a&gt;  &lt;/p&gt;




&lt;p&gt;So here is the thing. We are asking AI agents to do increasingly wild stuff. Write code. Browse the web. Run shell commands. Spin up browsers. Click around. Deploy websites. Use a computer like a human would. And for the most part, they are doing it.&lt;/p&gt;

&lt;p&gt;But there is a lurking problem that keeps platform engineers up at night.&lt;/p&gt;

&lt;p&gt;Where the hell is this code running?&lt;/p&gt;

&lt;p&gt;When you ask an agent to "run this script" or "install this package" or "check if that endpoint responds", you are effectively handing over a loaded gun to a very enthusiastic intern who has read every programming book but has absolutely zero survival instincts. That code could be malicious. Or buggy. Or it could just go nuclear on your host system because the agent decided to &lt;code&gt;rm -rf /&lt;/code&gt; thinking it was cleaning up temp files.&lt;/p&gt;

&lt;p&gt;That is where &lt;strong&gt;Agent Sandboxes&lt;/strong&gt; come in.&lt;/p&gt;

&lt;p&gt;Think of them as giving each agent its own airtight, disposable Linux container. A little VM crib. A playpen with rubber walls where they can run around and break things without ever touching your real infrastructure.&lt;/p&gt;

&lt;p&gt;And here is the kicker: this is not some vaporware future concept. Google Cloud ships Agent Sandbox as a managed GKE feature, and the open-source project behind the Kubernetes APIs lives under &lt;code&gt;kubernetes-sigs/agent-sandbox&lt;/code&gt;. You can run the open-source controller on your own Kubernetes cluster or use the managed GKE integration.&lt;/p&gt;




&lt;h2&gt;
  
  
  What GKE Agent Sandbox Actually Is
&lt;/h2&gt;

&lt;p&gt;Let me quote the docs directly so we are on the same page:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"GKE Agent Sandbox helps you manage isolated, stateful, and single-replica workloads on GKE. It is optimized for use cases like AI agent runtimes, where untrusted, LLM-generated code must be executed in a secure and performant environment."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What that means in plain English is:&lt;/p&gt;

&lt;p&gt;You get a Kubernetes-native way to spin up a single, stateful container that behaves like a lightweight VM. It has a stable hostname, persistent storage that survives restarts, kernel-level isolation, and network policies that default to "deny all". Your agent can connect to it, do its thing, disconnect, come back later, and find everything exactly as it left it. Or it can get garbage collected after a TTL and disappear without a trace.&lt;/p&gt;

&lt;p&gt;With a &lt;code&gt;SandboxWarmPool&lt;/code&gt;, already-started sandboxes can be assigned in milliseconds instead of waiting for a cold Pod to schedule, pull an image, and start. Cold-start latency still depends on your cluster, scheduler, image, and runtime.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture: CRDs All the Way Down
&lt;/h2&gt;

&lt;p&gt;The whole thing is built on Kubernetes custom resource definitions. There are four main ones that matter:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Sandbox (the core)
&lt;/h3&gt;

&lt;p&gt;This is the primitive. A single, stateful Pod with a stable hostname, optional persistent storage, and full lifecycle management. You create this, and the controller handles the rest -- Pod creation, network identity, volume provisioning, scheduled deletion, pausing, and resuming.&lt;/p&gt;

&lt;p&gt;It is the answer to the question: "I want a Linux box that stays alive for my agent. How do I get one?"&lt;/p&gt;

&lt;h3&gt;
  
  
  2. SandboxTemplate (the blueprint)
&lt;/h3&gt;

&lt;p&gt;Tired of writing the same YAML over and over? Templates let you codify runtime configuration once -- image, resource limits, runtime class (gVisor, Kata, standard), network policies, environment variables -- and reuse them everywhere. Platform teams define the templates. Developers just pick one and go.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. SandboxClaim (the request)
&lt;/h3&gt;

&lt;p&gt;This is the user-facing abstraction. In the current &lt;code&gt;v1beta1&lt;/code&gt; API, a developer or agent SDK creates a &lt;code&gt;SandboxClaim&lt;/code&gt; that references a &lt;code&gt;SandboxWarmPool&lt;/code&gt;. The warm pool references the &lt;code&gt;SandboxTemplate&lt;/code&gt;. The controller adopts an available pre-warmed sandbox from that pool, or creates capacity according to the pool configuration, and hands back a ready-to-use environment.&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;Claim Model&lt;/strong&gt; in action. You separate the &lt;em&gt;what&lt;/em&gt; (I need a sandbox) from the &lt;em&gt;how&lt;/em&gt; (here is where it runs on the cluster). And honestly? This is the pattern Kubernetes has needed for stateful workloads for a long time.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. SandboxWarmPool (the performance hack)
&lt;/h3&gt;

&lt;p&gt;Here is where it gets fast. A &lt;code&gt;SandboxWarmPool&lt;/code&gt; maintains a set of pre-warmed Pod instances in a ready state. When a claim comes in, the controller instantly assigns a Pod from the pool instead of waiting for image pulls and container startup.&lt;/p&gt;

&lt;p&gt;Warm pools reduce provisioning latency by keeping Sandbox instances pre-created and ready to be claimed. On GKE, Pod snapshots are a separate feature that can save and restore sandbox state for pause/resume and faster recovery; they are not required for a warm pool to work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security: Default Deny Is the Only Way
&lt;/h2&gt;

&lt;p&gt;Here is something that does not get talked about enough. When you give an agent a Linux box, you are trusting it with network access. A lot of agent sandbox solutions just throw a container at you and say "good luck".&lt;/p&gt;

&lt;p&gt;GKE Agent Sandbox implements a &lt;strong&gt;Default Deny&lt;/strong&gt; network security posture. Out of the box, code inside a sandbox cannot access your internal networks, your GKE control plane, or anything it should not. You explicitly define allowed egress and ingress rules in your &lt;code&gt;SandboxTemplate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Why does this matter? Because the most realistic threat from LLM-generated code is not "the AI becomes self-aware and takes over the world". It is "the AI wrote a Python script with a typo that accidentally hit the production database". Default deny prevents the accident. Fine-grained rules let you open specific doors when you need to (e.g., pip needs to reach PyPI, your agent needs to call an API).&lt;/p&gt;




&lt;h2&gt;
  
  
  Isolation Runtimes: Pick Your Poison
&lt;/h2&gt;

&lt;p&gt;The Sandbox CRD is runtime-agnostic. You can pair it with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Standard containers&lt;/strong&gt; -- fast, familiar, but minimal isolation between workloads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;gVisor&lt;/strong&gt; -- Google's user-space kernel. Gives you a second security boundary between your container and the host kernel. This is the recommended default for untrusted code execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kata Containers&lt;/strong&gt; -- hardware-level VM isolation. Each sandbox gets its own lightweight VM with its own kernel. The heaviest isolation, but also the strongest.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The beauty of the API is that switching between these is a field change in your &lt;code&gt;SandboxTemplate&lt;/code&gt;. You do not redesign your architecture. You just change &lt;code&gt;runtimeClassName&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Programmatic Access SDKs
&lt;/h2&gt;

&lt;p&gt;You do not need to write Kubernetes YAML to use this. There are first-class client libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python SDK&lt;/strong&gt; -- high-level client for LangChain, Vertex AI Agentic SDK, or any Python agent framework. Create, query, manage, and destroy sandboxes from your agent code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go SDK&lt;/strong&gt; -- for platform engineers building controllers and services on top of Agent Sandbox.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both SDKs abstract away the claim lifecycle. With the current Python SDK, your agent creates a sandbox with &lt;code&gt;client.create_sandbox(warmpool="python-sandbox-pool", namespace="default")&lt;/code&gt;. Behind the scenes, the SDK creates a &lt;code&gt;SandboxClaim&lt;/code&gt;, the controller assigns a Sandbox from the warm pool, and the client returns a handle for command execution and file operations.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Comparison Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;GKE Agent Sandbox (managed)&lt;/th&gt;
&lt;th&gt;kubernetes-sigs/agent-sandbox (open source)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed GKE add-on&lt;/td&gt;
&lt;td&gt;Self-installed Kubernetes controller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CRDs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sandbox, SandboxTemplate, SandboxClaim, SandboxWarmPool&lt;/td&gt;
&lt;td&gt;Sandbox, SandboxTemplate, SandboxClaim, SandboxWarmPool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Provisioning speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Warm pools reduce claim latency to millisecond-scale assignment&lt;/td&gt;
&lt;td&gt;Varies by cluster; warm pools avoid cold-start work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Isolation runtimes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;gVisor is required for managed Agent Sandbox workloads&lt;/td&gt;
&lt;td&gt;Runtime-agnostic through Kubernetes &lt;code&gt;runtimeClassName&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Default deny, fine-grained egress/ingress rules&lt;/td&gt;
&lt;td&gt;Configurable via standard K8s NetworkPolicies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Snapshots&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GKE Pod snapshots integrate with pause/resume&lt;/td&gt;
&lt;td&gt;Platform/runtime dependent; not required for warm pools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SDKs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python + Go&lt;/td&gt;
&lt;td&gt;Python + Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lifecycle mgmt&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed by Google (upgrades, patches)&lt;/td&gt;
&lt;td&gt;Self-managed via controller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Requires GKE 1.35.2-gke.1269000+ for full feature support&lt;/td&gt;
&lt;td&gt;Compatibility is release-specific; pin and test a release&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Licensing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Google Cloud SLA&lt;/td&gt;
&lt;td&gt;Apache 2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Google Cloud native teams who want "it just works"&lt;/td&gt;
&lt;td&gt;Multi-cloud, self-managed, air-gapped environments&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The Practical Takeaway
&lt;/h2&gt;

&lt;p&gt;Agent Sandbox solves a real problem that has been getting more urgent by the month. As LLMs get better at generating code, the volume of untrusted code being executed in agent loops is going to explode. Every one of those executions is an opportunity for something to go wrong.&lt;/p&gt;

&lt;p&gt;The old approach was: "just run it in a Docker container, it will be fine." A container can absolutely have a hostname and persistent volumes, but a one-off Docker workflow does not give you the Kubernetes-native &lt;code&gt;Sandbox&lt;/code&gt; lifecycle, claim/warm-pool allocation model, controller-managed identity, or stronger isolation runtime by itself. Those are the abstractions Agent Sandbox is adding.&lt;/p&gt;

&lt;p&gt;Agent Sandbox gives you those lifecycle and allocation primitives on top of Kubernetes, with SDKs in Python and Go. Isolation strength still depends on the runtime you configure; the managed GKE feature enforces gVisor for sandbox workloads.&lt;/p&gt;

&lt;p&gt;The open-source project under &lt;code&gt;kubernetes-sigs/agent-sandbox&lt;/code&gt; is the bedrock. Google's managed GKE add-on is the "press this button and it works" version. Both are worth knowing about.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Reality Check (Because Nothing Is Perfect)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Latency is low but not zero.&lt;/strong&gt; Even with warm pools and Pod snapshots, you are looking at hundreds of milliseconds to a second for sandbox assignment. For most agent use cases that is fine. For real-time loops that need sub-100ms responses, you will feel it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State management is your problem.&lt;/strong&gt; A sandbox is stateful by design. But what happens when an agent session crashes mid-execution? Do you keep the sandbox around? For how long? The TTL feature helps, but designing your garbage collection strategy is on you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network policy complexity is real.&lt;/strong&gt; Default deny is great for security. But the first time your agent cannot pip install because egress to PyPI is blocked, you will spend time debugging. And the first time a client's script needs to reach an internal API, you will be writing policy rules. It is manageable. But it is not zero-effort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Costs add up in warm pools.&lt;/strong&gt; Each pre-warmed Pod is a running container burning CPU and memory while it waits. If you keep a pool of 20 sandboxes hot, you are paying for 20 idle containers. The pause/resume via Pod snapshots helps offset this, but it is something to budget for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monitoring is a blank canvas.&lt;/strong&gt; Your existing Kubernetes monitoring? Probably set up for Deployments and StatefulSets. Ephemeral sandboxes that live for seconds to minutes are a different monitoring challenge. Log aggregation, metrics collection, cost attribution -- you are building some of this yourself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;If you want to reproduce the open-source setup on a fresh Kubernetes cluster, the sequence below is complete: install the controller &lt;strong&gt;and extensions&lt;/strong&gt;, create an executable Python runtime template, create a warm pool, give an in-cluster client the required RBAC, and run the SDK from a normal Python Pod.&lt;/p&gt;

&lt;p&gt;The commands below intentionally use &lt;code&gt;kubectl apply -f - &amp;lt;&amp;lt;'EOF'&lt;/code&gt; so you do not need to write YAML files locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install Agent Sandbox with the extension CRDs
&lt;/h3&gt;

&lt;p&gt;As of this writing, the current upstream release is &lt;code&gt;v0.5.3&lt;/code&gt;. Pinning the version makes the example reproducible instead of silently changing when a new release lands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"v0.5.3"&lt;/span&gt;

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://github.com/kubernetes-sigs/agent-sandbox/releases/download/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/sandbox-with-extensions.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for the controller components to come up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; agent-sandbox-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that both the core and extension APIs are installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl api-resources | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; sandbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see resources including &lt;code&gt;sandboxes&lt;/code&gt;, &lt;code&gt;sandboxclaims&lt;/code&gt;, &lt;code&gt;sandboxtemplates&lt;/code&gt;, and &lt;code&gt;sandboxwarmpools&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Create a Python runtime template and warm pool
&lt;/h3&gt;

&lt;p&gt;A plain &lt;code&gt;python:3.12-slim&lt;/code&gt; container with &lt;code&gt;sleep infinity&lt;/code&gt; is &lt;strong&gt;not enough&lt;/strong&gt; for &lt;code&gt;sandbox.commands.run()&lt;/code&gt;. The SDK sends HTTP requests to the runtime's &lt;code&gt;/execute&lt;/code&gt; endpoint on port &lt;code&gt;8888&lt;/code&gt;, so the sandbox image must implement that API.&lt;/p&gt;

&lt;p&gt;The upstream Python runtime image does exactly that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
apiVersion: extensions.agents.x-k8s.io/v1beta1
kind: SandboxTemplate
metadata:
  name: python-sandbox-template
  namespace: default
spec:
  podTemplate:
    spec:
      containers:
      - name: python-sandbox
        image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v0.1.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8888
---
apiVersion: extensions.agents.x-k8s.io/v1beta1
kind: SandboxWarmPool
metadata:
  name: python-sandbox-pool
  namespace: default
spec:
  replicas: 1
  sandboxTemplateRef:
    name: python-sandbox-template
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that the template, pool, Sandbox, and Pod exist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get sandboxtemplates,sandboxwarmpools,sandboxes,pods &lt;span class="nt"&gt;-n&lt;/span&gt; default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait until the warm-pool sandbox Pod is &lt;code&gt;Running&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Create a dedicated ServiceAccount and RBAC for the SDK client
&lt;/h3&gt;

&lt;p&gt;Do not run the SDK with the namespace's &lt;code&gt;default&lt;/code&gt; ServiceAccount in a real deployment. Give the client its own ServiceAccount with the permissions it needs to create/delete claims and resolve the underlying Sandbox.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sandbox-client
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: sandbox-client
  namespace: default
rules:
- apiGroups:
  - agents.x-k8s.io
  resources:
  - sandboxes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions.agents.x-k8s.io
  resources:
  - sandboxclaims
  verbs:
  - get
  - list
  - watch
  - create
  - delete
- apiGroups:
  - extensions.agents.x-k8s.io
  resources:
  - sandboxwarmpools
  - sandboxtemplates
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - pods
  - services
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: sandbox-client
  namespace: default
subjects:
- kind: ServiceAccount
  name: sandbox-client
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: sandbox-client
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the critical permissions using the fully qualified resource name syntax supported by &lt;code&gt;kubectl auth can-i&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl auth can-i get sandboxes.agents.x-k8s.io &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--as&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;system:serviceaccount:default:sandbox-client &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; default

kubectl auth can-i create sandboxclaims.extensions.agents.x-k8s.io &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--as&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;system:serviceaccount:default:sandbox-client &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; default

kubectl auth can-i delete sandboxclaims.extensions.agents.x-k8s.io &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--as&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;system:serviceaccount:default:sandbox-client &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three should return &lt;code&gt;yes&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Start a Python client Pod
&lt;/h3&gt;

&lt;p&gt;The SDK can run locally using &lt;code&gt;kubectl port-forward&lt;/code&gt;, but that mode requires &lt;code&gt;kubectl&lt;/code&gt; in the environment running the Python process. For this reproducible example, run the client &lt;strong&gt;inside the cluster&lt;/strong&gt; and use &lt;code&gt;SandboxInClusterConnectionConfig&lt;/code&gt;, which connects directly to the sandbox runtime and does not spawn &lt;code&gt;kubectl&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl run python-pod &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;python:3.12-slim &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Never &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--overrides&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{"spec":{"serviceAccountName":"sandbox-client"}}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--command&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;sleep &lt;/span&gt;infinity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ready pod/python-pod &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;120s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the Python SDK in that Pod, pinned to the controller release used above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; default python-pod &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  pip &lt;span class="nb"&gt;install &lt;/span&gt;k8s-agent-sandbox&lt;span class="o"&gt;==&lt;/span&gt;0.5.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Create a sandbox and execute Python inside it
&lt;/h3&gt;

&lt;p&gt;Run the client directly through stdin; no Python file is required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; default python-pod &lt;span class="nt"&gt;--&lt;/span&gt; python - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;PY&lt;/span&gt;&lt;span class="sh"&gt;'
from k8s_agent_sandbox import SandboxClient
from k8s_agent_sandbox.models import SandboxInClusterConnectionConfig

client = SandboxClient(
    connection_config=SandboxInClusterConnectionConfig()
)

sandbox = client.create_sandbox(
    warmpool="python-sandbox-pool",
    namespace="default",
)

try:
    result = sandbox.commands.run(
        'python3 -c &lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="sh"&gt;print("hello from my sandbox")&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="sh"&gt;'
    )
    print(result.stdout)
finally:
    sandbox.terminate()
&lt;/span&gt;&lt;span class="no"&gt;PY
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hello from my sandbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point the complete path is working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python-pod
    |
    | SandboxInClusterConnectionConfig
    v
SandboxClaim -&amp;gt; SandboxWarmPool -&amp;gt; Sandbox -&amp;gt; runtime Pod:8888
                                      |
                                      +-&amp;gt; POST /execute
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Troubleshooting the three failures you are most likely to hit
&lt;/h3&gt;

&lt;p&gt;If you get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SandboxWarmPoolNotFoundError: SandboxWarmPool "python-sandbox-pool" not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;check that the warm pool exists in the same namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get sandboxwarmpools &lt;span class="nt"&gt;-n&lt;/span&gt; default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get a &lt;code&gt;403 Forbidden&lt;/code&gt; mentioning &lt;code&gt;sandboxclaims&lt;/code&gt; or &lt;code&gt;sandboxes&lt;/code&gt;, check the ServiceAccount RBAC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl auth can-i get sandboxes.agents.x-k8s.io &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--as&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;system:serviceaccount:default:sandbox-client &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTPConnection(... port=8888): Failed to establish a new connection: Connection refused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;check the image used by the sandbox Pod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; custom-columns&lt;span class="o"&gt;=&lt;/span&gt;NAME:.metadata.name,IMAGE:.spec.containers[&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;.image,IP:.status.podIP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sandbox must run a runtime server that implements &lt;code&gt;/execute&lt;/code&gt; on port &lt;code&gt;8888&lt;/code&gt;; a normal Python image that only sleeps will not work with &lt;code&gt;sandbox.commands.run()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Clean up
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl delete pod python-pod &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;--ignore-not-found&lt;/span&gt;
kubectl delete sandboxwarmpool python-sandbox-pool &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;--ignore-not-found&lt;/span&gt;
kubectl delete sandboxtemplate python-sandbox-template &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;--ignore-not-found&lt;/span&gt;
kubectl delete rolebinding sandbox-client &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;--ignore-not-found&lt;/span&gt;
kubectl delete role sandbox-client &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;--ignore-not-found&lt;/span&gt;
kubectl delete serviceaccount sandbox-client &lt;span class="nt"&gt;-n&lt;/span&gt; default &lt;span class="nt"&gt;--ignore-not-found&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  On GKE instead
&lt;/h3&gt;

&lt;p&gt;For the managed GKE feature, Agent Sandbox requires GKE &lt;code&gt;1.35.2-gke.1269000&lt;/code&gt; or later. On an existing Standard cluster, Google also requires a gVisor-enabled node pool before enabling Agent Sandbox. The current command uses the beta cluster surface and includes the cluster location:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud beta container clusters update &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LOCATION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-agent-sandbox&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GKE additionally enforces sandbox workload requirements such as &lt;code&gt;runtimeClassName: gvisor&lt;/code&gt;, disabling automatic ServiceAccount-token mounting, running as non-root, dropping Linux capabilities, setting CPU/memory limits, and scheduling onto the gVisor sandbox node pool. Use the managed GKE deployment manifest from the official GKE guide rather than the minimal self-managed template above.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;GKE Agent Sandbox -- and the open-source &lt;code&gt;kubernetes-sigs/agent-sandbox&lt;/code&gt; project it is built on -- is what happens when someone finally builds the right abstraction for agent runtimes. It is Kubernetes-native, which means it fits into existing infrastructure without fighting it. It is fast enough for interactive use. It is secure by default. And it has SDKs that let agents manage their own environments programmatically.&lt;/p&gt;

&lt;p&gt;The era of "just run it in Docker and pray" is ending. The era of "give the agent its own Linux box, properly isolated, properly managed, properly fast" is here.&lt;/p&gt;

&lt;p&gt;And honestly? It is about damn time.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;All the sourcing for this post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.cloud.google.com/kubernetes-engine/docs/concepts/machine-learning/agent-sandbox" rel="noopener noreferrer"&gt;GKE Agent Sandbox documentation&lt;/a&gt; -- the primary source on the managed GKE add-on&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/kubernetes-sigs/agent-sandbox" rel="noopener noreferrer"&gt;kubernetes-sigs/agent-sandbox&lt;/a&gt; (~3k stars) -- the open-source CNCF SIG project under SIG Apps&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://agent-sandbox.sigs.k8s.io/docs/" rel="noopener noreferrer"&gt;Agent Sandbox documentation site&lt;/a&gt; -- full docs, getting started guides, Python/Go SDK references&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/k8s-agent-sandbox/" rel="noopener noreferrer"&gt;Agent Sandbox Python SDK&lt;/a&gt; -- programmatic sandbox management from Python&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pkg.go.dev/sigs.k8s.io/agent-sandbox" rel="noopener noreferrer"&gt;Agent Sandbox Go SDK&lt;/a&gt; -- same, but for Go&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>I hacked every dumb screen in my house into one dashboard</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Fri, 31 Jul 2026 19:46:50 +0000</pubDate>
      <link>https://dev.to/calganaygun/i-hacked-every-dumb-screen-in-my-house-into-one-dashboard-3e8f</link>
      <guid>https://dev.to/calganaygun/i-hacked-every-dumb-screen-in-my-house-into-one-dashboard-3e8f</guid>
      <description>&lt;p&gt;This Kindle was supposed to be obsolete.&lt;/p&gt;

&lt;p&gt;The tiny LCD beside it was designed to do little more than rotate a slide show.&lt;/p&gt;

&lt;p&gt;Now both show live transit departures, weather, tasks, and anything else I can pull from an API—and I control them from the same self-hosted dashboard.&lt;/p&gt;

&lt;p&gt;No custom firmware on the LCD. No soldering. No cloud subscription.&lt;/p&gt;




&lt;p&gt;It started with a cheap Chinese display:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fez00sezyv81wu09hhltd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fez00sezyv81wu09hhltd.png" alt="GeekMagic Ultra screen showing transport data" width="799" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;GeekMagic Ultra&lt;/strong&gt;, or "SmallTV" as people call it, a 240×240 IPS panel with a stock firmware that just rotates through a gallery slideshow or weather UI. Static images only, no dynamic data unles you use weather screen, no API for live content. But it has a &lt;code&gt;/doUpload&lt;/code&gt; endpoint and a &lt;code&gt;/set&lt;/code&gt; call. Punch in its IP, overwrite the same JPEG every time, and suddenly that dumb gallery display is showing live transit departures and Todoist tasks.&lt;/p&gt;

&lt;p&gt;No firmware mods. No soldering. Just one script.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;&lt;a href="https://github.com/calganaygun/geekmagic-ultra-scripts" rel="noopener noreferrer"&gt;geekmagic-ultra-scripts&lt;/a&gt;&lt;/strong&gt; to prove it works. Transit boards, task lists, weather — all running on stock hardware that cost pocket change. That project was fun. I thought it was the end of the story.&lt;/p&gt;




&lt;p&gt;Then I found a &lt;strong&gt;used, EOL'd Kindle 4 NT&lt;/strong&gt; for 100 PLN (like 25 USD) on the second-hand market. Amazon abondaned it, but I haven't :) It runs on Linux. It has an e-ink display that uses almost no power. A command called &lt;code&gt;eips&lt;/code&gt; can render images. It can toggle Wi-Fi, report battery, last weeks on a charge, and wake from deep sleep via its RTC.&lt;/p&gt;

&lt;p&gt;One jailbreak way to an SSH session and I knew: this thing is a perfect pull-based display. I highly inspired from melihkarakelle's project called &lt;a href="https://github.com/melihkarakelle/kindle4-weather-display" rel="noopener noreferrer"&gt;kindle4-weather-display&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78nk6paelultbh8lx6e5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78nk6paelultbh8lx6e5.png" alt="Kindle Weather/Todosit UI" width="800" height="1422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I had two completely different hacked screens: one push (GeekMagic), one pull (Kindle), and no unified way to manage them. Every device needed its own script, its own config, its own workflow.&lt;/p&gt;

&lt;p&gt;So I sat down and built the thing that ties them all together.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;hackreen&lt;/strong&gt; is a self-hosted control plane and design studio for every hacked display in your house. One web UI, one declarative screen language, deploy to any device.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually does
&lt;/h2&gt;

&lt;p&gt;Boots in two minutes (&lt;code&gt;docker compose up -d&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GeekMagic → push mode.&lt;/strong&gt; Configure the endpoint. Hackreen renders a 240×240 JPEG, overwrites the same gallery file, calls &lt;code&gt;/set&lt;/code&gt;, and the display updates instantly. Zero hardware hacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kindle 4 → pull mode.&lt;/strong&gt; Copy-paste one &lt;code&gt;wget | sh&lt;/code&gt; command into the Kindle. It installs a client that wakes Wi-Fi every 30 minutes, pulls a fresh image, renders it with &lt;code&gt;eips&lt;/code&gt;, reports battery, then goes back to RTC deep sleep for days of battery life. SSH stays reachable. There's even a debug mode: hold the center 5-way key during power-on and you get a shell.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hackreen Screen Language (HSL).&lt;/strong&gt; Declarative JSON format. Define data sources (clock, weather, Todoist, transit APIs), compose layers with text, images, icons, shapes. Every live source ships with &lt;strong&gt;sample data&lt;/strong&gt; so the preview works offline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design Studio.&lt;/strong&gt; Visual editor with instant preview. Connect to live APIs, iterate in real time, push when it looks right — without touching a config file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets Vault.&lt;/strong&gt; AES-256-GCM encrypted. Tokens stay safe at rest, never exposed by the API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2,000+ Lucide icons.&lt;/strong&gt; Built-in. &lt;code&gt;icon:lucide:cloud-rain&lt;/code&gt;, done.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Kindles pull. The GeekMagic gets pushed. You design once, deploy everywhere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F38ylun2mgd38pj4gswz8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F38ylun2mgd38pj4gswz8.png" alt="Hackreen Snapshot" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why self-hosted?
&lt;/h2&gt;

&lt;p&gt;This is a home lab tool. You run it on your LAN. Access through a VPN. No third party, no subscription, no "we changed our API, sorry." You own your data and your screens.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lineage
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/calganaygun/geekmagic-ultra-scripts" rel="noopener noreferrer"&gt;geekmagic-ultra-scripts&lt;/a&gt;&lt;/strong&gt; — the first proof of concept. Turned a stock gallery slideshow into a live information display by repeatedly overwriting one file. Transit, Todoist, weather templates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kindle 4 NT discovery&lt;/strong&gt; — second-hand e-ink device that could pull and display images with almost zero power consumption. Proved the pull model worked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/calganaygun/hackreen" rel="noopener noreferrer"&gt;Hackreen&lt;/a&gt;&lt;/strong&gt; — the orchestrator. Brought push and pull under one roof with a proper design pipeline, HSL language, and a unified API.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Every hacked screen in this house goes into Hackreen. The SmallTV in the kitchen. The Kindle on the desk. Whatever cheap display I find next — it's getting a pull URL or a push button. The question isn't "can I show this data on that screen?" anymore. The answer is always yes, it's just another screen in the dashboard.&lt;/p&gt;




&lt;p&gt;Check it out: &lt;strong&gt;&lt;a href="https://github.com/calganaygun/hackreen" rel="noopener noreferrer"&gt;github.com/calganaygun/hackreen&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;This project is highly inspired by Melih Karakelle's tweets and &lt;a href="https://github.com/melihkarakelle" rel="noopener noreferrer"&gt;projects&lt;/a&gt;, so special thanks to him.&lt;/p&gt;

</description>
      <category>gadget</category>
      <category>programming</category>
      <category>opensource</category>
      <category>automation</category>
    </item>
    <item>
      <title>Resisting the Eye of the Machine: A Reflection on AI and Data Ownership</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Tue, 24 Feb 2026 21:08:49 +0000</pubDate>
      <link>https://dev.to/calganaygun/resisting-the-eye-of-the-machine-a-reflection-on-ai-and-data-ownership-510m</link>
      <guid>https://dev.to/calganaygun/resisting-the-eye-of-the-machine-a-reflection-on-ai-and-data-ownership-510m</guid>
      <description>&lt;p&gt;AI both creates and consumes. For someone like me, who’s invested deeply in both the benefits and risks of these evolving systems, the duality is impossible to ignore. On one hand, AI supplements creativity, fast-tracks productivity, and offers insights unprecedented in human history. On the other, AI is a voracious consumer that treats every public thought, image, and pixel as a potential resource for improvement—its improvement, not ours.&lt;/p&gt;

&lt;p&gt;What happens to ideas when they’re not just shared, but consumed, repurposed, and disjointed from their original intention? This is not a fight against inevitable progress but an invitation to consider where the boundaries should lie.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hunger of the Machine
&lt;/h2&gt;

&lt;p&gt;Today’s AI systems are participants in a digital ecosystem. To feed their model-building appetite, they consume everything: tweets, screenshots, vague status updates, unfinished sketches, throwaway jokes—anything to refine prediction and replication capabilities. These systems don’t ask for permission; most of the time, they don’t even acknowledge the humans who originally created the content.&lt;/p&gt;

&lt;p&gt;As someone interested in sparking friction within this process, I’ve explored ways to actively undermine AI’s consumption. One approach stems from visual obfuscation principles to disrupt AI readers at the OCR level, reducing their ability to reconstruct coherent text segments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Segmentation and My Implementation
&lt;/h3&gt;

&lt;p&gt;The core idea relies on &lt;strong&gt;radical dynamic segmentation&lt;/strong&gt;. Imagine text that never fully "settles"—it pulses, shifts, even disassembles itself momentarily. While the human eye has an incredible ability to "fill in the blanks" and interpret movement, machines struggle with this flux.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbgyd4yhqsq3cpemuzgis.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbgyd4yhqsq3cpemuzgis.png" alt="Initial concept from h43z." width="598" height="767"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/h43z/status/1949241540465045853" rel="noopener noreferrer"&gt;h43z's initial concept&lt;/a&gt; focused on kinetic text—characters in constant motion to disrupt machine vision. This was the spark that got me thinking, but I took a different route: breaking characters into partial segments that flash independently. The chunking method was something I figured out through experimentation.&lt;/p&gt;

&lt;p&gt;The implementation is JavaScript-based, using Canvas to analyze each character's pixels and fragment them in various ways—radial slices, concentric rings, diagonal strips, random distributions. Each chunk flashes at randomized intervals. The result: text that humans can read but machines can't easily parse.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3zm3sgzv4hz9n3zg0yd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3zm3sgzv4hz9n3zg0yd.png" alt="One of my tested concepts, A screenshot shows 'Hello dev.to'" width="800" height="617"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I tested against OCR libraries like Tesseract and even LLM-adjacent pipelines. The simpler systems failed completely. Modern Live/Video APIs struggled but occasionally recovered—revealing both the method's potential and its limits.&lt;/p&gt;

&lt;p&gt;Why it works: It exploits the gap between human and machine perception. We thrive on approximation and motion. Machines expect clean, static data. Every fragmented flash introduces chaos that challenges their assumptions about how information should look.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations and Lessons
&lt;/h3&gt;

&lt;p&gt;Technology can’t be a self-contained solution to problems of technological overreach. One critical limitation is that dynamic segmentation, while effective on smaller scales, is computationally expensive to produce and impractical for systems requiring long text readability.&lt;/p&gt;

&lt;p&gt;Moreover, it raises a practical question: How many people would opt to obfuscate their content actively? To scale such efforts and normalize resistance, the tools need to be seamless, almost invisible to the writer. A browser extension that dynamically applies segmentation while retaining human readability—a future goal—might bridge this gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Philosophical Trade-Offs
&lt;/h2&gt;

&lt;p&gt;This technical exploration also emphasizes deeper philosophical questions. By participating in this cat-and-mouse game against AI, do we solve the problem or play into its competitive escalation? As much as the act of resistance feels gratifying, it’s worth asking: What happens when the effort to defend against machines becomes indistinguishable from innovations driving them forward?&lt;/p&gt;

&lt;p&gt;AI reveals how much has been surrendered—privacy, ownership, sometimes even the joy of creating for humans rather than systems. But agency remains deeply human. Perhaps that’s the key takeaway: less about domination and more about choosing what remains ours.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Closing: Toward Balancing Agency
&lt;/h2&gt;

&lt;p&gt;Dynamic segmentation obviously is not a silver bullet. It won’t end AI overconsumption, but it does add another tool to the resistance. My experiments aim to create what friction I can—disrupting the expectation that AI must own everything it sees. At the heart of this is the hope that small, deliberate acts can start larger conversations about human ownership in an AI-driven culture.&lt;/p&gt;

&lt;p&gt;As experiments continue, the tension between control and participation stays alive. To stabilize both technology and thought, we’ll need boundaries that don’t eliminate creativity but celebrate and protect its imperfection.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Acknowledgments:&lt;/strong&gt; To h43z, whose kinetic text concept was the initial inspiration that sparked my thinking on this problem. While their approach focused on character movement, it pushed me to explore the chunking and partial segmentation methods documented here.&lt;/p&gt;




&lt;p&gt;Additional References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My implementation of dynamic segmentation tests: &lt;a href="http://e.43z.one/ega5yzz" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The foundational thought by h43z: &lt;a href="https://x.com/h43z/status/1949241540465045853" rel="noopener noreferrer"&gt;Original Tweet&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>data</category>
      <category>discuss</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Redefining Event-Driven Architecture on Google Cloud</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Mon, 16 Feb 2026 19:10:10 +0000</pubDate>
      <link>https://dev.to/gde/redefining-event-driven-architecture-on-google-cloud-5abj</link>
      <guid>https://dev.to/gde/redefining-event-driven-architecture-on-google-cloud-5abj</guid>
      <description>&lt;p&gt;Building event-driven systems with Cloud Run, Pub/Sub, and Eventarc is a powerful pattern, but the gap between "Hello World" tutorials and production stability is wide. These are the hard-won lessons from the trenches of Google Cloud serverless architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Choosing Your Transport: Eventarc vs. Pub/Sub
&lt;/h2&gt;

&lt;p&gt;While Eventarc often uses Pub/Sub under the hood, the choice of which to interface with directly depends on your source and required control.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Eventarc&lt;/th&gt;
&lt;th&gt;Direct Pub/Sub&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GCP-native events (GCS, Firestore, Audit Logs)&lt;/td&gt;
&lt;td&gt;Custom inter-service messaging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed wrapper, high convenience&lt;/td&gt;
&lt;td&gt;Manual configuration, high control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Filtering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in attribute filtering&lt;/td&gt;
&lt;td&gt;Fine-grained policies &amp;amp; custom attributes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IAM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Uses &lt;code&gt;eventarc.eventReceiver&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Uses &lt;code&gt;pubsub.subscriber&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Use Eventarc for "plumbing" Google Cloud events. Use Direct Pub/Sub when you need a custom event bus or specific retry/ordering logic.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. The Infrastructure Reality Check
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Idempotency Requirement
&lt;/h3&gt;

&lt;p&gt;Pub/Sub guarantees &lt;strong&gt;at-least-once&lt;/strong&gt; delivery by default. While exactly-once delivery exists as an opt-in feature, your consumers must assume duplicates will happen. If your handler isn't idempotent, you risk double-charging users or corrupting state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Non-Negotiable Flow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract a unique &lt;strong&gt;Idempotency Key&lt;/strong&gt; (UUID/Hash) from the event.&lt;/li&gt;
&lt;li&gt;Check a fast-access cache (Memorystore or Firestore) for the key.&lt;/li&gt;
&lt;li&gt;If present, &lt;strong&gt;discard&lt;/strong&gt; the message as a duplicate.&lt;/li&gt;
&lt;li&gt;If absent, process the event and &lt;strong&gt;store&lt;/strong&gt; the key with a TTL.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Managing Cold Starts
&lt;/h3&gt;

&lt;p&gt;Cloud Run’s "scale to zero" is a budget-saver but a latency-killer. A container startup typically adds &lt;strong&gt;2–8 seconds&lt;/strong&gt; to the first request.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Fix:&lt;/strong&gt; Set &lt;code&gt;min-instances&lt;/code&gt; for latency-critical paths (this incurs cost).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Alternative:&lt;/strong&gt; Use &lt;strong&gt;Cloud Run Jobs&lt;/strong&gt; for asynchronous batch processing where start-time overhead is less relevant.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Eventarc Propagation Delays
&lt;/h3&gt;

&lt;p&gt;When deploying Eventarc triggers via Terraform or CLI, filtering rules can take &lt;strong&gt;60–120 seconds&lt;/strong&gt; to propagate across the Google network.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Production Fix:&lt;/strong&gt; Build a "warm-up" delay into your CI/CD pipeline. Do not trigger integration tests immediately after a successful deployment, or you will see intermittent, false-positive failures.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Calculating Realistic Costs
&lt;/h2&gt;

&lt;p&gt;Tutorials often suggest serverless is "pennies," but at scale, the math changes. Pub/Sub is billed at &lt;strong&gt;$40 per TiB&lt;/strong&gt;, with a &lt;strong&gt;1 KB minimum&lt;/strong&gt; per message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: 10M Events/Day (300M/Month)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Volume:&lt;/strong&gt; 300M messages × 1 KB (min size) ≈ &lt;strong&gt;293 GiB (0.286 TiB)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ingest &amp;amp; Delivery:&lt;/strong&gt; (0.286 TiB × $40) + (0.286 TiB × $40) = &lt;strong&gt;$23/month&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compute (Cloud Run):&lt;/strong&gt; 300M invocations (assuming 1s duration, 512MB RAM) ≈ &lt;strong&gt;$150–$200/month&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Total:&lt;/strong&gt; ~$175–$225/month. Significant, but highly predictable if you monitor message size and invocation duration.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Advanced Production Patterns
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Regional Co-location
&lt;/h3&gt;

&lt;p&gt;Eventarc triggers for multi-region services (like Firestore &lt;code&gt;nam5&lt;/code&gt;) are often pinned to specific regions (e.g., &lt;code&gt;us-central1&lt;/code&gt;). If your Cloud Run service resides elsewhere, you will incur &lt;strong&gt;cross-region egress charges&lt;/strong&gt; and increased latency. Always verify the region mapping table in the GCP documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Payload Sanitization at the Edge
&lt;/h3&gt;

&lt;p&gt;Using &lt;strong&gt;Eventarc Advanced&lt;/strong&gt;, you can use Common Expression Language (CEL) to transform or redact payloads before they reach the consumer. This is vital for PII compliance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Example: Redacting an email address in-flight
message.setField("data.email", re.extract(message.data.email, "(^.).*@(.*)", "\\1***@\\2"))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observability and Dead-Letter Topics (DLTs)
&lt;/h3&gt;

&lt;p&gt;In a distributed system, an event can "disappear" if a filter drops it or a consumer fails silently.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DLTs:&lt;/strong&gt; Every subscription must have a Dead-Letter Topic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerting:&lt;/strong&gt; Monitor the &lt;code&gt;subscription/dead_letter_message_count&lt;/code&gt; metric. A rising count is your first sign of a logic bug or schema mismatch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tracing:&lt;/strong&gt; Use OpenTelemetry to inject &lt;strong&gt;Trace IDs&lt;/strong&gt; into event attributes, allowing you to follow a single request from the producer through the bus to the consumer logs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. When to Avoid Event-Driven
&lt;/h2&gt;

&lt;p&gt;Don't "cargo-cult" this architecture if it doesn't fit your needs. Skip it if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You require &lt;strong&gt;strong consistency&lt;/strong&gt; and immediate transactions.&lt;/li&gt;
&lt;li&gt;Your end-to-end latency requirements are &lt;strong&gt;&amp;lt; 100ms&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The overhead of debugging distributed traces outweighs the scaling benefits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In these cases, stick to &lt;strong&gt;Synchronous gRPC/HTTP&lt;/strong&gt; or &lt;strong&gt;Cloud Workflows&lt;/strong&gt; for structured orchestration.&lt;/p&gt;




&lt;h3&gt;
  
  
  Final Takeaway
&lt;/h3&gt;

&lt;p&gt;The combination of Cloud Run and Eventarc is one of the most robust patterns in 2026. By respecting the boundaries of the platform—accounting for propagation delays, ensuring idempotency, and co-locating regions—you can build a system that scales effortlessly from zero to millions of events.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>distributedsystems</category>
      <category>googlecloud</category>
      <category>serverless</category>
    </item>
    <item>
      <title>A CAPTCHA Bypass Technique: Audio Files</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Fri, 30 Jan 2026 12:38:29 +0000</pubDate>
      <link>https://dev.to/calganaygun/a-captcha-bypass-technique-audio-files-315k</link>
      <guid>https://dev.to/calganaygun/a-captcha-bypass-technique-audio-files-315k</guid>
      <description>&lt;p&gt;This is a draft write-up from 2019, documenting a CAPTCHA bypass technique I discovered back then. All code and images shown are examples for educational purposes.&lt;/p&gt;




&lt;p&gt;One day back in 2019, I got tired of repeatedly logging into my school's student system just to enroll in a full class. Then a lightbulb went off in my head: I could automate these attempts and refocus on my actual work.&lt;/p&gt;

&lt;p&gt;When it comes to automating website processes, I love using &lt;a href="https://en.wikipedia.org/wiki/Userscript" rel="noopener noreferrer"&gt;user scripts&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Automation Plan
&lt;/h2&gt;

&lt;p&gt;Our school system expired user sessions after a while, even if you were actively working. So first, I needed to automate the login process. Once successfully logged in, navigating and enrolling in a class would be straightforward (just some click event magic).&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Login UI
&lt;/h2&gt;

&lt;p&gt;The school system had an internally managed CAPTCHA service. It displayed two numbers and asked for their sum. The images were slightly corrupted—but not enough to prevent OCR. However, I didn't want to rely on any API or image processing system to solve this CAPTCHA.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63iiiylbkwj5rfrmgr4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63iiiylbkwj5rfrmgr4y.png" alt="Example captcha image" width="442" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Inspecting the Audio Service for CAPTCHA
&lt;/h2&gt;

&lt;p&gt;After deciding not to use any image-related service, I started inspecting the network traffic of the login system. I noticed that the answer to the generated CAPTCHA was stored server-side in a session associated with me.&lt;/p&gt;

&lt;p&gt;When I clicked the audio playback button, I realized it was reading out the answer directly. Two different endpoints returned two different audio files, split into tens and ones digits.&lt;/p&gt;

&lt;p&gt;The audio system seemed like a perfect route for me. I had no intention of feeding these audio files into a speech-to-text service—I was looking for the fastest, hackiest solution possible.&lt;/p&gt;

&lt;p&gt;Since the same audio files should have the same file size, I decided to test this hypothesis first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvg4vgyuvgzaz0a1d7vd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvg4vgyuvgzaz0a1d7vd4.png" alt="Example HTTP traffic" width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And bingo! By mapping each tens and ones digit to their file sizes beforehand, I could automatically determine the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The Solution
&lt;/h2&gt;

&lt;p&gt;Here's an example of how the code worked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example mapping of file sizes to digit values&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tensMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// 0 tens&lt;/span&gt;
  &lt;span class="mi"&gt;1456&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// 1 ten&lt;/span&gt;
  &lt;span class="mi"&gt;1567&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// 2 tens&lt;/span&gt;
  &lt;span class="c1"&gt;// ... etc&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onesMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="mi"&gt;987&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// 0 ones&lt;/span&gt;
  &lt;span class="mi"&gt;1023&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// 1 one&lt;/span&gt;
  &lt;span class="mi"&gt;1145&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// 2 ones&lt;/span&gt;
  &lt;span class="c1"&gt;// ... etc&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Example: Fetch audio files and determine answer by file size&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;solveCaptcha&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tensResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/captcha/audio/tens&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onesResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/captcha/audio/ones&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tensSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tensResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onesSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onesResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tensValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tensMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tensSize&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onesValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;onesMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;onesSize&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tensValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;onesValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Use it in the login flow&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;solveCaptcha&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#captcha-input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#login-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I tested this approach, it worked perfectly!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Lessons Learned
&lt;/h2&gt;

&lt;p&gt;This experience taught me a few things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Look for alternative attack vectors:&lt;/strong&gt; When the obvious solution (OCR) seems complex, there might be simpler paths (audio files, metadata, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security through obscurity fails:&lt;/strong&gt; Just because a CAPTCHA uses audio doesn't mean it's secure—especially if the files are deterministic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File size is metadata:&lt;/strong&gt; Even without processing the content, file properties can leak information&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This technique worked because the audio files were pre-generated and static. A more secure implementation would generate unique audio files or add random noise to prevent size-based fingerprinting.&lt;/p&gt;

</description>
      <category>security</category>
      <category>captcha</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Uncomfortable Truth About AI-Assisted Development</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Wed, 28 Jan 2026 11:59:53 +0000</pubDate>
      <link>https://dev.to/calganaygun/the-uncomfortable-truth-about-ai-assisted-development-4ckp</link>
      <guid>https://dev.to/calganaygun/the-uncomfortable-truth-about-ai-assisted-development-4ckp</guid>
      <description>&lt;p&gt;&lt;em&gt;Or: How We Learned to Stop Worrying and Start Debugging at 2am&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I need to tell you about a report that made me uncomfortable. Not because it revealed anything shocking, but because it quantified what I've been watching happen in real-time across engineering teams for the past year.&lt;/p&gt;

&lt;p&gt;CodeRabbit analyzed 470 pull requests — 320 co-authored by AI, 150 written by humans. The headline number: &lt;strong&gt;AI-generated code contains 1.7x more issues than human-written code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But that's not the uncomfortable part. The uncomfortable part is that we already knew this. We just chose not to measure it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Velocity Trap
&lt;/h2&gt;

&lt;p&gt;Here's what's happening on the ground:&lt;/p&gt;

&lt;p&gt;Teams adopted AI coding assistants in 2024. By 2025, they're shipping 20% more PRs per developer. Product managers are thrilled. Engineers feel productive. The metrics look great.&lt;/p&gt;

&lt;p&gt;Then production incidents spike by 23.5%.&lt;/p&gt;

&lt;p&gt;At first, you blame other factors. Infrastructure changes. New team members. Bad luck. But when you dig into the post-mortems, a pattern emerges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A null pointer dereference that should have been caught by basic error handling&lt;/li&gt;
&lt;li&gt;Hardcoded credentials that somehow made it through review&lt;/li&gt;
&lt;li&gt;A database query executing 500 times in a loop instead of being batched&lt;/li&gt;
&lt;li&gt;Exception handling that swallows errors and returns success anyway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't exotic bugs. They're &lt;em&gt;boring&lt;/em&gt; bugs. The kind a junior developer makes in their first month. The kind that code review is supposed to catch.&lt;/p&gt;

&lt;p&gt;Except we're not reviewing like we used to. Because the code &lt;em&gt;looks fine&lt;/em&gt;. It compiles. It follows naming conventions. The structure makes sense. So we skim it, assume the AI got it right, and hit approve.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Numbers Actually Mean
&lt;/h2&gt;

&lt;p&gt;Let's break down what CodeRabbit found, because the devil is in the details:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logic errors: 2x higher&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Algorithm/business logic: 2.25x&lt;/li&gt;
&lt;li&gt;Concurrency control: 2.29x&lt;/li&gt;
&lt;li&gt;Null handling: 2.27x&lt;/li&gt;
&lt;li&gt;Exception handling: 1.97x&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tells you something fundamental: &lt;strong&gt;AI doesn't understand execution flow&lt;/strong&gt;. It pattern matches syntax. It knows what error handling &lt;em&gt;looks like&lt;/em&gt;, but not when you actually need it. It generates code that passes the happy path and explodes on edge cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security vulnerabilities: 1.57x higher&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XSS injection: 2.74x&lt;/li&gt;
&lt;li&gt;Insecure object references: 1.91x&lt;/li&gt;
&lt;li&gt;Password handling: 1.88x&lt;/li&gt;
&lt;li&gt;Insecure deserialization: 1.82x&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the scary one. Because security bugs don't just crash your app—they compromise your users. And AI is literally trained on public code repositories, including all the insecure code that's been written over the past two decades. It's regurgitating attack vectors from 2015 Stack Overflow answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance issues: 7.9x more I/O problems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one made me laugh, then cry. AI optimizes for "code that works" not "code that works &lt;em&gt;efficiently&lt;/em&gt;". Why batch database queries when you can just loop? Why cache when you can fetch? It's technically correct. It's also a production disaster waiting to happen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code quality: 3.15x worse readability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The irony here is brutal. One of the selling points of AI assistants is that they write "clean code". Except what they actually write is verbose, repetitive code with inconsistent naming and unnecessary abstraction. It's &lt;em&gt;formatted&lt;/em&gt; nicely. That's not the same thing as &lt;em&gt;readable&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 90th Percentile Problem
&lt;/h2&gt;

&lt;p&gt;Here's the number that keeps me up at night: at the 90th percentile, AI PRs contain &lt;strong&gt;26 issues&lt;/strong&gt; versus 12 for humans.&lt;/p&gt;

&lt;p&gt;This means AI doesn't just create more bugs on average — it occasionally creates absolute disasters. Code that's so broken it shouldn't have made it past the IDE, let alone into production.&lt;/p&gt;

&lt;p&gt;And because we're shipping faster, we're hitting these edge cases more often. It's not a theoretical risk. It's a ticking time bomb in your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is Hard to Fix
&lt;/h2&gt;

&lt;p&gt;The obvious answer is "just review AI code more carefully". But that misses the psychological trap we've fallen into.&lt;/p&gt;

&lt;p&gt;AI-generated code &lt;em&gt;feels&lt;/em&gt; trustworthy because it's consistently formatted, confidently written, and superficially correct. It doesn't have the telltale signs of junior code like hesitant variable names, inconsistent style, obvious copy-paste errors.&lt;/p&gt;

&lt;p&gt;So your brain does a pattern match: "this looks like senior-level code" → "probably fine" → approve.&lt;/p&gt;

&lt;p&gt;Except it's not senior-level code. It's &lt;em&gt;senior-looking&lt;/em&gt; code generated by a system that has no mental model of what it's building.&lt;/p&gt;

&lt;p&gt;The traditional markers we use for code quality — structure, naming, formatting — have been decoupled from actual correctness. We need new heuristics, and we haven't built them yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Works
&lt;/h2&gt;

&lt;p&gt;I'm not going to tell you to stop using AI assistants. I use them daily. They're legitimately useful for scaffolding, refactoring, and handling boilerplate.&lt;/p&gt;

&lt;p&gt;But here's what I've learned:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Ground the model in your context&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't just paste code into ChatGPT and expect it to understand your domain. Give it your architecture docs. Your API contracts. Your error handling conventions. The more context you provide, the less it has to guess.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Treat AI output as untrusted by default&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Would you merge code from a contractor you've never worked with before without thorough review? No? Then don't do it for AI.&lt;/p&gt;

&lt;p&gt;Any code touching auth, payments, PII, or critical business logic gets manual review. No exceptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Automate what AI gets wrong&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI is terrible at formatting, naming consistency, and basic security checks. So automate those with linters, formatters, and SAST tools in your CI pipeline.&lt;/p&gt;

&lt;p&gt;Don't waste human review time catching things machines can catch. Use humans for semantic review; does this actually solve the problem correctly?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Use independent review tools&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is CodeRabbit's obvious pitch, but it's also correct: don't use the same AI that generated code to review it. That's like asking someone to grade their own homework.&lt;/p&gt;

&lt;p&gt;Independent static analysis, security scanners, and code review tools catch different classes of bugs than generative models do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Accept the maintenance tax&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI-assisted development is a trade-off: velocity now, maintenance cost later. If you're not willing to pay down the technical debt, don't take on the loan.&lt;/p&gt;

&lt;p&gt;Budget time for refactoring. Expect to fix edge cases in production. Plan for the eventual rewrite when the generated code becomes unmaintainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Question
&lt;/h2&gt;

&lt;p&gt;The uncomfortable truth isn't that AI generates bugs. It's that &lt;strong&gt;we're willing to accept more bugs in exchange for speed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's a legitimate trade-off in some contexts. Early-stage startups trying to find product-market fit? Ship fast, fix later. Mature companies with millions of users and regulatory compliance? Maybe slow down.&lt;/p&gt;

&lt;p&gt;But let's be honest about what we're doing. We're not "augmenting developer productivity" in a risk-free way. We're shifting the risk/reward curve.&lt;/p&gt;

&lt;p&gt;More features, faster iteration, shorter cycle times; at the cost of more incidents, more maintenance burden, and more time spent debugging.&lt;/p&gt;

&lt;p&gt;Is that worth it? Depends on your context. But you can't answer that question if you're not measuring the cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens Next
&lt;/h2&gt;

&lt;p&gt;AI coding assistants aren't going away. They're getting better. Context windows are expanding. Models are learning from feedback. The tooling is improving.&lt;/p&gt;

&lt;p&gt;But the fundamental problem remains: &lt;strong&gt;LLMs are pattern-matching engines, not reasoning systems&lt;/strong&gt;. They don't understand your invariants. They don't trace execution paths. They don't think about failure modes.&lt;/p&gt;

&lt;p&gt;They surface-fit syntax without semantic understanding.&lt;/p&gt;

&lt;p&gt;Until that changes, AI-generated code will always carry a quality tax. The question is whether we're willing to pay it; and whether we're honest about the price.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AI code creates 1.7x more issues than human code across logic, security, performance, and maintainability&lt;/li&gt;
&lt;li&gt;The worst AI PRs (90th percentile) contain 26 issues vs 12 for humans; catastrophic failure modes are real&lt;/li&gt;
&lt;li&gt;Teams are shipping 20% more PRs but seeing 23.5% more production incidents&lt;/li&gt;
&lt;li&gt;AI optimizes for "looks correct" not "is correct"; it passes shallow tests but fails on edge cases&lt;/li&gt;
&lt;li&gt;Effective mitigation requires grounding models in context, automating quality checks, and treating AI output as untrusted&lt;/li&gt;
&lt;li&gt;The velocity gain is real, but so is the maintenance cost; choose consciously&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Full CodeRabbit report: &lt;a href="https://www.coderabbit.ai/whitepapers/state-of-AI-vs-human-code-generation-report" rel="noopener noreferrer"&gt;https://www.coderabbit.ai/whitepapers/state-of-AI-vs-human-code-generation-report&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vibecoding</category>
      <category>devops</category>
      <category>ai</category>
      <category>development</category>
    </item>
    <item>
      <title>AI Productivity Tips 1 - SQL Companion Bot with Gemini 1.5 Pro</title>
      <dc:creator>Çalgan Aygün</dc:creator>
      <pubDate>Sun, 25 Aug 2024 10:27:36 +0000</pubDate>
      <link>https://dev.to/calganaygun/ai-productivity-tips-1-sql-companion-bot-with-gemini-15-pro-5g2c</link>
      <guid>https://dev.to/calganaygun/ai-productivity-tips-1-sql-companion-bot-with-gemini-15-pro-5g2c</guid>
      <description>&lt;p&gt;In my current role, I often need to analyze database records and evaluate user performance metrics to identify anomalies. However, manually writing these one-off queries across multiple tables isn't efficient, especially when dealing with complex joins. To streamline this process, I turned to AI.&lt;/p&gt;

&lt;p&gt;Here’s a step-by-step guide on how to boost your productivity using AI for SQL queries:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start by navigating to &lt;a href="https://aistudio.google.com/" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt; and create a new chat prompt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9f28cn6ml538h14fqas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9f28cn6ml538h14fqas.png" alt="Google AI Studio Snapshot" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Next, set up a SQL Helper system prompt. Provide your database schema in the system prompt, also specify the RDBMS you’re using so that the AI can generate queries with the correct syntax. I tested this with &lt;a href="https://db-book.com/university-lab-dir/sqljs.html" rel="noopener noreferrer"&gt;The DB Book&lt;/a&gt;'s schema.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s an example system prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Act as a DB Admin/SQL Developer and generate the requested SQL queries based on the following DDL/Schema. Provide explanations and ensure that the queries are safe to run in a production environment. Add "Do not forget to review the SQL query before running." to all SQL responses.

RDBMS/SQL Syntax: &amp;lt;Your RDBMS&amp;gt;

My database DDL: &amp;lt;Your database and table DDLs&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Now, ask your query! For example, I asked: &lt;code&gt;I need to identify the students who are enrolled in a course taught by Teacher 1 and list all their other courses in a comma-separated format in a column.&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And just like that, the AI (thanks to Gemini 1.5 Pro) generated the query I needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7572ng29ty4qrzpk1l4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7572ng29ty4qrzpk1l4j.png" alt="Chat Snapshot" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>gemini</category>
      <category>productivity</category>
      <category>googlecloud</category>
    </item>
  </channel>
</rss>
