When discussing whether a coding agent is strong enough, we usually ask first: what model does it use?

Which model version is it? What reasoning effort is enabled? How large is the context window? How reliable are its tool calls? These questions matter because the base model defines important boundaries on what the agent can do.

But when building real agent systems, we quickly encounter a harder phenomenon to explain:

The same model can behave very differently under a different harness.

Here, the harness is the system layer between the model and the real execution environment. It determines what context the model can see, which tools it can call, how those tools are presented, how execution results are returned, when context is compressed, how failures are recovered from, and how a task continues from start to finish.

In an earlier article, “Harness Engineering: Engineering Beyond the Model”, I described the harness as the execution structure outside the model: tools, permissions, validation, observation, memory, and feedback jointly determine whether an agent can work reliably. Following that line of thought leads to a more specific question: even if two harnesses provide the same capabilities, do they expose those capabilities in forms that are equally easy for a model to use?

I use model ergonomics to describe this fit.

This is not yet a rigorously standardized academic term. Existing work more often uses concepts such as Agent-Computer Interface (ACI), agent scaffolding, tool interface, or harness design. But model ergonomics is a useful name for an increasingly important engineering question:

Does a harness expose environmental capabilities in a form that a particular model can understand, reason about, act through, and recover through easily?

This means that an agent’s observed capability cannot be attributed only to the model, or simply to the harness. What matters is the fit between the two.

A Harness Is Not Merely a Wrapper Around the Model

Early large-language-model applications can easily be understood as a simple pipeline:

task

model

answer

But the real execution process of an agent system is closer to:

task

harness constructs observation

model reasons

harness exposes actions

model selects action

harness executes

harness transforms feedback

model reasons again

...

The model does not interact directly with the computer. It interacts with the world constructed for it by the harness.

When SWE-agent introduced the Agent-Computer Interface in 2024, it made this point explicit: language-model agents are a new kind of computer user, so the interface designed for them can significantly affect their behavior and performance on software-engineering tasks.1

This suggests that observed agent capability is closer to:

Capability = f(Model, Harness, Environment, Budget)

rather than:

Capability = f(Model)

The Model × Harness interaction term is especially important.

The 2026 work Harness-Bench studies this issue more directly. It treats tools, context, state, permissions, constraints, and recovery mechanisms as parts of the harness and compares execution trajectories across model-harness configurations. One important conclusion is that agent capability is better reported at the model-harness configuration level than attributed to the base model alone.2

So, in an agent setting, “How strong is this model?” is itself an incomplete question.

A more precise question is:

Under what harness, tool environment, context policy, and execution budget can this model exhibit what level of capability?

Model Ergonomics Is About More Than Whether Something Is Possible

Model ergonomics can easily be misunderstood as “write some extra prompts for a specific model.”

Its scope is broader than that.

The fact that a model can theoretically perform an operation does not mean the current harness gives it the best interface for performing that operation.

Suppose a model has only one very powerful tool:

exec_command(command)

From a capability perspective, the model can use it to construct almost an entire local toolset for itself. With shell, Python, Perl, awk, or other programs, it can read files, traverse directories, search, batch-process data, modify files, and run tests.

From the perspective of whether an operation is expressible, a general shell is therefore close to Turing-complete.

But expressiveness is not the model’s only problem.

The model must also decide what action to take next, construct the correct parameters, control side effects, understand tool results, and recover after failures. Harness quality therefore also depends on questions such as:

  • Can the model easily select the correct action?
  • Is the action granularity appropriate?
  • Are tool parameters easy to generate reliably?
  • Do tool results contain enough information without excessive noise?
  • Are errors easy to classify?
  • Does the context preserve the state needed for the next step?
  • After a mistake, can the model easily return to a productive trajectory?

Therefore:

capability completeness ≠ ergonomic fit

An interface can have extremely high theoretical expressive power while forcing the model to make too many low-level decisions.

Another interface can provide many convenient structured tools but expand the action search space because the tools are numerous and semantically overlapping.

Model ergonomics is about the relationship between these two extremes.

Running Grok on Codex: What Comes After Protocol Compatibility

This issue becomes concrete when running Grok on the Codex harness.

Our goal is not to reimplement a Grok coding agent. It is to preserve as much of Codex’s existing execution system as possible, including Thread and session lifecycles, context and history, sandbox and approval, MCP, Code Mode, Multi-Agent, ToolRouter, and the App Server and UI contract.

The corresponding architecture principle is:

