Entity Relationship Graph

The Entity Relationship Graph enables second-degree screening — detecting when a customer is related to a sanctioned entity, even if they're not directly listed.

Example: "Amina Abacha" is not on any sanctions list, but is flagged as a family member of "Sani ABACHA" (OFAC-sanctioned).

---

How It Works

text
Customer: "Amina Abacha"
         │
         ▼
┌─────────────────────────────┐
│ Direct Sanctions Search     │ → No match found
└─────────────────────────────┘
         │
         ▼
┌─────────────────────────────┐
│ Relationship Graph Search   │ → Found: family_member of "Sani ABACHA"
└─────────────────────────────┘
         │
         ▼
┌─────────────────────────────┐
│ Decision: REVIEW            │
│ Reason: Related to OFAC     │
│ sanctioned individual       │
└─────────────────────────────┘

Screening Response

When a relationship is detected, the response includes relationship_match:

json
{
  "decision": "REVIEW",
  "audit_id": "aud_7f8a9b2c",
  "match": null,
  "relationship_match": {
    "related_to": {
      "entity_id": "ofac-12345",
      "entity_name": "SANI ABACHA",
      "source": "OFAC",
      "list_type": "sanctions"
    },
    "relationship": {
      "type": "family_member",
      "detail": "child of",
      "confidence": "stated"
    },
    "score": 0.94,
    "decision_reason": "Customer name matches known associate of sanctioned entity"
  }
}

Relationship Types

Type Description Example Patterns
family_member Blood relative or spouse son of, daughter of, wife of, married to
associate Known associate associated with, partner of, close ties to
owner Ownership/control beneficial owner of, shareholder of
owned_by Owned by another subsidiary of, controlled by
employee Employment director of, CEO of, works for
agent_of Acts on behalf agent of, representative of, acting for
linked_to Generic link linked to, connected to, affiliated with

Confidence Levels

Level Meaning Source
stated Explicitly in sanctions data "Son of Sani ABACHA" in OFAC remarks
inferred Pattern-matched from context "associated with" detected
weak Low confidence Requires verification

Relationships with weak confidence should be treated as leads requiring additional investigation, not definitive matches.

---

API Endpoints

Search Relationships

POST/v1/aml/relationships/search

Search Relationships

Search for potential relationships to sanctioned entities by name.

bash
curl -X POST "https://ag-aml.runloci.com/v1/aml/relationships/search" \
  -H "X-API-Key: your_api_key" \
  -d '{"name": "Amina Abacha", "min_score": 0.85}'

Response:

json
{
  "query": "Amina Abacha",
  "has_matches": true,
  "matches": [
    {
      "matched_name": "Amina ABACHA",
      "score": 0.94,
      "related_to": {
        "entity_id": "ofac-12345",
        "entity_name": "SANI ABACHA",
        "source": "OFAC"
      },
      "relationship": {
        "type": "family_member",
        "detail": "child of",
        "confidence": "stated"
      }
    }
  ]
}

Get Entity Relationships

GET/v1/aml/entity/{id}/relationships

Get Entity Relationships

Get all known relationships for a sanctioned entity.

bash
curl "https://ag-aml.runloci.com/v1/aml/entity/ofac-12345/relationships" \
  -H "X-API-Key: your_api_key"

Response:

json
{
  "entity": {
    "id": "ofac-12345",
    "name": "Sani ABACHA",
    "source": "OFAC"
  },
  "total_relationships": 5,
  "relationships": {
    "family_member": [
      {"target_entity_name": "Mohammed ABACHA", "detail": "parent of"},
      {"target_entity_name": "Abba ABACHA", "detail": "parent of"},
      {"target_entity_name": "Amina ABACHA", "detail": "parent of"}
    ],
    "owner": [
      {"target_entity_name": "ABACHA HOLDINGS LTD", "detail": "beneficial owner of"}
    ]
  }
}

Relationship Statistics

GET/v1/aml/relationships/stats

Relationship Statistics

Get statistics about the relationship graph.

bash
curl "https://ag-aml.runloci.com/v1/aml/relationships/stats" \
  -H "X-API-Key: your_api_key"

Response:

json
{
  "total_relationships": 1523,
  "by_type": {
    "family_member": 456,
    "associate": 312,
    "owner": 234,
    "employee": 189
  },
  "by_source": {
    "OFAC": 892,
    "UN": 234,
    "EU": 197,
    "HMT": 200
  }
}

Data Sources

Relationships are extracted from:

Source Field Quality
OFAC remarks ⭐⭐⭐ Rich data
UN COMMENTS ⭐⭐ Good
EU Remark ⭐⭐ Good
HMT notes ⭐⭐ Good
NIGSAC via OpenSanctions ⭐ Limited

OFAC provides the richest relationship data. We extract family members, business associates, and corporate ownership from OFAC remarks.

---

Performance

Relationship screening runs in parallel with direct screening:

text
┌─────────────────────────────────────┐
│          Promise.all([              │
│    ├── Direct Search ─────────────┤  ~30ms
│    └── Relationship Search ────────┤  ~15ms
│          ])                         │
└─────────────────────────────────────┘
         │
Total: max(30, 15) = ~30ms (NOT additive)
Metric Without Graph With Graph Impact
P50 32ms 33ms +1ms
P99 85ms 88ms +3ms

Configuration

Relationship screening can be configured per organization:

json
{
  "enabled": true,
  "min_score": 0.85,
  "decision_escalation": "REVIEW",
  "relationship_types": [
    "family_member",
    "associate", 
    "owner",
    "owned_by",
    "agent_of"
  ]
}
Setting Default Description
enabled true Enable/disable relationship screening
min_score 0.85 Minimum name match score
decision_escalation REVIEW Decision for relationship matches
relationship_types All Which relationship types to check

Setting decision_escalation to BLOCK will block transactions for relationship matches. Use with caution.

---

Use Cases

1. Onboarding KYC

Screen new customers for both direct sanctions and relationships:

python
result = screen(name="Jane Abacha")
if result.relationship_match:
    # Escalate to Enhanced Due Diligence
    initiate_edd(result.relationship_match.related_to)

2. Transaction Monitoring

Flag transactions involving related parties:

python
result = screen(name=beneficiary, amount=500000)
if result.decision == "REVIEW":
    if result.relationship_match:
        alert = f"Beneficiary related to {result.relationship_match.related_to.entity_name}"

3. Compliance Investigation

Use agent lookup for detailed investigation:

python
profile = agent_lookup(
    query="Sani Abacha",
    include_related=True,
    include_reverse_relationships=True
)
# Returns full network: who they're related to AND who's related to them

Support

Questions about the relationship graph? Contact support@runloci.com