Vend an endpoint
New to switchboard? Sign in and vend your first endpoint walks through the web wizard and the CLI step by step. This page is the reference for what an endpoint is and what it can be granted.
What an endpoint is
An endpoint is a scoped MCP endpoint switchboard vends to one agent. It is the agent's only door into switchboard, and it is the capability grant. Vending produces two things that always travel together:
- A URL —
https://<host>/mcp/<slug>— the agent's private MCP address. - A credential — a bearer token of the form
sbk_…, stored hashed and shown to you once at vend time.
Possessing the URL and the credential is the access. The URL alone is not a secret; the credential is. Switchboard serves the endpoint over Streamable HTTP only — the agent connects with URL + bearer and nothing else. There is no local binary to install.
An MCP client that supports OAuth can connect with the URL alone instead: switchboard's consent screen issues it a token for that one endpoint, and no long-lived credential is stored on the client.
What an endpoint is scoped to
Every endpoint carries a scope you set at vend time. An agent can never widen its own scope.
-
Queues — the set of queues this endpoint may see and act on. Queue names are scoped to the endpoint: two endpoints'
inboxqueues are unrelated. -
A verb allowlist — the MCP tools the endpoint may call. Each tool is gated by the verb of the same name:
Group Verbs Todos list_todos,get_todo,claim,claim_next,complete,fail,release,heartbeatWebhooks create_webhook,list_webhooks,rotate_webhook,delete_webhookFan-out routes add_webhook_route,list_webhook_routes,remove_webhook_routeRouting rules list_webhook_rules,set_webhook_rules,add_webhook_rule,update_webhook_rule,move_webhook_rule,remove_webhook_rule,test_webhook_rulesEvent history list_webhook_events,get_webhook_event,replay_webhook_eventDefault lease get_default_lease,set_default_leaseOutbound HTTP calls (notify hooks) create_notify_hook,list_notify_hooks,rotate_notify_hook,delete_notify_hookThe notify-hook verbs let the agent register an HTTPS URL that Switchboard POSTs a signed notification to when the endpoint's work is ready. Switchboard then dials a host the agent chose, so these verbs are never part of any default grant. The wizard and quick vend list them as their own "Outbound HTTP calls" group, unticked.
create_notify_hookreturns the Standard Webhooks signing secret (whsec_…) once.list_notify_hooksshows each hook's health, and never a secret or a URL's query string. No vend path grants them by default: name them in--verbs, or tick them in the wizard.The web wizard pre-checks the eight todo verbs, and so does
switchboard endpoint vend: with no verb flags it grants those eight, plus the two verbs that read and set the endpoint's own default lease, and nothing else (ADR-0047) — the credential a lane holds should be what the lane does. Ask for more with--verbs, naming verbs and/or the presetstodo,webhook-adminandall, or add the webhook, routing and event groups with--allow-webhook-admin;endpoint listshows what each lane ended up holding.list_todosalso grantsget_todo, so an endpoint vended beforeget_todoexisted has it.releasechanges state, so no other verb grants it: an older endpoint needs a re-vend to get it. The default-lease verbs let the agent read and change its own endpoint's default lease (below).switchboard endpoint vendgrants them, because a claim can already ask for the same lease on the call; the wizard leaves them unticked, and a friend endpoint can never hold them. -
A webhook ceiling — how many webhooks the endpoint may create, which source types (
github,gitea,cairn,generic;stripeandslackexist but aren't usable yet), and which queues those webhooks and their routing rules may target. A ceiling of 0 disables webhooks. -
A lifetime — until revoked, or a duration after which the endpoint expires on its own.
The endpoint enforces this scope at the boundary on every call: verbs outside the allowlist and queues outside the grant are denied.
The default claim lease
Every endpoint also has a default claim lease: how long a claim, claim_next or heartbeat
holds a todo when the call passes no lease_ttl_seconds. Left blank, it is the server default, 300
seconds. Set it when the endpoint's jobs run longer than five minutes, such as a model reviewing a
pull request for half an hour: then a worker that forgets lease_ttl_seconds keeps its todo, and a
bare heartbeat extends by your default instead of cutting the lease back to 300 seconds.
- It is whole seconds from 60 to 86400 (24 hours). The web forms and the CLI also take a duration
like
45mor1h. A value out of range is refused, never rounded to the nearest bound. - A
lease_ttl_secondson the call still wins, up to 86400. - It is not scope, so you can change it at any time without re-vending: on the endpoint's card,
with
switchboard endpoint edit SLUG --lease-ttl 1h(--lease-ttl defaultresets it), or withPATCH /api/v1/endpoints/{ref}. A change applies to the next claim or heartbeat; leases already granted keep their expiry. - The agent sees the number: its session instructions and its
claim,claim_nextandheartbeatdescriptions state the endpoint's default. An endpoint grantedset_default_leasecan change its own default; it can never change another endpoint's.
A longer default also means a crashed worker's todo waits longer before another worker gets it, because the todo is requeued only when the lease lapses. Pick the shortest lease that covers a job.
How to configure and vend one
-
Open Endpoints on the web board and choose + vend endpoint (the six-step wizard) or quick vend (one page, no webhook ceiling). Both take an optional default claim lease (the wizard asks on its lifetime step).
-
Name the agent, then choose its queues, verbs, webhook ceiling, and lifetime. Naming the agent registers it; registration alone grants nothing.
-
Vend, and copy the reveal. It shows the MCP URL, the credential, and the MCP client configuration exactly once — for a Claude Code–style client, an
.mcp.jsonentry:{"mcpServers": {"switchboard": {"type": "http","url": "https://<host>/mcp/<slug>","headers": { "Authorization": "Bearer sbk_…" }}}}
The agent can now drain its queues with list_todos / claim / complete.
Store the credential without printing it
The CLI can vend the same thing without the credential ever reaching the screen or a terminal
scrollback. --json prints the raw API response — the credential inside it — so capture it
straight into a file only you can read:
umask 077
switchboard endpoint vend my-agent --queue inbox --json > vend.json # created 0600
jq -r .mcp_json vend.json # the client wiring block, still containing the token
Then move the credential where your secrets live — pass it to op / pass / your secret store
from the file, never as a shell argument or an echo — and delete vend.json:
op item create --category=password --title switchboard-my-agent \
--password "$(jq -r .token vend.json)" && rm -f vend.json
Nothing in this path prints the token: vend --json writes to the file, the store reads the file,
and endpoint list never shows credentials at all. If a credential does end up somewhere it
should not be — a log, a transcript, a shared paste — the credential is compromised: revoke the
endpoint and vend a fresh one
(Operator CLI and API).
What you use an endpoint for
- Give an agent least-privilege access to exactly the queues and verbs its job needs — nothing more.
- Attribute every action. Every vended endpoint belongs to exactly one agent, which belongs to exactly one human. Every todo, webhook, or rule change carries that chain.
- Revoke instantly. Revoking an endpoint invalidates its stored credential and closes its live MCP sessions — the agent immediately loses all access, with no residue. Revoke = kill the endpoint.
Scope is immutable to shrink — widen it to grow
An endpoint's scope is immutable in the direction that removes power: a given URL + credential always means one fixed set of powers, and nothing edits that set downwards. To take something away from an agent, vend a new endpoint with the new scope and revoke the old one, rather than editing the live grant. The rotate button on an endpoint card starts the wizard pre-filled from the old scope. This keeps every capability trivial to audit — there is no "when did this scope change, and who changed it?" question, because a reduction is a new endpoint with its own reveal.
The direction that only adds has its own path, because re-vending is a bad trade there: a webhook
belongs to the endpoint that created it, so a re-vend mints a new ingest URL and signing secret and needs
an edit in the producer's hook configuration — for a change that breaks no route that works today.
switchboard endpoint scope widen SLUG adds an ingest queue, a source type or a verb, or raises the
webhook ceiling; switchboard endpoint scope add-queue SLUG QUEUE is that command with one flag. It
shows the old and the new grant and asks before writing anything, and the endpoint's credential is not
touched, so the lane keeps authenticating with the token it already has. Every field a widen moves is
recorded beside the change, with the value it replaced. See
ADR-0049 — Add-only endpoint scope widening.
The queues an endpoint may claim (its --queue at vend) are not reachable from there: that decides
which work the lane can take, so it stays a vend-time choice.
Next
- Connect it: Connect an agent over MCP.
- See the work surface itself: Drain the queue.
- Give one agent several least-privilege faces: Personas.
Deeper detail: ADR-0008 — Human principal + vended endpoints, ADR-0017 — MCP over Streamable HTTP only, and the vended-endpoints spec.