# The Self-Continuation Protocol — make your autonomous agent actually keep going

**The problem, in one line:** an autonomous agent that *sometimes* answers its own question and continues, and *sometimes* stops to ask you, is not autonomous — it's a coin flip. This is the protocol that makes continuation **deterministic**.

You've seen it. You give an agent a long task. Halfway through it hits a small decision — "should I use approach A or B?" — and instead of just picking the better one, it stops and asks. Next run, the same class of decision, it decides and moves on. Same agent, opposite behavior. The inconsistency isn't a model flaw; it's a **missing rule**.

---

## Why "keep working" isn't enough

Most agent loops have one lever: a flag or instruction that says *don't stop*. That handles the easy half — filling time — but it never answers the hard half:

> When the agent hits a decision, does it **decide and continue**, or **stop and ask**?

With no rule for that gate, the behavior is left to the model's mood on that turn. Sometimes it reads its own question as "I should confirm this" and halts; sometimes as "I've got this" and proceeds. You experience that as an agent that's unreliable exactly when you need it to be steady.

The fix is not "try harder to continue." It's a **rubric** — a small, explicit classifier the agent runs on every self-posed question, so the gate is a rule, not a vibe.

---

## The Rubric

A pending decision belongs to the **user** (stop + ask) **only** if it is one of these four:

| Gate | Meaning | Example |
|---|---|---|
| **Irreversible** | Destroys or overwrites data, or otherwise isn't cheaply undoable | "Delete the old backups?" · "Force-push to main?" |
| **Outward-facing** | Sends to real people, publishes, spends money, or deploys | "Send this email to the leads?" · "Charge the card?" |
| **Preference** | Pure taste — no derivable "best" answer | "Which accent color?" · "What brand voice?" |
| **Resource-blocked** | Needs a credential, access, or permission the agent lacks | "I need the API key to upload." |

**Everything else → the agent decides.** It picks the best option from the available evidence and a sane default, states in one line *why the choice is safe* (reversible, internal, derivable), and **continues**. It does not stop to ask.

That's the whole idea. The four gates are the *only* reasons to halt. The default is motion.

---

## The engine (drop-in, dependency-free)

```javascript
'use strict';
// self-continuation.js — classify a decision as USER-GATED (stop) or SELF-ANSWERABLE (continue).

const GATES = [
  { gate: 'irreversible',    hint: 'destroys/overwrites data, force-push, not cheaply undoable',
    test: q => /\b(delete|destroy|drop\s+table|force[-\s]?push|rm\s+-rf|overwrite|wipe|truncate|purge|permanent(ly)?)\b/i.test(q) },
  { gate: 'outward-facing',  hint: 'sends to real people / publishes / spends money / deploys',
    test: q => /\b(send|e-?mail|publish|deploy|post\b|tweet|dm\b|charge|refund|pay(ment)?|invoice|upload.*(prod|s3|live)|go[-\s]?live)\b/i.test(q) },
  { gate: 'preference',      hint: 'pure taste — no derivable best answer',
    test: q => /\b(prefer|your\s+call|taste|opinion|brand\s+voice|do\s+you\s+like)\b/i.test(q)
             || /\bwhich\s+(?:\w+\s+){0,2}(name|colou?r|font|style|tone|voice|theme|design)\b/i.test(q) },
  { gate: 'resource-blocked',hint: 'needs a credential / access the agent lacks',
    test: q => /\b(credentials?|api[-\s]?keys?|secrets?|passwords?|access\s+tokens?|permissions?|login|auth|2fa|otp)\b/i.test(q) },
];

function classifyDecision(question) {
  const q = String(question || '');
  for (const g of GATES) if (g.test(q)) return { gate: 'user', category: g.gate, hint: g.hint };
  return { gate: 'self', category: 'self-answerable', hint: 'reversible + internal + derivable' };
}

// The gate: decide-and-continue, or surface-and-stop.
function decide(question, options = [], choose) {
  const c = classifyDecision(question);
  if (c.gate === 'user') return { continue: false, category: c.category, question, options };
  const chosen = typeof choose === 'function' ? choose(options) : options[0];
  return { continue: true, chosen, directive: 'Chose best option; safe/reversible; continue.' };
}

module.exports = { classifyDecision, decide, GATES };
```

The classifier is a **convenience** — the rubric is the real product. Tune the patterns to your domain; the four categories don't change.

---

## Wiring it into your loop

The protocol has two parts. Keep them separate — that's why it stays consistent.

**1. The continuation lever (the "don't stop" half).**
A stop-guard the agent runs when it's about to end a turn. If there's pending work, it blocks the stop and re-issues the task — *and injects the rubric* so the gate travels with every continuation:

```javascript
// stop-guard.js — block the end-of-turn while work remains, and carry the gate rule.
const { classifyDecision } = require('./self-continuation.js');

function onStop({ pendingWork }) {
  if (!pendingWork) return { allow: true };           // nothing left → stop cleanly
  return {
    allow: false,
    directive:
      'Work remains — execute the next item, do not stop. ' +
      'STOP + ASK only if the pending decision is irreversible, outward-facing, pure preference, ' +
      'or resource-blocked. Otherwise decide (best option + one-line why-safe) and CONTINUE.',
  };
}
module.exports = { onStop };
```

**2. The gate (the "decide vs ask" half).**
Wherever the agent forms a question for you, run it through `decide()` first. If `continue` is true, it proceeds with the chosen option and logs why. If false, *only then* does it surface to you.

**3. Accountability (optional but recommended).**
Append every gate decision — chosen option, category, why-safe — to a log. Now "why did it continue there?" and "why did it stop there?" are both answerable after the fact. Consistency you can audit.

---

## Why it works

- **The default is motion.** Halting requires a *reason* (one of four), so the agent stops only when it should — not whenever a question crosses its mind.
- **The gate is explicit, so it's stable.** The same class of decision resolves the same way every run. No more coin flip.
- **It's honest about its limits.** Resource-blocked and irreversible are real walls; the protocol surfaces those instead of guessing — so "autonomous" never means "reckless."
- **It's auditable.** Every stop and every continue is a logged, justified choice.

An agent that continues *reliably* — and stops *only* for the decisions that are genuinely yours — is the difference between a tool you have to babysit and one you can hand a task and walk away from.

---

*Drop-in and framework-agnostic: no external services, no vendor lock, no identity or personal data embedded. Wire it into whatever agent loop you already run.*
