createFxbot
createFxbot(options), from @fxbot/sdk, opens fxbot's database, brings it up to date, and resolves to the fxbot object.
import { readFileSync } from "node:fs";
import { createFxbot } from "@fxbot/sdk";
const fxbot = await createFxbot({
databaseUrl: "postgres://fxbot:<password>@127.0.0.1:5432/fxbot",
secretKey: readFileSync("/path/to/secret.key", "utf8"),
});To add the SDK to a project, see Use the SDK in a project.
Requirements
| Needs | Why |
|---|---|
| Node 22.18 or newer | The package ships TypeScript source, which Node runs without a build. |
| Postgres with the pgvector extension available | Every record lives in Postgres. Migration 0005_memories creates the vector extension when the database lacks it. It stops with a message when the server has no pgvector, or when the extension is missing and fxbot's database role is not a superuser. |
| A key of 32 random bytes, in base64 | It seals every stored key and token. openssl rand -base64 32 makes one. |
pg_dump and tar on the PATH |
For the backup before migrations, when the database already holds fxbot's records. |
Options
FxbotOptions. Only databaseUrl and secretKey are required.
| Option | Type | Default | What it does |
|---|---|---|---|
databaseUrl |
string |
fxbot's Postgres. Every record lives there. Keys and tokens are stored only sealed. | |
secretKey |
Buffer or string |
The 32 bytes that seal keys and tokens: a Buffer, or the base64 text of the key file. A key of another length throws. |
|
vercelClientId |
string |
None | fxbot's Vercel OAuth app, for signing in with a Vercel account. Without it, a Vercel sign-in fails with 400. |
dataDir |
string |
data |
Where libfx keeps each chat's session files, under sessions/. A relative path is taken from the working directory. |
backupsDir |
string |
backups |
Where a backup goes before migrations change a database in use. |
version |
string |
0.0.0 |
The running version, for release(). |
releasesUrl |
string |
None | Where the newest stable release is read, in the shape of GitHub's releases/latest. It is read at start and once a day. Without it, nothing is asked. |
fetch |
typeof fetch |
globalThis.fetch |
The fetch for fxbot's own requests: sign-ins, model lists, key checks, MCP servers, the registries, skills, embeddings, and the release check. Turns use libfx's own fetch, except on a Vercel account and OpenCode. |
localUrl |
string |
http://127.0.0.1:8787 |
The server's own origin on this machine. An MCP sign-in with a loopback redirect comes back to <localUrl>/callback. |
clientMetadataUrl |
string |
None | The project's published OAuth client ID metadata document, for MCP servers that sign in with one. Without it, fxbot registers itself with each server that allows it. |
registryUrl |
string |
https://api.mcp.github.com |
The MCP registry that registry entries come from. It is mirrored into Postgres for search. |
everythingUrl |
string |
https://registry.modelcontextprotocol.io |
The official MCP registry. It is asked only when a search asks for everything. |
listsUrl |
string |
https://fxbot.sh |
The site that publishes fxbot's own lists, <listsUrl>/mcp-registry.json and <listsUrl>/skills-registry.json. They are read hourly. Until a read succeeds, fxbot uses the lists this release shipped with. |
syncRegistry |
boolean |
true |
false skips the registry sync at start. In 0.3.0, the hourly sync still runs. |
embedUrl |
string |
None | The machine's local embedder, an OpenAI-style API such as http://embed:8080/v1, for memory search. Trailing slashes are dropped. Without it, there is no local embedder. |
How fxbot's server sets them
| Option | From |
|---|---|
databaseUrl |
FXBOT_DATABASE_URL |
secretKey |
The file named by FXBOT_SECRET_KEY_FILE |
vercelClientId |
FXBOT_VERCEL_CLIENT_ID |
dataDir |
FXBOT_DATA |
backupsDir |
FXBOT_BACKUPS |
version |
version in the root package.json |
releasesUrl |
FXBOT_RELEASES_URL, or GitHub's releases/latest for the repository in the root package.json. None when FXBOT_UPDATE_CHECK is off. |
localUrl |
http://127.0.0.1:<FXBOT_PORT> |
clientMetadataUrl |
FXBOT_CLIENT_METADATA_URL |
registryUrl |
FXBOT_MCP_REGISTRY |
everythingUrl |
FXBOT_MCP_EVERYTHING |
listsUrl |
FXBOT_LISTS_URL |
embedUrl |
FXBOT_EMBED_URL |
The server leaves fetch and syncRegistry at their defaults. The variables are in Configuration.
What it does when called
In order:
- Reads
secretKey. - Connects to Postgres and runs the migrations it hasn't run. See Migrations. If they fail, it closes the connection and throws.
- Starts the release check, when
releasesUrlis set: at once, then once a day. - Starts the registry sync, unless
syncRegistryisfalse: fxbot's two lists and the mirror ofregistryUrl. It runs again every hour. - Loads the MCP servers and skills in Add-ons. The skills' repositories are checked for changes a minute after start, then hourly.
- Starts one libfx agent per provider, each with every bot tool. A provider whose agent doesn't start, such as one whose secret doesn't open, lists with an
error. The others run. - Starts filling in the vectors that memories and messages lack, in the background.
- Connects the MCP servers, in the background.
- Resumes the turns a stopped process left open, for each bot with a chat whose provider runs. Each reply is saved as usual.
Migrations
- The schema is the numbered SQL files in
packages/sdk/src/migrations/. 0.3.0 has0001_baselineto0005_memories. - Each file runs once, in order of its name, and is recorded in the table
fxbot_migrations. - All pending files run in one transaction. If one fails, none of them is kept, and the error names it.
- The transaction holds an advisory lock, so two processes that start at once take turns.
- When the database already holds fxbot's records, a backup is made before anything changes. It goes into
<backupsDir>/<time>-before-<first pending migration>/:database.dump, frompg_dump --format=custom, anddata.tar.gz, fromdataDirwhen it exists. The newest five backups are kept. If the backup fails, nothing is migrated. - A database that has a migration this release doesn't know was migrated by a newer release.
createFxbotrefuses it, and says to update or restore the backup taken before that update.
Errors
A call that fails on purpose throws an Error with a status, so a server can answer with the same status.
status |
When |
|---|---|
| 400 | Bad input, or a request fxbot refuses, such as a message to a bot with no provider |
| 404 | A missing bot, or a missing provider, memory, library item, add-on, or sign-in |
| 409 | An add-on changed since its preview, or a skill is already added |
| 502 | A service fxbot asked failed: a device code sign-in, a model list, a registry, an MCP server, or the summary for a provider switch |
An Error without a status is unexpected. fxbot's server answers it with 500.
Stopping
close() stops the timers, closes the MCP connections, and closes each provider's agent, which waits for the turns this process started. Then it ends the Postgres connection.
In 0.3.0, close() doesn't wait for the save of a reply that just finished. The reply and the bot's preview are written after the turn ends, so a script that calls close() right after a turn can reach a closed database. Keep the app running between turns. A fix is planned.