Skip to main content
Glama
README.md
<div align="center">

# Predicate

**Reasoning memory for AI agents — a self-improving knowledge graph that grows with use.**

*Every fact carries its provenance. Every answer carries its derivation. The schema sharpens itself the more your agent uses it.*

[![npm](https://img.shields.io/npm/v/predicate-skill?label=npm&color=blue)](https://www.npmjs.com/package/predicate-skill)
[![License: ELv2](https://img.shields.io/badge/License-ELv2-blue.svg)](packages/predicate-skill/LICENSE)
[![Node](https://img.shields.io/badge/node-%E2%89%A520-brightgreen.svg)](https://nodejs.org)
[![GitHub stars](https://img.shields.io/github/stars/NordicAgents/predicate?style=flat&color=yellow)](https://github.com/NordicAgents/predicate/stargazers)
[![Last commit](https://img.shields.io/github/last-commit/NordicAgents/predicate?color=green)](https://github.com/NordicAgents/predicate/commits)

[Install](#install--use-it-in-your-agent) · [How it works](#how-it-works) · [Architecture](#architecture) · [Packages](#packages)

</div>

---

## What is Predicate?

Most agent "memory" is a flat pile of text: the model re-reads it and takes it
on faith — no record of where a fact came from, no guarantee the same question
answers the same way twice, and no signal when two notes contradict each other.
It never gets smarter; it just gets bigger.

Predicate is different. It stores facts as RDF triples with per-triple
provenance and confidence, and answers questions through a deterministic
reasoner that produces an explanation path for every derived claim. And it
**learns its own shape**: the schema is versioned like code and evolves under a
propose → validate → use-gated promotion loop, so the structure your agent
relies on gets sharper the more it's used — and prunes what it doesn't.

The bet is **not** that a graph recalls facts better than a long context window —
at the scales we've measured ([`predicate-eval/SCALE-FINDINGS.md`](packages/predicate-eval/SCALE-FINDINGS.md)),
in-context recall is competitive and often simpler. The bet is that a graph makes
answers **auditable, reproducible, and contradiction-aware** in a way a flat pile
can't.

## Why it's different

- **Auditable answers.** `kg_explain` returns the chain of triples and rules
  that produced a claim — each step cited back to its source and confidence.
  Not "trust me," but "here's the derivation."
- **Contradictions surface instead of averaging out.** When two sources
  disagree about a fact the schema marks functional or disjoint, the reasoner
  flags the conflict rather than silently picking one.
- **The graph remembers, and the schema earns its keep.** Facts persist across
  sessions. New schema becomes durable only after real queries reference it
  within a TTL — unused proposals expire on their own, so the graph can't thrash.
- **Goal-conditioned growth.** Concepts enter the graph because a goal needed
  them, not because a document mentioned them.

## Install / use it in your agent

> **Prerequisite: Node 20+.** Nothing else — no Docker, no database to run.

The fastest path is the `predicate-skill` npm package, which bundles the MCP
server, the `predicate` CLI, and per-client integration adapters.

<details open>
<summary><strong>Claude Code</strong> — one-command marketplace install</summary>

```
/plugin marketplace add NordicAgents/predicate
/plugin install predicate@predicate
```

Restart Claude Code (or `/reload-plugins`), then:

```bash
predicate up        # creates the local store + the 8 named graphs
predicate doctor    # all checks green
```

Hooks, slash commands, and the `kg_*` tools are wired automatically. Slash
commands: `/predicate:up`, `/predicate:down`, `/predicate:status`,
`/predicate:ask <question>`.

> Marketplace install failing? Register Predicate as a plain MCP server
> instead — see **[Manual install](#manual-install-fallback-for-any-host)**
> below. The reasoning tools work; only automatic capture and slash commands
> are lost.

</details>

<details>
<summary><strong>Codex CLI</strong> (native plugin, capture supported)</summary>

```bash
codex plugin marketplace add NordicAgents/predicate
# then enable "predicate" in the interactive plugin browser
```

Set `[features] plugin_hooks = true` in `~/.codex/config.toml` and approve the
hooks once via `/hooks`. See `packages/predicate-skill/hooks/codex-cli/README.md`.

> Plugin install failing? Register Predicate as a plain MCP server instead —
> see **[Manual install](#manual-install-fallback-for-any-host)** below
> (reasoning tools work; no capture).

</details>

<details>
<summary><strong>VS Code Copilot</strong> / <strong>Cursor</strong> (MCP-only)</summary>

From your project root:

```bash
npx predicate-skill install vscode    # writes .vscode/mcp.json + AGENTS.md
npx predicate-skill install cursor    # writes .cursor/mcp.json + AGENTS.md
```

Restart the editor. Reasoning tools work; there is no automatic turn capture
(neither host exposes usable lifecycle hooks).

</details>

### Manual install (fallback for any host)

If a native plugin/marketplace install fails — or your host isn't listed above
(Continue.dev, OpenCode, any stdio MCP client) — run Predicate as a plain stdio
MCP server. You get all 10 `kg_*` reasoning tools on any MCP-capable host; the
only thing you lose is automatic Stop-hook capture (and, on Claude Code, the
slash commands).

```bash
npm install -g predicate-skill   # published package; ships the server + CLI
predicate up                     # create the local store + named graphs
predicate doctor                 # all checks green

# The MCP server command is (copy the resolved absolute path):
node "$(npm root -g)/predicate-skill/server.bundle.mjs"
```

No env vars are required: the server defaults to the disk-backed Oxigraph store
(`PREDICATE_BACKEND=oxigraph`, `PREDICATE_DATASET=predicate`) — identical to the
native installs. Set them only to override.

Register that command with your host:

**Claude Code**
```bash
claude mcp add predicate -- node "$(npm root -g)/predicate-skill/server.bundle.mjs"
```

**Codex CLI** — add to `~/.codex/config.toml` (use the absolute path printed by `npm root -g`):
```toml
[mcp_servers.predicate]
command = "node"
args = ["/ABSOLUTE/PATH/predicate-skill/server.bundle.mjs"]
```

**Continue.dev** — in `~/.continue/config.yaml`:
```yaml
mcpServers:
  - name: predicate
    command: node
    args: ["/ABSOLUTE/PATH/predicate-skill/server.bundle.mjs"]
```

> Full per-client matrix, the 10 MCP tools, the CLI reference, and config live in
> the package README: **[`packages/predicate-skill/README.md`](packages/predicate-skill/README.md)**.

## Architecture

```mermaid
%%{init: {
  "theme": "base",
  "themeVariables": {
    "fontSize": "15px",
    "primaryColor": "#FFD23F",
    "primaryTextColor": "#1A1A1A",
    "primaryBorderColor": "#1A1A1A",
    "lineColor": "#1A1A1A",
    "edgeLabelBackground": "#FFF7E1"
  }
}}%%
flowchart LR
  Agent["<b>your agent</b><br/>Claude Code · Codex"]:::actor
  Hook["<b>Stop hook</b><br/>turn capture"]:::actor

  subgraph Predicate["PREDICATE"]
    direction TB
    Tools["<b>10 kg_* tools</b><br/>stdio MCP"]:::iface
    Reasoner["<b>21-rule reasoner</b><br/>16 OWL 2 RL + 5 domain<br/>+ SHACL"]:::compute
    Storage["<b>Storage adapter</b><br/>Oxigraph · Fuseki"]:::data
    Graphs[("<b>8 named graphs</b><br/>tbox · tbox-staging · abox<br/>inferred · provenance · meta<br/>goals · usage")]:::store
  end

  Agent -->|MCP| Tools
  Hook  -->|assert| Tools
  Tools -->|SPARQL| Storage
  Storage <--> Graphs
  Reasoner -.->|CONSTRUCT fixpoint| Graphs
  Tools   -.-> Reasoner

  classDef actor   fill:#FFD23F,stroke:#1A1A1A,stroke-width:3px,color:#1A1A1A
  classDef iface   fill:#4ECDC4,stroke:#1A1A1A,stroke-width:3px,color:#1A1A1A
  classDef compute fill:#FF6B6B,stroke:#1A1A1A,stroke-width:3px,color:#FFFFFF
  classDef data    fill:#1A535C,stroke:#1A1A1A,stroke-width:3px,color:#FFFFFF
  classDef store   fill:#FFFFFF,stroke:#1A1A1A,stroke-width:3px,color:#1A1A1A

  style Predicate fill:#FFF7E1,stroke:#1A1A1A,stroke-width:3px,color:#1A1A1A
```

The agent reads the schema (`kg_explore_schema`), drafts SPARQL, asserts facts
with provenance (`kg_assert`), and asks questions (`kg_ask`). The reasoner does
the logic; the model formulates queries and interprets results.

### Runtime flow

```mermaid
%%{init: {
  "theme": "base",
  "themeVariables": {
    "fontSize": "14px",
    "actorBkg": "#FFD23F",
    "actorBorder": "#1A1A1A",
    "actorTextColor": "#1A1A1A",
    "actorLineColor": "#1A1A1A",
    "signalColor": "#1A1A1A",
    "signalTextColor": "#1A1A1A",
    "noteBkgColor": "#FF6B6B",
    "noteTextColor": "#FFFFFF",
    "noteBorderColor": "#1A1A1A",
    "labelBoxBkgColor": "#4ECDC4",
    "labelBoxBorderColor": "#1A1A1A",
    "labelTextColor": "#1A1A1A",
    "sequenceNumberColor": "#FFFFFF",
    "activationBkgColor": "#FFD23F",
    "activationBorderColor": "#1A1A1A"
  }
}}%%
sequenceDiagram
  participant Host as Agent host
  participant Stop as stop.sh hook
  participant Ext as turn-extractor.ts
  participant KG as kg_* tools
  participant R as Reasoner
  participant G as Named graphs

  rect rgb(255, 247, 225)
  Note over Host,G: TURN ENDS — capture
  Host->>Stop: turn payload (stdin)
  Stop->>Ext: predicate extract --from-stdin
  Ext->>KG: kg_assert (typed triples + provenance)
  KG->>G: write kg:abox + kg:provenance
  R->>G: forward-chain to fixpoint → kg:inferred
  end

  rect rgb(230, 250, 248)
  Note over Host,G: NEXT TURN — ask
  Host->>KG: kg_explore_schema / kg_ask
  KG->>G: SPARQL
  G-->>KG: results
  Host->>KG: kg_explain (why?)
  KG-->>Host: derivation path (cited triples + rules)
  end
```

> More diagrams (schema lifecycle, scale findings) live in
> [`docs/diagrams/`](docs/diagrams/README.md).

## How it works

- **Storage.** 8 named graphs separate slow-changing schema (`kg:tbox`) from
  fast-flowing facts (`kg:abox`), materialized entailments (`kg:inferred`),
  per-triple metadata (`kg:provenance`), goals (`kg:goals`), usage logs
  (`kg:usage`), staging (`kg:tbox-staging`), and version history (`kg:meta`).
- **Reasoning.** A curated set of **21 rules — 16 OWL 2 RL rules plus 5 domain
  and judgment derivations** (`Hotspot`, `FlakyCommand`, `ActiveFile`,
  current-judgment, conflict detection). The entailment rules run as SPARQL
  `CONSTRUCT` forward-chained to a fixpoint; disjointness is checked as an
  inconsistency pass; SHACL shapes add closed-world validation. The OWL 2 RL
  coverage is a scoped subset — in v1, `owl:propertyChainAxiom` is limited to
  length-2 chains and `owl:hasKey` to single-property keys.
- **Provenance.** Every triple is annotated with source, time, confidence, and
  extraction method using RDF-star. Low-confidence triples stay visible to
  queries but are excluded from the inference closure, so they cannot poison
  entailment.
- **Schema lifecycle.** The agent proposes deltas to `kg:tbox-staging`, never to
  `kg:tbox` directly. A proposal is promoted only after the reasoner accepts it
  and it has been referenced by N successful queries inside a TTL; unused
  proposals expire quietly.
- **Cross-session continuity.** A Stop hook extracts typed triples from each turn
  — files modified, commands that passed or failed — into `kg:abox`. The reasoner
  derives `Hotspot`, `FlakyCommand`, and `ActiveFile` so the next session can
  ask "what's unstable here?" without re-reading the repo.

## Packages

This is a pnpm monorepo. Each package has its own README with details.

| Package | Purpose |
|---|---|
| [`predicate-mcp`](packages/predicate-mcp/README.md) | MCP server, the 10 `kg_*` tools, and the storage adapters (Oxigraph + Fuseki). |
| [`predicate-reasoner`](packages/predicate-reasoner/README.md) | 21-rule forward-chaining reasoner + SHACL validation + inference traces for `kg_explain`. |
| [`predicate-agent`](packages/predicate-agent/README.md) | Goal store, decomposer, gap detector, schema proposer, promotion sweeper, generalizer, lifecycle controller. |
| [`predicate-cli`](packages/predicate-cli/README.md) | The `predicate` command-line interface. |
| [`predicate-ontology`](packages/predicate-ontology/README.md) | Versioned TBox catalog, SHACL shapes, meta vocabulary. |
| [`predicate-server`](packages/predicate-server/README.md) | Backend bootstrap + Fuseki/TDB2 docker-compose for the opt-in backend. |
| [`predicate-eval`](packages/predicate-eval/README.md) | End-to-end demo + multi-hop eval + ontology CI harness. |
| [`predicate-skill`](packages/predicate-skill/README.md) | The distributable npm package — bundled server + CLI + SKILL.md + per-client hooks. |

## Development

```bash
git clone https://github.com/NordicAgents/predicate
cd predicate
pnpm install
pnpm build            # builds all packages + the plugin bundle
pnpm test             # runs against the default Oxigraph backend, no Docker needed
                      # for the Fuseki leg: PREDICATE_BACKEND=fuseki + a running Fuseki
```

Other root scripts: `pnpm typecheck`, `pnpm lint`, `pnpm fuseki:up`,
`pnpm fuseki:down`.

## License

Elastic License 2.0 (ELv2) — source-available. See
[`LICENSE`](packages/predicate-skill/LICENSE).

Maintenance

ActivityInactive
ResponsivenessNo issues