Skip to content

expresses

expresses

Declare how a machine is reachable by the outside world. The expresses section defines the surfaces through which users, other machines, and external systems can interact with the machine. Every surface inherits the machine’s governance: a machine that is not allowed to access the network cannot be reached via an API surface that bypasses those restrictions.

MCP (Model Context Protocol) is implicit: every machine is automatically available as an MCP tool. The expresses section is for declaring additional surfaces beyond MCP.

When to use

Use expresses when a machine needs to be reachable through:

  • A REST API endpoint
  • A WebSocket connection for real-time communication
  • A webhook receiver for external event sources (Stripe, GitHub, etc.)
  • A web page served to end users (Kanvas)
  • An A2A (Agent-to-Agent) protocol endpoint

Omit expresses for machines that are only called by other machines via ask ... from or that only respond to events via subscribes. MCP availability does not require an expresses declaration.

Syntax

expresses
<surface_type>
<configuration>

Multiple surfaces can be declared in a single expresses section.

Surface types

api

Expose the machine as a REST API endpoint.

expresses
api
path: "/api/classify"
method: "POST"
authentication: "bearer_token"
ConfigRequiredDescription
pathYesURL path for the endpoint
methodNoHTTP method: "GET", "POST", "PUT", "DELETE" (default: "POST")
authenticationNoAuth type: "bearer_token", "api_key", "none" (default: "none")

webhook

Receive incoming webhooks from external services.

expresses
webhook
path: "/hooks/stripe"
authentication: "hmac_sha256"
provider: "stripe"
ConfigRequiredDescription
pathYesURL path for the webhook receiver
authenticationNoSignature verification method
providerNoNamed provider for pre-configured signature verification

websocket

Establish a WebSocket connection for bidirectional real-time communication.

expresses
websocket
path: "/ws/updates"
ConfigRequiredDescription
pathYesURL path for the WebSocket endpoint

page

Serve a web page to end users (Kanvas surface). This is how machines become user-facing applications.

expresses
page
path: "/"
title: "Order Dashboard"
ConfigRequiredDescription
pathYesURL path for the page
titleNoPage title shown in browser tab

a2a

Expose the machine via the Agent-to-Agent protocol, allowing other agents (local or remote) to discover and interact with it.

expresses
a2a
methods: ["tasks/send", "tasks/get"]
ConfigRequiredDescription
methodsNoSupported A2A methods (default: all standard methods)

Authentication types

AuthHeaderNotes
"bearer_token"Authorization: Bearer <token>Token verified via Phoenix.Token
"api_key"X-Api-Key: <key> or ?api_key=<key>Key verified via Phoenix.Token
"hmac_sha256"Signature header (provider-specific)For webhook signature verification
"none"(no header)No authentication required (default)

Examples

API with authentication

machine ticket_classifier
accepts
message as text, is required
responds with
team as text
confidence as decimal
implements
ask classify, using: "anthropic:claude-haiku-4"
with task "Classify this support ticket: ${input.message}"
returns
team as text
confidence as decimal
expresses
api
path: "/api/tickets/classify"
method: "POST"
authentication: "bearer_token"

Multiple surfaces

machine live_dashboard
expresses
api
path: "/api/metrics"
method: "GET"
authentication: "api_key"
websocket
path: "/ws/metrics"
page
path: "/dashboard"
title: "System Metrics"

Webhook receiver

machine stripe_handler
accepts
event_type as text, is required
data as map, is required
implements
decide route_event
when input.event_type is "payment_intent.succeeded"
compute handle_payment
{status: "processed", amount: input.data.amount}
when input.event_type is "charge.failed"
compute handle_failure
{status: "failed", reason: input.data.failure_message}
otherwise
compute skip
{status: "ignored"}
expresses
webhook
path: "/hooks/stripe"
authentication: "hmac_sha256"
provider: "stripe"

Governance

Every surface declared in expresses inherits the machine’s full governance configuration from ensures. There is no way to create a surface that bypasses governance. Specifically:

  • API requests go through the same permission checks as any other invocation
  • Webhook payloads are validated against the accepts contract before steps execute
  • WebSocket messages are governed per-message
  • Every surface access is recorded in the behavioral ledger as a SurfaceAccess event (Inv 3: Governance Mediation)

This means a machine’s expresses section only controls how the machine is reachable, not what it is allowed to do. The ensures section controls permissions regardless of the surface.

Translations

LanguageKeyword
Englishexpresses
Spanishexpresa
Frenchexpose
Germanstellt dar
Japanese表現
Chinese表达
Korean표현

See also

  • implements - Machine behavior (subscribes/publishes for event routing)
  • ensures - Governance rules inherited by all surfaces
  • accepts - Input contract validated on every surface request