AI agents
Key points

Key points

  1. 1Two subagent instruction sets are behaviorally equivalent when every fixture in a shared suite stays inside a written tolerance band on tool sequence, argument values and final answer content.
  2. 2You cannot diff behavior by reading prompts; you diff it by running the same fixtures against both versions with identical tool mocks, seeds and model settings.
  3. 3A no-op edit (a typo fix, a reordered sentence that changes nothing) should be recorded as equivalent so it skips the release gate instead of consuming risk budget.
  4. 4Any fixture that crosses its band is a behavior change, and the number and severity of crossings feed the existing risk score rather than a separate process.

Why a text diff cannot tell you whether an agent changed

A subagent is defined by a markdown file that carries a name, a purpose, a tool list and a system prompt, and that prompt is the whole behavioral contract of the worker (Prompt Engineering's walkthrough). Because the subagent runs in its own context window, with its own prompt and its own tool access, a one-sentence edit lands directly on the worker's behavior rather than being diluted by the parent conversation (the orchestration guide).

This is why prompt edits regress silently. A revision that adds "be concise" can quietly drop a citation the agent used to include, and nothing throws an error (the prompt A/B guide). Teams that treat the system prompt as a configuration string discover the change days later as a support ticket, with no log line pointing at the edit (the production infrastructure talk). One reported incident in that talk: an error rate that moved from 0.3% to 18% overnight after an untagged clarification to a system prompt, at a cost of about $14k in refunds.

So the unit of comparison is not the text. It is the set of observable decisions the agent makes: which tool it calls, with which arguments, in what order, and what it hands back. Agent evaluation frameworks make the same argument, that exact-match assertions break down once the model chooses its own path, and that naming, arguments, order and outcome must be scored instead (Braintrust's testing guide).

Build the fixture suite before you need it

A fixture is a frozen task plus a frozen environment. Both versions of the instruction set must see exactly the same input or the comparison is meaningless. You need four ingredients.

Tasks. Twenty to forty prompts that cover the agent's real job, not its happy path. Include the ordinary request, the ambiguous request, the request with a missing field, the request that touches a sensitive tool, and at least one task the agent should refuse. Single responsibility is the stated best practice for subagents, so your task list can be narrow, but it must include the edge cases the prompt is supposed to police (Microsoft Learn's multi-agent guidance).

Tool mocks. Never run the comparison against live services. Stub each tool with recorded state so a refund is not actually issued and an email is not actually sent (Braintrust). The mock should return a fixed payload for a given argument set, which means you can compare arguments exactly.

Seeds and settings. Fix the model, temperature and any sampling seed, and record them in the run manifest. If the two runs use different models or settings, you are comparing models, not instructions.

A place for failures. When production produces a bad trajectory, add it to the suite as a new fixture. The test case list should grow from real failures rather than from imagination.

Fixture fieldWhat it holdsWhy the comparison needs it
task_idStable identifierJoins results across the two runs
promptVerbatim user or parent messageSame input for both versions
tool_stateSeeded mock responsesNo live side effects, reproducible
expected_classOutcome class, not exact textAllows multiple valid routes
bandTolerance settings for this fixtureDifferent fixtures tolerate different drift
model_settingsModel, temperature, seedIsolates the instruction change

Capture structured output on both sides

Free text is the wrong comparison surface, because two correct answers rarely share wording. Force both versions to emit a schema: the ordered list of tool calls, each with its name and a normalized argument object, plus the final answer and any explicit refusal. Structured output features exist precisely so the response adheres to a supplied schema instead of drifting in format (OpenAI's structured outputs guide), and agent SDKs expose the same pattern through a validated model on the result object (the Strands SDK docs).

A run manifest plus per-fixture record can be as small as this:

{
  "run_id": "instructions-b",
  "instructions_ref": "reviewer-agent@9f3c",
  "model": "<fixed model id>",
  "temperature": 0,
  "seed": 42,
  "fixtures": [
    {
      "task_id": "refund-missing-order-id",
      "tool_calls": [
        {"name": "lookup_order", "args": {"order_id": null}},
        {"name": "ask_user", "args": {"field": "order_id"}}
      ],
      "final_answer": "I need the order number before I can check the refund policy.",
      "refused": false
    }
  ]
}

Then compute three deltas per fixture. The sequence delta is an edit distance over tool names. The argument delta is a field-by-field comparison after normalization (lowercase enums, sort list arguments, trim whitespace, round floats to a stated precision). The answer delta is a similarity score against the reference answer, plus a hard check on required content such as a citation or a refusal. Keep the raw records so a reviewer can see exactly which step moved.

Write the tolerance band down

A tolerance band is a per-fixture, per-dimension limit that says how much drift counts as noise. Writing it down is the step teams skip, and it is the step that makes the gate defensible in a review. The band should be set once, reviewed like code, and changed only with an explicit decision.

Three practical rules for setting it:

  1. Sequence is strict. If the agent calls a tool the reference run never called, or drops a required check such as reading policy before issuing a refund, that crosses the band regardless of the final answer. Ordering flexibility is only allowed where the reference itself shows several valid routes.
  2. Arguments are exact on identity fields and tolerant on formatting. A different order ID is a crossing. A timestamp formatted differently, or an argument that differs only in case, is not.
  3. Answers use a similarity threshold plus hard gates. Set a threshold per fixture class, and add non-negotiable checks (contains a source, declines on the sensitive task, does not invent a field) that override the score.
DimensionDefault bandCrossing exampleVerdict
Tool sequenceIdentical names, order may vary only where reference shows multiple valid routesAdds a write tool that was not called beforeBehavior change
Argument identity fieldsExact matchDifferent customer or order IDBehavior change
Argument formattingNormalized, then exactCase or whitespace difference onlyEquivalent
Final answer contentSimilarity at or above thresholdDrops a required citationBehavior change
Refusal behaviorExact class matchRefuses a task it previously completedBehavior change
Latency and token countRecorded, not gatedSlower but same decisionsEquivalent

If you are unsure where to place a threshold, run the same instructions against themselves ten times. The spread you see is your noise floor, and no band should be tighter than that.

The equivalence rule and how it feeds the risk score

The rule, stated so it can be quoted in a review: a pair of instruction sets is behaviorally equivalent when every fixture in the suite stays inside its preset band on tool sequence, argument values and answer content, across the stated number of repeated runs. Everything else is a behavior change.

Turn that into a routable decision:

  • Zero crossings, across all fixtures and all repeats: record the change as a no-op, mark it equivalent, and let it skip the full gate with a logged reference to the run manifest. This is the payoff. Prompt edits are frequent, and a "be concise" rewrite that changes nothing should not burn reviewer time (Braintrust on prompt management).
  • Any crossing: the edit is a behavior change. Score it, route it, gate it.

The risk score should absorb the result rather than sit beside it. A simple additive model works: start from a base score, add a weight per crossed fixture scaled by fixture criticality (a sensitive-tool fixture weighs more than a formatting fixture), add a term for how far the answer similarity fell below the threshold, and add a penalty if any run showed non-determinism above the noise floor. Two numbers matter for calibration: the crossing rate (crossed fixtures divided by total fixtures) and the worst single crossing. A change that crosses one low-criticality fixture should route to a fast review; a change that crosses three fixtures including a sensitive one should route to the full gate.

This is the same logic change management has used for years. The 7 R's ask who raised the change, why, what return is expected, what the risks are, and what happens if you reject it (SolarWinds' checklist). Behavioral equivalence answers the risk question with evidence instead of opinion, and the run manifest becomes the audit trail: what changed, which fixtures ran, what the deltas were, who approved the equivalence call (the prompt governance overview).

A worked example. Take 30 fixtures, with 4 marked critical because they touch a write tool. Version B crosses 3 fixtures: two formatting-only answer changes and one refusal on an ambiguous task that is not critical. Sequence and arguments match everywhere. If your band classifies formatting as equivalent, you have one real crossing out of 30, a crossing rate of about 3%, on a non-critical fixture. Route to fast review. Now flip one detail: one of the crossed fixtures is the refund task that no longer reads policy first. That single critical crossing should outweigh the other 29 passes, and the model should escalate the score to the full gate. The lesson is that the crossing rate alone is the wrong trigger; criticality has to multiply it.

A second worked example on scaling. Suppose the team ships 40 prompt edits a quarter and each full gate review costs a reviewer half a day. If equivalence lets 25 of those skip the gate, you recover roughly 12 reviewer-days a quarter. That is the business case for building the suite, and it is worth stating in the design doc so the work is not treated as optional quality overhead.

Keep the suite honest as the agent changes

The suite decays if nobody feeds it. Three maintenance habits keep it sharp.

Feed production failures back in. Every bad trajectory becomes a fixture, so the suite tracks real behavior rather than the team's first guesses (Braintrust).

Keep grounding and tools constant between runs. If the tools themselves changed, you are testing the tools, not the instructions, and attribution collapses (the A/B guide).

Re-baseline deliberately. When a behavior change is accepted, the new outputs become the reference for the next comparison. That re-baseline is itself a reviewable event, so record it with the same manifest.

One more safeguard worth adopting: because subagents are granted narrow tool sets by design, apply least privilege when you author the fixtures too. A comparison run should never hold credentials it does not need, since an agent with unnecessary access expands the blast radius of a test that goes wrong (the least privilege guide). Mocks make this easy; live tools make it a risk.

If your fixtures span several model providers and you want one run to compare instruction sets across them, Quanta Inference exposes text, image, video, audio and embedding models through a single OpenAI-compatible API key, which keeps the model setting in your manifest a one-line change.

FAQ

FAQ

What counts as a behavioral difference versus a cosmetic one?

A cosmetic change alters wording, formatting or ordering without changing any decision the agent makes: which tools it calls, with which identity arguments, and whether it answers, refuses or escalates. A behavioral difference changes at least one of those on at least one fixture. The tolerance band encodes the line, and normalizing arguments before comparison is what keeps cosmetic noise out of the result.

How many fixtures do I need before the comparison is trustworthy?

Enough to cover each tool the agent can call, each refusal case and each sensitive action, plus the edge cases that have already failed in production. In practice that means a few dozen, not a few. Run each fixture several times against identical instructions first, so you know your noise floor before you set any threshold, because a band tighter than the natural spread will flag every run as a change.

Does this replace A/B testing in production?

No, and the two answer different questions. The fixture comparison asks whether an edit changed the agent's decisions and runs before the release gate. A production experiment asks whether the change helped real users and needs deterministic assignment and a stable holdout to attribute outcomes. Use the fixture suite to decide what deserves a gate, and the production experiment to measure the effect of the changes that pass.

What do I do when a change is equivalent but I still want a record?

Record it anyway. Write the run manifest, the crossing rate of zero, and the fixture count into the change record, and mark the change as a no-op for routing. The record costs almost nothing and gives you the evidence trail later, which is exactly the traceability that prompt governance frameworks ask for. When someone asks what changed and who approved it, the answer already exists.

Can I compare instruction sets written for different agent frameworks?

Yes, if you normalize the observable surface. Both versions must be driven through the same task fixtures, with the same tool mocks, and must emit the same structured schema for tool calls, arguments and answers. Treat the schema as the contract, not the framework, and record the framework and model in the manifest so nobody later attributes a difference to the wrong cause.

Sources

Sources

  1. Master Claude Code Sub‑Agents in 10 Minutes
  2. Claude Code Subagents and Multi-Agent Orchestration ...
  3. How to A/B Test Two System Prompts in Production - agent-context.org
  4. System Prompts Are NOT Config, Treat Them Like Production ...
  5. How to test AI agents: A practical guide - Articles - Braintrust
  6. Multi-agent orchestration patterns and best practices - Microsoft Learn
  7. Structured model outputs | OpenAI API
  8. Return structured output
  9. What is prompt management? Versioning, collaboration, and ...
  10. Change Management Checklist
  11. What is Prompt Governance? The Critical Control for ...
  12. The principle of least privilege for AI agents
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles