Your local LLM app needs guardrails before it needs prompts A developer's production experience running autonomous agents on local LLMs 24/7, with over 8,000 logged failures, shows that successful calls don't guarantee correctness. The developer created a scaffold, `create-local-llm-app`, that enforces output contracts, human approval, and watchdog checks before any output leaves the app. The contract checker is open-sourced as `honto-contract`, and a failure log dataset is available on Hugging Face. Most local-LLM tutorials start with the fun part: the prompt. After running a fleet of autonomous agents on local models 24/7 and logging every failure — the ledger now holds over eight thousand entries — we start somewhere else. Here is the single most important thing that ledger taught us: the call succeeding tells you nothing. The majority of our contract violations were outputs that were So we distilled the survival kit into a scaffold you can stand up in one command: npx create-local-llm-app my-app Five files, about 180 lines, plain Node and Express, no framework lock-in. What gets wired in: A contract declares what "done" looks like — and then verifies the artifact itself. Never a proxy. Not the exit code, not a log line, not HTTP 200. contract.js has three kinds of clause: minChars — the cheapest check, and statistically the most valuable must — patterns that have to appear mustNot — leftover placeholder tags, unfinished markers, refusal leakage "as an AI, I cannot…" inside what was supposed to be a business document Every mustNot entry exists because it caught a real production failure. When the contract rejects an output, the failure reason goes into the next prompt. Three strikes and the item is rejected outright — there is no "accept with warnings", because accept-with-warnings is "apologize later" with extra steps. Nothing the model writes leaves the app without a person pressing approve. No decision means no. That rule comes from experience: an unattended script once contacted a real company because its default was "send". The dangerous side is never the default here. A heartbeat is the process alive? and a silent-zero check is anything actually being produced? . These are different questions. Running is not the same as producing — a fleet can be 100% "up" with zero output all day, and nothing in a standard health check will tell you. Because the guardrails are the product; the model is replaceable. Swap Ollama models in .env , replace the prompts with your own business task, and the contract/queue/watchdog skeleton stays exactly where it is. If you want to go deeper, the checker we run in production is free and MIT: honto-contract https://www.npmjs.com/package/honto-contract . A free snapshot of the failure ledger behind all of this is on Hugging Face https://huggingface.co/datasets/GXCafe/ai-agent-failure-logs . Start with the scaffold, break every guard on purpose, and watch them hold. That is the fastest way to trust your own unattended setup.