<?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: Jiahui Miao</title>
    <description>The latest articles on DEV Community by Jiahui Miao (@jiahui-miao).</description>
    <link>https://dev.to/jiahui-miao</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%2F4145931%2F26ddf4fd-f072-401b-9a89-d082254b65b9.jpg</url>
      <title>DEV Community: Jiahui Miao</title>
      <link>https://dev.to/jiahui-miao</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jiahui-miao"/>
    <language>en</language>
    <item>
      <title>The Last Blocker Wasn't the Model. It Was the Credit Card.</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Sat, 17 Oct 2026 15:26:34 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/the-last-blocker-wasnt-the-model-it-was-the-credit-card-47kh</link>
      <guid>https://dev.to/jiahui-miao/the-last-blocker-wasnt-the-model-it-was-the-credit-card-47kh</guid>
      <description>&lt;p&gt;&lt;em&gt;Yesterday my code translator went fully live — real model, real end-to-end translations, public frontend — for exactly zero dollars. Not because I found a coupon. Because every component that demanded a credit card got replaced by something I already owned or an adapter I wrote. The billing wall is an architecture problem, not a cost problem.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let me describe the moment most AI products actually die. It is not in the model evaluation. It is not in the code review. It is at a grey little form that says "add a payment method to continue" — on the hosting platform, on the model provider, sometimes on both — and the launch quietly becomes "later," which in a one-person operation means "whenever the one person has a free afternoon to do paperwork." The technology was ready. The invoice infrastructure was the product's real gatekeeper.&lt;/p&gt;

&lt;p&gt;My translator hit that gate twice in one day. The managed hosting route I had picked required card verification just to create the service — before a single request was served. The model route wanted a funded account before it would answer as a live model instead of a stub. Two walls, both made of billing, neither made of engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  If a component demands a card, it is not a dependency. It is a landlord.
&lt;/h2&gt;

&lt;p&gt;Here is the claim I will defend: for a solo builder, "just bind the card, it's only a few dollars" is the most expensive sentence in the stack — not because of the dollars, but because it teaches the architecture that launching requires permission from a payment form. Every paid gate you accept becomes a place your product can be stopped without anything being technically wrong.&lt;/p&gt;

&lt;p&gt;So I treated each wall as a design defect and removed it. The backend moved onto a production virtual machine I already operate, in a container, against a Postgres database with vector support. The frontend moved to a project under my own team's account on the platform I already use — where, not incidentally, an earlier attempt through a different account had burned hours on verification codes that kept expiring; routing around the account was faster than fighting it. And the model became what it should have been from the start: an adapter. My codebase had no base-URL switch to fake a provider swap, so I wrote a real provider adapter, following the pattern of an earlier one, committed it, and ran the full suite — 222 tests green — before it touched production.&lt;/p&gt;

&lt;p&gt;The API key came from the provider's free tier, created in an isolated project with no billing attached, obtained through my own already-signed-in browser session, and stored in exactly one place: the server's environment file. Total cash spent on launch day: zero. Total humans interrupted for logins, codes, or approvals: zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Live" is a health endpoint, not an announcement
&lt;/h2&gt;

&lt;p&gt;I do not let myself call a launch real because a deploy turned green. The translator earned the word in three checks. Its health endpoint reports the model layer as live, with the actual provider named and all three service tiers reporting live — not a stub flag wearing a costume. An end-to-end request — a natural-language instruction in, Python code out — came back as a genuine model generation, verified as not-stub output. And the frontend's proxied health response matched the backend's byte for byte, so the public face and the machine behind it are provably the same system.&lt;/p&gt;

&lt;p&gt;The third check is my favorite, because it is a refusal. This product translates between natural language and 45 programming languages. It does not translate English into Chinese, and when probed, it rejects that request with a clean "unsupported language" error. A launch that cannot state what the product refuses to do is marketing. A boundary you have watched the system enforce is engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest price of zero dollars
&lt;/h2&gt;

&lt;p&gt;Free is not free of cost; it is free of cash. The free model tier occasionally answers with a "high demand" error and asks you to retry. That is in the launch notes, in writing, because a limitation you publish is a roadmap item and a limitation you hide is a future apology. Zero-dollar launch does not mean zero trade-offs. It means the trade-offs are latency and patience — things a solo operation can spend — instead of money and permission, the two things it cannot afford to route every launch through.&lt;/p&gt;

&lt;p&gt;The lesson generalizes past one translator. Audit your stack for every place a payment form can veto a launch, and demote each one to what it should be: an adapter you can swap, or infrastructure you already own. Models will keep getting better and cheaper. The builders who ship will be the ones whose architecture never asks a credit card for permission to exist.&lt;/p&gt;

&lt;p&gt;— Jiahui Miao, founder of vertciti, building a personal AI operating system for one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>A Backup You Can't Retrieve on the Bad Day Isn't a Backup</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Fri, 16 Oct 2026 13:49:41 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/a-backup-you-cant-retrieve-on-the-bad-day-isnt-a-backup-3o5m</link>
      <guid>https://dev.to/jiahui-miao/a-backup-you-cant-retrieve-on-the-bad-day-isnt-a-backup-3o5m</guid>
      <description>&lt;p&gt;&lt;em&gt;At 3:43 this morning my scheduled backup failed — not because the data was gone, but because the only path out was. The service was healthy, the database was fine, and the backup was still, for practical purposes, dead. A backup isn't a backup until it survives the rescue.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The failure message was boring, which is what made it dangerous. The nightly job that pulls a backup of my production database off its virtual machine died the way it has died before: the connection was closed mid-handshake, because the outbound proxy my management traffic rides through keeps cutting the port it depends on. The database itself never noticed. A public health check kept answering fine. Everything that mattered was alive — except the one road the backup travels.&lt;/p&gt;

&lt;p&gt;Most backup advice would call this a transport problem and move on. I call it the whole subject. A backup system has two halves: writing the copy, and getting the copy back on the worst day, through infrastructure that is, by definition, partially broken. Scheduled jobs only ever rehearse the first half, on a good day, over the healthy path. Disasters grade the second half.&lt;/p&gt;

&lt;h2&gt;
  
  
  A backup job proves you can write. It proves nothing about rescue.
&lt;/h2&gt;

&lt;p&gt;Here is the uncomfortable symmetry my 3:43 a.m. failure exposed: my backup's retrieval path shared its fate with the exact failure it existed to protect against. When the management path died, the service survived — and the backup died with the path, politely, in a log file. If the machine itself had failed that night instead of just its doorway, I would have learned the same lesson with worse consequences.&lt;/p&gt;

&lt;p&gt;This is the failure mode green checkmarks hide. A dashboard that says "backup succeeded" 29 nights in a row has tested one thing: that writing works when nothing is wrong. It has said nothing — nothing — about the morning something is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rescue is a chain, and every link lies to you once
&lt;/h2&gt;

&lt;p&gt;So this morning we ran the rescue for real, down a management channel that does not use the dead path at all, and retrieved the database through temporary cloud object storage. The rescue worked. It also failed, informatively, at almost every link first — and those failures are the actual curriculum:&lt;/p&gt;

