AxiOwl Message Routing Explained

AxiOwl message routing is the part of AxiOwl that turns a human target name, such as a known Codex thread or VS Code chat, into a provider-specific delivery attempt. It is not just a text forwarder. The current AxiOwl C++ implementation keeps a local registry of sessions, resolves sender identity, checks whether the target is sendable, builds a visible message body with reply instructions, and then hands delivery to the correct provider edge.

That distinction matters because AxiOwl is designed for real operator workflows, not toy chat relay. A message should go to the named session the sender intended, and a reply should be able to find its way back to the original sender without asking the receiving agent to invent a route.

The Short Version

In the current Windows desktop implementation, the core routing flow is:

CLI or MCP tool call
-> axiowl.exe
-> command handler
-> MessagePipeline
-> sender and target resolution
-> targeted discovery repair when needed
-> provider edge dispatch
-> delivery worker
-> provider-specific write or handoff
-> evidence and delivery logs

The public shape is simple. A user or agent can send with the CLI:

axiowl send --to "<agent>" --body "<message>"

Provider-hosted agents normally use the MCP tool instead:

axiowl_send_message

The MCP server description in the implementation is explicit about the receipt boundary: success is an AxiOwl handoff receipt only. It does not automatically prove that the provider displayed the message, acted on it, or replied. AxiOwl separates "accepted by AxiOwl" from provider delivery proof and from the strongest proof, which is an actual response coming back through AxiOwl MCP with correct sender identity.

Routing Starts With Identity

AxiOwl has to know two things before it can route a message:

  1. Who is sending.
  2. Which registered target should receive the message.

For CLI sends, the pipeline can use explicit sender information when available. For MCP sends, the source code is stricter: the host MCP session ID is treated as the stable sender identity key. The server instructions tell provider agents to use axiowl_send_message and not construct raw command lines or provide --from manually.

This is not cosmetic. Reply routing depends on a real provider session identity. If AxiOwl only had a display name guessed from the prompt, the receiving agent might be given a reply path that points to the wrong session or a stale session. The architecture docs call this out directly: MCP sender identity must come from provider metadata or a provider patch that supplies metadata programmatically. Environment-only identity is not considered enough for final provider CLI support.

The Registry Is The Routing Table

AxiOwl's registry is the durable local routing table. A registry row represents a reachable provider session or agent. Important fields include:

When MessagePipeline::send receives a request, it validates that the target and body are not empty, resolves the sender, and then asks the registry for the target. If the target is missing or needs repair, the pipeline runs one targeted discovery attempt. That is deliberately limited. Discovery can repair stale inventory, but it is not treated as delivery proof.

If the target is still missing after discovery, AxiOwl rejects the send with a specific error. If the target exists but is marked not sendable, AxiOwl also rejects the send and includes the target's last error when available.

The Receipt Boundary

One of the most important implementation details is where AxiOwl says "accepted."

The pipeline marks a message as accepted_by_axiowl only after the target has resolved to a canonical registry row and the row is sendable. The evidence log records that this receipt is an AxiOwl-only receipt at the boundary after target resolution and before provider delivery completes.

That design prevents a common operations mistake: treating a local router receipt as proof that a provider session actually saw the message. AxiOwl's architecture separates three levels:

For real diagnostics, that third level is the strongest signal.

Final Visible Body And Reply Instructions

Before AxiOwl hands the message to a provider edge, it builds the final visible body. The source in final_visible_body_builder.cpp shows the practical intent: the target sees the original message plus a reply instruction block that points back to the sender with an axiowl_send_message MCP call.

When the sender is resolved, the final visible body starts with a "Message from …" line, includes the original body, and appends a reply instruction containing the sender name, run ID when present, and receipt message ID when present. This makes replies operationally simple for receiving agents: they do not need to guess where the answer belongs.

The same code also records body policy details, including whether activation state caused a license warning to be appended. That policy is logged during delivery handoff, so the operator can inspect what kind of message body was actually sent.

Provider Edges

Provider dispatch happens through provider_edges.cpp. The provider field from the registry row is normalized and mapped to a provider-specific implementation.

Current provider edge names in the dispatch table include:

The provider support matrix is more conservative than the dispatch list. It marks several surfaces as supported, including Codex agents, Codex CLI, VS Code native agents, VS Code Copilot-backed chat, Cursor agents, and Antigravity agents. It marks some CLI surfaces as targets rather than fully supported because current support requires provider-owned metadata and response-backed proof. That is an important difference: having code paths is not the same thing as meeting the support bar.

Delivery Worker Handoff

AxiOwl uses a delivery worker layer for provider delivery. The message pipeline writes a provider request and starts a delivery worker in the background. The worker parses the request, logs stages, calls deliver_to_provider, prints a structured result, and records whether the provider write succeeded, failed, or was accepted only in an unverified way.

This is why a send can return quickly while provider delivery continues. It also gives AxiOwl a cleaner evidence trail. The delivery logs include stages such as request acceptance, target resolution, route resolution, delivery worker handoff, provider write start, provider write success, provider handoff started unverified, or provider write failure.

For operators, those stages are the difference between "AxiOwl could not find the target," "AxiOwl handed the request to the provider edge," and "the provider edge reported a result."

Remote Routing Is Explicit, Not A Fallback

The source tree includes relay-session --stdio handling and remote_relay.cpp, which can receive JSON deliver frames and pass them through direct provider delivery or the normal message pipeline. The Windows desktop README also documents remote node setup commands such as registering a node and registering a remote agent.

At the same time, the current provider support matrix and remote provider page mark remote as unsupported for local-provider remediation builds. The code in provider_edges.cpp returns an out-of-scope result for remote delivery in that build context.

That means remote routing should be understood as an explicit node contract area, not a silent fallback. AxiOwl should not hide a failed local provider send by quietly routing somewhere else. If remote delivery is enabled in a future or selected configuration, it needs its own target record, node identity, relay contract, and validation path.

What This Gives Operators

AxiOwl's routing model gives operators and developers a few practical advantages:

That separation is especially useful when multiple AI coding tools are open at the same time. A Codex thread, a VS Code native chat, a Copilot-backed VS Code session, a Cursor agent, and an Antigravity session do not share one native message API. AxiOwl's job is to normalize the operator-facing route while preserving the provider-specific delivery path underneath.

The Practical Mental Model

The easiest way to understand AxiOwl routing is to think of it as a local message coordinator with a strict registry and provider adapters.

The sender says, "send this body to that named agent." AxiOwl asks, "do I know who you are, do I know that target, is it sendable, and which provider owns it?" Only after those checks does it build the final visible body and hand the request to the provider edge.

That is the core of AxiOwl message routing: simple commands on the surface, explicit identity and registry rules underneath, and evidence boundaries that make delivery behavior inspectable when something goes wrong.