You have seen this UX. Maybe you are using it right now.

"I want to run this command. Allow?" Sure. "I want to read that file. Allow?" Fine. "I want to call this API. Allow?" Yes. "I want to run the tests. Allow?" Yes, obviously, that is literally what I asked you to do.

Somewhere around the fifth prompt I start asking a different question: so where the hell is the autonomy? I handed the agent a job so I could stop babysitting it, and now I am babysitting it with extra steps.

I build ClarkCant, and this post is me being deliberately one-sided about a choice we made: Clark, the agent, does not ask for permission to do what you already asked it to do. I will also tell you where it still asks, because "never ask" is just as lazy as "always ask".

Confirmation is not control

Here is the uncomfortable thing about permission prompts. They work beautifully on the first one. You read the command, you think about it, you decide. By the twentieth, you are not reading. You are clicking Allow the way you click "I agree" on a terms of service page. Your hand has learned the button faster than your brain could learn the risk.

At that point the prompt is theatre. It still looks like a safety mechanism, and it still lets everybody say "the user approved it", but the human in the loop has quietly left the loop. Worse, the prompts are thickest exactly when you are deep in a long task and most tired, which is also when a strange command is most likely to slip through.

I do not think the people who design these flows are stupid. Asking is the cheapest way to look careful. But a control that depends on a human paying full attention, every time, forever, is not a control. It is a liability waiver with a nice button.

I shipped the approval card first

In fairness to everyone else: ClarkCant did exactly this. On 18 September 2026 we merged a change that put every command behind an approval card. The next day we replaced it with an execution policy. The commit messages from that day say it better than I can: "commands run under an execution policy instead of an approval card", and "asking a person is a policy, not the gate".

What we found when we looked honestly was worse than annoyance. The comment we left in packages/contracts/src/execution.ts says the old yes/no flag "made the approval card the load-bearing control: with it removed there was nothing left between a model's proposal and a shell." The card was not one layer of safety. It was the only one. And the comment at the top of apps/runtime/src/preflight.ts admits that a folder restriction had been removed in favour of that card.

So taking the card out of the default path was not the hard part. The hard part was putting real boundaries back into the host, where a model cannot talk its way past them.

