Skip to content

Configuration: dashboard, mesh and optional layers ​

This page lists every agentx.json setting for the dashboard, the mesh (other AgentX machines), voices, screen capture and the optional layers: business, boards, the intent graph and typed decisions. For the other sections, see the Configuration reference.

Each table gives the key, the kind of value it takes (its type), the value used when you leave it out (its default), and what it does. "required" means the file is rejected without it. A <id> in a heading is a name you choose.

dashboard ​

The dashboard is the web page served by agentx board serve. See Dashboard.

KeyTypeDefaultWhat it does
dashboard.enabledbooleanfalseTurns the dashboard server on.
dashboard.portnumber4202Port the dashboard listens on.
dashboard.bindstring"127.0.0.1"Address the dashboard listens on. Keep it local unless a reverse proxy sits in front (your own address).
dashboard.tokenstring—Bearer token required for changes made through the dashboard. Unset means changes need no token.
dashboard.daemonUrlstring"http://localhost:18800"The main daemon the dashboard reads live data from.
dashboard.daemonslist of objects[]Extra daemons to show, beyond the peers the main daemon already knows.
dashboard.draftAgentstring—Agent that drafts text when you create an issue from a board.

Each entry in dashboard.daemons:

KeyTypeDefaultWhat it does
namestringrequiredLabel shown for that daemon.
urlstringrequiredThat daemon's HTTP address.
dashboardUrlstring—That machine's dashboard address, used to pass settings changes through. Defaults to url with the port changed to 4202.
tokenstring—Bearer token for that daemon's API.
dashboardTokenstring—Bearer token for that machine's dashboard. Defaults to token.

mesh ​

The mesh links several AgentX machines so their agents can reach each other. See Add a second machine.

KeyTypeDefaultWhat it does
mesh.enabledbooleanfalseTurns the mesh on.
mesh.peerslist of objects[]The other machines this one talks to.
mesh.inboxeslist of objects[]Named inboxes that other machines may send work to. None are published until you add one.
mesh.discovery"static" | "mdns""static"How peers are found. Only static (the mesh.peers list) is used today.
mesh.healthCheck.intervalnumber60Seconds between checks that each peer is up.
mesh.healthCheck.timeoutnumber10Seconds to wait for a peer before counting it as down.
mesh.feed.enabledbooleantrueFollow the events of every reachable peer and show them in this machine's event feed. See Events from other machines.
mesh.feed.skipTypeslist of strings["task:step"]Event types peers leave out of the feed they send this machine. The default skips per-step agent activity. A change applies when this machine next reconnects to each peer.
mesh.delegation.asyncWhenHumanbooleantrueWhen a person started the conversation, an agent that asks another agent gets its answer later, as a new message, instead of waiting. See When an agent asks another agent. Applies without the mesh too.
mesh.delegation.timeoutMinutesnumber30Minutes a helper agent has to answer before the asking agent is told it timed out. From 1 to 240.

Each entry in mesh.peers:

KeyTypeDefaultWhat it does
urlstringrequiredThe peer's daemon address.
namestringrequiredThe peer's name.
tokenstring—Bearer token sent to that peer. Use an ${ENV_VAR} reference.

Each entry in mesh.inboxes:

KeyTypeDefaultWhat it does
namestringrequiredInbox name other machines see.
agentstringrequiredLocal agent that handles it. Not shown to other machines.
enabledbooleantrueWhether the inbox accepts work.

events ​

The daemon keeps its most recent events in memory so a late reader can catch up. See Events.

KeyTypeDefaultWhat it does
events.ringSizenumber1000How many recent events GET /events/recent can return. Older ones are dropped. Nothing is written to disk.

voice and meshVoices ​

How agents speak aloud. See Desktop assistant.

KeyTypeDefaultWhat it does
voice.provider"system" | "elevenlabs""system"Speech engine: the free system voices, or ElevenLabs.
voice.fallback"system" | "none""system"What happens when ElevenLabs cannot speak: use the system voice, or stay silent.
voice.systemstring or map of strings—System voice for agents without their own. A name, "system" for the OS default, or one per language such as { "en": "Samantha", "fr": "Thomas" }. Unset gives each agent its own.
voice.localestring"en"Language used when voices are assigned, for example "fr-FR".
voice.listenerstring—What agents call you, for example a first name. Unset means "the user".

