Research · 2026-W40

Human-in-the-loop AI automation for solopreneurs

Human-in-the-loop automation where silence is never consent

By Ruiqi Tan · Published 2026-09-28

Human-in-the-loop automation usually fails at the loop's least glamorous edge: what happens when the human does not answer. An approval message goes out, the person is busy, a timeout fires — and somewhere a code path treats "no answer" as "no objection". The action runs. Nobody decided it.

For a solopreneur this is not a corner case; it is the *normal* case. I am the only approver in my operation, and I am regularly asleep, traveling, or heads-down while my agents work. So the rule my whole approval layer is built on — published as [fail-closed-gate](https://github.com/yagebin79386/fail-closed-gate) — is blunt: **expiry is not approval, silence is not consent, and an unanswered request fails closed.**

The mechanics

Every consequential action my agents take — publishing content, changing configuration, anything irreversible — raises a gate: a JSON request in a pending directory, with a deadline. A sweep closes overdue requests as `expired`, and the expired decision record deliberately carries **no decider**, a rule the schema itself enforces. Downstream code asks one question — *may I proceed?* — and gets a fail-closed answer on every edge: unknown request, overdue-but-unswept request, and every outcome except an explicit approval all read as *blocked*. Decisions append to a daily ledger that grep can query; nothing is ever deleted.

The bugs that wrote the rules

Two production incidents shaped the protocol more than any design session. First, duplicate cards: pipeline re-runs used to stack approval requests nobody remembered, so request ids became deterministic — the same gate re-raised is the same id. Second, and worse: a re-raised gate once bounced every fresh decision against its *old* archived outcome, and three approvals were silently dropped before anyone noticed. The fix is that superseding a decided gate is explicit and auditable — the old archive is renamed, never deleted, and can never again speak for a request it no longer describes.

Why this beats "just ping me again"

Reminder-based flows optimize for the human answering faster. Fail-closed flows optimize for the system being *safe while unanswered* — which is the actual requirement of one-person automation. The cost is honest: things I do not approve in time do not happen, and the ledger shows a string of expired requests on my busiest weeks. That record is a feature. It is the difference between "the system did nothing because nobody said yes" and "the system did something because nobody said no."

Limits

The published tool is transport-agnostic by design: it stores requests, records decisions, and sweeps expiries, but showing requests to a human — chat bot, email, a terminal — is an adapter you wire yourself. And a gate only governs what flows through it; the discipline of routing *every* irreversible action through the gate is operational, not enforceable by the library.

Claims & evidence

Every externally sourced claim in this article traces to a recorded source.

Limitations

Transport adapters and the discipline of routing all irreversible actions through the gate remain the operator's responsibility.