spatial_query
Run geometric queries against the current game state.
spatial_query answers spatial relationship questions that would require math to answer from a snapshot. Instead of giving you all positions and asking you to compute distances, it computes them and returns sorted, filtered results.
When to use it
- "What is near X?" — radius search
- "What is closest to X?" — nearest search
- "What is in this area?" — area/bounding-box search
- "Does a ray from A hit B?" — raycast
- "How far is it to walk from A to B?" — path distance
- "What is the relationship between A and B?" — relationship
Query types
nearest
Find the closest nodes to a point or node.
{
"query_type": "nearest",
"from": "Player",
"k": 5,
"class_filter": ["CharacterBody3D", "Area3D"]
}from can be a node name/path or a [x, y, z] coordinate.
Response:
{
"result": {
"origin": [2.3, 0.0, -1.7],
"results": [
{ "node": "Enemy_0", "class": "CharacterBody3D", "global_position": [-1.5, 0.0, 4.2], "distance": 6.4 },
{ "node": "Pickup_0", "class": "Area3D", "global_position": [3.0, 0.5, -1.0], "distance": 1.3 },
{ "node": "Enemy_1", "class": "CharacterBody3D", "global_position": [7.0, 0.0, -2.0], "distance": 4.7 }
]
}
}Results are sorted by distance ascending.
radius
Find all nodes within a distance of a point.
{
"query_type": "radius",
"from": "Player",
"radius": 10.0,
"class_filter": ["CollectibleItem", "Enemy"]
}Response:
{
"result": {
"origin": [2.3, 0.0, -1.7],
"radius": 10.0,
"results": [
{ "node": "Pickup_0", "class": "Area3D", "global_position": [3.0, 0.5, -1.0], "distance": 1.3 },
{ "node": "Enemy_1", "class": "CharacterBody3D", "global_position": [7.0, 0.0, -2.0], "distance": 4.7 }
]
}
}area
Find nodes inside an axis-aligned bounding box.
{
"query_type": "area",
"min": [-5.0, -1.0, -5.0],
"max": [5.0, 3.0, 5.0]
}Response:
{
"result": {
"bounds": { "min": [-5, -1, -5], "max": [5, 3, 5] },
"results": [
{ "node": "Player", "class": "CharacterBody3D", "global_position": [2.3, 0.0, -1.7] },
{ "node": "Enemy_0", "class": "CharacterBody3D", "global_position": [-3.1, 0.0, 4.2] }
]
}
}Note: area results do not include distance — there is no single reference point.
raycast
Cast a ray from from in direction and report what it hits.
{
"query_type": "raycast",
"from": "Player",
"direction": [0.0, 0.0, -1.0],
"max_distance": 20.0,
"collision_mask": 3
}Response:
{
"result": {
"hit": true,
"node": "Wall_North",
"class": "StaticBody3D",
"global_position": [2.3, 0.0, -8.0],
"normal": [0.0, 0.0, 1.0],
"distance": 6.3
}
}If no hit: { "result": { "hit": false } }
The raycast is computed by querying the last known physics state — it uses the positions from the most recent collected frame, not a live physics query. For a live physics raycast, use spatial_action to call a method that performs PhysicsDirectSpaceState3D.intersect_ray.
path_distance
Calculate the navigation mesh path distance between two points or nodes.
{
"query_type": "path_distance",
"from": "Player",
"to": "Enemy_0"
}Response:
{
"result": {
"from": [2.3, 0.0, -1.7],
"to": [-3.1, 0.0, 4.2],
"distance": 9.8,
"reachable": true,
"waypoints": [
[2.3, 0.0, -1.7],
[0.5, 0.0, 1.0],
[-3.1, 0.0, 4.2]
]
}
}reachable: false means the navigation mesh has no path — the nodes are in disconnected regions. This is a very useful diagnostic for navmesh bugs.
relationship
Describe the spatial relationship between two specific nodes.
{
"query_type": "relationship",
"from": "Player",
"to": "Enemy_0"
}Response:
{
"result": {
"from": "Player",
"to": "Enemy_0",
"distance": 6.4,
"bearing_deg": 142.3,
"relative": [-5.4, 0.0, 6.0],
"occluded": false,
"in_fov": true
}
}| Field | Description |
|---|---|
distance | Euclidean distance in world units |
bearing_deg | Horizontal angle from from to to, relative to from's forward vector |
relative | [x, y, z] offset from from to to in from's local space |
occluded | true if there is a StaticBody3D or CSGShape3D between them (line-of-sight check) |
in_fov | true if to is within from's frustum (for Camera3D from) |
All parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
class_filter | string[] | optional | Filter by node class. |
from | any | required | Origin: node path (string) or position array [x,y,z] |
groups | string[] | optional | Filter by group membership. |
k | number | optional default: 5 | For nearest: number of results. |
query_type | any"nearest" | "radius" | "area" | "raycast" | "path_distance" | "relationship" | required | Query type: nearest, radius, area, raycast, path_distance, relationship. |
radius | number | optional default: 20 | For radius/area: search radius. |
to | any | optional | Target: node path (string) or position array [x,y,z] |
token_budget | number | optional | Token budget for the response. |
Example conversation
Tips
Use path_distance to debug navmesh reachability. If reachable: false, the navmesh is disconnected. If the distance is much longer than the straight-line distance, there may be unnecessary obstacles or the navmesh has a gap.
Use relationship for line-of-sight bugs. The occluded field tells you whether geometry blocks the path between two nodes — useful for AI perception debugging.
nearest with k: 1 is the fastest way to find "the closest thing." Use it instead of sorting a radius result yourself.
area is useful for zone-based queries. "What nodes are in room B?" Define room B's bounding box and query the area.