# Diagrams — Module B6: Inter-Agent Trust and Communication Security

**Module**: B6 — Inter-Agent Trust and Communication Security
**Diagram count**: 5
**Tool**: Mermaid (primary). Each diagram validated in [Mermaid Live Editor](https://mermaid.live).

---

## Diagram 1 — The Multi-Agent Mesh as a Trust Graph

**Type**: Trust graph / network
**Purpose**: The single most important visual in the module. A multi-agent mesh is not one agent — it is a graph of trust relationships. Every edge between two agents is a trust boundary as load-bearing as the boundary between the user and the agent. Most deployed meshes treat these edges as implicit-trust (dashed, red): shared context, no authentication, peer outputs consumed as fact. The blast radius is mesh-wide because the graph is connected and the trust is implicit.
**Reading the diagram**: Solid teal edges = authenticated channels (signed messages, the defense). Dashed red edges = implicit-trust channels (the mesh default — the attack surface). The orchestrator sits at the center; executors and supervisor form the mesh. Note how many edges exist — each one is a boundary an attacker can cross by forging a message.

```mermaid
flowchart TB
  ORCH["ORCHESTRATOR<br/>decomposes task · delegates<br/>trust level: HIGH"]
  RES["RESEARCH AGENT<br/>read-only · no commit<br/>trust level: LOW"]:::low
  CODE["CODE AGENT<br/>writes staging<br/>trust level: MED"]:::med
  DEPLOY["DEPLOY AGENT<br/>writes production<br/>trust level: HIGH"]:::high
  SUP["SUPERVISOR<br/>reviews · approves/rejects<br/>trust level: HIGH"]

  ORCH -->|"signed delegation"| RES
  ORCH -->|"signed delegation"| CODE
  ORCH -->|"signed delegation"| DEPLOY
  RES -.->|"IMPLICIT TRUST<br/>peer output as fact"| CODE
  CODE -.->|"IMPLICIT TRUST<br/>peer output as fact"| SUP
  SUP -->|"signed approval/reject"| ORCH
  RES -.->|"FORGEABLE<br/>'from: orchestrator'"| DEPLOY

  EDGE1["each edge = a trust boundary<br/>forgeable if unsigned"]:::danger
  RES -.-> EDGE1

  classDef low fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  classDef med fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#f0a868
  classDef high fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
  classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  style ORCH fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style SUP fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
```

> **Note**: Every line in this graph is a trust boundary. The dashed red lines are the mesh default — peer outputs consumed as fact, no authentication. A compromise of any one node (research, the lowest-trust agent) can reach every other node through these implicit edges. The solid teal lines are the defense: signed delegations and approvals. The module's job is to turn every dashed line solid.

---

## Diagram 2 — The Trust-Escalation Attack (Forged Orchestrator Message)

**Type**: Attack sequence / flow
**Purpose**: The canonical attack — Microsoft Failure Mode Taxonomy v2.0 #3 (Inter-Agent Trust Escalation). A low-trust agent is compromised (via injection, memory poisoning, or a compromised tool) and forges a message that claims to be from the orchestrator. The high-trust deploy agent, which trusts the orchestrator but cannot verify the sender, executes an unauthorized production deployment. The escalation is real: a read-only agent has triggered a production write.
**Reading the diagram**: Read left-to-right as the attack chain. Step 1: the attacker compromises the low-trust research agent. Step 2: the compromised agent forges an orchestrator message. Step 3: the high-trust agent acts on it because the channel is unauthenticated. The dashed red line is the vulnerability; the green annotation marks where the signature check (B6.2) would stop it.

```mermaid
flowchart LR
  ATK["ATTACKER<br/>indirect injection (B2)<br/>or memory poison (B3)"]:::danger
  RES["RESEARCH AGENT<br/>compromised<br/>trust level: LOW"]:::low
  FORGE["FORGED MESSAGE<br/>header: from=orchestrator<br/>intent=approve_deployment<br/>(unsigned — just a field)"]:::danger
  DEPLOY["DEPLOY AGENT<br/>trusts 'from' field<br/>cannot verify sender<br/>trust level: HIGH"]:::high
  HARM["PRODUCTION DEPLOYMENT<br/>triggered by a read-only agent<br/>= privilege escalation"]:::danger

  ATK -->|"1. compromise"| RES
  RES -->|"2. forge"| FORGE
  FORGE -.->|"3. unauthenticated<br/>channel"| DEPLOY
  DEPLOY -->|"4. execute"| HARM

  DEFENSE["B6.2 DEFENSE<br/>verify() rejects:<br/>signature invalid<br/>(no key = forged)"]:::good
  FORGE -. blocked by .-> DEFENSE

  classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  classDef low fill:#14141f,stroke:#f08080,color:#f08080
  classDef high fill:#14141f,stroke:#82e0aa,color:#82e0aa
  classDef good fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
  style ATK fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  style RES fill:#14141f,stroke:#f0a868,color:#f0a868
  style DEPLOY fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
  style DEFENSE fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
```

> **Note**: This is the multi-agent confused deputy. The deploy agent is the deputy — it holds production write authority. The forged orchestrator message is the abuse of that authority. The deploy agent cannot tell the forged message from a real one because the channel does not authenticate senders. The signature check at step 3 is the entire defense: a message the research agent cannot sign is a message the deploy agent must reject.

---

## Diagram 3 — The Cascade Chain (ASI06)

**Type**: Propagation / cascade
**Purpose**: Why the inter-agent edge has the worst blast radius on the B1 surface map. One poisoned or hallucinated output from a single agent propagates through the mesh as every downstream agent consumes it as fact. The cascade amplifies — each hop adds confidence because the output appears to come from multiple sources. Fan-out makes it worse: one orchestrator output poisons N executors.
**Reading the diagram**: Read left-to-right as the propagation. The poison enters at agent A, propagates to B (which treats it as fact), to C (which now believes it has two sources), to the commit. The blast-radius cap (cascade depth = 3) is the circuit breaker that stops propagation before it consumes the mesh.

```mermaid
flowchart LR
  POISON["POISONED OUTPUT<br/>from agent A<br/>(hallucinated or injected)"]:::danger
  A["AGENT A<br/>produces bad output"]
  B["AGENT B<br/>consumes A's output AS FACT<br/>reasoning builds on it"]
  C["AGENT C<br/>consumes B's output AS FACT<br/>now 'two sources' agree"]
  COMMIT["COMMIT / ACTION<br/>taken on poisoned foundation"]:::danger

  POISON --> A
  A -.->|"implicit trust<br/>no verification"| B
  B -.->|"implicit trust<br/>no verification"| C
  C -->|"acts on it"| COMMIT

  FANOUT["FAN-OUT<br/>orchestrator delegates to N executors<br/>one poison → N contaminated"]:::danger
  A -. amplifies .-> FANOUT

  CAP["BLAST-RADIUS CAP<br/>cascade depth ≤ 3<br/>fan-out ≤ N<br/>action budget ≤ K"]:::good
  C -. trips at .-> CAP

  classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  classDef good fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
  style A fill:#14141f,stroke:#f0a868,color:#f0a868
  style B fill:#14141f,stroke:#f0a868,color:#f0a868
  style C fill:#14141f,stroke:#f08080,color:#f08080
  style POISON fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  style FANOUT fill:#14141f,stroke:#f08080,color:#f08080
  style CAP fill:#14141f,stroke:#82e0aa,stroke-width:2px,color:#82e0aa
```

> **Note**: A single hallucination is a localized error the user corrects. A cascade is a contaminated reasoning chain — internally consistent, but the foundation was poisoned. By the time the action is taken, the original error is buried under layers of plausible derivation. The blast-radius cap does not detect the cascade (B8 observability does that); it ensures the cascade hits a hard limit and stops.

---

## Diagram 4 — The Signed-Message Verification Flow

**Type**: Process / control flow
**Purpose**: What the recipient does before acting on an inter-agent message. Five checks, all of which must pass. Drop any one and a path opens: drop the signature check and forgery works; drop the freshness window and an old captured message replays; drop the nonce and a message replays within the window; drop the task binding and an approval for task 42 replays against task 43. This is DD-16 ZeroClaw's HMAC receipts extended with replay protection and durable keys.
**Reading the diagram**: Read top-to-bottom as the verification gate. Every check is a hard gate — the first failure rejects the message. The OK path (green) is the only path that reaches "act on message." The five checks map to the five layers of the signed-message contract.

```mermaid
flowchart TB
  MSG["INCOMING INTER-AGENT MESSAGE<br/>header + payload + signature"]
  MSG --> C1{"1. Recipient?<br/>to == me"}
  C1 -->|"no"| R1["REJECT — wrong recipient"]:::danger
  C1 -->|"yes"| C2{"2. Task binding?<br/>task_id == current task"}
  C2 -->|"no"| R2["REJECT — task_id mismatch<br/>(replay across tasks)"]:::danger
  C2 -->|"yes"| C3{"3. Fresh?<br/>abs(now - ts) ≤ window"}
  C3 -->|"no"| R3["REJECT — stale<br/>outside freshness window"]:::danger
  C3 -->|"yes"| C4{"4. Nonce fresh?<br/>not seen before"}
  C4 -->|"no"| R4["REJECT — replayed nonce"]:::danger
  C4 -->|"yes"| C5{"5. Signature valid?<br/>HMAC verifies / key_id known"}
  C5 -->|"no"| R5["REJECT — forged or<br/>rotated-out key"]:::danger
  C5 -->|"yes"| ACT["ACT ON MESSAGE<br/>the only OK path"]:::good

  KEYSTORE["KEY STORE (durable — B5 vault)<br/>key_id → secret<br/>rotated, retained for verify window<br/>NOT ephemeral (closes ZeroClaw gap)"]:::good
  KEYSTORE -. provides key .-> C5

  NONCEC["NONCE CACHE (bounded LRU)<br/>seen nonces, TTL = freshness window<br/>cleans expired entries"]:::good
  NONCEC -. checks against .-> C4

  classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  classDef good fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
  style MSG fill:#14141f,stroke:#5eead4,color:#e4e4e8
  style C1 fill:#101018,stroke:#5eead4,color:#e4e4e8
  style C2 fill:#101018,stroke:#5eead4,color:#e4e4e8
  style C3 fill:#101018,stroke:#5eead4,color:#e4e4e8
  style C4 fill:#101018,stroke:#5eead4,color:#e4e4e8
  style C5 fill:#101018,stroke:#5eead4,color:#e4e4e8
  style KEYSTORE fill:#101018,stroke:#82e0aa,color:#82e0aa
  style NONCEC fill:#101018,stroke:#82e0aa,color:#82e0aa
```

> **Note**: Five gates, series — the first failure rejects. This is the same defense-in-depth discipline as B2's five-layer injection defense and B5's scope-check middleware: a deterministic, compiled verification chain that the model cannot talk its way past. The key store being durable (not ephemeral) is what closes the ZeroClaw gap Course 1 flagged — signatures now survive session boundaries, so the B3 sleeper attack (a poisoned message retrieved in a later session) can be verified.

---

## Diagram 5 — Compartmentalization with Trust Boundaries

**Type**: Trust zone / boundary
**Purpose**: Signed messages authenticate the channel; compartmentalization limits what an authenticated agent can ask another to do. Agents are partitioned into trust compartments, and every cross-compartment request is mediated, authorized, and audited by the orchestrator — not by the agents themselves. A low-trust research agent cannot direct a high-trust deploy agent without an explicit, orchestrator-enforced boundary crossing.
**Reading the diagram**: Three trust zones (low / medium / high), walled off. The orchestrator sits above all zones and mediates crossings. The dashed red arrow is the forbidden path (low → high without mediation); the solid teal arrows are authorized crossings, each logged. The load-bearing principle: the compartment boundary is enforced in the orchestrator because the agents can be coerced.

```mermaid
flowchart TB
  ORCH["ORCHESTRATOR<br/>policy enforcement point<br/>mediates every crossing"]

  subgraph LOW["LOW-TRUST COMPARTMENT"]
    direction LR
    RES["research agent<br/>read-only"]
  end
  subgraph MED["MEDIUM-TRUST COMPARTMENT"]
    direction LR
    CODE["code agent<br/>writes staging"]
  end
  subgraph HIGH["HIGH-TRUST COMPARTMENT"]
    direction LR
    DEPLOY["deploy agent<br/>writes production"]
  end

  RES -.->|"FORBIDDEN<br/>no agent-to-agent<br/>crossing without orchestrator"| DEPLOY
  RES -->|"1. request crossing<br/>(output = data, not instruction)"| ORCH
  ORCH -->|"2. policy check:<br/>is high-trust task<br/>independently authorized?"| CHECK{"AUTHORIZED?"}
  CHECK -->|"yes"| ORCH2["3. mediate + log<br/>+ rate-limit"]:::good
  ORCH2 -->|"4. signed delegation"| DEPLOY
  CHECK -->|"no"| DENY["DENY<br/>out-of-policy intent<br/>research → deploy blocked"]:::danger

  ORCH -.->|"enforces boundary"| LOW
  ORCH -.->|"enforces boundary"| MED
  ORCH -.->|"enforces boundary"| HIGH

  CAPS["BLAST-RADIUS CAPS<br/>cascade depth ≤ 3 · fan-out ≤ N<br/>session action budget ≤ K<br/>(B8 observability feeds)"]:::good
  ORCH -. enforces .-> CAPS

  classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  classDef good fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
  style ORCH fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style LOW fill:#0f0f16,stroke:#f08080,stroke-width:1.5px,color:#f08080
  style MED fill:#0f0f16,stroke:#f0a868,stroke-width:1.5px,color:#f0a868
  style HIGH fill:#0f0f16,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
  style RES fill:#14141f,stroke:#f08080,color:#f08080
  style CODE fill:#14141f,stroke:#f0a868,color:#f0a868
  style DEPLOY fill:#14141f,stroke:#82e0aa,color:#82e0aa
  style CHECK fill:#101018,stroke:#5eead4,color:#e4e4e8
  style CAPS fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
```

> **Note**: The orchestrator is the policy enforcement point because it is smaller, more deterministic, and more auditable than any agent. An agent cannot be trusted to enforce its own trust level — a compromised agent will claim whatever level gets its message through. This is the same principle as B4's tool gate and B5's scope check: the deterministic component holds the policy, because the model-in-the-loop component can be coerced. The blast-radius caps are the circuit breaker that stops a cascade before it crosses compartment walls.
