Skip to content

Architecture Overview

Wayland Core is a Cargo workspace of ~53 crates under crates/. Each crate owns a single domain; dependencies flow strictly downward through four layers. Nothing in the tree except wcore-cli depends on everything else, so individual crates compile and test in isolation.

CratePurpose
wcore-typesProvider-neutral data types: LlmRequest, LlmEvent, Message, ContentBlock. Every higher layer speaks this vocabulary.
wcore-compactContext compression algorithms: token folding, sanitization, CompactionLevel (Off / Safe / Full).
CratePurpose
wcore-configConfiguration cascade (WAYLAND_HOME / XDG / project-local .wayland-core.toml), ProviderCompat declarative-quirks table, credential vault, cross-platform shell helpers (shell_command_argv / shell_command).
wcore-protocolJSON-Lines host protocol: ProtocolCommand enum (10 inbound commands), ProtocolEvent enum (~25 event types), ToolApprovalManager.
wcore-plugin-apiPlugin trait, PluginContext, scoped registries. Isolation boundary: plugins have no dependency on wcore-browser, wcore-cua, or wcore-agent.
wcore-egressSingle outbound-HTTP chokepoint (EgressClient). A clippy.toml disallowed-methods lint bans reqwest::Client::new/builder everywhere else in the workspace so no network call can bypass the egress policy.
wcore-providersLlmProvider trait and all provider implementations.
wcore-pricingBundled pricing.toml with Q2-2026 list prices; token accounting types.
wcore-budgetExecutionBudget (7-axis tree), per-session and per-user-daily caps, CapWarn (80%) / CapBlock enforcement.
wcore-tools~75 built-in tools registered through bootstrap.rs. Tools absent their required env credentials are not registered at all (the NO-STUBS contract).
wcore-mcpMCP client (stdio / SSE / streamable-HTTP) and mcp-serve server.
wcore-skillsSkill front-matter parsing, variable substitution, shell expansion, conditional activation, per-skill permissions, SkillRouter, SkillWatcher.
wcore-memory5-partition x 3-tier SQLite store, auto-memorize, pluggable embedders, background decay.
wcore-sandboxSandboxBackend trait with platform backends: BubblewrapBackend (Linux), SandboxExecBackend (macOS), AppContainerBackend (Windows), DockerBackend (opt-in). Fail-closed default.
wcore-browser18-op ARIA-tree-first browser surface over Camoufox (default), chromiumoxide (opt-in chromium feature), or Browserbase (env-gated).
wcore-cuaComputer-use actions on macOS (CGEvent), Linux X11 (XTest), Linux Wayland (wlrctl/grim), Windows (UI Automation). First-time-per-app approval gate.
wcore-permissionsACL, bearer tokens, learned approval policy. See the status matrix for current wiring state.
wcore-observabilityTrace schema, span sinks, PII scrubber (28 patterns), OTLP exporter (off by default; enable with the otlp cargo feature).
wcore-safetyPre-exec content scan, URL safety checks, path validation, OSV dependency check.
wcore-repomapAider-style light symbol extractor and codebase index. No internal wcore-* deps by design.
wcore-user-modelUser preference and expertise backend abstraction (UserModelBackend). LocalBackend ships by default; wcore-honcho-adapter wires an alternative persistent backend.
wcore-compact(see bottom layer)
wcore-evalDeterministic skill-quality gate: 60-case corpus, precision/recall thresholds, gates GEPA evolution.
wcore-eval-scenariosScenario-level E2E harness: drives the real binary in --json-stream mode against real LLM APIs, asserts outcomes via LLM-as-judge.
wcore-evolveGEPA offline evolutionary optimizer: 4 mutators, plateau termination, graveyard, CuratorPort, PromptStore. Runs as a separate binary, not in-session.
wcore-replaySession-trace replay and diff for debugging.
wcore-dispatchInternal task dispatch primitives used by the agent loop.
wcore-cronCron scheduler: 5-field expressions, 3 target types (slash command / channel message / skill), CLI integration, cronjob LLM tool.
wcore-acpAgent Client Protocol: HTTP/SSE + stdio + WebSocket JSON-RPC 2.0, session CRUD, message/send. See the status matrix for completeness notes.
wcore-channelsChannel trait and shared channel types.
wcore-channels-registryAuto-registers channel adapters from ~/.wayland/channels/*.toml.
wcore-channel-slackSlack adapter.
wcore-channel-discordDiscord adapter.
wcore-channel-telegramTelegram adapter.
wcore-channel-signalSignal adapter.
wcore-channel-whatsappWhatsApp adapter.
wcore-channel-smsSMS adapter.
wcore-channel-emailEmail adapter.
wcore-channel-matrixMatrix adapter.
wcore-channel-msteamsMS Teams adapter (send-only; inbound deferred to v0.8.3).
wcore-channel-imessageiMessage adapter (macOS only).
wcore-fixture-harnessShared test fixture utilities.
wcore-swarmWorktree-isolated multi-agent dispatch. 4 topologies: Spawn (5), Swarm (20), Mesh (50), Fleet (100). Consensus and Debate overlays.
wcore-plugin-subprocessSubprocess plugin host (JSON-RPC/stdio).
wcore-plugin-wasmWASM Component Model plugin host (wasmtime + WASI).
wcore-honcho-adapterBridges UserModelBackend to a Honcho client for persistent cross-device user state.
CratePurpose
wcore-agentThe agent engine: AgentEngine::run, session management, tool dispatch, ForgeFlows workflow runner (RON DSL to GraphConfig IR to WorkflowRunner), plan mode, sub-agent spawning, self-evolution drafter, HITL approval.
wcore-cliBinary entry point. Three run modes: interactive TUI, one-shot positional prompt, --json-stream headless. 13 top-level subcommands.

Plugin crates (extend via wcore-plugin-api, no upward deps)

Section titled “Plugin crates (extend via wcore-plugin-api, no upward deps)”
CratePurpose
wayland-ollamaOllama local-inference provider. Registers via register_providers only.
wayland-browserPlugin packaging of wcore-browser via mirror types in wcore-plugin-api.
wayland-cuaPlugin packaging of wcore-cua via mirror types in wcore-plugin-api.
wayland-ijfwIJFW anchor plugin exercising every register_* surface.
wayland-honchoHoncho client library used by wcore-honcho-adapter.

Four traits define the primary extension boundaries. Provider, channel, tool, and routing implementations are registered by name and resolved at runtime; adding a new variant does not require modifying the engine.

Defined in wcore-providers. Every provider implementation converts between LlmRequest / LlmEvent (the provider-neutral types from wcore-types) and the wire format of its target API. Provider quirks (field naming, token-count field, schema sanitization, streaming shape) are declared in ProviderCompat rather than as conditionals in engine code. The engine calls provider.complete(request) and never inspects the provider type.

// wcore-types: what the engine sees
pub struct LlmRequest { /* model, messages, tools, params */ }
pub enum LlmEvent { TextDelta, ToolRequest, StreamEnd, /* ... */ }
// ProviderCompat (wcore-config/src/compat.rs:10): declares quirks as data
pub struct ProviderCompat {
pub max_tokens_field: Option<String>, // "max_tokens" vs "max_completion_tokens"
pub sanitize_schema: Option<bool>, // some providers reject unknown schema keys
// ~18 more fields
}

