Your workspace lives at https://<your-workspace>.lattice-db.se — an isolated graph database that's yours alone. People use the web console; apps and AI agents connect with an access token over HTTPS. This guide covers both.
Throughout, replace <your-workspace> with your actual subdomain and <token> with a token you create in step 2.
Sign in to the console
Open https://<your-workspace>.lattice-db.se in a browser and sign in with your username and password. If your organization uses single sign-on, click “Sign in with SSO” instead.
Once you're in, you get a query editor, an interactive graph view, and an ontology browser. If you're an admin, you'll also see a Settings tab — that's where tokens, users, and SSO live.
Create an access token
Apps and agents authenticate with a bearer token, never your password. Each token carries a role that decides what it can do.
- In the console, go to Settings → Tokens.
- Give it a name (e.g.
my-apporclaude) and pick a role. - Click Create, then copy it immediately — a token is shown only once and can't be retrieved later.
| Role | Can do | Use it for |
|---|---|---|
| readonly | Read data only. | Dashboards, analytics, read-only agents. |
| readwrite | Read and write data (not schema). | Your application's normal traffic. |
| admin | Everything — read, write, and change the schema/ontology; manage tokens & users. | Migrations, setup, letting Claude build your ontology. |
Least privilege. Give each app the lowest role it needs — a readonly token physically cannot write. Create separate tokens per app so you can revoke one without affecting the others.
Connect your app (HTTP API)
Send queries to the JSON endpoint with your token in the Authorization header. Every query goes to one place:
cURL
curl -s https://<your-workspace>.lattice-db.se/query \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"query":"MATCH (n:Person) RETURN n.name LIMIT 10"}'
JavaScript
const res = await fetch("https://<your-workspace>.lattice-db.se/query", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
},
body: JSON.stringify({
query: "MATCH (p:Person)-[:KNOWS]->(f) WHERE p.name = $name RETURN f.name",
params: { name: "Ada" },
}),
});
const { columns, rows } = await res.json();
Python
import requests
r = requests.post(
"https://<your-workspace>.lattice-db.se/query",
headers={"Authorization": "Bearer <token>"},
json={"query": "MATCH (n) RETURN count(n) AS n"},
)
print(r.json()) # {"columns": ["n"], "rows": [[42]]}
- Pass values as parameters (
$name) via theparamsobject — never string-concatenate into the query. - The response is
{ "columns": [...], "rows": [[...]] }. A returned node or relationship carries its label/type and properties. - Queries use openCypher —
MATCH,CREATE,MERGE, aggregation, variable-length paths, and more.
Connect Claude (MCP)
The Model Context Protocol lets an AI agent like Claude talk to your graph directly — run queries, read the schema, and (with a write-capable token) build your ontology for you. Your workspace speaks MCP at /mcp.
The Settings → Tokens panel gives you a ready-to-paste MCP snippet when you create a token — the quickest way to get the exact config for your workspace.
Claude Code (CLI)
claude mcp add --transport http lattice \
https://<your-workspace>.lattice-db.se/mcp \
--header "Authorization: Bearer <token>"
Claude Desktop
Open Settings → Developer → Edit Config and add your workspace under mcpServers:
{
"mcpServers": {
"lattice": {
"type": "streamable-http",
"url": "https://<your-workspace>.lattice-db.se/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
Restart Claude Desktop fully (quit from the tray/menu bar, not just the window). The lattice tools then appear under the tools/connector icon.
What Claude can do
- query — run openCypher and get the results back.
- explain — see a query's plan without running it.
- lattice://schema — read the tables, relationships, and indexes.
- lattice://dialect — read the exact query grammar (see below). Claude should read this before writing schema, so it uses Lattice syntax rather than guessing Neo4j's.
- With an admin or readwrite token, Claude can create your ontology — node & relationship tables, hierarchies, and constraints. A readonly token lets it explore but never change anything.
Starter prompt (paste to Claude with an admin token connected):
First read the lattice://dialect resource — that's the exact
query grammar this database accepts (an openCypher subset, NOT Neo4j),
including how to create schema. Then read lattice://schema to see what
already exists.
Now design and create an ontology for my domain: define the node
tables and relationship tables with CREATE NODE TABLE / CREATE REL
TABLE, then load the data. Build it incrementally and read
lattice://schema back after each step to confirm. If a query
errors, re-check it against lattice://dialect rather than guessing
another syntax.
Reading lattice://dialect first is what stops the agent from probing for syntax — it gets the grammar (DDL, the EXISTS { … } form, reserved words) up front.
The query language
Lattice speaks an openCypher subset. Crucially, schema is created from the query language itself — you don't need host or config access to make labels. Agents can also read this same reference live at lattice://dialect over MCP.
Create schema (DDL)
-- a label is a node table; a relationship is a rel table with declared endpoints
CREATE NODE TABLE Person(name STRING, age INT64, PRIMARY KEY(name));
CREATE NODE TABLE Dog EXTENDS Animal(breed STRING); -- subclassing
CREATE REL TABLE KNOWS(FROM Person TO Person, since INT64);
CREATE INDEX person_name ON Person(name); -- no colon before the label
-- then write data (the table must exist first)
CREATE (:Person {name:'Ada', age:36});
MATCH (a:Person {name:'Ada'}),(b:Person {name:'Bob'}) CREATE (a)-[:KNOWS {since:2020}]->(b);
Types: STRING, INT64, DOUBLE, BOOL, TIMESTAMP, list types (INT64[]), VECTOR(n) — note there is no FLOAT, use DOUBLE. PRIMARY KEY parses but v1 does not enforce uniqueness — enforce it in your app.
Read & write
MATCH,OPTIONAL MATCH,WHERE,WITH,RETURN,ORDER BY,SKIP,LIMIT,DISTINCT,UNWIND,UNION [ALL]- Aggregates
count/sum/avg/min/max/collect(incl.DISTINCT);CASE; variable-length(a)-[:KNOWS*1..3]->(b) CREATE,MERGE,SET,DELETE/DETACH DELETE; proceduresCALL vector_search(...),CALL algo.<name>(...)
Differences from Neo4j (the common mistakes)
- Existence test is the subquery form
EXISTS { (a)-[:R]->(b) }— notexists(pattern). - Pattern predicates in
WHEREaren't supported: instead ofWHERE NOT (a)-[:R]->(b), writeWHERE NOT EXISTS { (a)-[:R]->(b) }. EXISTS { … }is valid only as a top-levelWHEREcondition (optionally withNOT) — not insideOR, a projection, orCASE.CREATE INDEX name ON Label(prop)— no colon before the label.- No list indexing (
coll[0]); a name that's a reserved word (e.g.CONTAINS) must be backtick-quoted:`CONTAINS`. - Not supported:
DROP,SHOW,USE,CREATE CONSTRAINT.
Invite your team
Give teammates their own console login (admins only):
- Go to Settings → Users.
- Add a name, a password, and a role (
readonly/readwrite/admin). - Share the credentials with your teammate — they sign in at your workspace URL.
Prefer central control? Wire up SSO (next) and your team logs in with your identity provider instead of individual passwords.
Single sign-on (SSO)
Under Settings → Single sign-on, connect your OIDC identity provider (Authentik, Okta, Entra, Google Workspace, …) so your team signs in with it — and map IdP groups to Lattice roles.
- Enter your provider's issuer, client id, and client secret, set a redirect URL of
https://<your-workspace>.lattice-db.se/auth/sso/callback, and save. Lattice validates the provider before enabling it. - A “Sign in with SSO” button then appears on your login page.
If the SSO card shows “Managed by your organization,” your provider is configured centrally and can't be changed here — just use the SSO button to sign in.
Handling tokens safely
- Shown once. Copy a token when you create it and store it in your app's secret manager or
.env— never in source control. - Revoke anytime. Delete a token in Settings → Tokens and it stops working immediately; issue a fresh one to rotate.
- One token per app/agent, each at the lowest role it needs, so a leak is contained and revocation is surgical.
- Isolated by design. Your workspace is a private database — your tokens only work against your graph, and no one else's tokens work against it.