5. Run Enrichment

Purpose: Resolve multi-source enrichment context for entities during fact extraction. The orchestrator calls 8 API clients in parallel, merges context for prompt injection, and extracts structured notability signals for deterministic scoring bypass.

Universal sources (always called): Google Knowledge Graph, Wikidata, Wikipedia, GDELT. Domain-specific sources (topic-routed): TheSportsDB (sports), MusicBrainz (music), Nominatim (geography), Open Library (books).

Prerequisites:

  • GOOGLE_KG_API_KEY in .env.local (optional -- KG lookups fail open without it)
  • No API keys required for: Wikidata, Wikipedia, GDELT, TheSportsDB, MusicBrainz, Nominatim, Open Library
  • Enrichment runs automatically during fact extraction (no manual trigger needed)

Cost / Duration: $0 (all free APIs) | ~1-3 seconds per entity

Prompt

Test the enrichment orchestrator for an entity to verify API connectivity
and context resolution.

Step 1 — Run enrichment for a known entity:

```typescript
import { resolveEnrichmentContext, computeDeterministicNotability } from '@eko/ai/enrichment'

const result = await resolveEnrichmentContext({
  entityName: 'LeBron James',
  topicPath: 'sports/basketball',
})

console.log('Context length:', result.context?.length ?? 0)
console.log('Signals:', result.signals)

// Check deterministic notability bypass
const notability = computeDeterministicNotability(result.signals)
if (notability) {
  console.log('Deterministic notability:', notability)
}
```

Step 2 — Verify each source resolves:

- **KG**: `signals.kgFound` should be `true` for well-known entities
- **Wikidata**: `signals.wikidataFound` should be `true`; check `sitelinkCount`
- **Wikipedia**: Context should include a summary paragraph
- **GDELT**: Context should include article count, tone, and locations
- **Domain API**: For sports topics, TheSportsDB context should appear

Step 3 — Verify fail-open behavior:

Test with a nonexistent entity to confirm all sources return gracefully:

```typescript
const result = await resolveEnrichmentContext({
  entityName: 'xyznonexistent12345',
  topicPath: 'science/physics',
})

// Should return null context and empty signals, no errors
console.log('Context:', result.context) // null
console.log('KG found:', result.signals.kgFound) // false
```

The enrichment orchestrator uses `Promise.allSettled()` and wraps each
client in `safeResolve()` -- no single API failure blocks the pipeline.

Design notes:
- Topic routing: `sports/*` → TheSportsDB, `music/*` → MusicBrainz,
  `geography/*` → Nominatim, `books/*` → Open Library
- GDELT provides real-time event context (article volume, sentiment,
  geospatial data) as a universal source
- Deterministic notability bypass: when KG score >= 100 AND Wikidata
  sitelinks >= 20, the AI notability score is overridden to 0.85
- Skip parameter: pass `skip: ['wikipedia']` to exclude sources
  (useful in validation which already has Wikipedia data)

Verification

  • KG lookup resolves for well-known entities (or skips gracefully without API key)
  • Wikidata lookup resolves with sitelink count
  • Wikipedia summary included in context
  • GDELT event context included (article count, tone)
  • Domain-specific client called for matching topic paths
  • Deterministic notability bypass triggers for notable entities
  • Nonexistent entities return null context without errors
  • Metrics emitted: enrichment.resolved.<source>, enrichment.duration_ms

Back to index