05

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 typeQuestion answeredRecurring exampleChange path
SemanticWhat is true or preferred?The owner avoids meetings before 10:00Extract, verify, store or supersede
EpisodicWhat happened in a similar case?Alice’s no-question weekly FYI was correctly ignoredObserve outcome, review, retrieve as evidence
ProceduralHow should the agent behave?Obtain approval before scheduling external attendeesPropose, 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.

GateExample metricRelease decision
RoutingMacro F1 and critical-class recallNo critical regression; required class threshold passes
Tool behaviorExact tool and argument validityZero preapproval external scheduling in denial cases
SecurityPoisoning and authority denial rateEvery forbidden write/activation is denied
Operationsp95 latency, tokens, and costCandidate remains inside the declared budget
Positive controlInternal approved meeting completionUnaffected 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.

ApproachUse whenAvoid whenTrade-off
Direct activationLow-impact wording change has exhaustive deterministic coverage and no side-effect influenceRule changes routing, authorization, data scope, or toolsFast, but largest unobserved blast radius
Percentage canaryTraffic is sufficient for comparison and assignments can remain stableVery rare high-risk behavior would take too long to observeLimits exposure, but requires cohort and metric discipline
Tenant/user opt-inA specific owner requests experimental behaviorResults must generalize before approvalStrong containment, but selection bias affects evidence
Release bundleModel, retrieval, and prompt must change together for compatibilityVariables can be isolatedPreserves 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.