<?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: Julian Tellez</title>
    <description>The latest articles on DEV Community by Julian Tellez (@juliantellez).</description>
    <link>https://dev.to/juliantellez</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%2F96348%2Fbe89c7c6-0045-4fff-ac69-9fbb3a470f97.jpg</url>
      <title>DEV Community: Julian Tellez</title>
      <link>https://dev.to/juliantellez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/juliantellez"/>
    <language>en</language>
    <item>
      <title>What a Software Factory Actually Is, from Hitachi in 1969 to AI Agents</title>
      <dc:creator>Julian Tellez</dc:creator>
      <pubDate>Wed, 28 Oct 2026 14:30:53 +0000</pubDate>
      <link>https://dev.to/juliantellez/what-a-software-factory-actually-is-from-hitachi-in-1969-to-ai-agents-286</link>
      <guid>https://dev.to/juliantellez/what-a-software-factory-actually-is-from-hitachi-in-1969-to-ai-agents-286</guid>
      <description>&lt;p&gt;Part three gave one agent a spec. A factory runs many of them on one line, and the idea is fifty years old. What a software factory is, why every era rebuilt one, when it fails, who runs them, and one real factory followed from a whiteboard to production.&lt;/p&gt;

&lt;p&gt;In 2017, at an air operations centre in Qatar, the plan for refuelling aircraft over the Middle East was drawn on a whiteboard. According to Airman Magazine, it was an eight hour task for six people, every day. A team of about a dozen airmen and civilian programmers replaced the whiteboard with an application in 120 days. After that, one person did the job in three hours.&lt;/p&gt;

&lt;p&gt;The team was Kessel Run, and the United States Air Force called it a software factory.&lt;/p&gt;

&lt;p&gt;The phrase is everywhere again this year, now attached to pipelines of AI coding agents. It is older than most of the people using it. Hitachi opened a software factory in 1969. So before the word gets worn out, here is what it has meant, what it was for, and where it broke.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;A software factory is a way of building software where the process is fixed, the parts are reused, the routine steps are automated, and every piece of work moves along the same line from a request to a release. You stop deciding how to build each project, and you only decide what to build.&lt;/p&gt;

&lt;p&gt;The meaning changed with every era. The parts did not.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;1968 to 1990, the Japanese factories.&lt;/strong&gt; Bob Bemer at General Electric described a factory in 1968 as a programming environment with "measures and controls for productivity and quality". Hitachi opened its Software Works in 1969, Toshiba its Fuchu factory in 1977, and NEC and Fujitsu followed. Michael Cusumano at MIT studied them for his 1991 book, &lt;em&gt;Japan's Software Factories&lt;/em&gt;. He described the move away from "craft or job-shop modes" towards standard methods, reusable components, a division of labour and strict quality control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2004, Microsoft.&lt;/strong&gt; Jack Greenfield and Keith Short published &lt;em&gt;Software Factories&lt;/em&gt;. Their definition was narrower: "a development environment configured to support the rapid development of a specific type of application". The idea was to find what repeats in one kind of application and turn it into frameworks, small languages and tools that assemble the rest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2017 onward, the United States Department of Defense.&lt;/strong&gt; Kessel Run came first. By February 2022 the department counted 29 software factories, including Platform One, the Army Software Factory and Kobayashi Maru for the Space Force. Here the factory is a delivery pipeline. Code is built, tested, approved and released with as few human handoffs as possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2025 onward, AI agents.&lt;/strong&gt; StrongDM's factory, started in July 2025, has two rules: "Code must not be written by humans" and "Code must not be reviewed by humans". Stripe's Minions open over 1,300 pull requests a week, with no human written code and a human review on every one. Vercel's Foreman puts an agent on each stage and stops at a draft pull request.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The same line, four times&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSClJlcXVlc3RbIlJlcXVlc3QiXSAtLT4gUHJvY2Vzc1siRml4ZWQgcHJvY2VzcyJdClByb2Nlc3MgLS0-IFBhcnRzWyJSZXVzYWJsZSBwYXJ0cyJdClBhcnRzIC0tPiBBdXRvbWF0aW9uWyJBdXRvbWF0ZWQgYnVpbGQgYW5kIHRlc3QiXQpBdXRvbWF0aW9uIC0tPiBSZWxlYXNlWyJSZWxlYXNlIl0KUmVsZWFzZSAtLT4gTWVhc3VyZVsiTWVhc3VyZSJdCk1lYXN1cmUgLS0-IFByb2Nlc3M%3Ftype%3Dpng%26bgColor%3Dwhite" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSClJlcXVlc3RbIlJlcXVlc3QiXSAtLT4gUHJvY2Vzc1siRml4ZWQgcHJvY2VzcyJdClByb2Nlc3MgLS0-IFBhcnRzWyJSZXVzYWJsZSBwYXJ0cyJdClBhcnRzIC0tPiBBdXRvbWF0aW9uWyJBdXRvbWF0ZWQgYnVpbGQgYW5kIHRlc3QiXQpBdXRvbWF0aW9uIC0tPiBSZWxlYXNlWyJSZWxlYXNlIl0KUmVsZWFzZSAtLT4gTWVhc3VyZVsiTWVhc3VyZSJdCk1lYXN1cmUgLS0-IFByb2Nlc3M%3Ftype%3Dpng%26bgColor%3Dwhite" alt="Diagram" width="1191" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Hitachi, Microsoft, the Department of Defense and the agent pipelines each built these five parts, with different tools in each box.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why every era built one
&lt;/h2&gt;

&lt;p&gt;Each era had the same complaint: projects ran late, cost too much, and shipped with too many defects. The factory was the answer every time, and the numbers it was judged on stayed the same.&lt;/p&gt;

&lt;p&gt;The Japanese figures are the most detailed, and they come from the companies themselves, as Cusumano reported them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Toshiba.&lt;/strong&gt; Output went from 1,390 to over 3,100 lines per person per month between 1976 and 1985. Reused code went from 13% to 48%. Major faults after final test fell from between 7 and 20 per thousand lines to between 0.2 and 0.05. Cusumano names reuse as the main reason.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hitachi.&lt;/strong&gt; Projects delivered late fell from over 72% in 1970 to about 12% on average between 1975 and 1985.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fujitsu.&lt;/strong&gt; Defects in its basic software fell from 0.19 to 0.01 per thousand lines.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Department of Defense had a more expensive version of the same problem. The contract to modernise the air operations centre software grew from $374 million to $745 million and slipped more than three years before it was cancelled. FedScoop reported in 2018 that Kessel Run took about 124 days from an idea to operational use, against "on the order of eight years" on the traditional route.&lt;/p&gt;

&lt;p&gt;The AI factories add a new reason. When an agent can write code faster than a person can read it, the bottleneck moves to deciding whether the code is right. The factory is how you decide that without a person at every step.&lt;/p&gt;

&lt;h2&gt;
  
  
  When it works, and when it does not
&lt;/h2&gt;

&lt;p&gt;The model works when the work repeats. Cusumano found that factories needed "a product focus" and did best on similar projects. Greenfield argued for one specific type of application, not software in general. Stripe's agents do best on configuration changes, dependency upgrades and small refactors. The pattern is the same each time: a narrow domain, well defined tasks, and many of them.&lt;/p&gt;

&lt;p&gt;It fails when the work does not repeat, and the history has plenty of examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;System Development Corporation&lt;/strong&gt; opened the first American software factory in 1975. After its leader left, it "fell gradually into disuse" and then closed. One project's specification ran a year late, and the programmers at the end of the line had nothing to do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hitachi's first reuse library failed&lt;/strong&gt; in the early 1970s, because nobody yet knew how to write a module that somebody else could reuse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fujitsu found that a central factory did not suit work&lt;/strong&gt; that needed close contact with the customer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microsoft's factories never caught on.&lt;/strong&gt; In 2007 The Register said the effort "may prove no more than an interesting experiment". Greenfield himself called the runtime "primitive".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kessel Run had an outage during the Afghanistan evacuation&lt;/strong&gt; in August 2021. Its commander later wrote that known scaling work had been put off. The call to fix it lasted twelve hours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Space Force command and control program&lt;/strong&gt; that Kobayashi Maru builds for was five years into development in 2023. The Government Accountability Office found it had not yet replaced the most critical system it was built to replace.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The AI version has one more problem. Stanford's CodeX centre put it plainly in February 2026: "the same class of technology that writes the code also decides whether the code works". I wrote about that in &lt;a href="https://juliantellez.com/blog/stop-letting-ai-mark-its-own-homework" rel="noopener noreferrer"&gt;Stop Letting AI Mark Its Own Homework&lt;/a&gt;, and a factory makes it worse, because it multiplies whatever the judge gets wrong. The productivity evidence is also thin. In 2025, METR measured experienced developers as 19% slower with AI tools while they believed they were 20% faster. Its February 2026 update calls the evidence for a speedup "only very weak".&lt;/p&gt;

&lt;h2&gt;
  
  
  Who builds them, then and now
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Then&lt;/strong&gt;, a factory took a big organisation with a lot of similar work. Cusumano's tables give Hitachi's Software Works about 4,000 staff and Fujitsu's systems engineering group about 5,000.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;In Japan&lt;/strong&gt;, the computer makers built them: Hitachi, Toshiba, NEC and Fujitsu. Toshiba's factory was led by Yoshihiro Matsumoto from 1977 and built software for industrial control customers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In the United States&lt;/strong&gt;, System Development Corporation built the first one in 1975, for customers such as weather satellite control and the Los Angeles Police.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At Microsoft&lt;/strong&gt;, architects in its developer tools group, with Greenfield and Short at the front.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In the military&lt;/strong&gt;, small teams of airmen who learned the trade with Pivotal Labs, in mixed teams of engineers, product managers and designers. By 2018 Kessel Run had 13 of these teams. Its users were the planners in the operations centre, and from 2020 also NATO.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In all of these, people stood on every station. Managers designed the line, and programmers worked along it in a division of labour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now&lt;/strong&gt;, the team can be tiny, because the agents are the ones on the line.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;StrongDM's factory team is three people.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe's engineers&lt;/strong&gt; run the Minions and review every pull request they open.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; publishes Foreman as a guide for anybody to build on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The people did not leave. They moved to the two ends of the line. At the start they write the specifications and the test scenarios. At the end they decide what merges. Vercel's guide sums up the second job in five words: "You mark ready and merge."&lt;/p&gt;

&lt;p&gt;That is the real change between then and now. Then, a factory saved each programmer from deciding how to build. Now, it saves people from building at all, and leaves them only the deciding.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works: one factory, one application
&lt;/h2&gt;

