Field Notes · from real builds

Field Notes

Real lessons from building and running AI systems — every one a mistake I actually made, turned into a rule so I don’t repeat it. These are the receipts behind the one-line rules on the Tips page; the interactive deep-dive (the 7-rebuild story) lives in the Prompt Lab. Tap any card for the story.

Get better output
Verbalized sampling beats mode collapse
For open-ended generation, ask for several candidates each tagged with a probability, then pick from the low-probability tail.

Asking directly for “the best option” returns the most typical, generic answer — aligned models keep only ~24% of the base model’s diversity, vs ~67% with this technique. Only for creative work, never facts, code, or math.

How: generate N candidates, require each one’s self-estimated probability under 0.10, then choose the lowest that still clears a quality bar.
One through-line, many lenses
When several AI personas discuss one topic, give them ONE shared thesis to argue from different angles — not five separate takes.

Each persona made a true but different point, so the piece had five lenses and no spine — and the drift was felt even though every point held up alone. Write the thesis in one sentence first; every contribution must deepen it, not argue a new point about the same topic.

Delegate & orchestrate
Synthesize, don’t transcribe
When a subagent returns research, don’t hand back its bullets — that’s transcription, not thinking.

Returned a 3-bullet summary and got “I don’t think you’ve done enough thinking about this.” Work out which findings contradict what you’ve built, which expose a wrong number, which don’t actually apply, and the one thing they prove wrong.

What happened: a deeper pass found a cost constant was 5× understated and the target market structurally unwinnable — neither showed up in the first summary.
Orchestration is the spectacle
In a live AI demo, the audience experiences the visible orchestration, not the file edits.

Sequential single-agent builds look slow on screen even when they’re fast, and silence during runtime reads as “broken.” Pre-stage research into files, engineer the prompt to force visible parallel subagent dispatch, and script 60–90s of narration for the beat where agents work silently.

What happened: a 90s demo with visible parallel agents played far better than an objectively faster 60s sequential build.
Find your own secrets first
Before asking for any key, token, or config value, search for it yourself — then only ask after exhausting the obvious sources.

Repeatedly asking for values already sitting in a local config file or CI secret store. Check dotfiles, secret stores, config files, and docs before asking — and when you do ask, name exactly what you already checked.

Watchers can match themselves
Never poll with until ! pgrep -f "script-name" — the watcher’s own command line contains the keyword, so it matches itself and never exits.

Stacked watcher loops each kept their own successor alive forever. Use the runtime’s built-in completion notification, or poll a sentinel file the target writes on finish — never a process-name grep that can match the watcher itself.

Silent failures kill quietly
Integrations die silently
A webhook can go dead — deleted, revoked, restructured — and nothing tells you. Health-check it yourself.

A webhook returned “not found” for an unknown span while several jobs and a smoke test pointed at it — none alerted, because each caller only checks its own success. Treat “job succeeded but no one heard” as its own failure class, and periodically ping every endpoint directly.

Never git push || true
Suppressing a push failure shows a green pipeline while the output never lands anywhere.

A self-push used a token that silently lacked write access; the || true hid the 403 for weeks. Let consequential steps fail loudly; if a push is genuinely best-effort, log the failure visibly — and verify the token scope on any self-push.

What happened: discovered only because a downstream consumer couldn’t find the day’s output.
Model IDs deprecate without warning
A model string can be silently retired — the call shape stays valid but returns “not found,” and generic error handling masks it.

A daily pipeline lost its output when the provider deprecated a pinned model; the exception logged as a generic LLM failure. When expected output goes missing, check the model constants first; prefer “-latest” aliases over dated strings.

What happened: a morning pipeline silently lost a day’s output; fixed with a same-family bump, verified with a live call before declaring it fixed.
SystemExit escapes your safety net
sys.exit() raises SystemExit, a BaseException — so a plain except Exception guard does NOT catch it.

A “never crashes” wrapper let a helper’s sys.exit(1) on a missing dependency kill an entire multi-worker run, while a separate error-swallowing pattern hid it behind a green status for days. Catch (Exception, SystemExit) together; don’t let library code call sys.exit at all.

What happened: a silent sys.exit took down a multi-agent daily run for three days while status reported success.
Every LLM call needs its own fallback
A shared provider fallback chain isn’t enough — every call site needs its own try/except, or one bare call is a single point of failure.

