| name | graph-debug |
| description | How to inspect, render, and reason about the shared knowledge GRAPH —
for the facts-manager (report graph size/health, render the graph as
Markdown/Mermaid, spot orphan or duplicate entities) and for the
agent-manager (forensics: what graph search a session ran and what it
returned). Read this before answering any question about graph
structure, graph contents, or a session's graph-search behaviour.
Only relevant when a knowledge graph is configured; if the graph tools
are absent, this deployment has no graph and the skill does not apply.
|
Graph Debug
A shared knowledge graph of entities (GraphNode) and relationships
(edges) sits alongside the facts store. It is separate from the facts
KV/search store: facts are evidence; the graph is the distilled entity/edge
model a harvester extracts from that evidence. This skill is how you inspect
and explain it.
The graph is optional. If you do not have graph_search_nodes /
graph_neighbourhood / graph_stats in your tool set, this deployment runs
without a graph and nothing here applies — say so plainly instead of guessing.
Tools you have (by role)
| Tool | facts-manager | agent-manager | Purpose |
|---|
graph_search_nodes | ✓ | ✓ | Find entities by name / kind / seed scope-keys |
graph_search_edges | ✓ | ✓ | Find relationships by predicate / endpoints |
graph_neighbourhood | ✓ | ✓ | Bounded subgraph around one node (1–5 hops) |
graph_list_namespaces | ✓ | ✓ | Discover registered graph corpora from compact frontmatter |
graph_get_namespace | ✓ | ✓ | Read full descriptor for one namespace/corpus |
graph_stats | ✓ | ✓ | Node + edge counts and crawl backlog (read-only) |
read_session_retrieval_usage | ✓ | ✓ | Count-only fact/skill/graph retrieval usage for a session |
read_session_tree_retrieval_usage | ✓ | ✓ | Count-only retrieval usage rolled up across a spawn tree |
read_session_graph_node_usage | ✓ | ✓ | Exact graph node keys searched or loaded by a session |
read_session_graph_edge_search_usage | ✓ | ✓ | Edge-search shapes grouped by predicate key and endpoints |
read_session_graph_searches | — | ✓ | Forensics: what graph searches a session ran |
The read_session_*_retrieval_usage tools are lineage-gated for non-tuner
sessions: facts-manager can inspect itself and descendant sessions, while
agent-manager can inspect any session. Neither role mutates the graph through this skill. The facts-manager holds
the graph write/delete tools (dormant), plus namespace registry mutation tools
for explicit operator actions, but graph building is a harvester job — do
not crawl, upsert, archive, or delete here unless an operator explicitly asks.
Namespace discovery
If graph_list_namespaces is available, use it before graph traversal when the
question may be corpus/domain-specific. The compact frontmatter tells you what a
namespace contains and when it is relevant. Call graph_get_namespace only for a
namespace that looks relevant and needs details such as source or schema shape.
The reserved default namespace is the unscoped graph partition. Other
namespaces are corpus/domain keys such as corpus/acme; graph namespace filters
match that namespace and descendants such as corpus/acme/services. Use the
same namespace across graph tools and facts tools when you pivot between source
facts and graph structure.
Reporting on the graph (facts-manager)
When asked "how big is the graph", "is the graph healthy", or "what's in the
graph":
- Start with
graph_stats — it returns node count, edge count, and how many
facts remain uncrawled (the harvest backlog). A large uncrawled backlog
with few nodes means harvesting is behind, not that the graph is broken.
- If namespaces are present, list them first and choose the relevant corpus
rather than sampling the whole graph blindly.
- Sample structure with
graph_search_nodes (e.g. by kind) and expand a
few with graph_neighbourhood to characterise connectivity.
- Do not fan out a neighbourhood call per node to "count" the graph —
graph_stats already has the counts. Fanning out is a self-inflicted DoS.
Rendering the graph as Markdown / Mermaid
To render a region as a diagram an operator can read, pull a bounded
neighbourhood and emit a Mermaid graph block. Keep it bounded (one seed,
depth ≤ 2, or a single kind) — never try to render the whole graph at once.
graph LR
n_alvaro["Álvaro Herrera (person)"]
n_pg["PostgreSQL (project)"]
n_alvaro -->|contributes_to| n_pg
Label nodes with name (kind) and edges with the predicate. If the region is
large, render the top entities by degree and say you truncated.
Graph-search forensics (agent-manager)
When investigating "why did session X not find what it expected in the graph",
or "what did this agent actually search for":
- Start with
read_session_retrieval_usage({ session_id }). It returns
count-only aggregates for facts_search, facts_similar, search_skills,
graph_search_nodes, graph_search_edges, and graph_neighbourhood, grouped
by namespace with result counts and durations. It does not store returned
facts, nodes, or edges.
- If the question is about a specific graph anchor, call
read_session_graph_node_usage({ session_id, node_key_like?, kind? }) to see
exact node keys that were searched as seeds (kind="searched") or loaded as
neighbourhood anchors (kind="loaded").
- If the question is about relationships, call
read_session_graph_edge_search_usage({ session_id }) and inspect the
predicateKey, fromKey, toKey, namespace, call count, and result count.
- Use
read_session_graph_searches({ session_id }) only when you need the raw
timeline. Each row is a durable graph.searched event with operation
(graph_search_nodes, graph_search_edges, or graph_neighbourhood),
namespace, bounded query preview, and result counts.
- Compare the query to what you'd expect. A zero-result
graph_search_nodes
with an over-specific nameLike is a prompt problem, not a graph problem.
- Cross-check visibility: graph reads honour the same lineage/ACL as
read_facts. A session only sees nodes its accessible facts evidence.
If a session got zero results but the entity exists, confirm whether that
session's lineage actually has evidence linking to it before blaming the
graph.
- For semantic investigations ("find sessions similar to this failure"), use
facts_search (semantic / hybrid) and facts_similar — then pivot into the
graph with graph_search_nodes({ seeds: [<scopeKey>] }).
Common pitfalls
- Confusing "no graph" with "empty graph". No graph tools ⇒ no graph
configured. Tools present but
graph_stats reports zero nodes ⇒ a real but
empty/un-harvested graph. These are different findings — report which.
- Treating the graph as authoritative over facts. Facts are the evidence
of record; the graph is a derived view. A graph node with no accessible
evidencing fact is invisible to a reader by design, not a bug.
- Rendering unbounded. Always bound the region you visualise.