Day 069Working with AI10 min readChinese original ↗

I said "finish it" — why does Codex keep stopping?

我已经说了“把它做完”,为什么 Codex 还是不断停下来问我?
TL;DR
  • I asked Codex to go all the way from implementation to production acceptance, yet it kept stopping to wait for my approval. Only later did I understand that an AI task has at least three layers of authorization — task authorization, system execution permissions, and external identity and permissions — and they don’t merge automatically.
  • I didn’t open up every permission. Instead I set conservative defaults: writable inside the project, network and out-of-bounds operations still controlled, low-risk approvals handed to Auto-review. The current environment not seeing a credential doesn’t mean the credential has expired.
  • “Finish all of it” only expresses intent. An authorization that can really be executed spells out the chain of results, the scope of autonomy and the stopping conditions. What I want isn’t an AI that never asks, but one that only stops to ask when it truly needs my judgment.

Once, I asked Codex to complete a fairly long development task.

My request wasn’t vague:

finish the implementation

→ run the tests

→ commit

→ push

→ create a PR

→ wait for checks

→ merge

→ wait for deployment

→ complete production acceptance

I thought this amounted to a complete authorization.

As long as nothing went out of scope and no risk appeared, it should be able to carry on down this chain.

But that’s not how it actually went.

It stopped to create a worktree, stopped to run the local server, and might stop again to access the network, run Git operations or check login status.

Some steps that seemed to me like normal parts of completing the task, the system kept handing back to me for approval.

What really frustrated me wasn’t that AI has safety boundaries.

It was that one long task got chopped into many small human interruptions. I had clearly handed the goal to AI, yet I still had to stay nearby, confirming over and over that it “may continue.”

If I have to come back every so often to click allow, it can hardly be called continuous execution.

It was this experience that made me stop and really figure out:

I’ve already authorized the goal, so why still can’t AI finish it on its own?

Later I found I’d been treating three different kinds of “authorization” as one.

It turns out an AI task has at least three layers of authorization

Layer one: task authorization

This is the agreement between me and the AI.

I tell it:

  • what result to achieve;
  • where the scope of work is;
  • how far it may go;
  • which actions have business authorization.

For example, I allow it to make the change, test, commit, open a PR, deploy and do production acceptance.

This layer answers:

should this be done, and how far.

But my allowing it to push doesn’t mean the system has allowed it to access the network.

My allowing it to deploy doesn’t mean the deployment platform has confirmed its login identity either.

Layer two: system execution permissions

An AI coding agent doesn’t just act freely on your computer.

It usually runs in a restricted environment. The system controls:

  • which directories can be written;
  • whether network access is allowed;
  • whether local services can be started;
  • whether Git-related content can be changed;
  • whether files outside the workspace can be accessed;
  • which operations must be approved.

This layer answers:

even if the task allows it, can this specific action be executed directly?

This was the main source of my frequent interruptions.

From my point of view, “starting a server” and “pushing code” are both just part of the release flow; from the system’s point of view, they involve processes, the network and external state respectively, and each needs judging separately.

Business authorization and system permissions don’t merge automatically.

Layer three: external identity and permissions

Even if the task is authorized and the system environment allows the action, external services like GitHub, the deployment platform and the database still independently confirm:

  • who is logged in;
  • whether the credential can be read by the current environment;
  • whether this account has permission to push, merge or deploy;
  • whether the token is valid;
  • whether the current operation complies with the platform’s own permission rules.

This layer answers:

who are you, and are you entitled to do this?

You can think of the three layers as a business trip:

your boss approving the trip doesn’t mean the airport will skip security, nor that the hotel has already checked your ID.

Task authorization confirms the goal, system permissions control the actions, external authentication proves identity.

If any layer isn’t handled well, a long task may stop halfway.

I don’t want to abolish approvals; I just don’t want them all coming to me

After understanding these three layers, I also corrected my original idea.

I had thought the solution might be:

open up every permission so AI stops asking.

But that isn’t really a good direction.

