Files
agency-agents/examples/workflow-multi-agent-shared-identity.md
dreynow 29af62beab Add Identity Graph Operator agent + multi-agent shared identity workflow
New specialized agent: Identity Graph Operator - operates a shared identity
graph so multiple agents in a system all resolve to the same canonical entity.
Prevents duplicate records, conflicting actions, and cascading errors when
agents encounter the same real-world entity from different sources.

New example workflow: Multi-Agent Shared Identity - step-by-step walkthrough
of 3 agents (Support, Backend, Analytics) handling the same customer across
email, phone, and web channels with shared identity resolution.

Enhanced Agentic Identity & Trust Architect with a section showing how it
complements the Identity Graph Operator (agent identity vs entity identity).
2026-03-09 12:44:10 +00:00

7.5 KiB

Multi-Agent Workflow: Shared Identity Resolution

What happens when three agents all encounter the same customer from different sources - and how to prevent duplicate records, conflicting actions, and cascading errors.

The Problem

You're running a customer support system with three agents:

  • Support Responder processes incoming tickets
  • Backend Architect maintains the customer database
  • Analytics Reporter generates weekly customer reports

A customer named "Bill Smith" (wsmith@acme.com) contacts you through email support, then calls your phone line, then submits a web form. Each channel uses a different source system. Without shared identity, you get three separate customer records and three separate responses.

Agent Team

Agent Role in this workflow
Identity Graph Operator Resolves all records to canonical entities before other agents act
Support Responder Handles customer tickets (only after identity is resolved)
Backend Architect Designs the data model with identity-first architecture
Analytics Reporter Reports on unique customers, not duplicate records
Reality Checker Verifies merge decisions meet quality gates

The Workflow

Step 1 - Set Up the Identity Layer

Activate Identity Graph Operator

Activate Identity Graph Operator.

We have 3 data sources for customer records:
- "email_support" - tickets from email (fields: email, name, subject)
- "phone_support" - call logs (fields: phone, caller_name, call_date)
- "web_forms" - web submissions (fields: email, full_name, phone, message)

Set up the shared identity graph so all agents resolve to the same customer.

The Identity Graph Operator runs:

register_agent with capabilities: ["identity_resolution", "entity_matching", "merge_review"]

# Then resolves incoming records as they arrive

Step 2 - First Record Arrives (Email)

The Support Responder receives a ticket from email_support:

{
  "source": "email_support",
  "external_id": "ticket-9201",
  "email": "wsmith@acme.com",
  "name": "Bill Smith",
  "subject": "Can't reset my password"
}

Before responding, the Support Responder asks the Identity Graph Operator to resolve:

resolve with source_name: "email_support", external_id: "ticket-9201",
  data: { "email": "wsmith@acme.com", "first_name": "Bill", "last_name": "Smith" }

Result: New entity created (first time seeing this person).

{
  "entity_id": "ent-a1b2c3",
  "is_new": true,
  "confidence": 1.0,
  "canonical_data": { "email": "wsmith@acme.com", "first_name": "bill", "last_name": "smith" }
}

Support Responder now handles the ticket, tagged with entity_id: ent-a1b2c3.

Step 3 - Second Record Arrives (Phone)

A call comes in through phone_support:

{
  "source": "phone_support",
  "external_id": "call-7744",
  "phone": "+1-555-014-2",
  "caller_name": "William Smith"
}

Identity Graph Operator resolves:

resolve with source_name: "phone_support", external_id: "call-7744",
  data: { "phone": "+15550142", "first_name": "William", "last_name": "Smith" }

The engine doesn't have a phone match yet (the email record didn't include a phone). This creates a new entity:

{
  "entity_id": "ent-d4e5f6",
  "is_new": true,
  "confidence": 1.0
}

Two entities now exist. Are they the same person? The Identity Graph Operator isn't sure yet - no overlapping fields to match on.

Step 4 - Third Record Arrives (Web Form)

A web form submission comes in with BOTH email and phone:

{
  "source": "web_forms",
  "external_id": "form-3388",
  "email": "wsmith@acme.com",
  "full_name": "William Smith",
  "phone": "555-0142",
  "message": "Still can't reset my password, tried calling too"
}

Identity Graph Operator resolves:

resolve with source_name: "web_forms", external_id: "form-3388",
  data: { "email": "wsmith@acme.com", "first_name": "William", "last_name": "Smith", "phone": "+15550142" }

Now it gets interesting. The engine:

  1. Matches email to ent-a1b2c3 (exact email match)
  2. Matches phone to ent-d4e5f6 (exact phone match after normalization)
  3. Realizes both entities should be one person
{
  "entity_id": "ent-a1b2c3",
  "is_new": false,
  "confidence": 0.96,
  "canonical_data": {
    "email": "wsmith@acme.com",
    "first_name": "william",
    "last_name": "smith",
    "phone": "+15550142"
  }
}

The engine auto-merged ent-d4e5f6 into ent-a1b2c3 (the email entity had more members). The phone record is now linked to the same entity.

Step 5 - Verify the Merge

Activate Reality Checker to verify:

Activate Reality Checker.

The identity graph just auto-merged two entities:
- ent-a1b2c3 (email: wsmith@acme.com, name: Bill Smith)
- ent-d4e5f6 (phone: +15550142, name: William Smith)

Review the merge evidence and verify this is correct.

The Reality Checker asks the Identity Graph Operator:

explain with entity_id: "ent-a1b2c3"

Gets back the full audit: merge chain, per-field scores, nickname mapping (Bill -> William), timeline of events. Confirms the merge is valid.

Step 6 - Analytics Gets Clean Data

Activate Analytics Reporter:

Activate Analytics Reporter.

Generate a report on customer support volume this week.
Use the identity graph to count unique customers, not duplicate records.

The Analytics Reporter queries the identity graph:

search with q: "smith"

Gets back one entity with three linked source records, not three separate customers. The report shows 1 customer with 3 touchpoints, not 3 customers with 1 touchpoint each.

What Would Have Happened Without Shared Identity

With shared identity Without shared identity
1 customer record 3 separate customer records
Support agent sees full history across channels Support agent only sees the email ticket
Analytics reports 1 customer, 3 touchpoints Analytics reports 3 customers
One password reset Three separate password reset workflows
Customer gets one follow-up Customer gets three follow-ups

Key Patterns

  1. Resolve before acting. Every agent resolves incoming records through the identity graph BEFORE taking action. This is the single most important pattern.

  2. The bridge record. The web form submission (Step 4) was the bridge - it had both email AND phone, connecting two previously separate entities. This is why multi-source ingestion matters.

  3. Propose, don't merge. For lower confidence matches, the Identity Graph Operator creates proposals. The Reality Checker reviews them. Direct auto-merge only happens at high confidence.

  4. Memory compounds. After this workflow, the identity graph remembers that "Bill" and "William" at the same phone number are the same person. Future agents benefit from this learned association.

Scaling This Pattern

This 3-agent example works the same way with 30 agents or 300. The identity graph is the shared substrate:

  • Sales agents resolve leads before adding to CRM
  • Billing agents resolve customers before charging
  • Shipping agents resolve addresses before dispatching
  • Marketing agents resolve contacts before emailing
  • Compliance agents resolve entities before flagging

Every agent resolves first. Every agent gets the same answer. That's the pattern.


Prerequisites: Identity Graph Operator agent must be activated first. Uses Kanoniv as the identity graph backend (npx @kanoniv/mcp or pip install kanoniv).