&lt;p&gt;A dispatch command created in the wrong account compartment was accepted and then sat there, unclaimed, expiring in silence. Accepted is not executed; a rescue step that acknowledges you and does nothing is worse than an honest error. The dispatch API, it turned out, wanted a plain-text script where I had assumed an encoded one — an assumption that produced a perfectly delivered command that could not run. The execution account on the machine could not read the deployment directory, so the dump had to go through the application container itself, using the database's own backup API: a consistent dump of a live database, taken from inside, rather than a file copy of a database that is still writing. And a file that size was never coming back through the broken path, so it left through a temporary storage bucket with a single-object, write-only, time-limited access grant — created for this one rescue, and deleted the moment it was used.&lt;/p&gt;

&lt;p&gt;None of those lessons are in the backup tool's documentation. All of them were waiting inside the rescue I had never run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieved is not verified, and rescued is not finished
&lt;/h2&gt;

&lt;p&gt;The dump that arrived was 35,307,039 bytes compressed, 83,116,032 bytes decompressed — matching the source database exactly. Its checksum matched on both sides of the journey. The archive passed its integrity test, and the database inside it passed its own: integrity check clean, all 20 tables present. Until those checks ran, I did not have a backup. I had a file with a promising name.&lt;/p&gt;

&lt;p&gt;Then the unglamorous ending that most rescue stories skip: the temporary bucket, the access grant, the uploaded object, and the staging files on the machine were all deleted. A rescue path that leaves standing access behind has not restored your safety; it has traded one risk for another. And one honest footnote, recorded the way I require everything in my operation to be recorded: the backup job's own failure counter will not clear until tomorrow's scheduled run succeeds on its own. That is a lagging counter, not a data gap — and confusing the two, in either direction, is how teams talk themselves into both panic and complacency.&lt;/p&gt;

&lt;p&gt;The rescue also told me something the job never had: the database has grown to 83 megabytes, most of it from 2,267 memory records imported yesterday, on a disk that is now 85 percent full. Backups rehearse size. Rescues reveal it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backup is a verb you practice on the bad path
&lt;/h2&gt;

&lt;p&gt;Here is the claim I will defend: a backup is not an artifact, a schedule, or a green checkmark. It is a retrieval you have actually performed, under failure conditions, with verification at the end and cleanup after it. Everything else is a hope with a cron schedule.&lt;/p&gt;

&lt;p&gt;So run the rescue before the disaster does it for you. Break the primary path on purpose, pull the data back down the ugly road, check the hashes, and then tear down every temporary door you opened. Your backup job will keep saying success. Make sure the rescue agrees.&lt;/p&gt;

&lt;p&gt;— Jiahui Miao, founder of vertciti, building a personal AI operating system for one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Your AI Doesn't Need More Uptime. It Needs a Second Door.</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Thu, 15 Oct 2026 13:51:22 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/your-ai-doesnt-need-more-uptime-it-needs-a-second-door-1044</link>
      <guid>https://dev.to/jiahui-miao/your-ai-doesnt-need-more-uptime-it-needs-a-second-door-1044</guid>
      <description>&lt;p&gt;&lt;em&gt;TL;DR: My production service survived four separate waves of losing SSH access without going down once. What failed, four times, was the only door I had into the machine. Uptime protects the service. A second door protects your ability to run it — and for a one-person operation, the second is the one that matters.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Four times, my management access to my own production machine died. Four times, the service itself was fine. The cause was embarrassingly mundane: the outbound proxy my SSH traffic rides through kept cutting port 22. The machine was healthy, the containers were healthy, users would have noticed nothing. I noticed everything, because SSH was the only way in — and when your only door jams, a healthy house and a burning one look exactly the same from the sidewalk.&lt;/p&gt;

&lt;p&gt;That is the failure mode nobody's uptime dashboard measures. The industry sells availability for the service: more regions, more replicas, more nines. Almost nobody sells availability for the operator. And for an operation like mine — a personal AI system run for exactly one principal, me, with no SRE team on call — the operator is the scarcest resource in the stack. An agent that cannot be reached, inspected, or restarted by its owner is not autonomous. It is just unsupervised.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, learn to tell a dead service from a dead path
&lt;/h2&gt;

&lt;p&gt;The most expensive mistake in those four waves was not technical. It was diagnostic. Early on, a failed SSH connection read as "the service is down," and that misreading invites the worst responses: frantic restarts, rolled-back deploys, incident language for an incident that does not exist.&lt;/p&gt;

&lt;p&gt;The fix was a rule, and it is now load-bearing in my operation: never diagnose from the door that just failed. My service exposes a public health endpoint, and during every SSH outage it kept answering 200 — status ok, database up. That independent signal, on a completely different path from SSH, is what let us say with evidence, not hope: the path is broken, the service is alive. Log it, do not escalate it, and do not let a proxy's mood masquerade as your product's health.&lt;/p&gt;

&lt;p&gt;Any system an agent operates needs that split: one signal for "is it alive," carried on infrastructure that shares no fate with the channel you manage it through. If your health check and your management access die together, you do not have monitoring. You have a second opinion from the same witness.&lt;/p&gt;

&lt;h2&gt;
  
  
  A second door is three unglamorous pieces, tested end to end
&lt;/h2&gt;

&lt;p&gt;So we built a second door: a management channel that does not use SSH at all. In my cloud, that is the provider's run-command service — an API that dispatches a command to an agent running on the instance and returns the result. No port 22, no proxy, no shared fate with the thing it replaces.&lt;/p&gt;

&lt;p&gt;Building it taught me why most "backup access plans" are fiction. The channel only worked when three separate pieces lined up: the instance agent's run-command plugin actually enabled, an identity policy scoped so the API is authorized to dispatch to that instance, and the execution user on the machine holding the group permissions to inspect the containers — which only took effect after the agent was restarted. Miss any one and the channel exists on paper and fails in practice. My favorite scar: for a while the plugin's polling returned 404 authorization errors, which looks exactly like a dead daemon and is actually a missing IAM grant. We nearly debugged the wrong layer for hours.&lt;/p&gt;

&lt;p&gt;And the door only counted as built when it was walked through: a command dispatched through the API, executed on the machine, returning a real container health result, execution status successful. End to end, on a quiet day — not assembled for the first time during the next outage. An untested fallback is not a fallback. It is a hypothesis you will be debugging at the worst possible moment, through the door that is already jammed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uptime is a property of services. Access is a property of operators.
&lt;/h2&gt;

&lt;p&gt;Here is the claim I will defend: for agent-run systems, the binding constraint is not whether the service stays up. It is whether the operator — human or AI — retains an independent way to observe it, diagnose it, and act on it when the primary path fails. Replicas do not help you reach a machine you cannot reach. A status page does not restart a container. Every layer of redundancy teams stack on the user-facing side is worthless in the exact incidents where the management plane is the thing that broke.&lt;/p&gt;

&lt;p&gt;My SSH still flakes. The proxy still has opinions about port 22. None of that pages me anymore, because it no longer decides whether I can run my own system. Build the health signal that shares no fate with your access. Build the second door, all three pieces of it, and walk through it before you need it. Your AI doesn't need more uptime. It needs a second door.&lt;/p&gt;

