ADR-0032: Role-agent-owned, cross-channel memory with policy precedence

Status

Accepted (pending Phase 2 implementation)

Tags

digital-worker, memory, learning, multi-tenancy, ddd, bounded-context, ai

Decision

Digital Worker Phase 2 memory is owned by the role-agent within an organization, keyed on (org_id, role_agent_id), not by a chat channel. The same role-agent (e.g. “IT Agent”) carries one shared memory across every channel binding it serves in that org. Memory is also paired with approved, versioned skills under the same owner — memory and skills ship together, not memory-only. Two scopes ship in Phase 2:
  • org-wide (scope='org', role_agent_id NULL) — admin-authored policy memory, read-only to the learning pipeline.
  • role-agent (scope='role_agent') — the primary store; the only scope the auto-save pipeline may write.
channel and user scopes are modelled in the design but deferred; their columns are not added until those scopes ship (see ADR rationale below for why we did not pre-add nullable columns). When memories conflict, precedence is: system/developer policy → Gremlin org policy + RBAC → approved org-wide memory → approved role-agent memory. Admin-authored org policy memory therefore outranks anything the agent learned for its role. Memory is context, not authority — it can never grant permissions, bypass approval gates, or change AccessGate behavior.

Why

The product goal is an agent that improves across the teams it serves. If memory were channel-scoped, the IT Agent would re-learn “we call the VPN GlobalProtect” in every channel and feel amnesiac when moved between teams. Binding memory to the role-agent makes learning portable, which is the whole point. The precedence order is the surprising part worth recording: it is most-general-wins among memories (org-wide over role-agent), which is the opposite of the usual “most-specific-wins” instinct. The reason is that in MVP, org-wide memory is exclusively admin-authored policy, while role-agent memory is largely machine-learned. A human-authored org constraint must beat a habit the agent picked up, so general-over-specific is correct for this specific pairing. If channel/user scopes are added later, those slot in below role-agent as more-specific learned context — without disturbing the policy-over-learning principle. Restricting auto-save to scope='role_agent' keeps the classifier from ever writing an org-wide fact, so org policy stays a deliberate human act. This pairs with ADR-0033 (verified-identity-gated auto-save). Rejected alternatives:
  • Channel-local memory as the primary store. Re-learns the same facts per channel; defeats portability. Rejected as primary (kept as a deferred secondary scope).
  • Memory-only, skills later. Stores preferences but never produces a reusable procedure after repeated corrections. Rejected — the mistake-to-skill loop is core value.
  • Most-specific-wins precedence. Would let a learned role-agent habit override admin org policy. Rejected for the policy-vs-learning pairing.
  • Cross-organization memory sharing. A tenancy and confidentiality hazard. Rejected outright.

Consequences

  • Memory is a per-tenant, per-persona asset that must never cross org boundaries; every query is scoped by org_id and (for non-org memory) role_agent_id.
  • A role-agent reassigned to a new channel immediately “knows” what it learned elsewhere in the org — intended, but it means channel managers cannot fully sandbox an agent’s knowledge until channel scope ships.
  • Org-wide memory needs an admin authoring path; it is not a by-product of learning.
  • Precedence must be enforced at context-assembly time (ADR’s ContextPack), not in storage.

Rules for agents

  • Scope memory queries by (org_id, role_agent_id); org-wide rows have NULL role_agent_id.
  • The auto-save path MUST write only scope='role_agent'; never auto-create org-wide memory.
  • Never treat memory as authority — it cannot grant tools, skip approval, or alter AccessGate.
  • Do not add channel/user scope columns until those scopes are actually implemented.