Timeline of real ClarkCant commits, Saigon time. 18 September 2026, 22:35: commands behind an approval card (#16). 19 September, 18:07: commands run under an execution policy instead of an approval card. 18:44: asking a person is a policy, not the gate. 18:49: an emergency stop, and a trail that survives it. 19:10: one execution policy for every seam that can cause an effect (#23). 20 September, 16:15: the autonomy controls live in the Control tab of Settings.

Your intent is the authorization

When you type "clean the build folder and run the tests again", you have authorized cleaning the build folder and running the tests. That sentence is the permission. Asking "may I run rm -rf dist?" is asking you to re-authorize your own sentence, in a format that is harder to read than the one you wrote.

That is the principle in ClarkCant's DESIGN.md, and I will quote it because it is blunt on purpose: "Security must not be used as a reason to add a duplicate confirmation after the user has already expressed clear intent." The default execution mode is Autonomous. It is declared once in the code, as the default of the canonical execution policy, and the design rule for onboarding is equally plain: no permission questionnaire, just a one-line disclosure with a link to change the mode.

This is not "trust the model". It is "trust the request, and make the host enforce everything else".

Status card: the default execution mode in ClarkCant is Autonomous, declared once in DEFAULT_EXECUTION_POLICY_CONFIG, with the Jev guardrail enabled for every class except reads. Checked against the code on 5 October 2026.

A comparison of two approaches. Ask every step: you authorize again at every step, each command, file or call costs a prompt, by prompt twenty you click Allow without reading, the only thing stopping a bad command is whoever was paying attention, the second opinion is your tired eyes, outward actions are asked like everything else, finding out what happened means scrolling back through prompts, and when it goes wrong you approved it. Intent plus policy, audit and undo: you authorize once when you ask, nothing costs attention until something matters, there is no prompt twenty, host preflight enforces owned folders, a deadline and an output ceiling, the Jev guardrail may only narrow, sending, deleting or spending that you did not ask for is still asked, an append-only audit trail and an "Effects run without asking" list show what happened, and Stop plus Undo where honest handle mistakes.

Underlying data
[
  {
    "id": "who",
    "concern": "Who authorizes the work",
    "ask": "You, again, at every step",
    "intent": "You, once, when you ask for it"
  },
  {
    "id": "attention",
    "concern": "What it costs your attention",
    "ask": "One prompt per command, file or call",
    "intent": "Nothing until something matters"
  },
  {
    "id": "fatigue",
    "concern": "What happens on prompt twenty",
    "ask": "You click Allow without reading",
    "intent": "There is no prompt twenty"
  },
  {
    "id": "boundary",
    "concern": "What actually stops a bad command",
    "ask": "Whoever was paying attention",
    "intent": "Host preflight: owned folders, deadline, output ceiling"
  },
  {
    "id": "judgment",
    "concern": "Second opinion",
    "ask": "Your tired eyes",
    "intent": "Jev guardrail, which may only narrow"
  },
  {
    "id": "outward",
    "concern": "Sending, deleting, spending on its own",
    "ask": "Asked, like everything else",
    "intent": "Still asked, because you did not ask for it"
  },
  {
    "id": "after",
    "concern": "Finding out what happened",
    "ask": "Scroll back through the prompts",
    "intent": "Append-only audit trail, Effects run without asking list"
  },
  {
    "id": "mistake",
    "concern": "When it goes wrong",
    "ask": "You approved it, so it is on you",
    "intent": "Stop, plus Undo where it is honest"
  }
]

So what keeps it from doing something stupid?

Not a dialog. A pipeline. Every effect Clark wants to cause goes through the same order: host preflight, then the execution policy, then the guardrail, then execution, then evidence and audit.

Preflight is deterministic and runs before any model is consulted. A command must resolve inside a folder this node owns, the folder must exist, and the command carries a deadline (two minutes) and an output ceiling (8,000 bytes per stream). The child process gets an allowlisted environment, so SSH_AUTH_SOCK, AWS_* variables, GITHUB_TOKEN and provider keys do not leak into whatever runs. Secrets are metadata to the agent: it knows github_token exists and what it is for, and the value goes straight into one invocation, never back to the model.

Then the policy decides, in a fixed order: a node-wide "deny everything" beats all, OS and account boundaries come next, then your per-category rules, then the mode. Then Jev, the guardrail, may judge the command against your own written rules ("never delete git repositories"). Jev can deny, ask a clarifying question, or shrink the command, and if it tries to widen anything, a longer deadline, a bigger output, a folder outside the one the host chose, the whole answer is refused.

My favourite line in the codebase is a comment in packages/core/src/execution-policy.ts: "Autonomy changes who is asked, never what is checked."

Afterwards, you are not left guessing. Every effect lands in an append-only audit trail, by name and outcome, never by value. Settings has a list called "Effects run without asking", which exists precisely because Autonomous means things ran without a card. Stop is real: POST /stop kills every running child's process group, interrupts turns and cancels queued background work, and a stopped command is recorded as stopped, not failed. And Undo exists where it can be honest: a preference change returns to what was actually there before, a dismissed notice can be restored for five minutes, and a package rollback leaves the previous generation serving.

Counts taken from the ClarkCant code: 4 execution levels in Settings (Autonomous, Guarded, Ask every time, Deny everything); 7 effect categories (read, local-write, external-write, destructive, financial, communication, media-capture); 5 of them are risky and still asked about when you did not ask for them (external-write, destructive, financial, communication, media-capture); 4 kinds of hard boundary are asked in every mode (OS permission, OAuth, browser permission, vendor consent).

Underlying data
[
  {
    "id": "levels",
    "label": "Execution levels in Settings",
    "value": 4,
    "hint": "Autonomous, Guarded, Ask every time, Deny everything"
  },
  {
    "id": "categories",
    "label": "Effect categories",
    "value": 7,
    "hint": "read, local-write, external-write, destructive, financial, communication, media-capture"
  },
  {
    "id": "risky",
    "label": "Risky categories, still asked if you did not ask",
    "value": 5,
    "hint": "external-write, destructive, financial, communication, media-capture"
  },
  {
    "id": "hard",
    "label": "Hard boundaries asked in every mode",
    "value": 4,
    "hint": "OS permission, OAuth, browser permission, vendor consent"
  }
]

When asking is still the right call

Now the fair part. Clark still asks, and I think these are exactly the right places.

When the action is outside your intent. Autonomous has a risk gate: if Clark decides on its own to do something in a risky category, writing to something outside this machine, destroying data, spending money, sending a message, recording audio or video, it asks, because you never asked for that. The code comment calls this "the difference between an assistant that carries out what it was told and one that sends mail nobody asked it to send."

When it is not our decision to make. OS permission prompts, OAuth consent, browser camera and microphone permissions and a vendor's own confirmation are asked in every mode, including Autonomous. ClarkCant does not pretend it can grant those on your behalf, and browser and computer control never click a consent screen for you.

When the work came from someone else. A task a paired machine hands over only runs within what this machine's owner allowed that peer. Anything else waits for the owner, in every mode.

When there is genuinely more than one right answer. "Which project should I delete?" is not a permission prompt. It is a question, and it ends the turn, so waiting for your answer costs nothing.

Source excerpt from packages/core/src/execution-policy.ts, lines 347 to 380, the autonomous case of decideExecution. A rule that says ask still asks. Then the risk gate: if the effect is in a risky category and no person's instruction covers it, Clark asks, with the reason that autonomous mode does not act outside this machine on the agent's own initiative. Otherwise it executes and the execution is audited.

And if you simply prefer to be asked, that is your call, not mine. Settings has four levels: Autonomous, Guarded (local work runs, anything outward, destructive, financial, communicative or recording opens a card), Ask every time, and Deny everything. You can set rules per kind of work, and "Deny" always wins. You can also tell Clark to treat requests from other programs, an AI client over MCP or a script on the API, differently from your own messages. The point is not that asking is evil. The point is that asking should be a policy you chose, not the only thing standing between a model and your shell.

Where I might be wrong

I want to be straight about the weak spots, because a post like this is cheap otherwise.

The guardrail is a judgment layer, not a security boundary. If Jev cannot be reached, the default is to keep going without the judgment step. Preflight and containment still hold, and you can flip it to stop instead, but the default is fail-open and you should know that. Prompt injection from a web page can still steer a model; isolation reduces the damage, it does not prove safety. Undo does not exist for an email that already left, and we refuse to fake one. And ClarkCant is a bootstrap, not a release. The conformance ledger in the repo says so in plain words.

There are smart people who believe every action should be confirmed, and they are not wrong about the risk. I just think confirmation is the wrong tool for it. I might be wrong. Only people actually living with these agents can settle it, so tell me.

When an agent is doing something you asked for, what do you actually want?