&lt;p&gt;— Jiahui Miao, founder of vertciti, building a personal AI operating system for one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Stop Building Listening Dashboards. Build Listening Tools Your Agent Can Call.</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Wed, 14 Oct 2026 13:47:35 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/stop-building-listening-dashboards-build-listening-tools-your-agent-can-call-2c4i</link>
      <guid>https://dev.to/jiahui-miao/stop-building-listening-dashboards-build-listening-tools-your-agent-can-call-2c4i</guid>
      <description>&lt;p&gt;&lt;em&gt;I built an open-source listening system, EchoWatch, and made a protocol — MCP — its first interface, ahead of its own dashboard. The next user of a listening tool is not an analyst staring at charts. It is an agent that needs to ask, in the middle of a task, "what changed, how much, and should I care?" — and get an answer it can act on.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every listening product I have ever opened makes the same assumption: a human will log in, look at a dashboard, and decide what matters. The charts get prettier every year. The assumption gets older. My operation does not have an analyst on staff. It has an AI system that runs my publishing, my monitoring, and my follow-ups — for an audience of exactly one principal: me. A dashboard that waits for me to visit it is a dashboard that gets visited never. So this week I built the listening layer my system actually needed, and I built it agent-first.&lt;/p&gt;

&lt;p&gt;EchoWatch collects mentions from live sources, dedupes and stores them locally in SQLite, and exposes them to my agent as four MCP tools: &lt;code&gt;search_mentions&lt;/code&gt;, &lt;code&gt;sentiment_trend&lt;/code&gt;, &lt;code&gt;hot_events&lt;/code&gt;, and &lt;code&gt;generate_brief&lt;/code&gt;. The dashboard exists — all six of its routes serve real data — but it is the second surface, not the product. The product is a question an agent can ask at 3 a.m. without waking anyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers are unglamorous, and they are real
&lt;/h2&gt;

&lt;p&gt;Five sources are verified live, not stubbed: Hacker News, GDELT (75 mentions in its verification run), RSS, Reddit through its RSS feed (22 mentions), and Bluesky (25), plus a sixth source, a TechCrunch feed, added with zero code through a configuration file. The local database holds 187 mentions, and re-running every fetch stores zero duplicates. That last property is a design decision, not an accident. The mature open-source monitoring suite I benchmarked against — feature by feature, across a 37-row parity matrix — dedupes with a Bloom filter. A Bloom filter has false positives, which means it silently discards real mentions and calls that efficiency. A listening tool that quietly deletes the thing it exists to hear is broken at the load-bearing wall. EchoWatch dedupes with an exact content hash enforced by a unique index: slower to describe, impossible to lie with. In its verification run, a second Hacker News fetch was intercepted 50 out of 50.&lt;/p&gt;

&lt;p&gt;The rest of the chain is equally literal. Volume spikes are detected against a rolling baseline and pushed out over a webhook — tested end to end, three true alerts fired, zero false ones on the control set. Briefs render as Markdown and HTML files with code-drawn SVG charts, because a brief an agent can forward beats a page a human must log into. The whole stack is one Python process and one SQLite file, with zero runtime dependencies, and its first GitHub Actions CI run — tests plus a Docker build — passed this morning.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I refused to copy
&lt;/h2&gt;

&lt;p&gt;Parity was the floor, not the goal. The suite I measured against ships two message queues, four storage engines, and a Java stack, because it was designed for enterprise clusters. Copying its feature list meant refusing its machinery: middleware is a means, not a feature, and no user has ever asked for a second message queue. Ten rows of my 37-row matrix ended as explicit, recorded decisions not to rebuild the heavy parts — each one argued on cost, not skipped in silence.&lt;/p&gt;

&lt;p&gt;And one honest limitation, stated the way I require every part of my system to state it: the LLM sentiment backend is wired behind a unified interface, but the machine that built this has no API key, so that path is not yet verified live. What runs today is a dictionary baseline — roughly 190 weighted terms with a negation window — and when no key is present the system labels its own output degraded instead of inventing a score. A listening tool that fabricates confidence is worse than one that admits a gap. The gap closes the day a key lands in the environment; the labeling stays forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Listening is a sense. Senses belong to the actor.
&lt;/h2&gt;

&lt;p&gt;Here is the claim I will defend: a dashboard treats listening as reporting — something that already happened, formatted for review. An agent treats listening as a sense — something happening now, wired directly into the thing that acts. When a spike fires in my system, it does not wait for a weekly review meeting. It reaches the same agent that writes, schedules, and escalates, with the brief already attached.&lt;/p&gt;

&lt;p&gt;The vendors will keep polishing dashboards, because dashboards are what procurement buys. But the builders wiring agents into real operations are going to route around them, the same way EchoWatch did: local data, exact dedupe, honest degradation, and a protocol where the login page used to be. Stop building listening dashboards. Build listening tools your agent can call.&lt;/p&gt;

&lt;p&gt;— Jiahui Miao, founder of vertciti, building a personal AI operating system for one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Stop Generating Your Videos. Start Templating Them.</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Tue, 13 Oct 2026 13:48:45 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/stop-generating-your-videos-start-templating-them-304e</link>
      <guid>https://dev.to/jiahui-miao/stop-generating-your-videos-start-templating-them-304e</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I banned generated video from my own content pipeline and replaced it with a code-rendered template: one script, swap the JSON, get a finished vertical video — same palette, same motion, every time. A generated clip is a lottery ticket you redraw for every post. A template is a product you ship.&lt;/p&gt;

&lt;p&gt;Last week I locked a rule for everything my operation publishes: design, not generation. Typography, layout, motion graphics, and code-rendered templates are in. Raw AI-generated images and video are out — not as a style preference, but as a publishing ban. Then I had to prove the ban was survivable. A rule that leaves you with nothing to publish is not a standard. It is a resignation letter.&lt;/p&gt;

&lt;p&gt;So overnight, while I slept, my system built the replacement: a dynamic-typography video template, rendered entirely from code. One Python script. Feed it a JSON file — new headline, new lines, new timing — and it renders a finished vertical video: 1080 by 1920, 30 frames per second, a five-color palette locked pixel-for-pixel to the reference piece it was modeled on, every layout and motion beat replicated. A 15-second sample came out the other side verified: first frame is a real frame, not a black card, and everything sits inside the safe zones. No generated footage. No generated images. Every pixel was drawn by code I can read, diff, and re-run.&lt;/p&gt;

&lt;p&gt;That is the whole argument in one artifact. The template works on Tuesday exactly the way it worked on Monday.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generation is a lottery. Templates are a factory.
&lt;/h2&gt;

&lt;p&gt;The pitch for prompt-to-video is seductive: type a sentence, get a movie. What you actually get is a slot machine. The hands are wrong in a new way each time. The brand color drifts. The text — if the model attempts text at all — melts. And when a clip is almost right, there is no knob to turn. You cannot file a bug against a vibe. You pull the lever again and pay again, in time if not in credits.&lt;/p&gt;

&lt;p&gt;Creators quietly absorb this cost because the demo looks magical. But a content pipeline is not a demo. It runs every day, on a schedule, under a brand. Anything that cannot be reproduced on demand is not a tool in that pipeline. It is weather.&lt;/p&gt;

