Skip to content
UPG is in early alpha. The specification is still evolving and may change between versions.
Tools/Nodes/query

query

Traverse the graph following typed edges. Returns a subgraph (nodes + edges) in a single call. Example: query({ from: "persona", traverse: ["persona_pursues_job", "job_surfaces_need"], depth: 2 })

Nodesatomic (read-only)

Arguments

fromstringoptional

Start from all nodes of this type

from_idstringoptional

Start from a specific node ID (alternative to from)

traversearrayoptional

Edge types to follow at each level (in order). If omitted, follows all edges. Prefix with ! to exclude (e.g. "!product_builds_feature").

depthnumberoptional

Max traversal depth (default 3, max 10)

includearrayoptional

Fields to include per node: "title", "status", "tags", "description", "properties" (default: title, status, type)

limitnumberoptional

Max nodes to return (default 200, max 1000)

edge_includearrayoptional

Edge fields to return: "id", "type", "source", "target". Empty array = no edges. Default: all fields.

property_includearrayoptional

When "properties" is in include, only return these property keys (e.g. ["severity", "importance"])

diff_fromstringoptional

Result ID from a previous query. Returns added/removed NODES, plus added/removed EDGES when `edge_include` asks for edges. Two calls that differ only by `configuration` therefore diff one configuration against another.

configurationobjectoptional

Read ONE configuration instead of the union. Maps a configuration_axis (by node id, or by title when unambiguous) to a single one of its values. Surfaces absent under that value are dropped, composition edges qualified to other values are dropped, and edges left dangling go with them. An unknown axis or value is an error, never a silent no-op. Omit to read the union, which is the default and unchanged behaviour.

Returns

Shape
{ nodes, edges, total_nodes, total_edges, _result_id, truncated?, truncated_at_depth?, diff? }

The _result_id is a cache handle for diff_from; cache holds the last 20 results.

Examples

Live call against the Notion example graph.

Input

{
  "from": "persona",
  "traverse": [
    "persona_pursues_job"
  ],
  "depth": 1,
  "limit": 5,
  "include": [
    "title"
  ],
  "edge_include": []
}

Output

{
  "nodes": [
    {
      "id": "9cd363dc-b1be-4132-b1dc-043467866e57",
      "type": "persona",
      "title": "Akira the Admin"
    },
    {
      "id": "65234b60-eb2b-4c41-be63-7b17b2bc6a38",
      "type": "persona",
      "title": "Theo the Consultant"
    },
    {
      "id": "e956a8ef-288f-4ee2-b758-2a14b9d07206",
      "type": "persona",
      "title": "Lin the Thinker"
    },
    {
      "id": "2e8dd86d-6085-4068-a804-38d3e891ea1b",
      "type": "persona",
      "title": "Maya the Maker"
    },
    {
      "id": "7b2e7c5a-a73e-42c9-9416-e9e9ccfecc20",
      "type": "job",
      "title": "Build a team system that survives growth"
    }
  ],
  "edges": [],
  "total_nodes": 5,
  "total_edges": 0,
  "truncated": true,
  "truncated_at_depth": 0,
  "hint": "Limit of 5 nodes reached at depth 0. Increase limit to see deeper results.",
  "_result_id": "qr_1"
}

Warnings

Pre-flight payload guardrail: refuses above `UPG_MCP_PAYLOAD_HARD_LIMIT` (default 150 KB), warns above `UPG_MCP_PAYLOAD_SOFT_LIMIT` (default 50 KB). Tighten with `include` (e.g. `["title"]`) or `edge_include: []` to drop edges from the wire.

See Also