Skip to content

Foundation / Agentic Patterns

Collaboration Patterns

Realtime patterns for shared agentic surfaces — showing who is present, where they are pointing, what they are changing, and how conflicts are resolved. Every component is built to make human–agent co-editing legible and trustworthy.

Color rule: Red (--ds-color-agency) marks agent identity and authority. Blue (--ds-color-temporal) marks active presence. Gold (--ds-color-validation) marks conflict and human review gates. These three are the entire collaboration color vocabulary.

Component 1 of 4

PresenceAvatarStack

Agent-aware presence row. Humans render as circles, agents as squares. Executing agents pulse with an agency-red ring; active participants show a temporal-blue dot. Ghost participants (recently left) fade to 38% opacity.

Default (size=28)

T
R
FR
SC
C
+1
3 AGENTS·2 HUMANS

Large (size=36)

T
R
FR
SC
C
+1
3 AGENTS·2 HUMANS

Compact (size=20, maxVisible=3)

T
R
FR
+3
3 AGENTS·2 HUMANS
import { PresenceAvatarStack } from "@/components/patterns/PresenceAvatarStack";

const participants = [
  { id: "1", type: "agent", name: "Treasury", role: "ORCHESTRATOR", state: "executing" },
  { id: "2", type: "agent", name: "Risk",     role: "EXECUTOR",     state: "active" },
  { id: "3", type: "human", name: "Faramarz", state: "active", color: "#3D5AFE" },
  { id: "4", type: "human", name: "Sarah",    state: "idle" },
  { id: "5", type: "human", name: "James",    state: "ghost" },
];

<PresenceAvatarStack
  participants={participants}
  maxVisible={5}
  size={28}
  overlap={8}
  showTooltip
/>
PropTypeDefaultDescription
participantsPresenceParticipant[]All participants to display.
maxVisiblenumber5Max avatars before +N overflow chip.
sizenumber28Avatar size in px.
overlapnumber8Overlap between adjacent avatars in px.
showTooltipbooleantrueShow name+role on hover.
state: “executing

Agent running — agency red pulse ring

state: “active

Currently focused — temporal blue dot

state: “idle

Present, not interacting — muted dot

state: “ghost

Recently left — 38% opacity, no dot

Component 2 of 4

CollaborativeCursor

Ghost cursor overlay with identity badge. Placed inside a position: relative container. Human cursors use a standard arrow shape. Agent cursors use a bracket form — visually distinct from human pointers.

Shared editing surface
position: relative container
import { CollaborativeCursor } from "@/components/patterns/CollaborativeCursor";

// Inside a position:relative container:
<div style={{ position: "relative", width: "100%", height: 400 }}>
  {/* Human cursor */}
  <CollaborativeCursor
    id="user-1"
    type="human"
    name="Sarah Chen"
    x={25}          // % of container width
    y={40}          // % of container height
    color="#00897B"
  />

  {/* Agent cursor — executing */}
  <CollaborativeCursor
    id="agent-1"
    type="agent"
    name="Treasury Agent"
    role="ORCHESTRATOR"
    x={60}
    y={55}
    executing
  />

  {/* Ghost — recently left */}
  <CollaborativeCursor id="user-2" type="human" name="James" x={10} y={80} ghost />
</div>
PropTypeDefaultDescription
type"human" | "agent"Determines cursor shape.
namestringParticipant name in identity label.
rolestringAgent role label (agents only).
xnumberX as % of container width (0–100).
ynumberY as % of container height (0–100).
colorstring#3D5AFEHex color for human cursor. Agents always use --ds-color-agency.
executingbooleanfalseElevated opacity + EXECUTING label (agents only).
ghostbooleanfalseFade to 25% — participant recently left.

Component 3 of 4

LiveChangeIndicator

Diff highlight with attribution. Three modes — inline (underline), field (left border), block (full tint). Every change must be attributed to a named human or agent. State drives color: pending (blue/red), review (gold), accepted (green), rejected (faded).

Mode: inline

The EUR/USD position notional is €42.5MTreasuryPENDING with a P&L of +$128,400Sarah ChenPENDING.

Mode: field

$2,850,000
Risk AgentREVIEWERREVIEW

Updated from market data feed at 14:32:07 UTC

Mode: block

ComplianceORCHESTRATORPENDINGRegulatory threshold recalculation

Based on updated Basel IV guidelines, the capital adequacy ratio for the EUR book has been recalculated from 12.4% to 13.1%. This requires a position reduction of €8.2M by EOD.

