# Wayland Core

> Multi-provider AI agent CLI written in Rust

- **Type:** MCP server
- **Install:** `agentstack add mcp-ferroxlabs-wayland-core`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [FerroxLabs](https://agentstack.voostack.com/s/ferroxlabs)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [FerroxLabs](https://github.com/FerroxLabs)
- **Source:** https://github.com/FerroxLabs/wayland-core

## Install

```sh
agentstack add mcp-ferroxlabs-wayland-core
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Wayland Core

### The self-evolving AI agent. Brilliant today, smarter tomorrow.

**Most AI tools are as good as they'll ever be the day you install them. Wayland Core isn't — it convenes a council of rival models on your hardest problems, fuses their best answer into one, and rewrites its own prompts to get sharper every single run. Terminal-first, on your keys, in Rust.**

Terminal-first · Multi-provider · Self-evolving · MCP-native · Embeddable · Apache-2.0

[](https://www.npmjs.com/package/@ferroxlabs/wayland-core)
[](https://github.com/FerroxLabs/wayland-core/actions/workflows/ci.yml)
[](LICENSE)
[](https://www.rust-lang.org/)
[](#install)
[](#built-to-endure)

[Install](#install) · [Quick start](#quick-start) · [Providers](#provider-neutral-core) · [Orchestration](#orchestration--swarms) · [Crucible](#crucible--a-mixture-of-providers-council) · [Security](#security-by-default-fail-closed) · [Channels](#omni-channel-deployment--scheduled-triggers) · [Browser](#browser--computer-use) · [Memory](#memory-sessions--cost-governance) · [Evolution](#self-evolution-gepa) · [Endurance](#built-to-endure) · [Embedding](#embedding-json-lines-protocol--acp-interop) · [Docs](#documentation)

---

Most agents are frozen the day you install them, and married to one model. Wayland Core is neither. Hand it a hard problem and it convenes a **council of rival models** that cross-audit into one answer ([Crucible](#crucible--a-mixture-of-providers-council)). It **rewrites and scores its own prompts** between runs ([GEPA](#self-evolution-gepa)). Every tool runs in an OS-native sandbox behind a single egress gate, and it speaks [MCP](https://modelcontextprotocol.io/) in both directions — all from one Rust binary, on your keys. It's the engine inside [Wayland Desktop](https://getwayland.com), but it stands alone: a one-shot command, a full-screen TUI, or a headless stream you embed.

> **Wayland Core** is the engine, on its own, open (this repo, Apache-2.0). **[Wayland Desktop](https://getwayland.com)** is the GUI product built on it. Core is the engine; Desktop is one application that embeds it.

## The 30-second proof

```bash
npx @ferroxlabs/wayland-core "read Cargo.toml, list the workspace crates, and explain the dependency layering"
```

One command. The agent reads the file, runs `grep`/`glob` across the tree, reasons, and answers, with every tool call gated and streamed. Or run `wayland-core` with no arguments and it detects your provider keys and drops you into the TUI:

**Paste a key, get a provider.** Paste an API key (or run `/connect` in the TUI) and the engine fingerprints the provider from the key's shape, validates it live, and stores it in your OS keyring. From there, `/config` exposes Essentials and Advanced editors, `/doctor` shows provider, key, and MCP health, and `/effective` prints the resolved config with secrets redacted.

## What it is

- **A standalone engine.** The engine is the product, not a feature bolted onto an editor and not a wrapper around one vendor's API.
- **Terminal-first.** A one-shot command, an interactive TUI, or a headless stream. The terminal is the primary home, not an afterthought.
- **Embeddable.** Drive it from your own app over a typed JSON-Lines protocol. It is exactly how Wayland Desktop uses it.
- **Apache-2.0.** Permissive. Build on it commercially without an AGPL obligation.

## Install

**npm** (recommended, pulls the right prebuilt binary for your platform):

```bash
npm install -g @ferroxlabs/wayland-core
wayland-core --version
```

```bash
# or run it once, no install
npx @ferroxlabs/wayland-core "summarize the TODOs in this repo and draft a triage plan"
```

**Prebuilt binaries** for macOS (arm64/x64), Linux (arm64/x64), and Windows (arm64/x64) are on the [Releases](https://github.com/FerroxLabs/wayland-core/releases) page, each verifiable against `wayland-core-checksums.txt`.

**From source** (Rust 1.95+):

```bash
cargo install --git https://github.com/FerroxLabs/wayland-core wcore-cli
```

## Quick start

```bash
# 1. Generate a config, then add an API key for any provider
wayland-core --init-config
wayland-core --config-path        # shows where the config lives

# 2. One-shot: the agent reads files and uses tools to answer
wayland-core "Read Cargo.toml and explain the dependencies"

# 3. Interactive TUI (just run it)
wayland-core

# 4. Everything else
wayland-core --help
```

---

## Provider-neutral core

The engine never knows which vendor it's talking to. It builds one neutral request type, `LlmRequest`, and reads one neutral event stream, `LlmEvent` — `TextDelta`, `ToolUse`, `ThinkingDelta`, `Done`, `Error`. That's the whole contract. Every provider adapter implements a single async trait, `LlmProvider`, whose core method is `stream(&LlmRequest) -> Receiver`. Wire-format translation happens inside the adapter, where it belongs. The agent loop above it stays vendor-blind.

Vendor quirks don't get hardcoded. There is no `if base_url.contains("openai.com")` branch anywhere. The differences — field names, message-shape rules, which API surface to hit, reasoning vs. thinking, tool-array caps, temperature support, cache markers — live in one configuration layer, `ProviderCompat`: 31 `Option` fields where `None` means "use the provider's default." 24 preset constructors set those defaults per vendor, and a single map binds each of the 23 built-in providers to its preset. Your config layers on top. Every field resolves as `user.or(default)`, so anything you set wins and anything you leave alone keeps the shipped default. Adapters then read compat instead of sniffing URLs: `api_path()`, `max_tokens_field`, `uses_responses_api()`, `supports_temperature`, `include_usage_in_stream`, and the rest.

- **23 built-in providers, one `--provider ` switch.** The slug picks the wire, the base URL, and the compat preset.
- **Point any OpenAI-compatible backend at a built-in wire** with a custom alias — set `provider`, `model`, `api_key`, `base_url`, and you're done. No code.
- **Override a quirk in config, not in a fork.** A self-hosted server that rejects `stream_options`? `include_usage_in_stream = false`.
- **Data-driven pricing.** A bundled `pricing.toml` — 46 model rows across 25 provider tables — computes per-token cost in integer microcents from per-Mtok USD rates. Swap the whole catalog with `WAYLAND_PRICING_PATH`.
- **Resilience is built in.** Transient failures retry automatically, with multi-key rotation on supported providers; opt into a circuit breaker plus same-provider model fallback with one `[provider_chain]` block.

```toml
# Point a custom backend at the OpenAI wire, then bend one quirk
[providers.my-service]
provider = "openai"
model    = "custom-model-v1"
base_url = "https://my-service.example.com/api/openai"

[providers.my-service.compat]
include_usage_in_stream = false   # self-hosted server rejects stream_options
```

## Orchestration & swarms

A single agent is the floor, not the ceiling. Wayland Core fans one task out across many workers and brings the results back, with real isolation between them. Three distinct mechanisms ship in the code, and a four-tier topology model governs all of them: **Spawn** (5 agents), **Swarm** (20), **Mesh** (50), **Fleet** (100). Each tier fixes the agent cap, how much the parent sees, and the blackboard scope — and the caps are enforced, not advisory. Ask for 51 agents on a 50-cap tier and you get `TopologyError::ExceedsCap`, not a quietly-truncated run.

- **Sub-agents (`Spawn`)** fan parallel work out from one tool call. Each sub-agent gets its own conversation context and its own tool access; the count is capped by the active topology (default Spawn, 5).
- **Worktree swarm** runs N workers as OS subprocesses, each in a fresh `git worktree` on its own branch. A dirty-checkout guard runs `git status --porcelain` first and **refuses to dispatch on an uncommitted tree** — that guard exists because a contamination incident in v0.2.2 taught us why it has to. Per-worker timeouts, `kill_on_drop` SIGKILL on expiry, and idempotent `git worktree remove --force` cleanup. Process isolation, not threads, so one bad worker can't corrupt another.
- **In-process dispatchers** (`MeshDispatcher`, `FleetDispatcher`) are library primitives: they coordinate caller-supplied agent closures over a shared blackboard, enforce the tier cap, apply a timeout, and reduce the reports. Fleet partitions agents into shards (default 10) under topic prefixes like `fleet//shard-/`. They coordinate and reduce; spawning the agents is the orchestrator's job.

Every worker spawn goes through argv mode — `Command::new(program).args(args)`, no shell interpreter — so worker commands are never re-parsed by a shell. Final stdout/stderr come back through `collect()`; opt-in heartbeats (`.swarm-status.json`, ~5s tick) give you liveness without consuming the result.

Roll the results up however the job needs. The `wayland-core swarm` CLI dispatches the worktree path and routes the collected results through one of four reducers:

```bash
# Run the test suite across 4 isolated worktrees, roll up pass/fail/total
wayland-core swarm --workers 4 --worker-command "cargo test" \
  --base-branch main --branch-prefix swarm/ci --timeout 30m --reduce fleet

# Strict >50% majority over normalized worker stdout
wayland-core swarm --workers 5 --worker-command "pytest" --reduce consensus
```

- `mesh` — verbatim passthrough of every worker result.
- `fleet` — succeeded / failed / total roll-up.
- `consensus` — strict majority: a bucket wins only if its votes are more than half of the *successful* workers, otherwise the top three are returned as disputed.
- `debate` — first round whose workers agree wins; at the CLI the batch is a single round (multi-round replay lives in the orchestrator, not the CLI path).

Topology is pure data with cap enforcement, the guards have tests behind them (58 across the swarm crate), and the live TUI labels the running tier by sub-agent count — 0-5 Spawn, 6-20 Swarm, 21-50 Mesh, 51+ Fleet. One note on reach: the standard monitored relay clamps Spawn fan-out to the Mesh cap of 50, so the 100-agent Fleet ceiling is the unmonitored library path, not the everyday `Spawn` call.

## Crucible — a Mixture-of-Providers council

Crucible is a council of rival providers. Hand it a hard task and it fans out to N sub-agents, each pinned to its *own* LLM provider — Anthropic, OpenAI, DeepSeek, GLM, Kimi, Gemini, Flux-routed models — that answer in parallel; a separate, read-only judge then fuses them into one. The diversity is the whole point: cross-vendor, not one family arguing with itself. We call it **Mixture-of-Providers**.

*Convening a council live in the TUI: two proposers pinned to different vendors, an independent judge from a third, the certified ceiling ($0.70) beside the single-model cost ($0.49), the daily envelope, and the gate's reasoning — all on the table before you approve a cent.*

*…and the fused output: a three-vendor council ranking the audit by severity — every proposal, provider, and cost on the table. Head-to-head benchmarks (Crucible vs. router-level mixtures vs. solo frontier models, cost-matched) are in flight.*

It's off by default. List a roster in a `[crucible]` block:

```toml
[crucible]
enabled    = true
proposers  = ["anthropic:claude-opus-4-7", "openai:gpt-5", "deepseek:deepseek-v4-pro"]
aggregator = "anthropic:claude-opus-4-7"   # optional; falls back to the first usable proposal
```

Then run it: `wayland-core crucible "do a security audit of this deployment plan"`.

Each member pulls its *own* credentials from your `[providers]` map, so a council is genuinely keyed across vendors, not one key wearing hats. Routing prefixes don't defeat that — a Flux-pinned GPT-5 and a direct `openai:gpt-5` collapse to the same vendor family, so the judge stays independent and an Auto roster stays diverse.

Then the cost discipline, because N models answering one question costs N times as much:

- **A deterministic preflight gate decides whether to convene at all.** A zero-LLM keyword/length classifier reads the *leading* instruction span and sizes the roster by stakes — low goes Direct (one call), medium pulls 3 members, high pulls 5. A high-stakes word buried in a pasted stack trace won't escalate it.
- **Two roster modes.** Manual: you list the providers. Auto: a deterministic Assembler picks a cost-effective, vendor-diverse roster per task, and you can `--deny` a vendor or force `--deep`.
- **Spend is gated before anything spawns.** A judge-inclusive worst-case ceiling is certified up front. The per-run `max_cost_usd` cap is strict — an unpriceable roster under a cap is refused, not run. A default-on $20/user/day envelope rides on top.
- **It fails closed.** In a non-interactive session it refuses to spend unless you've explicitly opted in. On a TTY it prints a cost card and waits for Y/n.
- **The judge can't touch your machine.** The aggregator is a read-only sub-agent — no `Bash`, no `Write`, no `Edit`, by construction. Every proposal reaches it wrapped in untrusted-data fencing with forged section delimiters neutralized, so one poisoned proposer can't hijack the synthesis.

Fan-out is bounded by a per-route semaphore, and tail latency is capped: each proposer gets a hard deadline, and once quorum is met a global soft-deadline cancels the stragglers — timed-out members are kept as errored proposals so the provenance stays honest. The fused answer is either printed (Terminal mode) or injected as private guidance into the normal tool-using loop (Advisor mode, `--advisor`).

Shipped in v0.12.11. The council pipeline carries 84 unit tests plus 31 integration tests across the gate, resolver, roster validation, budget, fan-out, and injection-fencing paths.

**Where it's honest about its edges.** Some Flux-routed SKUs are unpriced today, so a Flux council can't always certify a hard ceiling — that's exactly why the per-run cap is opt-in and the daily envelope only soft-binds on Flux, accruing from actual usage instead of refusing up front. The daily envelope binds within a process, not yet across separate CLI runs. The convene-or-not gate is a deterministic heuristic, not a learned router. And the shipped invocation surface is the `wayland-core crucible` batch command; the slash command, natural-language tool, and full TUI/desktop approval cards are designed, not all shipped.

## Security by default (fail-closed)

Security here is a posture, not a checkbox. When the safe thing and the convenient thing disagree, the engine picks safe and makes you opt out on purpose. Four mechanisms carry that, and they hold up when someone reads the source.

- **No unsandboxed default.** Model-driven shell and tools run inside an OS-native sandbox — bubblewrap on Linux, `sandbox-exec` on macOS, AppContainer on Windows, Docker if you opt in. When no real sandbox is available, execution is refused, not quietly downgraded to host permissions. Running with no isolation takes an explicit `WAYLAND_ALLOW_NO_SANDBOX=1`. A stray `WAYLAND_SANDBOX=none` does nothing without it.
- **One egress chokepoint, enforced by a lint.** Every outbound HTTP request flows through a single client, and a clippy lint bans constructing a raw `reqwest` client anywhere else — so a missed migration fails the build instead of leaking a hole. On that seam sits a fail-closed host allowlist for untrusted URLs, an exfil-shape classifier that hard-denies suspicious POSTs and high-entropy paths to non-allowlisted hosts, a hard byte-cap body reader, and a resolve-once resolver that re-checks the IP at connect time to close DNS-rebinding races. Deny stops *before* the socket opens. Shared multi-tenant suffixes — `amazonaws.com`, `*.workers.dev`, `*.vercel.app`, around 45 of them — can never be apex-allowlisted.
- **SSRF and metadata floor, always on.** Cloud-metadata endpoints (`169.254.169.254` and the GCP, AWS, Alibaba, and Oracle equivalents) and lookalike hosts are rejected outrigh

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [FerroxLabs](https://github.com/FerroxLabs)
- **Source:** [FerroxLabs/wayland-core](https://github.com/FerroxLabs/wayland-core)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** yes
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-ferroxlabs-wayland-core
- Seller: https://agentstack.voostack.com/s/ferroxlabs
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
