Zum Inhalt springen
Developer Preview — APIs and language features may change before 1.0

Surfaces

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

A machine that runs is useful. A machine that is reachable is powerful. The expresses section declares how a machine is reachable by the outside world: as an API endpoint, a webhook receiver, a WebSocket connection, an A2A agent, or a web page.

Every surface inherits the machine’s governance. When a machine is invoked through any surface, every action still produces an intent that is mediated by the governance interpreter. A machine that cannot send email cannot send email regardless of whether it was invoked via Siri, a REST call, or another agent. The governance boundary does not move when the invocation surface changes.

MCP is implicit

Every machine is automatically available as an MCP tool. You do not need to declare anything in expresses for MCP to work. This is the zero-configuration default: write a machine, and it is immediately usable by Claude, Cursor, ChatGPT, VS Code, or any MCP-compatible client.

The expresses section is for declaring surfaces beyond MCP.

Declaring surfaces

machine my_service
accepts
query as text, is required
responds with
results as list
implements
ask search, using: "anthropic:claude-sonnet-4-6"
with task "Search for: ${input.query}"
returns
results as list
assuming
results: ["result 1", "result 2"]
expresses
api
path: "/api/search"
method: "POST"
auth: oauth, api_key
scopes: machines:run
webhook
path: "/hooks/incoming"
auth: signature
websocket
path: "/ws/updates"
auth: oauth, session
a2a
auth: oauth
page
path: "/search"
title: "Search"
auth: session

This machine is reachable six ways: MCP (implicit), REST API, webhook, WebSocket, A2A, and web page. All six surfaces invoke the same machine, respect the same governance, and record to the same behavioral ledger.

Surface types at a glance

SurfaceUse caseConfiguration
MCPAI tool calling (Claude, Cursor, etc.)Implicit, no config needed
APIREST endpoints for HTTP clientsPath, method, authentication
WebhookReceiving events from external servicesPath, provider, signature verification
WebSocketReal-time bidirectional communicationPath
A2AAgent-to-Agent protocol for multi-agent systemsMethods
PageWeb pages for end users (Kanvas)Path, title

Each surface type has its own guide page with full examples:

  • MCP - Model Context Protocol integration
  • REST API - HTTP endpoints
  • Webhooks - Receiving external events
  • WebSocket - Real-time connections
  • A2A - Agent-to-Agent protocol
  • Pages - Web interfaces (Kanvas)

Surface authentication

Every surface supports auth:, scopes:, and allow: config keys. When omitted, each surface type gets a secure default:

SurfaceDefault authWhy
APIoauth, api_keyMachine callers use either
MCPoauthMCP spec expects OAuth
PagesessionHumans use browsers
WebhooksignatureWebhooks use HMAC
WebSocketoauth, sessionEither machine or browser
A2AoauthAgent-to-agent uses OAuth

To make a surface public, write auth: public explicitly. To restrict access to specific users or organizations, add an allow: list:

expresses
api
path: "/api/data"
auth: oauth, api_key
scopes: machines:run
allow: @acme.com, [email protected], @*.corp.acme.com

The allow: list supports exact emails, exact domains (@acme.com), wildcard subdomains (@*.acme.com), and OAuth client IDs (client:oac2_xxx).

Dev mode: On localhost, surface auth is skipped entirely. No OAuth setup needed for local development.

See the expresses reference for full details.

Governance across surfaces

Every surface access is recorded as a SurfaceAccess event in the behavioral ledger. The event includes:

  • Which surface was used (:mcp, :api, :webhook, :websocket, :a2a, :page)
  • Who made the request (authentication identity)
  • What inputs were provided
  • The governance decision (allowed/denied) and which rules matched

This means you can answer questions like “how many times was this machine invoked via the API vs. via MCP?” or “which webhook deliveries were denied by governance?”

Authentication

Surfaces that accept external requests support authentication:

Auth typeHow it works
"bearer_token"Authorization: Bearer <token> header
"api_key"X-Api-Key header or ?api_key= query parameter
"hmac_sha256"Signature verification (for webhooks)
"none"No authentication (default)

Authentication determines who is making the request. Governance determines what the machine is allowed to do. These are separate concerns: a properly authenticated request can still be denied by governance if the machine does not have permission for the requested action.

The tunnel

Local machines are not directly reachable from the internet. The Kortex tunnel solves this by relaying requests through mashin.live to your local cell. Any machine with an expresses section is automatically exposed through the tunnel when your cell starts.

See Cells: Exposing local machines for details.

Next steps