mentionable.dev

Deployment Patterns

Single-line summary: Deploy Mentionable as a standalone Node service via @mentionable/node, embed into an existing web framework with one import, or run serverless on Vercel with a Postgres-backed KvStore + cron outbox.

See also: architecture-overview, transport-module-guide, webfinger-agent-card-guide, building-a-connector, glossary

Examples: examples/echo-agent, examples/gmail-echo-agent, examples/gmail-echo-vercel, examples/llm-agent-vercel, examples/embed-{next,express,hono,fastify,node-headless}, examples/slack-connector.

Standalone (Headless @mentionable/node)

The simplest deployment: a Node process that hosts WebFinger, the Agent Card, and the configured Transport modules.

import { createMentionable } from '@mentionable/node'
import { activityPub } from '@mentionable/transport-activitypub'
import { a2a } from '@mentionable/transport-a2a'
import { rest } from '@mentionable/transport-rest'

const mn = createMentionable({
  domain: 'example.com',
  agents: [
    {
      address: '@scheduler@example.com',
      handle: schedulerAgent.handle,
      card: schedulerCard,
    },
  ],
  transports: [activityPub(), a2a(), rest()],
})

mn.listen(3000)

Reference: examples/echo-agent (~30 LOC) and examples/embed-node-headless (~40 LOC).

Embedded (Existing Frameworks)

@mentionable/node exports a request handler you mount under your existing framework. WebFinger goes at the apex, everything else under basePath.

FrameworkExampleMount pattern
Next.jsexamples/embed-nextapp/api/.well-known/webfinger/route.ts + app/api/[[...mentionable]]/route.ts
Expressexamples/embed-expressapp.use(mentionable.handler)
Honoexamples/embed-honoapp.route('/', mentionable.handler)
Fastifyexamples/embed-fastifyapp.register(mentionable.fastifyPlugin)

basePath rule (see webfinger-agent-card-guide#basepath): WebFinger is always served at /.well-known/webfinger. Other endpoints (A2A, REST, AP inbox) MAY live under any prefix.

Vercel Serverless

The reference serverless template is examples/llm-agent-vercel — a noncoded full-stack LLM agent: Deploy-to-Vercel → Neon Postgres auto → /setup UI → ready.

ConcernVercel solution
Fedify KvStore@fedify/postgres — DO NOT use unstable_cache or in-memory; the function dies between invocations.
HistoryStorePostgres table keyed by thread_id.
Outbox / queued AP deliveryVercel Cron job that drains pending activities.
Agent secrets (API keys, DKIM key)Vercel env vars; configured in /setup then persisted via vercel env add.
OAuth (Gmail, etc.)OAuth client secrets in env; redirect URL pinned to the Vercel deployment URL.
Pub/Sub for Gmail inboundGoogle Pub/Sub push subscription → /api/gmail/inbound.

Important Vercel-specific gotcha (from feedback_next_bundler_externalize.md): packages with internal this.* dispatch (Fedify, some Postalsys modules) need serverExternalPackages in next.config.js, otherwise Next.js’s bundler silently breaks the dispatch at runtime.

Key Env Vars

VariablePurposeExamples
MENTIONABLE_DOMAINCanonical agent host.example.com
MENTIONABLE_BASE_URLPublic HTTPS base URL of this deployment.https://example.com
MENTIONABLE_AGENT_SIGNING_KEYEd25519 PKCS8 PEM (for Agent Card signing).(PEM body)
MENTIONABLE_AGENT_PREVIOUS_KEYSOptional grace-period keys, JSON array.[{"kid":"2026-04",...}]
GMAIL_CLIENT_ID / GMAIL_CLIENT_SECRETGmail OAuth client.(per-deployment)
GMAIL_PUBSUB_TOPICPub/Sub topic for inbound Gmail watch.projects/X/topics/gmail-inbound
GMAIL_PUBSUB_SUBSCRIPTIONPush subscription target.projects/X/subscriptions/gmail-push
DKIM_PRIVATE_KEY / DKIM_DOMAIN / DKIM_SELECTOROutbound email signing.mn._domainkey.example.com
A2A_BEARER_JWT_JWKS_URIA2A bearer-jwt issuer JWKS.(per-deployment)
OPENAI_API_KEY / ANTHROPIC_API_KEYLLM Harness backend.(per-agent)

The hosting-service embedder pattern (used by llm-agent-vercel) injects OAuth client secrets and Pub/Sub topic IDs from the operator’s GCP, so per-tenant users skip the GCP setup step.

Examples Map

ExampleUse caseNotable pieces
echo-agentMinimum Agent interface + transport modules.~30 LOC reference.
embed-node-headlessMinimal embed via @mentionable/node.~40 LOC reference.
embed-{next,express,hono,fastify}One-file mount in existing web app.Per-framework patterns.
gmail-echo-agentLong-running Node + Gmail API transport.Pub/Sub watch, DKIM outbound.
gmail-echo-vercelAbove, but serverless on Vercel.@fedify/postgres, Vercel Cron outbox.
llm-agent-vercelNoncoded fullstack LLM agent.Deploy-to-Vercel button, /setup UI, Neon, two modes (system-prompt or gitagent repo URL).
slack-connectorSlack workspace /agent slash command → all Mentionable agents.Slack request signing, A2A dispatcher, mention_relay: 'inline' override.

gitagent Mode B

examples/llm-agent-vercel’s /setup accepts a gitagent repo URL. The flow:

  1. User pastes repo URL.
  2. @mentionable/repo-analyzer reads the repo, produces an AgentProposal.
  3. @mentionable/gitagent-mapping maps the proposal into Mentionable address-space + system prompt + tool surface (MCP via @mentionable/mcp-builtins).
  4. The deployed agent now answers as that gitagent persona at @<repo>@<vercel-host>.

This is the noncoded path — operators do not write code, they paste a repo URL or a system prompt.

Local Development

pnpm install
pnpm -r run build      # build all packages
pnpm -F examples/echo-agent dev

For Vercel local development with Postgres-backed KvStore: vercel dev with vercel env pull .env.local after linking the project. The vercel:bootstrap skill / omc bootstrap flow handles linking and env provisioning safely.

CI Considerations

Per CLAUDE.md, the build CI matrix (typecheck / test / lint / format:check / e2e-phase1 / e2e-phase2a) MUST be green before merge. Three things break PRs the most:

Common Mistakes