meshVoices.<agent> sets the voice of an agent that runs on another machine, keyed by that agent's id. This machine speaks for it, so the other machine needs no ElevenLabs key. Unset fields come from the agent's card.

KeyTypeDefaultWhat it does
namestring—What to call the agent aloud.
provider"system" | "elevenlabs"—Speech engine for this agent. Overrides voice.provider.
systemstring or map of strings—System voice for this agent, as in voice.system.
elevenlabsVoiceIdstring—ElevenLabs voice to use.
gender"female" | "male" | "neutral"—Used to pick a matching voice when none is set.
stylestring—A few words on manner, for example "calm, brief".
introstring—One-line self-introduction used on first contact.
narrate"off" | "on" | "all"—Speak short updates from the agent's steps while it works. on skips scheduled jobs; all includes them.

screen ​

How agents capture the screen. See Capture the screen at the right moment.

KeyTypeDefaultWhat it does
screen.maxPixelsnumber1200000Pixel budget for one capture. Larger captures are scaled down.
screen.timeoutMsnumber5000Longest a capture waits for a change or for the screen to settle, in milliseconds.
screen.intervalMsnumber100Time between samples while waiting, in milliseconds.
screen.changeThresholdnumber (0–1)0.015Average difference above which two samples count as different.
screen.stableMsnumber400How long a region must stay unchanged to count as settled, in milliseconds.
screen.regionsmap of objects{}Named parts of the screen, in screen points. A name here replaces a built-in region of the same name.
screen.buffer.enabledbooleanfalseKeeps the last few seconds of a region in memory. Frames are written out only when asked for.
screen.buffer.secondsnumber (up to 120)10How many seconds the buffer keeps.
screen.buffer.fpsnumber (up to 10)2Frames per second kept in the buffer.
screen.buffer.regionstring"screen"Region the buffer records.
screen.buffer.maxPixelsnumber300000Pixel budget for one buffered frame.

Each entry in screen.regions (for example "chat": { "x": 0, "y": 0, "width": 400, "height": 300 }):

KeyTypeDefaultWhat it does
x, ynumberrequiredTop-left corner.
width, heightnumberrequiredSize of the region.

business ​

An experimental layer that runs agents like a team, with roles, working hours and a shared pool of work. It is off by default and its shape may change between minor versions. The whole business block is optional; when present, business.mainChannel and business.workSource are required.

KeyTypeDefaultWhat it does
business.enabledbooleanfalseTurns the business layer on.
business.timezonestring"UTC"Timezone for working hours.
business.mainChannelobjectrequiredChat where the team posts reports and "no plan today" notices: channel, chatId and optional accountId.
business.mainChannel.accountIdstring—Which account of that channel to post from.
business.workSourceobjectrequiredWhere agents find work. type is "backlog", "gitlab" or "wiki".
business.workSource.pathstring".agentx/backlog.md" for backlogThe backlog file (backlog), or the folder to read (wiki, required there).
business.workSource.projectslist of strings[]GitLab projects to read (gitlab). Empty means all configured GitLab projects.
business.workSource.globstring"**/*.md"Which files to read in the folder (wiki).
business.rolesmap of objects{}Job roles, keyed by role id.
business.orgChartmap of objects{}Which agent holds which role and when it works, keyed by agent id.
business.projectslist of objects[]Projects, with an optional project manager and client.
business.contactMaplist of objects[]Maps a chat or sender to a client and project, so the activity view credits the right client.
business.clientsmap of objects{}Per-client overrides, keyed by client id. Clients are otherwise worked out from projects and contactMap.
business.workTickMinutesnumber (1–60)15How often, in minutes during working hours, agents are asked to pick up work.
business.idleQueueThresholdnumber0Accepted but not read by the daemon yet.
business.standup.enabledbooleantrueRuns the morning standup. When off, it does nothing.
business.standup.plansDirstring".agentx/plans"Folder holding the day's plan (<date>.md, falling back to the week, then the month). With no plan, the standup posts a notice and starts no agent.
business.standup.maxAgentsPerDaynumber (1–100)20Most agents the standup may start in one morning.
business.standup.dryRunbooleanfalsePosts the day's plan for review but starts no agent.

