Day 068Working with AI7 min readChinese original ↗

70% of weekly Codex usage in two days

两天用了 70% 的 Codex weekly usage,我才发现 AI 开发的消耗不只发生在写代码时
TL;DR
  • I used 70% of my weekly Codex usage in two days. Looking back, most of it didn’t go into writing code, but into rereading context, premature parallelism, repeated verification and fixing the workflow itself.
  • The finer you split tasks, the more often you pay the startup cost again. Parallelism depends on contracts, not just files: don’t run several agents at once until the shared contract is stable.
  • I switched to one outcome, one main task, one active writer, and wrote these lessons into the project rules. The model decides how fast each step goes; the workflow decides whether the steps head to the same place.

Nearly 50% in one day, and more than 20% the next.

Two days in, I had already used over 70% of my weekly Codex usage.

When I saw the number, my first reaction was: did I pick too expensive a model? Did I start too many tasks? Did testing and releasing waste a lot of allowance?

But going back through the task records, I found these two days weren’t without output.

Several features were developed and released, and there was also a database migration rehearsal, production verification, bug fixes and release records. The problem was that these results were scattered across different features, fixes and process tasks.

If someone asked me:

what clearly visible product progress did this 70% of usage finally buy?

I’d struggle to answer right away.

It wasn’t that nothing got done, but that a lot got done without a complete sense of “outcome.”

I don’t have a token ledger precise to every call, and what follows isn’t a financial audit of that 70%. It’s more a workflow retrospective: where did AI actually spend its time and consumption, which costs were necessary, and which could have been avoided?

Usage isn’t only spent on writing code

I used to instinctively think of Codex usage as “how much code got written.”

Only after reviewing did I realize code is just part of it.

The consumption of an AI development task roughly also includes:

  • reading product and technical docs;
  • understanding the codebase, data structures and past decisions;
  • checking the state of the current branch, workspace and other tasks;
  • coordinating shared dependencies across several tasks;
  • review, tests, migrations and releases;
  • retries after tool failures;
  • fixing problems in the development workflow itself.

AI looking busy all the time doesn’t mean the product is moving forward at the same speed.

It may have read lots of files, written long analyses, run several rounds of checks and set up new workspaces. But not all of these actions necessarily turned into new code, clear decisions or released results.

The first drain: the same context read again and again

After one feature package was released, I created a new, separate task and workspace for the next feature.

From an engineering-management point of view, that made sense: clear task boundaries, and less risk of overwriting the previous round’s changes.

But once the new task started, it had to reread:

  • the product plan for the current stage;
  • the technical design;
  • the database structure;
  • the API and front-end implementation;
  • the previous round’s handover notes;
  • build and release constraints.

Much of this had already been confirmed in the previous round.

As a result, while I thought AI was already “pushing the next step,” it actually spent a good deal of time rebuilding its understanding of the project, and that day mainly completed a review of the technical plan, without getting into a full implementation.

That isn’t pointless work.

But it made me realize:

splitting into more tasks doesn’t mean moving faster. Every separate long task has its own startup cost.

Small tasks with clear boundaries and little context are fine to split.

But if several consecutive tasks share a lot of product, architecture and code background, splitting them too finely means paying the context cost over and over.

The second drain: tasks that weren’t truly independent running at the same time

At the time, several lines of work were moving forward in overlapping windows.

To avoid overwriting each other, they used different branches or worktrees, and the files they changed didn’t look entirely the same.

But some of these tasks shared:

  • APIs;
  • database migrations;
  • shared types;
  • data models;
  • common components;
  • product decisions that weren’t fully settled.

As soon as one line of work changed any of these shared parts, another might have to pause, wait for a handover, resync and verify again.

That made me correct a judgment I’d made rather crudely:

files not overlapping only shows they won’t directly overwrite each other; it doesn’t show they’re logically independent.

Whether things suit running in parallel should be judged by whether the shared contract is stable, not just by whether both sides touch the same file.

I later summed it up in one line:

parallelism depends on contracts, not just files.

The situations that truly suit running long tasks in parallel usually need all of these:

  • outputs independent of each other;
  • shared interfaces and data structures already stable;
  • no unresolved upstream dependencies;
  • simple integration at the end.

Otherwise, what looks like two agents working at once may just be creating waiting, syncing and rework sooner.

The third drain: caution gradually became repeated verification

Testing, review and release verification aren’t waste, of course.

Without them, the rework you end up with may cost more.

The problem is that verification easily slides from “necessary evidence” into a fixed ritual:

  • a full check after every small step;
  • different tasks rerunning the same tests;
  • authorizations and boundaries already confirmed being asked about again by a new task;
  • every handover producing the same evidence all over again.