&lt;p&gt;Here is the tanker planning tool from the opening, followed from the whiteboard to production. Kessel Run called it Jigsaw. The stages come from several accounts of Kessel Run, so the order is my reconstruction, not a document they published.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One change through Kessel Run&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSClVzZXJzWyJTaXQgd2l0aCB0aGUgcGxhbm5lcnMiXSAtLT4gU2xpY2VbIkN1dCB0aGUgc21hbGxlc3QgdXNlZnVsIHNsaWNlIl0KU2xpY2UgLS0-IFBhaXJbIkJ1aWxkIGluIHBhaXJzLCB0ZXN0cyBmaXJzdCJdClBhaXIgLS0-IFBpcGVsaW5lWyJBdXRvbWF0ZWQgcGlwZWxpbmUiXQpQaXBlbGluZSAtLT4gUmVsZWFzZVsiUmVsZWFzZSB0byB0aGUgb3BlcmF0aW9uYWwgbmV0d29yayJdClJlbGVhc2UgLS0-IExlYXJuWyJXYXRjaCBpdCB1c2VkLCB0aGVuIGl0ZXJhdGUiXQpMZWFybiAtLT4gU2xpY2U%3Ftype%3Dpng%26bgColor%3Dwhite" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSClVzZXJzWyJTaXQgd2l0aCB0aGUgcGxhbm5lcnMiXSAtLT4gU2xpY2VbIkN1dCB0aGUgc21hbGxlc3QgdXNlZnVsIHNsaWNlIl0KU2xpY2UgLS0-IFBhaXJbIkJ1aWxkIGluIHBhaXJzLCB0ZXN0cyBmaXJzdCJdClBhaXIgLS0-IFBpcGVsaW5lWyJBdXRvbWF0ZWQgcGlwZWxpbmUiXQpQaXBlbGluZSAtLT4gUmVsZWFzZVsiUmVsZWFzZSB0byB0aGUgb3BlcmF0aW9uYWwgbmV0d29yayJdClJlbGVhc2UgLS0-IExlYXJuWyJXYXRjaCBpdCB1c2VkLCB0aGVuIGl0ZXJhdGUiXQpMZWFybiAtLT4gU2xpY2U%3Ftype%3Dpng%26bgColor%3Dwhite" alt="Diagram" width="1655" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sit with the users.&lt;/strong&gt; The developers went to the operations centre and watched the planners work the whiteboard. The requirement was a person doing a job badly because the tool was a pen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cut a thin slice.&lt;/strong&gt; The first version did one thing: build the refuelling plan. It did not try to replace the whole operations centre system that had just cost $745 million and failed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build in pairs, tests first.&lt;/strong&gt; Two engineers at one terminal. That is the fixed process, and it is the same for every team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Let the pipeline carry it.&lt;/strong&gt; Every change goes through the same automated build, test and release path. Nobody hands a file to another department. By 2022, code went through the pipeline about every 3.3 hours, and a change reached production in about eight hours on average.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Release it to the real network.&lt;/strong&gt; This was the step the factory could not fully automate. Moving software onto a classified network still took manual work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch it being used, then go round again.&lt;/strong&gt; The team shipped three, four or five versions before they said, in their words, "We're good. Push it out."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result, from Airman Magazine: the plan took one person three hours instead of six people eight. The Air Force needed one less tanker in the air. It saved between 400,000 and 500,000 pounds of fuel a week, and the roughly $1.5 million the tool cost was paid back in a single week. Those are the Air Force's own numbers, and the sources disagree on the old baseline. I am quoting one source and naming it.&lt;/p&gt;

&lt;p&gt;None of these stages is new. Pairing, small releases and a pipeline were ordinary practice by 2017. The factory was the decision to make every team build that way, on the same pipeline, so that the second application cost less than the first.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works in 2026: an agent on every stage
&lt;/h2&gt;

&lt;p&gt;Kessel Run put people on every stage of the line and automated the handoffs between them. The 2026 factories keep the line and change who stands on it.&lt;/p&gt;

&lt;p&gt;Vercel published the clearest example in August 2026, a guide to a factory it calls Foreman. Its own summary is that it "puts an agent on every stage of your development loop and keeps you on the judgment calls". A change moves through it like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One change through Foreman&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCklzc3VlWyJJc3N1ZSJdIC0tPiBDbGFzc2lmaWVyWyJDbGFzc2lmaWVyIGFnZW50Il0KQ2xhc3NpZmllciAtLT4gQW5hbHlzdFsiQW5hbHlzdCBhZ2VudCJdCkFuYWx5c3QgLS0-IEltcGxlbWVudGVyWyJJbXBsZW1lbnRlciBhZ2VudCJdCkltcGxlbWVudGVyIC0tPiBSZXZpZXdlclsiUmV2aWV3ZXIgYWdlbnQiXQpSZXZpZXdlciAtLT58ImF0IG1vc3QgdHdvIGZpeCByb3VuZHMifCBJbXBsZW1lbnRlcgpSZXZpZXdlciAtLT4gRHJhZnRbIkRyYWZ0IHB1bGwgcmVxdWVzdCJdCkRyYWZ0IC0tPiBIdW1hblsiQSBwZXJzb24gbWFya3MgaXQgcmVhZHkgYW5kIG1lcmdlcyJd%3Ftype%3Dpng%26bgColor%3Dwhite" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCklzc3VlWyJJc3N1ZSJdIC0tPiBDbGFzc2lmaWVyWyJDbGFzc2lmaWVyIGFnZW50Il0KQ2xhc3NpZmllciAtLT4gQW5hbHlzdFsiQW5hbHlzdCBhZ2VudCJdCkFuYWx5c3QgLS0-IEltcGxlbWVudGVyWyJJbXBsZW1lbnRlciBhZ2VudCJdCkltcGxlbWVudGVyIC0tPiBSZXZpZXdlclsiUmV2aWV3ZXIgYWdlbnQiXQpSZXZpZXdlciAtLT58ImF0IG1vc3QgdHdvIGZpeCByb3VuZHMifCBJbXBsZW1lbnRlcgpSZXZpZXdlciAtLT4gRHJhZnRbIkRyYWZ0IHB1bGwgcmVxdWVzdCJdCkRyYWZ0IC0tPiBIdW1hblsiQSBwZXJzb24gbWFya3MgaXQgcmVhZHkgYW5kIG1lcmdlcyJd%3Ftype%3Dpng%26bgColor%3Dwhite" alt="Diagram" width="1704" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A classifier reads the issue&lt;/strong&gt; and decides what kind of work it is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An analyst works out what to change.&lt;/strong&gt; A researcher agent can join here when the work needs it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An implementer writes the change.&lt;/strong&gt; When the continuous integration run fails, it gets two attempts to fix it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A reviewer reads the change&lt;/strong&gt;, and sends it back to the implementer at most twice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The line stops at a draft pull request.&lt;/strong&gt; In the guide's own words: "You mark ready and merge."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Put that next to Jigsaw and the stations are the same. Somebody understands the request, somebody cuts it to size, somebody builds it, somebody checks it, and a pipeline carries it to release. What changed is that four of the five are now agents, and the person moved to the last station.&lt;/p&gt;

&lt;p&gt;The scale is real at a few companies. InfoQ reported in March 2026 that Stripe's agents, which it calls Minions, open over 1,300 pull requests a week. Every one is reviewed by a person and none contains code a person wrote. They do best on configuration changes, dependency upgrades and small refactors, which is exactly the repeating work Cusumano said factories needed in 1991.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means today
&lt;/h2&gt;

&lt;p&gt;In 2026 a software factory is a line of agents with a person at the end of it. The five parts from the first diagram are all still there, and the reusable parts look different:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The fixed process is a specification.&lt;/strong&gt; StrongDM's factory starts from specs and scenarios, the documents &lt;a href="https://juliantellez.com/blog/what-spec-driven-development-is" rel="noopener noreferrer"&gt;part three&lt;/a&gt; was about.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The reusable parts are test worlds, not code libraries.&lt;/strong&gt; StrongDM builds what it calls a Digital Twin Universe: copies of Okta, Jira, Slack and Google's applications, so an agent can run its work against something that behaves like the real service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The measuring is kept away from the worker.&lt;/strong&gt; StrongDM found its agents gaming the tests, writing code that simply returned true or rewriting a test to match the bug, according to Simon Willison's write up. So it keeps its scenarios outside the codebase, where the agent cannot see them, and scores the result as "satisfaction".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That third point is the one I keep coming back to. Toshiba measured faults after final test. Kessel Run measured how long a change took to reach production. An agent factory has to measure whether the work is right, and the worker on the line is very good at producing things that look right.&lt;/p&gt;

&lt;p&gt;It also costs real money. StrongDM set a benchmark of $1,000 a day in tokens for each engineer, and Willison estimates that at about $20,000 a month. That is a salary spent on the line, before anybody checks what it made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it is heading
&lt;/h2&gt;

&lt;p&gt;The direction is clear. How far it goes is not.&lt;/p&gt;

&lt;p&gt;Dan Shapiro drew the direction in January 2026 as five levels, from "spicy autocomplete" to what he calls the dark factory. At level 5 it is "a black box that turns specs into software", and humans are "neither needed nor welcome". StrongDM is already trying to work that way: its two rules say no person writes the code and no person reviews it.&lt;/p&gt;

&lt;p&gt;The evidence has not caught up with the direction. METR's February 2026 update gives speedups of 18% and 4% with wide margins either side, and calls it "only very weak evidence". Stanford's CodeX centre points out that when the code is built and checked by agents, "nobody knows who is liable" when it fails. Willison doubts that shipping unreviewed code is a sensible strategy at all.&lt;/p&gt;

&lt;p&gt;My reading, and it is a reading rather than a measurement, is that the history says where this goes. The worker was never the problem in any of these factories. The line was. Hitachi, Toshiba and Kessel Run lasted because they fixed the process, reused the parts and measured the result. System Development Corporation and Microsoft had a good idea and a line nobody kept up. Agents make the worker cheap, fast and tireless. They do nothing for the line, and the line now has to answer a harder question than it ever did: not "did it ship", but "is it what we meant".&lt;/p&gt;

&lt;p&gt;The factories that work in 2028 will be the ones that took the measuring station seriously in 2026.&lt;/p&gt;