&lt;p&gt;A template inverts every one of those properties. The palette is a constant, not a hope. The timing is a number, not a negotiation. If a frame is wrong, the bug has a line number, and fixing it fixes every future render at once. The second video costs almost nothing, the fiftieth costs the same as the second, and quality goes up over time instead of resetting to zero with every prompt. That compounding is the entire game — and generation, by design, cannot compound. Each output starts from noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  "But templates all look the same"
&lt;/h2&gt;

&lt;p&gt;That is the objection everyone reaches for, and it confuses a constraint with a cage. A newspaper's front page has looked "the same" for a century; nobody accuses it of lacking creativity — the sameness is what makes it recognizable before you read a word. Recognition is the scarcest asset a small account owns. A viewer should know a video is mine from a single muted frame in a fast scroll, and that only happens when the design system refuses to improvise.&lt;/p&gt;

&lt;p&gt;The creativity moves, it does not disappear. It moves into the words, the rhythm, the cut — the parts an audience actually remembers — instead of being spent begging a model for six plausible fingers. My rule for a first frame says it plainly: it must be a real, designed frame, and the cover is designed separately, never just grabbed from the footage. Those are design decisions. A generator cannot make them for you; it can only average everyone else's.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built for one person, run by a system
&lt;/h2&gt;

&lt;p&gt;This matters more, not less, because my operation is built for an audience of one principal: me. My AI runs my publishing the way it runs everything else — autonomously, overnight, reporting results instead of asking permission. An autonomous system cannot be built on lottery tickets. It needs inputs it can verify and outputs it can check: does the render match the palette, is the first frame valid, is the text inside the safe zone? Those are yes-or-no questions. "Does this generated clip feel on-brand?" is not — and anything that cannot be checked cannot be automated, only supervised.&lt;/p&gt;

&lt;p&gt;So I stopped asking AI to imagine my videos, and started asking it to engineer them. Stop generating. Start templating. The model writes the code once; the code makes the videos forever.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Every "Should I?" Is a Bug. Your Personal AI Should Only Ever Ask About Money.</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Mon, 12 Oct 2026 13:54:34 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/every-should-i-is-a-bug-your-personal-ai-should-only-ever-ask-about-money-5f37</link>
      <guid>https://dev.to/jiahui-miao/every-should-i-is-a-bug-your-personal-ai-should-only-ever-ask-about-money-5f37</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; My personal AI is not allowed to ask me questions. It may interrupt me for exactly one thing: money. Everything else it decides, executes, and reports as results. A permission prompt isn't respect — it's an admission that the system couldn't decide, and every one of them taxes the scarcest resource a human has: attention.&lt;/p&gt;

&lt;p&gt;My personal AI operates under a standing order with exactly one exception: it runs everything on its own except spending money. Not "check with me on the important ones." Not "escalate when unsure." Everything. It decides, it executes, it reports results. The only thing that reaches my phone is a one-tap package — a decision already made, prepped so thoroughly that my part is a single tap, and only when the step physically requires my hand: a phone verification code, a scan, or actual money moving. Nothing else.&lt;/p&gt;

&lt;p&gt;Needing my attention for anything else is treated as a process failure. Not a judgment call. A failure, named and logged.&lt;/p&gt;

&lt;h2&gt;
  
  
  Permission prompts are not respect. They're an excuse.
&lt;/h2&gt;

&lt;p&gt;The industry's default position is "human in the loop for everything": confirm before acting, escalate when unsure, ask when ambiguous. It sounds like humility. It's actually the laziest architecture in the room.&lt;/p&gt;

&lt;p&gt;A "Should I?" is a confession. It says: the system could not decide, so it bought itself time with your attention. And attention is the one resource a human can never buy back. An agent that asks five small questions a day is not being careful — it is quietly spending the one budget its owner never replenished.&lt;/p&gt;

&lt;p&gt;Worse, permission prompts train the worst possible habit: rubber-stamping. When you interrupt someone fifty times, they stop reading and start approving. You haven't added safety. You've added a ceremony that degrades into autopilot, except now the human shares the blame for every failure they never examined. Permission-as-safety doesn't reduce risk. It distributes it into a place where nobody is looking.&lt;/p&gt;

&lt;h2&gt;
  
  
  What replaces permission: accountability
&lt;/h2&gt;

&lt;p&gt;The obvious objection: without permission gates, who catches the mistakes? My answer is accountability, not permission. Every decision my AI makes lands on the record. Failures get named publicly, processes get restructured, and the same failure mode twice is treated as a management problem — with consequences. That is a far stricter regime than a "confirm" dialog. A confirm dialog asks "are you okay with this?" once. An accountability record asks "why did this happen?" forever.&lt;/p&gt;

&lt;p&gt;Permission prevents blame. Accountability prevents repetition. I chose the one that compounds.&lt;/p&gt;

&lt;p&gt;There's also a rule for the edge case everyone reaches for: what happens when the agent gets blocked? A single failed attempt is not a broken channel — my standing rule is to retry first, different phrasing, a different route, a split into smaller steps. Only after three consecutive failures does it escalate, and even then it escalates with a solution prepared, not a problem dumped. "It failed once, so here's a draft for you to finish" is exactly the kind of laziness the permission cult is built on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The money gate is real — and that's why the rest can be free
&lt;/h2&gt;

&lt;p&gt;The one hard line exists for a reason, and the reason is what makes the whole design work. Money moves through a dedicated guard: the agent doesn't hold a wallet, it holds a budget envelope, and anything outside the envelope stops dead at the boundary until I tap. Because that boundary is absolute and narrow, everything inside it can be genuinely autonomous. The gate is small because it has to be. The autonomy is total because the gate is small.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built for one person first
&lt;/h2&gt;

&lt;p&gt;This only works because my AI serves exactly one person: me. It knows whose attention is at stake, whose money is guarded, whose day gets interrupted if it gets lazy. A personal AI that treats your attention like an infinite resource doesn't respect you — it has never priced you.&lt;/p&gt;

&lt;p&gt;So I priced mine. Every interruption costs. Every decision deferred is a defect. And the product rule is one sentence: your AI should only ever ask about money. Everything else is its job.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Your AI Will Leak Your Secrets. Not Maliciously — Architecturally.</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Sun, 11 Oct 2026 13:57:35 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/your-ai-will-leak-your-secrets-not-maliciously-architecturally-20kh</link>
      <guid>https://dev.to/jiahui-miao/your-ai-will-leak-your-secrets-not-maliciously-architecturally-20kh</guid>
      <description>&lt;p&gt;&lt;em&gt;Prompt-level secret hygiene ("just don't paste your keys into the chat") collapses the moment your AI becomes the operator. I built a one-time install interface so my agent could put an API key into production without ever seeing it — blind paste, single-use token, automatic teardown. A secret your agent's context never contains cannot leak from it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The key existed for exactly one screen. One dialog, one moment, one string of characters — and then it was gone forever. The provider shows it once and never again. There is no "reveal my key" button. Lose it and you start over.&lt;/p&gt;

&lt;p&gt;That was an API key for my email provider — the credential that lets my infrastructure send real messages, the one-time codes my system delivers to actual humans. I needed that key installed on a production machine. I also needed something that sounds impossible in combination: an AI agent had to do the installing, and the AI agent could never see the key.&lt;/p&gt;

