How AxiOwl Thinks About Agents, Nodes, and Providers

AxiOwl is easiest to understand when its routing model is split into three plain nouns: agents, nodes, and providers. An agent is the addressable conversation or session a message can target. A node is the machine where that agent lives. A provider is the delivery surface AxiOwl must use to reach it.

That separation matters because AxiOwl is not trying to collapse every coding assistant into one generic chat box. It is a local coordinator that keeps a concrete registry of reachable sessions, records where they are, and then chooses the right delivery edge for the provider behind the session.

Agents Are Addressable Sessions

In the current Windows desktop implementation, an agent record is a real data structure, not just a nickname. AxiOwl stores fields such as agent_id, display_name, aliases, provider, provider_session_id, node_id, enabled, sendable, timestamps, source, and last_error.

The registry is persisted as a TSV file under the AxiOwl state directory. On Windows, the state root resolves to %LOCALAPPDATA%\AxiOwl, and agent rows live at:

%LOCALAPPDATA%\AxiOwl\registry\agents.tsv

That row tells AxiOwl several important things at once. The display name is the human-facing name an operator can use. Aliases let discovery and manual enrollment preserve alternate names or raw session identifiers. The provider session ID is the provider-specific address, such as a thread, conversation, composer, or CLI session identifier. The sendable flag is explicit, so a discovered row can be known without being treated as safe to deliver to.

Operators can inspect and add these rows through the CLI:

axiowl list agents
axiowl registry add-agent --name <agent> --provider <provider> --session <provider-session-id> [--node <node>]

A useful detail in the implementation is that AxiOwl prefers exact provider/session/node matches when merging records, but it also preserves names and aliases. That keeps the registry stable even when discovery learns a better display name later.

Nodes Are Where Agents Live

A node is AxiOwl's record for another machine. The current NodeRecord stores node_id, display_name, aliases, host, SSH user, SSH key path, enabled state, verification timestamps, and last error. Node rows live beside the agent registry:

%LOCALAPPDATA%\AxiOwl\registry\nodes.tsv

The CLI exposes this directly:

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

The node concept is what lets an agent record say "this target is not local." A remote agent can be represented with provider=remote, a node_id that points to nodes.tsv, and a provider session value that identifies the remote target. When Windows AxiOwl sends to a remote target, it looks up the node, builds an SSH command, and runs the remote Linux-side relay:

axiowl relay-session --stdio

The Linux remote app has a narrower job. The app README says the Windows build is the local coordinator, registry owner, and outbound SSH remote provider, while the Linux build is a remote Codex endpoint and relay-session receiver. It also states that the Linux remote app supports Codex CLI delivery only, not VS Code, Antigravity, desktop IPC, GUI, tray behavior, or remote relay chaining.

That is a deliberate boundary. A remote node is not a magic fallback for every unsupported local action. It is an explicitly registered machine with an SSH route and a constrained relay contract.

Providers Are Delivery Edges

Providers are the adapters behind agent records. The current provider dispatch recognizes names such as codex, codex_cli, vscode_native, vscode_copilot_backed, antigravity, antigravity_cli, cursor, cursor_cli, claude_code_cli, copilot_cli, opencode_cli, and remote.

The CLI normalizes common spellings. For example, vscode-native becomes vscode_native, codex-cli becomes codex_cli, vscode-copilot becomes vscode_copilot_backed, and opencode becomes opencode_cli.

This provider layer is where AxiOwl stays honest about support. If a provider name does not match a known edge, delivery fails with an unknown-provider result. If a create or rename edge is not implemented, the result says so. The security docs reinforce the same operating principle: selected provider integrations only, clear logs, loud failure when patch/config/install steps cannot be completed, and receipts that distinguish AxiOwl handoff from provider delivery proof.

What Happens During A Send

A send request enters through the CLI or MCP surface:

axiowl send --to <agent> --body <message> [--from <agent>] [--from-node <node>]
axiowl send --to <agent> --stdin [--from <agent>] [--from-node <node>]

Inside the message pipeline, AxiOwl first records that the request entered the pipeline. That receipt boundary is explicit: acceptance by AxiOwl does not automatically mean provider delivery, provider wake-up, or a provider reply.

Next, AxiOwl validates that the target and body are present. It resolves the sender identity from the explicit --from value and the registry. If the sender looks like a raw session identifier and cannot be resolved to a registered display name, AxiOwl can run targeted sender discovery once, then fails loudly if it still cannot resolve the identity.

Then AxiOwl resolves the target. It searches the agent registry by display name, alias, or session-like identifier. If the target is missing, the pipeline runs targeted discovery once through the configured discovery functions and merges proven rows into the registry. If the target is still missing, evidence-only, or known but not sendable, the send is rejected with a concrete error.

Only after that does AxiOwl build the provider request. The request includes the target record, resolved sender, final visible body, run ID, message ID, requested delivery method, and strictness. A delivery worker then hands the request to the provider edge.

Why The Split Helps Operators

The practical value is that troubleshooting becomes structured.

If the name is wrong, check the agent registry and aliases. If the machine is wrong, check the node registry and SSH verification. If the session is right but delivery fails, check the provider edge and delivery logs. If a message only reached AxiOwl but not the provider, the receipt should say that instead of pretending the route succeeded.

The same split also makes discovery safer. Discovery can find possible sessions, but AxiOwl still distinguishes evidence from sendable enrollment. It can update an existing manual row without blindly replacing a trusted name. It can preserve old display names as aliases when a provider title changes. It can keep remote routing explicit instead of hiding a local provider failure behind an unexpected SSH hop.

A Small Vocabulary For A Real Routing System

In AxiOwl, "agent" does not mean a vague AI persona. It means an addressable session row with a provider session ID, aliases, and sendability state. "Node" does not mean an abstract cluster member. It means a registered machine with host, SSH user, key path, and verification state. "Provider" does not mean a model brand alone. It means the delivery adapter AxiOwl must use for a given target.

That vocabulary is what lets AxiOwl route messages across local and remote assistant surfaces while still leaving an audit trail. The result is a system that can say where a target lives, how it should be reached, whether it is currently sendable, and exactly where a delivery attempt stopped.