> ## 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 queries

> Reference for the 14 read-only Pulse MCP tools that query the Knowledge Graph: 9 typed primary tools (decision history, related context, contradictions, supersedence, alternatives, learning, global) plus 5 power tools (Cypher, natural language, schema, grounding, reflective).

# Knowledge Graph queries

Pulse exposes **14 read-only KG tools**:

* **9 primary query tools** — typed, opinionated answers to the questions agents ask most often.
* **5 power tools** — escape hatches for arbitrary Cypher, natural-language search, schema introspection, grounding verification, and a reflective retrieve-critic stub.

Permissions are dotted-string flags in the granular registry (`okto-pulse-core/src/okto_pulse/core/infra/permissions.py:PERMISSION_REGISTRY`):

* The 9 primary tools sit under `kg.query.*` — granted as a wildcard or per-tool (`kg.query.decision_history`, `kg.query.global`, …).
* The 5 power tools split across `kg.power.natural`, `kg.power.schema_info`, `kg.power.cypher`. `kg.power.cypher` is the most restricted and is typically excluded from default presets.
* `kg.power.cypher` and the natural-language tool also write to the per-node hit counter that feeds `relevance_score` over time — every read result you take from these tools is logged.

None of these tools write graph data. None of them call an LLM at runtime — every primary tool is a deterministic combination of HNSW vector search and graph traversal. (`kg_query_reflective` is the sole exception and is a V1 stub.)

For the schema (11 node types, 10 rel types + `belongs_to`, 5 HNSW indexes) and tool inventory, see [overview](/reference/mcp/kg/overview).

***

## Primary query tools (9)

Source: `okto-pulse-core/src/okto_pulse/core/mcp/kg_query_tools.py:register_kg_query_tools`. Citations below reference `80-pulse-feature-inventory.md:519–531`.

### `okto_pulse_kg_get_decision_history`

Trace decisions about a topic over time. Hybrid HNSW + title-CONTAINS search, results ordered chronologically with supersedence chain summaries.

```text theme={null}
Input:
  board_id:  "brd_abc123"
  topic:     "retry strategy for webhook delivery"
  limit:     20
  since:     "2026-01-01T00:00:00Z"   (optional)
```

```json theme={null}
Output:
{
  "topic": "retry strategy for webhook delivery",
  "match_mode": "hybrid",
  "results": [
    {
      "node_id": "dec_8f1a",
      "title": "Exponential backoff with jitter for webhook retries",
      "type": "Decision",
      "created_at": "2026-02-14T10:22:11Z",
      "rationale": "Fixed retries cause thundering-herd at peer recovery...",
      "superseded_by": null,
      "score": 0.83
    },
    {
      "node_id": "dec_4c20",
      "title": "Fixed 3s retry interval, 5 attempts",
      "type": "Decision",
      "created_at": "2025-11-08T18:05:00Z",
      "superseded_by": "dec_8f1a",
      "score": 0.71
    }
  ]
}
```

### `okto_pulse_kg_get_related_context`

2-hop neighborhood traversal around a single node. Supports edge type filter, direction filter, max depth (default 2, cap 4).

```text theme={null}
Input:
  board_id:    "brd_abc123"
  node_id:     "dec_8f1a"
  edge_types:  ["supersedes", "depends_on", "violates"]   (optional)
  direction:   "both"                                     ("in" | "out" | "both")
  max_depth:   2
```

```json theme={null}
Output:
{
  "anchor": {"node_id": "dec_8f1a", "title": "Exponential backoff..."},
  "nodes": [
    {"node_id": "con_2e", "type": "Constraint", "title": "Webhook receivers must respond within 30s"},
    {"node_id": "dec_4c20", "type": "Decision", "title": "Fixed 3s retry interval, 5 attempts"}
  ],
  "edges": [
    {"src": "dec_8f1a", "rel": "depends_on", "dst": "con_2e"},
    {"src": "dec_8f1a", "rel": "supersedes", "dst": "dec_4c20"}
  ]
}
```

### `okto_pulse_kg_get_supersedence_chain`

Walk the `supersedes` chain for a decision (max depth 10). Returns nodes in newest-to-oldest order.

```text theme={null}
Input:
  board_id:  "brd_abc123"
  node_id:   "dec_8f1a"
  max_depth: 10
```

```json theme={null}
Output:
{
  "head": "dec_8f1a",
  "chain": [
    {"node_id": "dec_8f1a", "title": "Exponential backoff with jitter", "created_at": "2026-02-14T10:22:11Z"},
    {"node_id": "dec_4c20", "title": "Fixed 3s retry interval, 5 attempts", "created_at": "2025-11-08T18:05:00Z"},
    {"node_id": "dec_001", "title": "No retry — drop on failure", "created_at": "2025-09-02T09:11:30Z"}
  ],
  "depth": 3
}
```

### `okto_pulse_kg_find_contradictions`

Find `contradicts` edges. With no `node_id`, returns all contradiction pairs on the board. With `node_id`, returns the pairs anchored at that node.

```text theme={null}
Input:
  board_id: "brd_abc123"
  node_id:  "dec_8f1a"   (optional)
```