In one case, the model and effort a task had chosen temporarily got mistakenly written into the project-level default configuration.

That meant the model I chose in the interface for new tasks might be overridden by the project config.

Then the config’s impact had to be reviewed again, a fix committed and released, and verification done that the fixed setting had been removed.

That extra work wasn’t fixing the product, but fixing the AI workflow itself.

It also shows a problem:

a temporary choice in one task shouldn’t become a long-term rule without explicit authorization.

What should be reduced isn’t testing, but the same evidence being produced again and again.

A more sensible rhythm:

  • during development, run targeted checks directly related to the current change;
  • when an outcome is nearly done, do one full verification of the affected scope;
  • after release, do only the necessary production verification.

Strong models and high effort make the leaks drain faster

When I saw usage falling fast, the first thing I thought of was model cost.

But the model is more like an amplifier.

High-risk judgments, complex architectural conflicts and bugs that are hard to locate really do need a stronger model and higher effort.

But routine implementation, tests, migrations and well-defined release steps don’t need the top configuration throughout.

If the workflow already has:

  • repeated context loading;
  • premature parallelism;
  • repeated confirmation;
  • excessive verification;

then handing every task to the strongest model won’t solve these problems; it’ll only make the same path drain faster.

I later started choosing models with a simpler question:

is the hard part right now execution, or judgment?

If the hard part is just implementing a clear plan, a good-enough model will do.

If the hard part lies in complex debugging, architectural trade-offs, permissions or data risk, then raise the model and reasoning effort.

The top settings should be saved for problems that are genuinely unsolved and where mistakes are costly.

Redefining the unit of work in AI development

After the retrospective, I no longer default to “a small feature” or “one conversation” as the unit of work.

I now lean toward organizing tasks around one complete, verifiable outcome:

one clear, verifiable outcome → one main task → one main writer (active writer) → targeted checks during development → one full verification when nearly done → release and necessary production verification → a one-time handover

“One active writer” here doesn’t mean the whole project can only ever have one agent.

It means a continuous, long-chain outcome is by default owned by one main agent that actually writes and pushes it forward, so several agents aren’t interpreting the same product and technical boundaries at once.

Only when tasks are truly independent should long tasks run in parallel.

One outcome, one main task, one active writer; parallelism depends on contracts, not just files.

Write lessons into rules, instead of reminding each time

If every time I develop something I have to remind AI again:

  • don’t reread irrelevant material;
  • don’t casually start long tasks in parallel;
  • don’t do a full review at every step;
  • don’t write temporary choices into project defaults;
  • don’t keep asking after authorization has been given;

then these lessons haven’t really made it into the workflow.

So I wrote this retrospective into the project rules:

  • by default, one long task and one main writer;
  • check shared contracts and upstream dependencies before parallelizing;
  • use targeted checks during development;
  • do full verification only when close to release;
  • automatic code review isn’t a fixed ritual for every step;
  • models and effort aren’t permanently fixed in the project config;
  • when usage drops abnormally, pause to find the cause, but don’t keep polling the numbers.

The user is still responsible for goal priorities, and for decisions that change the product, architecture, risk, cost or external state.

AI should be responsible for narrowing the scope, controlling context, choosing the smallest sufficient verification, and proactively avoiding duplicated work.

After the adjustment

Later, I used this approach to complete a new high-risk cross-platform release task:

  • using a separate workspace;
  • keeping one serial writer;
  • running targeted checks during development;
  • doing one full regression before release;
  • completing one migration rehearsal;
  • doing one non-paid UAT;
  • and finally completing the release and release record together.

I can’t yet say the new way of working has significantly reduced usage.

Without comparable before-and-after data, that conclusion wouldn’t be honest.

But at least a few things became clear:

  • what exactly this delivery was;
  • who was responsible for the actual writing;
  • which work could be done in parallel;
  • which verification had to happen now;
  • which could wait until just before release.

For a project developed with AI, that clarity is valuable in itself.

More important than how much allowance was used: what was the output?

Usage still needs watching.

But I no longer only ask:

how much did this use?

I care more about:

what did all this consumption finally buy?

Code that runs, verification that passed, clear decisions and completed releases?

Or yet another context reload, repeated confirmation, coordination between tasks, and rework created by the workflow itself?

The cost of AI development doesn’t come only from model prices and tokens.

It also comes from how tasks are split, how context is passed along, how parallelism is organized, and whether verification fits the current risk.

The model decides how fast each step goes; the workflow decides whether the steps head to the same place.

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