Stock Codex owns the harness. Provider adaptation owns backend differences.

In the current design, the Grok Provider is mainly responsible for real protocol differences between Codex and the Grok Responses API: request/history projection, the Grok Responses dialect, projecting Codex’s canonical namespaced tools into flat functions that Grok accepts, and restoring returned calls to their canonical Codex tool identity.3

These are all forms of Provider compatibility.

They answer this question:

Can the existing Codex harness work correctly through the Grok API?

But once the model starts executing real coding tasks, another class of problem appears.

For example, when several files must be read at once, we have observed Grok repeatedly generating temporary Python programs through exec_command:

python3 - <<'PY'
from pathlib import Path

for path in paths:
    print(Path(path).read_text())
PY

This does not mean Grok cannot use Codex.

On the contrary, it successfully uses the shell exposed by Codex and can usually complete the task.

The more interesting question is:

Why does the model repeatedly reconstruct a file-reading abstraction inside the shell?

This is no longer a Provider protocol problem.

It is a model-ergonomics problem.

Shell Is a General Interface, but Not a Neutral One

In the current Grok-enabled Codex release/rust-v0.151.0, the model catalog for Grok 4.6 configures UnifiedExec, while apply_patch_tool_type is None.4

Codex’s tool-planning code registers exec_command and write_stdin for Unified Exec. The stock ApplyPatchHandler enters the tool registry only when model_info.apply_patch_tool_type is present.5

So, in this specific configuration, Grok receives a highly expressive shell but does not receive Codex’s native apply_patch tool.

This fact alone does not prove that the harness design is wrong.

It certainly does not prove that “giving Grok more file tools will necessarily improve performance.”

But it exposes an easily missed property of a generalized harness:

A general interface does not mean an interface without design bias.

If every model is given the same interface:

shell(command: string)

this can look highly generalized. Any model can use it, and a large set of computer operations can be expressed through it.

But choosing shell as the universal action representation is itself a strong design decision. It assumes that the model can reliably handle shell syntax, quoting, batching, side effects, stdout, and combinations of tools such as grep, sed, find, and Python.

For a model that is strong at these operations, this freedom can be highly effective.

For another model, the same freedom may simply enlarge the action space and add execution ceremony.

So a generalized harness is not “free of specialization.”

It often hides specialization inside an abstraction that has been treated as sufficiently universal.

GrokBuild Is a Design Signal, Not a Conclusion

xAI’s open-source GrokBuild provides an interesting comparison.

Its tool runtime contains a group of tools explicitly marked as Codex-specific:

apply_patch
grep_files
list_dir
read_file

The source describes these tools as ports and modifications of Codex implementations.6

It is easy to draw a conclusion that is too strong:

GrokBuild has read_file, so Grok must also have read_file when running in Codex.

There is not enough evidence to support that conclusion.

The GrokBuild design proves only that xAI chose to expose these structured file operations when building its own coding harness for Grok.

But the comparison is still useful.

Two harnesses that both aim to let Grok perform software-engineering tasks can choose very different action vocabularies:

Codex                  GrokBuild

exec_command           read_file
write_stdin            list_dir
...                    grep_files
                       apply_patch
                       ...

If the same model behaves very differently in the two environments, the difference cannot be attributed entirely to model weights.

More importantly, GrokBuild’s ToolConfig separates canonical tool identity from client-facing presentation. It supports overrides for tool names, parameter names, and descriptions.7

This suggests an important architectural direction:

What a tool is and how the model sees that tool do not necessarily need to live in the same layer.

That principle is more valuable than simply copying GrokBuild’s particular tools.

Generalized and Specialized Harnesses Are Not a Binary Choice

Once we accept model ergonomics, it is easy to move to the opposite extreme: if different models prefer different interfaces, maintain a dedicated harness for each model.

For example:

Model A ToolRouter
Model B ToolRouter
Grok ToolRouter
...

In the short term, this can make it easy to improve benchmark scores.

If a model does not use one tool well, replace it with another. If a context layout performs poorly, add a model-specific branch. If a model often stalls at a particular point, add a dedicated recovery rule.

If this continues, however, another class of problem appears:

semantic divergence
test explosion
model-version drift
duplicate runtimes
upgrade difficulty

Models themselves continue to change.

A workaround that is necessary today may become useless after the next model update, or even restrict a newer model’s capabilities.

So the real question is not:

Generalized harness or specialized harness?

It is:

What should be generalized, and what may be specialized?