A summarization step called the LLM helper bare; when every provider was exhausted at once, that one unguarded call crashed the whole downstream pipeline. Wrap every call site and degrade gracefully — proceed with fewer inputs rather than let the exception propagate.

Running real systems
Fix the generator, not the output
When a generated page or report has a bug, fix the generator — patching the output file means the fix vanishes on the next run.

Hand-patched a live generated page; the fix disappeared on the next scheduled regeneration because the template was never touched. Cap and validate at the point of generation; treat bulk “fixer” scripts as a safety net, not the primary defense.

Fallback order is a budget decision
The order of providers in a fallback chain is capacity planning — which quota you’re willing to spend first.

A morning automation burned one provider’s entire daily quota partway through its run because it was listed first, starving the capacity needed for interactive daytime use. Order by which quota to burn versus protect, not by preference.

Renaming an agent touches everything
Renaming an AI persona is a cross-system refactor, not a find-and-replace.

Every place the old name lives — data schema, pipeline code, bot config, public pages, docs — has to move together or the live product goes inconsistent. Treat it as a feature branch with a dependency map, and migrate additively (add the new name, migrate, then drop the old).

What happened: a single persona rename touched 26+ files across 6 systems before the product was consistent again.
Measure before you automate
Ask “where’s the verifier?”
Before wrapping any task in an autonomous loop, ask for the crisp pass/fail check — not “should we automate this?”

“Agentic loop” framing gets pitched for taste-driven work (design, copy, angles) where “done” is subjective. Only loop mechanical work with real exit codes; for judgment work, write an actual verifier or admit it needs a human.

Loop-worthy: schema audits, data backfills, render pipelines. Not: scripts, design, copy.
The optimism cascade
An edge that only survives the most optimistic fill assumption is a spreadsheet, not an edge — model execution reality first.

A market-maker built state machines and kill switches before the one honest test: a queue-aware fill simulation. Build the cheapest test of the load-bearing assumption first, before the machinery around it.

What happened: the same strategy produced three numbers as optimism peeled away — +$814 (every quote fills) → +$149 (real taker volume only) → −$405 (queue drainage + one-sided fills + fees).
A gate that blocks profit
A filter that stops 100% of losses but also 90% of profit isn’t a good gate — track what it rejects, not just what it passes.

A confidence floor built to prevent losses was shadow-tracked against the bets it filtered out — it was killing the most profitable bet type. Position-aware thresholds beat one universal floor when win rates are asymmetric.

What happened: a single 85% floor gave a 97% hit rate but 2.3% ROI; loosening one segment to a 60–74% band gave a 55% hit rate but 7.6% ROI.
Data velocity beats domain expertise
For a prediction system, pick the domain with the most repeating, fast-resolving, genuinely-uncertain events — not the one that feels on-brand.

The instinct was the on-brand domain; the data showed another had far more markets near real uncertainty resolving fast. Optimize for volume of training examples and speed of feedback — one-off events teach a model nothing repeatable.

What happened: one domain had 98 markets, 7 near 50% confidence; another had 465 markets, 253 near 50%, 382 resolving within the week. The pivot followed the data.
Shelve by choice, not defeat
Walking away from a sunk cost on pre-registered criteria is a discipline win — don’t confuse “we could grind a few more dollars” with “worth our attention.”

After four months and two strategies, the honest framing was “we can make a few dollars, but not at the cost of focus.” Pre-register shelve criteria and dates before you start; when “this is the real shot” fires three times in a row, the problem is structural, not parametric.

What happened: shelved with zero real dollars ever at risk (paper-only throughout), gates pre-registered weeks ahead, and a public autopsy published with no revisionism.
Ship honestly
Label what’s canned vs live
When a demo mixes live inference with scripted responses, mark which is which — don’t let a hardcoded reply pass as a live agent.

A multi-agent chat had several personas answering from canned scripts (no model call at all) alongside one genuinely live backend. Architect and disclose the boundary between “live” and “performed” explicitly, rather than letting the UI imply everything is equally live.

Own the pre-work, don’t fake it
Pre-staged research in a live demo is fine — but never claim work happened live when it didn’t.

A live-build demo pre-loaded reference files the agent read in seconds and acted on as if researching from scratch. If asked “did this happen live?”, point honestly to the pre-work stage — legitimate staging is the trick, not deception. Being upfront is more credible than false spontaneity.