
Lightweight Agent Messaging Without a Heavy Control Plane
AxiOwl's current C++ implementation treats agent messaging as a local routing problem, not as a hosted control-plane problem. The product is built around a native executable, CLI and MCP entry points, a durable local registry, JSONL evidence logs, and provider-specific delivery edges. That is the important distinction: AxiOwl coordinates messages between existing AI provider sessions without requiring every message to pass through a separate always-running broker service.
"Lightweight" here is not a benchmark claim. It is an architecture claim. The source shows a system that keeps the routing surface close to the user's machine, records state in local files, launches the same executable in specific modes, and makes provider handoff boundaries explicit.
Sources read
Source repo: C:\Users\kjhgf\OneDrive\Documents\postfourth\axiowl-cplus
README.mdapps/windows-desktop/README.mddocs/developer/README.mddocs/user/README.mddocs/reference/architecture-overview.mddocs/reference/provider-support-matrix.mddocs/reference/installer-behavior-matrix.mddocs/installer/README.mddocs/support/forensics.mdapps/windows-desktop/CMakeLists.txtapps/windows-desktop/src/main.cppapps/windows-desktop/src/app_paths.hppapps/windows-desktop/src/app_paths.cppapps/windows-desktop/src/registry.hppapps/windows-desktop/src/registry.cppapps/windows-desktop/src/evidence_log.hppapps/windows-desktop/src/evidence_log.cppapps/windows-desktop/src/message_pipeline.hppapps/windows-desktop/src/message_pipeline.cppapps/windows-desktop/src/delivery_worker.hppapps/windows-desktop/src/delivery_worker.cppapps/windows-desktop/src/provider_edges.hppapps/windows-desktop/src/provider_edges.cppapps/windows-desktop/src/provider_remote.cppapps/windows-desktop/src/remote_relay.cppapps/windows-desktop/src/mcp_server.cppapps/windows-desktop/src/cli.cppapps/windows-desktop/src/service_config.hppapps/windows-desktop/src/service_config.cppapps/windows-desktop/src/create_lifecycle.cppapps/windows-desktop/tests/core_tests.cppapps/windows-desktop/tests/mcp_conformance.ps1apps/windows-desktop/tests/installer_robustness_guard_tests.cpp- Built CLI help output from
apps/windows-desktop/build/Release/axiowl.exe --help
What AxiOwl Keeps Small
The Windows desktop README states the current implementation status plainly: the CLI skeleton, fixed send pipeline, create-session pipeline, TSV registry, final visible body builder, JSONL evidence log, provider edge interface, and live provider delivery for current local Windows edges are implemented. The same status block says the local always-running service is not implemented yet.
That shapes the whole product. The Windows build is described as a local coordinator, registry owner, and outbound SSH remote provider. The Linux build is described as a remote Codex endpoint, relay-session receiver, and Codex CLI delivery surface only. The reserved local endpoint is 127.0.0.1:37661, but run_status in cli.cpp reports that the local service is not implemented yet and that the CLI is running a direct local pipeline skeleton.
So the current control path is intentionally modest:
- A user or provider calls
axiowl.exe. - The CLI or MCP handler resolves the request.
- A local registry row determines the target route.
- A provider edge handles the provider-specific delivery attempt.
- Logs record the receipt, handoff, and provider evidence.
That is different from building a permanent central scheduler, database service, web API, queue, and worker fleet just to move a message between local provider sessions.
One Executable, Several Entry Points
The root executable is direct. main.cpp collects argv and calls axiowl::run_cli(args). The CLI help confirms the main command surface:
sendcreaterenamediscoverlist agentsdoctor inventoryprovider smoke-testnode list,node add, andnode verifyregistry add-agent,registry remove-agent, andregistry add-nodemcp-servermcp-self-testdelivery-workerrelay-session --stdio- license commands
status
That shape matters. AxiOwl does not need a separate user-facing service process for ordinary command entry. The executable can be used as a CLI, as a stdio MCP server, as a detached delivery worker, or as a relay-session endpoint.
The build file reflects the same layout. CMakeLists.txt builds axiowl_core, then links the axiowl executable against that core. It also builds installer helper executables, but the runtime command surface is centered on axiowl.exe. The install target places axiowl under bin, and the Windows README lists the native MCP server and internal delivery worker as modes of the same installed executable:
%LOCALAPPDATA%\AxiOwl\bin\axiowl.exe
%LOCALAPPDATA%\AxiOwl\bin\axiowl.exe mcp-server
%LOCALAPPDATA%\AxiOwl\bin\axiowl.exe delivery-worker
That is the first practical reason the system stays lightweight. The product can add capabilities without forcing each capability into a new daemon.
MCP Without A Network Listener
AxiOwl's MCP server is also local and stdio-oriented. mcp_server.cpp reads either line-based JSON-RPC messages or framed MCP messages with Content-Length headers from standard input. It writes responses to standard output. The MCP conformance test starts axiowl mcp-server --host codex --provider codex, verifies initialize, verifies tools/list, calls axiowl_version, and checks both line and framed protocol modes.
The tools exposed by the MCP server map back to the same CLI operations. axiowl_send_message builds a send argument list and calls the CLI path through run_cli_captured. axiowl_create_agent similarly builds a create command. Simpler tools such as list agents, status, version, node operations, registry add, discovery, and relay delivery are also routed into the local CLI implementation.
The MCP server's tool description is careful about the receipt boundary: success from axiowl_send_message is an MCP-to-AxiOwl handoff receipt only. Provider delivery and reply are not implied. That is a small but important design choice. The MCP surface does not pretend that a local tool call proves end-to-end delivery. It gives the provider a local tool interface, then the message pipeline and provider edge record what actually happened next.
Local Files Instead Of A Central Registry Service
A heavy control plane normally needs a persistent database service or a remotely hosted routing table. AxiOwl's current registry is local file state.
app_paths.cpp defines the state root. On Windows it uses %LOCALAPPDATA%\AxiOwl. On Linux-style environments it uses $XDG_STATE_HOME/axiowl or falls back to ~/.axiowl. Under that root, AxiOwl keeps:
registry\agents.tsvregistry\nodes.tsvlogs\events.jsonllogs\delivery.jsonllogs\create-lifecycle.jsonllogs\activation.jsonllicense\activation.json- runtime state such as
runtime\send-rate-limit.txtandruntime\send-rate-limit.lock
registry.cpp loads and saves the agent registry as TSV. A registry row includes the display name, aliases, provider, provider session id, node id, enabled state, sendable state, source, timestamps, and last error. Node records are stored separately in nodes.tsv.
The tests cover the plain-file model directly. core_tests.cpp checks registry roundtrips, node registry roundtrips, duplicate-name lookup behavior, session lookup behavior, and discovery merge behavior. It also checks that weak evidence-only Codex rows do not silently become sendable registry rows.
That is not a toy implementation detail. It is the difference between inspectable local state and opaque control-plane state. If an operator is debugging a bad route, the support docs point first to:
%LOCALAPPDATA%\AxiOwl\logs
%LOCALAPPDATA%\AxiOwl\registry
%LOCALAPPDATA%\AxiOwl\runtime
The operator can inspect which registry row was selected, whether it was sendable, where it came from, what the latest error was, and which delivery stage was logged.
The Send Path Is Direct, But It Has A Clear Handoff Boundary
The message pipeline is where the lightweight design becomes concrete.
MessagePipeline::send creates a message id, records that the request entered the pipeline, validates target and body, resolves sender identity, performs targeted discovery repair when needed, resolves the target registry row, checks sendable, builds the final visible message body, and starts delivery.
The receipt boundary is explicit. After target resolution but before provider delivery completes, the pipeline sets:
accepted_by_axiowl
It also logs delivery_receipt=axiowl_only and records that the receipt boundary is after target resolution and before delivery worker or provider work. Then it hands the provider request to the delivery worker.
The core test test_send_returns_axiowl_receipt_then_starts_delivery_handoff protects that behavior. It expects an AxiOwl receipt to be accepted by AxiOwl, not accepted by provider. It expects the receipt state to be accepted_by_axiowl. It expects the log to show the receipt boundary and a background delivery handoff. It also expects the sender receipt path not to wait for a provider result.
This is lightweight messaging with a realistic contract. AxiOwl accepts, validates, resolves, and hands off locally. It does not claim that local acceptance equals provider receipt. The stronger proof is still a provider reply through AxiOwl MCP with correct sender identity.
The Delivery Worker Is A Mode, Not A Control Plane
The delivery worker is the main place where AxiOwl avoids blocking the sender while still keeping provider delivery separate from initial receipt.
delivery_worker.cpp writes a temporary JSON request file, locates an AxiOwl executable, and starts axiowl delivery-worker --request <request-json-file> detached for normal handoff. The worker then parses that request, validates it, dispatches to deliver_to_provider, prints a structured worker result, appends evidence, and removes the request file after dispatch.
That design gives AxiOwl a background handoff without requiring a long-running queue service. The handoff has state, but it is a bounded request file. The provider result has structured fields, but it is produced by the same executable running a different command. Delivery evidence lands in the same JSONL log system.
The distinction is practical. A separate daemon can be added later if the product needs it. The current code already reserves a local service endpoint and tests the endpoint string. But today's implementation does not depend on that service for the normal CLI/MCP send path.
Provider Edges Keep The Center Small
The center of AxiOwl is not packed with provider-specific branching. provider_edges.cpp is a dispatch table. It normalizes the provider value and routes delivery, create, or rename to provider modules such as Codex, Codex CLI, VS Code native, VS Code Copilot-backed, Antigravity, Cursor, Claude Code CLI, Copilot CLI, OpenCode CLI, and related provider-specific code.
Unknown providers fail with a clear error. Unsupported create and rename paths return structured unsupported results. For the current local-provider remediation build, remote delivery is explicitly returned as out-of-scope in the provider edge dispatch, and the current provider support matrix marks remote unsupported for local provider support. The remote-oriented files still show the intended mechanics: provider_remote.cpp uses SSH to invoke axiowl relay-session --stdio, and remote_relay.cpp handles JSONL relay frames over stdin/stdout. But the support matrix is clear that remote should not become a fallback for local provider failures.
This edge model keeps the control layer small. AxiOwl's common pipeline does not need to know every private detail of VS Code, Cursor, Codex, or Antigravity. It needs a registry row, a sender identity, a final visible body, and a provider edge result. Provider-specific risk stays in provider-specific modules.
Install Footprint Follows The Same Pattern
The installer docs describe a local install under %LOCALAPPDATA%\AxiOwl. The core install includes bin\axiowl.exe, a manifest/provenance file, runtime directories, registry directories, logs, and selected provider integration files.
Selected provider features may install MCP config, provider bridge extensions, provider patches, CLI config, discovery records, and AxiOwl-owned wrappers or config files. The installer behavior matrix is explicit that provider features behave like separate install units. Unchecked provider features should not be installed, patched, closed, restarted, or removed as collateral damage.
That is another way AxiOwl avoids a heavy control plane. The installer does not assume every provider should be controlled. It detects provider surfaces, lets provider checkboxes drive install actions, and records proof and logs. For example, Codex support can install plugin and MCP integration. VS Code and Cursor support can install bridge extensions and selected patches. Antigravity can receive MCP config. CLI providers that still need metadata work remain target surfaces rather than being declared fully supported just because a config file can be written.
The result is a local coordination footprint, not a central management plane that takes ownership of every provider on the machine.
Why This Matters For Operators
Lightweight architecture is useful only if it makes operations clearer. In AxiOwl, it does.
When a message fails, the support docs tell operators not to collapse distinct events into one outcome. MSI install success, accepted_by_axiowl, provider acceptance, and MCP reply are different stages. That separation prevents false positives. A successful install does not prove a provider can reply. An AxiOwl receipt does not prove provider display. A provider acceptance result is still weaker than a real MCP reply from the target provider.
The local files make those stages reviewable:
- The registry shows the selected route.
- The
sendablefield explains whether AxiOwl is willing to target that row. source,last_seen_at,last_verified_at, andlast_errorshow how fresh and trustworthy the row is.events.jsonlrecords pipeline decisions.delivery.jsonlrecords delivery stages.create-lifecycle.jsonlrecords create and rename lifecycle events.- Runtime files show temporary handoff and rate-limit state.
For developers, the same design keeps the codebase easier to reason about. The CLI, MCP, registry, pipeline, delivery worker, provider edges, and installer checks are separate modules, but they do not depend on a hidden background control service to make basic behavior work.
Closing
AxiOwl's current implementation is lightweight because it uses local executable modes, stdio MCP, local registry files, JSONL evidence, direct pipeline logic, and provider-specific edges instead of a permanent central control plane. It still has real routing discipline: sender identity must resolve, targets must be sendable, discovery must have proof, receipts have clear boundaries, and provider delivery is logged separately from local acceptance.
That is the useful middle ground for agent messaging. AxiOwl can coordinate existing provider sessions without pretending to own the providers, and it can leave behind enough local evidence for an operator to understand exactly where a message stopped.
Image prompt:
Create a polished graphic image related to: lightweight agent messaging without a heavy control plane.
Subject: a compact desktop routing device sending thin glowing message paths between several small terminal windows and provider connector modules, with no central server tower, no labels, and visible lightweight file cards beside the router.
Style: halfway between a clean symbolic icon and a realistic product/technical illustration; professional SaaS/technical marketing style; crisp edges; high detail; no text; no logos.
Background: solid #00ff00 chroma key green screen background covering the full canvas edge to edge.
Restrictions: no owl, no axolotl, no birds, no animals, no mascot, no text, no watermark.