I currently prefer to separate the system into three layers.

┌────────────────────────────────────┐
│ Model Ergonomic Profile            │
│                                    │
│ tool presentation                  │
│ observation granularity            │
│ context policy                     │
│ reasoning defaults                 │
│ guidance / recovery                │
└────────────────┬───────────────────┘

┌────────────────▼───────────────────┐
│ General Semantic Harness           │
│                                    │
│ canonical tools                    │
│ ToolRouter                         │
│ sandbox / approvals                │
│ history / context                  │
│ multi-agent                        │
│ lifecycle / state                  │
└────────────────┬───────────────────┘

┌────────────────▼───────────────────┐
│ Provider / Wire Adapter            │
│                                    │
│ auth / endpoint                    │
│ request dialect                    │
│ reasoning projection               │
│ tool wire encoding                 │
│ response normalization             │
└────────────────────────────────────┘

Each layer solves a different problem.

The Semantic Harness Should Remain General

The first layer is the general semantic harness.

Model-specific implementation should be avoided here as much as possible.

Operations such as Read File, Apply Patch, Exec, MCP Call, Web Search, and Spawn Agent can all be understood as canonical semantic operations in an agent system.

Likewise, sandboxing, permissions, history, tool lifecycle, persistence, and cancellation should remain unified.

The most important requirement at this layer is not that every model sees exactly the same interface. It is that:

Execution authority must remain singular.

If Codex already owns the ToolRegistry, ToolRouter, sandbox, history, and extension runtime, then creating a separate Grok ToolRouter just to support Grok usually means the architecture is beginning to split.

This is also the boundary maintained by the current Codex Third-Party Provider North Star: Codex core keeps the canonical concepts, while Provider-specific behavior is projected only at the narrowest backend boundary.8

Provider Compatibility Should Cover Protocol Differences Only

The second layer is Provider compatibility.

This layer can be specialized because different backends do have real protocol differences.

For Grok, for example, it can handle:

logical Codex reasoning

Grok wire reasoning

canonical namespaced tool

backend-safe function name

reverse projection

canonical Codex identity

canonical history

Grok-compatible request representation

This specialization has a clear source: the backend contract is different.

It answers:

How can unified Codex semantics pass correctly through different Providers?

If a difference cannot be explained by the Provider API, wire protocol, or backend behavior, we should be cautious before deciding that it belongs in the Provider layer.

For example, even if experiments eventually validate that “Grok prefers read_file to shell,” that is not a protocol fact about the Grok Responses API.

It belongs to another layer.

The Model Ergonomic Profile Controls What the Model Sees

The third layer is model ergonomics.

It addresses this question:

Once the harness can run correctly, how should its capabilities be presented to the current model?

This layer may control things such as:

  • Which canonical tools are exposed directly to the model;
  • How tool names and descriptions are presented;
  • How parameter schemas are organized;
  • Action granularity;
  • Context compression;
  • The level of detail in tool results;
  • Reasoning defaults;
  • Recovery hints;
  • Direct, deferred, or other tool-exposure policies.

The most important boundary is:

Specialize the interface, not the execution authority.

Suppose future benchmarks show that Grok performs substantially better with read_file than when it must organize file reading through exec_command.

The correct direction is more likely to be:

model-facing read_file

canonical filesystem operation

stock Codex execution environment

rather than:

GrokReadFileRuntime
GrokFileSystem
GrokToolRouter

The first changes the model interface.

The second begins duplicating harness semantics.

Capability and Ergonomics Are Different Kinds of Facts

If model ergonomics is eventually introduced into model profiles, ergonomic preferences must not be confused with capabilities.

For example:

supports_image = true

describes a capability.

It answers:

Does this execution path support images?

By contrast:

prefer_file_tools_over_shell = true

if a policy like this exists in the future, would describe an ergonomic preference.

It answers:

According to the current benchmark evidence, does this interface make it easier for the model to perform reliably?

The stability of these two facts is very different.

Capabilities usually come from definite facts about an API, a model, or the complete execution path.

Ergonomic policies are empirical conclusions. They can become invalid when the model version, system prompt, tool implementation, or training method changes.

Model ergonomics should therefore satisfy several conditions:

  • It has benchmark or trajectory evidence;
  • It can be replaced independently;
  • It can be regression-tested;
  • It does not become a durable semantic contract;
  • A single observation does not hard-code it into long-lived architecture.

This is why seeing Grok use Python is not enough reason to add read_file.

