<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Gokul Kulkarni on Medium]]></title>
        <description><![CDATA[Stories by Gokul Kulkarni on Medium]]></description>
        <link>https://medium.com/@gokulkulkarni?source=rss-1c8f0ecb2927------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*4QdBa8o0NJbCSbPHx55YFg.jpeg</url>
            <title>Stories by Gokul Kulkarni on Medium</title>
            <link>https://medium.com/@gokulkulkarni?source=rss-1c8f0ecb2927------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 00:08:19 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@gokulkulkarni/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[OpenSpec: Making Your AI Coding Agent Agree Before It Builds]]></title>
            <link>https://medium.com/@gokulkulkarni/openspec-making-your-ai-coding-agent-agree-before-it-builds-bd86357e30f9?source=rss-1c8f0ecb2927------2</link>
            <guid isPermaLink="false">https://medium.com/p/bd86357e30f9</guid>
            <category><![CDATA[prompt-engineering]]></category>
            <category><![CDATA[context-engineering]]></category>
            <category><![CDATA[spec-driven-development]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[openspec]]></category>
            <dc:creator><![CDATA[Gokul Kulkarni]]></dc:creator>
            <pubDate>Tue, 07 Jul 2026 04:35:10 GMT</pubDate>
            <atom:updated>2026-07-07T04:35:10.955Z</atom:updated>
            <content:encoded><![CDATA[<h3>Spec-driven development keeps getting called “too heavy.” OpenSpec’s answer: two folders, three commands, and a diff for your requirements.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dpzGFsU6EzrF2960lcvSqA.png" /></figure><p>OpenSpec keeps a living source of truth in specs/ and proposes every change as a self-contained folder. (Replace with real hero image before publishing.)</p><p>Last time, we walked through <a href="https://medium.com/@gokulkulkarni/stop-prompting-start-specifying-08a411fc7ec9">spec-driven development</a> and GitHub’s <a href="https://medium.com/@gokulkulkarni/your-ais-best-plan-disappears-when-you-close-the-tab-b9c5ca923051">Spec Kit</a> — the idea that you agree on what to build <em>before</em> the AI writes code. The most common reply I got was some version of: “Sounds great, but it looks like a lot of ceremony.”</p><p>This one is for that reply.</p><h3>The problem OpenSpec exists to solve</h3><p>AI coding assistants are fast. They are also unpredictable — because the requirements usually live in one place: <strong>your chat history.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Bu1ouqjHMbEtbFjZ6NeOwg.png" /></figure><p>You describe what you want. The agent builds <em>something</em>. Three prompts later, the original intent is buried under corrections. Nobody — human or AI — can point to a single source that says “this is what we agreed to build.”</p><p>The result is familiar:</p><ul><li>The agent forgets a constraint you mentioned 20 messages ago.</li><li>Two features quietly contradict each other.</li><li>You re-explain the same context every session.</li><li>“Why does it work this way?” has no answer except scrolling.</li></ul><p><strong>OpenSpec adds a thin layer of written specs between you and the agent, so you agree on <em>what</em> to build before any code is written</strong> — and that agreement survives after the chat window closes.</p><blockquote><em>Assumption flagged: I’m treating “AI coding agent” as your main workflow (Claude Code, Cursor, Windsurf, and similar). OpenSpec supports 25+ tools. If you code without an agent, most of this still applies, but the payoff is smaller.</em></blockquote><p><em>(OpenSpec is one of a few tools in this space; GitHub’s Spec Kit is another. This piece stays focused on OpenSpec.)</em></p><h3>What OpenSpec actually is</h3><p>In plain terms: <strong>OpenSpec is a folder of Markdown files plus a small command-line tool</strong> (<a href="https://github.com/Fission-AI/OpenSpec">open-source, from Fission-AI</a>). No IDE lock-in, no heavy framework.</p><p>It gives your project one honest answer to the question <em>“what is this system supposed to do?”</em> — written down, versioned in git, and updated every time you ship a change.</p><p>Its philosophy, stated by the project itself:</p><ul><li><strong>Fluid, not rigid</strong> — no forced phases; work on what makes sense.</li><li><strong>Iterative, not waterfall</strong> — refine as you learn.</li><li><strong>Easy, not complex</strong> — set up in seconds.</li><li><strong>Brownfield-first</strong> — built for existing codebases, not just fresh ones.</li></ul><h3>The one idea to remember: two folders</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NDNJQ6XRmDUoArxrH4Mawg.png" /></figure><p>Everything lives under a single openspec/ directory, split in two:</p><pre>openspec/<br>├── specs/      ← Source of truth: how the system works TODAY<br>└── changes/    ← Proposals: modifications, each in its own folder</pre><ul><li><strong>specs/</strong> is the durable asset. It describes current, agreed behaviour.</li><li><strong>changes/</strong> is the workbench. Each proposed change is a self-contained folder that lives here until it’s done, then merges into specs/.</li></ul><p>That separation is the whole trick. You can have three changes in flight at once without them stepping on each other, review each one in isolation, and keep specs/ always reflecting reality.</p><h3>The killer concept: delta specs</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Si_pZgEMxES0mjzOmsRGEg.png" /></figure><p>Most spec tools make you rewrite the whole specification for every change. OpenSpec doesn’t. It uses <strong>delta specs</strong> — you only write <em>what’s changing</em>, tagged into three buckets:</p><pre>## ADDED Requirements      → new behaviour, appended to the spec<br>## MODIFIED Requirements   → changed behaviour, replaces the old version<br>## REMOVED Requirements    → deprecated behaviour, deleted from the spec</pre><p>Think of it as a <strong>git diff for requirements.</strong> Instead of “here’s the entire 400-line auth spec again, spot the change,” you write:</p><pre>## MODIFIED Requirements</pre><pre>### Requirement: Session Expiration<br>The system MUST expire sessions after 15 minutes of inactivity.<br>(Previously: 30 minutes)</pre><p>Why this matters, in points:</p><ul><li><strong>Clarity</strong> — reviewers see the change, not unchanged noise.</li><li><strong>No conflicts</strong> — two changes can touch the same spec file if they hit different requirements.</li><li><strong>Brownfield fit</strong> — real work is <em>modifying</em> existing systems; deltas make that first-class.</li></ul><p>When a change is finished, OpenSpec merges those deltas into the main spec automatically. Your specs/ folder grows organically, one change at a time.</p><h3>How a spec is written</h3><p>Specs aren’t prose. They’re structured so both humans and agents read them the same way:</p><pre># Auth Specification</pre><pre>## Requirements</pre><pre>### Requirement: User Authentication<br>The system SHALL issue a JWT token upon successful login.</pre><pre>#### Scenario: Valid credentials<br>- GIVEN a user with valid credentials<br>- WHEN the user submits the login form<br>- THEN a JWT token is returned<br>- AND the user is redirected to the dashboard</pre><p>Three things to notice:</p><ul><li><strong>Requirements</strong> are the <em>what</em> — observable behaviour, not code.</li><li><strong>Scenarios</strong> are the <em>when</em> — concrete, testable Given/When/Then examples.</li><li><strong>SHALL / MUST / SHOULD</strong> (RFC 2119 keywords) signal how strict each rule is.</li></ul><p>The golden rule: <strong>a spec is a behaviour contract, not an implementation plan.</strong> No class names, no library choices, no step-by-step code. If the implementation can change without changing what the user sees, it doesn’t belong in the spec.</p><h3>The workflow: three commands, no phases</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LBNBd4CaPdwci6B7GOk3Kw.png" /></figure><p>OpenSpec’s current workflow is called <strong>OPSX</strong>, driven by slash commands you type to your AI agent. The core loop is three moves:</p><pre>/opsx:propose   →   /opsx:apply   →   /opsx:archive</pre><p>Here’s a real session — adding dark mode:</p><pre>You: /opsx:propose add-dark-mode<br>AI:  Created openspec/changes/add-dark-mode/<br>     ✓ proposal.md — why we&#39;re doing this, what&#39;s changing<br>     ✓ specs/       — requirements and scenarios<br>     ✓ design.md    — technical approach<br>     ✓ tasks.md     — implementation checklist</pre><pre>You: /opsx:apply<br>AI:  Implementing tasks...<br>     ✓ 1.1 Add theme context provider<br>     ✓ 1.2 Create toggle component<br>     ✓ 2.1 Add CSS variables<br>     All tasks complete!</pre><pre>You: /opsx:archive<br>AI:  Archived to changes/archive/2025-01-23-add-dark-mode/<br>     Specs updated. Ready for the next feature.</pre><ul><li><strong>Propose</strong> — the agent turns your idea into a change folder with a plan you can read and correct <em>before</em> it codes.</li><li><strong>Apply</strong> — the agent implements the checklist, ticking off tasks.</li><li><strong>Archive</strong> — the change merges into specs/ and moves to a dated archive folder for history.</li></ul><p>Two more commands are worth knowing:</p><ul><li><strong>/opsx:explore</strong> — think through an idea with the agent <em>before</em> committing to a change. A thinking partner, no structure required.</li><li><strong>/opsx:verify</strong> — check that the implementation actually matches the specs.</li></ul><p><strong>The key design choice:</strong> these are <em>actions, not phases.</em> Real work isn’t linear — you implement, realise the design was wrong, update it, keep going. OpenSpec lets you edit any artifact at any time instead of forcing plan → build → done.</p><h3>Inside a change folder</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*U2dWJsQPvU93afxh6S_95Q.png" /></figure><p>Each change is one folder holding everything needed to understand it:</p><pre>openspec/changes/add-dark-mode/<br>├── proposal.md   ← WHY and WHAT (intent, scope, approach)<br>├── design.md     ← HOW (technical approach, architecture decisions)<br>├── tasks.md      ← STEPS (implementation checklist with checkboxes)<br>└── specs/        ← the delta specs (what&#39;s changing)</pre><p>These artifacts build on each other — proposal informs specs, which inform design, which inform tasks. But you’re never forced to create all of them. Skip design for a trivial change; that’s fine.</p><h3>Getting started (2 minutes)</h3><pre># Requires Node.js 20.19.0+<br>npm install -g @fission-ai/openspec@latest</pre><pre>cd your-project<br>openspec init</pre><p>Then tell your AI agent:</p><pre>/opsx:propose &lt;what-you-want-to-build&gt;</pre><p>openspec init generates skill/command files your agent auto-detects (in .claude/skills/ or the equivalent for your tool). Re-run openspec update after upgrades to refresh them.</p><h3>Making it yours: customization</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hYypz-PRHaORBcS0eyZrvw.png" /></figure><p>OpenSpec’s defaults are deliberately plain so you can start in seconds. But real teams have real conventions, and OpenSpec gives you three levels to bend it to yours — use the lightest one that does the job.</p><p><strong>Level 1 — Project config (</strong><strong>openspec/config.yaml).</strong> The easiest lever, enough for most teams. One file lets you:</p><ul><li>Set a <strong>default schema</strong>, so you skip --schema on every command.</li><li>Inject <strong>project context</strong> — your tech stack, API style, testing tools — which OpenSpec feeds into <em>every</em> artifact the agent generates.</li><li>Add <strong>per-artifact rules</strong> — e.g. “every proposal must include a rollback plan,” applied only to proposals.</li></ul><pre># openspec/config.yaml<br>schema: spec-driven<br>context: |<br>  Tech stack: TypeScript, React, Node.js, PostgreSQL<br>  Testing: Jest + React Testing Library<br>rules:<br>  proposal:<br>    - Include rollback plan<br>  specs:<br>    - Use Given/When/Then format</pre><p>The point: instead of re-typing “we use Postgres and value backwards compatibility” into the chat every session, you write it once and the agent always sees it.</p><p><strong>Level 2 — Custom schemas.</strong> A schema defines <em>what artifacts exist and how they depend on each other.</em> The default (spec-driven) is proposal → specs → design → tasks. When that doesn’t fit, fork it and edit:</p><pre>openspec schema fork spec-driven my-workflow</pre><p>You get the schema plus its templates in openspec/schemas/my-workflow/, version-controlled with your code. From there you can drop artifacts (a “rapid” workflow of just proposal → tasks), add them (insert a review step before tasks), or rewrite the templates that guide what the agent produces. Validate before use with openspec schema validate.</p><p><strong>Level 3 — Global + community schemas.</strong> Store schemas at the user level (~/.local/share/openspec/schemas/) to reuse across projects, or pull in <strong>community schemas</strong> — opinionated workflows shared as standalone repos that wire OpenSpec into other tools. The maintainers recommend keeping schemas project-local when you can, since versioning them with your code is cleaner.</p><blockquote><em>The mental model: </em><strong><em>config tunes the words, schemas tune the workflow.</em></strong><em> Reach for config first; only build a schema when your process genuinely differs.</em></blockquote><h3>OpenSpec Stores (very early beta)</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hjejSQpPoOPFWrBPE8qESw.png" /></figure><p><em>Heads-up: Stores landed in v1.5.0 (June 2026) and the maintainers explicitly label it “very early beta — expect breaking changes.” Treat this as a preview, not production.</em></p><p>Everything so far assumes your specs live inside one repo. But planning often spans repos — a backend, a frontend, a mobile app that all share the same contracts. Where does the “source of truth” live then?</p><p><strong>Stores</strong> are OpenSpec’s answer: <strong>planning that lives in a repo of its own.</strong></p><ul><li>A <strong>store</strong> is a standalone OpenSpec repo — the same openspec/ shape you already know (specs + changes) — that you <strong>register</strong> on your machine.</li><li>Once registered, normal commands (list, show, status, validate, new change, archive, …) can act on that store <em>from anywhere</em> by adding --store &lt;id&gt;.</li><li>Because it’s just a git repo, it’s shared the way everything else is — git push. One planning source your whole team, and every coding agent, can read across every repo.</li></ul><p>In plain terms: instead of specs being trapped inside each service, you can have a dedicated <strong>planning repo</strong> (or a <strong>contracts repo</strong>) that every project points at. Stores replaces OpenSpec’s older “workspace and initiative” model with something simpler.</p><p>Why it matters: it’s the step from <em>“specs for this project”</em> to <em>“specs for this system,”</em> which is where spec-driven development starts paying off for teams rather than solo developers. Just remember the beta label before you bet a team workflow on it.</p><h3>Honest caveats</h3><p>I’d be selling you something if I skipped these:</p><ul><li><strong>It wants strong models.</strong> OpenSpec recommends high-reasoning models for planning <em>and</em> implementation; weaker models produce weaker specs.</li><li><strong>Context hygiene matters.</strong> Clear your context before implementation; a cluttered window degrades results.</li><li><strong>It’s discipline, not magic.</strong> OpenSpec gives you the structure. You still have to actually read the proposal before saying “apply.”</li></ul><h3>Why this is worth your attention</h3><p>Spec-driven development isn’t new. What OpenSpec gets right is <strong>removing the ceremony</strong> — no rigid gates, no framework to learn, just Markdown and three commands.</p><p>The real payoff isn’t the specs themselves. It’s that <strong>your intent stops living in a disposable chat and starts living in a versioned, reviewable source of truth</strong> your agent reads every time.</p><p>For anyone shipping real features with an AI agent, that’s the difference between <em>directing</em> the work and <em>hoping</em> the agent remembered.</p><p><em>Next in this series: turning delta specs into a team review workflow — how a change folder becomes a pull-request-shaped conversation. If you’ve tried spec-driven development with your agent, I want to hear what stopped you or what clicked — drop a response below.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bd86357e30f9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Your AI’s Best Plan Disappears When You Close the Tab]]></title>
            <link>https://medium.com/@gokulkulkarni/your-ais-best-plan-disappears-when-you-close-the-tab-b9c5ca923051?source=rss-1c8f0ecb2927------2</link>
            <guid isPermaLink="false">https://medium.com/p/b9c5ca923051</guid>
            <category><![CDATA[github-spec-kit]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[ai-tools]]></category>
            <category><![CDATA[spec-driven-development]]></category>
            <category><![CDATA[spec-kit]]></category>
            <dc:creator><![CDATA[Gokul Kulkarni]]></dc:creator>
            <pubDate>Tue, 30 Jun 2026 04:01:01 GMT</pubDate>
            <atom:updated>2026-06-30T04:15:59.048Z</atom:updated>
            <content:encoded><![CDATA[<p><em>GitHub’s Spec Kit takes the spec out of the chat window and puts it in your repo — versioned, reviewable, and shared by every agent. Here’s the full workflow.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/924/1*zzKHTvUcZSvRWhZiWczxCQ.png" /></figure><p>Last week we discussed <a href="https://medium.com/@gokulkulkarni/stop-prompting-start-specifying-08a411fc7ec9">Spec-Driven Development</a> — the idea that you should write a clear spec <em>first</em> and let your AI agent build from it, instead of nudging a chat box until the code looks right.</p><p>We also pointed at the easiest on-ramp: plan mode. You ask the agent to write a plan, it shows you what it intends to change, you approve, it builds. Good habit. But it has one quiet flaw.</p><p><strong>The plan is disposable.</strong> It lives inside that one chat session. Approve it, run it, close the window — and it’s gone. No version history. Nothing your teammate can read. Nothing the <em>next</em> agent can pick up. Great for a single change. Useless for code that has to live for years.</p><p>That gap is exactly what GitHub’s <strong>Spec Kit</strong> fills. This is the deep dive we promised.</p><h3>What Spec Kit actually is</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/924/1*-_FklyldW4jScLRiVFKxnQ.png" /></figure><p>Spec Kit is a free, open-source toolkit from GitHub. In one line: <strong>it turns the throwaway spec into a real, versioned file inside your repository</strong> — and gives your AI agent a set of structured commands to write, refine, and execute against it.</p><p>You don’t learn a new editor or a new language. Spec Kit installs into a project, then adds a handful of slash commands to the AI coding agent you already use. It works with 30+ agents — Claude Code, GitHub Copilot, Gemini CLI, Cursor, and more.</p><p>The mental shift is small but important:</p><blockquote><em>With plan mode, the spec is a message. With Spec Kit, the spec is a file — one that gets committed, reviewed in a pull request, and evolved like any other part of your codebase.</em></blockquote><p>That’s the whole point. The thing you agreed on stops vanishing.</p><h3>Setting it up (about two minutes)</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/924/1*8cRo4QUFK27fBhF1te3mvw.png" /></figure><p>Spec Kit ships as a small command-line tool called specify. You install it once, then bootstrap any project with it.</p><p><strong>1. Install the tool.</strong> It runs on Python and is installed with uv (a fast Python package manager):</p><pre>uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@vX.Y.Z</pre><p><em>(Replace </em><em>vX.Y.Z with the latest release tag. Pinning a version keeps your setup reproducible.)</em></p><p><strong>2. Initialize a project.</strong> Tell it which agent you use:</p><pre>specify init my-project --integration claude<br>cd my-project</pre><p>This drops a .specify/ folder into your project — templates, helper scripts, and a place to keep your project’s rules. From here on, everything happens through slash commands inside your AI agent.</p><p>Prerequisites are modest: Python 3.11+, Git, and one supported AI agent. That’s it.</p><h3>The workflow, command by command</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/924/1*R3ZlAWmabG3yuy4AD6Ud1w.png" /></figure><p>Spec Kit’s core loop is <strong>Constitution → Specify → Clarify → Plan → Tasks → Implement</strong>, with two optional quality checks along the way. Each command produces a real file you can read and edit. Here’s what each one does, in plain terms.</p><h3>1. /speckit.constitution — write the house rules, once</h3><p>Before any feature, you set your project’s non-negotiables: code quality bar, testing standards, performance expectations, UX consistency.</p><pre>/speckit.constitution Create principles focused on code quality, testing<br>standards, UX consistency, and performance requirements.</pre><p>This writes a constitution.md file. Every later step is checked against it — so the agent stops quietly drifting from your standards. Think of it as the rulebook the rest of the work has to obey.</p><h3>2. /speckit.specify — say what and why, not how</h3><p>Describe the feature in plain language. No tech stack yet — just the goal and the user experience.</p><pre>/speckit.specify Build a photo-album app. Albums are grouped by date,<br>re-orderable by drag-and-drop. Inside an album, photos show as tiles.</pre><p>The agent drafts a full specification — user stories and requirements — and saves it to a new, dedicated branch and folder (e.g. specs/001-photo-albums/spec.md). This is the document that replaces the chat message. It’s yours to refine.</p><h3>3. /speckit.clarify — let the agent interview you</h3><p>This is the step most people skip and later regret. The agent asks you targeted questions about everything you left vague, and records your answers right in the spec.</p><pre>/speckit.clarify</pre><p>Catching a missing rule here — as a sentence — is the cheapest bug fix you’ll ever make. Run it <em>before</em> planning.</p><h3>4. /speckit.plan — now bring the tech stack</h3><p>Only now do you talk architecture: language, framework, database, constraints.</p><pre>/speckit.plan Use React Native with a local SQLite store. No cloud uploads.</pre><p>The agent produces a technical blueprint — and usually supporting files like data-model.md, research.md, and API contracts. This is where you confirm it’s building the thing the <em>right</em> way, before any code exists.</p><h3>5. /speckit.tasks — break it into reviewable chunks</h3><pre>/speckit.tasks</pre><p>The plan becomes a tasks.md checklist: small, ordered steps, each with the exact files it touches. Tasks that can run in parallel are flagged, and dependencies are respected (models before services, services before screens). You can read the entire build as a to-do list before a line is written.</p><h3>6. /speckit.implement — let it build</h3><pre>/speckit.implement</pre><p>The agent works through the task list in order, checking off each step. Because the spec, plan, and tasks are all written down, it has nothing left to guess — and you can review progress against a plan you already approved.</p><h3>The two optional power-ups</h3><ul><li><strong>/speckit.checklist</strong> — generates a quality checklist for your spec. GitHub calls it <em>“unit tests for English”</em>: it checks your requirements for gaps, vagueness, and contradictions before you build.</li><li><strong>/speckit.analyze</strong> — run after tasks, before implement. It cross-checks the spec, plan, and tasks against each other and flags anything inconsistent or uncovered.</li></ul><p>There’s also /speckit.taskstoissues, which turns your task list into GitHub issues — handy for team tracking.</p><h3>What you’re left with — and why it matters</h3><p>After a feature, your repo contains real, committed artifacts:</p><pre>.specify/memory/constitution.md     ← your project&#39;s rules<br>specs/001-photo-albums/<br>  ├── spec.md                       ← what &amp; why<br>  ├── plan.md                       ← how<br>  └── tasks.md                      ← the steps</pre><p>This is the difference from plan mode, made concrete. The spec is <strong>versioned</strong> (it changes through commits and pull requests), <strong>shared</strong> (your teammate reads the same source of truth you do), and <strong>durable</strong> (six months later, the next agent — or the next engineer — picks up exactly where you left off).</p><p>You’re no longer maintaining software by editing code and hoping the docs keep up. You evolve the spec, and the code follows.</p><h3>Plan mode vs Spec Kit — pick the right weight</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/924/1*zOAnqsLlZKAVLK_DfXxAJQ.png" /></figure><p>These two aren’t rivals so much as different settings on the same dial.</p><ul><li><strong>Plan mode</strong> is SDD-lite — zero setup, perfect for a single change. But the spec is disposable: it lives in the session and vanishes when you close it.</li><li><strong>Spec Kit</strong> is the structured, gated version — a constitution, explicit gates, and a file for every phase. More ceremony up front, but the spec becomes a permanent, versioned part of your repo.</li></ul><p>Plan modeSpec KitSetupNoneOne-time installThe specA message in the chatA file in your repoSurvives the session?NoYes — committed &amp; versionedShareable with the team?NoYes, via pull requestsBest forA single, quick changeFeatures and systems that must last</p><p>The rule of thumb: reach for plan mode when you’re making one change you’ll never revisit. Reach for Spec Kit when the code — and the reasoning behind it — has to live.</p><h3>Make it your own: Extensions and Presets</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/924/1*ZeiGSl4MBLpefTuLYSNdSg.png" /></figure><p>Out of the box, Spec Kit gives you the core loop. But two mechanisms let you reshape it for your team — and this is where it gets genuinely powerful.</p><p><strong>Extensions add new capabilities.</strong> They introduce brand-new commands and phases that don’t ship with the core — think Jira integration, a post-implementation code-review step, or project health diagnostics. You browse and install them from the command line:</p><pre>specify extension search<br>specify extension add &lt;extension-name&gt;</pre><p><strong>Presets change <em>how</em> the existing workflow behaves</strong> — without adding new capabilities. They override the templates, commands, and terminology Spec Kit already uses. Real examples from the community catalog: a <em>Security Governance</em> preset that bakes secure-coding and compliance checks into every spec, a <em>Jira</em> preset that makes the “tasks to issues” step create Jira tickets instead of GitHub ones, a <em>Table of Contents</em> preset that adds navigation to long specs — even a <em>Pirate Speak</em> preset that renames specs to “Voyage Manifests” (a fun demo of how deep the customization goes).</p><pre>specify preset search<br>specify preset add &lt;preset-name&gt;</pre><p>The simple way to remember it: <strong>extensions teach Spec Kit new tricks; presets change how it does the tricks it already knows.</strong></p><h3>A concrete extension worth knowing: agent-assign</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/924/1*-qoKNR8vQEKOODSezXwNeQ.png" /></figure><p>Here’s the limitation it solves. By default, /speckit.implement runs <em>every</em> task in one flat context — the same generalist AI handles your database models, your UI, and your tests. As a project grows, that one-size-fits-all approach leaves quality on the table.</p><p>The community <a href="https://github.com/xymelon/spec-kit-agent-assign"><strong>spec-kit-agent-assign</strong></a> extension fixes this. It scans the specialized agents you’ve defined (a backend specialist, a frontend specialist, a test writer) and routes each task to the best-fit one, then runs each in its own focused context. It adds three commands that slot in after /speckit.tasks:</p><pre>/speckit.agent-assign.assign     → matches each task to the right agent<br>/speckit.agent-assign.validate   → checks every task has a valid agent<br>/speckit.agent-assign.execute    → runs each task with its assigned specialist (replaces /speckit.implement)</pre><p>The author benchmarked it by building the same app twice — once with standard Spec Kit, once with agent-assign — and had three frontier models grade both. The specialized version scored roughly <strong>40% higher</strong> overall. The intuition is simple: a focused agent with relevant context does better work than a generalist juggling everything at once.</p><p><em>(Note: extensions and presets are community-built and not audited by GitHub — review the source before installing. agent-assign currently targets Claude Code agent definitions and needs Spec Kit 0.3.0+.)</em></p><h3>When to use it (and when not to)</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/924/1*KLOcsWhSxxsCyQDOYvXhsw.png" /></figure><p>Use Spec Kit when the code has to live: real features, team projects, anything you’ll maintain or hand off. The versioned spec pays for itself the first time someone asks “why does it do that?” and the answer is a file, not a memory.</p><p>Skip it for throwaways. A one-off script doesn’t need a constitution. Plan mode, or just a good prompt, is plenty.</p><p>The old skill was writing code fast. The new one is being precise about what you want — and then <em>keeping</em> that precision somewhere it won’t disappear. Spec Kit is where you keep it.</p><p><em>Notes: command names use the current </em><em>/speckit.* prefix (mid-2026); some agents in “skills mode” use a </em><em>speckit-* form instead. Exact generated files vary slightly by agent and version. Always pin a release tag when installing. Verify against the official docs at github.github.io/spec-kit, as the toolkit is evolving quickly.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b9c5ca923051" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Stop Prompting. Start Specifying.]]></title>
            <link>https://medium.com/@gokulkulkarni/stop-prompting-start-specifying-08a411fc7ec9?source=rss-1c8f0ecb2927------2</link>
            <guid isPermaLink="false">https://medium.com/p/08a411fc7ec9</guid>
            <category><![CDATA[ai-coding]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[context-engineering]]></category>
            <category><![CDATA[spec-driven-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Gokul Kulkarni]]></dc:creator>
            <pubDate>Tue, 23 Jun 2026 04:43:01 GMT</pubDate>
            <atom:updated>2026-06-23T04:43:01.023Z</atom:updated>
            <content:encoded><![CDATA[<h3>The bottleneck in AI coding moved from writing code to saying what you actually want. Spec-Driven Development is the fix.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KNMW10qf9otU0wkpi-tojQ.png" /></figure><p>Last week I asked an AI agent to “add a password reset flow.” Thirty seconds later I had working code. It just wasn’t <em>my</em> code — it emailed a 6-digit code that never expired, ignored rate limiting, and silently logged the user out everywhere.</p><p>Fast, confident, and quietly wrong. That gap — between what I said and what I meant — is the whole story of building software with AI right now. And it has a fix.</p><h3>The trap of vibe coding</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8K7Hwf2jq_xbT2D-l4TXYA.png" /></figure><p>The default way most people use coding agents looks like this:</p><p>You type a short prompt. The agent generates a change. You run it, eyeball the result, and it’s <em>almost</em> right. So you go back to the chat, nudge it, run it again, nudge again.</p><p>This loop has a name now — <strong>vibe coding</strong> — and it feels productive because something is always moving.</p><p>The problem isn’t speed. It’s that the only record of <em>what you wanted</em> lives in a messy chat history. There’s no contract. The agent is guessing, you’re guessing, and the bugs are the difference between the two guesses.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*h_01qYmF9z1t1srSD1-nDA.png" /></figure><p>For a throwaway script, fine. For anything you have to maintain, this is technical debt being created at machine speed.</p><h3>What Spec-Driven Development actually is</h3><p>Spec-Driven Development (SDD) flips the order of operations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vwndziKjRXEHDBK8Lx584w.png" /></figure><p>Instead of <em>code first, document later</em>, you write a clear specification first — a plain-language description of <strong>what</strong> to build and <strong>why</strong> — and let the agent generate the code, tests, and docs from it.</p><blockquote><em>The spec becomes the primary artifact. The code is just its expression in a particular language. Maintaining software stops being “editing code” and becomes “evolving the spec.”</em></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*msT0_A3o1aEgMXV7h4MhPA.png" /></figure><p>That one shift changes everything downstream. The spec is the source of truth that both you and every AI agent align on <em>before</em> a line of code is written.</p><h3>The four phases</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w8csvWvJVJ8tR1xXplrO0g.png" /></figure><p>Good SDD isn’t a free-for-all. It runs as four reviewable steps, each a checkpoint you approve before moving on:</p><ol><li><strong>Specify</strong> — Describe the goal and the user journey in plain language. The agent drafts a detailed spec; you refine it.</li><li><strong>Plan</strong> — Declare the architecture, stack, and constraints. The agent proposes a technical design.</li><li><strong>Tasks</strong> — The agent breaks the work into small, independently testable chunks.</li><li><strong>Implement</strong> — The agent writes each task; each one is small enough to review and validate on its own.</li></ol><p>The magic is in the gates. You catch the “code never expires” mistake in the <strong>Specify</strong> step — as one sentence to edit — instead of in production.</p><h3>Where it sits next to TDD and BDD</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tdp4PJtgaM249WsRhRSr6A.png" /></figure><p>If you’ve written tests-first before, SDD doesn’t replace that. It sits above it.</p><p><strong>SDD</strong> answers <em>what and why</em> — the intent. <strong>BDD</strong> checks behavior across the system. <strong>TDD</strong> locks in correctness at the code level. You still write tests; SDD just gives them something authoritative to be tested against.</p><p>Think of the spec as the constitution, and TDD/BDD as the laws that enforce it.</p><h3>The password reset, done right</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OdYfG1LhwC_a7ev3jnCO9A.png" /></figure><p>Back to my example. Here’s the same feature as a spec instead of a prompt:</p><ul><li><strong>WHEN</strong> a user requests a reset, <strong>THE SYSTEM SHALL</strong> email a single-use link valid for 15 minutes.</li><li><strong>WHEN</strong> a link is used or expires, <strong>THE SYSTEM SHALL</strong> invalidate it immediately.</li><li><strong>WHEN</strong> more than 3 requests come from one account in an hour, <strong>THE SYSTEM SHALL</strong> rate-limit further attempts.</li><li><strong>WHEN</strong> a reset completes, <strong>THE SYSTEM SHALL</strong> invalidate all active sessions.</li></ul><p>That’s not code. A non-engineer could read it and catch a missing rule. But it’s precise enough that the agent has nothing left to guess — and the four mistakes from my first attempt are now impossible by definition.</p><p>That WHEN… THE SYSTEM SHALL… shape is borrowed from aerospace requirements writing. It turns out jet-engine rigor is exactly what fuzzy AI prompts were missing.</p><h3>Start where you already are: Claude Code’s plan mode</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PS6ltx5U-qtnkXdJowcjTg.png" /></figure><p>You don’t need to install anything to feel this. If you use Claude Code, <strong>plan mode</strong> is SDD’s core idea compressed into one keystroke.</p><p>Turn it on and the agent flips to <strong>read-only</strong>. It can read your files, search the codebase, and ask clarifying questions — but it cannot write to disk, run commands, or change anything. It uses that window to hand you a <strong>numbered plan</strong>: which files it will touch, in what order, and why.</p><p>Then you’re the gate:</p><ul><li><strong>Review it</strong> — read the plan like a diff of intent.</li><li><strong>Push back or edit</strong> — open it, rewrite the bits that are wrong.</li><li><strong>Approve</strong> — only now does the agent execute, step by step, still asking before each real change.</li></ul><p>The cost is about 30 seconds of reading. The payoff is that you catch the “wait, why is it touching the auth module?” moment <em>before</em> the file gets touched — not in code review, not in production. For my password reset, plan mode is where I’d have seen “no expiry, no rate limit” while it was still a sentence.</p><p>That’s the whole SDD loop in miniature: <strong>agree on the intent, then build.</strong></p><h3>Why plan mode isn’t enough for the long run</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Wo8MXILIDWvl9DenExTYBw.png" /></figure><p>Here’s the catch — and it’s the reason the dedicated tools exist.</p><p><strong>The plan is disposable.</strong> It’s a message in your session, not a managed artifact. Approve it, run it, close the terminal — and the plan is gone. There’s no file to keep.</p><p>That breaks down the moment software has to <em>live</em>:</p><ul><li><strong>No version history.</strong> You can’t diff how the intent changed between releases.</li><li><strong>No shared source of truth.</strong> Your teammates — and the next AI session, or a different agent entirely — don’t inherit that plan. Everyone starts from a blank context again.</li><li><strong>Nothing to evolve.</strong> SDD’s core promise is that the spec is the primary artifact you <em>maintain</em>. Plan mode gives you the gate but never the durable spec to manage.</li></ul><p>Plan mode is perfect for a single change today. It’s not built to carry a feature’s intent across months, people, and dozens of sessions.</p><h3>When you need managed specs: Spec Kit &amp; OpenSpec</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DmwRUKuqTNtDwFfb_UUwGQ.png" /></figure><p>To make the spec a real, persistent artifact — checked into the repo, versioned, evolved — you move up to a dedicated tool. Two open-source ones lead, and I’ll cover each in its own piece:</p><ul><li><strong>GitHub Spec Kit</strong> — a structured, gated take on the four phases. Thorough and agent-agnostic; works with Copilot, Claude Code, Gemini, and more.</li><li><strong>OpenSpec</strong> — a lighter, “fluid not rigid” alternative. Each change gets its own folder of spec, design, and tasks, stored in your repo, and it’s built to work on existing codebases, not just greenfield ones.</li></ul><p>So think of it as a spectrum: <strong>plan mode</strong> for the in-the-moment gate, <strong>Spec Kit / OpenSpec</strong> when the spec needs to outlive the session. Detailed walkthroughs of both tools are coming separately.</p><h3>Zoom out: this is context engineering</h3><p>Step back and SDD stops looking like a niche workflow. It’s one piece of the bigger shift happening in how we work with AI.</p><p>We’ve moved past <strong>prompt engineering</strong> — the art of phrasing one clever instruction. The discipline that actually predicts whether an agent succeeds is <strong>context engineering</strong>: giving the model the right information, in the right form, at the right time. Not how you ask, but <em>what it can see</em> when it answers — memory, files, history, the lot.</p><p>A spec is exactly that, for the part that matters most: your intent.</p><blockquote><em>Prompt engineering is how you ask. Context engineering is what the model knows when you ask. A spec is the cleanest, most durable context you can give it.</em></blockquote><p>That reframes the whole piece:</p><ul><li><strong>Vibe coding</strong> fails because the context is a messy, disappearing chat.</li><li><strong>Plan mode</strong> improves the context — but only for one session.</li><li><strong>Managed specs</strong> make the right context <em>permanent</em> — versioned in the repo, identical for every teammate and every agent, so nobody re-explains the intent from scratch.</li></ul><p>SDD is context engineering applied to intent. The spec is how you stop re-explaining yourself to the machine.</p><h3>When to use it — and when not to</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tMzCynPoh8-IJijzpj-sYQ.png" /></figure><p>SDD is worth the overhead when the software is serious: long-lived, shared across a team, or carrying real consequences if it’s wrong.</p><p>For a one-off script or a quick experiment, the chat loop is fine. Don’t write a constitution for a sticky note.</p><p>The line is simple: <strong>the longer the code has to live, the more the spec earns its keep.</strong></p><h3>The takeaway</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*f1su6ZZ-7lu1MP_Qz0Vrgg.png" /></figure><p>Writing code got cheap. Being precise about what you want is now the rare skill.</p><p>So the question isn’t whether AI can write your next feature. It’s whether you can say, clearly enough, what that feature should do.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=08a411fc7ec9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Prompt → Context Engineering]]></title>
            <link>https://medium.com/@gokulkulkarni/prompt-context-engineering-c0d21bb2ab0c?source=rss-1c8f0ecb2927------2</link>
            <guid isPermaLink="false">https://medium.com/p/c0d21bb2ab0c</guid>
            <category><![CDATA[ai-engineering]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[generative-ai-tools]]></category>
            <category><![CDATA[ai-tools]]></category>
            <category><![CDATA[ai-agent]]></category>
            <dc:creator><![CDATA[Gokul Kulkarni]]></dc:creator>
            <pubDate>Tue, 16 Jun 2026 04:15:34 GMT</pubDate>
            <atom:updated>2026-06-16T04:15:34.927Z</atom:updated>
            <content:encoded><![CDATA[<h3>Your AI Agent Isn’t Dumb. It Just Can’t See What It Needs.</h3><h3>The real skill shifted from writing the perfect prompt to managing everything the model looks at — and that shift has a name.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J5UDUa5izESNLEzo74uauA.png" /></figure><p>The context window is a desk. The craft is deciding what goes on it.</p><p>Last time, we left off with a small fleet — agents running many jobs in parallel while you stepped away to do something else.</p><p>But anyone who has run one for more than ten minutes knows the deflating part. The agent starts strong. Then it drifts. It forgets a decision it made three steps ago. It confidently invents a function that doesn’t exist. And the longer the task runs, the worse it gets.</p><p>The reflex is to blame the model — <em>it’s just not smart enough yet.</em> Almost always, that’s the wrong diagnosis. The culprit isn’t intelligence. It’s <strong>context</strong>.</p><h3>The failures have names now</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uhJie4jv5En-IpNX6HA5bg.png" /></figure><p>These aren’t random glitches. The field has settled on names for them, and each one points back to the same root cause.</p><ul><li><strong>Context rot</strong> — quality quietly decays as a long task fills the window. The agent isn’t getting dumber; its workspace is getting more crowded.</li><li><strong>Lost-in-the-middle</strong> — hand a model a long stretch of text and it pays the most attention to the beginning and end, the least to the middle. Bury the key detail in paragraph forty of sixty and it may as well not be there.</li><li><strong>Context poisoning</strong> — one hallucination gets read back into the next step, then the next, compounding like a rumor that hardens into “fact.”</li></ul><p>Notice what they share. None is a reasoning failure. All three are <em>what-the-model-sees</em> failures. Fix what it sees, and most of them simply stop.</p><h3>From wording the prompt to managing the view</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1m_FwLCUNatHl_MFfL_XDw.png" /></figure><p>For a couple of years, the prized skill was <strong>prompt engineering</strong> — finding exactly the right words to coax a good answer out. And wording does matter.</p><p>But here’s the reframe: the model has no memory. On every single call, it sees only what’s in front of it — its context window — and nothing else. Whatever it “knew” a moment ago is gone unless you put it back.</p><p>So the skill that moves the needle stopped being <em>how you phrase the question</em> and became <em>how you manage everything the model sees around it.</em> That’s context engineering. Prompt engineering didn’t die — it became a subset. The prompt is now one input among many you design.</p><blockquote><em>Context engineering is putting just enough of the right information in front of the model — and nothing else.</em></blockquote><h3>The desk</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TO0pi4GcvD09eBbyXRhQpw.png" /></figure><p>The cleanest picture: the context window is the model’s <strong>desk</strong>.</p><p>Everything it needs for <em>this</em> step has to fit on that desk. Too little, and it guesses. Too much clutter, and it loses the thread — and pays for every scrap of paper, in money and time. Engineering the context means keeping exactly the right things on the desk, in the most compact form that still works.</p><p>And the surprising part: a bigger desk doesn’t fix it.</p><p>The obvious move is to give the model more room, and windows have ballooned into the millions of tokens. But stuff a giant window full and performance <em>degrades</em> — slower, pricier, less accurate, lost-in-the-middle and all. More context isn’t better. The right context is. That’s why curation is a real skill, not a storage problem.</p><h3>Four ways context gets in — two questions</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j2r2KDO572eY5kQMYYCJ1A.png" /></figure><p>So what actually goes on the desk? It arrives through four channels, easiest to hold as answers to two questions.</p><h3>How do we bring the right knowledge in?</h3><ul><li><strong>Retrieval.</strong> Our running example throughout: an AI agent fixing a bug in the <em>checkout flow</em> of a large codebase. It doesn’t read the whole repo — it fetches the <em>few</em> files that touch checkout. Pulling the right pages and leaving the rest on the shelf is retrieval.</li><li><strong>Memory.</strong> At the start, you gave it one rule: the <em>payments module</em> sits right next to checkout — leave it alone, it’s out of scope and too risky to touch. Several steps later, that rule only holds if it’s been carried forward onto the desk. Memory is how earlier decisions survive into the present step — because the model won’t remember them on its own.</li></ul><h3>How do we let it act and bring results back?</h3><ul><li><strong>Tool results.</strong> The agent runs the test suite and reads the failure back into the window — fresh context it didn’t have a second ago. (This is where <em>tools</em> and <em>MCP</em>, the standard way agents plug into the outside world, come in. I won’t re-explain them here — that’s its own piece: <a href="https://medium.com/@gokulkulkarni/agent-hands-tools-mcp-826456d76134">Tools &amp; MCP</a>.)</li><li><strong>Multi-agent handoffs.</strong> For a messy side-quest — say, a thousand lines of logs — the agent spins up a subagent, lets it wade through, and takes back only a short summary. The mess stays off the main desk. (If “subagent” is new, that’s the previous rung: <a href="https://medium.com/@gokulkulkarni/what-actually-makes-an-ai-an-agent-a-plain-english-guide-7a7264e2ecc5">Agents 101</a>.)</li></ul><h3>The one move underneath all four</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bFkXX0CEiEqFOeU0D5Nc3w.png" /></figure><p>Lay the four side by side and the same decision repeats: <em>what gets onto the desk, and in what compressed form?</em></p><p>That’s the whole craft. Context engineering isn’t four tricks to memorize — it’s <strong>one discipline with four entry points.</strong> Retrieval, memory, tool results, handoffs: each is just another place where you choose what the model sees and how tightly you can pack it.</p><h3>The craft is shipping as tooling</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ME5wYACqzreZ_Oe3wfB_YA.png" /></figure><p>You can tell a principle has matured when people build software whose only job is to enforce it. Context engineering is there.</p><ol><li><strong>RTK</strong> (“Rust Token Killer”) sits between your shell and the agent and squeezes noisy command output — git status, test logs, package-manager chatter — by 60–90% before it reaches the window.</li><li><strong>Repomix</strong> packs an entire codebase into one AI-friendly file, dropping tests and build artifacts so only signal gets in.</li><li><strong>Gitingest</strong> and friends do the same “filter the noise, fit the window” job.</li></ol><p>There’s a commercial edge here, not just an accuracy one. Every token on the desk is <strong>money and time</strong> — a bloated context is a slower, pricier request on <em>every</em> call, so trimming it compounds across thousands of runs. Better answers are the headline; cheaper and faster are the quiet bonus.</p><p>(A proper head-to-head on these tools comes later in the series — this is just proof the lever is real.)</p><h3>Why this points somewhere bigger</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IZ10aW51E7utVqSoEf1fEA.png" /></figure><p>Here’s the catch that sets up everything after this. All of this curation — the retrieval, the carried-forward decisions, the summaries — you reassemble it <em>by hand, every session.</em> The window resets, and your careful context evaporates. You build the same desk again tomorrow.</p><p>Which raises an obvious question: what if you didn’t? What if the context that matters were written down once, durable — the source everything else is rebuilt from?</p><p>That artifact has a name. It’s where we go next — and it’s the moment the spec stops being paperwork and becomes the source code.</p><p><em>This is Post 3 in a series on how AI is changing the way software gets made. Next: the spec as the source of truth.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c0d21bb2ab0c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Agent Hands: Tools & MCP]]></title>
            <link>https://medium.com/@gokulkulkarni/agent-hands-tools-mcp-826456d76134?source=rss-1c8f0ecb2927------2</link>
            <guid isPermaLink="false">https://medium.com/p/826456d76134</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[mcp-server]]></category>
            <category><![CDATA[mcps]]></category>
            <category><![CDATA[generative-ai-tools]]></category>
            <dc:creator><![CDATA[Gokul Kulkarni]]></dc:creator>
            <pubDate>Mon, 15 Jun 2026 13:16:27 GMT</pubDate>
            <atom:updated>2026-06-15T13:16:27.556Z</atom:updated>
            <content:encoded><![CDATA[<p><em>A web URL points at an exact place. An agent picks a tool by what it means to do. That one difference is the whole story of MCP.</em></p><p>In the last piece, we landed on a simple line: an agent is only as capable as the tools it can actually reach. A prediction engine with a goal and a loop is still just <em>talking</em> until it can do something — read a file, query a database, send a message, look up an order.</p><p>So this piece is about the hands. What a “tool” actually is, how you write one, and what MCP — the standard everyone’s suddenly talking about — really changes. We’ll end with working code, but let’s start with the idea that makes all of it click.</p><h3>What a tool actually is</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bDaZvVH1sdkbQxv9Fvze4w.png" /></figure><p>A tool is a described capability the agent can choose to call.</p><p>That’s it. Not magic, not a plugin in the app-store sense. Under the hood a tool is two ordinary things bolted together:</p><ul><li><strong>A description</strong> — a name, a plain-language explanation of what it does and when to use it, and the inputs it expects.</li><li><strong>A function</strong> — normal code that actually does the work and returns a result.</li></ul><p>Here’s the part that surprises people: <strong>the model never runs your code.</strong> It can’t. It only emits text. So the loop works like a relay:</p><ol><li>The agent decides it needs a tool and produces a structured request — “call get_order_status with orderId: 8842&quot;.</li><li><em>Your</em> program sees that request and runs the real function.</li><li>You hand the result back into the conversation.</li><li>The agent reads the result and continues its loop.</li></ol><p>The model proposes; your code disposes. Hold onto that — it matters for everything below.</p><h3>The shift: HTTP binds by address, agents bind by intent</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*15TBGLrtAbe0AkSPh962YQ.png" /></figure><p>If you’ve built anything on the web, you already know the old model. You call a URL.</p><blockquote>GET <a href="https://api.shop.com/v1/orders/8842">https://api.shop.com/v1/orders/8842</a></blockquote><p>A URL is an <strong>address</strong>. It points at one exact place, and to use it you have to know that place in advance — the precise path, the method, the parameter names. A developer wires that call by hand, at coding time. Get one character wrong and it breaks. The binding between “what I want” and “what I call” is literal, fixed, and brittle.</p><p>In code, that wiring looks like this:</p><pre>// The developer decides — at code time — exactly what to call.<br>async function getOrder(orderId) {<br>  const res = await fetch(<br>    `https://api.shop.com/v1/orders/${encodeURIComponent(orderId)}`<br>  );<br>  return res.json();<br>}</pre><pre>// Nothing &quot;chooses&quot; this for you. You name the endpoint, by hand.<br>const order = await getOrder(&quot;8842&quot;);</pre><p>A human looked at the need (“I want this order’s status”) and hard-coded the mapping to one exact address. The computer never decides <em>which</em> call fits the situation — that decision was already made, in advance, by the person who wrote the line.</p><p>And on the <em>other</em> end — the server — that address is bound to a function just as literally. This is how a URL gets “linked” to the code that runs it:</p><pre>// Express: the URL path is mapped to exactly one handler.<br>app.get(&quot;/v1/orders/:id&quot;, async (req, res) =&gt; {<br>  const data = await getOrderById(req.params.id);<br>  res.json(data);<br>});</pre><p>The string &quot;/v1/orders/:id&quot; <em>is</em> the link. The router does a dumb, literal match: this exact path → this exact function. Spell the path differently and the request misses entirely. Nothing reads the <em>meaning</em> of the request; it only matches the address.</p><p>Keep that snippet in mind — because the tool we write later links to its function a completely different way. Same job (request reaches the right code), opposite mechanism: a <strong>path</strong> does the linking in HTTP, a <strong>description</strong> does it for a tool.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hkMcQRTVLTB6860wc17jsw.png" /></figure><p>An agent doesn’t get an address. It gets a <strong>menu</strong> — a list of tools, each with a plain-language description of what it’s for. Then it does something a URL never could: it reads your actual request, works out the <em>intent</em>, and picks the tool whose description best matches.</p><p>You say <em>“any update on order 8842?”</em> Nobody told the agent to call get_order_status. It chose that tool because the description said <em>&quot;use this when the user asks where their order is,&quot;</em> and that matched what you meant.</p><blockquote>HTTP routes by address. Agents route by intent. The description is the new endpoint.</blockquote><p>This flips where the important work lives. On the web, the contract is the URL and the data shape. With tools, <strong>the contract is the description</strong> — because that sentence is what the model reads to decide whether your tool is the right one. A vague description is a broken API, even if the code is perfect.</p><p>One honest clarification, so nobody emails me: MCP often travels <em>over</em> HTTP on the wire. The contrast isn’t HTTP-the-protocol versus MCP. It’s about <em>who decides what to call, and how</em> — a developer matching an exact address at code time, versus a model matching an intent to a description at run time.</p><p>Side by side:</p><p>HTTP / RESTMCP / agent toolsYou call it byAn exact address (URL + path)A plain-language description (intent)Who picks which to callPre-wired by the developer; the framework (Spring, Servlets, Express…) dispatches by literal path matchThe model, at run time, by matching intentThe link to the codeA route string — /v1/orders/:idThe tool&#39;s descriptionHow it&#39;s matchedLiteral: path matches or it doesn&#39;tSemantic: by meaningInputs defined byPath / query / body paramsA typed input schema (JSON Schema / Zod)DiscoveryRead the API docs yourselfAgent asks the server &quot;what can you do?&quot;Reuse across appsEach client wires its own callsWrite once; any MCP host can use itWhen it driftsWrong path → 404Vague description → tool ignored or misused</p><p>The row that matters most is the first one. Everything else follows from <em>address versus intent</em>.</p><h3>How a tool is written</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5S7wnzmvNrjHApg1G_ocQg.png" /></figure><p>Let’s make it concrete. A tool has two parts: the description the model sees, and the function your code runs.</p><p>First, the <strong>description</strong> — this is what’s handed to the model. (This shape is the function-calling format used by the major model APIs.)</p><pre>{<br>  &quot;name&quot;: &quot;get_order_status&quot;,<br>  &quot;description&quot;: &quot;Get the current status of a customer&#39;s order. Use this when the user asks where their order is or what&#39;s happening with an order.&quot;,<br>  &quot;input_schema&quot;: {<br>    &quot;type&quot;: &quot;object&quot;,<br>    &quot;properties&quot;: {<br>      &quot;orderId&quot;: {<br>        &quot;type&quot;: &quot;string&quot;,<br>        &quot;description&quot;: &quot;Order ID, e.g. &#39;8842&#39;&quot;<br>      }<br>    },<br>    &quot;required&quot;: [&quot;orderId&quot;]<br>  }<br>}</pre><p>Notice there’s no logic here at all — just <em>meaning</em>. The description field is the intent contract. The input_schema tells the model exactly what to fill in.</p><p>Now the <strong>function</strong> that actually runs when the model asks for it:</p><pre>async function getOrderStatus({ orderId }) {<br>  const res = await fetch(<br>    `https://api.shop.com/v1/orders/${encodeURIComponent(orderId)}`<br>  );<br>  const data = await res.json();<br>  return `${data.status}, ETA ${data.eta}`;<br>}</pre><p>Look closely and you’ll see both worlds in one place. The agent reached this function <em>by intent</em>. But the function itself reaches the orders service <em>by address</em> — a plain HTTP call. That’s the relationship in a nutshell: <strong>intent on the outside, exact addresses on the inside.</strong> The tool is the translator between the two.</p><p>And the round trip, end to end:</p><ol><li>You ask: <em>“Where’s my order 8842?”</em></li><li>The model replies not with prose but with a request: use get_order_status, orderId = &quot;8842&quot;.</li><li>Your loop catches that, runs getOrderStatus, gets back &quot;Shipped, ETA Tuesday&quot;.</li><li>You feed that string back into the conversation.</li><li>The model turns it into: <em>“Order 8842 has shipped and should arrive Tuesday.”</em></li></ol><p>The model supplied the judgement; your function supplied the fact.</p><h3>How the agent wires it all together</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ohsa7xbxZx_r2sY5xetY9w.png" /></figure><p>We’ve written a tool. But how does the agent actually <em>receive</em> it, decide to use it, and act on the result? That’s the loop from the last piece — here it is in code, with the model’s API doing the talking (TypeScript, using Anthropic’s SDK as the example):</p><pre>import Anthropic from &quot;@anthropic-ai/sdk&quot;;</pre><pre>const client = new Anthropic();</pre><pre>// 1. The menu — every tool&#39;s description (its intent) handed to the model.<br>const tools = [<br>  {<br>    name: &quot;get_order_status&quot;,<br>    description:<br>      &quot;Get the current status of a customer&#39;s order. Use when the user asks where their order is.&quot;,<br>    input_schema: {<br>      type: &quot;object&quot;,<br>      properties: {<br>        orderId: { type: &quot;string&quot;, description: &quot;Order ID, e.g. &#39;8842&#39;&quot; },<br>      },<br>      required: [&quot;orderId&quot;],<br>    },<br>  },<br>];</pre><pre>// 2. The matching real functions, keyed by tool name.<br>const executors = {<br>  get_order_status: async ({ orderId }) =&gt; {<br>    const res = await fetch(`https://api.shop.com/v1/orders/${orderId}`);<br>    const data = await res.json();<br>    return `${data.status}, ETA ${data.eta}`;<br>  },<br>};</pre><pre>async function runAgent(userMessage) {<br>  const messages = [{ role: &quot;user&quot;, content: userMessage }];</pre><pre>  // 3. The loop — keep going until the model stops asking for tools.<br>  while (true) {<br>    const response = await client.messages.create({<br>      model: &quot;claude-sonnet-4-6&quot;,<br>      max_tokens: 1024,<br>      tools,            // the menu goes in on every turn<br>      messages,<br>    });</pre><pre>    // Model answered in plain text — the goal is met, we&#39;re done.<br>    if (response.stop_reason !== &quot;tool_use&quot;) {<br>      return response.content.find((b) =&gt; b.type === &quot;text&quot;)?.text;<br>    }</pre><pre>    // 4. The model asked to use a tool. Run it — YOUR code, not the model&#39;s.<br>    messages.push({ role: &quot;assistant&quot;, content: response.content });</pre><pre>    const toolResults = [];<br>    for (const block of response.content) {<br>      if (block.type !== &quot;tool_use&quot;) continue;<br>      const run = executors[block.name];<br>      const result = await run(block.input);<br>      toolResults.push({<br>        type: &quot;tool_result&quot;,<br>        tool_use_id: block.id,<br>        content: result,<br>      });<br>    }</pre><pre>    // 5. Hand the results back; the loop runs again with them in context.<br>    messages.push({ role: &quot;user&quot;, content: toolResults });<br>  }<br>}</pre><pre>await runAgent(&quot;Where&#39;s my order 8842?&quot;);</pre><p>That’s the entire mechanism, and it’s the relay from earlier made literal:</p><ul><li>The <strong>menu</strong> (tools) is sent on every turn — that&#39;s how the model knows what it <em>could</em> call.</li><li>When the model wants one, it doesn’t run anything; it returns a tool_use block, and the loop stops to act.</li><li><strong>Your</strong> code looks up the function, runs it, and packages the answer as a tool_result.</li><li>The result goes back in as the next message, and the model continues — often turning a raw &quot;Shipped, ETA Tuesday&quot; into a friendly reply, or deciding it now needs a <em>different</em> tool.</li></ul><p>Two things are worth staring at. First, the loop is dumb on purpose — it just shuttles requests and results back and forth; all the judgement lives in the model. Second, notice the two pieces you hand-maintain: the tools menu and the executors map. Keep those in mind — because automating exactly that wiring is the whole reason MCP exists.</p><h3>Enter MCP — and the problem it solves</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*L-hdDIsmi35YyUoynqO6Jw.png" /></figure><p>So far so good for one app. Now multiply it.</p><p>Every team that wanted to give an agent tools used to wire them up its own way. Your order-lookup tool for your assistant didn’t work in my code editor’s agent, which didn’t work in someone’s chat app. Ten tools across five different agents meant fifty bespoke integrations. The classic M×N mess.</p><p><strong>MCP — the Model Context Protocol — is the standard that turns M×N into M+N.</strong> The usual one-liner is <em>“USB-C for AI”</em>: agree on one connector, and anything plugs into anything.</p><p>The shape is simple:</p><ul><li>An <strong>MCP server</strong> exposes your tools (your order-lookup tool, your database tool, your file tools).</li><li>An <strong>MCP host</strong> — the agent app — connects to that server.</li><li>On connecting, the host asks, <em>“what can you do?”</em> and the server returns its list of described tools.</li><li>From then on, the agent picks among them <strong>by intent</strong>, exactly as before — except now those tools are reusable by <em>any</em> MCP-compatible agent, not just yours.</li></ul><p>In loop terms: the tools menu is now <em>fetched</em> from the server instead of hand-written, and the executors live inside the server. The two pieces you were maintaining by hand both move behind a standard interface — so any agent can borrow them.</p><p>Write the tool once; every agent that speaks MCP can use it. That’s the whole pitch, and it’s why MCP spread so fast.</p><h3>Writing the same tool as an MCP server</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jObg6tINtaQJsRAH0VqNeg.png" /></figure><p>Here’s the order-lookup tool again — this time as a proper MCP server, so any agent can reach it. With the official TypeScript SDK:</p><pre>import { McpServer } from &quot;@modelcontextprotocol/sdk/server/mcp.js&quot;;<br>import { z } from &quot;zod&quot;;</pre><pre>const server = new McpServer({ name: &quot;orders&quot;, version: &quot;1.0.0&quot; });</pre><pre>server.registerTool(<br>  &quot;get_order_status&quot;,<br>  {<br>    description:<br>      &quot;Get the current status of a customer&#39;s order. Use when the user asks where their order is.&quot;,<br>    inputSchema: { orderId: z.string().describe(&quot;Order ID, e.g. &#39;8842&#39;&quot;) },<br>  },<br>  async ({ orderId }) =&gt; {<br>    const data = await fetchOrder(orderId);<br>    return { content: [{ type: &quot;text&quot;, text: `${data.status}, ETA ${data.eta}` }] };<br>  }<br>);</pre><p>Look at what’s doing the work. The description is the same intent contract from before — the sentence the model reads to decide whether this tool fits. The inputSchema (a Zod schema) declares the inputs it must fill in. The handler does the real work and returns the result. Same anatomy as the raw tool earlier — a name, a description, typed inputs, a function — now wrapped so any MCP-compatible agent can discover and call it.</p><p>Now put this beside that Express route from earlier. There, the link was a literal path — app.get(&quot;/v1/orders/:id&quot;, handler). Here, there is no path at all. The handler is linked by its <strong>description</strong> — &quot;Get the current status of a customer&#39;s order…&quot; — and the model matches your request to it by meaning. Same shape (something → a handler), but the &quot;something&quot; changed from an address you must know to an intent the model infers.</p><p>Different language, identical anatomy: a name, a description carrying the intent, a typed input schema, and a handler that does the real work and returns a result. MCP didn’t change what a tool <em>is</em>. It standardised how a tool is <em>offered</em>, so it stops being trapped inside one app.</p><h3>Why this matters — and what’s next</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OL_TSNZZLiTH6Icxhk9e4w.png" /></figure><p>Pull it together:</p><ul><li>A tool is a described capability plus a function — the agent’s hands.</li><li>Agents bind to tools by <strong>intent</strong>, not by address, so the description is the real interface.</li><li>MCP standardises that offer, so a tool written once works across every agent that speaks the protocol.</li></ul><p>But there’s a catch sitting in plain sight, and it’s the thread that runs through this whole series. Every tool result — every order status, every query row, every file you hand back — lands right back in the agent’s finite working memory. Give an agent twenty tools and let it run a long loop, and that desk fills up fast.</p><p>Which is exactly the problem the next piece is about: when the model can reach everything, the hard part is no longer <em>access</em>. It’s deciding what deserves a place in the window at all. That’s context engineering — and it’s where this series has been heading all along.</p><p><em>Have you written a tool or an MCP server yet? I’d love to hear what you plugged into your agent — and where it surprised you.</em></p><p><em>Have you written a tool or an MCP server yet? I’d love to hear what you plugged into your agent — and where it surprised you.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=826456d76134" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What Actually Makes an AI an “Agent”? (A Plain-English Guide)]]></title>
            <link>https://medium.com/@gokulkulkarni/what-actually-makes-an-ai-an-agent-a-plain-english-guide-7a7264e2ecc5?source=rss-1c8f0ecb2927------2</link>
            <guid isPermaLink="false">https://medium.com/p/7a7264e2ecc5</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[generative-ai-tools]]></category>
            <category><![CDATA[large-language-models]]></category>
            <dc:creator><![CDATA[Gokul Kulkarni]]></dc:creator>
            <pubDate>Mon, 15 Jun 2026 04:14:18 GMT</pubDate>
            <atom:updated>2026-06-15T04:14:18.184Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SkQsLd1BGCwPM-9QljYVUA.png" /></figure><p><em>It isn’t a smarter chatbot. It’s the same forgetful prediction engine — handed a goal, a loop, and a set of tools.</em></p><p>Ask a chatbot a question and it answers, then stops. Then you watch a coding “agent” open a file, run the tests, read the errors, fix the code, and run the tests again — on its own, until it works.</p><p>Same underlying AI. Completely different behaviour. The gap isn’t intelligence. It’s structure — and once you see the structure, the whole “agent” buzzword stops being mysterious.</p><h3>First, what’s actually underneath</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I7NkfQFVni0igTsx3KHcAA.png" /></figure><p>Before “agent” makes sense, you need to know what the model at the centre really does.</p><p>A large language model isn’t a database you look things up in, and it isn’t a brain that knows facts. It does one humble thing: it predicts the next chunk of text, again and again, choosing the most likely continuation of what came before.</p><p>It learned those patterns from a huge amount of writing. So it absorbed <em>how language tends to go</em> — not a clean file of facts.</p><p>That one mechanism explains its talents and its failures at once. The engine that writes a fluent paragraph can also state something false with total confidence. Creativity and hallucination come from the same place.</p><p>Two limits matter most. Keep them in your back pocket:</p><ul><li><strong>No memory between calls.</strong> Every request starts blank. When a chat app seems to remember your earlier messages, it’s quietly re-sending the whole history each time.</li><li><strong>A finite working memory.</strong> Everything it can weigh at once — your request, the conversation, whatever it’s looking at — must fit in a fixed space called the <em>context window</em>. Too little and it’s clueless; too much and the important part drowns in noise.</li></ul><p>A forgetful engine, working on a small desk. Hold that picture.</p><h3>From answering to acting</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ySShbYvvaLzCZUJgVgocLw.png" /></figure><p>A plain chatbot takes your message and gives one reply. That’s the entire transaction.</p><p>An agent is built around something larger: a <strong>goal</strong>. Instead of replying once, it keeps working until the goal is met. To pull that off, it needs three ingredients.</p><ul><li><strong>A goal</strong> — the outcome it’s aiming for. “Fix the failing test,” not “tell me about the failing test.”</li><li><strong>A loop</strong> — it doesn’t answer once; it cycles: think, act, look at the result, decide what’s next, repeat.</li><li><strong>Tools</strong> — ways to actually <em>do</em> things instead of just talking: read a file, run a command, search the web, call a service.</li></ul><blockquote>A chatbot holds a conversation. An agent works through a checklist.</blockquote><p>That’s the shift in a single line. Everything else is detail.</p><h3>The loop, made concrete</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Q7RE0ZUz9a01NvHKjUS23Q.png" /></figure><p>Say the goal is “find and fix a broken link on my website.” The agent doesn’t answer in one breath. It moves in steps:</p><ol><li><strong>Plan</strong> — work out what “broken link” means and how to check.</li><li><strong>Act</strong> — run a tool that scans the pages.</li><li><strong>Observe</strong> — read what came back: one link returns a 404.</li><li><strong>Decide</strong> — find that link in the source and correct it.</li><li><strong>Check</strong> — scan again to confirm nothing’s broken.</li><li><strong>Stop</strong> — goal met, so it ends.</li></ol><p>Step 3 is the interesting one. <em>Observing</em> — reacting to real results instead of guessing — is where an agent earns its keep, and also where it goes wrong. Misread a result and the whole loop heads down the wrong road.</p><h3>Why the window is the real ceiling</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HKqVOR7qtX7MQpKTy8P_pw.png" /></figure><p>Now those two limits come due.</p><p>Every pass through the loop piles more onto that small desk: the original plan, the output of each tool, the growing record of what it has already tried. On a short task, no problem. On a long one, the desk fills up.</p><p>When it does, the agent slips. It forgets a decision from twenty steps ago. It drifts from the goal. It repeats work it already finished.</p><p>None of this is the model getting “dumber.” It’s the working memory overflowing, and older context getting crowded out. Deciding what deserves a place on that crowded desk turns out to be <em>the</em> core skill of working with these systems. It has a name — <strong>context engineering</strong> — and it’s a story for the next piece.</p><h3>What an agent is not</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gG0wvLQsiiPHpsYr4ZmLIw.png" /></figure><p>A few myths cause most of the confusion:</p><ul><li><strong>Not conscious.</strong> No intentions, no understanding. A prediction loop with a goal bolted on.</li><li><strong>Not infallible.</strong> It can take a confident, completely wrong step — then build on it.</li><li><strong>Not meant to run unwatched.</strong> Good setups keep humans at the checkpoints that matter, especially before anything irreversible.</li></ul><p>Picture a tireless junior worker: fast, capable, occasionally confidently wrong, and in need of review. That gets you far closer than “genius” or “toy.”</p><h3>Where this leaves us</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WD6RM8AcSY0p6KysKjWZrQ.png" /></figure><p>An agent is less exotic than the word suggests. A prediction engine, pointed at a goal, running in a loop, reaching for tools — and boxed in by a forgetful, finite memory.</p><p>Which raises the obvious next question: an agent is only as good as the tools it can actually reach. So how do you hand it those tools — and is there a standard way to do it?</p><p>That’s where we go next. If you’ve worked with an AI agent that surprised you — for better or worse — I’d love to hear what it did.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7a7264e2ecc5" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>