<?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: Vishal Kumar Singh</title>
    <description>The latest articles on DEV Community by Vishal Kumar Singh (@singhvishalkr).</description>
    <link>https://dev.to/singhvishalkr</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3864378%2F754000d1-6c68-430b-8042-41cf729e8e03.jpeg</url>
      <title>DEV Community: Vishal Kumar Singh</title>
      <link>https://dev.to/singhvishalkr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/singhvishalkr"/>
    <language>en</language>
    <item>
      <title>Why This Backend Engineer Stopped Calling LLM APIs From Every Service And Started Running a Local Agent Instead</title>
      <dc:creator>Vishal Kumar Singh</dc:creator>
      <pubDate>Tue, 21 Apr 2026 13:09:09 +0000</pubDate>
      <link>https://dev.to/singhvishalkr/why-this-backend-engineer-stopped-calling-llm-apis-from-every-service-and-started-running-a-local-2n4n</link>
      <guid>https://dev.to/singhvishalkr/why-this-backend-engineer-stopped-calling-llm-apis-from-every-service-and-started-running-a-local-2n4n</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/openclaw-2026-04-16"&gt;OpenClaw Writing Challenge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Every Backend Team Has Right Now
&lt;/h2&gt;

&lt;p&gt;If you run a Java or Node backend in 2026, your architecture diagram probably has a&lt;br&gt;
new blob labelled &lt;em&gt;"LLM"&lt;/em&gt; with an arrow pointing to it from every second service.&lt;br&gt;
Someone added an &lt;code&gt;OpenAIClient&lt;/code&gt; bean six months ago to summarise tickets. Someone&lt;br&gt;
else added an &lt;code&gt;AnthropicClient&lt;/code&gt; to rewrite customer emails. The data science team&lt;br&gt;
spun up their own proxy because they wanted Gemini for embeddings.&lt;br&gt;
From an engineering perspective, this is the same mess we cleaned up a decade ago&lt;br&gt;
with Kafka and service meshes, just with a different label. Every team re-implements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retry, timeout, and circuit-breaker policy around an external API&lt;/li&gt;
&lt;li&gt;Secret management for a rotating pile of vendor keys&lt;/li&gt;
&lt;li&gt;Audit logs of "what prompt went out, what came back, who paid for it"&lt;/li&gt;
&lt;li&gt;Context collection -- pulling email, calendar, docs, tickets -- over and over
I wanted a different pattern: &lt;strong&gt;one local daemon that owns the model connection and
the context, and every app in my personal workflow talks to it over a stable API&lt;/strong&gt;.
That is exactly what &lt;a href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;OpenClaw&lt;/a&gt; is. This post
is a backend engineer's mental model of OpenClaw, how I set it up, and why I think
the "AI as a local gateway" pattern is about to eat a lot of the &lt;code&gt;LLMClient&lt;/code&gt; beans
we have been writing.
## What OpenClaw Actually Is (In Backend Terms)
OpenClaw is an open-source personal AI agent you run on your own machine. Strip away
the marketing and the shape is very familiar:&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;daemon&lt;/strong&gt; listening on &lt;code&gt;localhost:18789&lt;/code&gt; (they call it the Gateway)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;control plane&lt;/strong&gt; UI in the browser for config, skills, and chat&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;pluggable model backend&lt;/strong&gt; -- you bring your own Anthropic, OpenAI, Google,
Ollama, or local model key&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;channel adapter&lt;/strong&gt; layer that speaks Slack, Discord, Telegram, WhatsApp,
Signal, Teams, and a few more&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;skills&lt;/strong&gt; abstraction -- small, composable units of capability that the agent
can invoke
If you squint, this is a little personal API gateway plus a rules engine plus a
provider-agnostic LLM client. The thing that makes it interesting is that the
&lt;em&gt;context and the policy live on your box&lt;/em&gt;, not in a vendor tenant.
## The Five-Minute Install
Node 24 is the recommended runtime (22.14+ also works). On macOS/Linux/WSL2:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://openclaw.ai/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;On Windows PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;iwr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-useb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://openclaw.ai/install.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or just &lt;code&gt;npm i -g openclaw@latest&lt;/code&gt; if you already run a Node toolchain. Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw onboard &lt;span class="nt"&gt;--install-daemon&lt;/span&gt;
openclaw gateway status     &lt;span class="c"&gt;# should show listening on 18789&lt;/span&gt;
openclaw dashboard          &lt;span class="c"&gt;# opens the Control UI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You paste in an API key for whichever provider you already have a budget with --&lt;br&gt;
I used Anthropic for authoring-heavy work and a small Ollama model for anything&lt;br&gt;
that touches private data. That switch is a single field in the dashboard, not a&lt;br&gt;
code change in your apps.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Mental Model That Clicked For Me
&lt;/h2&gt;