Each entry in business.roles.<role>:

KeyTypeDefaultWhat it does
titlestringrequiredRole name given to the agent.
responsibilitieslist of strings[]Listed in the agent's instructions.
sopPathstring—File with the role's standard procedure, referenced in the agent's instructions.
kpislist of strings[]Measures of success for the role.

Each entry in business.orgChart.<agent>:

KeyTypeDefaultWhat it does
rolestringrequiredRole id from business.roles.
reportsTostring—Agent id of the manager. Must be another agent in the org chart.
schedule.dayslist of "mon"…"sun"Monday to FridayWorking days.
schedule.start, schedule.endstring HH:MMrequiredStart and end of the working day.
schedule.lunchobject—Lunch break, with start and end as HH:MM.
utilizationTargetnumber (0–1)0.8Share of working time the agent should be busy.

Each entry in business.projects:

KeyTypeDefaultWhat it does
idstringrequiredProject id, for example group/project.
pmstring—Agent id of the project manager.
clientstring—Client the project belongs to. Defaults to the part of id before the first /.

Each entry in business.contactMap (the first match wins: chatId, then username, then channel):

KeyTypeDefaultWhat it does
clientstringrequiredClient this contact belongs to.
channelstring—Channel kind, for example "telegram".
chatIdstring—The chat's id on that channel.
usernamestring—Sender's username.
senderIdstring—Sender's numeric id, when the username changes.
projectstring<client>/_chatProject the conversation counts toward.
displayNamestring—Name shown for the contact.

Each entry in business.clients.<client>:

KeyTypeDefaultWhat it does
namestringthe client idDisplay name.
kind"client" | "internal" | "own"—client is someone waiting on you; own is your own product; internal has no outside deadline.
respondWithinstring—How long a wait may last before it matters, such as "4h", "90m" or "2d". Unset means no deadline.
standinglist of strings[]What agents may do for this client without asking; "*" means everything. Ignored when kind is client.

boards ​

Kanban boards backed by GitLab issues, shown on the dashboard's Boards page. boards is a list; each board has these keys:

KeyTypeDefaultWhat it does
idstringrequiredBoard id: lowercase letters, digits, - or _.
namestringrequiredBoard title.
source.type"gitlab"requiredWhere issues come from. Only GitLab today.
source.projectslist of stringsrequiredGitLab project paths. At least one.
primaryToolLabelstring—A label every card must carry; shown as a fixed filter chip.
labelslist of objects[]Labels offered when you create or edit a card.
columnslist of objectssix columnsThe columns. The default is Open, To Do, Doing, On Hold, Review and Closed, driven by Status:: scoped labels.
timeRangeDaysnumber (1–365)30How many days of open issues to show.
closedWindowDaysnumber (1–365)30How many days of closed issues the Closed column shows.
reconciliationobject{}Settings for flagging stale cards, listed below.
reconciliation.enabledbooleantrueAccepted but not acted on yet: flagging cards left in Doing too long.
reconciliation.staleDoingMinutesnumber45Accepted but not acted on yet.
reconciliation.respectLunchBreakbooleantrueAccepted but not acted on yet.
reconciliation.respectSchedulebooleantrueAccepted but not acted on yet.
reconciliation.action"badge" | "notify""badge"Accepted but not acted on yet.

Each entry in labels:

KeyTypeDefaultWhat it does
namestringrequiredThe GitLab label, used as written.
colorstring #rrggbb"#6366f1"Label colour.
descriptionstring—Label description.

Each entry in columns:

KeyTypeDefaultWhat it does
idstringrequiredColumn id: lowercase letters, digits, - or _.
titlestringrequiredColumn heading.
kind"open-backlog" | "scoped-label" | "closed" | "label""label"Which issues land here. open-backlog: open issues with no status label. scoped-label: open issues with scopedLabel. closed: closed issues; dragging here closes, dragging out reopens. label: open issues with mapsToLabel.
mapsToLabelstring—For label columns: label added on entry and removed on exit.
scopedLabelstring—For scoped-label columns: the full label, such as Status::Doing.
scopedPrefixstring"Status"For open-backlog columns: issues with a label of this prefix are left out.
accentstring—Colour of the column's top bar.

