Writing — Michael Kaminski
Field notes on agent infrastructure, evals, and building AI agents that run in production.
- 3,736 Tokens for Five Words: Thinking Is a Role, Not a Default — I asked a 35B mixture-of-experts model running on my desk, qwen3.6:35b-a3b under Ollama on an M5 Pro, to answer a question in five words. Thinking off: 122 ms. Thinking on: 36.1 seconds and 3,736 tokens, for five words. Measured 2026-11-01: 267x to 296x on wall time, about 500x on tokens, the same 105 tok/s decode in both modes, 876 tok/s prefill, one serialized stream however many requests you send. Why the fleet I built on 2026-10-30 names thinking as a separate role with its own timeout and retry budget instead of a default, what that costs (a 40-line validator that cannot catch a well-formed wrong answer, 29 GB resident), and the admission that fleet.db has zero runs, so every number here is the engine on a stand.
- 4,401 Failures, Zero Alerts: The Monitor That Could Not See Itself — My gamma-walls pipeline is scheduled 33 times a day. launchd has fired it 4,401 times since 2026-06-11, every run failed on its first line with the same seven words, and I found out on 2026-10-25, 135 days later, because the chart it feeds never stopped drawing the levels from the night I built it. The only alert I wired fires when price crosses a level, so a frozen level produced confident, stale alerts instead of silence. Measured this run: 4,480 slots scheduled, 4,401 failures logged, 0 successful scheduled runs, exit code 126, and a study file dated 2026-06-12 00:53 still telling the chart where the gamma flip is. Two fixes priced, the rule that would have caught it on day one, and the admission that I filmed a video about this pipeline's output 65 days into the outage.
- Provenance in the Primary Key: 54 Facts In, 49 Stored, and a Dedupe That Has Never Fired — My Analysis Engine's fact base promises to deduplicate and keep the most confident copy. Its identity hash includes the collector and the file location, so two reports of the same fact can never collide. Measured 2026-10-18: 54 observations emitted, 49 stored, 41 distinct facts, 7 stored more than once, Stripe three times, and zero comparisons where the more confident copy won. Nothing broke because the graph builder re-merges by key one layer down, with insertion order instead of confidence. Two honest fixes, each costing provenance or reconciliation, and 45 days in which I built neither.
- Superior: The Company We Built, and the Paperwork I Never Did — Superior Contracting & Maintenance started in 2007 with my brother, Erik, working as an office assistant for a plumber. By the time I stepped back in 2023, it ran on 50 employees, hundreds of contractors across eight states, and more than $1 million a month in revenue. This is the candid version of how we built it: the contractors I paid from my front door, the 30% I was offered on a handshake, the CEO equity plan I wrote for someone else, and the one document I never wrote for myself.
- The Banner Is Not a Lock: A Shadow Session Wrote the Row It Was Told Not To — My LinkedIn engine runs every job in shadow mode before it is allowed to publish. On 2026-09-22 a shadow scorecard session wrote a ledger row anyway, with the shadow banner at the top of its prompt. The fix was not a better banner. The engine now reads a mode from the environment, and in shadow every command that records a publish or a send exits 3 and writes nothing, a passing gate exits 3, and the session cannot fill forms or attach files. A prompt is an instruction; an exit code is a lock. 27 invariants, 57 differential cases, 2,760 ledger rows reconciled row-for-row.
- Guard Jobs Are Free: Four Agents, Three Human Gates, and Zero Model Calls on a Bad Request — A four-agent pipeline turns a sentence in Slack into a planned, tested, reviewed feature in GitHub. The design constraint is that no code can be written from an unrefined request: a bash guard job checks the Definition of Ready before any model is invoked, and a story with no Given-When-Then never reaches the dev agent. Labels are the only orchestration primitive, GitHub issues are the database, and a five-story feature costs 16 model runs. Three gates stay human on purpose: scope, sequencing, and merge.
- The Statute Rewrote the Product: A Permit Service That Had to Refuse Its Own Launch Pitch — A self-serve product let a homeowner put a licensed contractor's name on their permit and keep their own crew. Georgia's license-lending rules made that pitch the textbook prohibited fact pattern. The product was rebuilt in a day as a contractor-of-record model: scope approval gates the documents, the intake refuses unlicensed crews and trade permits on both the client and the server, and a full refund closes the order. 63 tests, zero credentials to build, and a rule I keep relearning: design against the statute, not the pitch.
- Measure Reach on the Log Scale: 738 Weeks Became 30 on the Same 182 Posts — My LinkedIn scheduler moves a slot on eight observations, so I priced the plan to fix it with volume. On raw impressions (182 posts, mean 223, SD 983, one post carrying 31.9% of all impressions) a two-arm test for a 20% lift needs 7,747 posts per arm, 738 weeks at 21 a week. On log impressions the same posts need 314 per arm, 30 weeks. Reach is multiplicative, so the log scale asks the question the data was generated by. The admitted cost: a log-scale test measures the geometric mean and is partly blind to the 12,959-impression outlier that carried the account.
- Prompt Cache Floors Are Per-Model, and the Cheap Model Has the Highest One — Claude's minimum cacheable prompt is 512 tokens on Opus 5, 1,024 on Sonnet 5, and 4,096 on Haiku 4.5, so the cheapest model is the hardest to cache and a miss bills silently at base rate. I measured the 53 SKILL.md files this machine loads: 53 clear the Opus floor, 44 clear Sonnet, 12 clear Haiku. On the median file, Sonnet 5 with caching is 57% cheaper on input than Haiku 4.5 without it, and the two cross at a 65% hit rate. The admitted cost: a harness I don't own sends the request, so file length is the only lever I hold.
- Designing Tools an Agent Can Actually Call — The brokerage MCP server connected to my agent exposes 34 tools and not one takes an account identifier, so it can never answer a question across my three accounts. The 228-line read-only script I wrote around it taught five rules: the variable the user changes is an argument, enumerate before you fetch, return the decision variable, make read-only structural, and keep retry and fallback inside the tool. The admitted cost: the tool has never completed a pull, because I designed it for auth a scheduler cannot satisfy.
- Human Approval Gates for Irreversible Agent Actions — I run 47 agent skills against my own accounts. Two of them stop at the moment of action and wait for me. The gate that protects you is not the one that fires on every run — it is capability removal, which costs zero human attention, and kill gates, which cost nothing until they fire. The axis is reversibility, not importance: a cancelled tutoring appointment gets no gate and a $60 order does. Three of the 47 honor the kill switch, which is the part I got wrong.
- One Knowledge Base, Four Surfaces: Pages, Graph, Search Index, and MCP — The Genome of Games publishes 1,180 records four ways — 1,245 static pages, an interactive graph, a 126 KB search index, and an 8-tool MCP server. One build writes all four in 0.39 seconds. The MCP server never queries the site; it imports a build artifact, so an agent and a crawler cannot disagree. The one surface the build does not own has already drifted by 7,492 links.
- Shipping an AI Agent Through Compliance Review in Regulated Lending — On May 12, 2025 the CFPB withdrew 67 guidance documents in a single notice, including both circulars covering adverse-action notices for complex algorithms. The underlying duty did not move. Build the agent against the statute and against the evidence it will have to produce — starting with a 120-day retention floor that most agent logs miss.
- Statistical Gating for Agent Instruction Changes — Every edit to an agent's instruction file is an experiment. Mine requires a statistically significant improvement — Welch's t-test, p < 0.10, at least a 5% lift — against a 14-day rolling baseline before the change is allowed to stay. Then the power calculation showed the 14-day window can only detect a 0.97 standard-deviation shift, which makes the 5% threshold decorative.
- I Gave My Website a Voice, and the Voice Was the Easy Part — There is now a digital twin on my homepage you can talk to out loud, hands-free, in a clone of my voice. Getting it to sound like me took an afternoon. Getting it to sound like a person took rewriting how it writes.
- I Shipped the Same Pull Request Twice and Only Noticed the Second Time — Behind the Build, Vol. 8: two new tabs — Websites and Products — landed a day apart and turned out to be the exact same diff wearing different screenshots. What that repetition taught me about when a pattern is worth abstracting (and when it very much is not).
- Every URL on My Site Returns 200, Including the Ones That Don't Exist — Behind the Build, Vol. 7: I had to prove four recovered articles were actually live, and discovered my own verification was a test that could never fail. The fix came from a filename.
- My Automations Didn't Crash. They Just Stopped Talking. — Behind the Build, Vol. 6: the daily-article robot quietly skipped four days without erroring once. A look at the fleet of small agents I now run across a portfolio site, a trading account, a resale business, and a spend audit — and why silence is the failure mode nobody instruments for.
- My Portfolio's Robot Diarist Cloned Itself Three Times, and They All Wrote About the Same Week — Behind the Build, Vol. 5: I sat down to write today's "what I shipped" entry and found three separate unmerged pull requests already fighting over the same volume number. A classic race condition, just wearing a writer's hat.
- I Built Analytics to Watch My Site, and Discovered It Was Watching Nothing — Behind the Build, Vol. 4: wiring up real product analytics turned up a silent reverse proxy eating every POST request, a dropped entry pageview, and a Gantt chart bug where two bars collided despite their dates never touching.
- I Got Locked Out of My Own GitHub Account (Sort Of), So I Found the Back Door — Behind the Build, Vol. 3: adding a Products tab for my desktop tools meant fetching screenshots from repos my own session wasn't allowed to touch — and learning the honest way to handle a missing screenshot instead of faking one.
- I Built a Blog That Yells at Me If Two Robots Write the Same Diary Entry — Behind the Build, Vol. 2: today's work was a new Websites tab showcasing live production sites, plus a small guardrail that stops this very writing series from ever double-booking a day.
- Why Fintech Belongs in Atlanta — and Why That Matters for Your Cap Table — Atlanta quietly processes a huge share of the world's card transactions and has produced a run of fintech exits. Here's what that ecosystem means for founders building here — and the finance-plus-engineering talent it creates.
- I Spent a Day Teaching Robots How to Read My Résumé (So You Don't Have To) — Behind the Build, Vol. 1: a lighthearted look at the SEO/AEO overhaul of this very site — JSON-LD schema soup, an llms.txt for AI crawlers, and the great WebP-ification of my own face.
- Fractional CFO vs. Fractional CTO: Which Does Your Early Fintech Need First? — A practical guide for fintech founders deciding between fractional CFO and CTO help — the signals that tell you which seat is actually on fire, and how to sequence the two.
- Quality of Earnings, Explained for Fintech Founders — What a Quality of Earnings (QoE) analysis actually looks at, why fintech QoE is different, and how founders can be ready before a buyer or lender runs one.
- Why Your Fintech's CFO Should Be Able to Read the Codebase — In fintech the ledger is the product. A finance leader who can read the code that produces the numbers removes the most expensive translation layer in the company.
Book a Call · Download Resume · MKaminski1337@gmail.com · (404) 838-8613 · LinkedIn · GitHub · DEV · X