Skip to main content
Version: latest

Explore relationships

Explore relationships follows the stored relations around one entity and marks each relation as stated by a passage or only connected in the graph.

Python functionexplore_relationships
Built-in agent toolexplore_relationships
MCP toolexplore_relationships
Required inputsentity_id. Python also needs store and scope.
Optional inputsdepth (default 1), relation_types, max_nodes (default 25), max_edges (default 50)
ReturnsAn ExplorationResult with nodes and edges
NeedsAn entity_id from entity search
ReadsRelations between entities, and the passages in scope that state them
API referenceagrag.evidence.explore_relationships

Overview​

Use this tool when the question asks how things connect, who or what is related to an entity, or which passage states a relation.

Each edge is one of two kinds.

  • An assertion has at least one visible passage in scope attached to the relation. The edge lists up to three of those passages as evidence ids. Fetch evidence reads them.
  • A path means two entities are connected in the graph and no passage in scope states the relation. A conclusion drawn from a path needs its own support.

An edge has source_id and target_id as stored, so the direction is the direction of the stored relation. A node has entity_id, label, name, and depth, which is the number of relations from the start entity.

Example​

The examples use the notes from Set up the example, and they reuse store, embedder, scope, and short from that page. maria_id is the entity_id of the first hit for "Maria Chen" in the entity search example, and planner_id is the entity_id of the first hit for "route planner". Outputs come from a real run.

List what Maria Chen connects to, one step out:

view = await explore_relationships(store, maria_id, scope=scope, depth=1)
names = {maria_id: "Maria Chen"} | {n.entity_id: n.name for n in view.nodes}
for edge in view.edges:
print(
f"{edge.kind.value} {names[edge.source_id]} -[{edge.relation_type}]-> "
f"{names[edge.target_id]} evidence: {[short(e.evidence_id) for e in edge.evidence]}"
)
print("truncated_by:", [bound.value for bound in view.truncated_by])
assertion Maria Chen -[AUTHORED]-> Orion Planner evidence: ['ev1:c:f24b301d...3e66aa77']
assertion Maria Chen -[WORKS_FOR]-> Acme Robotics evidence: ['ev1:c:f24b301d...3e66aa77']
truncated_by: []

Both edges are assertions, and the passage ...3e66aa77 states both. Fetch that id to read the sentence "Maria Chen works for Acme Robotics and wrote the Orion Planner."

See which bound cut a walk​

truncated_by names every bound that cut a walk. These three calls show how a walk is cut and how to narrow it. The first starts at the planner and goes one step, the second follows only AUTHORED relations, and the third allows one edge:

view = await explore_relationships(store, planner_id, scope=scope, depth=1)
print([(n.name, n.depth) for n in view.nodes], [b.value for b in view.truncated_by])

view = await explore_relationships(
store, maria_id, scope=scope, depth=1, relation_types=["AUTHORED"]
)
print([e.relation_type for e in view.edges], [b.value for b in view.truncated_by])

view = await explore_relationships(store, maria_id, scope=scope, depth=1, max_edges=1)
print(len(view.edges), [b.value for b in view.truncated_by])
[('Maria Chen', 1)] ['depth']
['AUTHORED'] []
1 ['edges']

The first call reaches Maria Chen and stops with depth, because she has more connections that a one-step walk does not follow. Raise depth to 2 to follow them. The second call narrows the walk with relation_types, and nothing is cut. The third call stops with edges, because the entity has more edges than max_edges allows.

Usage​

In Python​

Call explore_relationships as in the example above. Python needs the connected store, the entity_id, and the scope.

In the built-in agent​

The agent calls explore_relationships on its own after entity_search returns an entity. The agent version caps depth at 2 and the node and edge limits at 200.

On the MCP server​

An MCP client calls explore_relationships with an entity_id from an entity_search hit.

{"entity_id": "a0083936-0bf3-5836-9ebf-95cf350434ec", "depth": 1, "relation_types": ["AUTHORED"]}

The parameter ranges and the MCP caps are in the relationship exploration parameters.

Result​

Bound in truncated_byMeaning
nodesMore entities were reached than max_nodes allows.
edgesMore edges existed than max_edges allows.
depthEntities at the last depth have further connections that were not followed.
candidatesMore relations existed than the per-step read limit.
StatusMeaning
okThe walk ran. The result may hold no edges.
unavailableThe start entity is missing, or no passage of it is in scope. Both cases give the same status.
malformedentity_id is not a canonical UUID string.
failedThe store failed during the walk.

A call with an id that is not a UUID returns malformed and the detail not an entity id.

Full JSON of the one-step walk from Maria Chen

This is view.model_dump_json(indent=2) for the first example.

{
"status": "ok",
"nodes": [
{
"entity_id": "adaafece-3687-5c94-800c-cd95c34c3eda",
"label": "Organization",
"name": "Acme Robotics",
"depth": 1
},
{
"entity_id": "e1dca08d-5569-57b4-be51-638d800f4b79",
"label": "Software",
"name": "Orion Planner",
"depth": 1
}
],
"edges": [
{
"source_id": "a0083936-0bf3-5836-9ebf-95cf350434ec",
"target_id": "adaafece-3687-5c94-800c-cd95c34c3eda",
"relation_type": "WORKS_FOR",
"kind": "assertion",
"evidence": [
{
"evidence_id": "ev1:c:f24b301d-f73a-5291-9d80-7ea3cbd5291c:c174f9d9eba7d79c:440441fc-6865-5391-8e02-a44c3e66aa77",
"document_key": "/home/you/acme-notes.md",
"location": { "char_start": null, "char_end": null, "page_numbers": [] }
}
]
},
{
"source_id": "a0083936-0bf3-5836-9ebf-95cf350434ec",
"target_id": "e1dca08d-5569-57b4-be51-638d800f4b79",
"relation_type": "AUTHORED",
"kind": "assertion",
"evidence": [
{
"evidence_id": "ev1:c:f24b301d-f73a-5291-9d80-7ea3cbd5291c:c174f9d9eba7d79c:440441fc-6865-5391-8e02-a44c3e66aa77",
"document_key": "/home/you/acme-notes.md",
"location": { "char_start": null, "char_end": null, "page_numbers": [] }
}
]
}
],
"truncated": false,
"truncated_by": [],
"detail": null
}