AxiOwl Agent Registry Explained

The AxiOwl agent registry is the local source of truth that tells AxiOwl which AI sessions exist, what they are called, which provider owns them, and whether AxiOwl has enough proof to send to them. It is not just a display list. In the current C++ implementation, the registry is durable local state that the send pipeline, discovery system, MCP reply path, and remote-node routing all depend on.

AxiOwl's job is to let supported provider sessions send messages to each other through a local Windows coordinator. To do that reliably, it needs more than a friendly chat name. It needs a provider, a provider-owned session id, a node id, aliases, timestamps, sendability state, and recent evidence about whether the row is still usable. That is what the registry stores.

What The Registry Stores

The current Windows desktop implementation uses TSV-backed registry files. The main agent registry row is represented in code as AgentRecord, with fields for:

There is also a separate node registry represented by NodeRecord. Node rows store the node id, display name, aliases, SSH host, SSH user, SSH key path, enabled state, verification timestamps, and last error. That separation matters because an agent row answers "which target session should receive this message?" while a node row answers "where is the remote machine and how can AxiOwl reach it?"

The CLI exposes both surfaces. Operators can inspect sendable agents with:

axiowl list agents

They can add a manual local or remote agent row with:

axiowl registry add-agent --name "Test Agent" --provider codex --session "<provider-session-id>"

And they can add a remote node with:

axiowl registry add-node --id "front" --host "<host>" --user "<ssh-user>" --key "<ssh-key-path>"

For a remote agent, the row ties the visible target name to the remote provider route:

axiowl registry add-agent --name "Remote Test" --provider remote --node "front" --session "<remote agent name>"

Names Are Not Enough

AxiOwl deliberately avoids treating a chat name as the whole identity. The registry matching logic can resolve by display name, alias, exact provider session id, or a bare session id extracted from a provider-specific session string. It prefers sendable matches over merely enabled matches and uses recency fields when more than one row could match.

That design is important because provider surfaces can reuse names, rename sessions, expose raw UUID-like ids, or keep stale workspace metadata around. A display name is useful for humans, but the provider-owned session id is the stronger routing fact.

The sender side follows the same principle. When a provider replies through MCP, AxiOwl needs to know which provider session sent the reply. The developer docs state the intended order clearly: use provider-owned MCP metadata first, then an explicit provider session id that matches a registry row, then an explicit sender address or alias, and finally targeted discovery repair. The current implementation also avoids treating a raw-looking session id as a trusted human display name unless the row is manual.

The sendable Flag Is A Real Gate

One of the most important fields in the registry is sendable.

A row can be known without being safe to use as a delivery target. The support docs tell operators to inspect registry rows, provider session ids, display names, aliases, sendable, source, timestamps, and last_error when discovery or delivery behaves badly. The message pipeline enforces the same distinction. If a target is known but not sendable, the send is rejected with a clear error instead of pretending the route is valid.

That makes the registry useful operationally. It can remember evidence-only rows and stale rows without allowing them to masquerade as working targets. It also gives support work a concrete place to look: if a target appears in discovery but is not listed by axiowl list agents, the likely reason is that the row is not both enabled and sendable.

Discovery Feeds The Registry, But Does Not Own Everything

AxiOwl discovers provider sessions and merges them into the registry. The current docs describe discovery as provider-specific work that can add new sessions, refresh last-seen fields, enrich manual rows, downgrade stale auto-discovered rows, and repair a missing target once during send.

The implementation follows that model. Discovery rows must have required identity fields before they can become registry rows. A discovered row must also prove sendability before it is enrolled as a new sendable target. If the row is evidence-only, missing proof, archived, or carrying an error, it is skipped, recorded as evidence, or used to downgrade an existing non-manual row.

Manual rows are treated differently. If an existing registry row came from a manual source, discovery can enrich it, but the merge path protects it from being downgraded by weaker discovery evidence. This is a practical operator safeguard: a deliberately configured route should not be silently weakened by a noisy scan.

Targeted Repair During Send

The registry is durable, but it is not assumed to be perfect forever. When the message pipeline cannot find a usable target, or when a target requires repair, AxiOwl performs targeted discovery once for that requested name.

That repair path checks the supported local provider surfaces in sequence, merges whatever it finds into the registry, and then asks again whether the target is now enabled, sendable, and not still marked as needing repair. If the target becomes usable, the send can continue. If discovery only finds evidence but no exact sendable row, the pipeline returns a specific error explaining that target evidence was found but no sendable exact target row was discovered.

This is an important design choice. AxiOwl does not silently guess a route just because something with a similar name was seen. It performs a bounded repair attempt, records what happened, and either resolves a canonical registry row or fails loudly.

How The Registry Fits The Send Pipeline

The developer docs summarize the message flow as:

MCP tool or CLI command
  -> CLI/MCP handler
  -> MessagePipeline
  -> validate target/body/sender
  -> resolve sender identity
  -> resolve target registry row
  -> targeted discovery repair when needed
  -> build final visible body
  -> provider_edges dispatch
  -> provider module
  -> delivery proof/log

The registry is involved before provider dispatch. It tells AxiOwl which provider edge to use, which provider session id to pass, which node is involved, and what canonical display name should appear in logs and receipts.

Once the target row is resolved, provider delivery moves through provider_edges.cpp into provider-specific modules. The registry does not prove that the provider displayed or processed the message. It proves that AxiOwl found a route it considers valid enough to attempt. End-to-end proof still requires a provider reply through AxiOwl MCP with correct sender identity.

Why Operators Should Care

For day-to-day use, the registry is what makes simple commands possible:

axiowl send --to "Target chat name" --body "Message text"

The command can be simple because the registry carries the routing details behind the name. It is also what makes troubleshooting concrete. Instead of wondering whether "the agent exists," an operator can ask sharper questions:

Those answers live under the AxiOwl local state and registry area. The support docs specifically call out %LOCALAPPDATA%\AxiOwl\registry as one of the first places to collect during install, discovery, send, or reply failures.

A Small File With A Large Responsibility

The AxiOwl registry is intentionally plain and inspectable, but it sits at the center of the product. It connects human names to provider session identities, filters known sessions down to sendable routes, keeps local and remote targets distinct, gives discovery a durable merge point, and gives the send pipeline a canonical row to route through.

That is why AxiOwl treats the registry as durable local state instead of a temporary cache. If the registry is accurate, messages can be addressed by useful names while still routing through provider-owned identities. If it is stale, AxiOwl has enough structure to repair, downgrade, or fail loudly instead of making an unsupported delivery look successful.