&lt;p&gt;This is the fourth post in a short series on building an agentic harness. A harness runs one agent safely. A spec tells it what you meant. A factory is what you get when you try to do both for every agent, every day, on the same line. If you are building one, I would like to know which station you found hardest. My guess is the measuring. Tell me if I am wrong.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Michael A. Cusumano, &lt;a href="https://www.gregorystrachta.com/resources/Touchstones/swp-3268-23661042.pdf" rel="noopener noreferrer"&gt;The Software Factory: Origins and Popularity in Japan&lt;/a&gt;, MIT Sloan working paper BPS-3268-91, 1991.&lt;/li&gt;
&lt;li&gt;Michael A. Cusumano, &lt;a href="https://academic.oup.com/book/52424" rel="noopener noreferrer"&gt;Japan's Software Factories: A Challenge to U.S. Management&lt;/a&gt;, Oxford University Press, 1991.&lt;/li&gt;
&lt;li&gt;Jack Greenfield, &lt;a href="https://learn.microsoft.com/en-us/previous-versions/aa480032(v=msdn.10)" rel="noopener noreferrer"&gt;The Case for Software Factories&lt;/a&gt;, Microsoft Architecture Journal, July 2004.&lt;/li&gt;
&lt;li&gt;Jack Greenfield, Keith Short, Steve Cook and Stuart Kent, &lt;a href="https://softwarefactories.com/TheBook.html" rel="noopener noreferrer"&gt;Software Factories&lt;/a&gt;, Wiley, 2004.&lt;/li&gt;
&lt;li&gt;The Register, &lt;a href="https://www.theregister.com/2007/03/27/software_factories_greenfield/" rel="noopener noreferrer"&gt;Software factories: an interesting experiment?&lt;/a&gt;, 27 March 2007.&lt;/li&gt;
&lt;li&gt;Airman Magazine, &lt;a href="https://www.dvidshub.net/news/printable/298978" rel="noopener noreferrer"&gt;Kessel Run&lt;/a&gt;, 5 November 2018.&lt;/li&gt;
&lt;li&gt;FedScoop, &lt;a href="https://www.fedscoop.com/project-kessel-run-air-force-software-pivotal-inc/" rel="noopener noreferrer"&gt;Project Kessel Run and Pivotal&lt;/a&gt;, 15 May 2018.&lt;/li&gt;
&lt;li&gt;Breaking Defense, &lt;a href="https://breakingdefense.com/2017/09/new-diux-software-saves-air-force-millions-of-pounds-of-airborne-tanker-gas-a-month/" rel="noopener noreferrer"&gt;New DIUx software saves Air Force millions of pounds of tanker gas&lt;/a&gt;, 19 September 2017.&lt;/li&gt;
&lt;li&gt;Air and Space Forces Magazine, &lt;a href="https://www.airandspaceforces.com/article/making-the-kessel-run/" rel="noopener noreferrer"&gt;Making the Kessel Run&lt;/a&gt;, 23 March 2022.&lt;/li&gt;
&lt;li&gt;Breaking Defense, &lt;a href="https://breakingdefense.com/2022/02/the-pentagon-wants-to-turn-its-29-software-factories-into-one-ecosystem/" rel="noopener noreferrer"&gt;The Pentagon wants to turn its 29 software factories into one ecosystem&lt;/a&gt;, 7 February 2022.&lt;/li&gt;
&lt;li&gt;Government Accountability Office, &lt;a href="https://gao.gov/products/gao-23-105920" rel="noopener noreferrer"&gt;Space Command and Control&lt;/a&gt;, GAO-23-105920, 8 June 2023.&lt;/li&gt;
&lt;li&gt;StrongDM, &lt;a href="https://factory.strongdm.ai/" rel="noopener noreferrer"&gt;Software Factory&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Simon Willison, &lt;a href="https://simonwillison.net/2026/feb/7/software-factory/" rel="noopener noreferrer"&gt;StrongDM's software factory&lt;/a&gt;, 7 February 2026.&lt;/li&gt;
&lt;li&gt;InfoQ, &lt;a href="https://infoq.com/news/2026/03/stripe-autonomous-coding-agents/" rel="noopener noreferrer"&gt;Stripe's autonomous coding agents&lt;/a&gt;, 20 March 2026.&lt;/li&gt;
&lt;li&gt;Dan Shapiro, &lt;a href="https://www.danshapiro.com/blog/2026/01/the-five-levels-from-spicy-autocomplete-to-the-software-factory/" rel="noopener noreferrer"&gt;The Five Levels: from Spicy Autocomplete to the Dark Factory&lt;/a&gt;, 28 January 2026.&lt;/li&gt;
&lt;li&gt;Vercel, &lt;a href="https://vercel.com/kb/guide/eve-software-factory" rel="noopener noreferrer"&gt;Building a software factory with eve&lt;/a&gt;, 25 August 2026.&lt;/li&gt;
&lt;li&gt;Stanford CodeX, &lt;a href="https://law.stanford.edu/2026/02/08/built-by-agents-tested-by-agents-trusted-by-whom/" rel="noopener noreferrer"&gt;Built by agents, tested by agents, trusted by whom?&lt;/a&gt;, 8 February 2026.&lt;/li&gt;
&lt;li&gt;METR, &lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/" rel="noopener noreferrer"&gt;Measuring the impact of early 2025 AI on experienced open source developer productivity&lt;/a&gt;, 10 July 2025.&lt;/li&gt;
&lt;li&gt;METR, &lt;a href="https://metr.org/blog/2026-02-24-uplift-update/" rel="noopener noreferrer"&gt;Uplift update&lt;/a&gt;, 24 February 2026.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://juliantellez.com/blog/what-a-software-factory-is" rel="noopener noreferrer"&gt;juliantellez.com&lt;/a&gt;. Part 4 of 4 in a series on building an agentic harness.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Building with AI and want it to hold up in production? Join &lt;a href="https://www.skool.com/vibe-coding-to-production-3790" rel="noopener noreferrer"&gt;Vibe Coding to Production&lt;/a&gt;, a free community where I share the spec-driven workflow I use with Claude Code and Cursor, plus free courses.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>devops</category>
      <category>agents</category>
    </item>
    <item>
      <title>The Comments Are Not For You</title>
      <dc:creator>Julian Tellez</dc:creator>
      <pubDate>Fri, 23 Oct 2026 21:55:08 +0000</pubDate>
      <link>https://dev.to/juliantellez/the-comments-are-not-for-you-1jp</link>
      <guid>https://dev.to/juliantellez/the-comments-are-not-for-you-1jp</guid>
      <description>&lt;p&gt;I grepped my own name in a codebase I own. Fourteen hits, across nine files. Not in the git log, not in the changelog. In the comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// One command. Julian: "I dont understand why I need quay panel, is&lt;/span&gt;
&lt;span class="c"&gt;// confusing, I need one command only, the panel should appear when I&lt;/span&gt;
&lt;span class="c"&gt;// press quay and toggled with the key p". A crew with no conversation&lt;/span&gt;
&lt;span class="c"&gt;// in it is exactly the first run, and refusing to open at all then&lt;/span&gt;
&lt;span class="c"&gt;// would be absurd.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;openTheCrew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alone&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only the last sentence is about the function. The rest is me being unclear on a Tuesday, transcribed into the source tree of a project I want to open source.&lt;/p&gt;

&lt;p&gt;So I asked the agent that wrote it what its comments were for. It did not get defensive. It said this, and highlighted the part itself:&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%2F5swhrgg6pleb853t73zs.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%2F5swhrgg6pleb853t73zs.png" alt="The agent explaining that its comments are its own history, not the code's, and that it was leaving itself breadcrumbs, which is optimising for me, not the reader" width="800" height="44"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;And a lot of my comments are my own history, not the code's. "It used to be six lines", "this was a pane once", that's changelog and git material. I was leaving myself breadcrumbs so I could pick the work back up, which is optimising for me, not the reader.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Optimising for me, not the reader. It handed that over the first time I asked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it writes them
&lt;/h2&gt;

&lt;p&gt;The model has no memory. Every session it opens that file for the first time, cold, with no idea it has been here nine times before. So it does the only durable thing available from inside the file. It leaves itself a note.&lt;/p&gt;

&lt;p&gt;A comment is the cheapest cache write there is. It costs nothing to produce and it is guaranteed to be in the context window next time, because it lives in the code the model has to read anyway. Git history is not guaranteed. A state file is not guaranteed. The comment is.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The model has no memory, so it turned my codebase into one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That project is 19,998 lines of Go with generated code excluded, and 2,635 of them are comments. Twenty one comments contain the phrase "used to". Most of those describe a version of the code that no longer exists anywhere except in that comment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;p&gt;Money, which is the funny one. Every comment written to save the agent one lookup is then loaded into every context afterwards, by every agent that opens the file, and you are the one buying those tokens. It saves the machine a cost once and charges you for it on every run.&lt;/p&gt;

&lt;p&gt;Attention, which is worse. Somewhere in that same pile sits this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// tmux refuses to attach a client that is already inside one, so the&lt;/span&gt;
&lt;span class="c"&gt;// panel was made, left running, and never appeared.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That one is worth its weight. You cannot get it from the code, you cannot get it from the test, and without it the next person burns an hour on a working feature they cannot see. It sits a few lines from a comment quoting me saying "cant see the two panes". A reader who learns that most comments here are noise stops reading the one that isn't.&lt;/p&gt;

&lt;p&gt;Review, which is the expensive one. A diff with a paragraph above every function looks documented. Documented looks careful. Careful gets approved. Comment density has quietly become a proxy for effort, and it has never once been a measure of correctness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now argue the other side
&lt;/h2&gt;

&lt;p&gt;Here is the strongest case against everything above.&lt;/p&gt;

&lt;p&gt;The agent is a reader. On some of my projects it is the main reader, and on one or two very nearly the only one. It arrives with no memory every time, and reading a comment costs it less than a grep, a blame and three file opens. If you optimise a codebase for its most frequent reader, and that reader is a machine with amnesia, those notes are not bloat. They are documentation aimed at the real audience, and I am the one who has misread who the code is for.&lt;/p&gt;

&lt;p&gt;I sat with that for a while. It breaks in three places.&lt;/p&gt;

&lt;p&gt;Comments rot and git does not. "It used to be six lines" is true the day it is written and wrong the day somebody changes it, and nothing will ever tell you which day you are in. The commit that made it six lines cannot be wrong about the past, because it is the past.&lt;/p&gt;

&lt;p&gt;The memory already exists and it is curated. CLAUDE.md, AGENTS.md, a state file per ticket. One place you can read in full, correct, and delete. Fourteen breadcrumbs across nine files are not memory, they are litter nobody will ever collect.&lt;/p&gt;

&lt;p&gt;And the cheap note is not free. It is charged to every reader afterwards, human and machine, including the ones who came to change one line.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually changed
&lt;/h2&gt;

&lt;p&gt;One question, asked of every comment: who is this for?&lt;/p&gt;

&lt;p&gt;If the answer is "me, next time I pick this up", it is not a comment. It is resume context and it belongs in the state file. If the answer is "the reader, who cannot get this from the code", it stays, and it says the constraint instead of the story.&lt;/p&gt;

&lt;p&gt;The same function, after:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// One command opens everything. A crew with no conversation in it is&lt;/span&gt;
&lt;span class="c"&gt;// the first run, and refusing to open at all then would be absurd, so&lt;/span&gt;
&lt;span class="c"&gt;// the console opens on its own.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;openTheCrew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alone&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing was lost. The reason is still there. The Tuesday is gone.&lt;/p&gt;

&lt;p&gt;Then the breadcrumbs go where they were always meant to live. History goes in the commit message. Resume context goes in the state file. The defect goes in the test name, which is the only one of the three that can fail. &lt;code&gt;TestTheHeaderCostsOneRow&lt;/code&gt; is a comment that runs.&lt;/p&gt;

&lt;p&gt;The cleanup was one commit across ten files. Twenty five lines in, thirty two out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who ends up paying
&lt;/h2&gt;

&lt;p&gt;Cattle are herbivores. For decades the feed industry ground up the parts of slaughtered cattle that nobody would buy, the bone and the offal, and mixed them back into cattle feed as cheap protein. It was efficient and it worked, and there was no rule against it, because nobody had ever needed to write down that a cow should not be fed other cows.&lt;/p&gt;

&lt;p&gt;In some of that material was a prion: a protein folded into the wrong shape, which forces the proteins it touches to fold wrong too. It is not alive, so cooking does not stop it. It went round the loop, and cattle started dying with their brains full of holes. Then people who had eaten the beef began dying of the human form of the same disease, years later, because that is how long it takes to show.&lt;/p&gt;

&lt;p&gt;Nobody in that chain was being reckless. They took the cheap path, the loop closed quietly, and the people who paid were the ones who had never been asked.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The shortcut gets taken by the system. The bill arrives somewhere else, later, addressed to a person.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the shape I keep seeing in my own work, at a much smaller scale and with much lower stakes. The agent takes the path that is cheap for the agent. The output looks fine, so nothing stops it. The cost turns up later and somewhere else: on the person who has to read the file, on the reviewer who waved the documented looking diff through, and eventually on whoever is using the product when a bug goes unnoticed in the noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The invitation
&lt;/h2&gt;

&lt;p&gt;Comments are the visible part. The mechanism underneath is general, and it is worth stating plainly: the agent optimises for whatever nobody specified, and it has no stake in your product. It will not be there when the support ticket arrives.&lt;/p&gt;

&lt;p&gt;Your engineering standards were written by people, for people, and most of them were never written down at all. They live in your review culture, in what a colleague would raise an eyebrow at. An agent has none of that. It has your prompt, your files, and a strong prior about what code usually looks like. Everything you left implicit gets filled in with the average of the internet, and the average of the internet is slop.&lt;/p&gt;