graph ​

The intent graph sorts requests into a fixed tree of topics and helps wiki search. It is off by default.

When a request is not already in the graph's cache, the classifier asks the intent-path decision seat first if that seat is active under decisions.seats, and only falls back to graph.classifierModel when the seat has no confident answer. In shadow the model still decides and the seat's answer is recorded next to it, so agentx decisions stats shows how often the two agree before the seat takes over. The path a request was filed under also steers the wiki: while that request runs, agentx_wiki_query asks the daemon for its path and ranks the articles that match the question by how much of the path they share, weighted by graph.retrievalWeights.graph. A query sent before the request is classified, or from outside a running request, searches without a path.

KeyTypeDefaultWhat it does
graph.enabledbooleanfalseTurns the intent graph on.
graph.baseDirstring".agentx/graph"Folder holding the graph's files.
graph.draftAgentstring—Agent that proposes classifications. Falls back to dashboard.draftAgent.
graph.reviewAgentstring—Agent agentx graph review uses to approve or reject pending classifications. Falls back to graph.draftAgent.
graph.autoApproveStructure"strict" | "extend-leaves" | "any""extend-leaves"Which classifications skip review. strict: none. extend-leaves: those that reuse existing topics or add one new topic at the deepest level. any: all.
graph.autoApproveConfidencenumber (0–1)1Classifications at or above this confidence also skip review. 1 turns this off.
graph.classifierModelstring"claude-haiku-4-5-20251001"Model used to classify.
graph.retrievalWeights.graphnumber0.6Weight of topic match in wiki search.
graph.retrievalWeights.bm25number0.4Weight of text match in wiki search.

decisions ​

Typed decisions ("seats") let a small, fast model answer fixed-choice questions with a probability. Everything is off by default. See Jev and typed decisions.

KeyTypeDefaultWhat it does
decisions.enabledbooleanfalseTurns typed decisions on.
decisions.dbPathstring".agentx/decisions/decisions.sqlite"Database where every decision is recorded.
decisions.redactStatebooleanfalseStores only a fingerprint of each decision's input, not its text. You can no longer replay decisions offline.
decisions.keepStateRowsnumber2000How many recent inputs to keep in full per seat; older ones keep only the fingerprint.
decisions.defaultBackendstring"local"Backend used by seats that don't name one.
decisions.backendsobject{}Settings for each backend below.
decisions.seatsmap of objects{}Per-seat settings, keyed by seat name.
decisions.routingobject{}Models to move simple tasks to.
decisions.routing.cheapModelstring—Cheaper model for claude-code agents (older form of the next key).
decisions.routing.cheapModelsobject—Cheaper model per engine.
decisions.routing.cheapModels.claude-codestring—Cheaper model for claude-code agents, such as a claude- model or haiku.
decisions.routing.cheapModels.codex-clistring—Cheaper model for codex-cli agents, such as a gpt- model.

Local backend (asks a model through an agent engine):

KeyTypeDefaultWhat it does
decisions.backends.localobject{}The local backend.
decisions.backends.local.providerstring"claude-code"Engine used to ask.
decisions.backends.local.modelstring"claude-haiku-4-5-20251001"Model used to ask.
decisions.backends.local.structureMode"auto" | "tool" | "text""auto"How the answer's shape is enforced: a forced tool call, JSON in text, or whichever the engine supports.
decisions.backends.local.normalizeProbabilitiesbooleantrueRescales the model's probabilities so they add up to 1.
decisions.backends.local.nRetryMalformedStructurenumber (0–3)1Retries when the answer has the wrong shape.
decisions.backends.local.maxStateCharsnumber24000Longest input sent, in characters.

