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, aiDecision
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_idNULL) — 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 toscope='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_idand (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 NULLrole_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/userscope columns until those scopes are actually implemented.