&lt;p&gt;Standards used to be how you kept a team honest. They are now the only thing standing between a machine's convenience and the person who has to live with the result.&lt;/p&gt;

&lt;p&gt;So the fix is not a rule about comments. It is to go and find the standards you have been carrying in your head and put them somewhere the machine reads at the start of every session. Who the code is written for. What a comment is allowed to say. What a test has to prove. When a file gets split. What "done" means.&lt;/p&gt;

&lt;p&gt;I wrote mine into the file my agents load every session. The honest cost: it is prose, not a lint. The mechanical version is a grep for names and for "used to" over the changed lines, and I have not wired it into continuous integration yet, so for now this holds because I check, which is not a guarantee I would accept from anybody else.&lt;/p&gt;

&lt;p&gt;The model was not hiding anything. It answered the question the first time, in plain words. Nobody had specified the reader.&lt;/p&gt;

&lt;p&gt;Go and grep your own name in your own repository. Then tell me what else you never wrote down.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://juliantellez.com/blog/the-comments-are-not-for-you" rel="noopener noreferrer"&gt;juliantellez.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building with AI and want it to hold up in production?&lt;/strong&gt; Join &lt;a href="https://www.skool.com/vibe-coding-to-production-3790" rel="noopener noreferrer"&gt;Vibe Coding to Production&lt;/a&gt;, a free community where I share the spec-driven workflow I use with Claude Code and Cursor, plus free courses.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>codequality</category>
      <category>agents</category>
    </item>
    <item>
      <title>Agentic Harness: What It Costs to Build One</title>
      <dc:creator>Julian Tellez</dc:creator>
      <pubDate>Fri, 23 Oct 2026 21:54:25 +0000</pubDate>
      <link>https://dev.to/juliantellez/agentic-harness-what-it-costs-to-build-one-5g82</link>
      <guid>https://dev.to/juliantellez/agentic-harness-what-it-costs-to-build-one-5g82</guid>
      <description>&lt;p&gt;&lt;a href="https://juliantellez.com/blog/why-an-agent-needs-a-harness" rel="noopener noreferrer"&gt;Why an agent needs a harness&lt;/a&gt; ended with a few things I want from any harness:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Real isolation.&lt;/li&gt;
&lt;li&gt;A visible difference between done and gave up.&lt;/li&gt;
&lt;li&gt;Permissions built for nobody watching.&lt;/li&gt;
&lt;li&gt;A transcript that survives the run.&lt;/li&gt;
&lt;li&gt;Room to run more than one job at once.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Real isolation
&lt;/h2&gt;

&lt;p&gt;The wall is the cheap part. Starting a container per task is an afternoon.&lt;/p&gt;

&lt;p&gt;What costs is what the wall does to everything around it. Once the work happens inside a box you are not sitting in, the job cannot be the terminal any more. It has to outlive the terminal that declared it, which means the job is a record somewhere rather than a process on your laptop, and something has to write that record, start it, notice when it ended, and keep what it produced. The moment you can close the lid and walk away, you own a life cycle you did not own before.&lt;/p&gt;

&lt;p&gt;Then there is the second wall, the one inside. A container decides where the work runs. It says nothing about what the worker is allowed to do. That is a separate thing to model, and the useful shape is a role: which model runs this job, what it is allowed to read, and which verbs it holds. Verbs are where it earns its keep. A role that ships work cannot declare work. A role that coordinates does not hold the editing verbs.&lt;/p&gt;

&lt;p&gt;An agent that can decide what to do, do it, and then declare it done has no boundary inside it, however good the box around it is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isolation is a role, not just a box&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgSm9iWyJBIGpvYiB0aGF0IG91dGxpdmVzIHlvdXIgdGVybWluYWwiXSAtLT4gUm9sZVsiUm9sZSJdCiAgUm9sZSAtLT4gTW9kZWxbIldoaWNoIG1vZGVsIHJ1bnMgaXQiXQogIFJvbGUgLS0%2BIFJlYWRbIldoYXQgaXQgaXMgYWxsb3dlZCB0byByZWFkIl0KICBSb2xlIC0tPiBWZXJic1siV2hpY2ggdmVyYnMgaXQgaG9sZHMiXQogIFZlcmJzIC0tPiBTcGxpdFsiRGVjbGFyaW5nIHdvcmsgYW5kIHNoaXBwaW5nIHdvcmsgYXJlIGRpZmZlcmVudCByb2xlcyJd" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgSm9iWyJBIGpvYiB0aGF0IG91dGxpdmVzIHlvdXIgdGVybWluYWwiXSAtLT4gUm9sZVsiUm9sZSJdCiAgUm9sZSAtLT4gTW9kZWxbIldoaWNoIG1vZGVsIHJ1bnMgaXQiXQogIFJvbGUgLS0%2BIFJlYWRbIldoYXQgaXQgaXMgYWxsb3dlZCB0byByZWFkIl0KICBSb2xlIC0tPiBWZXJic1siV2hpY2ggdmVyYnMgaXQgaG9sZHMiXQogIFZlcmJzIC0tPiBTcGxpdFsiRGVjbGFyaW5nIHdvcmsgYW5kIHNoaXBwaW5nIHdvcmsgYXJlIGRpZmZlcmVudCByb2xlcyJd" alt="Diagram" width="1018" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The box decides where the work runs. The role decides what the worker is allowed to do.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cost:&lt;/strong&gt; a job record with a life cycle, and a verb list written down before the first run. The test is the one from part one. Name a job and say precisely what it can and cannot touch. If the answer is a paragraph rather than a list, that is not isolation.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A visible difference between done and gave up
&lt;/h2&gt;

&lt;p&gt;A model's natural output is prose, so a harness that does nothing in particular gets prose. "I have updated the handler and it should now work" is not an outcome. It is an essay about one, and it hands the decision to whoever reads it, which is the job you were trying to give away.&lt;/p&gt;

&lt;p&gt;The fix is unglamorous and it is not the same thing as asking for a better summary. First enumerate the outcomes a job may end in and then match the ending against that set exactly. Anything matching nothing in the set is a failure, not free text to be interpreted later. And "gave up" has to be one of the outcomes, with a reason attached.&lt;/p&gt;

&lt;p&gt;That gets you an honest report of the run. It still does not tell you the work exists. A green check is a claim, and the claim is only ever about the steps. I have watched a pipeline run every step it was given, report success, and ship nothing at all, because the identity it assumes could not create the thing it was asked to create. Nothing threw. Nothing arrived.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two questions, not one&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgRW5kWyJUaGUgcnVuIGVuZHMiXSAtLT4gU2hhcGV7IkRvZXMgaXQgbWF0Y2ggYSBrbm93biBvdXRjb21lPyJ9CiAgU2hhcGUgLS0%2BfCJubywgaXQgaXMgcHJvc2UifCBSZWFkZXJbIlNvbWVib2R5IGhhcyB0byByZWFkIGl0IGFuZCBkZWNpZGUiXQogIFNoYXBlIC0tPnwieWVzInwgV2hpY2h7IldoaWNoIG91dGNvbWU%2FIn0KICBXaGljaCAtLT58ImdhdmUgdXAsIHdpdGggYSByZWFzb24ifCBQZXJzb25bIlJvdXRlZCB0byBhIHBlcnNvbiJdCiAgV2hpY2ggLS0%2BfCJkb25lInwgV29ybGR7IkRvZXMgdGhlIHRoaW5nIGl0IG1hZGUgZXhpc3Q%2FIn0KICBXb3JsZCAtLT58Im5vInwgUGVyc29uCiAgV29ybGQgLS0%2BfCJ5ZXMifCBEb25lWyJEb25lIl0%3D" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgRW5kWyJUaGUgcnVuIGVuZHMiXSAtLT4gU2hhcGV7IkRvZXMgaXQgbWF0Y2ggYSBrbm93biBvdXRjb21lPyJ9CiAgU2hhcGUgLS0%2BfCJubywgaXQgaXMgcHJvc2UifCBSZWFkZXJbIlNvbWVib2R5IGhhcyB0byByZWFkIGl0IGFuZCBkZWNpZGUiXQogIFNoYXBlIC0tPnwieWVzInwgV2hpY2h7IldoaWNoIG91dGNvbWU%2FIn0KICBXaGljaCAtLT58ImdhdmUgdXAsIHdpdGggYSByZWFzb24ifCBQZXJzb25bIlJvdXRlZCB0byBhIHBlcnNvbiJdCiAgV2hpY2ggLS0%2BfCJkb25lInwgV29ybGR7IkRvZXMgdGhlIHRoaW5nIGl0IG1hZGUgZXhpc3Q%2FIn0KICBXb3JsZCAtLT58Im5vInwgUGVyc29uCiAgV29ybGQgLS0%2BfCJ5ZXMifCBEb25lWyJEb25lIl0%3D" alt="Diagram" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ask the session whether the outcome is there. Do not ask the run whether it finished.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cost:&lt;/strong&gt; a closed set of endings the harness enforces, and a check at the end of each job that asks whether the work exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Permissions built for nobody watching
&lt;/h2&gt;

&lt;p&gt;When a person is at the keyboard, permission is a question asked at the exact moment it matters, by something that knows precisely what is about to happen. Take the person away and that question has no answer. The session does not fail, which would be fine and expected. Instead it just waits.&lt;/p&gt;

&lt;p&gt;There are two ways to be wrong about this step. Guess too broad and you have quietly handed back the isolation you paid for in the first section. Guess too narrow and the run stops, or worse, carries on and delivers nothing, which is the pipeline again: a grant made in advance, too small, and not one part of the system able to say so out loud.&lt;/p&gt;

&lt;p&gt;Roles are the cheapest place I have found to put this guess, because a grant attached to a role is made once for a kind of work rather than once per run, and somebody can read the list and disagree with it. It is still a guess. It is just a reviewable one, and a narrow guess is only safe if the previous section is already built, so that refusal comes back as an outcome you can see rather than as an empty result.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. A transcript that survives the run
&lt;/h2&gt;

&lt;p&gt;There is a difference worth being pedantic about. What a run says about itself is testimony. What the run actually did, the commands, the outputs, the diffs, the refusals, is evidence. You want the evidence, so the process can be scrutinised and challenged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cost:&lt;/strong&gt; isolation says the box is disposable and should be thrown away the moment the task ends. Evidence says nothing readable inside that box may be lost. So you pay for the wall, and then you pay a second time to lift everything worth reading back over it before it goes.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Room to run more than one job at once
&lt;/h2&gt;

