/v1/api/actionsAPI keySearch the spine
Rank the project's derived cells, entities, and artifacts against a query, packed to a budget.
With a `query`, this ranks and packs. Without one it pages the raw collection — `{"input": {"kind": "cells"}}` returns one bounded page plus a `nextCursor`, and `kind: "entities"` selects the entity collection instead.
Every returned row carries its own ids, which is what lets a downstream answer cite the exact cell it rested on.
**Tether the read when you know what it should rest on.** `fileIds` and `entities` are the two ids ingestion hands back, and passing either narrows the walk to what those files and entity names back. This is how you ask a question of one uploaded drawing rather than of the whole project.
**Ask for a shape and you get one.** Pass a JSON Schema as `schema` and the response carries a `structured` object conforming to it, synthesized from the same ranked rows — which still come back beside it, so every field can be checked against what it was derived from. The natural-language `query` is still required: it decides what is retrieved, and the schema only decides how the answer is laid out over it.
Body
| Field | Type | Required | Description |
|---|---|---|---|
| action | string | required | Must be `"memory_query"`. |
| input.kind | string | optional | List mode: what to read — 'cells' (default) or 'entities'. |
| input.query | string | optional | Natural-language question or task; when present, results come ranked by relevance to it instead of as a paged dump. |
| input.budget | number | optional | Query mode: approximate token ceiling the ranked response packs to. Leave it unset unless your context is genuinely smaller than the model window — unset returns every ranked row retrieval found, bounded only by the model's own input window. |
| input.cursor | string | optional | List mode: the nextCursor from a prior dispatch, to continue the window. |
| input.fileIds | string[] | optional | Query mode: tether the answer to these ingested files — only knowledge derived from them is returned. Use the fileIds ingestion handed back. |
| input.entities | string[] | optional | Query mode: tether the answer to these entity names — each one is seeded into the spine walk alongside the entities the query itself names. Use the entity names ingestion handed back. |
| input.schema | object | optional | Query mode: a JSON Schema the answer must conform to. With it, the response carries a `structured` object matching the schema, grounded in the same retrieved rows; without it the response is the retrieved rows alone. |
curl -X POST "https://runlog-7613480744.us-central1.run.app/v1/api/actions" \
-H "Authorization: Bearer $RUNLOG_API_KEY" \
-H "X-Project-Id: p7Kd2mQx" \
-H "Content-Type: application/json" \
-d '{
"action": "memory_query",
"input": {
"budget": 4096,
"entities": [
"North Elevation"
],
"fileIds": [
"4mHqZ1nR8vTbC0sWyLpAeGkJ3dXfU6iO2rN"
],
"query": "what is the total glazed area and the floor count",
"schema": {
"properties": {
"floorCount": {
"type": "integer"
},
"glazedAreaSqFt": {
"type": "number"
}
},
"required": [
"glazedAreaSqFt",
"floorCount"
],
"type": "object"
}
}
}'{
"action": "memory_query",
"result": {
"artifacts": [
{
"artifactId": "art_5Hn2Kp",
"title": "Envelope takeoff"
}
],
"cells": [
{
"cellId": "c_7Hq2Rm",
"text": "The north elevation carries 12,480 sq ft of glazing across six occupied floors."
}
],
"entities": [
{
"entityId": "e_2Kd9Lp",
"kind": "component",
"name": "North Elevation"
}
],
"query": "what is the total glazed area and the floor count",
"structured": {
"floorCount": 6,
"glazedAreaSqFt": 12480
}
}
}Errors
| Status | error | When |
|---|---|---|
| 400 | action is required | The body named no action. |
| 400 | query is required when a schema is supplied | A schema was sent without a query. A shape alone names nothing to retrieve. |
| 403 | action not available to an API key | The key's tier does not reach this action. |
| 400 | invalid request body | The body is not JSON, or exceeds the 1 MB request-body cap. |
| 401 | invalid API key | The `Authorization` header is missing, malformed, or names a revoked key. |
| 400 | name the target project via the X-Project-Id header or projectId query | No project was named and the key is not bound to one. |
| 429 | rate limit exceeded | You passed 60 requests/minute on this key. `Retry-After` carries the seconds to wait. |
| 500 | internal error | The relay failed to serve the request. Retry with backoff; the cause is logged server-side against your request. |