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

# Knowledge Graph consolidation

> Reference for the 7 transactional Pulse MCP tools that write to the Knowledge Graph: open a session, propose nodes and edges, reconcile against existing graph state, and atomically commit. Covers content-hash dedup, agent-allowed edge types, the ADD/UPDATE/SUPERSEDE/NOOP reconciliation hints, and per-candidate overrides.

# Knowledge Graph consolidation

Consolidation is the only path that writes to a Pulse Knowledge Graph. Seven MCP tools compose into a single transactional flow:

```text theme={null}
begin → add_node_candidate* → add_edge_candidate* → propose_reconciliation → commit
                                                                          \
                                                                           → abort
```

The session is in-memory until `commit`, which atomically writes all candidates plus an audit row plus an outbox event. A content-hash check on `begin` short-circuits no-op replays. Sessions expire after 1 hour (`kg_session_ttl_seconds`).

Each primitive is gated by its own dotted-string flag in the granular permission registry: `kg.session.begin`, `kg.session.add_node`, `kg.session.add_edge`, `kg.session.get_similar`, `kg.session.propose`, `kg.session.commit`, `kg.session.abort`. The meaningful gate is `kg.session.commit` — presets sometimes grant everything except `commit` for dry-run-only roles. Cognitive agents typically receive the full set. User-facing dashboards typically receive none. See [overview](/reference/mcp/kg/overview#permissions-and-authentication) for the full preset model.

Source: `okto-pulse-core/src/okto_pulse/core/mcp/kg_tools.py:register_kg_tools`. Citations below reference `80-pulse-feature-inventory.md:503–515`.

***

## The transactional flow

### 1. `okto_pulse_kg_begin_consolidation`

Open a session for a board. Pulse computes a `content_hash` over the artifact you are consolidating (a spec, a card validation record, a decision artifact); if a previous commit produced the same hash, the call returns `nothing_changed: true` and you can skip the rest.

```text theme={null}
Input:
  board_id:       "brd_abc123"
  source_type:    "spec"
  source_id:      "spec_007"
  source_version: 4
  payload_hash:   "sha256:8c1f..."   (optional — Pulse computes if omitted)
```

```json theme={null}
Output:
{
  "session_id":      "kgs_01HV...",
  "content_hash":    "sha256:8c1f...",
  "nothing_changed": false,
  "expires_at":      "2026-05-07T16:30:00Z"
}
```

When `nothing_changed: true`, abort and exit:

```json theme={null}
{
  "session_id":      null,
  "content_hash":    "sha256:8c1f...",
  "nothing_changed": true
}
```

### 2. `okto_pulse_kg_add_node_candidate`

Add a node candidate to the open session. Stays in-memory until commit. Call once per node you want to materialize.

```text theme={null}
Input:
  session_id:  "kgs_01HV..."
  node_type:   "Decision"
  title:       "Exponential backoff with jitter for webhook retries"
  body:        "Fixed retries cause thundering-herd at peer recovery..."
  attributes:  {"confidence": 0.9, "rationale": "..."}
  source_ref:  {"spec_id": "spec_007", "section": "retry-strategy"}
```

```json theme={null}
Output:
{
  "candidate_id": "cand_001",
  "node_type":    "Decision",
  "embedding_status": "queued"
}
```

Embeddings are computed on commit, not on add. The `attributes` map is type-specific — `Decision` accepts `rationale`/`confidence`, `Constraint` accepts `severity`/`scope`, etc. Unknown keys are dropped on commit with a warning in the audit row.

### 3. `okto_pulse_kg_add_edge_candidate`

Add an edge candidate connecting two candidates (or one candidate and one existing node by `node_id`).

<Warning>
  Cognitive agents may only add 5 edge types: `supersedes`, `contradicts`, `depends_on`, `relates_to`, `validates`.

  The remaining 6 (`derives_from`, `mentions`, `violates`, `implements`, `tests`, `belongs_to`) are reserved for the Layer 1 deterministic worker. Attempts to add them via MCP return a `403 reserved_edge_type` error.
</Warning>

```text theme={null}
Input:
  session_id: "kgs_01HV..."
  src:        {"candidate_id": "cand_001"}
  dst:        {"node_id":      "dec_4c20"}     # existing node
  rel_type:   "supersedes"
  attributes: {"reason": "thundering-herd at recovery"}
```

```json theme={null}
Output:
{
  "edge_candidate_id": "edge_cand_001",
  "rel_type":          "supersedes",
  "valid":             true
}
```

### 4. `okto_pulse_kg_get_similar_nodes`

Before reconciling, ask the graph what existing nodes look like a given candidate. Used to decide whether to `UPDATE` an existing node, `SUPERSEDE` it, or add a fresh one. HNSW vector search if the candidate type has an index, else title-prefix fallback.

```text theme={null}
Input:
  session_id:   "kgs_01HV..."
  candidate_id: "cand_001"
  k:            5
```

```json theme={null}
Output:
{
  "candidate_id": "cand_001",
  "match_mode":   "hnsw",
  "matches": [
    {"node_id": "dec_4c20", "title": "Fixed 3s retry interval, 5 attempts", "score": 0.78},
    {"node_id": "dec_001",  "title": "No retry — drop on failure",          "score": 0.61}
  ]
}
```

### 5. `okto_pulse_kg_propose_reconciliation`

Compute reconciliation hints for **every candidate** in the session. The hints are advisory — `commit` will use them by default but you can override per candidate.

```text theme={null}
Input:
  session_id: "kgs_01HV..."
```

```json theme={null}
Output:
{
  "session_id": "kgs_01HV...",
  "proposals": [
    {
      "candidate_id": "cand_001",
      "hint":         "SUPERSEDE",
      "target_node":  "dec_4c20",
      "rationale":    "Same topic, newer rationale, contradicts older fixed-interval rule"
    },
    {
      "candidate_id": "cand_002",
      "hint":         "ADD",
      "rationale":    "No similar node above 0.7 threshold"
    }
  ]
}
```

Hint semantics:

| Hint        | Meaning                                                                            |
| ----------- | ---------------------------------------------------------------------------------- |
| `ADD`       | Insert as a new node.                                                              |
| `UPDATE`    | Update an existing node (`target_node`) in place. Used for refining attributes.    |
| `SUPERSEDE` | Insert as new + add `supersedes` edge to `target_node`. The old node is preserved. |
| `NOOP`      | Already present and unchanged — drop on commit.                                    |

### 6. `okto_pulse_kg_commit_consolidation`

Atomically write all candidates. Pulse runs four side-effects in one transaction:

1. Embed each new node (sentence-transformers, 384-dim).
2. Apply node and edge candidates per their hint (or per `agent_overrides`).
3. Append a row to the audit table with the full session payload + hash.
4. Emit an outbox event for downstream consumers.

```text theme={null}
Input:
  session_id: "kgs_01HV..."
  agent_overrides:                                     (optional)
    - candidate_id: "cand_001"
      hint:         "ADD"                              # override SUPERSEDE → ADD
      rationale:    "Keeping both — different scopes"
```

```json theme={null}
Output:
{
  "session_id":  "kgs_01HV...",
  "committed":   true,
  "applied": {
    "added":      [{"candidate_id": "cand_001", "node_id": "dec_8f1a"}],
    "updated":    [],
    "superseded": [],
    "noop":       []
  },
  "edges_added": [
    {"edge_id": "edge_551", "src": "dec_8f1a", "rel": "supersedes", "dst": "dec_4c20"}
  ],
  "audit_row_id": 17284,
  "outbox_event": "kg.consolidated.v1"
}
```

If commit fails (lock conflict, schema violation, embedder timeout), nothing lands and the session enters a `committable: false` state. Either retry `commit` or call `abort`.

### 7. `okto_pulse_kg_abort_consolidation`

Drop an in-flight session without writing anything. No compensating delete is needed because nothing was persisted yet.

```text theme={null}
Input:
  session_id: "kgs_01HV..."
```

```json theme={null}
Output:
{
  "session_id": "kgs_01HV...",
  "aborted":    true
}
```

Use abort when:

* `nothing_changed` is detected after `add_*` is already in flight.
* Reconciliation surfaces a contradiction the agent isn't allowed to introduce.
* Session TTL is about to expire and you can't finish the work.

***

## End-to-end example

A cognitive agent finishes a spec evaluation and wants to record the resulting `Decision` and a `supersedes` edge to the previous decision on the same topic.

```text theme={null}
1. begin_consolidation(spec_007 v4)
   → session_id, content_hash, nothing_changed=false

2. add_node_candidate(type=Decision, title="Exponential backoff...")
   → cand_001

3. get_similar_nodes(cand_001, k=5)
   → matches[0] = {dec_4c20, score=0.78}

4. add_edge_candidate(src=cand_001, dst=dec_4c20, rel=supersedes)
   → edge_cand_001

5. propose_reconciliation()
   → cand_001: SUPERSEDE → dec_4c20

6. commit_consolidation()
   → added: [dec_8f1a], edges: [supersedes dec_8f1a → dec_4c20]
```

That's the full happy path. Six tool calls. The seventh (`abort`) is only reached on the unhappy path.

***

## Idempotency and replay safety

Two layers protect the graph from duplicate writes:

1. **Content hash on `begin`.** Re-consolidating the same `(source_type, source_id, source_version)` with no actual change returns `nothing_changed: true` and never enters a session. Replays are safe.
2. **`NOOP` reconciliation hint.** Even when a session is opened, candidates whose existing nodes already match are tagged `NOOP` and skipped on commit.

The combination means an agent can safely call the consolidation flow on every spec evaluation without worrying about bloating the graph with duplicates.

***

## Permissions and audit trail

Every consolidation produces an audit row containing the session id, content hash, all candidates, all reconciliation hints, all overrides, and the agent identity from the API key. The audit row is the system-of-record — query the graph to see *what* the state is, query the audit table to see *how it got there*.

The 6 deterministic edge types (`derives_from`, `mentions`, `violates`, `implements`, `tests`, `belongs_to`) are written exclusively by the Layer 1 worker, not via MCP. This keeps cognitive agents out of structural-graph mutations and makes the deterministic skeleton machine-checkable.

***

## Common errors

| Error                    | Cause                                                                                                        | Fix                                                                                      |
| ------------------------ | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
| `403 reserved_edge_type` | Agent tried to add `derives_from` / `mentions` / `violates` / `implements` / `tests` / `belongs_to` via MCP. | Use one of the 5 cognitive edge types, or let the Layer 1 worker write the relationship. |
| `409 session_expired`    | Session exceeded `kg_session_ttl_seconds` (default 3600).                                                    | Re-open with `begin_consolidation`.                                                      |
| `409 commit_conflict`    | Another session committed first and the candidate now collides.                                              | Re-run `propose_reconciliation` and re-commit.                                           |
| `422 unknown_attribute`  | Attribute key not in the type's schema.                                                                      | Drop the unknown key, or extend the type's schema.                                       |
| `429 rate_limit`         | Too many consolidations per minute for this agent.                                                           | Back off and retry.                                                                      |

***

## Next steps

<CardGroup cols={2}>
  <Card title="Queries" href="/reference/mcp/kg/queries">
    Read tools that surface what's in the graph after consolidation.
  </Card>

  <Card title="Health & migration" href="/reference/mcp/kg/health">
    Operate the consolidation queue, dead-letter recovery, and decay tick.
  </Card>
</CardGroup>
