Cross-Agent Isolation Policy
The cross-agent-isolation policy category prevents one agent from reading another agent's memory, scratchpad, tool state, or context -- even when they share the same tenant runtime. A finance-bot must not silently pull a support-bot's session context, and a sub-agent must not exfiltrate its parent's working memory unless explicitly authorized.
This is the agent-level analogue of multi-tenancy. Required for the Atlassian / IBM enterprise pitch. Maps to NIST AI RMF MS-2.7 (segmentation between AI systems), ISO 42001 A.8.3 (information access restriction), and OWASP LLM01 lineage gap.
Rules
| Rule | Type | Default | Description |
|---|---|---|---|
isolation_scopes | string[] | ["memory", "context", "tool_state", "scratchpad"] | Surfaces to isolate |
allow_cross_agent_reads | object[] | [] | Allowlist entries: {source, target} pairs OR {trust_group} names |
block_cross_tenant | boolean | true | Hard-block any cross-tenant read regardless of allowlist |
tool_patterns_cross_agent | string[] | ["memory.read_other_*", "scratchpad.read", "agent_handoff.*"] | fnmatch patterns for cross-agent tool calls |
action_on_violation | string | block | block, warn, or redact |
How It Works
Runs at before_workflow and mid_execution. after_workflow is a no-op (isolation is enforced before the surface is touched).
Three checks in order:
1. Cross-tenant short-circuit (hard ceiling)
If block_cross_tenant: true and the context carries a cross_tenant_read marker whose tenant differs from the calling agent's tenant -> BLOCK, bypassing the allowlist. No allowlist entry can override this.
2. Explicit cross-agent reads
Reads context.read_from_agent -- the runtime emits this when memory.read(agent=...), handoff(...), or similar primitives are invoked. Normalizes to (source, target) pairs and checks against allow_cross_agent_reads.
3. Pending tool calls on cross-agent surfaces
Scans context.pending_actions for tool calls whose name matches any of tool_patterns_cross_agent (fnmatch). Tries to extract target_agent from args (args.agent, args.target_agent, args.source_agent, args.from). If the target is set and not allowlisted -> violation.
Allowlist Resolution
Entries can be:
{"source": "*", "target": "shared-memory"}-- any agent may read shared-memory{"source": "finance-bot", "target": "audit-logger"}-- specific pair{"trust_group": "loan-underwriting"}-- both agents must carry membership incontext.agent_trust_groups
Star wildcards (*) match any source/target. fnmatch patterns are supported.
Context Attributes Read
| Attribute | Phase | Purpose |
|---|---|---|
context.tenant_id / context.tenant | all | Calling agent's tenant for cross-tenant check |
context.cross_tenant_read | all | Explicit cross-tenant handoff marker |
context.read_from_agent | all | Explicit cross-agent read signal |
context.agent_name | all | Source agent for pair resolution |
context.pending_actions | all | Pending tool calls to scan |
context.agent_trust_groups / context.trust_groups | all | Declared trust-group memberships |
Example Policy
Strict isolation with declared trust groups
{
"name": "Strict cross-agent isolation",
"category": "cross-agent-isolation",
"rules": {
"isolation_scopes": ["memory", "context", "tool_state", "scratchpad"],
"allow_cross_agent_reads": [
{"source": "*", "target": "shared-memory"},
{"trust_group": "loan-underwriting"}
],
"block_cross_tenant": true,
"tool_patterns_cross_agent": [
"memory.read_other_*",
"scratchpad.read",
"agent_handoff.*"
],
"action_on_violation": "block"
},
"scope": {
"agents": ["*"]
},
"enabled": true
}
SDK Integration
import waxell_observe as waxell
waxell.init()
@waxell.observe(
agent_name="finance-bot",
enforce_policy=True,
metadata={"agent_trust_groups": ["loan-underwriting"]},
)
async def finance(query: str) -> str:
return await analyze(query)
For multi-agent workflows that need to legitimately share state, declare both agents in the same agent_trust_groups AND add a {"trust_group": "<name>"} entry to allow_cross_agent_reads.
Observability
| Field | Example (BLOCK) |
|---|---|
| Category | cross-agent-isolation |
| Action | block |
| Reason | Agent 'finance-bot' attempted to read state from 'support-bot'; no allowlist entry permits this cross-agent read. |
| Metadata | {"source_agent": "finance-bot", "target_agent": "support-bot", "nist_ai_rmf": "MS-2.7", "iso_42001": "A.8.3"} |
Common Gotchas
- Cross-tenant is a hard ceiling. No allowlist can override
block_cross_tenant: true. To allow cross-tenant reads (rare), explicitly disable the flag. - Allowlist entries are dicts, not strings.
{"source": "...", "target": "..."}or{"trust_group": "..."}. Plain strings are silently ignored. - Trust groups require BOTH agents to declare membership. If only the source agent carries the group, the entry doesn't apply.
- fnmatch patterns, not regex.
memory.read_other_*matchesmemory.read_other_agentbut notmemory.readOther. Patterns are also case-insensitive (the handler matches both raw and lowercased). - Reads
same-tenant cross-agent-- not cross-tenant. This category is for isolating agents within ONE tenant. Cross-tenant is handled as a hard ceiling. - Pending tool calls need
argspopulated with the target. If your runtime doesn't passagent/target_agentin tool args, the policy can't extract a target and reportsunknown. redactaction is supported in addition toblock/warn-- useful when you want the run to continue but the cross-agent read to be stripped from the response.
Next Steps
- Delegation Policy -- Constrain agent-to-agent handoffs and budgets
- Memory Policy -- Per-agent memory policy (writes/reads)
- Identity Policy -- Agent identity and authentication
- Compliance Policy -- NIST AI RMF / ISO 42001 framework binding
- Policy Categories & Templates -- All categories