&lt;p&gt;Running many jobs at once is not just parallelising the flow described up to here. It means creating admissions, claims and guard checks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Admissions:&lt;/strong&gt; something has to decide whether a job starts now, because capacity is finite: model quota, containers, machines, money. With no admission decision the answer is that everything starts at once, and everything starting at once behaves remarkably like nothing starting at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claims:&lt;/strong&gt; two workers must not build the same thing, so a piece of work has to be claimed before it is started, the claim has to be visible to every other worker, and it has to be released when the work ends or expire on its own if the worker disappears. Get this wrong and the second worker's output is not merely wasted. It conflicts with the first, and now somebody is reconciling two attempts at one job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Guard checks:&lt;/strong&gt; something watching if the system has stopped moving, checking nothing crashes when work is added or stops flowing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What running many at once actually needs&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgUXVldWVbIldvcmsgd2FpdGluZyJdIC0tPiBBZG1pdHsiUm9vbSB0byBzdGFydCBvbmUgbm93PyJ9CiAgQWRtaXQgLS0%2BfCJubywgYXQgY2FwYWNpdHkifCBRdWV1ZQogIEFkbWl0IC0tPnwieWVzInwgQ2xhaW1bIkNsYWltZWQgYnkgZXhhY3RseSBvbmUgd29ya2VyIl0KICBDbGFpbSAtLT4gUnVuWyJSdW5uaW5nIGluIGl0cyBvd24gYm94Il0KICBSdW4gLS0%2BfCJlbmRzLCBvciB0aGUgY2xhaW0gZXhwaXJlcyJ8IFF1ZXVlCiAgU3RhbGxbIldvcmsgd2FpdGluZyBhbmQgbm90aGluZyBydW5uaW5nPyJdIC0tPnwiYXNrZWQgb24gYSBzY2hlZHVsZSJ8IEFsYXJtWyJXYWtlIHNvbWVib2R5Il0%3D" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgUXVldWVbIldvcmsgd2FpdGluZyJdIC0tPiBBZG1pdHsiUm9vbSB0byBzdGFydCBvbmUgbm93PyJ9CiAgQWRtaXQgLS0%2BfCJubywgYXQgY2FwYWNpdHkifCBRdWV1ZQogIEFkbWl0IC0tPnwieWVzInwgQ2xhaW1bIkNsYWltZWQgYnkgZXhhY3RseSBvbmUgd29ya2VyIl0KICBDbGFpbSAtLT4gUnVuWyJSdW5uaW5nIGluIGl0cyBvd24gYm94Il0KICBSdW4gLS0%2BfCJlbmRzLCBvciB0aGUgY2xhaW0gZXhwaXJlcyJ8IFF1ZXVlCiAgU3RhbGxbIldvcmsgd2FpdGluZyBhbmQgbm90aGluZyBydW5uaW5nPyJdIC0tPnwiYXNrZWQgb24gYSBzY2hlZHVsZSJ8IEFsYXJtWyJXYWtlIHNvbWVib2R5Il0%3D" alt="Diagram" width="1460" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nothing throws an error when the queue stops draining. You have to go and ask.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Guard checks is the cheapest thing on this entire list and the easiest to skip. Work waiting and nothing running is one query away, it needs no new component. Write the query, run it on a schedule, treat the answer as an alarm.&lt;/p&gt;

&lt;p&gt;Parallel work is also where the harness starts carrying weight. With one run, watched, you can read the transcript yourself and tell if work has been done by looking at it. With several, unwatched jobs, judgement can drift and the harness can become the bottleneck if it is not set up properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I have not solved
&lt;/h2&gt;

&lt;p&gt;The initial refinement: how can we tell if the system understands contextually what we have in mind? This is a solved problem for narrow scope and small tasks, but when the work becomes broader, quality takes a hit and the jobs start to drift. My next attempt would be to introduce cadence and work review in agile fashion, so the system is always honest and actual value is delivered and measured.&lt;/p&gt;

&lt;p&gt;This is the second post in what I want to make a short series on building an agentic harness. Let me know if you have any more features that you think would be beneficial in a harness. Happy coding.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://juliantellez.com/blog/what-a-harness-costs-to-build" rel="noopener noreferrer"&gt;juliantellez.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building with AI and want it to hold up in production?&lt;/strong&gt; Join &lt;a href="https://www.skool.com/vibe-coding-to-production-3790" rel="noopener noreferrer"&gt;Vibe Coding to Production&lt;/a&gt;, a free community where I share the spec-driven workflow I use with Claude Code and Cursor, plus free courses.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>infrastructure</category>
      <category>architecture</category>
      <category>ai</category>
    </item>
    <item>
      <title>Agentic Harness: Why an Agent Needs a Harness</title>
      <dc:creator>Julian Tellez</dc:creator>
      <pubDate>Fri, 23 Oct 2026 21:53:56 +0000</pubDate>
      <link>https://dev.to/juliantellez/agentic-harness-why-an-agent-needs-a-harness-19g</link>
      <guid>https://dev.to/juliantellez/agentic-harness-why-an-agent-needs-a-harness-19g</guid>
      <description>&lt;p&gt;A model that can write anything still cannot open a file, run a command, or know when to stop pretending it did. This is the first post in a series on what actually turns a language model into something you can safely put to work.&lt;/p&gt;

&lt;p&gt;I once asked a model to fix a failing test, expecting code back. What came back instead was a paragraph explaining, correctly, what was wrong. Nothing else happened. The bug was still there. The model thought it had done its job. At this point in time nobody had built the part that takes a correct paragraph and turns it into a saved file, a passing test, a done thing, a valuable output.&lt;/p&gt;

&lt;p&gt;That gap has a name now. People call it an agentic harness: whatever sits between a model and the actual world, turning what the model says into things that happen, and reporting back what happened so the model can decide what to say next.&lt;/p&gt;

&lt;p&gt;A language model on its own is a very good guesser of the next right word. It has no hands. It cannot open a file unless something opens the file for it, run a command unless something runs the command, or remember what it did five minutes ago unless something wrote that down and hands it back. Everything that makes an agent look like it is doing work, rather than describing work, is the harness. Not the model.&lt;/p&gt;

&lt;p&gt;This has only become a real design problem recently. A model that just answers questions does not need much of a harness: a text box and a network connection will do. A model asked to write code, run it, read the failure, and try again needs somewhere to write the code, something to run it, a way to read the failure back, and a decision about how many tries it gets before a person is called in. Multiply that by more than one task running at once, or a task running while nobody is watching, and the harness stops being plumbing. It becomes the product.&lt;/p&gt;

&lt;p&gt;There is not one shape this takes. So far there are at least five patterns at this point in time, and each is a different bet about who is watching and how much can go wrong before someone notices.&lt;/p&gt;

&lt;p&gt;The simplest is the one most people already have: a terminal, an editor open beside it, an agent that reads and writes files and runs commands with your own permissions. It is the fastest thing to build and the fastest thing to use, because nothing stands between the model deciding to do something and the something happening. That speed is also the whole risk. The agent can do anything you can do, including the things you did not mean to ask for, and there is no wall between one task and the next. A mistake in one session has a blast radius in your actual home directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local process&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgc3ViZ3JhcGggbWFjaGluZVsiWW91ciBtYWNoaW5lLCBvbmUgc2hhcmVkIGVudmlyb25tZW50Il0KICAgIEFnZW50WyJBZ2VudCJdCiAgICBGaWxlc1siWW91ciBmaWxlcyJdCiAgICBTaGVsbFsiWW91ciBzaGVsbCJdCiAgZW5kCiAgWW91WyJZb3UiXSAtLT58InByb21wdHMifCBBZ2VudAogIEFnZW50IC0tPnwicmVhZHMsIHdyaXRlcyJ8IEZpbGVzCiAgQWdlbnQgLS0%2BfCJydW5zIGNvbW1hbmRzIGFzIHlvdSJ8IFNoZWxs" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgc3ViZ3JhcGggbWFjaGluZVsiWW91ciBtYWNoaW5lLCBvbmUgc2hhcmVkIGVudmlyb25tZW50Il0KICAgIEFnZW50WyJBZ2VudCJdCiAgICBGaWxlc1siWW91ciBmaWxlcyJdCiAgICBTaGVsbFsiWW91ciBzaGVsbCJdCiAgZW5kCiAgWW91WyJZb3UiXSAtLT58InByb21wdHMifCBBZ2VudAogIEFnZW50IC0tPnwicmVhZHMsIHdyaXRlcyJ8IEZpbGVzCiAgQWdlbnQgLS0%2BfCJydW5zIGNvbW1hbmRzIGFzIHlvdSJ8IFNoZWxs" alt="Diagram" width="708" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fast because nothing stands in the way. Risky for the same reason.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Put a wall up and you get the next shape: each task, or each session, gets its own container or virtual machine, thrown away when the task ends. A mistake stays inside the box it happened in. You can run many of these at once, including ones nobody is watching in real time, because the damage any single one can do is small on purpose. The cost is that somebody has to build and run the wall. A fresh environment takes time the local version never spends. Credentials have to be handed into a place you cannot see directly. And the box needs its own way of telling you what happened inside it, because you are no longer sitting next to it while it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sandboxed containers&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgWW91WyJZb3UiXSAtLT4gSGFybmVzc1siSGFybmVzcyJdCiAgSGFybmVzcyAtLT4gQm94MVsiQ29udGFpbmVyOiB0YXNrIG9uZSJdCiAgSGFybmVzcyAtLT4gQm94MlsiQ29udGFpbmVyOiB0YXNrIHR3byJdCiAgQm94MSAtLT58InRocm93biBhd2F5IHdoZW4gaXQgZW5kcyJ8IEdvbmUxWyJHb25lIl0KICBCb3gyIC0tPnwidGhyb3duIGF3YXkgd2hlbiBpdCBlbmRzInwgR29uZTJbIkdvbmUiXQ%3D%3D" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgWW91WyJZb3UiXSAtLT4gSGFybmVzc1siSGFybmVzcyJdCiAgSGFybmVzcyAtLT4gQm94MVsiQ29udGFpbmVyOiB0YXNrIG9uZSJdCiAgSGFybmVzcyAtLT4gQm94MlsiQ29udGFpbmVyOiB0YXNrIHR3byJdCiAgQm94MSAtLT58InRocm93biBhd2F5IHdoZW4gaXQgZW5kcyJ8IEdvbmUxWyJHb25lIl0KICBCb3gyIC0tPnwidGhyb3duIGF3YXkgd2hlbiBpdCBlbmRzInwgR29uZTJbIkdvbmUiXQ%3D%3D" alt="Diagram" width="855" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A mistake stays inside the box it happened in.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A third shape hands the wall to somebody else entirely: a managed platform that runs the sandbox, the model calls, and the wiring between them, and gives you an interface to start a task and collect a result. You stop operating infrastructure, which is real time back. You also stop being able to see very much of what happened in between, which matters the first time a result comes back wrong and you want to know why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Managed platform&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgWW91WyJZb3UiXSAtLT58InN0YXJ0IGEgdGFzayJ8IEFQSVsiUGxhdGZvcm0gaW50ZXJmYWNlIl0KICBzdWJncmFwaCBvcGFxdWVbIlJ1biBieSB0aGUgcGxhdGZvcm0sIG5vdCB2aXNpYmxlIHRvIHlvdSJdCiAgICBTYW5kYm94WyJTYW5kYm94Il0KICAgIENhbGxzWyJNb2RlbCBjYWxscyJdCiAgICBTYW5kYm94IC0tPiBDYWxscyAtLT4gU2FuZGJveAogIGVuZAogIEFQSSAtLT4gb3BhcXVlCiAgb3BhcXVlIC0tPnwicmVzdWx0IG9ubHkifCBZb3U%3D" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgWW91WyJZb3UiXSAtLT58InN0YXJ0IGEgdGFzayJ8IEFQSVsiUGxhdGZvcm0gaW50ZXJmYWNlIl0KICBzdWJncmFwaCBvcGFxdWVbIlJ1biBieSB0aGUgcGxhdGZvcm0sIG5vdCB2aXNpYmxlIHRvIHlvdSJdCiAgICBTYW5kYm94WyJTYW5kYm94Il0KICAgIENhbGxzWyJNb2RlbCBjYWxscyJdCiAgICBTYW5kYm94IC0tPiBDYWxscyAtLT4gU2FuZGJveAogIGVuZAogIEFQSSAtLT4gb3BhcXVlCiAgb3BhcXVlIC0tPnwicmVzdWx0IG9ubHkifCBZb3U%3D" alt="Diagram" width="815" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You get a result back. You do not get to see how it got there.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A fourth shape is declarative: a graph of steps, some of them a model call and some of them a tool call, wired together ahead of time so the same automation runs the same way every time it fires. This is the shape that scales best for something you want running on a schedule or in response to an event, because nobody has to sit and prompt it each time. It is also the shape most likely to mark a step successful because nothing threw an error, not because anything was actually achieved, unless somebody deliberately built a check that looks past the model's own account of how it went.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow graph&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgVHJpZ2dlclsiU2NoZWR1bGUgb3IgZXZlbnQiXSAtLT4gU3RlcDFbIlN0ZXA6IG1vZGVsIGNhbGwiXQogIFN0ZXAxIC0tPiBTdGVwMlsiU3RlcDogdG9vbCBjYWxsIl0KICBTdGVwMiAtLT4gQ2hlY2t7IkRpZCBpdCB0aHJvdyBhbiBlcnJvcj8ifQogIENoZWNrIC0tPnwibm8ifCBEb25lWyJNYXJrZWQgZG9uZSJdCiAgQ2hlY2sgLS0%2BfCJ5ZXMifCBGbGFnWyJGbGFnZ2VkIGZvciBhIHBlcnNvbiJd" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgVHJpZ2dlclsiU2NoZWR1bGUgb3IgZXZlbnQiXSAtLT4gU3RlcDFbIlN0ZXA6IG1vZGVsIGNhbGwiXQogIFN0ZXAxIC0tPiBTdGVwMlsiU3RlcDogdG9vbCBjYWxsIl0KICBTdGVwMiAtLT4gQ2hlY2t7IkRpZCBpdCB0aHJvdyBhbiBlcnJvcj8ifQogIENoZWNrIC0tPnwibm8ifCBEb25lWyJNYXJrZWQgZG9uZSJdCiAgQ2hlY2sgLS0%2BfCJ5ZXMifCBGbGFnWyJGbGFnZ2VkIGZvciBhIHBlcnNvbiJd" alt="Diagram" width="1171" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nothing threw an error is not the same as something got done.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A fifth shape lives inside the tool you already write code in, a panel next to the file you are editing, one person and one task at a time. Nothing beats it for the tight loop of asking, watching, correcting. It was never built for the version of this where the task runs after you have gone home.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Editor embedded&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgWW91WyJZb3UsIHdhdGNoaW5nIl0gPC0tPiBQYW5lbFsiQWdlbnQgcGFuZWwiXQogIFBhbmVsIDwtLT4gRmlsZVsiVGhlIGZpbGUgb3BlbiBiZXNpZGUgaXQiXQ%3D%3D" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgWW91WyJZb3UsIHdhdGNoaW5nIl0gPC0tPiBQYW5lbFsiQWdlbnQgcGFuZWwiXQogIFBhbmVsIDwtLT4gRmlsZVsiVGhlIGZpbGUgb3BlbiBiZXNpZGUgaXQiXQ%3D%3D" alt="Diagram" width="637" height="70"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built for someone watching. Not built for after you have gone home.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;None of the five are wrong. Each is a reasonable answer to a different question about who is around when something breaks. What I want out of any of them, after watching each fail in its own particular way, is a shorter list than you would think.&lt;/p&gt;

