sethserver.com Subscribe
An orange cartoon robot with spiral ears and an antenna is working on its own exposed chest cavity filled with colorful circuit boards and components, using tools from a white tray below. The background is split between cyan (top) and orange (bottom) sections.

Next-Level Self-Healing: Building Agents That Fix Their Own Bugs

By Seth Black • Updated: September 17, 2026

AI · 3 min read

Like this kind of writing? Get one email a week with notes on startups, AI, and the occasional strong opinion about Python: subscribe to the newsletter.

I like "vibe coding" as much as anyone. You toss a prompt into an LLM, it spits out code, and you squint at it wondering if it'll work. Sometimes it does. Sometimes it invents a library that has never existed on this planet, solar system, and probably multiverse. That's how you learn the word hallucination.

Early ChatGPT 3.5 made this worse because the context window was tiny. You'd paste in a stack trace and the model would lose the top half before it reached the bottom. The first time it confidently stated a "fact" that was completely fake, it was clarifying. I stopped treating the model like a coworker and started treating it like a tool with sharp edges.

The next step past vibe coding is self-correction. Not the model apologizing ...it does that already! I mean an agent that runs commands, hits a wall, reads the error, fixes itself, and tries again-without you having to click "try again, dummy."

From "hands" to logic: why OpenClaw-style control matters

If you've played with OpenClaw-style architectures, you know the big idea: give the agent "hands." Let it operate a real shell, a real filesystem, real tools. That's where bugs stop being abstract and start being undeniable.

Agents don't need more personality. They need feedback loops.

A loop that looks like this:

  1. Generate a command or code change
  2. Run it in a real PTY/bash shell
  3. If it fails, capture stderr + stack trace
  4. Ask a "Critic" to diagnose the failure
  5. Patch and retry
  6. Stop only after a clean run or a hard limit

At that point, it stops being a demo and becomes a system.

The orchestrator: LiteLLM + a Builder/Critic split

The Builder/Critic pattern works because it's iterative and it stays anchored to what actually happened. Coding quizzes taught me that people can charm their way through a narrow test. Terminals don't care.

LiteLLM is handy here because it normalizes providers. You can use one model to build and another to critique without rewriting your stack every time a vendor tweaks their API.

A rough sketch:

from litellm import completion

def call(model, messages):
    return completion(model=model, messages=messages).choices[0].message["content"]

builder_model = "gpt-4.1-mini"
critic_model  = "claude-3.5-sonnet"

Then you wire the loop.

The reflection pattern (the part that actually matters)

The agent needs to see the raw failure. Not your summary. The actual error output.

import subprocess, textwrap

def run(cmd):
    p = subprocess.run(cmd, shell=True, capture_output=True, text=True)
    return p.returncode, p.stdout, p.stderr

def reflect(task, cmd, stdout, stderr):
    prompt = f"""
Task: {task}

Command attempted:
{cmd}

STDERR:
{stderr}

Fix the issue. Output a corrected command or a patch.
"""
    return call(critic_model, [{"role":"user","content":prompt}])

Now the agent reacts to reality instead of guessing.

The best part is that most failures are boring. Missing dependency. Wrong path. Bad quoting. Off-by-one. The kind of stuff that burns time because humans are also juggling Slack, CI noise, and half-finished context.

Source of truth: put the whole messy loop in S3

If you don't store iterations, you get a vibe coding hangover. You end up with working code and no idea why it works or what changed.

This is also how fake "AI automation" happens. I worked at a SaaS shop that sold "AI magic," and a chunk of it was spreadsheet column mapping and data formatting. The support team told me to watch them do it. It was Excel with extra steps. That kind of thing scales right up until it doesn't.

So: store every attempt. Store the inputs, outputs, diffs, and the final validated artifact. S3 works. Boring is good.

A simple key scheme:

Now you have an audit trail and a clean "blessed" output that your production system can trust.

Next: physical systems that can recover

I want to push this pattern into robotics and puzzle-like systems. Escape rooms with agents. Props that can tell they failed, figure out why, and retry. Also: small language models on phones, and small robots running on small AI chips. A Jetson strapped to a tiny server stack can do real work if the software doesn't give up on the first error.

Self-healing agents are the next step. Less guessing, more verification.

-Sethers

Share this post
Newsletter

One email, once a week.

Notes on databases, systems, and the occasional strong opinion about Python. No spam, unsubscribe anytime.

Seth Black
Written by

Seth Black

Engineer and founder based in Texas. Writes about databases, AI, and running things in production. Embeds in small teams as lead engineer.

More from AI

View all →
AI

How to be a Good Farrier: What the Car Teaches Us About AI and Your Job

Nov 10, 2026
AI

Principle of Least Privilege in the AI Age

Apr 14, 2026
AI

How to Actually Secure MCP (Model Context Protocol)

Apr 14, 2026