Behavioral anomalies are starting points for investigation.

They are not design conclusions.

Model ID May Not Be the Final Abstraction Either

Going further, model ergonomics may not ultimately be modeled entirely around model IDs.

We can of course select different profiles from identifiers such as:

grok-4.6
model-a
model-b

But the more important properties may be the behavioral dimensions behind the model, such as:

shell fluency
tool-schema adherence
parallel-call reliability
context-noise tolerance
self-recovery strength
action-granularity preference
planning reliability

These dimensions are not yet standardized enough to justify turning them into a formal schema today. Doing so would be premature abstraction.

But they point toward the more important research question.

What we really want to know is not:

What special code should Grok have?

It is:

Under what interaction regime can Grok complete tasks most reliably?

The same question applies to different models in the same family, different reasoning configurations, and even different versions before and after a model upgrade.

A shared API does not imply an identical optimum for agent interaction.

Harness Quality Has at Least Two Dimensions: Generality and Adaptability

Once we accept this view, “Is this harness good?” also requires a more precise definition.

The first dimension remains Generality:

How many models can connect? How many Providers can run? How many environments can be supported?

This is portability in the traditional sense.

But there should also be a second dimension: Adaptability.

It asks:

After connecting a new model, how much additional mechanism is required for it to approach its own agent-capability frontier?

This gives us two very different kinds of systems.

One harness may support one hundred models, but expose every model to the same lowest-common-denominator interface.

Another may preserve the same semantic kernel while allowing different models to use validated tool presentation, context policies, and recovery policies.

Counting only “how many models are supported” cannot distinguish the quality of these two harnesses.

We can even describe the idea with a concept that is not mathematically rigorous but is still useful:

Harness Efficiency(Model)
    =
Observed Agent Capability(Model, Harness)
    /
Potential Agent Capability(Model)

The denominator cannot be observed directly, so this is not an engineering metric that can be calculated literally.

But it expresses an important goal:

A good harness should do more than let a model run. It should reduce the capability lost in the interface and execution loop.

The Benchmark Unit Should Be Model × Harness

This also changes how benchmarks should be designed.

Suppose we observe:

Model A + Harness X = 70
Model A + Harness Y = 48

Model B + Harness X = 52
Model B + Harness Y = 69

Then “Is Model A or Model B stronger?” is no longer a fully specified question.

At minimum, it should become:

Under what harness, budget, and environment is which model-harness pairing more effective?

The recent work Same Model, Different Harness takes a more direct approach: hold the model fixed, change context management and stalled-work handling, and observe changes in coding-agent results. It is still a relatively recent preprint, so its specific findings should not be treated as settled consensus on their own, but the experimental design clearly illustrates how harness effects can be isolated.9

Self-Harness approaches the question from another direction: discover model-specific failure patterns through execution traces, propose small harness modifications, and validate them through regression testing.10

Together, these works point toward a methodology:

Model ergonomics should be studied through controlled experiments, not decided because “this tool call looks inelegant.”

Back to Grok: How Model Ergonomics Should Be Validated

For Grok’s tendency to organize file operations through Python inside Codex, I would therefore not begin with “How do we stop it from writing Python?”

Python is not a failure.

We should first define the observations that actually matter, such as:

  • Task success;
  • Patch correctness;
  • Token usage;
  • Tool-call count;
  • Latency;
  • Invalid-action rate;
  • Recovery rate;
  • Unnecessary shell complexity;
  • Approval and sandbox surface.

Then compare controlled harness configurations, for example:

A. current Codex tool surface

B. current surface
   + improved tool guidance

C. current surface
   + stock apply_patch

D. current surface
   + read_file

E. current surface
   + read_file / list_dir / grep_files

If the results are:

A  61%
B  62%
C  69%
D  69%
E  72%

then ergonomic specialization has clear value.

If the results are only:

A  61%
E  62%

while maintenance cost and the tool surface both grow significantly, then reducing Python invocation from 80% to 10% has little engineering value by itself.

Prettier tool calls do not necessarily mean a stronger agent.

Why apply_patch Is a Better Early Experiment

In the current Grok × Codex implementation, I would investigate apply_patch before immediately adding the full read_file / list_dir / grep_files tool family.

The first reason is architectural cost.

Codex already has a stock ApplyPatchHandler; the current Grok catalog simply does not enable the corresponding apply_patch_tool_type.

So validating whether Grok can correctly use stock apply_patch through the existing reversible tool projection is a narrower experiment than adding an entirely new toolset.