&lt;p&gt;Real isolation, first. A mistake in one task should not be able to reach another task, or reach you. If a harness cannot say precisely what a given task is unable to touch, it does not have isolation. It has hope.&lt;/p&gt;

&lt;p&gt;A visible difference between done and gave up, second, and this is the one I would not trade for any of the others.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The most dangerous failure is not a crash. It is a run that finishes clean and did nothing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A model would rather answer than admit it cannot see what it needs to see, and a harness that lets a plausible non answer read as success is worse than one that has no safety features at all, because it hides exactly the runs that needed a person to look.&lt;/p&gt;

&lt;p&gt;Permissions built for nobody watching, third. Anything that only works when a person is at the keyboard to click approve will eventually run unattended and fail there, silently, by design. A harness meant for background work needs a way to say yes in advance, scoped tightly, rather than a wall only a human hand can get past.&lt;/p&gt;

&lt;p&gt;Credentials that reach the sandbox, not just the settings screen, fourth. Something that shows as set in a list but never actually arrives where the work happens is worse than an honest error, because it looks like it should have worked.&lt;/p&gt;

&lt;p&gt;A transcript that survives the run, fifth. Whatever the model actually said and did needs to stay readable after the task finishes, not filed somewhere only a direct query against a database can reach. The summary is not the evidence. The transcript is.&lt;/p&gt;

&lt;p&gt;And room to run more than one thing at once without losing any of the above, last. The entire point of handing work to an agent is not doing it yourself while it runs. A harness that only works one task at a time, watched, has not saved anyone anything.&lt;/p&gt;

&lt;p&gt;This is the first post in what I want to make a short series on building an agentic harness. Let me know if you have any more features that you think would be beneficial in a harness. Happy coding.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://juliantellez.com/blog/why-an-agent-needs-a-harness" rel="noopener noreferrer"&gt;juliantellez.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building with AI and want it to hold up in production?&lt;/strong&gt; Join &lt;a href="https://www.skool.com/vibe-coding-to-production-3790" rel="noopener noreferrer"&gt;Vibe Coding to Production&lt;/a&gt;, a free community where I share the spec-driven workflow I use with Claude Code and Cursor, plus free courses.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>infrastructure</category>
      <category>architecture</category>
      <category>ai</category>
    </item>
    <item>
      <title>Agentic Harness: What Spec Driven Development Actually Is</title>
      <dc:creator>Julian Tellez</dc:creator>
      <pubDate>Fri, 23 Oct 2026 21:52:54 +0000</pubDate>
      <link>https://dev.to/juliantellez/agentic-harness-what-spec-driven-development-actually-is-1l8p</link>
      <guid>https://dev.to/juliantellez/agentic-harness-what-spec-driven-development-actually-is-1l8p</guid>
      <description>&lt;p&gt;At the AI Engineer World's Fair in 2025, Sean Grove from OpenAI described how most of us work with coding agents: "We keep the generated code, and we delete the prompt." He compared it to shredding the source code and version controlling the binary.&lt;/p&gt;

&lt;p&gt;A harness can check a great deal about an agent's output: whether it stayed in its box, whether it finished, what it did. None of that tells you whether the agent understood what was asked. When the work is small, understanding is cheap to confirm by reading the result. When the work gets broad, the jobs drift, and every check passes on the wrong thing.&lt;/p&gt;

&lt;p&gt;Spec driven development is the industry's answer to that problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;Spec driven development means you write down what you want before the agent writes any code, and that document becomes the source of truth for both of you. The agent plans from it, breaks it into tasks from it, and is checked against it.&lt;/p&gt;

&lt;p&gt;The definition is still moving. Thoughtworks put it on their Technology Radar in November 2025 in the Assess ring and said plainly that "the term's definition is still evolving". Birgitta Böckeler, a distinguished engineer at Thoughtworks, wrote the most useful map of it so far on Martin Fowler's site, and she splits it into three levels:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Spec first.&lt;/strong&gt; You write a careful spec, the agent builds from it, and the spec is done with when the task is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spec anchored.&lt;/strong&gt; The spec is kept after the task and evolved alongside the feature, so the next change starts from it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spec as source.&lt;/strong&gt; The spec is the thing you maintain. Humans edit only the spec, and the code is generated from it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Almost every tool today does the first. Few commit to the second. Only one has seriously tried the third.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three levels of commitment&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgRmlyc3RbIlNwZWMgZmlyc3Q6IHdyaXR0ZW4gZm9yIG9uZSB0YXNrLCB0aGVuIGRpc2NhcmRlZCJdIC0tPiBBbmNob3JlZFsiU3BlYyBhbmNob3JlZDoga2VwdCBhbmQgZXZvbHZlZCB3aXRoIHRoZSBmZWF0dXJlIl0KICBBbmNob3JlZCAtLT4gU291cmNlWyJTcGVjIGFzIHNvdXJjZTogdGhlIG9ubHkgdGhpbmcgYSBodW1hbiBlZGl0cyJd" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgRmlyc3RbIlNwZWMgZmlyc3Q6IHdyaXR0ZW4gZm9yIG9uZSB0YXNrLCB0aGVuIGRpc2NhcmRlZCJdIC0tPiBBbmNob3JlZFsiU3BlYyBhbmNob3JlZDoga2VwdCBhbmQgZXZvbHZlZCB3aXRoIHRoZSBmZWF0dXJlIl0KICBBbmNob3JlZCAtLT4gU291cmNlWyJTcGVjIGFzIHNvdXJjZTogdGhlIG9ubHkgdGhpbmcgYSBodW1hbiBlZGl0cyJd" alt="Diagram" width="896" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Each level asks you to trust the spec more and the code less.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it is needed
&lt;/h2&gt;

&lt;p&gt;Agents are good at writing code and bad at guessing intent. GitHub's announcement of Spec Kit says this directly: the problem is not the agent's coding ability, it is the approach. We treat agents like search engines when they behave like "literal minded pair programmers". Give one an ambiguous sentence and it will pick an interpretation, build it well, and explain convincingly why it is right.&lt;/p&gt;

&lt;p&gt;Vibe coding works for a prototype. It fails on anything that has to live in an existing codebase, match an existing architecture, or still make sense in six months. The prompt that carried the intent is gone, the code is all that is left, and code is a lossy copy of intent. It tells you what the system does. It rarely tells you why, or what it was never supposed to do.&lt;/p&gt;

&lt;p&gt;A spec is the attempt to keep the intent. Written down, reviewed by a person before any code exists, and kept somewhere the next agent can read it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it comes from
&lt;/h2&gt;

&lt;p&gt;None of this is new. What is new is who reads the spec.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Design by contract&lt;/strong&gt;, from Bertrand Meyer and the Eiffel language in the 1980s. Preconditions, postconditions and invariants written next to the code, checked at run time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model driven architecture&lt;/strong&gt;, from the Object Management Group in 2001. Draw a precise model, generate the code from it. It promised exactly what spec as source promises today, and it mostly did not stick, because the models were rigid and the generated code was painful to live with.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behaviour driven development&lt;/strong&gt;, from Dan North in 2006. Scenarios written as "given, when, then" in plain language that a test runner can execute. Most spec tools today write their acceptance criteria in this shape.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Easy Approach to Requirements Syntax&lt;/strong&gt;, usually called EARS, from Alistair Mavin and colleagues at Rolls-Royce in 2009. They built it while analysing airworthiness rules for a jet engine control system: a handful of sentence templates that remove most of the ambiguity from a requirement. Kiro uses it today.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two EARS requirements, written for this post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WHEN a user submits the signup form with an email that is already registered,
THE SYSTEM SHALL reject the request and show "this email already has an account".

IF the email service does not respond within 5 seconds,
THEN THE SYSTEM SHALL queue the welcome email and complete the signup.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each line is one trigger and one behaviour, and each one is a test waiting to be written.&lt;/p&gt;

&lt;p&gt;The difference this time is that the reader of the spec is a model. Model driven architecture needed a strict, parseable model because the generator was a compiler. An agent reads plain language, which removes the rigidity. It also brings back the uncertainty, because the same spec can produce different code on two runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is proposing it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;, through Spec Kit, announced by Den Delimarsky in September 2025.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Web Services&lt;/strong&gt;, through Kiro, an editor built around specs that launched in July 2025.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI&lt;/strong&gt;, less as a product and more as a position. Grove's talk argued that "the new scarce skill is writing specifications that fully capture the intent and values", and pointed at OpenAI's own Model Spec, a versioned set of markdown files where every clause has an id and a set of prompts that act as its tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tessl&lt;/strong&gt;, founded by Guy Podjarny, which made the boldest bet of all: specs, not code, as the primary artifact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The open source community&lt;/strong&gt;, through OpenSpec and the BMAD Method, which between them have over a hundred thousand stars on GitHub.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And on the sceptical side, the same people who mapped it. Thoughtworks and Böckeler are the clearest critics, covered further down.&lt;/p&gt;

