The engine reads one JSON file, engine.json. basalt init writes it and updates it each time you run init. You rarely edit it by hand. This page lists every key, so you know what a value does when you see it.
Where the files live
Section titled “Where the files live”| What | Linux | macOS |
|---|---|---|
| Engine config (default) | /etc/basalt/engine.json |
/Library/Application Support/Basalt/engine.json |
| Agent sockets and the person socket | /run/basalt/ |
/Library/Application Support/Basalt/run/ |
State directory (stateDir) |
/var/lib/basalt |
/Library/Application Support/Basalt/state |
| The agent’s connection string | <config dir>/agents/NAME.url, mode 0600 |
<config dir>/agents/NAME.url, mode 0600 |
If you run init with --config, --socket-dir or --credential-file, the engine runs as you in the foreground. Init writes the config and the credential file itself, under your config directory, and prints the one basalt engine --config ... command. Without them, init offers to install the engine as a background service. The connection string with the agent’s password goes into the credential file, never into engine.json.
An example
Section titled “An example”{
"socketDir": "/run/basalt",
"mode": "SERVICE",
"personUids": [501],
"pagesUrl": "http://localhost:8787",
"limits": { "statementTimeoutMs": 5000, "readRowLimit": 1000 },
"agents": [
{
"name": "demo_bot",
"osUser": "imantumorang",
"credentialFile": "/etc/basalt/agents/demo_bot.url",
"initArgs": ["--agent=demo_bot", "--write=basalt_demo.leads,basalt_demo.lead_notes"]
}
]
}
Top-level keys
Section titled “Top-level keys”| Key | Type | Default | What it does |
|---|---|---|---|
socketDir |
string | the path in the table above | Holds one socket per agent, <socketDir>/<name>.sock. Required. |
agents |
array | One entry per agent. At least one. See Agent keys. | |
limits |
object | see below | The read row limit and the time limit. |
stateDir |
string | the path in the table above | Where the engine keeps each agent’s last verified ledger chain head (<stateDir>/<agent>.head.json, mode 0600) It verifies from that head on start and every hour. |
pagesUrl |
string | http://localhost:8787 |
The base URL of the approval, undo and passkey pages. The page origin, and so the passkey’s origin, is this URL. The older key approvalPage is still read, origin only. |
pagesAddr |
string | 127.0.0.1:<port of pagesUrl> |
Where the engine serves those pages on loopback. "off" turns them off. A non-loopback address is refused. If the port is taken the engine refuses to start and names it. |
linkBudget |
integer | 1800 |
The longest long link, in characters, that the engine hands an agent as the way to open a page. Short links are never measured. |
operatedBy |
string | PERSON |
PERSON or AGENT: who runs machine steps on the engine’s machine. See A bot on its own computer. |
mode |
string | SAME_USER |
SERVICE when init installed the background service, else SAME_USER. Only SERVICE opens the person socket. |
personUids |
array | none | OS user ids that may use the person socket. Init records yours. An empty list admits nobody. |
directAddr |
string | off | A loopback address that a tunnel of yours forwards to, for the direct transport. "off" or empty is off. Only with the portal as pagesUrl. |
vault |
string | OFF |
ON or OFF. Whether the engine dials out to the Vault for portal short links. |
vaultUrl |
string | the Vault | Overrides the Vault’s address, for development and tests only: a ws:// URL on a loopback address. |
devLocalPages |
boolean | false |
Lets an agent-operated engine use local pages, for development only. Every personMessage then carries a warning. |
pii |
object | see below | Sizes the classification dictionary. See Column classes. |
With operatedBy: AGENT, pagesUrl is the hosted portal, because the loopback pages would belong to the bot’s machine.
Limits
Section titled “Limits”| Key | Default | What it does |
|---|---|---|
statementTimeoutMs |
5000 |
The time limit on a query. The agent role has its own limit, --statement-timeout on basalt init (30 seconds by default), which also covers preview_revert. Between 1 ms and 10 minutes. |
readRowLimit |
1000 |
The most rows a query may return. Between 1 and 100,000. A query over it is QUERY_TIMEOUT. |
Agents never set limits. The numbers in context: Limits and defaults.
Column classes
Section titled “Column classes”| Key | Default | What it does |
|---|---|---|
pii.maxMemoryMB |
512 |
The memory budget of the classification dictionary. The engine sets GOMEMLIMIT to twice this unless the environment sets it. |
pii.scanRowsPerSecond |
20000 |
How fast the engine scans your tables to build the classification dictionary. |
basalt service install writes the service’s memory limits from maxMemoryMB at install time. After raising it, run basalt service install again with the same flags so the unit is rewritten.
Agent keys
Section titled “Agent keys”Each entry of agents has:
| Key | What it does |
|---|---|
name |
The agent’s name: lowercase letters, digits and _. Its role is <prefix>_agent_<name>. person is reserved. |
osUser |
The OS user the agent runs as, the only one allowed on its socket. Defaults to you at init. |
credentialFile |
The file that holds the agent’s connection string. Mode 0600, owned by the engine’s user. |
initArgs |
The flags basalt init was run with, saved as strings. Every “run init again” step uses exactly these, plus the one change it is for. |
setup |
A pending setup from your laptop: setupId, kind, guardVersion, expiresAt, code and fingerprint. Removed once the setup runs. Nothing secret. |
initArgs saves a flag only when its value is not the default, except --agent and --os-user. It never holds the admin connection string, --database-url or a one-shot flag such as --yes, --dry-run or --rotate-password. A value that is a connection URL or holds password= is refused.
Environment variables
Section titled “Environment variables”| Variable | Used by | What it holds |
|---|---|---|
BASALT_ADMIN_DATABASE_URL |
init, uninstall, passkey remove, classify |
Your admin connection string. Without it these commands ask at a hidden prompt. It is never written anywhere. |
BASALT_DATABASE_URL |
log, approve, revert, passkey, upgrade |
An agent connection string, in same-user mode. A flag always wins over it. |
BASALT_ADMIN_DATABASE_URL must be a postgres:// or postgresql:// URL. A keyword and value string is refused before init connects. basalt init --remote ignores it, on purpose.
Names in your database
Section titled “Names in your database”| What | Name |
|---|---|
| Prefix | basalt, set with --prefix. |
| The guard’s schema | basalt_meta, with its owner role <prefix>_guard. |
| An agent’s role | <prefix>_agent_<name>. Through Supabase’s pooler, <prefix>_agent_<name>.<ref>. |
| The group of agent roles | <prefix>_agents. |
An agent role must be a plain role. Init refuses an existing role that is a superuser, can create roles or databases, bypasses row-level security, belongs to any role other than <prefix>_agents, or owns objects in the database. A role name is at most 63 bytes.
The connection string init builds
Section titled “The connection string init builds”Init builds the agent’s connection string from yours. It keeps the scheme, hosts, ports and database, swaps in the agent’s user and password, and keeps only these parameters: host, port, dbname, sslmode, sslrootcert, sslcrl, sslcertmode, sslnegotiation, sslsni, channel_binding, require_auth, target_session_attrs, connect_timeout, application_name, min_protocol_version, max_protocol_version and default_query_exec_mode. It drops every other parameter, among them user, password, passfile, service, servicefile and your TLS client identity (sslcert, sslkey, sslpassword). sslrootcert and sslcrl are file paths. After basalt service install, the engine’s OS user must be able to read them.
Check what is set
Section titled “Check what is set”Run basalt status --agent NAME. It prints the config path, whether the engine runs, the socket and state directories, the pages URL, operatedBy and each problem with its fix. It never prints the credential file’s contents. See CLI.
BasaltDB · Apache-2.0