Chat, AG-UI and MCP endpoints
Members of the organization talk to an environment’s published workflows on the Chat
page, which needs no setup beyond a chat trigger. Everything outside the product, such as
a website’s chat widget, another company’s agents or a sending system, reaches a workflow
through an incoming connection: a connection
that owns one endpoint and decides who may call it.
The Chat page
Section titled “The Chat page”Chat in the icon rail opens the environment’s Chat page. A member holds production
chats there with the workflows the current
published version offers: those with a chat trigger that are in service. While none does,
the page says a workflow with a chat trigger has to be published first.
- New chat starts a chat with the one chat workflow, opens a menu of them by title when there are several, and is disabled when there is none. Opening the page or pressing New chat creates nothing; the chat is created with its first message or file.
- A new chat opens on the start view: the agent’s icon, name and agent description, the workflow’s title when more than one workflow takes chats, and the workflow’s example prompts.
- The history lists your own chats under Last 7 days and Older, eight at first and more with Show more. Search matches titles and the text of every message. A row’s context menu deletes the chat.
- A chat runs the published version that was current when it started; publishing again does not change it.
- Replies stream with their tool calls. A reply that parked reads Waiting: a chat waiting for input takes your next message, and one waiting for a decision takes none until the decision is made (see Sessions and decisions).
- While a reply is being written, the composer’s Send becomes Stop, which cancels that turn; Enter sends nothing meanwhile. The reply keeps what it had produced and ends with a Cancelled note rather than a failure. The editor’s chat surface has the same Stop.
A chat belongs to the member who
started it. Another member’s chat is not found, and the Sessions page marks it as personal
with a lock. To try a draft, use the start action on a chat start state in the editor,
which opens a testing chat over the workflow’s session view (see
Workflows and the editor).
Example prompts
Section titled “Example prompts”A chat trigger can list up to six example prompts,
each at most 200 characters. Choosing one puts it in the composer without sending it. The
agent never reads them, and editing them changes no deployment.
states: answer: triggers: chat: session: triggers.-1.threadId examples: - Where is my order 4711? - I want to return a damaged item.Incoming connections
Section titled “Incoming connections”Register one on the Connections page from the catalog’s incoming entries: AG-UI endpoint, MCP endpoint or Webhook. The protocol is fixed for the connection’s life. Registering mints its endpoint’s address in this environment, shown on the row with Copy URL:
| Protocol | Address | Serves |
|---|---|---|
AG-UI endpoint (agui) |
/api/agui/<token> |
the chat trigger of one workflow |
MCP endpoint (mcp) |
/api/mcp/<token> |
every mcp trigger that names it, one tool per workflow |
Webhook (webhook) |
/api/webhooks/<token> |
the webhook trigger of one workflow |
The address is stable: publishing, editing the connection, or removing and restoring a trigger leave it unchanged, and deleting the connection and registering the same identifier again restores it. An inherited connection gets an address of its own in each environment. The address is never written to a file or shown to an agent.
An endpoint serves nothing until the published version holds a trigger naming its
connection; registering alone opens nothing. The trigger names it with connection:
states: answer: triggers: chat: session: triggers.-1.threadId connection: support-widget intake: triggers: intake: type: webhook connection: orders-hookA chat, mcp or webhook trigger that names no connection has no endpoint (a chat one
is still on the Chat page). Two triggers naming one AG-UI or webhook connection both fail to
deploy, naming the connection and the workflows, until one remains. The row reads Serving
with a count, Not used, or Error with the deployment’s message. A request to an
address that serves nothing gets 404, whatever the reason.
Edits to a connection’s mode, origins and limits take effect when the environment is published. Regenerating an endpoint token takes effect at once.
Who may call an endpoint
Section titled “Who may call an endpoint”Each connection declares one Authentication mode:
| Mode | UI label | A caller is admitted when | Protocols |
|---|---|---|---|
public |
None: anyone with the URL | always | AG-UI, webhook |
bearer |
Endpoint token | it sends Authorization: Bearer <endpoint token> |
all three |
oidc |
OIDC | it sends a JWT the declared issuer signed | all three |
The endpoint token is issued by the platform,
starts with amx_, and is shown once, when you register or switch to bearer. Only its
SHA-256 digest is stored, so it cannot be shown again. Regenerate issues a new one and
the old one stops working at once. Under oidc, the connection declares an Issuer and an
Audience, and optionally a JWKS URL and the accepted algorithms (RS256 when unset).
The audience is required: without it, every token the issuer signs for any application would
be admitted. No platform user is created for the token’s subject.
A member calling an AG-UI or MCP endpoint with their own platform sign-in is admitted whatever the
mode, when their role on the agent holds workflows:use (a User); without it, the call is treated
as any other caller’s and the mode decides. A webhook reads no platform sign-in. A credential
opens only its own connection’s endpoint and nothing else of the platform.
Browser origins list the sites whose pages may call an AG-UI or MCP endpoint, one per
line; blank means server-to-server only, and * allows any site. A call from a page on any other
site is refused before anything starts. A webhook takes none.
A member’s sign-in counts on these endpoints only when it is the member’s own doing: a bearer token, or a proxy sign-in’s session from the platform’s own pages. A page on another site, even a declared one, that a signed-in member happens to visit calls as one of the connection’s own callers, never as that member.
Calls per minute sets two ceilings: per caller (the token’s subject, otherwise the client
address), and for the endpoint in total. Blank uses the protocol’s defaults: 30 and 300 for
AG-UI and MCP, 600 and 600 for a webhook. A refused call gets 429 with a retry time, before
any session is opened, and only calls that would start a turn count. Members are bound by the
platform’s own per-user ceiling instead.
Every session an endpoint opens runs in the organization’s scope and appears on the
Sessions page for every member. One an AG-UI or MCP caller opened records the connection it
came through and, under oidc, the caller’s subject.
The AG-UI endpoint
Section titled “The AG-UI endpoint”An AG-UI client posts a RunAgentInput to the address and reads the turn as an AG-UI event
stream (server-sent events, or the protocol’s binary encoding when Accept asks for it):
curl -N "https://<host>/api/agui/<token>" \ -H "Authorization: Bearer amx_..." \ -H "Content-Type: application/json" \ -d '{"threadId":"","runId":"r-1","tools":[],"context":[], "messages":[{"id":"m1","role":"user","content":"Where is my order 4711?"}]}'- The platform owns the thread id. The stream’s
RUN_STARTEDevent carries the one to send next; a value it did not issue to this caller opens a fresh chat. - A message continues the chat where its previous turn left off; it does not replay
history. While a turn is still running, or the chat waits for a decision, a new message
is refused with
409. - A turn that parks ends its stream with a
RUN_FINISHEDevent whose outcome describes the pending decision or wait. Aresumeentry naming it resolves it as the platform’s own surfaces would: it records the decision, or delivers the firing it names. - Client-supplied
toolsandcontextare not honoured, and the stream says so. An external caller cannot attach uploaded files. - A workflow that runs another one as a child session
reports it as
archmax.sub_workflow_startandarchmax.sub_workflow_resultcustom events, and frames the child’s messages witharchmax.sub_workflow_frame. Each names the child session by itsdispatchid:2for the session’s second dispatch,1~1for the first one made inside dispatch1. A dispatch made inside another one also names it asparent. Treat the id as an opaque string, unique within the turn.
Chats an endpoint opens appear in no member’s chat history.
The MCP endpoint
Section titled “The MCP endpoint”An MCP client connects to the address over Streamable HTTP; the endpoint keeps no MCP
session. It lists one tool per workflow it serves, named after the workflow’s slug and
described by the trigger’s description. The tool’s input schema comes from the trigger’s
requires, and its result carries the trigger’s returns:
states: refund: triggers: mcp: connection: partner-agents description: Refund one order and report the amount. requires: - { name: order_id, type: string, description: The order to refund. } returns: - { name: total, type: number }Every call opens a new session at the mcp entry with its arguments as locked variables,
and answers when the turn settles: status (succeeded, awaiting_decision,
awaiting_input, failed, cancelled), a message, and on success the returns. When the
platform stops waiting first, the status is running and the session carries on. A
non-conforming argument, a workflow out of service or a reached spend cap is a tool error,
and no session opens. trace: true on the trigger adds the session’s steps and tool calls
to every result. An MCP call takes no files: an mcp trigger declaring a type: file entry in
requires or returns is a validation error, and its deployment is in error, so the endpoint
does not list its tool. See
the signature.
A refused request gets 401 with a Bearer challenge; under oidc it names the endpoint’s
protected resource metadata, /api/mcp/<token>/.well-known/oauth-protected-resource.
The webhook endpoint
Section titled “The webhook endpoint”A sending system POSTs to the address; 202 answers with { "delivery": "<id>" }, and the
firing is processed off the request. The firing’s payload holds the method, the
content-type, user-agent and x-request-id headers, the query and the body (parsed
when it is JSON, at most 256 KiB). An X-Delivery-Id header names the delivery, so a
sender’s retry fires once; without it, the body’s digest serves as its id. Payload fields,
trigger guards and testing a webhook are on Triggers.