<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Agents on Prefect Dev Log</title><link>https://dev-log.prefect.io/blog/agents/</link><description>Recent content in Agents on Prefect Dev Log</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><copyright>Copyright © 2025, Prefect Technologies Inc.</copyright><lastBuildDate>Sun, 10 May 2026 12:00:00 -0500</lastBuildDate><atom:link href="https://dev-log.prefect.io/blog/agents/index.xml" rel="self" type="application/rss+xml"/><item><title>Agents Need Rails</title><link>https://dev-log.prefect.io/agents-need-rails/</link><pubDate>Sun, 10 May 2026 12:00:00 -0500</pubDate><guid>https://dev-log.prefect.io/agents-need-rails/</guid><description>&lt;p>If you&amp;rsquo;d asked me a year ago whether I&amp;rsquo;d ever ship a library without reading every line of its source code, I would have clutched my pearls and spluttered indignantly. Shipping a black box gets engineers paged at 3am, gets companies on the front page of Hacker News (for the wrong reasons), and earns you a reputation as a slop cannon. Reading the source is part of the job, and skipping that step is how you end up putting your name on something with strong opinions about correctness&lt;/p>
&lt;p>Dear reader, I did it anyway.&lt;/p>
&lt;p>The library is &lt;a href="https://github.com/PrefectHQ/burner-redis">&lt;code>burner-redis&lt;/code>&lt;/a>, an embedded Redis-compatible backend built to replace &lt;a href="https://github.com/cunla/fakeredis">&lt;code>fakeredis&lt;/code>&lt;/a> in the in-memory mode of &lt;a href="https://github.com/chrisguidry/docket">&lt;code>docket&lt;/code>&lt;/a>, which is an asynchronous background task system built on Redis streams used as a dependency by both &lt;a href="https://github.com/jlowin/fastmcp">FastMCP&lt;/a> and &lt;a href="https://github.com/PrefectHQ/prefect">Prefect&lt;/a>. In fairness, &lt;code>fakeredis&lt;/code> is built as a testing tool, and we were using it for a use case beyond its design; memory leaks in its Lua implementation and a string of breaking changes were the natural cost of stretching it that way. The goal was never &amp;ldquo;Redis, but better&amp;rdquo;; the goal was to support the Redis behavior &lt;code>docket&lt;/code> needs, as a drop-in for &lt;code>redis.asyncio.Redis&lt;/code>.&lt;/p>
&lt;p>An AI coding agent wrote nearly all of it, and I trusted the tests, the interfaces, and the prior art to do the steering. The question of whether an agent can write code has been answered to death by now; the interesting one is &lt;em>when&lt;/em> agent-written code holds up, with this project as a useful data point because it did.&lt;/p>
&lt;h2 id="the-target-was-already-specified">The Target Was Already Specified&lt;/h2>
&lt;p>This project worked because every interface was already pinned down, leaving the agent to implement against contracts that already existed and were enforceable, with three contracts doing almost all the work:&lt;/p>
&lt;ul>
&lt;li>&lt;code>docket&lt;/code>&amp;rsquo;s test suite already described which Redis behaviors &lt;code>burner-redis&lt;/code> needed to support; a test that passed against real Redis but failed against &lt;code>burner-redis&lt;/code> was a bug, with no judgment call required.&lt;/li>
&lt;li>&lt;a href="https://github.com/redis/redis-py">&lt;code>redis.asyncio.Redis&lt;/code>&lt;/a>, the async client in &lt;code>redis-py&lt;/code>, defined the Python-facing API surface (return types, exception classes, method signatures, all of it), and the agent had to match the shape that was already there.&lt;/li>
&lt;li>Redis itself, with fifteen-plus years of mature command semantics, provided the third rail; when a command&amp;rsquo;s behavior was unclear, the answer was always &amp;ldquo;go run it against real Redis and see what it does.&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;p>Put those together and correctness is externally defined at every layer, leaving the agent no room to &amp;ldquo;decide&amp;rdquo; the answer, which was already living in a test, a &lt;code>redis-py&lt;/code> stub, or &lt;code>redis-cli&lt;/code>. That&amp;rsquo;s a very different shape of work from &amp;ldquo;build me a thing that does X&amp;rdquo;, where the channel between right and wrong is narrower and falling off either bank is observable.&lt;/p>
&lt;h2 id="where-it-was-still-hard">Where It Was Still Hard&lt;/h2>
&lt;p>Redis still has sharp edges, and &lt;code>redis-py&lt;/code> compatibility is its own little crucible:&lt;/p>
&lt;ul>
&lt;li>Return types and exceptions have to match &lt;code>redis-py&lt;/code>; a method that returns &lt;code>bytes&lt;/code> when the client expects &lt;code>int&lt;/code> is technically defensible and operationally broken.&lt;/li>
&lt;li>Pipelines and locks are API-shape problems first and storage problems second, and what gets buffered, batched, and atomically applied has to feel identical from the client&amp;rsquo;s perspective.&lt;/li>
&lt;li>Streams, consumer groups, and Lua scripting have subtle behaviors you only catch by running real workloads through them.&lt;/li>
&lt;/ul>
&lt;p>Skip the tour. An agent can grind through this category of work for hours on end, patiently and methodically, as long as failures are observable, because a test that fails or a return type that mismatches gives unambiguous feedback, and an agent grinding inside that loop pulls its weight.&lt;/p>
&lt;h2 id="when-agents-earn-it">When Agents Earn It&lt;/h2>
&lt;p>The result is a library that&amp;rsquo;s actually pretty useful, and the AI-agent workflow was genuinely cool, but the sober conclusion matters more than the cool story. Agents are strongest when the interface already exists, the behavior is testable, the prior art is mature, and correctness is externally defined. Drop any one of those rails and you&amp;rsquo;re back to a different kind of problem altogether, one where the agent has to invent something rather than match it.&lt;/p>
&lt;p>The agent wrote the code, but the tests, interfaces, and prior art did much of the steering.&lt;/p></description></item></channel></rss>