Skip to content

Computation as Code

Reproducible computation shouldn't be done by the model as reasoning — have it write code and execute that instead. What disappears is error, not consumption — the answer becomes deterministic, and the procedure survives so it can be checked. This page doesn't claim it's cheaper. No one has measured which path costs less.

Problem

Numeric aggregation and unit conversion sometimes go wrong, and the way they go wrong is hard to spot — a plausible-looking number with a plausible number of digits comes back. The model does arithmetic as reasoning, so the answer is probabilistic — there isn't even a guarantee that the same input returns the same answer. Order it to "double-check," and the double-check is reasoning too — there's no escaping the loop of checking a reasoning error with more reasoning. Aggregation with no test, a sum no one verified by hand, a conversion waved through by eye — all of it carries the error downstream into a decision.

Context

Applies when:

  • The computation follows a fixed procedure — aggregation, conversion, diffing, ratios. Anything where a fixed input and procedure determine a unique answer
  • The same computation runs repeatedly — write the procedure into code once, and every run after that is just execution
  • The result feeds a downstream decision — anywhere a decision gets built on top of a number that might be wrong

Does not apply when:

  • It's a one-off rough estimate. Writing the code itself has a cost, and that cost doesn't always pay off for a throwaway estimate
  • It's a judgment, not a computation. "Is this estimate reasonable?" doesn't reduce to code
  • The input is ambiguous and normalizing it is itself a judgment call. If what to count and how isn't settled, deciding that isn't code's job

Boundary with neighboring patterns:

  • Separating Mechanical Gates from Semantic Gatesa different application of the same idea. That pattern puts verification on a deterministic means; this pattern puts computation on one. Both come down to "don't let a non-deterministic means produce an answer that could be produced deterministically"
  • Bounding Permissions by Structure — this pattern can collide with that one. Executing code requires execution permission. How to keep both while permissions stay tight is covered in the Practice section
  • Matching Thinking Depth to the Task — that pattern is a dial for how much to pay for reasoning; this pattern is the judgment to take work that doesn't suit reasoning out of reasoning altogether

Solution

Reasoning path versus code pathOn the reasoning path above, the model computes the input in its head, leaving only a number behind. The process leaves no trace, can't be checked, and the answer can change on rerun. On the code path below, the model writes code, a machine executes it, and a number comes out. Because the procedure survives as code, it can be checked, and rerunning it returns the same answer. The difference between the two paths is a difference in what survives.Reasoning path (only a number survives)InputModel computes it in its headNumberNo trace survives — unverifiable, non-deterministic, can change on rerunEven if it's right, there's no way to see that it's rightCode path (the procedure survives)InputModel writes codeExecution (machine)NumberCode survives= checkable, deterministic, same on rerunIf it's wrong, the error can be fixedThe difference between the two paths is what survives — the top keeps only a number, the bottom keeps the procedure

Have the model write the computation and execute it. Change the model's job from "produce the answer" to "write the code that produces the answer," and hand the job of producing the answer to a machine. Why does this work? Two reasons.

First, determinism. Computation is, by nature, a deterministic procedure. Given a fixed input and a fixed procedure, the answer is uniquely determined. Having the model do it means approximating a deterministic procedure with a probabilistic means.

The approximation is often right. The problem is that there's no way to tell whether it was — on the reasoning path, only a number survives; how that number was produced doesn't.

Put it into code, and regardless of whether the answer is correct, the same input is guaranteed to return the same answer. And because the procedure survives as code, when it's wrong, the error can be fixed.

A reasoning error can't be fixed the same way — there's no guarantee it will fail the same way next time either.

Second, the scope of responsibility that can be handed off. There's also the option of ordering a "double-check," but the double-check is reasoning too. As long as a reasoning error is being confirmed by more reasoning, the loop never closes.

Putting computation into code cuts this loop — it hands the judgment of whether something is correct over to a machine. Extending this separation beyond computation to verification in general is Separating Mechanical Gates from Semantic Gates.

