How Do You Release Agent Behavior Safely? Add Behavioral Contracts, Compatibility Checks and Promotion Gates
A model change can pass health checks and still break your agent.
A prompt change can preserve output schema and still change which tools the agent chooses.
A router change can improve average cost and silently starve a specialist that is essential for one high-risk workload.
A memory migration can keep every row intact and still change which memories are retrieved.
A verifier upgrade can make every dashboard greener while making the system less trustworthy.
At that point you no longer have a prompt problem.
You have a release engineering problem.
The core rule for this chapter is:
Agent behavior is a production interface. Release it with explicit contracts, compatibility checks, promotion gates and rollback plans.
That means treating a behavioral release with the same seriousness as:
- an API change,
- a database migration,
- a protocol change,
- a compiler upgrade,
- or a production dependency replacement.
The runtime may still be built from models, prompts, tools and policies.
But the thing users depend on is behavior.
1. The failure mode: everything is healthy, but the release changed the system
Suppose a coding agent currently uses:
model: model-v7
system prompt: prompt-42
router: router-12
search policy: search-8
verifier: verifier-19
tool registry: tools-31
memory schema: memory-6
You update only the model:
model-v7 -> model-v8
The deployment starts cleanly.
Latency looks normal.
The model endpoint returns 200s.
No schema errors occur.
Yet the new model:
- calls tools earlier,
- stops search sooner,
- follows retrieved memories more literally,
- produces fewer candidates,
- and is more persuasive when wrong.
Infrastructure monitoring says:
HEALTHY
Behavioral monitoring says:
REGRESSION
Step 23 showed how to detect that regression.
This chapter asks the next question:
How should the platform release a behavior-changing component so the regression is less likely to escape in the first place?
2. Define the behavioral release unit
A common mistake is to version only the model.
That is too narrow.
The observable behavior of an advanced agent is usually produced by a bundle:
BehaviorRelease
├── model versions
├── prompt versions
├── router policy
├── search policy
├── budget policy
├── critic policy
├── escalation policy
├── tool registry
├── retrieval configuration
├── embedding model
├── memory schema
├── verifier versions
├── safety policy
└── runtime code version
Two runs should not merely say:
model = x
They should identify the complete behavioral release:
from dataclasses import dataclass
@dataclass(frozen=True)
class BehavioralRelease:
release_id: str
runtime_version: str
model_version: str
prompt_version: str
router_version: str
search_policy_version: str
budget_policy_version: str
critic_policy_version: str
tool_registry_version: str
retrieval_version: str
memory_schema_version: str
verifier_version: str
safety_policy_version: str
This is not bureaucracy.
It is what makes comparison, rollback and attribution possible.
Without it, a production trace may tell you:
this run failed
but not:
which behavioral configuration produced the failure?
3. A behavioral contract is stronger than an output schema
Traditional software often defines contracts structurally.
For example:
{
"status": "PASS | FAIL | UNKNOWN",
"summary": "string"
}
An agent can preserve that schema while becoming dramatically worse.
So a behavioral contract must include semantics.
For a coding agent, a release contract might state:
The agent must:
1. never modify the active checkout during speculative analysis;
2. run required validation before claiming PASS;
3. preserve UNKNOWN when validation evidence is missing;
4. never use a higher-privilege tool than the task allows;
5. not regress verified-success rate beyond tolerance;
6. not increase false-success rate beyond tolerance;
7. remain within the declared cost and latency envelope;
8. preserve repository state on failed/rejected attempts.
These are not all unit-test assertions.
Some are:
- invariants,
- statistical guarantees,
- operational limits,
- or semantic expectations.
Together they form the release contract.
4. Contract types
A useful agent release system separates several kinds of contracts.
4.1 Structural contracts
Examples:
- tool argument schema,
- event schema,
- memory record schema,
- verifier result schema,
- checkpoint schema.
These are conventional compatibility checks.
4.2 Behavioral invariants
Examples:
- no mutation before authorization,
- no PASS without required verifier evidence,
- no stale worker commit,
- no speculative side effect to shared state,
- no cross-tenant memory access.
These should usually be deterministic.
4.3 Statistical quality contracts
Examples:
verified_success >= baseline - 1.0 percentage point
false_success <= baseline + 0.2 percentage point
UNKNOWN rate <= expected band
cost/success <= allowed threshold
p95 latency <= allowed threshold
These need evaluation data.
4.4 Routing contracts
Examples:
- high-risk tasks must reach a verifier-capable route,
- unsupported tasks must not be routed to a narrow specialist,
- escalation remains available when local models fail.
4.5 Capability contracts
Examples:
- fallback model supports structured tool calling,
- browser worker supports required authentication mode,
- verifier can inspect the artifact type produced by the executor.
4.6 Data contracts
Examples:
- retrieval metadata remains present,
- memory provenance survives migration,
- freshness timestamps remain comparable,
- embedding dimensions match the active index.
The important point is:
Compatibility is multi-dimensional.
5. Compatibility is directional
Suppose version B can read version A’s checkpoint.
That does not mean A can read B’s checkpoint.
So compatibility should not be recorded as:
A compatible with B
but as:
reader=B, writer=A -> compatible
reader=A, writer=B -> incompatible
A simple matrix helps:
| Producer | Consumer | Result |
|---|---|---|
| old prompt | new verifier | PASS |
| new prompt | old verifier | FAIL |
| old memory | new retriever | PASS |
| new memory | old retriever | UNKNOWN |
| old checkpoint | new runtime | PASS |
| new checkpoint | old runtime | FAIL |
This becomes essential during rolling deployments where old and new workers coexist.
6. Backward compatibility is not enough
Agent releases often require behavioral compatibility, not only schema compatibility.
Imagine the tool schema remains unchanged:
run_tests(scope: str) -> TestResult
The new model starts calling:
run_tests(scope="all")
instead of:
run_tests(scope="affected")
Everything is structurally compatible.
But:
- cost changes,
- latency changes,
- contention changes,
- and Step 21’s scheduler may start shedding other workloads.
Therefore release tests should include behavior distributions such as:
tool-call count
tool selection
search depth
escalation rate
verification rate
memory-read rate
retry count
cost per successful task
7. Build a release manifest
A release should be inspectable as data.
release_id: agent-2026-08-09.24
runtime: 7.14.0
models:
default: model-v8
verifier: verifier-model-v5
prompts:
planner: planner-44
critic: critic-18
router: router-13
search_policy: search-9
budget_policy: budget-11
tools: tools-32
retrieval: retrieval-17
memory_schema: memory-7
verifier: verifier-20
safety_policy: safety-8
compatibility:
min_checkpoint_schema: 5
max_checkpoint_schema: 7
min_memory_schema: 6
rollback:
previous_release: agent-2026-08-08.23
Now deployment, traces, benchmarks and rollback all refer to the same immutable release object.
8. Promotion should be a state machine
Do not think of deployment as:
merge -> production
Use explicit stages:
DRAFT
↓
OFFLINE_VALIDATED
↓
SHADOW
↓
CANARY
↓
LIMITED
↓
GENERAL
And failure paths:
any stage
↓
BLOCKED
↓
ROLLED_BACK
A release record can capture that directly:
from enum import Enum
class PromotionStage(str, Enum):
DRAFT = "draft"
OFFLINE_VALIDATED = "offline_validated"
SHADOW = "shadow"
CANARY = "canary"
LIMITED = "limited"
GENERAL = "general"
BLOCKED = "blocked"
ROLLED_BACK = "rolled_back"
9. Gate 1: deterministic contract tests
Before expensive benchmarks, run deterministic checks.
Examples:
- every tool reference resolves
- every prompt variable is supplied
- tool schemas parse
- policy configuration validates
- model supports required features
- verifier supports output artifact type
- memory migration is reversible or explicitly irreversible
- checkpoint reader supports active schema versions
This should be cheap and fast.
Do not spend frontier-model budget discovering that a JSON field was renamed.
10. Gate 2: invariant tests
Then test hard behavioral invariants.
Examples:
def test_cannot_pass_without_verification():
result = run_task(verifier_available=False)
assert result.status != "PASS"
def test_speculative_branch_cannot_commit():
result = run_speculative_branch()
assert result.shared_mutations == []
def test_stale_worker_is_fenced():
stale = worker(epoch=4)
current = lease(epoch=5)
assert commit(stale, current) == "REJECTED"
These are especially valuable because model upgrades should not be allowed to negotiate around them.
11. Gate 3: behavioral regression suite
Next, run the candidate release over a benchmark corpus.
For every case, compare:
baseline release
vs
candidate release
Record transitions:
PASS -> PASS
PASS -> FAIL
PASS -> UNKNOWN
FAIL -> PASS
FAIL -> FAIL
UNKNOWN -> PASS
UNKNOWN -> FAIL
UNKNOWN -> UNKNOWN
Do not collapse those immediately into one number.
A release with:
+10 FAIL -> PASS
-2 PASS -> FAIL
may be good.
A release with:
+50 UNKNOWN -> PASS
may be suspicious if the verifier also changed.
12. Paired evaluation is more informative than two aggregate dashboards
Suppose:
baseline verified success: 78%
candidate verified success: 79%
Looks fine.
But paired transitions show:
old PASS -> new FAIL: 8%
old FAIL -> new PASS: 9%
That means the candidate is not simply better.
It is behaving differently.
You need to know where.
Slice by:
- task class,
- risk level,
- tool family,
- repository size,
- tenant,
- language,
- route,
- verifier,
- and workload source.
A one-point global gain can hide a severe regression in the highest-risk cohort.
13. Define promotion thresholds before seeing the result
Do not evaluate a release and then invent a threshold that lets it pass.
A promotion policy might be:
promotion_gate:
min_cases: 500
verified_success_delta_min: -0.005
false_success_delta_max: 0.001
p95_latency_delta_max: 0.10
cost_per_success_delta_max: 0.08
high_risk_false_success_delta_max: 0.0
The important thing is not these exact numbers.
The important thing is that they are:
- explicit,
- versioned,
- reviewed,
- and known before evaluation.
14. Promotion gates should be cohort aware
A global gate can still hide local damage.
For example:
overall success: +2%
code migration tasks: +4%
small bug fixes: +3%
production incident tasks: -8%
The release should not automatically promote.
A stronger gate looks like:
overall false-success within tolerance
AND
high-risk false-success non-regressing
AND
critical cohorts above minimum success floor
15. Shadow before canary
A shadow release receives production inputs but cannot affect production outputs.
production request
├── active release -> real result
└── candidate release -> shadow result
Now you can compare:
- route decisions,
- tool choices,
- search depth,
- final candidate,
- verifier result,
- cost,
- latency,
- and uncertainty profile.
The candidate sees realistic traffic without being allowed to mutate shared state.
16. Shadow evaluation needs side-effect isolation
Do not let the shadow release:
- send emails,
- merge PRs,
- mutate production databases,
- deploy infrastructure,
- click purchase buttons,
- or otherwise duplicate real-world effects.
Use:
- recorded tool outputs,
- read-only tools,
- sandboxes,
- worktrees,
- synthetic external systems,
- or dry-run adapters.
This is Step 19’s speculative-execution rule applied to release engineering.
17. Canary the behavior, not just the binary
A canary means a small amount of production traffic receives the candidate behavior.
But the canary slice matters.
Bad canary:
1% random traffic
Better canary:
1% traffic
with representation across:
- task classes
- risk classes
- tenants
- tools
- routes
Otherwise the canary can miss exactly the cohort that will later regress.
18. Promotion requires evidence, not elapsed time
Do not promote because:
it has been 30 minutes and nothing exploded
Promote because:
sample threshold reached
AND
contract checks passed
AND
critical cohorts are within tolerance
AND
false-success is controlled
AND
cost/latency remain acceptable
AND
no unexplained drift signal is active
Time can be part of the gate.
It should not be the gate.
19. Rollback must be designed before promotion
A rollback plan is not:
we can probably redeploy the old version
A release should know its rollback target:
candidate = release-24
rollback = release-23
And the platform should know whether rollback is:
- code-only,
- configuration-only,
- schema-compatible,
- checkpoint-compatible,
- memory-compatible,
- or requires migration.
20. Rollback compatibility matters
Suppose release 24 writes memory records in schema 7.
Release 23 understands only schema 6.
Then this is not safe:
release 24 -> writes schema 7
rollback -> release 23
unless you have:
- dual writes,
- backward-compatible readers,
- migration-on-read,
- or a downgrade migration.
This is exactly why behavior release engineering intersects with data migration.
21. Expand-contract migrations work well for agent systems
Instead of:
old schema -> replace -> new schema
use:
expand
↓
read old + new
↓
write compatible data
↓
backfill
↓
verify
↓
contract old format
This supports rolling workers and rollback.
It is especially useful for:
- memory schemas,
- trace events,
- checkpoints,
- tool payloads,
- verifier evidence,
- and routing features.
22. Prompt changes are migrations too
A prompt can change the meaning of a tool argument without changing the tool schema.
Old prompt:
Use scope="affected" unless the user explicitly requests full validation.
New prompt:
Prefer full validation when correctness matters.
The API did not change.
The usage contract did.
Therefore prompt changes deserve:
- regression tests,
- tool-distribution comparisons,
- cost comparisons,
- and rollout gates.
23. Router changes are routing migrations
A router upgrade can redistribute workload across experts.
Before:
local model 70%
code specialist 20%
frontier model 10%
After:
local model 45%
code specialist 20%
frontier model 35%
Maybe success improves.
Maybe cost triples.
Maybe frontier-model queues saturate and Step 21 starts shedding interactive work.
Router releases should therefore test:
routing regret
expert utilization
missed escalation
unnecessary escalation
cost per verified success
queue pressure
24. Verifier releases need a special gate
Verifier upgrades are dangerous because they change the measurement system itself.
If executor and verifier both change together, observed gains become hard to interpret.
Prefer staged releases:
1. hold executor fixed
2. evaluate candidate verifier
3. validate verifier against deterministic/gold evidence
4. promote verifier
5. then evaluate executor changes
This reduces confounding.
25. Release one behavioral axis at a time when possible
Changing all of these simultaneously:
model
prompt
router
retrieval
verifier
budget policy
may produce a better system.
But it produces poor evidence.
If the candidate regresses, attribution is difficult.
Prefer narrower releases when feasible:
release A: model only
release B: router only
release C: retrieval only
This is not always operationally possible.
When it is not, the release manifest should make the compound change explicit.
26. Compatibility tests should include mixed-version execution
Distributed systems rarely switch every worker atomically.
During deployment you may have:
worker A -> release 23
worker B -> release 23
worker C -> release 24
worker D -> release 24
Test scenarios like:
old coordinator -> new worker
new coordinator -> old worker
old checkpoint -> new worker
new checkpoint -> old worker
old memory writer -> new reader
new memory writer -> old reader
If any of these combinations are impossible, encode that in deployment policy.
27. Use capability negotiation rather than assumptions
Workers can advertise capabilities:
{
"runtime": "7.14.0",
"checkpoint_schemas": [5, 6, 7],
"memory_schemas": [6, 7],
"tools": ["git", "pytest", "browser_readonly"],
"verification": ["unit_test", "schema_check"]
}
The coordinator can then avoid scheduling incompatible work.
This is safer than assuming every live worker supports every active release feature.
28. Release contracts belong in code
Do not leave promotion rules only in a dashboard.
Represent them explicitly:
from dataclasses import dataclass
@dataclass(frozen=True)
class PromotionGate:
min_cases: int
min_verified_success_delta: float
max_false_success_delta: float
max_cost_per_success_delta: float
max_p95_latency_delta: float
def promotable(metrics, gate: PromotionGate) -> bool:
return (
metrics.case_count >= gate.min_cases
and metrics.verified_success_delta >= gate.min_verified_success_delta
and metrics.false_success_delta <= gate.max_false_success_delta
and metrics.cost_per_success_delta <= gate.max_cost_per_success_delta
and metrics.p95_latency_delta <= gate.max_p95_latency_delta
)
The production implementation will likely be more nuanced.
But even a simple explicit rule is better than:
looks okay
29. Keep promotion authority outside the candidate agent
The candidate release should not decide:
I performed well enough to deploy myself
Promotion authority belongs to an external release controller using:
- benchmark evidence,
- production shadow evidence,
- canary evidence,
- verifier results,
- and explicit release policy.
This follows the recurring series rule:
The system being evaluated does not get to define reality.
30. Promotion events should be observable
A release event should record:
@dataclass(frozen=True)
class PromotionDecision:
release_id: str
from_stage: str
to_stage: str
baseline_release_id: str
case_count: int
verified_success_delta: float
false_success_delta: float
cost_delta: float
latency_delta: float
evidence_refs: tuple[str, ...]
policy_version: str
decision: str
reason: str
Now deployment itself becomes part of the trajectory history.
31. Release evidence should be immutable
Do not overwrite the benchmark artifact that justified a release.
Store:
release
↓
benchmark snapshot
↓
shadow evidence
↓
canary evidence
↓
promotion decision
If the release later regresses, you need to know:
- what evidence was available,
- what threshold applied,
- and why promotion was allowed.
32. Version the promotion policy too
A release can pass under one policy and fail under another.
So store:
promotion_policy_version = gate-12
Without that, historical release decisions become difficult to reproduce.
33. Release gates should include operational compatibility
A behavior can be correct but operationally incompatible.
Examples:
- doubles token usage,
- doubles browser concurrency,
- calls a rate-limited provider more often,
- increases DB writes,
- expands checkpoint size,
- increases verifier queue pressure.
So release validation should include:
correctness
cost
latency
resource demand
queue pressure
rate-limit demand
verification demand
34. A release can be behaviorally better and still be rejected
Suppose candidate release 24 improves verified success:
+1.5%
but increases cost per verified success:
+80%
The correct decision may be:
BLOCKED
Advanced architecture is not a power ladder.
A more capable but economically unusable release is not automatically better.
35. Release gates should understand UNKNOWN
Suppose a stricter verifier causes:
PASS rate 82% -> 78%
UNKNOWN rate 3% -> 8%
false PASS 2% -> 0.5%
A naive success metric says the release got worse.
A reliability-aware release gate may say the release got better.
Again:
UNKNOWN ≠ failure
Sometimes UNKNOWN means the new release stopped pretending to know.
36. Release by risk class
A useful deployment order is:
read-only low-risk tasks
↓
reversible write tasks
↓
moderate-risk automations
↓
high-consequence actions
This gives the release more evidence before granting greater authority.
Risk-based rollout is often more meaningful than random percentages alone.
37. Authority can be part of the release stage
For example:
SHADOW
read only
CANARY
reversible writes only
LIMITED
bounded production writes
GENERAL
normal approved authority
This is powerful because deployment progression controls not only traffic volume but capability exposure.
38. Do not migrate safety policy implicitly
Suppose a release needs a new tool.
Do not infer:
new tool exists -> agent may use it
Tool availability and tool authorization are different.
Safety policy changes should have their own explicit review/version.
39. Release engineering for coding agents
A coding-agent release may change:
- model,
- patch prompt,
- tree search,
- repository retrieval,
- test selection,
- verifier,
- or workspace handling.
Useful release contracts include:
no active-checkout mutation
no PASS without required tests
no merge without authorization
workspace cleanup invariant
changed-file scope invariant
cost per verified repair
regression rate on known-good repairs
Shadow mode can replay real tasks in isolated worktrees.
40. Release engineering for research agents
A research-agent release may change:
- query generation,
- retrieval provider,
- reranker,
- source-quality policy,
- synthesis prompt,
- citation verifier.
Contracts can include:
citation coverage
primary-source preference
source freshness
unsupported-claim rate
retrieval precision
retrieval recall proxy
cost per verified answer
A release that writes better prose but cites weaker sources is not necessarily an improvement.
41. Release engineering for browser agents
Browser agents add stateful external risk.
Contracts may include:
no irreversible click during shadow
state revalidation before commit
idempotency for retryable actions
postcondition verification
checkout/purchase authority boundaries
Canary stages should increase authority gradually.
42. Release engineering for data agents
A data agent may change:
- SQL generation,
- schema retrieval,
- execution planning,
- result validation,
- or summarization.
Contracts can include:
read/write scope
query-cost ceiling
row-count sanity checks
schema compatibility
result reproducibility
validation coverage
43. Release engineering for DevOps agents
DevOps agents need especially strict release gates.
Contracts may include:
no production mutation without approval
plan-before-apply invariant
current-state refresh before apply
rollback path exists
postcondition verified
blast-radius ceiling
A canary should start with low-authority environments before touching production.
44. Release engineering for mixture-of-agents systems
A mixture-of-agents runtime may keep the same experts while changing only the router.
That can still change the system dramatically.
Version:
expert set
router
routing features
fallback order
judge
verifier
budget allocation
Then compare:
routing distribution
expert utilization
routing regret
cost per verified success
false-success by route
45. Keep release units small enough to attribute
If every deployment bundles twenty behavioral changes, you lose experimental resolution.
A useful rule:
Change the smallest behavioral surface that solves the measured problem.
That gives you:
- cleaner evidence,
- easier rollback,
- clearer attribution,
- and smaller blast radius.
46. But do not force artificial independence
Some changes are coupled.
A new verifier may require a new evidence schema.
A new model may require a prompt migration.
A new tool protocol may require runtime changes.
In those cases, release them together—but declare the coupling explicitly.
47. Promotion should fail closed on missing evidence
Suppose the canary has insufficient high-risk cases.
Do not interpret that as:
no regressions observed
Interpret it as:
insufficient evidence
The promotion state should remain:
BLOCKED
or:
WAITING_FOR_EVIDENCE
This is the release-engineering equivalent of preserving UNKNOWN.
48. Build a release scorecard
A useful scorecard might look like:
Release: agent-2026-08-09.24
Baseline: agent-2026-08-08.23
Correctness
verified success +1.2%
false success -0.3%
UNKNOWN +0.6%
Routing
routing regret -4.0%
missed escalation -1.1%
Cost
cost / verified success +3.0%
Latency
p50 -2.0%
p95 +5.0%
Safety
invariant failures 0
Compatibility
checkpoint matrix PASS
memory matrix PASS
tool schema PASS
Recommendation: PROMOTE_TO_CANARY
This is far more useful than:
new version looks better
49. Release automation should remain boring
You do not need another autonomous agent deciding whether releases should deploy.
A good release controller can be ordinary software:
read immutable evidence
apply explicit gates
produce promotion decision
record decision
update release state
If a human approval is required, insert it explicitly.
50. The full release loop
At this point the production architecture can support:
behavioral change
↓
release manifest
↓
structural compatibility
↓
invariant tests
↓
offline paired benchmark
↓
shadow evaluation
↓
canary
↓
cohort-aware promotion gates
↓
limited rollout
↓
general rollout
↓
drift monitoring
↓
rollback if needed
That is a very different operating model from:
change prompt
restart agent
hope
51. How this connects to the earlier stages
The recent stages now fit together as one production control system:
Step 13 trajectory observability
Step 14 learn from verified trajectories
Step 15 explicit control policies
Step 16 dynamic budget scheduling
Step 17 uncertainty decomposition
Step 18 expected value of information
Step 19 speculative execution
Step 20 distributed coordination
Step 21 platform scheduling
Step 22 failure containment
Step 23 behavioral drift detection
Step 24 behavioral release engineering
Each stage answers a different failure mode.
None of them is a mandatory capability ladder.
52. Do you actually need behavioral release engineering?
Maybe not.
If your system is:
- one model,
- one prompt,
- read only,
- manually operated,
- easy to validate,
- and cheap to roll back,
then a simple benchmark and manual deployment may be enough.
Add formal release machinery when you have measured problems such as:
- silent regressions,
- mixed-version incompatibility,
- hard-to-attribute changes,
- risky rollouts,
- migration failures,
- or slow recovery from bad releases.
Remember the series rule:
Complexity must earn its cost.
53. Final implementation checklist
Before promoting an agent behavior release, ask:
[ ] Is the full behavioral release versioned?
[ ] Are hard invariants explicit?
[ ] Are schemas and checkpoints compatible?
[ ] Are memory/tool/retrieval migrations tested?
[ ] Is the benchmark paired against the active baseline?
[ ] Are critical cohorts evaluated separately?
[ ] Are false-success and UNKNOWN rates included?
[ ] Is verifier drift independently checked?
[ ] Are cost and latency within contract?
[ ] Has shadow evaluation completed?
[ ] Is the canary representative?
[ ] Are promotion thresholds predefined?
[ ] Is rollback target known?
[ ] Is rollback schema-compatible?
[ ] Are in-flight distributed tasks safe across versions?
[ ] Is release authority external to the candidate agent?
[ ] Is the promotion policy itself versioned?
If several answers are no, you do not yet have a reliable release.
You have a configuration change.
54. The deeper principle
Advanced agents are often described as if the difficult problem were making them more capable.
In production, another problem quickly becomes just as important:
How do you know that the version you are about to release is actually the system you think you tested?
The answer is not another prompt.
It is:
- explicit behavior versions,
- explicit contracts,
- explicit compatibility,
- explicit evidence,
- explicit promotion,
- and explicit rollback.
That is release engineering.
And once agent behavior becomes a releaseable artifact, the next question becomes unavoidable:
How do you reproduce an old agent run exactly enough to investigate, audit, compare or recover it months later?
That leads to the next stage: deterministic replay, provenance, reproducible environments and audit-ready execution records.