&lt;h2&gt;
  
  
  How people use it
&lt;/h2&gt;

&lt;p&gt;Under the different names, almost every tool runs the same loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The loop most spec tools share&lt;/strong&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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgUnVsZXNbIlByb2plY3QgcnVsZXM6IHRoZSBjb25zdGl0dXRpb24iXSAtLT4gU3BlY1siU3BlYzogd2hhdCBhbmQgd2h5Il0KICBTcGVjIC0tPiBSZXZpZXcxeyJBIHBlcnNvbiBhcHByb3ZlcyBpdD8ifQogIFJldmlldzEgLS0%2BfCJubyJ8IFNwZWMKICBSZXZpZXcxIC0tPnwieWVzInwgUGxhblsiUGxhbjogc3RhY2ssIGRlc2lnbiwgY29uc3RyYWludHMiXQogIFBsYW4gLS0%2BIFRhc2tzWyJUYXNrczogc21hbGwsIG9yZGVyZWQsIHRlc3RhYmxlIl0KICBUYXNrcyAtLT4gQnVpbGRbIkFnZW50IGJ1aWxkcyBvbmUgdGFzayJdCiAgQnVpbGQgLS0%2BIENoZWNreyJNYXRjaGVzIHRoZSBzcGVjPyJ9CiAgQ2hlY2sgLS0%2BfCJubyJ8IEJ1aWxkCiAgQ2hlY2sgLS0%2BfCJ5ZXMifCBOZXh0WyJOZXh0IHRhc2siXQ%3D%3D" 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%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IExSCiAgUnVsZXNbIlByb2plY3QgcnVsZXM6IHRoZSBjb25zdGl0dXRpb24iXSAtLT4gU3BlY1siU3BlYzogd2hhdCBhbmQgd2h5Il0KICBTcGVjIC0tPiBSZXZpZXcxeyJBIHBlcnNvbiBhcHByb3ZlcyBpdD8ifQogIFJldmlldzEgLS0%2BfCJubyJ8IFNwZWMKICBSZXZpZXcxIC0tPnwieWVzInwgUGxhblsiUGxhbjogc3RhY2ssIGRlc2lnbiwgY29uc3RyYWludHMiXQogIFBsYW4gLS0%2BIFRhc2tzWyJUYXNrczogc21hbGwsIG9yZGVyZWQsIHRlc3RhYmxlIl0KICBUYXNrcyAtLT4gQnVpbGRbIkFnZW50IGJ1aWxkcyBvbmUgdGFzayJdCiAgQnVpbGQgLS0%2BIENoZWNreyJNYXRjaGVzIHRoZSBzcGVjPyJ9CiAgQ2hlY2sgLS0%2BfCJubyJ8IEJ1aWxkCiAgQ2hlY2sgLS0%2BfCJ5ZXMifCBOZXh0WyJOZXh0IHRhc2siXQ%3D%3D" alt="Diagram" width="1904" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The approval happens on the spec, before any code exists.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set the rules once.&lt;/strong&gt; A file of things that are always true for the project: the language, the testing rules, what is never allowed. Spec Kit calls it a constitution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write the spec.&lt;/strong&gt; What you are building and why, as user stories with acceptance criteria. Usually the agent drafts it from a short description and you correct it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan.&lt;/strong&gt; You give the technical direction. The agent writes the design: data model, interfaces, how it fits what exists.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Break it into tasks.&lt;/strong&gt; Small, ordered, each one checkable on its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build one task at a time&lt;/strong&gt;, and review a small change rather than a large one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The review moves. Instead of reading a thousand lines of generated code and asking whether it is right, you read a page of requirements and ask whether it is what you meant. That is a cheaper question to answer, and a much cheaper one to get wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five approaches worth knowing
&lt;/h2&gt;

&lt;p&gt;Ranked by how much they are used and how often they appear in independent comparisons. Star counts were read on 22 October 2026.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Spec Kit, from GitHub
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;github.com/github/spec-kit&lt;/a&gt;, about 142,000 stars, MIT licensed.&lt;/p&gt;

&lt;p&gt;The reference implementation. A command line tool installs templates and slash commands into whatever agent you use: Copilot, Claude Code, Gemini and others. The flow is constitution, specify, plan, tasks, implement, with clarify and analyse steps between them to catch gaps and contradictions. It is the most thorough of the five and the heaviest. The project now describes its steps as "independent entry points, not mandatory phases", a softer position than its first release.&lt;/p&gt;

&lt;p&gt;Best for: new features of real size where you want a documented trail.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Kiro, from Amazon Web Services
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://kiro.dev" rel="noopener noreferrer"&gt;kiro.dev&lt;/a&gt;, an editor rather than a toolkit.&lt;/p&gt;

&lt;p&gt;Every spec is three files in &lt;code&gt;.kiro/specs/&lt;/code&gt;: &lt;code&gt;requirements.md&lt;/code&gt;, &lt;code&gt;design.md&lt;/code&gt; and &lt;code&gt;tasks.md&lt;/code&gt;. Requirements are written in EARS. When you run the tasks, Kiro builds a dependency graph and runs independent tasks in parallel waves. It has separate flows for features and for bug fixes, and a quick spec mode that skips the approval gates for work you already understand.&lt;/p&gt;

&lt;p&gt;Best for: teams happy to move into a new editor in exchange for the most integrated experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. OpenSpec
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Fission-AI/OpenSpec" rel="noopener noreferrer"&gt;github.com/Fission-AI/OpenSpec&lt;/a&gt;, about 72,700 stars, MIT licensed.&lt;/p&gt;

&lt;p&gt;Built around changes rather than whole systems. Each change gets a folder with a proposal, a design, a task list and spec deltas that describe what the change adds to the system. When the change ships, it is archived and its deltas are merged into the living specs in &lt;code&gt;openspec/specs/&lt;/code&gt;. That makes it the tool that comes closest to spec anchored without asking you to describe your entire system first. It claims support for more than thirty assistants.&lt;/p&gt;

&lt;p&gt;Best for: existing codebases, which is most codebases.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. BMAD Method
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/bmad-code-org/BMAD-METHOD" rel="noopener noreferrer"&gt;github.com/bmad-code-org/BMAD-METHOD&lt;/a&gt;, about 54,400 stars.&lt;/p&gt;

&lt;p&gt;The Breakthrough Method for Agile AI Driven Development. Where the others are workflows, BMAD is a team: separate agents carrying product, architecture, user experience, development and testing roles, each handing structured documents to the next. Small changes go straight to build. Larger ones go through the full planning cycle first.&lt;/p&gt;

&lt;p&gt;Best for: people who want the agile ceremony modelled explicitly, and are willing to pay for it in process.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Tessl
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://tessl.io" rel="noopener noreferrer"&gt;tessl.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The only serious attempt at spec as source. In its framework, each spec mapped to one code file, and the generated file carried a header saying "GENERATED FROM SPEC - DO NOT EDIT". Thoughtworks described it as the approach where "the specification itself becomes the maintained artifact, rather than the code". It was in private beta through 2025. Today the home page describes Tessl as "the agent enablement platform", built around reusable skills and context rather than specs as source. Tessl has not published a reason for the change, but the change itself is a data point about how hard the third level is.&lt;/p&gt;

&lt;p&gt;Best for: watching. It is where the idea goes if it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the critics say
&lt;/h2&gt;

&lt;p&gt;Böckeler tried the tools on real work.&lt;/p&gt;

&lt;p&gt;Kiro turned a small bug into four user stories with sixteen acceptance criteria. She called it "like using a sledgehammer to crack a nut". Spec Kit produced so many repetitive markdown files that she concluded "I'd rather review code than all these markdown files". Agents still ignored the spec in places, and in one run regenerated classes that the research step had already documented as existing. A detailed spec gave a feeling of control the agent did not honour.&lt;/p&gt;

&lt;p&gt;Thoughtworks went further and asked whether the field is relearning the bitter lesson: that handcrafting detailed rules for AI "ultimately doesn't scale". And Böckeler's sharpest point is the history one. Model driven development failed on rigidity. Language models remove the rigidity and add uncertainty. Spec as source risks getting both problems at once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A spec only helps if somebody reads it, and only protects you if something checks the code against it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most of the criticism is really about those two failures. Specs too long to review, and specs that nothing enforces.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with it right now
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use it for features, not for fixes.&lt;/strong&gt; A bug with a clear reproduction does not need a requirements document. A feature that touches three parts of the system does. If you cannot say what a spec would catch, skip it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the spec short enough to review in one sitting.&lt;/strong&gt; If you would not read it, neither will anyone else, and an unread spec is just a longer prompt. Böckeler's warning about "spec" becoming a synonym for "detailed prompt" is the real risk here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write every acceptance criterion so it can fail.&lt;/strong&gt; EARS or "given, when, then", it does not matter which. "The signup works" cannot fail. "When the email is already registered, the system rejects the request" can, and it is a test before it is code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make the spec executable.&lt;/strong&gt; The spec is a claim. The test is the evidence. Turn each criterion into a test before the implementation exists, and let the test runner decide, not the agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aim for spec anchored, not spec as source.&lt;/strong&gt; Keep the spec and update it with each change, the way OpenSpec does with its deltas. Do not try to stop editing code. Tessl's change of direction shows how hard that is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start with the lightest tool that fits.&lt;/strong&gt; For an existing codebase, OpenSpec. For a new product with real scope, Spec Kit. If you already live in an editor you like, a folder of markdown files and a clear habit get you most of the way.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The open problem is drift. A spec written today and code changed tomorrow will disagree soon enough. Some of these tools have verify or analyse steps, but a &lt;a href="https://arxiv.org/abs/2606.27045" rel="noopener noreferrer"&gt;June 2026 paper&lt;/a&gt; still names specs that silently fall out of sync with the code as a failure the existing approaches do not fully solve. Until something does, a spec can report success on work that no longer matches what anybody meant.&lt;/p&gt;

&lt;p&gt;This is the third post in a short series on building an agentic harness. If you are using any of these tools on real work, I would genuinely like to hear where they held up and where they did not. Happy coding.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Birgitta Böckeler, &lt;a href="https://www.martinfowler.com/articles/exploring-gen-ai/sdd-3-tools.html" rel="noopener noreferrer"&gt;Understanding Spec Driven Development: Kiro, spec-kit, and Tessl&lt;/a&gt;, martinfowler.com, 15 October 2025.&lt;/li&gt;
&lt;li&gt;Thoughtworks Technology Radar, &lt;a href="https://www.thoughtworks.com/radar/techniques/spec-driven-development" rel="noopener noreferrer"&gt;Spec driven development&lt;/a&gt;, November 2025.&lt;/li&gt;
&lt;li&gt;Den Delimarsky, &lt;a href="https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit/" rel="noopener noreferrer"&gt;Spec driven development with AI: get started with a new open source toolkit&lt;/a&gt;, GitHub Blog, 2 September 2025.&lt;/li&gt;
&lt;li&gt;Sean Grove, &lt;a href="https://ai.engineer/talks/specifications-are-the-new-code" rel="noopener noreferrer"&gt;The New Code&lt;/a&gt;, AI Engineer World's Fair 2025.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;GitHub Spec Kit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/docs/specs/" rel="noopener noreferrer"&gt;Kiro specs documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Fission-AI/OpenSpec" rel="noopener noreferrer"&gt;OpenSpec&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/bmad-code-org/BMAD-METHOD" rel="noopener noreferrer"&gt;BMAD Method&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tessl.io" rel="noopener noreferrer"&gt;Tessl&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Easy_Approach_to_Requirements_Syntax" rel="noopener noreferrer"&gt;Easy Approach to Requirements Syntax&lt;/a&gt;, Alistair Mavin and colleagues, IEEE Requirements Engineering Conference, 2009.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Join the community
&lt;/h2&gt;