import { LiveChangeIndicator } from "@/components/patterns/LiveChangeIndicator";

// Inline — wraps changed text
<p>
  Notional:{" "}
  <LiveChangeIndicator
    mode="inline"
    state="review"
    author={{ type: "agent", name: "Treasury", role: "EXECUTOR" }}
  >
    €42.5M
  </LiveChangeIndicator>
</p>

// Field — wraps a form field row
<LiveChangeIndicator
  mode="field"
  state="review"
  author={{ type: "agent", name: "Risk Agent", role: "REVIEWER" }}
  description="Updated from market data feed"
  onAccept={() => acceptChange()}
  onReject={() => rejectChange()}
>
  <VaRLimitField value={2850000} />
</LiveChangeIndicator>

// Block — wraps a content block
<LiveChangeIndicator
  mode="block"
  state="pending"
  author={{ type: "agent", name: "Compliance", role: "ORCHESTRATOR" }}
>
  <RegulatoryUpdateCard />
</LiveChangeIndicator>
PropTypeDefaultDescription
mode"inline" | "field" | "block""inline"Visual presentation mode.
stateChangeState"pending"pending | review | accepted | rejected.
authorChangeAuthor{ type: 'human'|'agent', name, role? }
descriptionstringShort change description (field/block modes).
onAccept() => voidAccept callback — shows Accept button when provided.
onReject() => voidReject callback — shows Reject button when provided.

Component 4 of 4

ConflictResolutionBanner

Agent conflict surface. When two participants (agents or human + agent) produce diverging values the system cannot auto-resolve, this component surfaces both versions for human arbitration. Conflict is gold — it is a decision gate, not an error.

CONFLICT
EUR/USD Forward RateMaturity: 2026-06-30
HUMAN REVIEW REQUIRED
A
Treasury Agent· ORCHESTRATOR
1.0842
CONFIDENCE
91%

Derived from Bloomberg forward curve + Basel spread adjustment

B
Sarah Chen
1.0856

Manual correction based on desk trading sheet at 15:00 CET

import { ConflictResolutionBanner } from "@/components/patterns/ConflictResolutionBanner";

const [state, setState] = useState<ConflictResolutionState>("unresolved");

<ConflictResolutionBanner
  fieldLabel="EUR/USD Forward Rate"
  description="Maturity: 2026-06-30"
  state={state}
  versionA={{
    id: "a",
    label: "Version A",
    authorName: "Treasury Agent",
    authorType: "agent",
    authorRole: "ORCHESTRATOR",
    value: "1.0842",
    confidence: 0.91,
    reasoning: "Bloomberg forward curve + Basel spread",
  }}
  versionB={{
    id: "b",
    label: "Version B",
    authorName: "Sarah Chen",
    authorType: "human",
    value: "1.0856",
    reasoning: "Desk trading sheet at 15:00 CET",
  }}
  onAcceptA={() => setState("resolved_a")}
  onAcceptB={() => setState("resolved_b")}
  onMerge={() => setState("resolved_manual")}
/>
PropTypeDefaultDescription
fieldLabelstringShort label for the field/block in conflict.
descriptionstringDescription of the conflict context.
versionA / versionBConflictVersion{ id, label, authorName, authorType, authorRole?, value, confidence?, reasoning? }
stateConflictResolutionState"unresolved"unresolved | resolved_a | resolved_b | resolved_manual.
onAcceptA / onAcceptB() => voidAccept callbacks — show Accept buttons when provided.
onMerge() => voidManual merge — shows Merge Manually option.
Color rule: Conflict state is always gold (--ds-color-validation). Conflict is not an error — it is a decision gate. Red (agency) is reserved for agent identity markers. Green (--ds-color-outcome-positive) signals resolved state.

Anti-Patterns

What NOT to do

Do

Use circular avatars for humans, square for agents — entity type must be visually distinct.

Show EXECUTING state agents with agency-red rings, not temporal blue.

Attribute every live change to a named participant.

Use gold for conflict banners — conflicts are decisions, not failures.

Ghost stale cursors (opacity 25%) rather than removing immediately.

Don't

Don't show agents with human-style circular avatars — this obscures entity type.

Don't use red for conflict banners — red means error or agent authority.

Don't show anonymous diffs — every change needs attribution.

Don't auto-resolve agent conflicts — always surface to human.

Don't use CollaborativeCursor outside a position:relative container.

Related