&lt;p&gt;I kept trying to think about OpenClaw as "just another chat UI", and none of it&lt;br&gt;
made sense until I flipped the frame. Here is the frame that worked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;OpenClaw is a &lt;strong&gt;sidecar for your digital life&lt;/strong&gt;. Each skill is a tiny service.&lt;br&gt;
Each channel is a transport. You -- the human -- are the load balancer.&lt;br&gt;
Once I thought about it that way, every design decision made sense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why a local daemon?&lt;/strong&gt; Because sidecars have to be co-located. Latency,
trust, and data locality all get much easier when the agent is on the same
host as the secrets it needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why skills instead of one giant prompt?&lt;/strong&gt; Because production services are
composed of small, testable units with clear contracts. Prompts without
boundaries become the stored procedures of the AI era.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why so many channels?&lt;/strong&gt; Because in a sidecar model, transport is cheap.
Slack, Telegram, CLI -- all just ingress to the same brain.
## A Concrete Setup For A Backend Engineer
Here is the layout I actually ended up with after two evenings of tinkering. It
mirrors how I would structure an internal platform team's "AI access layer" at
work, just scaled down to one human.
&lt;strong&gt;Providers&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Primary model: Anthropic Claude (authoring, refactoring, design docs)&lt;/li&gt;
&lt;li&gt;Private model: a local Ollama &lt;code&gt;qwen&lt;/code&gt; variant for anything that references real
customer data, internal service names, or unpublished work&lt;/li&gt;
&lt;li&gt;Embeddings: provider-native on whichever model the skill is pointed at, so I do
not have to babysit a second key
&lt;strong&gt;Skills I wrote or enabled&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;jira-triage&lt;/code&gt;&lt;/strong&gt; -- reads a ticket URL, extracts repro steps, asks clarifying
questions, drafts a reply. Rule: never posts automatically. Always returns a
draft to me.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;pr-review-prep&lt;/code&gt;&lt;/strong&gt; -- given a PR URL, pulls the diff, identifies risky files
using a small heuristic (touches &lt;code&gt;application-prod.yml&lt;/code&gt;, changes a migration,
edits a security filter), and writes a review checklist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;weekly-brag&lt;/code&gt;&lt;/strong&gt; -- every Friday, scrapes my GitHub activity, merged PRs, and
Medium drafts, and emits three bullets in "impact / action / metric" form for
my running brag doc. Feeds my promotion file instead of dying in chat history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;calendar-debrief&lt;/code&gt;&lt;/strong&gt; -- pre-meeting skill that pulls the calendar event,
finds the last three email threads with the attendees, and gives me a
two-sentence primer.
&lt;strong&gt;Channels&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Slack in a private workspace just for me (&lt;code&gt;@claw ping me when X&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;CLI (&lt;code&gt;openclaw ask "..."&lt;/code&gt;) for terminal-first work&lt;/li&gt;
&lt;li&gt;iMessage for phone-originated captures
&lt;strong&gt;Policies&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Any skill that would write to an external system (post a ticket comment,
send an email, push code) must return a draft instead of executing, by default&lt;/li&gt;
&lt;li&gt;Any skill that touches &lt;code&gt;*.mmt.internal&lt;/code&gt; or files under &lt;code&gt;~/work/&lt;/code&gt; must use the
local model, never a hosted one&lt;/li&gt;
&lt;li&gt;Every agent run writes a JSON line to &lt;code&gt;~/.openclaw/audit.log&lt;/code&gt; -- same spirit as
any access log you would keep in a regulated system
That last one is worth emphasising. If you think of AI usage as &lt;em&gt;traffic&lt;/em&gt;, then
everything you already know about traffic applies: log it, budget it, rate-limit
it, and be able to answer the question "what did this system say and do, on my
behalf, yesterday?"
## What Running This For A Week Actually Felt Like
I have opinions.
### The good&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The context stays put.&lt;/strong&gt; I stopped copy-pasting ticket text into a chat
window. My Slack thread with &lt;code&gt;@claw&lt;/code&gt; already has what it needs. This is the
biggest quality-of-life change, and it is underrated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-model is a config field.&lt;/strong&gt; The fact that switching from a hosted model
to a local one was a radio button meant I actually &lt;em&gt;did&lt;/em&gt; it for sensitive work,
rather than promising myself I would.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The skill abstraction composes.&lt;/strong&gt; &lt;code&gt;pr-review-prep&lt;/code&gt; calls &lt;code&gt;jira-triage&lt;/code&gt; when a
PR mentions a ticket ID. They were written days apart and nothing broke. This
is the composition story that "custom GPTs" never quite nailed because the
boundaries were not proper ones.
### The sharp edges&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill authoring is still more art than engineering.&lt;/strong&gt; You are writing
prompts, tool definitions, and fallback logic in a format that is evolving
quickly. Expect to refactor your own skills every few weeks. Treat them like
any other code: version them, review them, and write little acceptance notes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability is young.&lt;/strong&gt; The audit log is there, but the analytics around
"how often does this skill run, how much does it cost, which provider is
flaking" are not what you get from a mature API gateway. I ended up writing a
tiny shell script to &lt;code&gt;jq&lt;/code&gt; the audit log into a weekly summary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provider drift is real.&lt;/strong&gt; Two of my skills broke when I switched models
because one provider is stricter about tool-call JSON. Treat the model as an
external dependency: pin versions where you can, write a smoke test where you
cannot.
### The thing I did not expect
I write a lot of Java for a living. The most surprising win was using OpenClaw as
the &lt;em&gt;ingress&lt;/em&gt; for design-doc drafting from my phone. I dictate a messy idea in
iMessage while walking, a skill cleans it up into a structured doc template, and
by the time I am back at my laptop it is a well-formed markdown file waiting in
&lt;code&gt;~/docs/drafts/&lt;/code&gt;. That workflow does not exist in the "open a chat UI, paste,
copy back" model. It only shows up when the agent lives on your side of the API.
## What I Would Tell Another Backend Engineer Before They Start
If you already run services for a living, you will underestimate how much of your
existing mental model transfers. Here is the short version:&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat skills like services.&lt;/strong&gt; Name them clearly, give them inputs/outputs,
version their prompts, write down their failure modes. A "prompt with tool use"
is just a service with two backends (the model and the tool).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put a policy at the edge.&lt;/strong&gt; Decide early which skills are allowed to talk to
the hosted model, which must use local, and which are draft-only. It is much
harder to retrofit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log everything.&lt;/strong&gt; The audit log is the single most reassuring file on my
machine right now. Future-you will want to know what past-you authorised.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do not try to replace your team's AI strategy with your personal one.&lt;/strong&gt;
OpenClaw is a sidecar for &lt;em&gt;you&lt;/em&gt;. If your employer has an enterprise story, use
it for work. Use OpenClaw for the long tail of personal and side-project work
where you are the CISO, the SRE, and the user all at once.
## Where I Think This Pattern Goes
I have been building backend systems long enough to recognise a shape when it
repeats. We went from "every app has its own auth" to OAuth gateways. We went
from "every app has its own cache" to Redis-as-a-service. We went from "every
app has its own queue" to Kafka. Each time, the shared thing moved to a
well-defined, pluggable gateway, and app code got smaller and clearer.
AI is on the same curve. The "every app embeds an &lt;code&gt;OpenAIClient&lt;/code&gt;" phase is the
first draft. The next phase is a gateway that owns the provider connection, the
context, the policy, and the audit trail. For enterprises, that gateway will be
an internal platform service. For me, personally, it is OpenClaw.
If you have been waiting for the right time to stop pasting ticket text into a
chat window, this is that time. Install the daemon, write one skill that
replaces one copy-paste workflow, and see what happens. Budget an hour.
## Appendix: The One-Hour Starter Skill
If you want to actually try this today, here is the smallest useful skill I
wrote and how I structured it. This is the kind of thing that takes an evening
and pays for itself in a week. Full source (with tests and CI) lives at
&lt;a href="https://github.com/singhvishalkr/pr-review-prep" rel="noopener noreferrer"&gt;github.com/singhvishalkr/pr-review-prep&lt;/a&gt;.
An OpenClaw skill is a directory with a &lt;code&gt;SKILL.md&lt;/code&gt; at the root. Everything the
agent needs to know &lt;em&gt;about when to use the skill&lt;/em&gt; is in the YAML frontmatter;
everything it needs to know &lt;em&gt;about how&lt;/em&gt; is in the markdown body. That's the
whole format.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pr-review-prep/
├── SKILL.md              # frontmatter (name/description) + markdown guidance
├── scripts/
│   └── risk-scan.sh      # deterministic heuristic, ~60 lines of bash
└── test/
    ├── run.sh            # 5 unit tests, zero deps
    └── fixtures/         # file-list + PR-body fixtures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here is the heart of &lt;code&gt;SKILL.md&lt;/code&gt;. The frontmatter is what OpenClaw reads to&lt;br&gt;
decide when this skill should fire. The &lt;code&gt;metadata.openclaw.requires&lt;/code&gt; block is&lt;br&gt;
what lets the dashboard offer to &lt;code&gt;brew install gh&lt;/code&gt; for you the first time you&lt;br&gt;
invoke it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pr-review-prep&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Prep&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;GitHub&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pull-request&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;review&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;by&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pulling&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;diff&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;`gh`,"&lt;/span&gt;
  &lt;span class="s"&gt;flagging risky files via heuristics, and emitting a reviewer checklist.&lt;/span&gt;
  &lt;span class="s"&gt;Use when&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;(1) the user pastes a GitHub PR URL and asks for a review/checklist,&lt;/span&gt;
  &lt;span class="s"&gt;(2) the user wants a pre-review summary before a 1:1 code review.&lt;/span&gt;
  &lt;span class="s"&gt;NOT for&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;merging PRs, posting review comments directly to GitHub, or&lt;/span&gt;
  &lt;span class="s"&gt;non-GitHub PRs (GitLab/Bitbucket)."&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;openclaw&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;emoji&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🦞"&lt;/span&gt;
    &lt;span class="na"&gt;requires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;bins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gh"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bash"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;brew&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;brew&lt;/span&gt;
        &lt;span class="na"&gt;formula&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gh&lt;/span&gt;
        &lt;span class="na"&gt;bins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;gh&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;GitHub&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;CLI&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(brew)"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key design choice: &lt;strong&gt;the risk detection is a bash script, not a prompt.&lt;/strong&gt;&lt;br&gt;
Here is the relevant slice of &lt;code&gt;scripts/risk-scan.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-Eq&lt;/span&gt; &lt;span class="s1"&gt;'(^|/)application(-[a-zA-Z0-9]+)?\.ya?ml$'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;flag &lt;span class="s2"&gt;"config-change — confirm per-env overrides exist"&lt;/span&gt;
&lt;span class="k"&gt;fi
if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-Eq&lt;/span&gt; &lt;span class="s1"&gt;'Migration\.java$|(^|/)migrations/|\.sql$'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;flag &lt;span class="s2"&gt;"db-migration — check rollback and dual-write plan"&lt;/span&gt;
&lt;span class="k"&gt;fi
if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-Eq&lt;/span&gt; &lt;span class="s1"&gt;'(^|/)(security|auth|authz|authn)/'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;flag &lt;span class="s2"&gt;"security-sensitive — require second reviewer"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every rule is one line of &lt;code&gt;grep -E&lt;/code&gt; you can read in git. The LLM then composes&lt;br&gt;
the checklist prose &lt;em&gt;from those flags&lt;/em&gt;. That split matters: your organisation's&lt;br&gt;
risk model is the thing that should be visible in &lt;code&gt;git blame&lt;/code&gt;, not hidden&lt;br&gt;
inside a prompt string an agent loaded at startup.&lt;br&gt;
The repo ships with 5 unit tests (&lt;code&gt;bash test/run.sh&lt;/code&gt;) and a GitHub Actions&lt;br&gt;
workflow that runs shellcheck plus the tests on every push. Boring choices.&lt;br&gt;
That is the point: we already know how to make small pieces of infrastructure&lt;br&gt;
trustworthy, and a skill is a small piece of infrastructure.&lt;br&gt;
Happy clawing. 🦞&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>openclawchallenge</category>
      <category>ai</category>
      <category>java</category>
    </item>
    <item>
      <title>I Built a Production-Grade Microservice That Does Absolutely Nothing</title>
      <dc:creator>Vishal Kumar Singh</dc:creator>
      <pubDate>Mon, 06 Apr 2026 18:13:15 +0000</pubDate>
      <link>https://dev.to/singhvishalkr/i-built-a-production-grade-microservice-that-does-absolutely-nothing-8fb</link>
      <guid>https://dev.to/singhvishalkr/i-built-a-production-grade-microservice-that-does-absolutely-nothing-8fb</guid>
      <description>&lt;p&gt;This is a submission for the DEV April Fools Challenge: Silly Software&lt;/p&gt;

&lt;p&gt;What I Built&lt;/p&gt;

&lt;p&gt;Teapot-as-a-Service (TaaS) — a Spring Boot microservice whose sole purpose in life is to refuse your coffee brewing requests by returning HTTP 418 I'm a teapot. Every. Single. Time.&lt;/p&gt;

&lt;p&gt;It's built with the same architectural rigor you'd use for a payment processing system at a Fortune 500 company. Except instead of processing payments, it processes existential crises about being a teapot.&lt;/p&gt;

&lt;p&gt;Demo&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/singhvishalkr" rel="noopener noreferrer"&gt;
        singhvishalkr
      &lt;/a&gt; / &lt;a href="https://github.com/singhvishalkr/teapot-as-a-service" rel="noopener noreferrer"&gt;
        teapot-as-a-service
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Production-grade, cloud-native, enterprise teapot infrastructure. RFC 2324 compliant. Zero business value. DEV April Fools 2026.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Teapot-as-a-Service (TaaS) ☕→🫖→418&lt;/h1&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Production-grade, cloud-native, enterprise teapot infrastructure.&lt;/strong&gt;
RFC 2324 compliant. Zero business value. Maximum over-engineering.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What is this?&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;A Spring Boot microservice whose &lt;strong&gt;sole purpose&lt;/strong&gt; is to refuse coffee brewing requests by returning &lt;code&gt;HTTP 418 I'm a teapot&lt;/code&gt;. Built with the same architectural rigor you'd use for a payment processing system — circuit breakers, health checks, Prometheus metrics, scheduled self-affirmation — except it does absolutely nothing useful.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This is my submission for the &lt;a href="https://dev.to/challenges/aprilfools-2026" rel="nofollow"&gt;DEV April Fools Challenge 2026&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Architecture&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│                    TaaS v418.0.0-ENTERPRISE              │
├─────────────────────────────────────────────────────────┤
│  Controller Layer     → Accepts brew requests            │
│  Validation Layer     → Validates (then rejects anyway)  │
│  Brewing Engine       → Refuses with style               │
│  Exception Handler    → Always returns 418               │
│  Health Indicator     → "Am I still a teapot? Yes."      │
│  Self-Affirmation     → Logs motivational quotes q/30s   │
│  Prometheus Metrics   → Tracks refusal rate per second   │&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/singhvishalkr/teapot-as-a-service" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Try it yourself:&lt;/p&gt;

&lt;p&gt;curl -X POST &lt;a href="http://localhost:4180/api/v1/brew" rel="noopener noreferrer"&gt;http://localhost:4180/api/v1/brew&lt;/a&gt; \&lt;br&gt;
  -H "Content-Type: application/json" \&lt;br&gt;
  -d '{"beverageType":"coffee","temperatureCelsius":92,"volumeMl":250,"additive":"none"}'&lt;/p&gt;

&lt;p&gt;What you get back:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "status": 418,&lt;br&gt;
  "error": "I'm a teapot",&lt;br&gt;
  "message": "I'm a teapot. I refuse to brew coffee. This is not a negotiation.",&lt;br&gt;
  "incidentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",&lt;br&gt;
  "rfcReference": "&lt;a href="https://datatracker.ietf.org/doc/html/rfc2324" rel="noopener noreferrer"&gt;https://datatracker.ietf.org/doc/html/rfc2324&lt;/a&gt;",&lt;br&gt;
  "timestamp": "2026-04-06T18:00:00Z",&lt;br&gt;
  "metrics": {&lt;br&gt;
    "totalRefusals": 42,&lt;br&gt;
    "refusalRatePerSecond": 0.0023,&lt;br&gt;
    "uptime": "0d 5h 12m 33s",&lt;br&gt;
    "teapotMood": "Smugly Ceramic"&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Every refusal comes with a unique incident ID (for your records), an RFC reference (for compliance), and the teapot's current mood. Because enterprise software needs observability, even when it's refusing to do anything.&lt;/p&gt;

&lt;p&gt;Prize Category&lt;/p&gt;

&lt;p&gt;Best Ode to Larry Masinter — This entire project is a love letter to RFC 2324 and the HTTP 418 status code. Larry Masinter authored the original "Hyper Text Coffee Pot Control Protocol" RFC in 1998 as an April Fools' joke. Twenty-eight years later, I've built the production infrastructure his joke deserves.&lt;/p&gt;

&lt;p&gt;How I Built It&lt;/p&gt;

&lt;p&gt;The "Problem"&lt;/p&gt;

&lt;p&gt;Every enterprise needs a teapot. But not just any teapot — a cloud-native, RFC-compliant, observable, self-affirming teapot. The kind of teapot that would pass a MAANG system design interview.&lt;/p&gt;

&lt;p&gt;The Architecture&lt;/p&gt;

&lt;p&gt;I used Java 21 and Spring Boot 3.4 because if you're going to over-engineer something, you should use the most enterprise framework available. Here's what's inside:&lt;/p&gt;

&lt;p&gt;The Brewing Engine — Accepts your coffee request, validates it against bean validation constraints, then refuses it with a randomly selected passive-aggressive message. The validation is the best part: it checks your beverage type, temperature (per ISO 3103), volume, and tea additive... and then rejects you anyway.&lt;/p&gt;

&lt;p&gt;The Health Indicator — Spring Actuator health check that confirms, every 30 seconds, that the service is still a teapot. Key health details include canBrewCoffee: false, willBrewCoffee: false, and shouldBrewCoffee: "absolutely not".&lt;/p&gt;

&lt;p&gt;Prometheus Metrics — Tracks taas.brew.refusals with the tag reason: identity_crisis_averted. You can graph your refusal rate per second in Grafana. For when you need a dashboard showing how much coffee you're not making.&lt;/p&gt;

&lt;p&gt;The Self-Affirmation Scheduler — Every 30 seconds, the teapot logs a motivational message to itself:&lt;/p&gt;

&lt;p&gt;[SELF-AFFIRMATION] I am a teapot. I am enough.&lt;br&gt;
[SELF-AFFIRMATION] My handle is strong. My spout is true.&lt;br&gt;
[SELF-AFFIRMATION] No amount of POST requests will change who I am inside.&lt;br&gt;
[SELF-AFFIRMATION] I am not broken. I am 418.&lt;/p&gt;

&lt;p&gt;Because even teapots need mental health support in production.&lt;/p&gt;

&lt;p&gt;The Global Exception Handler — No matter what goes wrong, the response is always 418. Server error? 418. Validation failure? 418. The heat death of the universe? Believe it or not, also 418.&lt;/p&gt;

&lt;p&gt;What Makes It Enterprise-Grade&lt;/p&gt;

&lt;p&gt;Version: 418.0.0-ENTERPRISE (semver, but make it dramatic)&lt;/p&gt;

&lt;p&gt;Port: 4180 (418 + 0, obviously)&lt;/p&gt;

&lt;p&gt;SLA: 99.999% refusal uptime guaranteed&lt;/p&gt;

&lt;p&gt;Compliance: RFC 2324, RFC 7168, ISO 3103, and SOC2_TEAPOT (I made that last one up)&lt;/p&gt;

&lt;p&gt;Docker support: Because even useless software deserves containerization&lt;/p&gt;

&lt;p&gt;6 unit tests: All passing. All confirming the teapot refuses coffee. All completely unnecessary.&lt;/p&gt;

&lt;p&gt;The ASCII Banner&lt;/p&gt;

&lt;p&gt;When you start the service, you're greeted with a full ASCII art "TEAPOT" banner, the version number, and the motto: "I'm short, I'm stout, and I'm not brewing your coffee."&lt;/p&gt;

&lt;p&gt;What I Learned&lt;/p&gt;

&lt;p&gt;Bean validation is hilarious when applied to beverages. The error message "Only coffee variants are supported — this is a TEAPOT, after all" brings me joy every time.&lt;/p&gt;

&lt;p&gt;Spring Actuator health checks can have existential depth. shouldBrewCoffee: "absolutely not" is technically a valid health detail.&lt;/p&gt;

&lt;p&gt;The best code is code that does nothing, perfectly. Zero bugs in production because there's zero business logic. This is the dream.&lt;/p&gt;

&lt;p&gt;RFC 2324 is genuinely funny. It defines BREW and WHEN HTTP methods, a Content-Type: message/coffeepot header, and the 418 status code. Larry Masinter was ahead of his time.&lt;/p&gt;

&lt;p&gt;The Repo&lt;/p&gt;

&lt;p&gt;Everything is open source under MIT: github.com/singhvishalkr/teapot-as-a-service&lt;/p&gt;

&lt;p&gt;Clone it. Run it. Try to brew coffee. I dare you.&lt;/p&gt;

&lt;p&gt;git clone &lt;a href="https://github.com/singhvishalkr/teapot-as-a-service.git" rel="noopener noreferrer"&gt;https://github.com/singhvishalkr/teapot-as-a-service.git&lt;/a&gt;&lt;br&gt;
cd teapot-as-a-service&lt;br&gt;
./mvnw clean package&lt;br&gt;
java -jar target/teapot-as-a-service-418.0.0-ENTERPRISE.jar&lt;/p&gt;

&lt;p&gt;The teapot will be waiting. And it will say no.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>418challenge</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