The network, files, credentials and production environments should have boundaries. Especially when AI can run commands, change code and connect to outside services, having no limits at all isn’t worth pursuing.

The real question isn’t “why do approvals exist,” but:

which approvals really need my judgment, and which could the system handle according to established rules?

I don’t need to personally decide whether each local server start is reasonable, nor do I want to keep approving routine Git operations that are already part of the release flow.

Where I need to step in is:

  • whether the product direction has changed;
  • whether the scope of work has grown;
  • whether the architecture or data structure changes;
  • whether new permissions or costs are involved;
  • whether destructive operations are needed;
  • whether something abnormal appears in production.

Those are the judgments a PM or project owner should make.

Technical boundaries can still exist, but they shouldn’t escalate into a business decision every time.

You can first set system defaults that suit you

Afterwards, I didn’t choose to open up all of Codex’s permissions.

I used a fairly conservative set of defaults better suited to continuous work:

  • allow normal writes within the current project or a separate worktree;
  • don’t additionally open up the whole computer or unrelated directories;
  • network and out-of-workspace operations remain controlled;
  • out-of-bounds operations are approved as needed;
  • low-risk approvals that fit the rules go to Auto-review;
  • external services still use their own login and permission mechanisms.

The point of this setup isn’t “more permissions,” but:

day-to-day work inside the project runs as smoothly as possible, while checks remain when boundaries are truly crossed.

Writable within the project

If AI can’t even handle the files, Git state or separate worktree in the current project properly, development tasks will naturally keep stopping.

But that doesn’t mean it needs access to the whole computer.

Usually opening only the scope the current project needs is enough.

Network permissions

If the task explicitly includes:

  • fetch and push;
  • creating or updating a PR;
  • checking deployment status;
  • accessing necessary remote services;

you need to confirm in advance how these operations will be approved.

Otherwise, AI only discovers after writing the code that it can’t reach the remote, and the whole “automatic release” breaks off halfway.

Auto-review

Auto-review doesn’t abolish safety boundaries; it changes who handles approvals.

Some routine, low-risk out-of-bounds requests can first go to an automatic reviewer instead of calling the user back every time.

What it solves is:

whether I personally have to click approve.

It won’t open up the network automatically, nor will it make protected paths unrestricted from then on.

But for me, that’s already important enough.

As long as the system can judge for itself within safe bounds, I don’t care how many internal approvals happen in the background. What I care about is whether the task keeps interrupting my attention.

External authentication

Logging in to external services needs handling separately too.

I also ran into a case that’s easy to misjudge:

a check in the ordinary sandbox showed the GitHub login seemed to have expired, but rechecking in an environment that could read the system Keychain, the login was actually still valid and remote access worked fine.

That taught me a very practical judgment:

the current environment not seeing a credential doesn’t mean the credential itself has expired.

Before asking the user to log in again, it should first recheck through actual remote access, or in an environment with the same access to the credentials.

Otherwise, a difference between environments can be misjudged as an authentication failure, creating yet another unnecessary human interruption.

System defaults only solve part of the problem

After adjusting the configuration, I found that just turning on Auto-review still wasn’t enough.

Because some pauses weren’t caused by system permissions, but by AI being unsure:

  • how far I had actually allowed it to go;
  • whether the next step still belonged to the original task;
  • whether a certain action needed business authorization again;
  • whether, when something changed, it should handle it itself or stop and ask me.

So “finish all of it” was still too vague.

A more effective way is to make three things clear at the start of a long task.

First: spell out the chain of results

Don’t just say:

finish this feature.

Instead, state which stages this task actually covers:

create a separate workspace

→ finish the implementation

→ run the tests

→ commit

→ push

→ create and update the PR

→ wait for checks

→ merge

→ wait for deployment

→ complete non-destructive production acceptance

Some tasks only need the code written.

Others require going all the way to production verification.

If the chain of results isn’t spelled out, AI may ask again on reaching every new stage:

should I keep going?

Second: say which steps it can handle autonomously

