Reference

Agent API

LatticeKit speaks MCP. An AI client — a Claude Code session, a desktop connector, any Model Context Protocol client — can connect to a single LatticeKit tenant and read the business, propose changes to it, and prove those changes work, under a grant the tenant’s operator consented to and can revoke at any time.

Status: The gateway is built and in internal testing. There is no public endpoint yet — this page documents the contract a client will connect against, and is the reference target advertised by the gateway’s own protected-resource metadata. If you want to be told when it opens, join the waitlist.

The endpoint

One route, streamable-HTTP MCP, stateless. One JSON-RPC message in, one JSON response out; notifications get a 202.

MethodSupported
initialize, ping, notifications/*Yes
tools/list, tools/callYes
resources/list, resources/readYes — the caller documentation, addressed latticekit://docs/…
JSON-RPC batchingNo — removed in the 2025-06-18 MCP revision

Protocol faults come back as JSON-RPC errors. Tool-execution failures come back as isError: true tool results carrying an RFC 7807 problem detail as text — so a failed booking tells the agent why it failed in a form it can act on. Authentication failures are plain RFC 7807 401/403.

Connecting

Clients discover the authorisation server the standard way, via RFC 9728 protected-resource metadata:

GET /.well-known/oauth-protected-resource/agent/v1/mcp

That returns the resource id, the authorisation server, and the supported scopes. From there a client registers dynamically, walks authorise → consent → token, and calls the endpoint with a bearer token. The consent screen belongs to the tenant’s operator: they see which client is asking, choose the scopes, and can revoke the grant afterwards without rotating any credential. Machine API keys are also supported for server-to-server clients that are not walking a browser flow.

ScopeGrants
agent:readRead capabilities — schedules, availability, catalog, customers, orders, comms history. Roughly a hundred, matching what a tenant operator can already see.
agent:writeTier-1 actions only: check in a booking, record attendance, submit a form response. The repetitive things a scanner, a register or a kiosk does. Every write requires an Idempotency-Key.
agent:proposeThe right to ask for a tier-2 action. Calling one parks a proposal; a human reads it and decides. Anything that moves money or touches a person’s record lives here.

Finding the right tool

tools/list deliberately advertises a small fixed core — fifteen tools or fewer — rather than the full capability surface. Agents degrade under schema sprawl, so discovery beats enumeration:

lattice_search_capabilities
Keyword search across everything this grant can reach.
lattice_describe_capability
The full typed schema for one capability, plus what it costs to be wrong.
lattice_invoke
Call any capability the grant permits, by id.

Everything visible stays callable through lattice_invoke whether or not it is advertised. The short list is a context optimisation for the connecting agent, not a security boundary — the boundary is the grant.

What an agent cannot do

Capabilities are invisible to the gateway until a provider explicitly opts in, so the default for anything newly built is unreachable. Beyond that:

  • An agent inherits the same CapabilityInvoker checks a human operator gets — it cannot reach an action an operator could not, nor reach it under weaker rules.
  • Tier-2 and above never execute on an agent’s say-so. They park for a human.
  • Per-grant daily ceilings bound call counts and money, so a loop that goes wrong is limited by policy rather than by whoever notices first.
  • A grant can be marked sandbox-only, which forces sandbox posture server-side: a request header can add sandboxing, never remove it.
  • A grant can be narrowed to one business unit.
  • Every call is audited against the grant, not just the credential.

Creating a business from an agent

An agent can also take a person from a description of their business, to a live demo of it, to an account that keeps that demo — and come out the other side holding a grant to it. This runs on a second, pre-tenant MCP endpoint, POST /agent/v1/signup, with the same protocol shape as the tenant endpoint above (initialize, ping, tools/list, tools/call and the documentation resources) and a fixed set of tools.

Credentials are arguments here. There is no authorization server for this endpoint and nothing to discover: a conversation’s secret and a signup’s agentToken are each returned once, when the thing is created, and passed back as arguments on every later call about it (the signup token is also accepted as a bearer, for clients that can set one). A credential given as an argument that fails is a tool result with isError: true, never an HTTP 401.

Two things stay the person’s and cannot be done by the agent: confirming the email — where they also accept the terms and allow the agent’s access — and, only while the platform collects a card at signup, putting a card on file on the payment processor’s page. The agent relays instructions and links; every result carries a nextStep written to be relayed.

ToolCredentialWhat it does
lattice_signup_modenoneReturns { mode, waitlistOpen, cardRequired, conciergeMode, demoMode }. While the platform is invite-only every account tool answers 403 with problem type signup-closed; the concierge tools answer to conciergeMode instead. cardRequired: false means a confirmed email is the last step before the business exists. Check first.
lattice_startersnoneThe ten example businesses — racquet club, gym, salon, studio, restaurant, barbershop, spa, clinic, hotel, music school — each with a summary and the setup a preview of it starts from. Free to call.
lattice_conversation_opennone{ starter?, clientName }. Opens a conversation with the concierge, from a starter or from scratch. Returns { conversationId, secret, state, nextStep }; the secret is shown once. Nothing is created.
lattice_conversation_saysecretRelay what the owner says about their business, in their words, and get the reply — which may be a question to relay back. The transcript is what the preview is drafted from; ready: true means the concierge has enough. Capped at twelve model turns, two previews, seven days.
lattice_conversation_previewsecret{ email, businessName? }. Drafts the business behind the owner’s email — offers, hours, resources, staff, pricing — and keeps the blueprint on the conversation.
lattice_conversation_demosecretBuilds a live, bookable demo of the previewed business at its own address, in about a minute. One per conversation; it winds down after a week unless the owner creates the business, which keeps it as it stands. A described business not yet tied to a starter is refused with demo-no-starter and the keys to choose from — pick one with lattice_conversation_starter and call again.
lattice_conversation_statesecretThe transcript, the blueprint, the demo and whether it is live, turns remaining, and what to do next.
lattice_signup_startnone{ email, businessName, slug, clientName, conversationId?, secret? }. With the conversation, the business is created from it — its demo becomes the business, nothing is rebuilt. Sends the confirmation email and returns { signupId, agentToken, conversationId, status, cardRequired, expiresAt, nextStep }. The agentToken (prefix sgat_) is shown once and lives as long as the signup (48 hours). Nothing has been created yet, and the terms are not accepted here.
lattice_signup_statustokenReturns { status, emailVerified, termsAccepted, agentAccessAllowed, cardOnFile, cardRequired, conversationId, tenantId, grantClaimed, expiresAt, nextStep, paymentUrl? }. Where a card is required it carries paymentUrl once the email is confirmed and the terms accepted; where none is, confirming the email creates the business at once and the person lands signed in.
lattice_signup_payment_linktoken{ fresh? }. The same link on its own. Refused before the email is confirmed or the terms accepted, and once a card is on file. fresh: true replaces an expired link.
lattice_signup_completetoken{ slug? }. Creates the business now — only once the email is confirmed and the terms accepted, and only where no card is required or one is on file. A 409 means it already exists: claim the grant.
lattice_signup_claim_granttokenOnly once status is completed, and only once. Mints a grant on the new business — scopes agent:read + agent:propose, 30 days, 500 calls a day — and returns { apiKey, grantId, mcpUrl, tenantId, scopes, expiresAt, dailyCallLimit, nextStep }. The apiKey is shown once; use it as the bearer at mcpUrl. A second claim answers signup-grant-claimed.

What the person does, and where: on the confirmation page they accept the Terms of Service and Privacy Policy and tick “Let clientName access businessName once it is created” — both are required, and the agent cannot supply either. Where a card is required, on the payment page they add one, which never passes through LatticeKit or the agent. They may open the payment link in a different browser from the one that confirmed the email.

The grant the agent receives is the owner’s decision, made on that confirmation page. It appears in the console under Agents like any other connection and can be revoked there at any time; it cannot write or move money, only read and propose. Refusals: a signup tool with neither a bearer nor an agentToken argument is 401; a token for a different signupId is 403; an expired signup is 410. Everything an agent can act on — validation, a wrong or missing conversation secret, the re-send cooldown, the wrong state, every concierge and demo refusal, an already-claimed grant — comes back as a tool result with isError: true, its text ending in the problem type and HTTP status it corresponds to.

Machine-readable documentation

The documents written for callers — the domain model, the contracts, and how to connect — are published for machines two ways, generated from one list so they cannot drift apart:

SurfaceFor
/llms.txtAn index: what LatticeKit is, then every document as a link with a one-line summary. Small enough to read before deciding what to fetch.
/llms-full.txtEvery document concatenated, for a crawler that wants the whole thing in one request.
MCP resources/readThe same documents, served to a connected agent as latticekit://docs/… resources.

Individual documents are also served as plain Markdown — for example /docs/scheduling.md for the booking model, /docs/errors.md for the error contract, or /docs/what-is-latticekit.md for orientation.

Configuring a business, reviewably

The interesting thing an agent can do here is not call fifty endpoints in the right order. It is emit one document. Pirenne exports a whole tenant’s configuration as a portable YAML bundle and applies one back transactionally, so an agent proposes a single reviewable artefact, a human approves it once, and it can be diffed, pinned and rolled back.

Four starter businesses ship as ordinary bundles — racquet club, gym, salon, studio — and each carries its own scenario as an acceptance test. An agent can apply a starter, run its scenario against the real configuration with every side effect neutralised, and get back a structured verdict on whether the business it just built actually works.