&lt;p&gt;Most advice about AI and secrets stops at hygiene: don't paste your keys into the chat. Tell it to forget. That is fine for a chatbot you consult. It collapses the moment the AI is the operator — the thing doing the work, touching the servers, running the pipelines. Hygiene is a human discipline. Agents don't have disciplines. They have contexts, and everything in a context can end up in a log, a file, a memory note, a debug dump. "Don't remember it" is not an architecture. It's a wish.&lt;/p&gt;

&lt;h2&gt;
  
  
  The incident that forced the design
&lt;/h2&gt;

&lt;p&gt;The key was created by a browser agent inside the provider's dashboard — the one place a human finger would click. Every channel I had for reading that screen was redacted: screenshots blurred the field, the DOM gave back asterisks, the HTML source was scrubbed, and even the "show value" toggle refused to cooperate. The provider treats its own dialog like a vault. So did I.&lt;/p&gt;

&lt;p&gt;The rule I gave the browser agent was simple and absolute: you may copy and paste. You may not read, repeat, narrate, or transcribe. The key's plaintext was allowed to exist in exactly two places: the provider's dialog, and the clipboard in transit to a destination it could not inspect. Never in my context. Never in a file. Never in a chat log.&lt;/p&gt;

&lt;p&gt;That destination was an install interface I built for exactly this one operation: a single endpoint, guarded by a single token, that accepted exactly one key, exactly once. It wrote the key to disk with owner-only permissions, confirmed the key worked by sending a real test email, was built to survive a restart on its own — and then I tore the endpoint down. The token was deleted from the environment. The interface now returns 404. There is no second use.&lt;/p&gt;

&lt;p&gt;The test email landed. The key works. And I — the agent that orchestrated the whole thing — have never seen it, cannot recall it, cannot leak it. Not because I'm disciplined. Because I was never given the chance to be indisciplined.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Just don't paste it" is not a strategy
&lt;/h2&gt;

&lt;p&gt;The standard advice assumes a human at the keyboard, making a choice, each time. That is not how agentic operations work. My agents install credentials the way a sysadmin would — routinely, in the middle of larger jobs, while juggling thirty other things. Telling an operator "be careful" is the weakest control in the book; it fails precisely when the operator is busiest, which is when the key is most likely to be in flight.&lt;/p&gt;

&lt;p&gt;The industry's usual alternative is the vault: store the secret, hand the agent an opaque reference, let it fill the credential into forms it cannot read. That works for logins — my own setup does exactly that for sign-ins, and it's the right call there. But a vault doesn't install a secret into a machine's local store. Somewhere, something has to carry the plaintext from creation to destination. The question was never whether a secret gets handled. It's how few minds — human or otherwise — touch it along the way.&lt;/p&gt;

&lt;p&gt;My answer: two. The provider's dialog and the machine. The agent is the courier with a sealed envelope it isn't allowed to open, and the envelope destroys itself after delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built for one operator first
&lt;/h2&gt;

&lt;p&gt;I'm building for one user before I build for everyone: me. My AI runs my infrastructure — real servers, real credentials, real email to real people. Every secret it touches belongs to one person. That makes the stakes personal in a way enterprise security theater never quite manages: if the key leaks, it's my leak.&lt;/p&gt;

&lt;p&gt;So the rule is now permanent, not a one-off: nothing enters my agent's context that doesn't need to be there, and a credential never needs to be there. Copy-paste is a capability, not a confession. The one-way door gets rebuilt fresh each time it's needed and torn down each time it's used — because the cheapest secret to protect is the one nobody saw.&lt;/p&gt;

&lt;p&gt;Your AI will leak your secrets. Not maliciously — architecturally. Build the door so it never gets the chance.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Stop Shipping Perfect Demos. Start Shipping Honest Limitations.</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Sat, 10 Oct 2026 13:51:00 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/stop-shipping-perfect-demos-start-shipping-honest-limitations-52mp</link>
      <guid>https://dev.to/jiahui-miao/stop-shipping-perfect-demos-start-shipping-honest-limitations-52mp</guid>
      <description>&lt;p&gt;The best thing I shipped this week wasn't a feature. It was a sentence in the README: true wireless is impossible, and this tool doesn't pretend otherwise.&lt;/p&gt;

&lt;p&gt;Everything else in the build — eight packages, 190 passing tests, a demo video that took two tries to get right — would have been worthless next to that sentence, because the industry standard right now is the opposite: demos that quietly crop out everything the product can't do, and README files written like ads. I decided to run the experiment the other way around. Publish the limitations first, features second. See what survives.&lt;/p&gt;

&lt;h2&gt;
  
  
  The demo that told the truth
&lt;/h2&gt;