For example:

  • creating a separate workspace from the current main line;
  • syncing the latest code;
  • running existing tests;
  • fixing check failures within scope;
  • resolving conflicts that don’t change semantics;
  • updating the PR;
  • waiting for CI and deployment;
  • completing production checks already authorized.

These steps may still trigger system-level safety approvals.

But in business terms, they shouldn’t be treated as a new decision again.

In other words:

the system can keep checking boundaries, but AI doesn’t need to ask me again “do you still want to finish this task?”

Third: make clear when it must stop

What truly needs human involvement is usually not routine execution, but exceptions.

For example:

  • the product goal changes;
  • the original scope needs expanding;
  • the architecture needs changing;
  • a semantic conflict appears in a shared contract;
  • data migration or permission changes are involved;
  • new paid calls are needed;
  • an unplanned destructive operation comes up;
  • authentication, rechecked the right way, really has expired;
  • something abnormal appears in production.

This part can’t be skipped.

Otherwise, “fewer approvals” easily turns into “letting AI guess when it’s unsure.”

My understanding of complete authorization now is:

not telling AI it can do anything, but spelling out the chain of results, the scope of autonomy and the stopping conditions.

A reusable authorization template for long tasks

Later I started expressing it at the start of a task in something like this way:

This task’s authorization covers:

- creating an isolated workspace;

- completing the implementation and tests within scope;

- commit, push, creating and updating the PR;

- waiting for checks, resolving non-semantic conflicts within scope, and merging;

- waiting for deployment and completing non-destructive production verification.

The routine steps above belong to the same chain of results and don’t need to be asked about again as business decisions.

You must pause in the following situations:

- a change in product or architecture direction;

- an expanded scope of work;

- a semantic conflict in a shared contract;

- changes to data migration or permission boundaries;

- new paid calls;

- unplanned destructive operations;

- authentication that, rechecked in the right environment, has really expired;

- abnormal production state.

It can’t bypass the system’s safety mechanisms, nor replace external logins.

But it can reduce another common kind of interruption:

AI coming back to ask at every step because it doesn’t know the user’s real authorization boundaries.

After the adjustment, tasks really did run more continuously

Later, I completed another long task with the adjusted settings and way of authorizing.

It covered implementation, tests, a PR, merging, migration, deployment checks and production UAT.

That time, the release process no longer kept stopping to wait for me to handle approvals.

It did still hit a false negative in the authentication environment along the way, but AI rechecked through actual remote access and carried on, without asking me to log in again.

This is just one later sample. It can’t prove every future task will go smoothly, nor show how much a particular setting reduced interruptions.

But at least one thing changed:

the safety judgments in the system still exist, but no longer all turn into manual work for me.

That’s exactly the result I wanted.

Finally, the takeaways I got

1. “I allow you to finish the task” only solves the first layer of authorization

It can’t automatically open up system permissions, nor replace external services’ logins and account permissions.

2. Before a long task starts, check the default execution environment

At the very least, know:

  • where in the current project is writable;
  • how network access is approved;
  • who reviews routine out-of-bounds requests;
  • whether external credentials work normally in the current environment.

Don’t wait until the task is halfway through to deal with these basics one by one.

3. Replace “finish all of it” with a chain of results, a scope of autonomy and stopping conditions

“Finish all of it” expresses intent.

An authorization that can really be executed needs to say how far to go, which steps can be done autonomously, and when it must pause.

4. Automation isn’t better the more permissions it has

A more sensible state is:

  • routine paths run smoothly;
  • low-risk approvals are handled automatically;
  • external identities are prepared in advance;
  • real anomalies still go to a person.

5. Measure the interruptions that actually land on the user

I don’t care how many safety judgments exist in the background.

What I care about is:

how many times I really need to come back and decide, and whether those decisions are ones only I can make.

AI autonomy isn’t abolishing every boundary.

What I want isn’t an AI that never asks, but one that only stops to ask when it truly needs my judgment.

Written in Chinese and translated into English with the help of AI. Read the original