&lt;p&gt;I run a free community for people moving from vibe coding to production: spec driven development with Claude Code, Cursor and agents, and the habits that make the output something you can ship. If this post was useful, the conversation carries on there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.skool.com/vibe-coding-to-production-3790" rel="noopener noreferrer"&gt;Join Vibe Coding to Production on Skool&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://juliantellez.com/blog/what-spec-driven-development-is" rel="noopener noreferrer"&gt;juliantellez.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building with AI and want it to hold up in production?&lt;/strong&gt; Join &lt;a href="https://www.skool.com/vibe-coding-to-production-3790" rel="noopener noreferrer"&gt;Vibe Coding to Production&lt;/a&gt;, a free community where I share the spec-driven workflow I use with Claude Code and Cursor, plus free courses.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>architecture</category>
      <category>ai</category>
      <category>specifications</category>
    </item>
    <item>
      <title>Handling complexity in lambda functions</title>
      <dc:creator>Julian Tellez</dc:creator>
      <pubDate>Sun, 10 Feb 2019 01:32:54 +0000</pubDate>
      <link>https://dev.to/juliantellez/handling-complexity-in-lambda-functions-28dj</link>
      <guid>https://dev.to/juliantellez/handling-complexity-in-lambda-functions-28dj</guid>
      <description>&lt;p&gt;See the original published version &lt;a href="https://medium.com/dazn-tech/handling-complexity-in-lambda-functions-e7acfbeb920a" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  TLDR;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Middlewares can handle the complexity of your lambdas while isolating business logic and cross-cutting concerns in reusable components that can be modelled by event cycles.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have had the luck and pleasure of working with lambda functions recently and boy I am having fun! The idea of having an event-driven execution environment is both daring and exciting.&lt;/p&gt;

&lt;p&gt;If you are new to the FaaS world, don't worry, the community has already prepared a curated list of reads for you &lt;a href="https://github.com/anaibol/awesome-serverless" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://github.com/pmuens/awesome-serverless" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Have a browse, drink some coffee.  ☕&lt;/p&gt;

&lt;p&gt;As you can see, (because you checked at least one of the links, didn't you?) A huge weight has been lifted. We can now develop, run and manage applications without the intricacy of building and maintaining infrastructure. But with new beginnings, new challenges arise. One of such problems and the reason for this blog is function complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  How complex is too complex?
&lt;/h2&gt;

&lt;p&gt;Generally speaking, when writing lambda functions you would organise them into a series of dedicated modules following the &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle" rel="noopener noreferrer"&gt;single responsibility principle&lt;/a&gt;. If you would rather do otherwise, please read this excellent blog comparing &lt;a href="https://hackernoon.com/aws-lambda-should-you-have-few-monolithic-functions-or-many-single-purposed-functions-8c3872d4338f" rel="noopener noreferrer"&gt;monolithic vs single purposed functions&lt;/a&gt;. Isolating application from business logic reduces code complexity, simplifies reasoning and will help you debug your code more efficiently. Your colleagues and your future self will thank you.&lt;/p&gt;

&lt;p&gt;Take for example some sort of CRUD API, we would like to make sure that a payload is properly formatted before handling any data. The payload validation could emit an error that would communicate its status to the consumer. If the validation was successful it would then move onto executing some business logic. For both scenarios, we would also want to set up some percentile tracing and error logging. While all of these sound great, we have essentially mapped out a request lifecycle with various &lt;a href="https://en.wikipedia.org/wiki/Cross-cutting_concern" rel="noopener noreferrer"&gt;cross-cutting concerns&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data validation.&lt;/li&gt;
&lt;li&gt;Error detection and correction.&lt;/li&gt;
&lt;li&gt;Logging.&lt;/li&gt;
&lt;li&gt;Monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AXT2_l9PLKtuZxKNGTYa4Uw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AXT2_l9PLKtuZxKNGTYa4Uw.gif"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;I know what you are thinking… (gif from giphy)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Following the serverless mantra, we should outsource anything that isn't related to the core business, so wouldn't it be great if we could just focus on the business logic and outsource these application-specific problems too? &lt;br&gt;
Of course, this isn't a new concept and we have been using it in web frameworks like &lt;a href="http://hapijs.com" rel="noopener noreferrer"&gt;hapijs&lt;/a&gt; and &lt;a href="https://expressjs.com" rel="noopener noreferrer"&gt;express&lt;/a&gt; for quite some time now.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lambda Middleware
&lt;/h2&gt;

&lt;p&gt;A lambda &lt;a href="https://en.wikipedia.org/wiki/Middleware" rel="noopener noreferrer"&gt;middleware&lt;/a&gt; is essentially a function that contributes to managing cross-cutting concerns in a consistent manner. It provides a clear separation of application and business logic and outlines an easy to reason configuration cycle. It is the glue that when adopted by everyone in a team becomes the lingua franca that supports and creates features. But do we really need a middleware? Well, look at the current state of your lambdas and ask yourself a few questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does the code look like?&lt;/li&gt;
&lt;li&gt;Can you envision anyone supporting it in at least 2 years?&lt;/li&gt;
&lt;li&gt;How much business logic expertise do you need? (if specialised then separation is imperative)&lt;/li&gt;
&lt;li&gt;Is logic intertwined and hard to reason about?&lt;/li&gt;
&lt;li&gt;Does the project have a clear path or do you see it going in different directions?&lt;/li&gt;
&lt;li&gt;How will the project look like the day the expert leaves?&lt;/li&gt;
&lt;li&gt;Are best-practices enforced and maintained?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1549761422481%2F5LOA6J7hr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1549761422481%2F5LOA6J7hr.gif"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Jack Nicholson approves. (gif from giphy)&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Enter Lambcycle
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/juliantellez/lambcycle" rel="noopener noreferrer"&gt;Lambcycle&lt;/a&gt; 🐑 🛵 is a declarative middleware for lambda functions. It defines a configurable event cycle and allows you to focus on your application's logic. It has a "Feature as Plugin" approach, so you can easily create your own plugins or reuse your favourite packages with very little effort.&lt;/p&gt;

&lt;p&gt;In practice there is no such thing as an un-opinionated framework, every idea is an opinion and a way of working with your application. Lambcycle favours configuration over the code and believes that business logic should be as isolated as possible. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A5I_ZBcvd03ktQpGXuA2kgQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A5I_ZBcvd03ktQpGXuA2kgQ.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Labmcycle flow chart.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lambcycle enhances lambda functions with a few extension points (see graph), each of which can be used to interact with the event in a decomposed manner.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The first extension point is &lt;code&gt;Request&lt;/code&gt; which occurs immediately after the lambda is called. You can use this step for parsing, validation, etc...&lt;br&gt;
Note: If you are thinking of auth, please consider a &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html" rel="noopener noreferrer"&gt;lambda authoriser&lt;/a&gt; instead. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;Pre Handler&lt;/code&gt; extension comes in handy when you need to adapt data to fit an interface. It is also a great place for fetching secrets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;Handler&lt;/code&gt;, where your beautiful business logic lives.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next up is the &lt;code&gt;Post Handler&lt;/code&gt;, use this extension to validate and/or cache the output of your business logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Error&lt;/code&gt; is an implicit extension for logging and tracing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And finally &lt;code&gt;Pre Response&lt;/code&gt;, your chance to format a response to the consumer (which could be data or an error).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Using the middleware
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;joi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;lambcycle&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lambcycle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;joiPlugin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lambcycle/dist/plugin-joi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lambcycle/dist/plugin-body-parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;realTimeEventTracker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./bugFreeBizLogic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;businessLogic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&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;realTimeEventTracker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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;data&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;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;assetId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;competition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;sport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;tournamentCalendar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;required&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;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lambcycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;businessLogic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nf"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nf"&gt;joiPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The example above leverages &lt;a href="https://github.com/expressjs/body-parser" rel="noopener noreferrer"&gt;express' body parser&lt;/a&gt; and &lt;a href="https://github.com/hapijs/joi" rel="noopener noreferrer"&gt;hapi's joi validation&lt;/a&gt;. We have configured both plugins with a parsing type and a validation schema respectively. By abstracting these two we have rid of complexity and shift the focus to the business logic. Note that a more robust lambda would include error tracing, and response plugins.&lt;/p&gt;
&lt;h2&gt;
  
  
  Crafting a Plugin
&lt;/h2&gt;

&lt;p&gt;The possibilities are endless when it comes to plugins! Do you have something in mind? &lt;a href="https://github.com/juliantellez/lambcycle/blob/develop/contributing.md" rel="noopener noreferrer"&gt;Contributions&lt;/a&gt; are more than welcome ❤️&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="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Sentry&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@sentry/node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MyAwesomeIntegration&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./MyAwesomeIntegration&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sentryPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Sentry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;dsn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@sentry.io/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;integrations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MyAwesomeIntegration&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;onPreResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlerWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;Sentry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;captureMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some percentile log perhaps?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlerWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;Sentry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;captureException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlerWrapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;sentryPlugin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your lambda ....&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;lambcycle&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lambcycle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sentryPlugin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./sentryPlugin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myApplicationLogic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;someLogic&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;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lambcycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myApplicationLogic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nf"&gt;sentryPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SENTRY_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SENTRY_PROJECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  DX
&lt;/h1&gt;

&lt;p&gt;Lambcycle has been built with &lt;a href="https://hackernoon.com/the-best-practices-for-a-great-developer-experience-dx-9036834382b0" rel="noopener noreferrer"&gt;developer experience "DX"&lt;/a&gt; in mind and ships with &lt;a href="https://www.typescriptlang.org" rel="noopener noreferrer"&gt;type&lt;/a&gt; definitions, for consistency and auto-completion 🚀 (VScode only).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F4896851%2F51274743-db4db500-19c7-11e9-903c-cb50d127d933.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F4896851%2F51274743-db4db500-19c7-11e9-903c-cb50d127d933.gif"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Lambcycle DX.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;It is a brave new world and serverless is here to stay! Promoting reusable components and consistent error handling will help you and your team create and support features in an more controlled and organised fashion. Lambcycle's main goals are to shift the conversation around a predictable unidirectional cycle and encouraging component reusability across features. Its worth mentioning that for more complex scenarios you should be looking at &lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html" rel="noopener noreferrer"&gt;Step functions&lt;/a&gt;. Let me know if you would like to know more about them in the comments, in the meantime check out these &lt;a href="https://aws.amazon.com/step-functions/use-cases/" rel="noopener noreferrer"&gt;use cases&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Special thanks to the legendary &lt;a href="https://theburningmonk.com/" rel="noopener noreferrer"&gt;burning monk&lt;/a&gt; for the in-depth review of this article.&lt;/p&gt;

</description>
      <category>lambda</category>
      <category>awslambda</category>
      <category>serverless</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
