> ## Documentation Index
> Fetch the complete documentation index at: https://docs.experio.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Enrichment Rules

> Enrich the knowledge graph with LLM-powered post-processing rules

## Overview

Enrichment rules let you enrich your knowledge graph **after** document ingestion is complete. Using prompt-based, LLM-powered rules, you can:

* **Add or update attributes** on existing nodes (e.g., tag projects with domains from a taxonomy)
* **Create new nodes** inferred from existing data (e.g., generate Obligation nodes from ContractClauses)
* **Create relationships** between nodes (e.g., link Employees to Skills based on resume content)
* **Create nodes and relationships** in one step (e.g., create Obligation and link it to the source)

Navigate to **Admin > Graph > Rules**.

## How It Works

Each enrichment rule has three parts:

| Part       | Description                                                                     |
| ---------- | ------------------------------------------------------------------------------- |
| **Input**  | What to pull from the graph — target nodes and their attributes or related data |
| **Prompt** | Natural language instructions for the LLM, with placeholders for node data      |
| **Output** | What to create — new attributes, nodes, relationships, or combinations          |

The system processes each target node through the LLM and applies the results back to the graph.

## Creating a Rule

1. Click **Create Rule**
2. Enter a **name** and optional **description**
3. Configure the three sections below

### Target Configuration

| Field                 | Description                                                                                       |
| --------------------- | ------------------------------------------------------------------------------------------------- |
| **Target node label** | The entity type to process (e.g., Project, Employee, ContractClause)                              |
| **Target filter**     | Optional Cypher filter to limit which nodes are processed (e.g., only nodes missing an attribute) |

### Input Configuration

Choose what data to send to the LLM for each node:

| Input mode              | Description                                                                         |
| ----------------------- | ----------------------------------------------------------------------------------- |
| **Full node**           | All properties of the target node (except embeddings)                               |
| **Selected attributes** | Only the attributes you specify (e.g., `name`, `description`, `scope`)              |
| **Neighborhood**        | Include related nodes via relationships (e.g., Project → Status, Employee → Resume) |

### Prompt

Write a natural language prompt that guides the LLM. Placeholders are replaced with actual graph data before the prompt is sent.

#### Target node placeholders

| Placeholder            | When available           | Description                                                                             |
| ---------------------- | ------------------------ | --------------------------------------------------------------------------------------- |
| **`{node}`**           | Full node input mode     | The entire target node as formatted text (all attributes except embeddings)             |
| **`{attribute_name}`** | Selected attributes mode | Individual attributes from the target node (e.g., `{name}`, `{description}`, `{scope}`) |

Placeholder names must match the attribute names in your **Input configuration**. Use snake\_case if your graph uses it.

#### Related data placeholders

When **Neighborhood** is configured, you can reference related nodes:

| Placeholder                     | Description                                                     | Example                                                          |
| ------------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------- |
| **`{neighborhood}`**            | All 1-hop neighbors (when using a wildcard neighborhood config) | Formatted list of every related node                             |
| **`{related.Label}`**           | All related nodes of a specific label                           | `{related.Resume}` — all Resume nodes linked to the target       |
| **`{related.Label.attribute}`** | A specific attribute from related nodes of that label           | `{related.Resume.experience}` — experience text from each Resume |

The `Label` in `{related.Label}` must match the **target label** from your neighborhood configuration (e.g., Resume, Skill, Status).

#### Taxonomy expansion

Use **`@TaxonomyName`** to inject taxonomy values into the prompt. The tag is replaced with a list of active leaf values from that taxonomy type.

| Tag           | Expands to                                 |
| ------------- | ------------------------------------------ |
| `@Domain`     | All leaf values in the Domain taxonomy     |
| `@Industries` | All leaf values in the Industries taxonomy |
| `@Skill`      | All leaf values in the Skill taxonomy      |

The LLM receives the full list, which helps it choose from valid options. Define taxonomies in **Admin > Graph > Taxonomies** before creating rules.

#### Example prompt

```
Given this project:
Name: {name}
Description: {description}
Scope: {scope}

From the resume experience: {related.Resume.experience}

Classify this project into exactly one domain from: @Domain
Return only the domain name, nothing else.
```

#### Output format

The system automatically appends format instructions based on your **Output type**. For attributes, nodes, and relationships, the LLM is instructed to return valid JSON only — no markdown, prose, or bullet points. You can add **Output instructions** per attribute to give the LLM extra guidance (e.g., "Use title case" or "Pick the most specific match").

<Info>
  Prompts support the same `@TaxonomyName` syntax used in ingestion. Define your taxonomies before creating rules for best results.
</Info>

### Output Configuration

| Output type             | Description                       | Example                                  |
| ----------------------- | --------------------------------- | ---------------------------------------- |
| **New attribute**       | Add a property to the source node | Set `domain` on Project                  |
| **Updated attribute**   | Modify an existing property       | Update `risk_level`                      |
| **New node**            | Create a new entity               | Create `Obligation` node                 |
| **Relationship**        | Link source to an existing node   | `Employee -[:HAS_SKILL]-> Skill`         |
| **Node + relationship** | Create node and link to source    | `ContractClause -[:GRANTS]-> Obligation` |

For relationships, specify the relationship type and target node label. The LLM will match or create target nodes based on your prompt.

## Running Inference Jobs

1. Save your rule
2. Click **Run Job** (or use the dropdown on the rules list)
3. Optionally enable **Overwrite existing** to re-process nodes that already have results
4. Monitor progress in the **Jobs** tab

### Job Status

| Status        | Description               |
| ------------- | ------------------------- |
| **Queued**    | Job is waiting to start   |
| **Running**   | Job is processing nodes   |
| **Completed** | Job finished successfully |
| **Failed**    | Job encountered an error  |
| **Cancelled** | Job was stopped by user   |

### Job Actions

* **View** — See job details and results
* **Cancel** — Stop a running job
* **Resume** — Continue a failed or cancelled job from where it left off

## Viewing Results

* **Per rule:** Open a rule and go to the **Jobs** tab to see execution history
* **All jobs:** Use the **Executions** tab on the Rules page to see all enrichment jobs across rules
* **Job details:** Click any job to view processed nodes, errors, and created/updated entities

## Flow Integration

Enrichment rules can be used as steps in **Flows**. Add an **Enrichment** node to your flow and select the rule to run. The enrichment step runs when the flow executes, either manually or on a schedule.

## Configuration

Settings that affect enrichment (available in **Admin > System Settings**):

| Setting                                 | Description                                                        | Default |
| --------------------------------------- | ------------------------------------------------------------------ | ------- |
| **ENRICHMENT\_NODE\_CONCURRENCY**       | Number of nodes processed in parallel per job                      | 4       |
| **ENRICHMENT\_RESULT\_RETENTION\_DAYS** | Days to keep EnrichmentResult rows before purge (0 = keep forever) | 90      |

## Best Practices

* **Start with taxonomy** — Define taxonomies before creating rules; `@TaxonomyName` expansion improves classification accuracy
* **Test on a subset** — Use a target filter to limit nodes when testing a new rule
* **Review results** — Check job results after the first run to ensure the prompt produces expected output
* **Use specific prompts** — Clear, specific prompts yield better results than vague instructions

<Tip>
  Enrichment runs asynchronously via RabbitMQ. Ensure the enrichment worker is running (e.g., in Docker Compose) for jobs to process.
</Tip>
