# KnowledgeTools as GraphRAG

`KnowledgeToolsGraphStoreProvider` is the bundled `GraphStoreProvider` that
serves live `KnowledgeTools` triples to `@Retrieval(strategy = GRAPH)`. The
provider is `@since 0.14.0` in TnsAI 0.14.0 (`TnsAI@c2bb5306`).
It ships in Maven Central `0.14.1`.

This is the same in-process bag that `kg_add_triple` writes. It is not a
second graph and it does not add a Maven edge from `tnsai-tools` to
`tnsai-intelligence`.

## When it claims a Role

The adapter claims a Role when **all** of these hold:

- `tnsai-tools` is on the classpath
- `KnowledgeTools` can be loaded
- either `@Retrieval.sources` names `knowledge-tools`, or the fence is
  empty **and** the Role declares no FILE `@KnowledgeSource`

A FILE-sourced Role with an empty fence is claimed by
`InMemoryGraphStoreProvider` (the file-derived graph), not by live
`kg_add_triple` triples. Name `knowledge-tools` explicitly to keep the
built-in bag on those Roles.

Without the tools artifact the provider stays silent. GRAPH with no other
claiming adapter is still a configuration error (`GraphCapabilityException`)
and fails **above** `@Retrieval.onFailure`. Graph retrieval never falls back
to vector search.

The provider is a **framework default**. A consumer-supplied
`GraphStoreProvider` that also claims the Role wins; the built-in is
dropped. Two or more non-default claimants stay a configuration error.

Fence an explicit backend with `sources = "knowledge-tools"` when another
graph adapter is installed.

## Live triples

Each `KnowledgeTools` instance keeps its own bag. Graph retrieval unions
every live instance at retrieve time, so a `kg_add_triple` that lands after
the Role binding was built is still visible. Hits are stamped with source
`knowledge-tools`.

Query matching is ASCII-only. `KnowledgeToolsGraphStore` lower-cases with
`Locale.ROOT` then splits on `[^a-z0-9]+`. A query that contains no ASCII
letters or digits (CJK-only, Turkish `İ`/`ı` only) produces **no tokens**
and scores 0. This is not `InMemoryGraphStore.identityKey`, which keeps
`\p{L}`. Mixed queries keep the ASCII fragments only (`İstanbul` →
`stanbul`).

```java
@Retrieval(strategy = Retrieval.Strategy.GRAPH)
public final class KgRole extends Role {
    // no FILE @KnowledgeSource; tnsai-tools on the classpath
}
```

```java
@Retrieval(
    strategy = Retrieval.Strategy.GRAPH,
    sources = "knowledge-tools")
public final class FencedKgRole extends Role {
    // keeps the built-in bag when another adapter is also installed
}
```

## Not this page

- The full GRAPH / MULTI_QUERY / HIERARCHICAL / TEMPORAL strategy inventory
- Neo4j or other consumer `GraphStore` modules