This page's claim ends here. It doesn't claim "code is cheaper." Writing and executing code also consumes tokens — the output of writing the code, the tool calls, reading the result. This catalogue has no material that measures which is cheaper against doing it in reasoning. Not writing as if something were measured when it wasn't is this catalogue's convention. What Official does (and doesn't) say about cost is covered in the Practice section.

Trade-offs

Advantages

  • Becomes deterministic. Rerunning returns the same answer. Reasoning carries no such guarantee, and there's no way to see whether it was right either
  • The procedure survives. It can be checked. Errors can be fixed. When the same computation repeats, it can be reused directly. A reasoning path leaves only a number behind

Costs

  • Requires execution permission. Running code means letting a process do something, which puts this pattern in direct tension with the work of tightening permissions (Bounding Permissions by Structure). There's a mitigation that narrows execution scope through the permission pattern (Practice section), but the tension never goes to zero
  • Writing the code costs something. For a one-off rough estimate, code can cost more. And this catalogue doesn't write that "code is cheaper if it repeats" either — no material measures which path consumes more

GitHub Copilot in Practice

No dedicated feature corresponds to this pattern. It's a tool-independent practice, and no surface (VS Code / github.com / Copilot CLI / cloud agent) has a mechanism that instructs "do the computation in code." What the tools give is a place — an environment where code can be written and executed, and the permission to allow or deny that execution — nothing more. Whether that place gets used for computation is up to how it's operated. Below: how Copilot CLI does this practice while keeping permissions tight, and what VS Code's official docs say about cost.

Copilot CLI — write and execute, with shell permission kept narrow

Putting computation into code requires letting the written code execute. In Copilot CLI, shell execution is managed as a tool called shell, and the scope of what's allowed can be narrowed with permission patterns (source: CLI command reference, retrieved 2026-07-16) Official:

The --allow-tool and --deny-tool options accept permission patterns in the format Kind(argument). The argument is optional—omitting it matches all tools of that kind.

| shell | Shell command execution | shell(git push), shell(git:*), shell |

shell with no argument is permission for the entire shell. Running an aggregation script doesn't need that much opened up. The :* suffix narrows the scope in a way that prevents partial-match mistakes Official:

For shell rules, the :* suffix matches the command stem followed by a space, preventing partial matches. For example, shell(git:*) matches git push and git pull but does not match gitea.

The official example shows allow and deny stacked together Official:

shell
# Allow all git commands except git push
copilot --allow-tool='shell(git:*)' --deny-tool='shell(git push)'

Evaluation order is in the source text too Official:

Deny rules always take precedence over allow rules, even when --allow-all is set.

⚠ This "deny takes precedence" text is from the tool permission pattern section. A similarly worded statement exists separately for URL permission settings, but that one is about URLs — don't mix the two into a general "Copilot always denies first."

This operation is this pattern's practical connection point. As noted in Context, this pattern can collide with Bounding Permissions by Structure — but it isn't a binary choice between opening everything up or giving up. Allow only the scope needed to write and run an aggregation script, and stack deny on the operations you want closed off, and running code for computation and keeping permissions tight can coexist.

Don't confuse the two, though. This is "how permission is granted," not "the feature of putting computation into code." Giving the model a place and permission to execute doesn't stop it from doing the computation as reasoning anyway. "Don't do this aggregation in your head — write a script and execute it" has to be said on the prompt or instruction-file side — the tool only gives the place, not the instruction to compute there.

VS Code — what the official docs say about cost (and what they don't)

Having the model do computation as reasoning has a cost dimension too, and on the VS Code surface, the official docs link the amount of thinking causally to cost (source: Language models (customization), retrieved 2026-07-16) Official:

Higher thinking effort produces more thinking tokens, which increases AI credit consumption. Only increase thinking effort for genuinely complex tasks.

The overall picture of cost is on the same surface (source: Language models (concepts), retrieved 2026-07-16) Official:

Different models consume AI credits at different rates, based on the model and the number of tokens processed. More capable models cost more per token, while lighter models extend your usage further.

Other factors also affect credit consumption, such as thinking effort (higher effort produces more thinking tokens), context window size, and tool usage. Prompt caching lowers the effective cost of a request by reusing tokens from a previous one.

It's tempting to conclude from this that "putting computation into code makes that consumption disappear." That conclusion doesn't follow from the source text. All the source text says is "raising thinking effort produces more thinking tokens, which increases AI credit consumption" (the VS Code surface). The code path isn't free either — writing the code and calling tools both consume tokens, and the source text itself names tool usage as one of the factors that consumes credits. This catalogue has no material measuring which of the two paths costs less. This pattern's grounds are determinism and checkability, not cost. How to dial thinking depth is Matching Thinking Depth to the Task's subject.

Also Known As

NameSource
Computation as Code / Don't Let the LLM Do ArithmeticDescriptivethis catalogue's descriptive name; no primary source uses it

This pattern has, as far as could be confirmed, no established name — and no corresponding mechanism has a name either, since it's a tool-independent practice. Other patterns list an official mechanism name (Subagent, Prompt caching, etc.) as a related term in the Also Known As table, but this pattern has nothing that plays that role. The shell tool permission covered in the Practice section is the name for "how to build a place that can execute code," not the name for this practice. Using the place's name as the practice's name would create the misreading "allowing shell = doing computation in code." In reality, the model can still do computation as reasoning even with the place available.

Note also that this pattern went through a round of rejection and revival during this catalogue's selection process. The reason for rejection was "no corresponding tool mechanism" — but that criterion itself was the mistake. Being tool-independent is a reason for inclusion, not rejection. The more general a practice is, the less likely it is to have a tool-specific feature behind it.

  • Separating Mechanical Gates from Semantic Gatesa different application of the same idea. That pattern puts verification, this pattern puts computation, on a deterministic means. Two applications of the same principle: don't let a non-deterministic means produce an answer that could be produced deterministically
  • Bounding Permissions by Structuredirectly in tension. Executing code requires execution permission. Narrowing execution scope with a permission pattern lets the two coexist (Practice section), but the tension never reaches zero
  • Matching Thinking Depth to the Task — that pattern is a dial for how much to pay for reasoning; this pattern is the judgment to take work that doesn't suit reasoning (deterministic computation) out of reasoning altogether. This catalogue doesn't claim either path is cheaper, on either page
  • Making the Verification Target Explicit — if what to compute is left ambiguous, putting it into code still misses the target. The target has to be made explicit before computation happens
  • If reading just one more next: Making the Verification Target Explicit — having made it checkable, it's next to turn what gets verified into a contract