Defined in wcore-channels. Each of the 10 channel adapter crates implements Channel and is auto-registered at startup from ~/.wayland/channels/*.toml. The engine dispatches outbound messages through the registry by channel name; adding a new adapter is a new crate, not an engine change.

Tool (via wcore-tools and wcore-plugin-api)

Section titled “Tool (via wcore-tools and wcore-plugin-api)”

Built-in tools are registered in wcore-agent/src/bootstrap.rs. The NO-STUBS rule applies here: tools whose required environment credentials or system dependencies are absent are not registered. A tool that is registered is expected to be fully functional. Plugins register additional tools through PluginContext::register_tool using the mirror types in wcore-plugin-api, with no dependency on wcore-agent or wcore-tools.

Defined in wcore-sandbox. Platform backends implement SandboxBackend::execute(manifest, command) -> SandboxOutput. The dispatcher in default_for_platform() selects the strongest available backend at spawn time. If no real backend is available and WAYLAND_ALLOW_NO_SANDBOX=1 is not set, the engine refuses execution rather than falling back to unsandboxed host execution.

Wayland Desktop is an Electron application. It embeds Wayland Core as a subprocess and communicates exclusively through the wcore-protocol JSON-Lines protocol (--json-stream). Desktop renders the conversation, approval UI, and sub-agent monitors. The engine does the agent loop, tool dispatch, provider routing, and security enforcement.

The protocol commands include ToolApprove, ToolDeny, ApprovalResume, AddMcpServer, and others. The engine’s contract is complete on its side. One known gap exists in Desktop: WCoreCommand is currently missing the ApprovalResume arm, which means HITL-gated tool calls dispatched from the Desktop GUI can hang until the app-side fix lands. The engine contract itself is correct; the fix is entirely in the Desktop codebase.

This boundary also means Wayland Core is fully usable without Desktop. The same binary runs as a terminal agent, as a headless subprocess behind any host, or as an MCP server.

Dependencies flow downward. wcore-types has no internal deps. wcore-cli may depend on anything. Plugin crates in the wayland-* namespace may depend on wcore-plugin-api and wcore-types but not on wcore-agent, wcore-tools, wcore-browser, or wcore-cua directly. The build enforces this via build.rs lint checks in wcore-plugin-api. Circular or upward references break the build.