How Antimetal right-sizes agents with an epistemic workspace
How we match agent effort to incident complexity.

Why production incidents break coding agents
Coding agents are good at resolving software issues because most of the context sits in the code and documentation in front of them, and because they can run tests to close the loop quickly.
A live production incident removes both advantages. The symptom is observable, but the cause can live entirely outside the code, in a config value, a deploy, or a third-party system. When we put coding agents up against real incidents, we ran into three problems.
- Complexity of incidents varies wildly: A production incident can span multiple systems and end deep in the codebase, or come down to one system, one place, and a straightforward fix. The incident itself tells you which: whether the alert names a failing component or only a symptom, how many systems its evidence spans and how much telemetry sits in the window. As a result of this varied complexity, coding agents under-engineer the complex problems and over-engineer the simple ones, and the cost is wasted latency, unnecessary token expenditure, and incorrect fixes.
- Context lives outside the code, and facts decay over long runs: Most of what the agent needs sits with integration providers before it ever touches the code: tickets in Jira, docs in Linear, traces in Datadog, Betterstack, and CloudWatch. Gathering this is only half the problem. Summarizing and offloading it just compresses what was gathered, without answering whether the right things were gathered. The agent has to pull out the code constraints and architectural conventions a fix must respect, and hold them in a structured form downstream agents can read without early facts decaying over a long run.
- There is no test to close the loop in production: With a GitHub issue, the agent runs the test suite and knows whether the fix works. A production incident usually has no failing test to run; the fix might not even be code. The agent has to be its own verifier, and an agent left to verify itself defaults to confirming its own work.
How Antimetal agents push past this constraint
Our solution has three components, one per problem: an incident complexity router that decides how much reasoning an incident deserves, an epistemic workspace where that reasoning is captured, and an adversarial verification nudge that makes each agent try to break its own findings before the fix is finalized.
- Right-size the reasoning: We score the incident's complexity up front by tuning a router agent on thousands of production incidents, and then set a reasoning budget based on that: how many agents to spawn in parallel, how deep the agents should go, prompts that the agents carry, and the model / inference parameters that they run with.
- Curate what matters into the epistemic workspace: As Antimetal agents run, they capture not the raw context but the pieces that matter: the causal reasoning behind the incident, the core code constraints, and the architectural conventions the fix must respect, curated from the multi-provider context into a structured virtual filesystem that downstream agents read directly. Each entry is marked as verified, with the provider and query it came from, or as a hypothesis, so facts established early do not decay as the run grows and raw payloads never enter the context of downstream agents.
- Adversarial verification nudge: Because the agent has to be its own verifier, we make it argue against itself. Once per run, a checkpoint fires and forces the agent to stop and look for the hole in its own reasoning before it commits a finding. The agent has to name the existing repo pattern its fix reuses and show a concrete source for every constraint it is leaning on. If the fix is anything larger than the smallest mechanism that works, it has to justify the extra weight. It also has to name at least one alternative it considered and ruled out, along with the evidence for rejecting it. This framing is adversarial on purpose: asking an agent to find the hole in its own reasoning calibrates it better than asking it to confirm its work.
With this approach, our agents are faster and more intelligent about the fix itself. They know when to produce a code fix and when not to. And the fix is grounded: because it is held to the workspace's verified constraints and code locations, it follows your architecture and conventions instead of the generic defaults in the agent's training data. The rest of this blog covers how a production incident flows through each of the solution components.
Step 1: A reasoning budget is assigned to a production incident
The first thing that happens to an incident is not investigation. It is scored based on its complexity. Before any agent reads a line of code, a lightweight verification router judges how complex the incident is and decides how much effort it is worth, sizing it onto one of the two paths:
- Shallow path: The incident has a single, named cause, like one exception in one stack frame in one service. We spawn fewer agents with pointed prompts and they run a tight investigation.
- Deep: The incident is ambiguous or has multiple causes, like a latency regression or a cascade across services with no clear culprit. We spawn more agents and they investigate deeper.
The router carries no tools and never investigates. It reads the incident, scores it against a rubric distilled from past production runs, and emits one structured decision:
- A
p_workspacescore from 0 to 1: The router's own confidence estimate of how much the incident needs the deeper, workspace-building path. A low score means the evidence points to a direct, shallow fix. A high one means the incident looks like it needs the full workspace. The score comes from the rubric below. - A mode, shallow or deep: This sets how many agents run and what they are allowed to build.
The router scores the incident based on the 4 axes below:
| Axis | Routes shallow | Routes deep |
|---|---|---|
| Signal specificity | One deterministic exception, a single stack frame, a named code location | A symptomatic aggregate with no single culprit, broad language |
| Source / provider | A specific integration with a stack and breadcrumbs, one error class | A composite SLO breach |
| Causal locality | Failure isolated to one service or one symbol | Multi-service involvement or a cascading topology |
| Likely fix shape | A config, env, or one-line code fix, when the evidence names what happened and when | A cross-service or performance regression, vague evidence, or a problem deep in the codebase |
The call made here is what the rest of the run inherits. It sets how much epistemic workspace gets built, how much evidence the fix is checked against, and how much reasoning budget is spent on the incident.
Step 2: Agents curate the epistemic workspace
Based on the path that the router picked, the spawned agents build the epistemic workspace.
Epistemic, from the Greek episteme, marks the line between what was observed and what was concluded.
The epistemic workspace is a set of structured artifact files in the virtual file system that contains the important portions of the raw context gathered from multiple providers, such as code constraints and architectural best practices. Each artifact that the agent produces in the workspace is downstream of problems with current coding agents and what is required to solve for each. Each pain point maps to a capability a vanilla coding agent needs, and each capability is one artifact the epistemic workspace produces.
| Type | Problem with current coding agents | Property it needs | How the epistemic workspace solves this problem |
|---|---|---|---|
| Structured context retrieval | What it learns lives as free text in its chat history, where one fact is hard to find and easy to lose over a long run. Most of the text is stored as raw blobs that is hard to search over. Summarized content misses out on key information. | Typed, addressable context that is structured and can be searched over easily. | Typed primitives and an INDEX manifest: One versioned record per issue, that later agents read by pointer instead of re-reading everything. Agents can read structured output easily and can progressively disclose what they want to explore in the codebase. |
| Causal reasoning | It reasons in prose, so the cause-and-effect chain blurs, correlation passes for causation, and it re-walks branches it already ruled out | Explicit causal reasoning tied to evidence. | A causal graph: A typed DAG where every node names the evidence behind it, and ruled-out branches keep their rejection evidence |
| Verified facts & code constraints | A guess and a checked fact sit together as sentences, so under pressure a hard constraint quietly decays into a suggestion. Agents lose attention over time, and simple context engineering is not an effective solution, so we want to store typed constraints instead. | Observed facts kept apart from guesses, each one sourced. | Constraints: Typed records that must name where each constraint was seen, a log, a line of code, or a test; anything reached by analogy is refused and moved to a hypotheses list. |
| Code grounding | It references symbols and files it never confirmed exist, and edits one without seeing what depends on it. It becomes tough for vanilla coding agents to cite every caller when a problem might be very deep in the codebase and might relate to hundreds of dependencies that need to be mapped and taken care of. This cannot be solved using the non-determinism of a large language model. | Verified code references with their blast radius. | Verified code locations: This artifact names a file, a symbol, and a status, and lists every caller of anything marked for change. We are experimenting with Language Server Protocol (LSP) for this to resolve every reference to the symbol instead of agents wasting compute and latency using filesystem tools. |
The workspace runs on one rule: Anything an agent reached by analogy instead of observation is refused as a constraint and moved to a hypotheses list the next agents can still reason over. And they read it all through progressive disclosure, following a manifest of pointers to the files they actually need instead of loading everything at once.
Step 3: Adversarial verification nudge
Before a fix is finalized, each agent turns on its own work and tries to break it. Once per run, we let each agent keep going and drop a self-rate adversarial checkpoint into its run. This is a steering mechanism - it fires once mid run and forces the agent to stop and grade itself on four questions:
| Check | What the agent must show |
|---|---|
| Reuse | The existing repo pattern the fix reuses, or what it grepped for if none. |
| Source | A concrete source for every constraint; unsourced claims demote to hypotheses. |
| Leanest fix | The smallest mechanism that works; anything larger has to be justified. |
| Alternatives | At least one alternative it ruled out, with the evidence for rejecting it. |
The framing is adversarial on purpose: asking the agent to find the hole in its own reasoning calibrates it better than asking it to confirm its work. Whatever survives the check stays in the workspace, and the final fix is held to it. Anything the agent could not back up with evidence gets demoted to a hypothesis.
Experimentation
We ran a controlled experiment on our agent harness with and without the epistemic workspace to isolate what the workspace and its right-sizing actually buys. The model and inference parameters used by each agent-harness was kept constant across a set of production issues. As a part of this experiment, we asked one question: Does the epistemic harness ship better, directly merge-able PRs and knows when not to ship code?
How we tested it
We tested the workspace against real production incidents. An offline agent-as-judge replays each incident from alert to proposed fix, applies the diff to a clean clone at the commit the agent saw in production, and scores it against the six-dimension rubric below.
| Dimension | Rubric component |
|---|---|
| Correctness | Does the diff fix the actual mechanism the investigation identified (root cause, not symptom)? |
| Architectural coherence | Right package/layer/abstraction; cross-component contracts honored. |
| Conventions & idioms | Reads like the surrounding code; reuses existing helpers (judged against the customer repo). |
| Failure-mode handling | Transient vs permanent distinguished; edge cases; no silent catch. |
| PR shape & scope | Minimum diff; no incident-detail leakage; problem/root-cause/fix/verification present. Operational fix when no code changes are required. |
| Buildability | Imports/symbols resolve at the pinned SHA; syntax/types parse; runtime assumptions hold. |
What we found
The harness with the epistemic workspace won the majority of incident families.
- It knows when not to ship code. On config and noise issues, the kind that are not real code defects, it returned an operational fix while the baseline shipped code anyway, and scored about 20-40% higher across those incidents. This was the clearest separation between the two systems, and the one we care most about, since a plausible-looking PR for a problem that was never a code defect wastes a reviewer's time and fixes nothing.
- It finds deeper root causes. On genuine code bugs (an over-strict validation gate, a deploy cache-policy issue, a missing index), it traced the real mechanism and fixed the logic, where the baseline patched the symptom or missed the cause entirely. It scored 20-25% higher on those bugs, and the causal graph is what got it there. With each step grounded in a source or a log, it followed the chain to the true cause instead of stopping at the first symptom.
- Fixes land at the right layer. Its most consistent margins, about 5% higher on each, came on fixing the real cause and sitting at the right layer, the two dimensions that decide whether a PR is mergeable. The verified code locations and their caller lists showed it where the change belonged and what depended on it.
- PRs are leaner. Single surgical diffs, no duplicate emissions. The self-check forced the leanest mechanism and made the agent justify anything larger, which kept every diff tight.
Conclusion
Everything above came from watching coding agents fail on real production incidents. We saw them burn tokens on simple problems and lose facts halfway through hard ones, and this system is what closing those gaps looks like today. We believe the future of agents in production goes further: agents that can build their own environment to work in, verify the fixes, curate the tools they have access to and how they interact with the context within it. We are pushing our agents towards that direction actively to improve agentic production engineering.





