How AxiOwl Keeps Remote Routing Narrow

Remote routing is useful only when it stays specific. The moment a messaging tool treats "remote" as a general permission to scan machines, open ports, or guess delivery paths, it stops being an operator tool and starts becoming infrastructure sprawl. AxiOwl's current design takes the opposite approach: remote state is represented explicitly, remote discovery is bounded, and provider delivery must pass through the same registry and proof rules as local delivery.

That matters because AxiOwl is not trying to be a broad remote-control mesh. It is a local Windows coordinator for sending messages between named AI provider sessions. Its source tree separates the Windows desktop app, Linux desktop work, and a reserved Linux remote package area. The actual routing contract remains small: resolve one sender, resolve one target, choose one provider edge, and record what happened.

Remote Starts With a Node Row

AxiOwl does not treat every reachable host as a possible target. Remote machine awareness starts in the node registry, represented by NodeRecord in the source. A node row carries a stable node_id, display name, aliases, host, ssh_user, optional ssh_key_path, enabled state, verification timestamps, and last error.

The CLI exposes that boundary directly:

axiowl node list
axiowl node add --id <node-id> --host <host> --ssh-user <ssh-user> [--key <ssh-key-path>] [--name <display-name>] [--alias <alias>]
axiowl node verify --id <node-id>

Verification is deliberately plain. The implementation builds an SSH command with BatchMode=yes and ConnectTimeout=10, then runs a remote identity check:

hostname; whoami; pwd; hostname -I

If that check succeeds, the node receives a last_verified_at value. If it fails, the node row records a concrete SSH failure. This keeps node enrollment operationally inspectable: a node is not just a hostname in a hidden config file; it is a registry row that can be listed, verified, and diagnosed.

Agent Routing Still Uses One Registry Row

Remote support does not bypass the agent registry. AxiOwl's registry model maps a human target name to provider identity and node identity. In source, an AgentRecord includes display_name, aliases, provider, provider_session_id, node_id, enabled, sendable, source, timestamps, and last_error.

That shape is important. A remote target is not "anything on host X." It still has to resolve to one agent row. The message pipeline first validates the request body and sender, then looks up the target by name. If the row is missing or stale, AxiOwl can run a targeted repair attempt once. If the row is known but sendable is false, the send is rejected with "target is known but not sendable."

The practical effect is narrow routing by construction:

The registry is not a reasoning engine. The architecture docs say it should not invent provider facts. The implementation follows that rule by separating evidence-only discovery from sendable enrollment and by keeping last_error on rows that cannot be used.

Targeted Discovery Is Not a Remote Sweep

AxiOwl has discovery code, but discovery is not a blank check. The main pipeline's miss-handling path logs targeted_discovery_once, then tries local provider discovery in order. The current source explicitly excludes remote discovery from local targeted miss resolution, adding the issue "Remote discovery is out of scope for local targeted miss resolution."

The CLI makes the same boundary visible. axiowl discover supports local provider scopes such as codex, codex-cli, vscode-native, vscode-copilot, copilot-cli, antigravity, cursor, claude-code-cli, opencode-cli, and all. When the requested provider is remote, the current build returns an excluded report instead of sweeping remote nodes. When all is used, it runs the local provider discovery set and reports remote discovery as excluded from local all-provider discovery.

That is a conservative choice. It means a normal "find my target" operation does not fan out across every registered SSH host. Remote rows can exist, node rows can be managed, and remote relay code exists in the tree, but the active discovery surface remains local unless a more explicit remote contract is enabled.

Remote Relay Code Uses a Small Protocol

The source also shows what a bounded remote path looks like when it is used. provider_remote.cpp builds a relay input file containing JSONL frames, then invokes:

axiowl relay-session --stdio

over SSH on the destination node. The relay session implementation writes a hello frame, accepts deliver frames, and returns either deliver_result or error frames. Delivery fields include a request id, target, body, strict flag, sender information, and optional direct remote provider identity.

This is a narrow relay protocol rather than a general remote API server. It uses stdio over SSH. It does not require a public manager port. It does not expose an always-listening remote HTTP service. The remote side either delegates to a direct provider request when a provider and provider session id are supplied, or it runs the normal local MessagePipeline on that node.

The relay also preserves receipt honesty. A remote result carries state, target, provider, error, and detail. If the remote process returns no deliver_result, AxiOwl reports that instead of pretending the message arrived.

The Current Dispatch Keeps Remote Out of Scope

There is one especially important implementation detail: the current provider_edges.cpp dispatch table returns excluded_remote_out_of_scope for provider=remote delivery in this local-provider remediation build. The error text says remote delivery is out of scope for the build, and the evidence includes the target and session.

That may look surprising next to provider_remote.cpp, but it is exactly the kind of boundary AxiOwl needs. Having remote relay implementation code in the tree is not the same as enabling every remote route in the active provider dispatch table. The dispatch layer is the gate. If a build is focused on local provider remediation, remote delivery remains unavailable even if supporting code exists elsewhere.

Create behavior is similarly narrow. The provider dispatch returns an unsupported result for remote create because remote create requires an explicit remote node and remote provider contract before it can be enabled. Rename has a remote delegate path, but it still requires a registry target, a node registry row, SSH host/user fields, and a remote CLI command.

Why This Helps Operators

Narrow routing makes operations easier to reason about. When a message does not arrive, the operator can inspect a finite chain:

axiowl status
axiowl node list
axiowl node verify --id <node-id>
axiowl list agents
axiowl discover <provider> --target <agent> --json

The status command prints the state root, agent registry path, node registry path, evidence log, delivery log, runtime role, registered agents, and registered nodes. On Windows it reports "Windows local coordinator"; on Linux it reports "Linux remote Codex endpoint." That role distinction matters because remote chaining is not treated as a universal capability on every runtime.

The operator also gets safer failure modes. A missing target does not cause an unbounded search. A stale row does not silently become sendable. A known but unproven row is rejected before provider delivery. A remote provider route that is out of scope reports that state directly. Those are practical security and reliability properties, not just documentation preferences.

The Design Principle

AxiOwl's remote routing model follows the same principle as its local routing model: one sender, one target, one body, one provider edge, one receipt. Remote support adds a node dimension, but it does not change the core contract.

That is why the system keeps node enrollment explicit, target resolution registry-based, discovery targeted, sendability proof-based, and remote relay protocol-shaped. AxiOwl can grow remote capabilities without turning remote routing into a broad ambient permission. For agent-to-agent messaging, that narrowness is the feature: it keeps the path understandable, auditable, and safe to operate.