```json theme={null}
Output:
{
  "anchor": "dec_8f1a",
  "pairs": [
    {
      "left":  {"node_id": "dec_8f1a", "title": "Exponential backoff..."},
      "right": {"node_id": "con_99",   "title": "Webhook payloads must arrive in order"},
      "edge_id": "edge_771",
      "created_at": "2026-02-14T10:23:02Z"
    }
  ]
}
```

### `okto_pulse_kg_find_similar_decisions`

Hybrid ranked similarity. The reranking formula is fixed in `kg_service.py:244`:

```text theme={null}
score = 0.5 × semantic + 0.2 × graph_centrality + 0.2 × recency_decay + 0.1 × confidence
```

This is the **search reranking** score, not the persisted `relevance_score` on each node — do not conflate the two (`80-pulse-feature-inventory.md:957`).

```text theme={null}
Input:
  board_id: "brd_abc123"
  query:    "How should we handle out-of-order events from the queue?"
  limit:    5
```

```json theme={null}
Output:
{
  "results": [
    {
      "node_id": "dec_5b2",
      "title": "Sequence-number gating for queue consumers",
      "score": 0.78,
      "components": {"semantic": 0.81, "graph_centrality": 0.66, "recency": 0.92, "confidence": 0.80}
    }
  ]
}
```

### `okto_pulse_kg_explain_constraint`

Returns the origin spec/decision for a `Constraint` node, related constraints, and any `Bug` nodes that record violations of it.

```text theme={null}
Input:
  board_id: "brd_abc123"
  node_id:  "con_2e"
```

```json theme={null}
Output:
{
  "constraint": {"node_id": "con_2e", "title": "Webhook receivers must respond within 30s"},
  "origin": {"type": "spec", "id": "spec_007", "title": "Webhook delivery v2"},
  "related_constraints": [
    {"node_id": "con_2f", "title": "Retries must use exponential backoff"}
  ],
  "violations": [
    {"node_id": "bug_4411", "title": "Slow consumer caused 30s+ retries", "resolved_at": "2026-03-01"}
  ]
}
```

### `okto_pulse_kg_list_alternatives`

For a `Decision`, return the `Alternative` nodes that were considered and discarded, with the recorded `reason_discarded`.

```text theme={null}
Input:
  board_id: "brd_abc123"
  node_id:  "dec_8f1a"
```

```json theme={null}
Output:
{
  "decision": "dec_8f1a",
  "alternatives": [
    {
      "node_id": "alt_22",
      "title": "Token-bucket rate limit instead of backoff",
      "reason_discarded": "Adds complex per-tenant accounting; backoff is sufficient for current volume."
    }
  ]
}
```

### `okto_pulse_kg_get_learning_from_bugs`

Trace `Learning` nodes derived from bugs in an area, via `Learning → Bug` `validates` edges.

```text theme={null}
Input:
  board_id: "brd_abc123"
  area:     "webhook delivery"
  limit:    10
```

```json theme={null}
Output:
{
  "results": [
    {
      "learning": {"node_id": "lrn_18", "title": "Always log raw delivery latency, not retry-counter"},
      "bug": {"node_id": "bug_4411", "title": "Slow consumer caused 30s+ retries"},
      "captured_at": "2026-03-02T11:00:00Z"
    }
  ]
}
```

### `okto_pulse_kg_query_global`

Cross-board semantic search via the global discovery layer (`~/.okto-pulse/global/discovery.lbug`). ACL-filtered: only returns nodes from boards the calling agent's API key can read.

```text theme={null}
Input:
  query: "What did we decide about retry strategies?"
  limit: 20
```

```json theme={null}
Output:
{
  "results": [
    {"board_id": "brd_abc123", "node_id": "dec_8f1a", "title": "Exponential backoff...", "score": 0.81},
    {"board_id": "brd_other",  "node_id": "dec_5b2",  "title": "Sequence-number gating...", "score": 0.74}
  ],
  "boards_searched": 4
}
```

***

## Power tools (5)

Source: `okto-pulse-core/src/okto_pulse/core/mcp/kg_power_tools.py:register_kg_power_tools`. Citations: `80-pulse-feature-inventory.md:535–543`.

These are escape hatches. Reach for them when the typed primary tools don't cover the question, when you need full schema introspection, or when you need to verify an answer is grounded in actual graph data.

### `okto_pulse_kg_query_cypher`

Read-only Cypher against the board graph. Safety rails:

* Write keywords (`CREATE`, `DELETE`, `MERGE`, `SET`, `REMOVE`) are rejected by whitelist.
* `LIMIT` is auto-injected if the query lacks one.
* Variable-length paths bounded to `*..20`.
* 30-second timeout.
* 30 requests / minute / agent rate limit.

```text theme={null}
Input:
  board_id: "brd_abc123"
  cypher:   "MATCH (d:Decision)-[:supersedes]->(o:Decision) RETURN d.title, o.title"
  params:   {}
```

```json theme={null}
Output:
{
  "columns": ["d.title", "o.title"],
  "rows": [
    ["Exponential backoff with jitter", "Fixed 3s retry interval, 5 attempts"],
    ["Fixed 3s retry interval, 5 attempts", "No retry — drop on failure"]
  ],
  "row_count": 2,
  "elapsed_ms": 18
}
```

