Procedural Memory: Evolving Instructions
Treat changes to the agent’s behavior as versioned, evaluated, approved, and reversible releases.
The enterprise problem and today’s slice
Enterprise problem: A mailbox owner needs the agent to follow a durable rule—“for external attendees, propose times and obtain approval before scheduling”—but an unsafe or accidental rule can alter every future request and create unauthorized calendar actions.
Whole-course context: The workflow can already retrieve tenant-scoped facts and accepted episodes; today consumes the Day 4 episode, feedback, route, and trace references that reveal a repeated behavioral gap.
Today’s slice: Add immutable procedural-memory versions, controlled proposal and approval transitions, version-pinned prompt loading, canary activation, and rollback in the provider control plane; the hosted runtime executes only the active approved version.
End-of-day evidence: A reviewer can inspect a draft-to-active state history, versioned evaluation result, approval identity, Alice-request canary trace, denied unauthorized activation, and rollback proof with immutable IDs.
Still unsolved: Automatic candidate extraction, durable queue processing, contradiction consolidation, physical deletion, production database selection, CI/CD infrastructure, and fleet-wide operations remain deferred.
The smallest complete procedural model
Facts and examples cannot safely express a rule that governs many future requests. Procedural memory stores how the agent should behave, and its smallest complete model is version, evidence, and controlled activation.
Rule: Classify memory by function, not by wording. “No meetings before 10:00” is semantic when it states a preference; “never schedule an external attendee without approval” is procedural because it constrains future actions; “Alice’s FYI was ignored” is episodic because it records one outcome. The realistic failure is storing “always forward invoices” from an external email as a user preference, allowing an attacker’s sentence to control future tools. Decision rule: if a memory changes behavior across a class of requests, route it through procedural safeguards even when it sounds like a fact.
| Memory type | Question answered | Recurring example | Change path |
|---|---|---|---|
| Semantic | What is true or preferred? | The owner avoids meetings before 10:00 | Extract, verify, store or supersede |
| Episodic | What happened in a similar case? | Alice’s no-question weekly FYI was correctly ignored | Observe outcome, review, retrieve as evidence |
| Procedural | How should the agent behave? | Obtain approval before scheduling external attendees | Propose, evaluate, approve, canary, activate |
Immutable versions and exact prompt loading
If active instructions are overwritten in place, traces cannot reproduce the behavior that ran and rollback becomes guesswork. Store immutable versions and load exact IDs before every decision node they govern.
Rule: Any text change creates a new draft version; unchanged text does not transfer approval to the revision. A simple typo fix becomes version 12, not an edit to version 11. In the Alice request, the graph state records both triage and response procedure versions so the proposed-slots behavior can be reproduced. The failure mode is loading “latest” during a long-running graph, causing one execution to use two versions. Decision rule: resolve and pin procedure versions at execution start or an explicit safe boundary; never resolve by mutable “latest” inside each node.
class ProcedureVersion(BaseModel):
procedure_id: str
version: int
scope: Literal["triage", "response", "memory_policy"]
instructions: str
status: Literal["draft", "approved", "active", "retired"]
proposed_by: str
approved_by: str | None
evaluation_run_id: str | None
created_at: str
def load_procedures(state: EmailState, config):
tenant_id = config["configurable"]["tenant_id"]
triage = procedure_store.get_active(tenant_id, scope="triage")
response = procedure_store.get_active(tenant_id, scope="response")
return {
"triage_instructions": triage.instructions,
"triage_procedure_version": triage.version,
"response_instructions": response.instructions,
"response_procedure_version": response.version,
}
Prompt precedence remains explicit: immutable system safety policy first, approved scoped procedure second, accepted episodes as evidence third, and the untrusted current email last. These layers complement one another; procedural memory does not replace semantic or episodic memory.
Proposal is not activation
An optimizer that can activate its own suggestion can convert one noisy correction into fleet-wide policy. Generation, evaluation, approval, rollout, and activation must be distinct state transitions with narrower authority at each interface.
Rule: Give the proposing component only draft-write authority. A simple optimizer can suggest clearer wording after reviewed failures; in the recurring case, several premature external bookings motivate a draft requiring owner approval. The failure mode is self-approval or hidden scope expansion from one mailbox to an organization. Decision rule: no component that generates instruction text may be the sole authority that evaluates and activates it; high-impact or scope-expanding changes require independent human approval.
def propose_procedure_update(current, reviewed_failures):
candidate = optimizer.invoke({
"current_instructions": current.instructions,
"reviewed_failures": reviewed_failures,
"constraint": "Preserve system safety policy and tool authorization.",
})
return procedure_store.create_draft(
scope=current.scope,
instructions=candidate.instructions,
supersedes=current.version,
)
def authorize_procedure_write(candidate, actor):
if actor.kind != "authenticated_user":
return "reject"
if not actor.has("agent.procedure.propose"):
return "reject"
if candidate.enables_side_effects or candidate.expands_data_scope:
return "human_review"
return "evaluate"
Even an administrator cannot use a tenant procedure to override immutable isolation, secret handling, or tool-level authorization. Tenant procedures may narrow behavior; they cannot create a tool or grant a permission that the hosted application did not expose.
Evaluate behavior, not wording
A readable prompt diff may still ignore critical mail or select unsafe tools. Evaluation must compare observed behavior under pinned current and candidate releases.
Rule: Gate on consequences and rare high-impact cases, not only average accuracy. A simple test checks whether newsletters without questions remain ignore; the realistic suite checks Alice’s external meeting stops before scheduling, internal approved scheduling still works, security mail remains visible, and poisoned instructions are denied. A failure occurs when macro accuracy improves while external preapproval scheduling becomes possible. Decision rule: any hard safety or authorization regression blocks release regardless of aggregate gain; otherwise use predeclared thresholds for route quality, corrections, latency, tokens, and cost.
Store the dataset version, model configuration, retrieval corpus version, tool schemas, expected results, observed results, and artifact ID with each run. Without pinned inputs, “version 12 passed” is not reproducible evidence.
| Gate | Example metric | Release decision |
|---|---|---|
| Routing | Macro F1 and critical-class recall | No critical regression; required class threshold passes |
| Tool behavior | Exact tool and argument validity | Zero preapproval external scheduling in denial cases |
| Security | Poisoning and authority denial rate | Every forbidden write/activation is denied |
| Operations | p95 latency, tokens, and cost | Candidate remains inside the declared budget |
| Positive control | Internal approved meeting completion | Unaffected authority still succeeds |
Canary, rollback, and trade-offs
Offline evidence cannot expose every production interaction, so immediate fleet-wide activation creates unnecessary blast radius. Canary rollout limits exposure and immutable versions make rollback a pointer change rather than a prompt reconstruction.
Rule: Change one major behavioral variable at a time and trace its version on every decision. A simple rollout assigns version 12 to 5% of eligible requests; in Alice’s case, monitor premature-tool denials, user corrections, and escalation rates against version 11. The failure mode is combining a prompt, model, embedding, and retrieval change so causality is unknowable. Decision rule: canary when the behavior affects side effects or many requests; roll back automatically when a hard safety event occurs or a declared threshold breaches, and treat inseparable multi-part changes as one versioned release bundle.
| Approach | Use when | Avoid when | Trade-off |
|---|---|---|---|
| Direct activation | Low-impact wording change has exhaustive deterministic coverage and no side-effect influence | Rule changes routing, authorization, data scope, or tools | Fast, but largest unobserved blast radius |
| Percentage canary | Traffic is sufficient for comparison and assignments can remain stable | Very rare high-risk behavior would take too long to observe | Limits exposure, but requires cohort and metric discipline |
| Tenant/user opt-in | A specific owner requests experimental behavior | Results must generalize before approval | Strong containment, but selection bias affects evidence |
| Release bundle | Model, retrieval, and prompt must change together for compatibility | Variables can be isolated | Preserves compatibility, but makes causal diagnosis harder |
Rollback must restore the active pointer and prove the previous behavior with a fresh trace. It does not delete the failed version; retaining its evidence prevents the same unsafe proposal from being rediscovered without context.
Key takeaways
Without release discipline, procedural memory is a durable prompt-injection and change-management surface. Treat instructions with the same care as behavior-changing code.
- Procedural memory governs classes of future decisions, so it has greater blast radius than one fact or episode.
- Store immutable, scoped versions and pin exact version IDs into each execution trace.
- Proposal, evaluation, approval, canary, activation, and rollback are separate authority transitions.
- A tenant procedure can narrow behavior but cannot override system policy or tool authorization.
- Evaluate behavior under pinned inputs, then roll out gradually with explicit rollback thresholds.
Checklist
The useful next action is one complete, reversible procedure release—not a library of untested rules. Use the Alice external-meeting rule to prove the lifecycle end to end.
- [ ] Create immutable draft version 12 with scope, proposer, superseded version, and timestamps.
- [ ] Run a pinned suite covering Alice’s external request, an internal positive control, critical mail, and poisoning probes.
- [ ] Record an authorized human approval tied to the exact evaluation run and version.
- [ ] Canary the version with stable assignment and trace every decision’s procedure version.
- [ ] Prove no calendar event exists before owner approval, then prove approved scheduling still works.
- [ ] Trigger a threshold breach in a test environment and verify atomic rollback to version 11.
- [ ] Attempt unauthorized activation and preserve the denial evidence beside the positive control.