Your first MemQL program
Build a personal reading list with four constructs: a concept, mutation, query, and tool. You can validate the whole file offline, then run it on a cluster where your account has authoring permission. No model call is needed.
The complete file
Save this as reading.memql in its own workspace folder, or open the checked-in
example. Use a separate folder
from the engine's core DSL to keep your tutorial definitions distinct.
/// A reading-list item owned by the signed-in person.@rowAuthz(owner="ownerUserId")@displayCard(primary="title", status="finished")concept readingItem { ownerUserId string! title string! finished bool} /// Add an item. Ownership comes from the authenticated actor.@actormutation readingItem addReadingItem { args { itemId string! title string! } insert { accept { title } stamp { id: args.itemId ownerUserId: actor.userId finished: false } }} /// Read your list, optionally narrowed to finished or unfinished items.@actorquery readingItem readingItems { args { finished bool } filter row => row.ownerUserId == actor.userId && (args.finished == nil || row.finished == args.finished) sort "row.createdAt", "desc" paginate 50} /// Give the same read operation a tool interface.@handler(type="query", query="query readingItems(finished: args.finished)")@executionTime("fast")tool listReadingItems { finished boolean @description("True for finished; false for unfinished. Omit for both.")}- Concept: the fields every reading item can hold.
!makes a field required. The engine supplies intrinsic fields such asidandcreatedAt; do not redeclare them. - Mutation:
acceptcopies the listed argument;stampsupplies the id, authenticated owner, and initial completion state. The caller cannot choose someone else's owner id. - Query:
@actormakes the caller available. The filter narrows by owner, then by the optional argument.nilmeans no completion filter was supplied. Sorting and pagination bound the result to the newest 50 rows on the first page. - Tool: gives the query a described argument surface. A tool declaration does not by itself grant an agent permission to use it or configure an AI provider.
The adjacent namespace.pin file contains reading, so this example retains
its namespace when the folder is named reading-list. Keep it with the source
and manifest when copying the example.
The concept is v1:reading:readingItem. Names and imports are covered in
naming conventions.
Keep a memql.toml beside the file when sharing or mounting it as a domain:
memql = "1.0"edition = "2026"The checked-in example includes this manifest. It declares the language edition; it does not select the engine release.
Validate before connecting
With a checkout of this repository and the Go toolchain declared by its
go.mod, run from the repository root:
go run ./cmd/memqllint examples/reading-listFor your own copy, replace the path with the example folder. Directory-mode lint also runs engine load-time validation against the embedded core tree. It does not test cluster authorization, persistence, or live execution. The extension also reports diagnostics as you edit.
Run it in VS Code or Cursor
- Install the extension, open the example's folder, and trust the workspace when you intend to connect.
- Use MemQL: Add Cluster, supply your cluster domain, select it, and sign in. Use a development cluster and an account allowed to train constructs.
- Use the concept's training action to dry-run and then promote
readingItem. Concepts cannot be staged privately; promoting this one registers a shared schema, while its rows remain governed by the ownership tier. - Run
addReadingItemfrom its CodeLens. SupplyitemIdas a fresh unique string (for example,reading-first-item) andtitleasRead the MemQL language guide. This writes an actual row. - Run
readingItemswithfinishedset tofalse. Your new item should appear withfinished: false. You can also runlistReadingItemswith the same argument; it calls the query. - Find
readingItemin Data to inspect rows visible to your account, and inspect the run result in the editor.
The editor injects local runnable definitions into an authoring session when needed. Running them is not promotion; a mutation run still writes data. To make a query or tool persist beyond the session, explicitly stage it for personal use or promote it to the cluster. Resolve any preflight or permission refusal before retrying. See runtime execution and training for the exact scope of each action.
Try one change
Change the query's sort direction from "desc" to "asc", save, and run it
again. With several items, the first page now starts with the oldest ones.
Saving only changes your file; the connected cluster's training indicators tell
you whether a previously promoted definition differs from it.
To extend the program, follow the shipped to-do mutations and queries. Updates create another version of a row; keep its required payload and ownership intact. Read the authoring rules before changing a schema with existing data.
Continue
Reusable predicates · Tools and automations · Events · Access model.