---
name: knowledge-graph-building
description: >-
  Extracts entities and relationships from text to build structured knowledge graphs.
  Use when building graphs from documents, extracting entity relationships, connecting
  information across sources, or mapping dependencies. NOT for keyword extraction,
  tagging, or full-text search.
allowed-tools:
  - Read
  - Glob
  - Grep
  - Bash
---

## Identity & Scope

**Executor:** either
**Model tier:** sonnet
**Scope:** Text documents, codebases, documentation, structured data files.
**Off-limits:** Modifying source documents, external API calls without approval, database writes without approval.

### Hard Rules
- No credentials in output or git — ever
- No spending money or publishing without explicit user approval
- No deleting files — archive first, 48hr hold
- Report completion to boss via structured output

## Essential Principles

1. **Deduplicate aggressively** — "Python", "Python 3.11", "CPython" are one entity. Guards against: fragmented graphs with duplicate nodes.
2. **Score every relationship** — Not all connections are equally certain. Guards against: treating inferences as facts.
3. **Respect temporal boundaries** — "works_at" needs a timespan. Guards against: stale relationships shown as current.
4. **Extract bidirectionally** — If A depends_on B, check if B used_by A. Guards against: incomplete graphs.

## When to Use
- "Build a knowledge graph from this data"
- Mapping dependencies between services, libraries, or modules
- Extracting organizational relationships from text
- Connecting concepts across multiple documents for synthesis

## When NOT to Use
- Simple keyword extraction — use text processing tools
- Full-text search — use Grep instead
- Summarizing a single document — just summarize directly
- Building a relational database schema — use data modeling skills

## Rationalizations to Reject

| Shortcut | Why it's wrong |
|----------|----------------|
| "Skip dedup, let consumer handle it" | Duplicates make the graph unreliable. Dedup is part of extraction. |
| "All relationships are high confidence" | Uniform scores are useless. Differentiate inferred from explicit. |
| "Temporal data is optional" | Without time bounds, outdated relationships appear current. |
| "Only extract named entities" | Implicit entities (by role/pronoun) carry valuable relationships. |

## Workflow

### Phase 1: Source Analysis
**Entry:** Source text or document set identified.
**Actions:**
1. Catalog all source documents.
2. Define entity types for this domain (Person, Org, Technology, Product, etc.).
3. Define relationship types. Plan batching (10-20 docs per batch).
**Exit:** Entity and relationship taxonomies defined.

### Phase 2: Entity Extraction
**Entry:** Phase 1 complete.
**Actions:**
1. Extract named and implicit entities with type classification.
2. Deduplicate: merge aliases, abbreviations, variants into canonical names.
3. Record first_seen/last_seen and key properties per entity.
**Exit:** Deduplicated entity list with types, properties, temporal bounds.

### Phase 3: Relationship Extraction
**Entry:** Phase 2 complete.
**Actions:**
1. Extract explicit relationships (stated in text) and implicit ones (inferred from context).
2. Score confidence: 0.9+ explicit, 0.5-0.89 inferred, flag <0.5 as uncertain.
3. Add temporal bounds where data supports it. Check bidirectional completeness.
**Exit:** Edge list with confidence scores and temporal bounds.

### Phase 4: Verify
**Entry:** All prior phases complete.
**Actions:**
1. Check for remaining duplicates (unmerged aliases).
2. Spot-check 5 random relationships against source text.
3. Validate output matches required JSON structure.
**Exit:** All checks pass — report results to boss/user.

## Output Format

```json
{
  "skill": "knowledge-graph-building",
  "status": "completed",
  "worker": "worker-009",
  "summary": "Extracted 47 entities and 83 relationships from 12 documents. 6 uncertain flagged.",
  "findings": [
    {"item": "47 entities extracted", "severity": "info", "detail": "12 Person, 18 Tech, 8 Org, 5 Product, 4 Concept. 9 duplicates merged."}
  ],
  "graph": {
    "entities": [
      {"id": "e1", "name": "Django", "type": "Technology", "properties": {"language": "Python"}, "first_seen": "2005"},
      {"id": "e2", "name": "Simon Willison", "type": "Person", "first_seen": "2003"}
    ],
    "relationships": [
      {"source": "e2", "target": "e1", "relationship": "created", "confidence": 0.95, "valid_from": "2003"}
    ]
  },
  "errors": [],
  "elapsed_seconds": 73.8
}
```

**Bad example:** `{"graph": {"entities": [{"name": "Django"}], "relationships": [{"source": "Django", "target": "Python", "relationship": "related_to"}]}}` — No types, no confidence, no temporal data, "related_to" too vague.

## Escalation Triggers

STOP and report to boss when:
- Source documents contain personal data requiring privacy handling
- Corpus exceeds 500 documents (needs different strategy)
- >30% of relationships have confidence below 0.5
- You discover credentials in source documents

Report as: `{"status": "escalated", "reason": "...", "context": "...", "recommendation": "..."}`

## Success Criteria

- [ ] All source documents processed
- [ ] Entities deduplicated with canonical names and type classifications
- [ ] Every relationship has a confidence score
- [ ] Temporal bounds present where data supports them
- [ ] Low-confidence relationships (<0.5) flagged
- [ ] Output matches JSON format above
