Skip to main content
Flow runs in your Node process. Host an MCP server behind HTTPS, or run a messaging worker with a durable database. You choose the model, messaging provider and observability system.

Before you start

Use Node 22.18 or later and a project from the quickstart. Install its locked dependencies with npm ci. Keep agent/, src/ and the package files in the deployed application; TypeScript source runs directly on Node.

Start a production process

The starter’s npm run mcp binds to loopback for local development. Add this entry point to listen on the container or server’s network interface:
src/serve-mcp.ts
Start it with:
Terminal
Put a TLS reverse proxy or load balancer in front of the process. Preserve the MCP paths and OAuth discovery routes, and allow streaming responses. Connect remote hosts to https://your-domain.example/mcp; plugins use /mcp/plugin.Add the MCP authentication configuration before exposing account data. A public listener is not an authentication boundary.
Check it worked: curl http://127.0.0.1:8080/health returns ok. Then make a real tool request or send a test message; a healthy listener alone does not prove the integration works.

Persist conversations

Messaging state includes history, pending messages, background tools, scheduled messages and the agent’s own records. The default database is in memory and is lost on restart. With a custom buildAgent, pass the database through host: options.host to createAgent, as the starter does. Here is a Postgres host configuration fragment; pool is your application’s node-postgres pool:
Postgres host configuration
Call await agent.resume() before accepting messages with a durable database. Cut-off turns run again; a tool that was running is reported as interrupted rather than silently executed again.
Pass context.idempotencyKey through to your backend’s idempotency mechanism for writes. Flow supplies the same key for the same tool input in a retried turn; your backend enforces one write.

Handle retries and restarts

Pass the provider’s message id as messageId to agent.message(). A retried webhook with that id is handled once. Ids are kept for seven days by default (keepMessageIdsDays). Flow Messaging’s adapter supplies these ids for you. Run one steady-state messaging instance per database, kept warm with CPU available for timers. Conversation leases protect deployment overlap; a dead copy’s lease expires after 15 seconds. They are not a substitute for verifying multi-instance steady-state operation. Keep the process under a supervisor, retain logs and alert when its messaging stream stops. On release, stop routing new work to the old process and allow active work to finish before termination. agent.status() reports activity and idle time.

Production checklist

  • Store secrets in your hosting platform’s secret store; never bake .env into an image.
  • Use live messaging senders for real customers, not shared trial numbers.
  • Keep the local playground private; the entry points above do not serve it.
  • Back up the database and test restoring it. Never share a SQLite file across machines.
  • Exercise restart recovery, a retried webhook and a slow tool before sending customer traffic.
The MCP server and tool CLI need no Flow account. Using Flow’s models, Messaging or scenario-test cloud remains optional and uses the credentials for those services.

Inspect traces

Connect runtime events to your observability system.

Deploy on Flow instead

Let Flow supply the host and durable store.