Agent Guide
Canonical contracts for agents using docs URLs, CLI, voice, and the daemon API
Lattices exposes the same execution model through these interfaces:
- Docs URLs for discovery and citation
- CLI for shell-based agents
- Daemon API for typed programmatic control
- Voice / hands-off / HUD as clients of the same execution layer
The rule is simple: agents should learn the canonical action model first, then choose the transport that fits the environment.
First check
Run these read-only commands before any mutation. They do not move windows.
lats call api.schema # every daemon method and its parameters
lats call desktop.snapshot # what is on screen now, with window idsExpect a method list, then a snapshot of the current space. If either call
fails, the usual cause is that the menu bar app, which hosts the daemon, is not
running. Ask the user to start it with lats app. Then resolve a target with windows.resolve or dryRun before you
place a window. See Discoverability.
Install the skills
lattices-dev/lattices is the skills.sh catalog for the product
family. Skills live under skills/.
| Skill | Product |
|---|---|
lattices |
Workspace control, tiling, sessions, screen text |
action |
Native observe / resolve / act / record |
voice |
The voice domain: spoken commands, voice intents, and speech output through the Voice app |
blink |
Spatial notes through the blink CLI |
npx skills add lattices-dev/lattices --list
npx skills add lattices-dev/lattices --all --global --yes
npx skills add lattices-dev/lattices --skill lattices --global --yes
npx skills add lattices-dev/lattices --skill action --global --yes
npx skills add lattices-dev/lattices --skill voice --global --yes
npx skills add lattices-dev/lattices --skill blink --global --yesThe browser_* tools come from lats mcp, not from a plugin. The
action-browser@lattices plugin carries only the skill text. See
MCP.
Each product owns its own work. Concepts
lists every lats command, the process that receives it, and the product
that does the work. Product docs: Action,
Canvas, Voice.
To install the Action product itself, run lattices action install. It
downloads the latest signed Action.app release to /Applications.
lattices action status reports install, runtime, and agent state;
lattices action call <method> talks to the Action agent without a monorepo
checkout. Action 0.4.0 and Lattices 0.15.1 use authenticated private IPC;
earlier releases use the local agent port. Let the matching CLI discover the endpoint.
See Processes and ports.
Action private layers
Action private layers create virtual displays. Lattices workspace layers group
windows and use layer.activate; they do not create Action's private surface.
For private browser work, use Action MCP layer_open { browser: true },
layer_snapshot, layer_click/type/js, and layer_close.
First run lats action capabilities and query capabilities plus tools/list
on the active Action MCP connection. Compare source/native fingerprints, check
safety.privateLayer, and require host acceptance for desktop preservation.
Stop on quarantine; do not rebuild an installation target or fall back to a
regular browser. A missing block is not proof of isolation. Reconnect MCP after
updates and repeat discovery. Matching a published version does not verify
MCP or native feature parity.
The CLI offers layer lifecycle, snapshot, PiP, and recording. Browser flags, input, navigation, and JavaScript require MCP. Raw Action WebSocket and the Lattices daemon do not provide that orchestration. Follow the Action skill and layer reference for leases, operator takeover, cleanup, and acceptance requirements.
Canonical mutations
These are the preferred action identifiers:
| Action | Purpose | Preferred surface |
|---|---|---|
windows.place |
Place a window or session using a typed placement spec | actions.execute |
layers.activate |
Bring up a workspace layer with explicit activation mode | Daemon API |
spaces.optimize |
Rebalance a set of windows using an explicit scope and strategy | Daemon API |
tabs.stack |
Turn explicit or Hyperspace-selected windows into ephemeral cross-app tabs | Daemon API |
tabs.layout |
Expand a live tab stack to grid or collapse it back to tabs | Daemon API |
Compatibility wrappers still exist:
| Legacy method | Canonical equivalent |
|---|---|
windows.place |
actions.execute with type=windows.place |
window.tile |
windows.place |
layers.switch |
layers.activate |
layout.distribute |
spaces.optimize with scope=visible, strategy=balanced |
Discoverability
Agents should use these paths in order:
- API schema:
lats call api.schema - Read-only workspace map and UI hygiene: /lattices/docs/workspace-map
- Daemon reference: /lattices/docs/api
- Agent guide: /lattices/docs/agents
- Voice model: /lattices/docs/voice
- Concepts / config: /lattices/docs/concepts, /lattices/docs/config
Useful CLI discovery commands:
lats help
lats call api.schema
lats call desktop.snapshot
lats map
lats call terminals.capture '{"session":"<live-session>","lines":40}'
lats voice intentsdesktop.snapshot is the structured “what is in front of the user?” read.
lats map draws that same current-space view as ASCII. terminals.capture
is exact tmux pane text, not OCR.
For window actions, resolve before mutating when target identity matters:
lats call windows.resolve '{"target":{"kind":"session","session":"frontend-a1b2c3"},"placement":"left"}'
lats call actions.execute '{"type":"window.place","target":{"kind":"session","session":"frontend-a1b2c3"},"args":{"placement":"left"},"dryRun":true}'windows.resolve and dryRun return the resolved wid, app/title,
target resolution path, display, and planned frame without moving the
window.
Verified windows.place receipts include undoable: true when Lattices
captured a concrete window id and previous frame. Agents can restore the
latest undoable placement, or an entire request batch, through:
lats call history.undo '{}'
lats call history.undo '{"requestId":"req_..."}'
lats call history.undo '{"receiptId":"exec_...","dryRun":true}'Undo checks that the window is still where the original receipt left it
before restoring the previous frame. Pass force:true only when the
caller intentionally wants to override a later manual move.
Agent documentation artifacts
The site build emits agent-first files in addition to rendered pages. Use these when an agent needs raw markdown, prompt text, or a compact context bundle without scraping HTML. Every docs page also has a Use with an agent control that copies the page or its product's docs.
Prefer the product-scoped files. They hold only that product's current
guides. <product> is lattices, action, blink, or speech.
| Need | URL |
|---|---|
| One product's index and first check | /<product>/docs/llms.txt |
| One product's current docs, full text | /<product>/docs/llms-full.txt |
| One product's docs as JSON | /<product>/docs/agent-docs.json |
| One page as readable Markdown | /<product>/docs/<slug>.md or /<product>/docs/<slug>/index.md |
| Exact Markdown source | /<product>/docs/markdown/<slug>.md |
| Public product instructions | /<product>/docs/AGENTS.md |
HTML pages advertise their Markdown representation with rel="alternate"
and the relevant product index with rel="describedby". The Markdown page
links resolve to canonical web pages; source mirrors preserve the original
bytes. Product indexes follow the llms.txt proposal.
llms-full.txt is a complete-context convenience file, not a separate standard.
Pages named agents use /agents/index.md so their Markdown does not collide
with public AGENTS.md instructions on case-insensitive filesystems. Follow
the page's advertised alternate URL when retrieving its content.
The public AGENTS.md files contain product-use instructions. Repository
maintainer instructions and local workspace paths are not copied into them.
Archives and prompt templates stay outside the automatic current context.
Discovery and semantic metadata
| File or markup | Purpose | Status |
|---|---|---|
/agent/discovery.json |
Coverage, format status, and retrieval links | Project-specific manifest |
/.well-known/agent-skills/index.json |
Downloadable skills with content digests | Discovery draft, v0.2 |
/.well-known/ai-catalog.json |
Catalog of documentation and skills | AI Catalog draft |
/robots.txt, /sitemap.xml |
Crawl policy and canonical page inventory | Standard crawler formats |
| JSON-LD in each docs page | Product identity, documentation collection, technical article, breadcrumbs | Schema.org |
The site serves documentation and downloadable skills. It does not host an A2A agent or a remote MCP server, so it publishes no A2A agent card, MCP server card, or OAuth service metadata. Local MCP installation remains documented in the product guides. Draft discovery support does not change product permissions.
GitHub Pages serves explicit static files. This site does not promise Markdown
content negotiation or custom HTTP discovery headers; use the linked .md
URLs. JSON-LD and discovery links are present in the initial HTML and are
updated during navigation.
The family-wide files below combine the product documentation.
| Need | URL |
|---|---|
| Discovery manifest | /agent/manifest.json or /docs.json |
| Full docs with markdown bodies | /agent/docs.json or /agent-docs.json |
| Prompt registry | /agent/prompts.json or /prompts.json |
| Combined agent context | /agent/context.md or /agent-context.md |
| Combined raw docs | /agent/bundles/all.md or /docs/all.md |
| Core onboarding bundle | /agent/bundles/core.md |
| Daemon/API bundle | /agent/bundles/daemon-api.md |
| Voice and prompts bundle | /agent/bundles/voice.md |
| Install bundle | /agent/bundles/install.md |
| Raw markdown mirror | /agent/raw/docs/<slug>.md or /docs/markdown/<slug>.md |
Prompt files are mirrored at /prompts/<id>.md and
/docs/prompts/<id>.md. Nested docs keep path-safe slugs, for example
docs/reference/install-agent.md becomes
/agent/raw/docs/reference/install-agent.md.
Local scripts can import the same convenience functions used by the build:
import {
collectMarkdownArtifacts,
getMarkdownDoc,
getPrompt,
buildAgentManifest,
buildPromptRegistry,
buildContextBundle,
writeAgentArtifacts,
} from './apps/site/scripts/agent-docs.mjs'Run bun run docs:agent to regenerate the static artifacts without
running the full site build.
Placement contract
At the boundary, placements may be strings for convenience. Inside the daemon, the canonical contract is typed.
String shorthand:
{ "placement": "top-right" }
{ "placement": "grid:3x2:2,0" }Typed placement objects:
{ "placement": { "kind": "tile", "value": "top-third" } }
{ "placement": { "kind": "grid", "columns": 3, "rows": 2, "column": 2, "row": 0 } }
{ "placement": { "kind": "fractions", "x": 0.5, "y": 0, "w": 0.5, "h": 1 } }This lets voice stay natural while the executor stays explicit.
Choosing a surface
Use the daemon API when you need:
- typed receipts and traces
- explicit targeting by
wid,session, orapp - composition across layers, windows, and optimization
Use the CLI when you need:
- one-shot shell execution
- quick discovery from inside an agent terminal
- compatibility with environments that already have
lats
Use docs URLs when an agent needs:
- a citeable contract
- a stable page to open in a browser or pass to another agent
- quick onboarding without reading source
Examples
Node.js:
import { daemonCall } from '@lattices/lattices'
await daemonCall('sessions.launch', { path: '/Users/you/dev/frontend' })
await daemonCall('windows.resolve', {
target: { kind: 'session', session: 'frontend-a1b2c3' },
placement: 'left'
})
await daemonCall('actions.execute', {
type: 'window.place',
target: { kind: 'session', session: 'frontend-a1b2c3' },
args: { placement: { kind: 'tile', value: 'left' } }
})
await daemonCall('layers.activate', { name: 'review', mode: 'launch' })
await daemonCall('spaces.optimize', { scope: 'visible', strategy: 'balanced' })CLI:
lats call api.schema
lats call windows.resolve '{"target":{"kind":"session","session":"frontend-a1b2c3"},"placement":"left"}'
lats call actions.execute '{"type":"window.place","target":{"kind":"frontmost"},"args":{"placement":"left"}}'
lats call windows.place '{"session":"frontend-a1b2c3","placement":"left"}'
lats call layers.activate '{"name":"review","mode":"launch"}'
lats call spaces.optimize '{"scope":"visible","strategy":"balanced"}'Receipts and traceability
Mutating daemon calls should return structured receipts when possible. The important fields for agents are:
- resolved target
- resolved placement / scope / mode
- affected window IDs
- computed plan and applied mutations
- verification status
- trace entries explaining why the daemon chose that path
This is what keeps voice, hands-off, and scripted execution scrutable.
Voice and hands-off
Voice is not a separate execution system. It should compile into the same canonical actions:
- "put Terminal in the upper third" →
windows.place - "bring up review" →
layers.activate - "make this nice" →
spaces.optimize
That keeps the interaction layer flexible while the executor stays predictable.
Assistant intelligence boundary
Assistant planning lives in TypeScript where possible:
bin/assistant-intelligence.tsowns the intent catalog, prompt assembly, local rule planner, desktop snapshot formatting, and plan normalization.bin/handsoff-worker.tsandbin/handsoff-infer.tscall that module before falling back to model inference.- Swift should remain the macOS execution layer: hotkeys, windows, AX/CG, SkyLight, panels, and visual feedback.
Use lats assistant plan <text> --json to inspect the TS planner without
launching the app or mutating the desktop.