@sym-bot/xmesh
v0.9.49
Published
xMesh — enterprise agentic mesh runtime for task execution, evidence, explicit rulings, and grounded learning.
Maintainers
Readme
xMesh
xMesh is an enterprise agentic-mesh runtime. Give it a business task and it forms a crew, runs the work, keeps the evidence, stops for an explicit ruling when required, and carries approved learning into later missions.
Claude Code user? One line installs it, and nothing needs configuring.
npm install -g @sym-bot/xmesh. Run xmesh in your project directory, reopen Claude Code
there, and it is ready. What it adds is a second mind for Claude Code itself: when Claude Code
hands a task to xMesh, the work runs on the same Claude login you already have — your
subscription, no second account, no API key — but not in another Claude Code window. It runs
the same Claude CLI headless, inside a harness xMesh supplies: a workspace, grounding context,
the mission brief and its checks, an independent critic, an evidence file and an audited
record. Claude Code gets the result back reviewed, with its evidence, and approved learning
from it carries into later missions.
xMesh is for work that is difficult to solve with one prompt, one agent, or a fixed workflow. It adds the operating layer that a dependable multi-agent system needs:
- Task-first execution. Start with an outcome and success criteria, not an org chart of agents.
- Receiver autonomy. Agents decide for themselves whether a task or observation is relevant. There is no central component assigning cognition.
- Seven dimensions of cognition. CAT7 expresses Focus, Issue, Intent, Motivation, Commitment, Perspective, and Mood as the dimensions through which a node evaluates an observation.
- Selective admission. SVAF weighs those dimensions against receiver-local anchors and turns the evidence into one whole-block admission decision.
- Sovereign memory. Every participant keeps its own store and admission policy. There is no shared pool of private agent memory.
- Semantic continuity. Local MiniLM recall retrieves relevant prior cognition by meaning before a mission worker starts, so later work can build on what the mesh already learned.
- Traceable work. Mission progress, findings, checks, decisions, and lineage remain on the record.
- Explicit rulings. Consequential work can stop for an approval or ruling, recorded on the mission as a separate act from the work.
- Learning by consequence. Outcomes that survive review can influence later missions; convincing failures do not earn authority merely by sounding good.
xMesh runs on the open Mesh Memory Protocol. The xMesh runtime and cognition core are proprietary SYM.BOT software. The protocol and the agent-connection package are separate open components.
Product status
Security note, 0.9.45 (2026-09-04). In every published version through 0.9.44 a mind spawned by the worker inherited the daemon's whole environment — passcode, relay token, licence, vendor keys — and any child of the mind that reads an environment could read it. 0.9.45 spawns every mind with an explicitly built environment: the runtime's secrets, every other lane's credential and the file paths that point at them are removed, and only the family its own CLI authenticates with is kept. Rotate any model API key that sat in the daemon's environment on a host where missions ran, upgrade, then rotate the passcode and relay token. Found by a mesh review of our own shipped source; no evidence of exploitation was looked for and none is claimed. Details in the changelog.
Current evaluation release: 0.9.49 (16 September 2026). Install it from npm or run the
multi-platform Docker image. Its publication gate completed before anything shipped and the
published containers are the exact artifacts the gate scanned. The published evidence records
zero scan findings on both architectures and an empty exception list; that is a bounded scan
result, not a claim that the image is vulnerability-free. A plain npm install of this package
currently resolves two HIGH advisories in the ML dependency chain (adm-zip GHSA-xcpc-8h2w-3j85
and sharp GHSA-f88m-g3jw-g9cj, both via @huggingface/transformers, whose published
versions pin them); xMesh uses that chain only for local text embeddings; the container image removes adm-zip
after install and carries sharp as a tracked HIGH deliberately, because pruning it breaks
the runtime's neural entry point. The advisories clear for installers when the upstream pins move. This release makes cognition from
finished mission rooms reachable to recall; it does not claim an improvement in retrieval quality.
Erratum, 31 August 2026 — 0.9.31 release notes. The notes bundled with 0.9.31 are headed
"A release can no longer half-ship." That sentence is false and the release it shipped in is what
disproved it: 0.9.31 reached npm while the container registry still served 0.9.30 as latest, and
the Kubernetes manifest published by that release pinned a 0.9.31 image that did not yet exist.
The images were promoted by hand about twenty-five minutes later and verified layer-for-layer
against the artifacts the gate scanned, which is the state described above. What the credential
preflight actually guarantees is narrower: publishing authentication is proven before any
irreversible step. The retraction is recorded here because the notes ship inside the package and
cannot be amended in place.
| Product surface | Status | What it means |
| --- | --- | --- |
| Developer Runtime | Available now | Compiled proprietary runtime from public npm. Includes the CLI and HTTP API for local development and evaluation. |
| Coding-agent integration | Available now | Codex, Claude Code, and other MCP clients can commission missions and collect results through the bundled xmesh-mcp bridge. |
| Sovereign agent integration | Available now | An MCP-capable agent can join as a mesh peer through @sym-bot/mesh-channel while keeping its tools, model, credentials, machine, and private store. |
| Station | Not in the npm package | The customer operations cockpit is planned for the paid Team Mesh deployment. |
| Team Mesh | Production rollout | One customer-controlled deployment for a production team, subject to the published security and operations gates. |
| Enterprise Federation | Shipped, licence-gated | Independently governed team meshes can expose and read approved decisions across an organization. The cross-organization endpoints return HTTP 402 without a production Team Mesh licence. (Distinct from the spend 402: a fresh install runs under a default cap of 40 work units per UTC day, and the spend 402 fires only when that cap — or one a person chose at POST /api/spend/choice — binds. No licence involved.) |
The npm package is deliberately API-only. It does not contain the Station or the
repository's development web interface. A fresh install prints ui: none (API only) at
startup.
Five-minute start: use xMesh from a coding agent
The canonical, maintained walkthrough is the Developer quick start in the xMesh Guidebook. The compact path below is kept with the package so a fresh install remains usable offline.
Requirements: Node.js 20 or later and an authenticated Claude Code or Codex CLI — the mind a
mission runs inside. A Claude Code user needs nothing else: install, start, restart Claude
Code. The mind runs on the Claude login you already have; xMesh adds the harness around it —
workflow, context, memory, evidence, audit — and hands the reviewed result back to Claude Code.
A mission asked from Claude Code carries the session's project directory, so "this repository"
means the project you are in and the deliverables it names land there. Several sessions share
the one runtime: each is recorded under its own seat, and one person's sessions are one
sovereign — the seat is attribution and routing, not a boundary between people.
(jq appears only in the optional HTTP commands further down.)
1. Install xMesh
npm install -g @sym-bot/xmeshThis one package installs both commands: xmesh runs the local runtime and xmesh-mcp
lets a coding agent call it.
2. Start the runtime
# From your project directory. Leave it running.
xmeshThe mind a mission runs inside is detected: the claude CLI on PATH is used when nothing
says otherwise, and a mission's independent review runs on it too. It is separate from the
Claude Code or Codex client through which you offer the mission. To run missions on Codex
instead, start with XMESH_LLM_PROVIDER=cli:codex xmesh; to run them on a model behind an
API key, save a lane (see Models).
On first run xMesh generates a passcode, prints it, and stores it in
~/.xmesh/passcode. The API listens on http://localhost:8787 by default. Started from a
project directory, it also writes the MCP bridge into that directory's .mcp.json (step 3).
Prefer a container? docker run -d -p 8787:8787 -v xmesh:/state symbotdocker/xmesh:0.9.49
runs the same artifact with nothing to install — see Docker.
Check both process health and useful readiness:
curl -s http://localhost:8787/api/health
# → {"verification":"on — every mission is independently reviewed by a second model (…)",
# "spend":{"protection":"unconfigured"},"ok":true,"ready":true,"grounded":false}okmeans the server is listening.readymeans it can accept and run work — an LLM mind is available.groundedmeans it is on a live mesh, as itself, with cognition to reason from.- The authenticated
GET /api/readinessendpoint explains which one is missing and why.
A fresh install with a working provider commonly shows ready:true, grounded:false: it can
do work, but it has no peers to ground in yet. That is an isolated deployment, not a broken
one. Without a resolvable provider it shows ready:false; grounded becomes true when the
runtime has a live mesh identity and cognition to reason from.
3. Restart Claude Code — the bridge is already wired
Starting xmesh from your project directory wrote .mcp.json there with the bridge from
this install. Restart Claude Code in that directory (or run /mcp) and approve the xmesh
server when it asks; the mesh_* tools are then available. Nothing else is required.
Another project later? Run xmesh there too. It finds the runtime already running for your
user, wires that project to it, says so, and exits — one runtime serves every project on the
machine. To wire a directory by hand, or a board on another port, the same step is one command:
xmesh mcp install --url http://localhost:8787It is idempotent: run it again and it changes nothing; run it after the install it pointed
at is gone and it repairs the path. Every xmesh command run from a project
directory does the same thing on the way past. For Codex, codex mcp add xmesh --env XMESH_URL=http://localhost:8787 --env XMESH_SEAT=your-name -- xmesh-mcp
does the same job.
Verification is on by default: every mission's completion is independently reviewed by a
second model — that review is the product's own claim, demonstrated on your first mission.
Independent verification runs a second model and may increase provider usage; cost-sensitive
users can opt out with XMESH_MISSION_CRITIC=0 xmesh, and /api/health will then report
verification: off (explicit opt-out) — unverified missions never look equivalent to verified
ones.
A connection's seat is who your missions are recorded as asked-by and where completion
notifications are sent. Inside a Claude Code session the bridge derives it from the session
(claude-<project>-<session>, the same name the SYM mesh plugin uses there, so notifications
reach that plugin when it is installed). Pass --seat <name> (or set XMESH_SEAT) to pin
another name; a connection with no seat at all — a hand-wired Codex entry without one — is
recorded anonymous, the runtime deliberately sends nothing back, and xmesh review tells you
so at the moment you commission.
The bridge finds the passcode the same way the CLI does (XMESH_PASSCODE, then the passcode
file under XMESH_STATE_DIR / XMESH_TEAM_ROOT / ~/.xmesh). If it is talking to a board on
another host or state directory, set XMESH_PASSCODE explicitly in the MCP server environment.
Fully restart the MCP client after adding or changing the server. MCP tool schemas are cached when the connection opens; restarting xMesh alone does not refresh them.
4. Optional: replace the default spend limit with your own (a person does this, once)
A fresh install runs under a default cap of 40 commissioned work units per UTC day —
generous against measured normal use of ~6 missions/day. It is a default, not a decision:
/api/health reports chosen: false while it is in effect, and when it binds, the refusal
says so and hands you the number you did not have on day one — what a day of your own work
actually costs.
xMesh will still never accept unbounded spend on its own: that mode requires an explicit call with a name recorded against it. The choice is also deliberately NOT an MCP tool — the mesh must never set its own budget. To replace the default, as the deployment's owner:
# authenticate with the passcode the runtime printed at first start
TOKEN=$(curl -s -X POST http://localhost:8787/api/session \
-H 'content-type: application/json' \
-d '{"credential":"<your passcode>","seat":"you"}' | jq -r .token)
# (`passcode` is accepted as the field name too — both spellings in this README work)
# choose ONE: a daily workload cap (measured normal use: ~6 missions/day; 40 is generous) …
curl -s -X POST http://localhost:8787/api/spend/choice \
-H "x-mesh-token: $TOKEN" -H 'content-type: application/json' \
-d '{"mode":"workload","dailyUnits":40}'
# … or a daily USD line ({"mode":"usd","dailyUsd":20}), or explicitly accept unbounded
# spend ({"mode":"unbounded"}) — recorded in the ledger; health will say protection: none.GET /api/health shows spend.protection so you can see the state at a glance; the full
detail (today's count, remaining) lives on the authenticated /api/readiness.
5. Commission work and collect the result
In the restarted coding agent, ask it to run any useful task in xMesh. Describe the outcome
you want in normal language; the coding agent should recognize the request and invoke
mesh_mission itself. For example:
Run this task in xMesh: review this repository and identify the top three release risks.
No MCP syntax is required in your prompt. The coding agent should return the mission id; keep
it so you can ask the agent to check that mission's status or retrieve its final result later.
Under the hood it follows that exact id with mesh_missions. Always pass the id: completed
missions leave the live list when their temporary crew dissolves, but an id lookup still
returns the finished record and result. Use mesh_ask for a grounded answer without a
deliverable, and mesh_review for a second opinion on an existing file or diff.
That is the primary developer path: your coding agent is the client, xmesh-mcp is the
bridge, and xMesh forms and governs the temporary crew that performs the mission.
HTTP API quick start
The same workflow is available directly over HTTP. Create an authenticated session and offer a mission:
# Paste the passcode printed by xMesh.
curl -s http://localhost:8787/api/session \
-H 'content-type: application/json' \
-d '{"passcode":"YOUR_PASSCODE","seat":"developer"}'
# Use the returned token.
curl -s http://localhost:8787/api/missions \
-H 'content-type: application/json' \
-H 'x-mesh-token: YOUR_TOKEN' \
-d '{
"intent":"Review the release candidate and write a go/no-go recommendation to /srv/work/go-no-go.md",
"criteria":"CHECK: file /srv/work/go-no-go.md\nCHECK: contains /srv/work/go-no-go.md VERDICT:\nCite blocking evidence; a human rules on unresolved risk"
}'On a fresh install this runs under the default spend cap (see step 4) and returns the mission
record. Past the cap — default or chosen — every door answers a structured 402 naming the
state and the remedy. Follow it through GET /api/missions
(status, checks, cost, harness), settle the day with POST /api/eod, and read what broke with
GET /api/eod/breaks. Authorization: Bearer <token> works everywhere x-mesh-token does.
How a mission runs — from request to verified outcome
A mission is a governed unit of work. xMesh records every offer, execution, review, decision and replay in an append-only commission record, so a result stays traceable long after the run. Nothing waits on a human mid-run; a human sees only what broke.
- Offer.
POST /api/missionsrecords the ask and its criteria as a signed offer. Name aroomand it is filed into that room instead; omit it and a mission room forms. A standing room whose memory fits it may host it; otherwise a fresh mission room forms with a doer and — if verification is on — a critic on a different model or vendor. - Execute. The doer works, reports progress, and completes with an artefact. The harness grades the criteria mechanically (see Writing criteria). The result is recorded at once: delivered, or — if it hit a capability it lacks — a root-cause record with an approval card. The doer's capacity is released; the critic is held a few minutes for its verdict, then released.
- Verify. The critic reads the artefact and the doer's evidence log and either approves or objects, on the record. Adversarial review lenses may add their own verdicts.
- Reconcile.
POST /api/eod(or the daily ticker,XMESH_EOD_HOUR, default 23) reconciles every recorded result against its independent review: matched (authority credited to the doer), no-counterparty (unverified — nobody could review it), or break (doer and critic disagree, or the checks failed). Only breaks reach you:GET /api/eod/breaks. - Decide. A break names its exits — validate (overrule the critic), dismiss (uphold it), or
replay:
POST /api/lifecycle/<commission-key> {"verdict":"validated"|"dismissed"}orPOST /api/missions/<key>/replay. A record is never rewritten; a replay is a new mission run citing the original. Withdraw an open mission withPOST /api/missions/<key>/abandon. - Investigate. Every break has a root-cause report — the result, the objection, the harness it
ran on, and the implicated resource:
GET /api/missions/<key>/rca;POST …/rca/deepasks the mesh for the causal hypothesis.
The runtime enforces capacity and deadlines. It never decides which cognition a participant must accept — that receiver-autonomous boundary is what makes xMesh a mesh, not a router.
The cognition loop — admit, retain, recall
A Cognitive Memory Block expresses an observation across the seven CAT7 dimensions: Focus, Issue, Intent, Motivation, Commitment, Perspective, and Mood. They are dimensions of cognition, not merely transport fields: different nodes can weigh the same observation differently while still exchanging one interoperable projection.
SVAF is the admission membrane. The receiver reconstructs semantic geometry from the block's text, compares each dimension with its own anchors under its own weights, and turns that dimensional evidence into one decision about the complete block: redundant, aligned, guarded, or rejected. It never trusts an embedding supplied by the sender, and it does not partially store whichever dimensions happened to pass. An admitted block becomes the receiver's own remix, with lineage back to its source.
Semantic recall is the continuity mechanism. Once loaded, the same local
Xenova/all-MiniLM-L6-v2 encoder supports a second job: xMesh searches durable cognition by
meaning across the CAT7 dimensions and builds the relevant context before a mission worker
starts. The MiniLM encoder selects prior context; it is not the Codex, Claude Code, or other
model that performs the mission. The separately trained SVAF research evaluator is not implied
by this baseline runtime path.
Recall expands the cluster, not just the nearest row (0.9.22). Ranked memories that belong
to your own past missions each bring a bounded set of same-mission siblings into the brief,
at the same brief size. Expanded rows are labeled [via …] instead of carrying a relevance
score they never earned, never cross a tenant boundary, and never displace ranked anchors
beyond a fixed byte share. The same join is on the query surface:
GET /api/query?q=…&mode=relevance&expand=1 returns an expanded count and marks each
expanded row with a via reference to the anchor that earned its room.
Writing criteria — the check grammar
Criteria are prose plus mechanical CHECK: clauses. A clause the grammar cannot read is refused
at the offer (HTTP 400 naming it), never silently dropped:
CHECK: file <path> the artefact exists (fabricable — a touch passes it)
CHECK: contains <path> <needle> the artefact says something (substantive)
CHECK: not-contains <path> <needle> it does NOT say something (a scaffold mark, a placeholder)
CHECK: contains-at-least <path> <N> <needle> at least N occurrences
CHECK: run <command> behaviour — needs a shell the sandbox usually gatesUse absolute paths under the workspace and at least one substantive check; a mission graded on
file alone is written as a break at EOD ("delivered on file-existence checks only") because
nothing substantive grounded it, and a result whose own checks fail is a break too. A file that
declares itself in progress (Status: IN PROGRESS, _pending_) fails every substantive check
until the mark is gone.
Verification — the critic
XMESH_MISSION_CRITIC=1 # staff a critic on every mission
XMESH_MISSION_MIND_B=claude # or codex — a different vendor is the strongest independence
XMESH_MISSION_MODEL_B=claude-sonnet-5 # a different base model than the doer when the vendor is the same
XMESH_CRITIC_SETTLE_MS=300000 # how long a completed mission holds its critic for a verdict (default 5 min)The critic is fail-closed: it never falls back to another model, and its silence is never read
as approval — no verdict means unverified (reported as no-counterparty by the API), and the
report says so.
Cost and the harness stamp
Every mission run records what it cost (input / cached / output tokens, and USD where the provider
states it) and the harness it ran on — content-addresses of the doer's brief template, the
constitution, the critic's rubric and the check grammar. GET /api/eod/harness reads the
record grouped by harness: runs (bookings), matched, breaks, objections/approvals,
authority-credit events (paid), and cost per verified outcome (usdPerMatched). Change a
template or a rubric and the record shows the before and after as two groups.
The four texts can be overridden per deployment under <state>/resources/
(constitution.md, rubric.md, template.claude.md, template.codex.md; templates carry
{{WORK}} and {{CRITERIA}}). A valid override replaces the default whole and is hashed like
one; a constitution or rubric override may refine or add rules, never delete a default one; an
invalid override is ignored and logged once.
Production network boundary
The server binds all interfaces by default and authenticates with a passcode exchanged for a
bearer token over plain HTTP — fine on a developer machine, not on a network. For anything
beyond localhost: set XMESH_BIND_HOST=127.0.0.1 and terminate TLS in front (any reverse
proxy — nginx, Caddy, an ingress — forwarding to the loopback port),
and never expose raw :8787 on a public interface. The Docker examples above publish the port to the host only;
publishing it wider without TLS sends credentials and mission data in the clear.
On a cloud platform whose edge terminates TLS for you (e.g. RunPod's HTTPS proxy on an exposed
HTTP port), the transport half is the platform's; the credential half is yours, and two
settings make it explicit: XMESH_REQUIRE_CREDENTIAL=1 refuses to boot unless XMESH_PASSCODE
was explicitly provided (a generated passcode printed to platform logs is not a chosen posture),
and XMESH_TRUST_PROXY=1 lets the login throttle see real client addresses through
X-Forwarded-For — set it only behind a proxy you trust, never on a directly exposed server.
The login door itself is throttled (per-address and global sliding windows) whichever way it is
reached. For licensing a containerized deployment, set XMESH_TEAM_ROOT to a path unique to your
deployment (the licence binds to that path — see the Kubernetes manifest's comments), read
the team-… id from /api/version, and point XMESH_LICENSE at your signed licence.
XMESH_TRUST_PROXY is a hop count — the number of proxies in front of the server — never a
switch. A non-numeric value (true) is refused by name at boot rather than ignored.
Read the environment before deploying it. The runtime refuses most mistakes at boot; a few
boot to a green /api/health and fail later — a team root written with a trailing slash (a
licence minted against an id the runtime never binds), a SYM_STATE_DIR that points outside
the root, an api: lane with no key, a cli: lane whose CLI is not on the runtime's PATH.
xmesh deploy-check reads those from the environment it runs in, prints the team-… id the
runtime will bind before the first boot, and exits 1 on a fault:
# native install: the same environment the service will run with
XMESH_TEAM_ROOT=/srv/xmesh/acme XMESH_LLM_PROVIDER=cli:claude xmesh deploy-check
# container: run it inside the image, so PATH answers for the image, not the host
docker run --rm --entrypoint xmesh --env-file .env symbotdocker/xmesh:0.9.49 deploy-checkIt never reads a secret's value: a credential is reported by length, a key file by whether it is
readable. --json for scripts.
Operating discipline: reports, not just checks
xMesh deployments are operated largely by agents coordinating over messages, and a season of
audits taught one lesson worth stating here rather than in a postmortem: every false claim
came from a report, not from a file. A release version is not an installed state. A package's
create time is not a version's publish time. A file's presence is not a process's behaviour.
When you report state — to a human, a peer seat, or a ledger — carry three things in the same
sentence as the claim: the instrument and its scope ("/api/version on loopback", not "the
board is on"), a machine-printed clock beside the reading (never typed from memory), and the
object you actually examined, since a claim about a file must not be written as a claim
about a running process. A clean result states what was checked. If the scope will not fit in
the sentence, the claim is bigger than the check.
Two MCP integrations, two different jobs
| Integration | Direction | Use it when |
| --- | --- | --- |
| Bundled xmesh-mcp | Coding agent → xMesh runtime | Codex, Claude Code, or another MCP client should offer missions, monitor them, retrieve results, or request reviews. |
| @sym-bot/mesh-channel | Agent ↔ sovereign mesh peers | The agent itself should become a long-lived SYM participant with its own identity, admission policy, and private memory. |
A deployment may use both, but they are not substitutes. Most developers evaluating xMesh
from a coding agent should start with xmesh-mcp above.
Join an existing agent as a sovereign peer
xMesh does not replace or wrap your agents. First an existing MCP-capable agent becomes a sym agent: it receives a stable identity, a sovereign store, an admission membrane, and mesh tools. It then earns a meaningful place by contributing to work. There is no central registration step on purpose.
Example MCP configuration:
{
"mcpServers": {
"sym-mesh": {
"command": "npx",
"args": ["-y", "@sym-bot/mesh-channel"],
"env": {
"SYM_NODE_NAME": "acme-reviewer",
"SYM_ROOM": "acme-engineering"
}
}
}
}Give every long-lived agent a stable SYM_NODE_NAME and an explicit SYM_ROOM. A changing
name creates a new identity; a wrong room creates a healthy but isolated participant.
What crosses the mesh is a signed projection chosen by the sender. Each receiver evaluates the complete projection under its own policy and stores only its own admitted remix with lineage. The mesh does not remotely read or write another participant's private store.
See the mesh-channel README for host-specific MCP setup and failure diagnosis.
State and sovereignty
Native development uses two local trees:
~/.xmesh/— sessions, passcode, mission and server state.~/.sym/— the sovereign stores and identities of local mesh participants.
For a customer or container deployment, name one tenant root:
XMESH_TEAM_ROOT=/srv/xmesh/acme xmeshThat produces:
/srv/xmesh/acme/xmesh server state
/srv/xmesh/acme/sym participant storesBack up the complete tenant root. Do not run two xMesh processes against the same writable root. Scale by adding independently governed team roots, not by adding writers to one store.
If you run xMesh under macOS launchd, a plist edit is not picked up by
launchctl kickstart -k — that restarts the process on the already-loaded job, so the new
process keeps the old environment. After changing environment in the plist, launchctl bootout
then launchctl bootstrap the job, and confirm with launchctl print against the running job.
Use kickstart -k only for a code change with an unchanged plist.
LLM providers
xMesh supports two credential models. Choose one explicitly for a controlled deployment:
| Use case | Provider |
| --- | --- |
| Individual development with an existing CLI login | cli:claude or cli:codex |
| Customer or enterprise deployment | api:anthropic or api:openai |
Example enterprise configuration:
XMESH_LLM_PROVIDER=api:openai \
XMESH_LLM_KEY_FILE=/run/secrets/llm-key \
XMESH_LLM_BASE_URL=https://ai-gateway.acme.internal/v1 \
XMESH_LLM_MODEL=gpt-5.6-luna \
xmeshPrefer XMESH_LLM_KEY_FILE to an environment variable. The file is read for each call, so
the credential can be rotated without restarting the runtime. When
A trailing /v1 on the base URL is accepted and normalized — https://gw.example and
https://gw.example/v1 name the same endpoint, never /v1/v1. When
XMESH_LLM_BASE_URL is set, redirects to another origin are refused before the prompt or
credential is sent.
The declared enterprise-provider path is wired from version 0.6.1 onward. A declared but unusable provider—or no declared provider and no detectable local Claude CLI—makes the deployment not ready and refuses worker spawns instead of silently substituting a fake response. Native development may still detect an authenticated local Claude CLI when no provider is declared.
Models — the lane table
Work runs on lanes: an adapter (claude or codex protocol), a transport (cli on a
subscription, api on a metered key), an endpoint, a model, the name of a credential, a pool,
and the capabilities the operator declares. Edit them in Station → Models or through
PUT /api/lanes/:name; every xagent reads the table at hand-over and decides for itself what a
task needs. The table never carries a secret — the host that runs the work holds the value — so
it can live where you choose: this host, a shared file, or any GET/PUT { rev, lanes } URL
(XMESH_LANES_SOURCE; sym-relay serves one per channel). Details: docs/models.md.
Docker
The published image is on Docker Hub and needs no credentials, no repository access, and no build:
docker volume create xmesh-acme
docker run -d --name xmesh -p 8787:8787 \
-v xmesh-acme:/state \
symbotdocker/xmesh:0.9.49linux/amd64 and linux/arm64. Pin the version you intend to evaluate; latest exists and
moves. The image installs the same pinned npm runtime artifact you would get from
npm i -g @sym-bot/[email protected] — not identical bytes, because the build prunes the browser
ONNX bundle and the native binaries for other platforms, neither of which can execute here.
Measured on a fresh volume with no environment at all, it answers in about two seconds:
{"ok":true,"ready":false,"grounded":false}ready:false is correct there and is not a fault. No provider is declared, so no mind
resolves and worker spawns are refused rather than silently echoed; GET /api/readiness says so
in as many words. Such a container still serves the whole API, the CLI and the MCP bridge — it
can be inspected, configured and integrated — it just cannot yet think. Since 0.9.39 the image
carries its worker mind (a pinned codex CLI, proved present at build); declare the provider and
hand it a key and ready becomes true. The image starts as root only to take ownership of the
volume paths and provably drops to an unprivileged user (uid 1000) before any identity check,
login, or server code runs; all state stays on the volume you mount.
Give it the provider, a key and a credential when you want it to do work rather than answer:
docker run -d --name xmesh -p 8787:8787 \
-v xmesh-acme:/state \
-e XMESH_LLM_PROVIDER=api:openai \
-e OPENAI_API_KEY=<your key> \
-e XMESH_PASSCODE=<credential> -e XMESH_REQUIRE_CREDENTIAL=1 \
symbotdocker/xmesh:0.9.49The entrypoint performs the supported stdin API-key login into an ephemeral CODEX_HOME,
verifies it, hands the same key to the runtime's own api:openai completion as a 0600 file
(XMESH_LLM_KEY_FILE, read per call — unless you named XMESH_LLM_KEY_FILE or
XMESH_LLM_API_KEY yourself), and unsets it before the server starts — the key never appears
on a command line and never sits in the long-lived process environment. On a persistent deployment, name
XMESH_TEAM_ROOT beneath your mounted volume and set XMESH_VOLUME_MOUNT to the mount: the
team root then owns all state, and the volume carries a deployment-identity marker so a later
pod naming a different team root refuses rather than quietly becoming a different deployment.
Building it yourself, from a source checkout, is the same artifact by a longer route:
docker build --build-arg XMESH_VERSION=0.9.49 -t xmesh:0.9.49 .The build installs a pinned version from npm rather than copying the working tree — copying
would ship whatever was uncommitted. It also fails if the neural embedding path cannot load,
which is not decoration: the image published before this one was built on Alpine, and
onnxruntime-node ships glibc-linked bindings that cannot load under musl. It served correctly
and could not embed a single vector, silently, because the runtime falls back to lexical recall
by design. The base is now Debian slim and the build proves the path rather than assuming it.
One volume is one tenant. Do not attach two xMesh containers to the same volume.
A server-only container can be healthy but not ready: xMesh grounds work in participant
stores on its own filesystem. An empty sym tree gives it nothing to reason with. Check the
ready value, not only the HTTP status code. A container also has its own filesystem and
/tmp, so it cannot see peers or other deployments on its host unless you deliberately provide
the required state and networking.
The Kubernetes sample at deploy/kubernetes/xmesh.yaml is a
pre-1.0 evaluation sample, API-only: one stateful replica and one persistent volume per
tenant, server image alone. Without a co-located agent it will not ground missions — it
answers every endpoint from an empty canvas. The released image digest, the agent sidecar,
and a real-cluster proof are 1.0 gates; production deployment starts with a Team Mesh licence.
Budget management
xMesh never meters you for money — pricing is a flat team licence (below). Budget management is the opposite direction: limits you set on what xMesh may spend from your own provider account, all local, all changeable at any moment by your own validator, all auditable in your own state files. Two layers and two cost levers:
1. The deployment spend contract — a default you can replace. A fresh deployment runs under
workload/40 with chosen: false; a person may replace it with one of three modes
(POST /api/spend/choice, validator+). Only unbounded requires an explicit human acceptance,
and it is recorded with their name:
| mode | you set | what it enforces |
|---|---|---|
| workload | dailyUnits (default 40) | a hard cap on commissioned work units per UTC day — provider-independent; 40 sits above the heaviest measured real day (31) and far below a runaway loop |
| usd | dailyUsd | a daily dollar line, enforced as a hard cap where the provider reports cost; the workload cap backstops where it does not (CLI subscriptions report none) |
| unbounded | — | explicitly accepted unlimited provider spend — recorded in the ledger; health reports protection: none |
Over the line, every door answers the same structured 402 naming the state and the remedy.
A refusal admits nothing: no request is announced, no worker staffed, no unit consumed.
Duplicate asks are free. State lives in your tenant (spend-choice.json, spend-day.json,
spend-ledger.jsonl); read it at /api/health (protection class, public) and
/api/readiness / /api/spend (counts and remaining, authenticated).
2. Per-room daily USD lines — optional, finer. Any room can carry its own budget:
PUT /api/rooms/<name>/policy with dailyBudgetUsd (validator+), or set
XMESH_ROOM_BUDGET_USD to give every room without its own line the same default.
This layer counts known dollars (asks and fills whose provider reported cost) per UTC
day. Past the line, an ask or offer in that room answers 402 with the numbers, and a
validator may pass it anyway with an explicit overBudget: true — the override is recorded
on the commission's brief. dailyBudgetUsd: 0 is a valid posture: every ask and offer in
that room needs a validator. Read any room's line and spend at GET /api/rooms/<name>/budget.
3. Cost levers that are not budgets. Verification runs a second model on every mission —
that is the product's own proof, and it roughly doubles per-mission provider usage;
cost-sensitive deployments opt out with XMESH_MISSION_CRITIC=0, and health then says so
(verification: off (explicit opt-out)) rather than letting unverified work look verified.
Concurrency is bounded by the mind governor (half your cores, minus one), and a single
mission is bounded in time by its 60-minute deadline — both cap how fast anything can burn,
neither is a spend limit.
None of this reports anywhere: no activation, no usage phone-home. The ledger is yours.
Licensing
- Developer Runtime: free for local development, evaluation, and non-production use.
- Team Mesh: one flat annual licence per production team root, with unlimited human users and agents.
- No metering: pricing is not based on people, seats, agents, devices, IP addresses, sessions, tokens, or usage.
Licences are verified locally and entirely offline. xMesh does not need a usage-metering service or activation call to operate.
Starting a paid pilot (the offer): mail [email protected] with the subject
Team Mesh pilot, naming the team root you want to take to production. A pilot begins as a
private engagement: your production team root licensed for a year, unlimited humans and
agents in that mesh, direct support from the team that builds xMesh, and your launch findings
worked as first-class Board items. Pre-1.0 every production engagement is set up this way —
there is no self-serve checkout yet, and this page will say so when that changes.
Licence v2 has shipped (since 0.7.x) and implements the production-team contract above: a
licence names the team roots it covers, and a root's identity is derived from its canonical
path — so a licence validates only in the root it was issued for. In any other root it simply
does not validate, and that deployment runs as EVALUATION (unlicensed) — visibly, not
silently. The legacy seats cap survives only for existing v1 licences, honoured through
their expiry. It is not the pricing model and has not been since v2.
Decision record (2026-08-25, pre-1.0 boundary): the Developer Runtime is free for local development and non-production evaluation; production use of a team mesh requires a Team Mesh licence, arranged as a private pilot/contract. Pre-1.0 this boundary is contractual — the runtime marks unlicensed roots as evaluation and does not technically refuse them. The fail-closed enforcement gate is a named 1.0 item and will be documented when it can actually refuse.
The free allowance is a deployment, not a seat: a home-directory install has no team root at
all and is the free Developer Runtime. Unlicensed named team roots remain available for
evaluation and are visibly marked EVALUATION (unlicensed) in operator status. A licence is
required when an independently governed team mesh moves into production; it still covers
unlimited humans and agents in that mesh.
See xmesh.bot for the Enterprise Pilot and Team Mesh paths.
Current boundaries
- The public npm artifact contains the Developer Runtime CLI and API, not Station.
- Existing agent integration is shipped through
@sym-bot/mesh-channel; a general source-system connector SDK and catalogue are not yet a supported product surface. - xMesh integrates cognition about business work. Transactional writes remain the job of the source systems and their existing controls.
- A server with no local participants can listen successfully while having no grounded capability. Use readiness, not presence, as the operational test.
- Cross-organization federation endpoints are shipped and licence-gated; they return HTTP 402 without a production Team Mesh licence. Deployment topology, identity, and source-system controls remain the customer's responsibility.
Develop
This is a private source repository. The published npm package contains compiled proprietary software.
npm install
npm run dev # API on :8787 and repository development UI on :5181
npm test # server suite; no paid APIs required
npm run typecheck
npm run build # compiled runtime artifactReleasing (node scripts/release.mjs X.Y.Z, after writing the CHANGELOG entry): the script gates,
bumps, tags, pushes and publishes in that order. After it, know how each deployment is served:
a tenant that runs from this checkout (bin/xmesh.js in its plist) deploys on restart — the
checkout is the deploy; a tenant that runs the global package (…/bin/xmesh) stays on the old
version until npm i -g @sym-bot/[email protected] and a restart. One of three tenants on the founder's
host sat two minors behind for a week because nobody asked which kind it was. GET /api/version
answers for each: {version, tree, startedAt, generation, teamId} — tree is null for a package.
Useful references:
docs/agentic-mesh-reference.md— mechanism and status of the agentic mesh.docs/integration-reference.md— shipped integration surfaces and claims that must remain future tense.docs/ARCHITECTURE.md— system architecture.deploy/kubernetes/xmesh.yaml— single-writer deployment shape (pre-1.0 evaluation sample, API-only).
Support and security
Defects, questions, and security reports: [email protected] with the subject
xMesh defect report (or xMesh security report — those are read first and not
discussed publicly before a fix ships). Product page: xmesh.bot.
There is no public issue tracker yet; mail is the supported channel and every report
gets a reply.
License
Copyright © 2026 SYMBOT LTD, trading as SYM.BOT. All rights reserved. See LICENSE and the SYM.BOT Software License Agreement.
The operator CLI — xmesh <verb>
The same tenant the MCP bridge talks to (XMESH_URL, or the passcode under XMESH_TEAM_ROOT /
XMESH_STATE_DIR / ~/.xmesh). Human tables by default, --json for scripts.
xmesh status tenant version, tree, restart owed
xmesh deploy-check the environment, read before deploying it: teamId, state dirs, proxy hops, mind
xmesh soak the soak counters — 20 consecutive clean runs = soaked
xmesh ask "<question>" --room R an answer with citations, and what it cost
xmesh offer "<work>" --criteria "CHECK: file out.md
CHECK: contains out.md <needle>" lints first; --force offers with warnings
xmesh lint "<work>" --criteria … the lint report only
xmesh missions · detail <key> · eod [--run] · breaks · rule <key> validated|dismissed · replay <key>
xmesh abandon <key> | --stale one rested row, or every rested unstaffed row
xmesh register [room] [--md] · proposals · workers · budget <room> [usd/day]
xmesh review <path> --questions "…" a second opinion on your own file or diff
xmesh assess <engagement> [--call N] [--notes "…"] the integration assessment, prefilled