<Warning>
  `kg_query_cypher` is the broadest read tool — but the typed primary tools above are faster and safer for the common patterns. Reach for Cypher only when the typed tools genuinely don't fit.
</Warning>

### `okto_pulse_kg_query_natural`

Plain-English question against the graph. Hybrid embedding + HNSW + 1-hop traversal expansion. No LLM — deterministic.

```text theme={null}
Input:
  board_id: "brd_abc123"
  query:    "Why did we move away from fixed retry intervals?"
  since:    "2025-01-01T00:00:00Z"   (optional)
  until:    null
  limit:    10
```

```json theme={null}
Output:
{
  "answer_nodes": [
    {"node_id": "dec_8f1a", "title": "Exponential backoff with jitter", "snippet": "Fixed retries cause thundering-herd...", "score": 0.84}
  ],
  "supporting_edges": [
    {"src": "dec_8f1a", "rel": "supersedes", "dst": "dec_4c20"}
  ]
}
```

### `okto_pulse_kg_schema_info`

Schema introspection. Use this to assert the live schema version before issuing version-specific Cypher, or to discover new node/edge types after an upgrade.

```text theme={null}
Input:
  board_id: "brd_abc123"
```

```json theme={null}
Output:
{
  "schema_version": "0.3.3",
  "node_types": ["Decision", "Criterion", "Constraint", "Assumption", "Requirement",
                 "Entity", "APIContract", "TestScenario", "Bug", "Learning", "Alternative"],
  "rel_types":  ["supersedes", "contradicts", "derives_from", "relates_to", "mentions",
                 "depends_on", "violates", "implements", "tests", "validates", "belongs_to"],
  "vector_indexes": [
    {"node_type": "Decision",    "dim": 384, "metric": "cosine", "model": "sentence-transformers/all-MiniLM-L6-v2"},
    {"node_type": "Constraint",  "dim": 384, "metric": "cosine"},
    {"node_type": "Requirement", "dim": 384, "metric": "cosine"},
    {"node_type": "Entity",      "dim": 384, "metric": "cosine"},
    {"node_type": "Learning",    "dim": 384, "metric": "cosine"}
  ]
}
```

### `okto_pulse_kg_verify_grounding`

Verify that an agent-generated answer is actually backed by retrieved KG nodes. V1: deterministic entity check + Jaccard fallback at 0.7 threshold.

```text theme={null}
Input:
  board_id:        "brd_abc123"
  answer_text:     "We use exponential backoff with jitter to avoid thundering-herd retries."
  retrieved_nodes: ["dec_8f1a", "con_99"]
```

```json theme={null}
Output:
{
  "grounded": true,
  "score": 0.82,
  "matched_entities": ["exponential backoff", "jitter", "retries"],
  "unmatched_phrases": []
}
```

### `okto_pulse_kg_query_reflective`

V1 stub of the reflective retrieve-critic loop. Returns a single retrieve+critic pass. The full multi-step loop requires an LLM callable wired through the Python API — this MCP variant is intentionally a thin stub.

```text theme={null}
Input:
  board_id: "brd_abc123"
  query:    "What constraints apply to webhook retries?"
```

```json theme={null}
Output:
{
  "stub": true,
  "candidates": [
    {"node_id": "con_2e", "title": "Webhook receivers must respond within 30s", "score": 0.79}
  ],
  "critic_notes": "Single-pass retrieval. For multi-step reflection, use the Python API."
}
```

***

## Choosing a tool

| You want…                                        | Use                         |
| ------------------------------------------------ | --------------------------- |
| Decisions about a topic, ordered in time         | `kg_get_decision_history`   |
| Everything within 2 hops of a node               | `kg_get_related_context`    |
| The full supersedes chain back to the root       | `kg_get_supersedence_chain` |
| Pairs of nodes that contradict each other        | `kg_find_contradictions`    |
| Top-N decisions by hybrid similarity score       | `kg_find_similar_decisions` |
| The origin and downstream impact of a constraint | `kg_explain_constraint`     |
| Why an alternative was rejected                  | `kg_list_alternatives`      |
| Lessons from past bugs in an area                | `kg_get_learning_from_bugs` |
| Cross-board semantic search                      | `kg_query_global`           |
| An arbitrary read query                          | `kg_query_cypher`           |
| Plain-English question against this board        | `kg_query_natural`          |
| The live schema                                  | `kg_schema_info`            |
| Verify an answer is grounded in graph data       | `kg_verify_grounding`       |
| One-shot reflective retrieve                     | `kg_query_reflective`       |

***

## Determinism note

Every primary query and every power tool except `kg_query_reflective` is deterministic over a fixed graph state. Same `board_id` + same input + same `graph.lbug` snapshot = same output. This is what makes the KG safe to depend on for long-horizon agent decisions.

***

## Next steps

<CardGroup cols={2}>
  <Card title="Consolidation" href="/reference/mcp/kg/consolidation">
    Write nodes and edges into the graph through transactional sessions.
  </Card>

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