Relation graph¶
The optional graph_* tools record typed relationships between entities. It is useful for
questions about connections — for example, who works on a project, which technology it uses,
or what a task depends on — where a normal note or a retrieved document may not contain the
complete answer in one place.
It is not a replacement for the Agent Tools memory_* tools. Store notes, dates, amounts, and
facts about one entity in memory. Store only relationships with the graph. The model receives
instructions to keep the same fact out of both stores.
For memories and relationships in one store with semantic recall, see the graphmem MCP server in Suggested MCP Servers.
Enable it¶
The graph is a built-in extension, but is deliberately opt-in. Install MiniBot with the graph
extra, then enable its extension in config.toml:
poetry install --extras graph
[extensions]
modules = ["minibot.extensions.tools.graph"]
[extensions.config."minibot.extensions.tools.graph"]
sqlite_url = "sqlite+aiosqlite:///./data/graph.db"
sqlite_url is optional; it defaults to sqlite+aiosqlite:///./data/graph.db. Set
echo = true in the extension configuration only when SQLAlchemy query logging is useful for
debugging. As with every extension, MiniBot stops at startup if it cannot import or register it.
Configuring it as an extension, rather than bundling it, also makes the tools available to spawned task workers.
Data model and scope¶
Each graph edge has a source node, relation, target node, optional attributes, and validity dates.
The store is scoped to the current owner and graph namespace, so one user’s edges cannot appear in
another user’s result. The namespace defaults to memory; use another graph value only for
a genuinely separate domain, not to split one user’s personal graph.
Nodes are typed identifiers in type:id form, such as person:alex,
project:website, or tech:python. Prefer lowercase ASCII identifiers with underscores between
words. Node and relation identifiers are normalized when written, but callers should search first
and reuse an existing identifier rather than introduce a near-duplicate. Relations are lowercase
verb phrases read from source to target, such as works_on, uses, depends_on, or
prefers.
Operations¶
The graph is exposed as one tool per operation, so a pattern such as graph_* covers all of
them in tools_allow, tools_deny or require_approval. The old graph name is rejected
there at config load.
graph_linkCreate or update a live edge. Requires
source,rel, andtarget. An optionalattrsvalue is a JSON object string with additional edge fields. Repeating the same triple updates it instead of creating a duplicate.graph_unlinkClose a live edge that is no longer true. Requires
source,rel, andtarget. The edge is retained as history rather than deleted.graph_mergeMerge a duplicate node into its canonical identifier.
sourceis the incorrect identifier;targetis the identifier to retain. All edges mentioning the source are rewritten.graph_neighborsExpand relationships around
node.directionmay beout(the default),in, orboth;depthdefaults to 1 and is capped at 5.relfilters traversal to one relation.limitdefaults to 50,max_nodesdefaults to 100, andhistory = trueadds closed edges. A response withtruncated = truereached the node limit.graph_pathFind the shortest connection between
sourceandtarget. It follows relationships in either direction, so a useful connection can be found even if no edge points directly from the source to the target.max_depthdefaults to 4 and is capped at 8.graph_searchFind edges and node identifiers from a text fragment matched against source, relation, and target. It requires
queryand defaults to 25 results. Use it before adding or traversing an entity when its canonical identifier is unknown.
Every tool accepts the optional graph namespace. graph_neighbors and graph_search can include
closed edges with history = true. Edges with valid_to are historical: present them as past
relationships, never current ones.
Examples¶
Record that Alex works on a website project with graph_link:
{
"source": "person:alex",
"rel": "works_on",
"target": "project:website"
}
Find everything connected to the website project within two hops with graph_neighbors:
{
"node": "project:website",
"direction": "both",
"depth": 2
}
Explain the connection between a person and a technology with graph_path:
{
"source": "person:alex",
"target": "tech:python"
}
When a relationship changes, close the old edge with graph_unlink and create the replacement
with graph_link in the same turn. This preserves when the superseded relationship stopped
being current.