simple-jev backend (a self-hosted server that reads the model's own probabilities):

KeyTypeDefaultWhat it does
decisions.backends.simpleJevobject{}The simple-jev backend.
decisions.backends.simpleJev.baseUrlstring"http://127.0.0.1:8000/v1"Server address.
decisions.backends.simpleJev.modelstring—Model to use.
decisions.backends.simpleJev.apiKeyEnvstring—Name of the environment variable holding the key.
decisions.backends.simpleJev.timeoutMsnumber30000Request time limit, in milliseconds.
decisions.backends.simpleJev.maxStateCharsnumber6000Longest input sent, in characters.
decisions.backends.simpleJev.maxChoiceOptionsnumber (2–255)50Most options one question may have.

jev backend (Jev through OpenRouter) and typesafe backend (Jev direct from TypeSafe):

KeyTypeDefault (jev)Default (typesafe)What it does
decisions.backends.jev.baseUrl, decisions.backends.typesafe.baseUrlstring"https://openrouter.ai/api/alpha""https://api.typesafe.ai/v1"Service address.
decisions.backends.jev.path, decisions.backends.typesafe.pathstring"/decisions""/systemone"Endpoint path.
decisions.backends.jev.model, decisions.backends.typesafe.modelstring"jev-latest""jev-latest"Model id.
decisions.backends.jev.apiKeyEnv, decisions.backends.typesafe.apiKeyEnvstring"OPENROUTER_API_KEY""TYPESAFE_API_KEY"Name of the environment variable holding the key.
decisions.backends.jev.timeoutMs, decisions.backends.typesafe.timeoutMsnumber3000030000Request time limit, in milliseconds.
decisions.backends.jev.maxStateChars, decisions.backends.typesafe.maxStateCharsnumber9000090000Longest input sent, in characters.
decisions.backends.jev.maxChoiceOptions, decisions.backends.typesafe.maxChoiceOptionsnumber (2–255)255255Most options one question may have.

Each entry in decisions.seats.<seat>:

KeyTypeDefaultWhat it does
mode"off" | "shadow" | "active""off"off: unused. shadow: runs and records only. active: its answer is used.
backendstringdecisions.defaultBackendBackend for this seat.
modelstring—Model for this seat.
timeoutMsnumber10000Time limit per decision, in milliseconds.
temperaturenumber1Calibration fitted from labelled answers (agentx decisions calibrate). 1 means not calibrated yet.
explorenumber (0–1)0.15Share of would-be skips run anyway, so the seat can still be graded.
holdoutnumber (0–1)—Share of turns that skip the seat as a comparison group. Only seats that run an experiment read it.
json
"decisions": {
  "enabled": true,
  "seats": { "request-gate": { "mode": "shadow", "backend": "jev" } }
}

demo ​

How long agentx demo waits while it starts. The demo reads this from the agentx.json in the folder you run it from. It needs no config file, so this is only for machines where it starts slowly.

KeyTypeDefaultWhat it does
demo.startupTimeoutSecondsnumber (1–3600)—Seconds each startup step may take: each node answering /health, the dashboard answering /live, the nodes finding each other. Unset: AGENTX_DEMO_STARTUP_TIMEOUT, else 60, raised when the machine is busy (the 1-minute load average above the CPU count), up to 300. The --startup-timeout flag overrides both.

Check it worked ​

  1. Terminal: in the folder with agentx.json, run agentx config check. It prints ✓ Config valid.
  2. Terminal: run agentx config get <path> for the key you changed, for example agentx config get mesh.healthCheck.interval. It prints the new value.
  3. Terminal: run agentx daemon status to confirm the daemon is running.

If something is wrong ​

  • config check names a field: fix the value to match the type in the tables above. Ids for boards and columns must be lowercase.
  • Dashboard changes don't show: the dashboard is its own process. Restart it after changing dashboard settings.
  • A mesh peer shows as down: check its url and token, then raise mesh.healthCheck.timeout if the link is slow.
  • agentx demo says Timed out waiting for …: the machine is too busy for the startup limit. Run it again with --startup-timeout 300, or set demo.startupTimeoutSeconds. The line Startup limit: … at the top shows the value in use and where it came from.
  • A backend key is empty at runtime: the variable named in apiKeyEnv is missing from .env. Add it, then restart the daemon.

Released under the MIT License.