Saved Queries

What are saved queries?

Saved queries let you store a CAL recipe once and execute it by name. Instead of regenerating complex RECALL or ASSEMBLE pipelines on every call, define the query once with DEFINE QUERY and invoke it with RUN.

DEFINE QUERY "user_prefs"($user, $limit = 10) AS {
  RECALL beliefs WHERE subject = $user AND relation = "likes" RECENT $limit
}

RUN "user_prefs"($user = "john")
POST /api/memories/default/cal
Content-Type: text/cal

DEFINE QUERY "user_prefs"($user, $limit = 10) AS { RECALL beliefs WHERE subject = $user AND relation = "likes" RECENT $limit }

Saved queries persist across server restarts. They are scoped to the memory (database) where they are defined.

How do I define a saved query?

Use DEFINE QUERY with a name, optional parameters, and a body containing any read-tier CAL statement.

-- No parameters
DEFINE QUERY "recent_beliefs" AS {
  RECALL beliefs RECENT 10
}

-- With parameters and defaults
DEFINE QUERY "user_prefs"($user, $limit = 10) AS {
  RECALL beliefs WHERE subject = $user AND relation = "likes"
  RECENT $limit WITH rerank
}

-- With a description
DEFINE QUERY "agent_context"($user, $budget = 4000)
  DESCRIPTION "Full agent briefing for any user" AS {
  ASSEMBLE "agent briefing" FROM
    knowledge: (RECALL beliefs WHERE user_id = $user RECENT 20),
    goals:     (RECALL goals WHERE assigned_to = $user)
  BUDGET $budget tokens
  WITH dedup, diversity(0.5)
  FORMAT markdown
}

-- COALESCE with fallback chains
DEFINE QUERY "find_preference"($user, $topic) AS {
  COALESCE {
    RECALL beliefs WHERE subject = $user AND relation = "likes" AND object LIKE $topic
  } OR {
    RECALL beliefs ABOUT $topic WHERE subject = $user
  }
}

Parameter rules:

  • Parameters use $name syntax
  • Optional defaults: $limit = 10
  • Parameters without defaults are required at RUN time
  • Maximum 10 parameters per query

Body rules:

  • The body must contain only read-tier statements: RECALL, EXISTS, ASSEMBLE, HISTORY, COALESCE, BATCH
  • Write statements (ADD, SUPERSEDE, ACCUMULATE, REVERT) are rejected
  • RUN inside a body is rejected (no recursion)

How do I execute a saved query?

Use RUN with the query name and parameter bindings.

-- Basic
RUN "recent_beliefs"

-- With parameters (required params must be supplied)
RUN "user_prefs"($user = "john")

-- Override defaults
RUN "user_prefs"($user = "bob", $limit = 5)
POST /api/memories/default/cal
Content-Type: text/cal

RUN "user_prefs"($user = "john")
areev cal 'RUN "user_prefs"($user = "john")'

How do call-site overrides work?

When running a saved query, you can override the FORMAT and extend the WITH options at the call site. This lets you reuse the same retrieval logic with different output formats.

-- Same query, three different outputs
RUN "agent_context"($user = "john") FORMAT json           -- dashboard
RUN "agent_context"($user = "john") FORMAT markdown        -- report
RUN "agent_context"($user = "john") FORMAT TEMPLATE "email_summary"  -- email

Override rules:

ClauseBehavior
FORMATCall-site replaces the body’s FORMAT entirely
WITHCall-site merges with body’s WITH options. On conflict, call-site wins
-- Body defines: WITH dedup, diversity(0.5)
-- Call-site adds: WITH explanation, diversity(0.8)
-- Effective: WITH dedup, diversity(0.8), explanation
RUN "agent_context"($user = "john") WITH explanation, diversity(0.8)

How do I compose saved queries with output templates?

Saved queries and output templates serve different layers. DEFINE TEMPLATE controls how results look. DEFINE QUERY controls what results are retrieved. Compose them freely.

-- Step 1: Define an output template
DEFINE TEMPLATE "brief"
  ELEMENT {
- [{{grain.type}}] {{grain.subject}}: {{grain.content}}
  }

-- Step 2: Define a query
DEFINE QUERY "user_context"($user) AS {
  RECALL beliefs WHERE subject = $user RECENT 20
}

-- Step 3: Compose at call site
RUN "user_context"($user = "john") FORMAT TEMPLATE "brief"
RUN "user_context"($user = "john") FORMAT json
RUN "user_context"($user = "john") FORMAT markdown

The same retrieval logic produces three different output formats without duplicating the query.

How do I list and inspect saved queries?

-- List all saved queries
DESCRIBE QUERIES

-- Inspect a specific query (shows params, body, description)
DESCRIBE QUERY "user_prefs"
POST /api/memories/default/cal
Content-Type: text/cal

DESCRIBE QUERIES

DESCRIBE QUERIES returns:

{
  "queries": [
    { "name": "user_prefs", "description": "...", "param_count": 2, "body_size": 50 },
    { "name": "agent_context", "description": "Full agent briefing", "param_count": 2, "body_size": 180 }
  ]
}

DESCRIBE QUERY "user_prefs" returns the full definition including parameters, defaults, and body text.

How do I delete a saved query?

Use DROP QUERY. This requires cal_destructive_ops to be enabled on the database.

DROP QUERY "user_prefs"

What are the constraints?

ConstraintLimit
Max queries per memory100
Max body size8,192 bytes
Max parameters10
Name formatLowercase letters, digits, underscores. 1-64 chars. Must start with a letter.
RecursionForbidden (RUN inside DEFINE QUERY body is rejected)
Write statements in bodyForbidden (ADD, SUPERSEDE, etc. are rejected)
  • CAL Guide: Full CAL statement reference including RECALL, ASSEMBLE, and LET bindings
  • Search & Recall: How retrieval scoring, reranking, and WITH options work
  • Supersede: How to update and version memories