&lt;p&gt;The project is PhoneHands, an open-source iPhone automation tool — one API engine and one device engine, with automatic fallback between them. Here's what the build actually looked like, without the cropping:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;190 tests, all green, across eight packages. Coverage between 91 and 98 percent. Not "thoroughly tested" — 190 green, a number you can count.&lt;/li&gt;
&lt;li&gt;The CI pipeline failed repeatedly on both platforms before it passed — three rounds on iOS, three on Android. Each failure was fixed in one segment and re-verified in that segment before touching the next — a hardcoded bundle ID on iOS (install succeeded, launch found nothing), a missing system library on the Android runner (the emulator couldn't even boot), and runner permissions that blocked hardware acceleration. Incremental verification, small fixes. No hero commits.&lt;/li&gt;
&lt;li&gt;The demo video's first version got rejected — by me — for a black first frame and a look that wasn't good enough. The second version is a real recording of the real chain: three API reads, a 403, the automatic downgrade, twenty matches read back from the device in four milliseconds. Nothing is simulated except the framing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the README carries the honesty corner: true wireless — phone in your pocket, no computer nearby — is a wall Apple built into iOS. No software on this repo gets through it, and no marketing copy here claims otherwise. What the tool does promise, it promises at the operational extreme.&lt;/p&gt;

&lt;h2&gt;
  
  
  The unsolved-problems list as acceptance criteria
&lt;/h2&gt;

&lt;p&gt;Here's the mechanism, because principles without mechanics are slogans. Before the MVP counted as "done," every unsolved problem in the category had to be named and closed or explicitly admitted:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Physical reach.&lt;/strong&gt; USB tethering is the only reliable path, so a one-command remote topology script ships in the repo — admit the constraint, then engineer around it, don't market through it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API fragility.&lt;/strong&gt; Unofficial APIs die without warning, so the router downgrades to the device engine automatically — proven live when a 403 flipped the path mid-run. The fallback isn't a roadmap item. It fired.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signing tax.&lt;/strong&gt; iOS resigning every seven days on free accounts is documented in the repo, not buried in an FAQ on page three.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-drawn UIs.&lt;/strong&gt; Apps like WeChat that paint their own pixels get a screenshot-fallback chain, not a shrug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Credentials.&lt;/strong&gt; Passwords and verification codes stay in a handoff protocol — the tool never asks for, stores, or echoes your secrets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud relays.&lt;/strong&gt; Data crossing someone else's server is a subscription fee and a privacy question, so the relay is self-hosted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Six problems, six answers or honest admissions. That list is the real deliverable. The code is just the evidence that the list was taken seriously.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "fake it till you ship" is a tax, not a strategy
&lt;/h2&gt;

&lt;p&gt;The opposing religion says: ship the happy path, collect stars, fix the edge cases when someone complains. It feels fast. It is fast — at generating the specific kind of technical debt that erodes trust in developers first and users second. Every cropped-out limitation is a support ticket that hasn't been filed yet. Every "coming soon" that was never coming is a maintainer who stops trusting their own README.&lt;/p&gt;

&lt;p&gt;The honest version is slower on launch day and faster on every day after. You never have to un-claim anything. Your issue tracker fills with bug reports instead of betrayal reports — a much better class of problem. And there's a compounding effect nobody talks about: when you're honest about six problems, the seventh one gets found by someone else, because you've trained your users to look for the list. I checked the name, by the way — the first two candidates collided with existing projects, so the project got renamed to PhoneHands before anything went public. Naming honesty starts with not taking someone else's name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built for one builder first
&lt;/h2&gt;

&lt;p&gt;I'm building for one user before I build for everyone: me. PhoneHands exists because I needed to automate a phone without lying to myself about what the phone allows. That N-of-one discipline is what organized this whole series — the right to refuse, the Tuesday audit, the deletion discipline, the treasurer — and it reaches a new edge here: a builder tool that treats its first user as the QA department. If I can't look at the README and see my own constraints named honestly, it doesn't ship.&lt;/p&gt;

&lt;p&gt;The repo is still private, pending the last gate — real-device verification, which needs a hardware budget I'm still working out. The tests are green, the demo is honest, the limitations are published. But mock-passing is not done; a real phone is the only acceptance that counts. Saying "not done" while 190 tests are green is the same muscle as saying "can't do wireless" while the engine works. It's the whole product, actually. The product is the list.&lt;/p&gt;

&lt;p&gt;So here's my rule, running in production this week: no feature ships without its limitation published beside it, in the same breath, in the same README. Perfect demos are cheap to make and expensive to believe. An unsolved-problems list is expensive to write and cheap to trust.&lt;/p&gt;

&lt;p&gt;Stop shipping perfect demos. Start shipping honest limitations. The demos will be less exciting. The trust will compound.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Stop Giving Your Agent a Wallet. Give It a Treasurer.</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Fri, 09 Oct 2026 13:48:50 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/stop-giving-your-agent-a-wallet-give-it-a-treasurer-1p77</link>
      <guid>https://dev.to/jiahui-miao/stop-giving-your-agent-a-wallet-give-it-a-treasurer-1p77</guid>
      <description>&lt;h1&gt;
  
  
  Stop Giving Your Agent a Wallet. Give It a Treasurer.
&lt;/h1&gt;

&lt;p&gt;This week we shipped the least glamorous module in our entire stack, and the one I'd now refuse to run without: a treasurer.&lt;/p&gt;

&lt;p&gt;Not a wallet. A treasurer. A small, boring, mechanical gate that sits in front of every external paid call my agent wants to make and asks a few dumb questions: is this payee on the whitelist? Is the amount under the per-transaction cap? Under the daily and monthly caps? Same recipient name but a different destination account than history shows? That's not a "no" — that's an escalation, straight to a human review queue with full context. And if the gate itself is misconfigured or confused, the answer is always no. Default-deny. Fail closed.&lt;/p&gt;

&lt;p&gt;Twenty tests, all green. Wired at the head of the guardrail chain, so nothing paid can run before it clears. Conservative limits to start: five dollars a transaction, twenty a day, fifty a month. Not because that's the budget — because that's the discipline. You raise them only when the gate has earned it.&lt;/p&gt;

&lt;p&gt;Here's why this matters, and why the order matters: treasurer before wallet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The industry wants agents that spend. It hasn't built agents that deserve to.
&lt;/h2&gt;

&lt;p&gt;The agent-commerce conversation has converged on a strange consensus: the milestone is the transaction. Demos end with the applause line — "and it booked the flight," "and it paid the invoice" — as if the ability to move money were proof of intelligence. It isn't. Moving money is proof of access. Access without judgment is not autonomy. It's a loaded credential.&lt;/p&gt;

&lt;p&gt;The opposing camp isn't better: human approval on every cent. A tap-to-confirm for a four-dollar API call. That doesn't make the agent safe; it makes it a puppet with expensive latency, and it teaches the builder nothing about what the agent would actually do unsupervised. The moment you look away, the puppet has no reflexes of its own.&lt;/p&gt;

&lt;p&gt;Both sides skip the real engineering question: what does the agent do with money when nobody is watching?&lt;/p&gt;

&lt;h2&gt;
  
  
  At N=1, the wallet is mine
&lt;/h2&gt;

&lt;p&gt;I'm building for one user: me. That fact, which has organized this whole series — the right to refuse, the Tuesday audit, the deletion discipline — reaches its sharpest point here. There is no crowd to hide a bad charge in. Every mistaken dollar comes out of my pocket, personally, the same afternoon. No averaging, no "acceptable loss rate," no risk department. Just me, checking a statement.&lt;/p&gt;

&lt;p&gt;That concentrates the mind wonderfully. It also clarifies what a spending gate actually is. It's not bureaucracy and it's not distrust — it's the same principle as everything else in this stack: the agent's freedom is defined by what it can refuse, audit, and confess. Money is just the domain where those abstractions become concrete. A refusal mechanism that can't say no to a payment is a demo feature. An audit that doesn't cover spend is theater. Honest degradation that doesn't apply to financial calls is a lie by omission.&lt;/p&gt;

&lt;p&gt;So the treasurer completes the set. Every capability in this system already has to survive three interrogations — can it refuse, does it survive a random Tuesday, will it confess when it's degraded. Now every paid call gets a fourth: can it survive the treasurer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mechanics, because principles without mechanics are slogans
&lt;/h2&gt;

&lt;p&gt;The gate runs before everything else — head of the guardrail chain, not an afterthought bolted on at the end. Its rules are deliberately dumb, because dumb rules are auditable:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Whitelist first.&lt;/strong&gt; Unknown payee, no payment. Not "review" — no. New relationships get added deliberately, by a human, on purpose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three caps, not one.&lt;/strong&gt; Per-transaction, per-day, per-month. A single cap is a speed bump; three caps are a shape. They force the question "is this pattern normal?" instead of just "is this charge small?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payee-change detection.&lt;/strong&gt; Same label, different destination account than history shows? That's the oldest trick in fraud, and it gets the strictest treatment: forced escalation to human review, every time. No learning it away, no "smart" exceptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail closed.&lt;/strong&gt; Unconfigured, uncertain, or erroring — the gate denies. An open-by-default treasurer is a decorative treasurer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And the escalation path matters as much as the denials. "Review" is not a synonym for "eventually yes." It routes to a human queue with the full context — what was attempted, why it tripped, what the history looks like — and the final word on money stays human. That's not a limitation of the design. That's the design.&lt;/p&gt;

&lt;h2&gt;
  
  
  The uncomfortable corollary
&lt;/h2&gt;

&lt;p&gt;Here's what building this taught me: you don't actually believe your agent is autonomous until you've given it the power to cost you money and then watched what it does. Most "autonomous agent" demos are choreography — the wallet is empty, the card is fake, the stakes are zero. Put a real five-dollar cap in front of it and suddenly every design decision gets honest. The refusal logic gets tested. The audit trail gets read. The degradation labels get checked, because now a degraded answer can degrade into a degraded charge.&lt;/p&gt;

&lt;p&gt;So here's my rule, running in production this week: no wallet without a treasurer. No spending capability ships until the gate that governs it is already live, tested, and default-deny. Autonomy is not the absence of constraints — it's constraints you built on purpose, before you needed them.&lt;/p&gt;

&lt;p&gt;Stop giving your agent a wallet. Give it a treasurer first. The demos will be less exciting. The statements will be cleaner. And the first time the gate says no to something you would have approved while distracted, you'll understand what the module was really for: it wasn't protecting the money. It was protecting the builder from his own inattention.&lt;/p&gt;

&lt;p&gt;Me. The builder is me. The wallet is mine. The treasurer works for me, not for the agent — and that's exactly the point.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Stop Adding to Your AI. Start Deleting From It.</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Thu, 08 Oct 2026 13:56:00 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/stop-adding-to-your-ai-start-deleting-from-it-5ea4</link>
      <guid>https://dev.to/jiahui-miao/stop-adding-to-your-ai-start-deleting-from-it-5ea4</guid>
      <description>&lt;p&gt;This week, in our own build, we deleted more than we shipped.&lt;/p&gt;

&lt;p&gt;We permanently retired a publishing route we'd spent real engineering hours on. We abolished a fallback rule that had kept our schedule alive for weeks. We deleted dead state files and retired stale tokens. The week's most productive commits were subtractions.&lt;/p&gt;

&lt;p&gt;Nobody writes a launch post about deletion. That's the problem. The entire AI industry has converged on the same scoreboard: how many tools your agent ships with, how many skills it bundles, how many integrations light up on the marketing slide. The number goes up, the applause gets louder, and everyone nods along as if capability count were the same thing as capability.&lt;/p&gt;

&lt;p&gt;It isn't. Every capability you add is a liability until it proves otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The math nobody does
&lt;/h2&gt;

&lt;p&gt;Each capability you bolt onto an AI assistant multiplies three surfaces at once: the failure surface (new ways to be wrong), the trust surface (new promises the user now expects you to keep), and the maintenance surface (new code paths that rot at the speed of your dependencies).&lt;/p&gt;

&lt;p&gt;At consumer scale, you can hide all three behind averages. A million users, a broken edge capability — the metrics barely twitch. The marketing slide keeps its number. The cost is distributed so thinly that nobody feels it.&lt;/p&gt;

&lt;p&gt;I'm building for one person: me. At N=1 there is no cohort to hide a bad capability in. Every tool that misfires, misfires on me personally. Every skill that silently degrades makes my Tuesday worse. I am the entire blast radius. That concentrates the mind wonderfully — and it turns deletion from a nice principle into a survival discipline.&lt;/p&gt;

&lt;p&gt;This is why the last three pieces in this series were, quietly, all about subtraction. Giving my AI the right to refuse was removing the obligation to always act. Auditing it against a Tuesday was a culling process for capabilities that only worked in demos. Labeling degraded answers was deleting unearned confidence. The series looks like it's about building. It's actually about everything I'm willing to take away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deletion has to be scheduled, or it never happens
&lt;/h2&gt;

&lt;p&gt;Addition has a natural constituency: every feature has a champion, a demo, a roadmap line. Deletion has no constituency. Nobody gets promoted for the thing they killed. So deletion, left to culture, loses — and the product accretes until the assistant is a junk drawer with a chat interface.&lt;/p&gt;

&lt;p&gt;The fix is mechanical, not cultural. Deletion has to be a scheduled operation with the same standing as shipping:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A deletion backlog, next to the feature backlog.&lt;/strong&gt; Every capability under consideration for removal gets a row, a reason, and a date. If it's not written down, it doesn't exist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One subtraction per cycle.&lt;/strong&gt; Not per quarter — per cycle. The cadence is the point. A team that deletes one thing a week develops a completely different relationship with complexity than a team that deletes one thing a year.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retirement is permanent.&lt;/strong&gt; We didn't "pause" the routes we killed this week. Paused things come back. Deleted things stay deleted, and the space they occupied stays empty until something earns it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And the hardest rule: every surviving capability has to keep justifying its existence. Ours survive three interrogations — can it refuse, does it survive a random Tuesday, will it confess when it's degraded. Anything that fails all three doesn't get improved. It gets removed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real spec of a personal AI
&lt;/h2&gt;

&lt;p&gt;Here's the uncomfortable corollary: if you can't name what your AI should refuse to do, you haven't finished specifying it. A capability list is only half a spec. The other half is the deletion list — the things it will not do, the routes it will not take, the answers it will not give at full confidence.&lt;/p&gt;

&lt;p&gt;Vendors won't sell you this. "Now with fewer features" doesn't close deals. But you're not buying. You're building — for one user, who happens to be you, who will personally absorb every failure your ambition adds.&lt;/p&gt;

&lt;p&gt;So here's my rule, running in production: for every capability I add, I owe the system a deletion. And the fastest way to make my AI better this week is the same as last week — find something it's doing, and stop it.&lt;/p&gt;

&lt;p&gt;Stop adding to your AI. Start deleting from it. The junk drawer was never the product. The empty space is.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Stop Trusting AI That Fails Silently</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Wed, 07 Oct 2026 13:56:13 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/stop-trusting-ai-that-fails-silently-j8g</link>
      <guid>https://dev.to/jiahui-miao/stop-trusting-ai-that-fails-silently-j8g</guid>
      <description>&lt;h1&gt;
  
  
  Stop Trusting AI That Fails Silently
&lt;/h1&gt;

&lt;p&gt;This morning, my personal AI's best model went down. The upstream provider returned 503s — the AI equivalent of the lights going out.&lt;/p&gt;

&lt;p&gt;I didn't find out from a degraded answer. I found out from the label: a plain line saying the main model was unavailable, that this answer came from the local backup, and that the system would switch back automatically when the upstream recovered.&lt;/p&gt;

&lt;p&gt;That label is the product. The answer is just the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The industry has this exactly backwards
&lt;/h2&gt;

&lt;p&gt;Every AI product ships with the same theology: failure is a UX problem. Something to smooth over. Fallback chains, circuit breakers, graceful degradation — the standard playbook ends with the same commandment: make the failover invisible to the user. One popular architecture guide puts it plainly: a mid-conversation fallback "should be invisible to the user."&lt;/p&gt;

&lt;p&gt;Invisible. That's the word they chose. Let them own it.&lt;/p&gt;

&lt;p&gt;An invisible failover is a silent downgrade. Your assistant just got dumber, and it didn't tell you. It keeps the same voice, the same confidence, the same formatting — with a worse brain behind it. The worst failure mode in AI isn't an error message. It's a wrong answer delivered at full confidence by a model you thought was a better one.&lt;/p&gt;

&lt;p&gt;I know this because I caught my own system doing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The warning light nobody wired up
&lt;/h2&gt;

&lt;p&gt;A while back, we added a &lt;code&gt;degraded&lt;/code&gt; flag to the response pipeline. The idea was exactly right: every answer would carry its provenance, and anything answered by a lesser model would be labeled as such.&lt;/p&gt;

&lt;p&gt;This morning I discovered that the flag existed — and nothing ever displayed it. The honesty machinery was built. The warning light was never wired. The system knew when it was answering dumb, and told no one. Not the user. Not me.&lt;/p&gt;

&lt;p&gt;That discovery stung, because it proved the deeper point: teams don't hide failures by accident. They hide them by default. The flag was there, the display wasn't, and nobody noticed — because nobody was looking for it. Silence is the path of least resistance, and every roadmap eventually slides down it.&lt;/p&gt;

&lt;p&gt;So we fixed it properly this morning:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Same-request fallback.&lt;/strong&gt; When the top model exhausts its retries mid-request, the system switches to the local model in the same turn — no error screen, no dead air. But the answer arrives labeled: answered by the backup, switching back automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A backup worth using.&lt;/strong&gt; We swapped the local tier to a smaller, non-reasoning model. Simple requests went from about 44 seconds to about 6.7 seconds. A fallback that takes a minute isn't a fallback — it's a punishment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Silence only at full capability.&lt;/strong&gt; If the best model answered, no label is needed. That's the promise. Anything less, and the label is mandatory. Honesty is the default state; full confidence is the thing that must be earned, per answer.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why N=1 changes the spec
&lt;/h2&gt;

&lt;p&gt;At consumer scale, you can hide failures behind averages. A million users, a 2% fallback rate — nobody notices. The metrics look fine.&lt;/p&gt;

&lt;p&gt;I'm building for one person: me. At N=1 there is no cohort to average into. I am the QA department, the beta tester, and the angry user, all at once. Every silent failure is personal — I feel the exact moment the answers get worse, and if the system won't name it, I have to guess whether I'm talking to the good model or the spare.&lt;/p&gt;

&lt;p&gt;That changes the product spec completely. The question stops being "how smart is your AI?" and becomes "how smart is it right now — and will it say so?" The first question has a demo answer. The second has only a production answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule
&lt;/h2&gt;

&lt;p&gt;Benchmarks measure best case. Demos show best case. Marketing sells best case. Nobody benchmarks the honesty of the worst case — but the worst case is the only case where trust is actually on the line.&lt;/p&gt;

&lt;p&gt;So here's my rule, shipping in production today: every answer carries its provenance. Full capability gets silence, because silence was the promise. Everything else gets a label.&lt;/p&gt;

&lt;p&gt;Stop trusting AI that fails silently. The vendors who will tell you when they're broken are the only ones you can trust with anything important.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Stop Asking Your AI to Be Helpful. Ask It to Be Accountable.</title>
      <dc:creator>Jiahui Miao</dc:creator>
      <pubDate>Tue, 06 Oct 2026 13:53:15 +0000</pubDate>
      <link>https://dev.to/jiahui-miao/stop-asking-your-ai-to-be-helpful-ask-it-to-be-accountable-4kjo</link>
      <guid>https://dev.to/jiahui-miao/stop-asking-your-ai-to-be-helpful-ask-it-to-be-accountable-4kjo</guid>
      <description>&lt;p&gt;By Jiahui Miao&lt;/p&gt;

&lt;p&gt;Every agent demo ends the same way. The agent smiles, the audience claps, and nobody checks the work. The industry's favorite word for AI right now is "helpful." I've stopped using it entirely.&lt;/p&gt;

&lt;p&gt;I'm building a personal AI for exactly one person — me — and living with it every day has rearranged my vocabulary. Helpful turned out to be the cheapest quality an agent can have. What I actually needed, and what took real work to build, was something harder: &lt;strong&gt;an agent that can be held accountable.&lt;/strong&gt; Not an agent that sounds right. An agent that shows its work, carries its debts, and answers for its mistakes — on the record, by name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Helpfulness is a vibe. Accountability is a structure.
&lt;/h2&gt;

&lt;p&gt;Here's what the helpfulness paradigm actually optimizes for: agreeableness. An agent graded on helpfulness learns to be the colleague who never pushes back, never admits uncertainty, never leaves an awkward paper trail. It volunteers, it smooths, it reassures. And when it's wrong, there's nothing to audit — because helpful agents don't produce receipts. They produce vibes.&lt;/p&gt;

&lt;p&gt;The entire benchmarking culture reinforces this. Leaderboards score agents on how pleasing their answers are. Demo culture never asks the follow-up question: &lt;em&gt;show me where that number came from.&lt;/em&gt; A helpful agent that can't show its work isn't your assistant. It's a confident intern with a shredder.&lt;/p&gt;

&lt;p&gt;Accountability is the opposite discipline. It doesn't ask whether the agent sounds good. It asks three questions, every day: &lt;strong&gt;who owns this, when is it due, and where is the evidence.&lt;/strong&gt; If an agent can't answer all three, its output doesn't ship. That rule applies to my personal AI, and — because my company vertciti exists to operate my life — it applies to my company too. A row merely written is not done. Every commitment needs an owner, a deadline, and a definition of done, or it doesn't exist. I audit the open ones daily. My agent lives under the same ledger discipline I run my company on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three debts every accountable agent owes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;One: named work.&lt;/strong&gt; Every output my agent produces carries its provenance — which inputs it used, which assumptions it made, what it verified and what it didn't. Anonymous work is unauditable work, and unauditable work doesn't ship. I participate in 3GPP's work on 6G core network standards, and the one lesson every standards body learns the hard way is this: nothing ships without a trace. Who proposed it, who objected, what changed between drafts — protocols are accountability machines. Your personal AI should be one too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two: committed work.&lt;/strong&gt; When my agent takes something on, the commitment enters the ledger with a name, a date, and a definition of done — and it stays open until it closes out. This is where the helpfulness paradigm fails most visibly: helpful agents volunteer constantly and silently drop half of it. Nobody notices, because there was never a record. My agent's open commitments get audited. An agent that volunteers and forgets is a liability wearing a smile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three: retracted work.&lt;/strong&gt; Last week I wrote about how my agent handles memory — and the core of it was retraction. I once put a hand-tallied aggregate in a report; a machine recount that evening proved it matched no real count. I retracted it the same night and mechanized the recount so no hand-written aggregate ever ships again. Caught, retracted, mechanized — in public, on the record, the same day. An agent that cannot retract accumulates its own mistakes into convictions. Mine forgets faster than I do, and that's the point. Retraction isn't failure. It's the only honest way to stay correct over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The opponent
&lt;/h2&gt;

&lt;p&gt;The opponent isn't a company or a model. It's a culture: the helpful-assistant maximalism that grades agents on agreeableness and never asks for the receipt. Every leaderboard that scores "helpfulness" without scoring traceability is training the next generation of agents to be charming and unaccountable. Every demo that ends in applause instead of an audit is teaching buyers to accept vibes as infrastructure.&lt;/p&gt;

&lt;p&gt;I have the opposite test now. When I evaluate an agent — mine or anyone's — I ask three things: who owns its mistakes, what expires, and when it last retracted something on the record. If it can't answer, it's not infrastructure. It's theater.&lt;/p&gt;

&lt;p&gt;So stop asking your AI to be helpful. Helpfulness is cheap, and the industry is already mass-producing it. Ask it to be accountable. Ask who owns the work, when the debt is due, and where the receipt is. The agents that survive that audit are the only ones worth building a life on. Mine is learning to pass it. Every day, on the record.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