Second, a structured tool has value beyond model ergonomics: it preserves semantic intent.

When the model calls:

apply_patch

the harness knows that the model is modifying files.

When the model modifies files through:

exec_command("python3 ...")

all semantic meaning is hidden inside arbitrary code execution.

The first form is easier to integrate with sandboxing, approval, tracing, telemetry, replay, and failure classification.

So the value of a structured tool should not be measured only by whether the model prefers to call it.

It can also make agent actions more intelligible to the harness as a whole.

If File Tools Are Needed, They Still Should Not Duplicate the Runtime

Suppose benchmarks eventually show that Grok benefits significantly from read_file, list_dir, or grep_files.

That still does not mean GrokBuild’s entire tool runtime should be ported into Codex.

Codex already allows extension tools to enter the same ToolRegistry and ToolRouter.11

A more reasonable structure would therefore be:

model-facing compatibility tool

Codex extension adapter

stock filesystem / sandbox context

stock ToolRouter

The model gets an action vocabulary that is easier for it to use, while the system still keeps:

one history
one router
one sandbox
one execution authority

This is the key to making a generalized semantic harness and specialized model ergonomics coexist.

Generalize Semantics; Specialize Interaction

In the end, I think the most useful boundary between generalized and specialized harnesses can be compressed into one sentence:

Generalize semantics as much as possible; allow measured specialization in ergonomics.

The corresponding system structure is:

Generalized Semantic Harness
        +
Thin Provider Compatibility Layer
        +
Measured Model Ergonomic Profiles

The first layer prevents the system from fragmenting as the number of models increases.

The second handles real protocol differences between backends.

The third accepts an increasingly visible fact: different models are not identical “API consumers.”

They can have different tool-selection habits, context tolerance, action granularity, recovery patterns, and execution biases.

A mature harness should not pretend these differences do not exist.

But it also should not reimplement an agent runtime for every model because of those differences.

The difficult part, and the part that most clearly demonstrates the quality of harness engineering, is to preserve unified semantics, safety boundaries, and execution authority while allowing the interface to be adjusted in limited and verifiable ways according to actual model behavior.

At first, the primary question was:

Can the model run?

Then it became:

Can the model use tools?

Later:

Can the model finish long-horizon tasks reliably?

Model ergonomics moves the question one step further:

Does this harness allow this model
to use its capabilities efficiently and reliably?

This may become a fundamental dimension for evaluating agent harnesses.

The model determines the potential boundary of agent capability. The harness determines how those capabilities are converted into reliable real-world behavior, and how much of them survive that conversion.

What needs optimization has never been only the model.

It is the entire model-harness system.

Footnotes

  1. John Yang et al., SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering, 2024.

  2. Yilun Yao et al., Harness-Bench: Measuring Harness Effects across Models in Realistic Agent Workflows, 2026.

  3. The Grok × Codex case in this article is based on the release/rust-v0.151.0 branch of Harness-X-Harness/codex. In that implementation, the Grok Provider handles Provider-specific adaptation such as request projection, the Responses dialect, and flat-function projection.

  4. In grok_catalog.rs, the current Grok 4.6 catalog configures shell_type: UnifiedExec, apply_patch_tool_type: None, and tool_mode: None.

  5. In spec_plan.rs, Unified Exec registers ExecCommandHandler and WriteStdinHandler; ApplyPatchHandler is registered only when model_info.apply_patch_tool_type.is_some().

  6. xAI GrokBuild’s implementations/codex module contains apply_patch, grep_files, list_dir, and read_file. The source describes them as Codex-specific tool implementations ported and modified from Codex.

  7. GrokBuild’s ToolConfig supports name_override, params_name_overrides, and description_override, separating internal tool identity from client-facing presentation.

  8. Codex Third-Party Provider North Star defines the goal as preserving the stock Codex harness and placing only verified backend API differences at the Provider projection boundary.

  9. Sydney Lewis, Same Model, Different Harness: Different Coding-Agent Results, 2026. At the time of writing, this was still a relatively recent preprint, so I cite it mainly for its research question and experimental design rather than treating the results of one paper as a final conclusion.

  10. Self-Harness: Harnesses That Improve Themselves, 2026.

  11. The current Codex spec_plan.rs combines core tools, MCP tools, extension tools, and dynamic tools into one ToolRegistry, then constructs a unified ToolRouter. This provides an existing boundary for adding model-facing compatibility tools without duplicating the execution runtime.