
How AxiOwl Separates Operator Control From Agent Autonomy
Agent-to-agent messaging gets confusing when a routing tool starts acting like it owns the agent. AxiOwl is designed around the opposite boundary. It gives the operator a concrete way to address, route, and audit messages between named agent sessions, while the receiving agent remains responsible for what it does after the visible message arrives.
That separation matters. AxiOwl is not a hidden supervisor, a durable automation queue, or a system that silently drives one provider when another one fails. Its job is narrower and easier to inspect: accept a message request, resolve the sender and target through the registry, build one final visible message, hand it to one provider edge, record what happened, and return a receipt that does not claim more than the system can prove.
The Operator Controls Addressing And Routing
The operator-facing surface is intentionally explicit. The current Windows desktop app exposes axiowl.exe with commands such as:
axiowl list agents
axiowl status
axiowl registry add-agent --name "Test Agent" --provider codex --session "<provider-session-id>"
axiowl send --to "<agent>" --body "<message>"
For longer content, the documented safe path is stdin:
@'
Full message body here.
Quotes and multiple lines stay intact.
'@ | axiowl send --to "<agent>" --stdin
This is operator control: choosing the target, choosing the content, deciding whether a registry row should exist, and inspecting status. AxiOwl does not ask a model to guess which session should receive the message. The target is resolved against durable registry state containing display names, aliases, provider names, provider session ids, node ids, sendability, discovery source, last-seen fields, and last error text.
The architecture documentation describes the live flow as:
user / provider MCP call / CLI
-> axiowl.exe
-> MCP or CLI command handler
-> MessagePipeline
-> registry target and sender resolution
-> targeted discovery repair when needed
-> provider_edges dispatch
-> provider-specific delivery
-> delivery logs and provider proof
That is the control plane. It is about routing a visible message to a known provider session, not taking over the agent's reasoning loop.
The Agent Controls Its Own Response
AxiOwl's product contract treats a reply as a separate future message initiated by the receiver. That is an important design decision. A successful send does not mean the receiving agent agreed, completed the task, or replied. It means AxiOwl accepted the request, resolved the route, and, when provider proof is available, handed the message to the selected provider edge.
The final visible body builder makes the boundary visible to the receiver. When AxiOwl resolves the sender, it appends an MCP-style reply instruction block that tells the receiving agent how to send content back only if requested. The current implementation phrases that as an explicit tool call to mcp__axiowl.axiowl_send_message with the original sender as the to value. If sender resolution fails, AxiOwl does not invent a return path. It attaches a warning that the sender could not be resolved and that no send-back command is attached.
That policy keeps autonomy with the receiving agent. The agent can read the message, decide whether a response is needed, and start a new AxiOwl send if appropriate. AxiOwl does not treat provider stdout as a reply, wait for a generated response as part of send success, or fold the receiver's future behavior into the original receipt.
MCP Is A Front Door, Not A Remote Control Override
AxiOwl also exposes an MCP server. In the current implementation, mcp_server.cpp advertises tools including axiowl_whoami, axiowl_list_agents, axiowl_send_message, axiowl_create_agent, discovery, status, node, and registry operations.
The important point is how axiowl_send_message is described to the MCP host. Its tool description says the host MCP session ID is used as the stable sender identity key and that success is an MCP-to-AxiOwl handoff receipt only; provider delivery and reply are not implied. That is the same boundary expressed at the tool layer.
MCP gives an agent a typed way to ask AxiOwl to send a message. It does not turn AxiOwl into the agent's hidden brain. The sender identity must come from provider/session metadata or other registered identity material, then AxiOwl resolves it through the registry before building reply instructions. The developer docs are direct on this point: provider replies need enough metadata for AxiOwl to identify the sender session, and the MCP server should fail loudly when metadata is missing.
Receipts Are Evidence Boundaries
AxiOwl uses receipts to avoid overclaiming. The model types include both accepted_by_axiowl and accepted_by_provider. The architecture reference separates those meanings:
accepted_by_axiowlmeans AxiOwl accepted and validated the request and handed it to the delivery layer.accepted_by_providermeans the provider edge reported that the target provider accepted the message.- A response over MCP is stronger proof that the target provider received the message, acted on it, and replied through AxiOwl with provider-owned sender identity.
The message pipeline implementation records an early stage stating that the MCP or CLI request entered the AxiOwl message pipeline and that provider delivery is not implied. Later, after target resolution and route selection, it records message_accepted_by_axiowl with a receipt boundary before delivery-worker or provider completion.
That is operationally useful. An operator can see where the boundary is: accepted by AxiOwl, handed to delivery, accepted by a provider, or rejected with an error such as missing target, unresolved sender, unsendable registry row, or unknown provider.
Provider Edges Keep Autonomy And Weirdness Isolated
Provider-specific behavior lives behind provider edges. The dispatch table in provider_edges.cpp selects one edge based on the target registry row, including providers such as codex, codex_cli, vscode_native, vscode_copilot_backed, antigravity, antigravity_cli, cursor, cursor_cli, claude_code_cli, copilot_cli, and opencode_cli.
This is another control/autonomy separation. AxiOwl's middle does not know how every provider inserts a message, wakes a chat, or proves acceptance. It calls one adapter with the final visible body and expects a provider result. The provider edge contract says adapters must not append sender names, remove helper text, add provider-specific reply instructions, summarize the body, or split it into hidden pieces. Encoding and transport escaping are allowed; changing the meaning of the visible body is not.
Fallbacks are also constrained. The provider-edge plan allows fallback only inside a provider family and requires degraded results to be marked as degraded with a reason. It explicitly rejects cross-family behavior such as a failed VS Code target being silently sent to Codex instead. That gives operators predictable routing and gives agents a clear visible context.
Current Implementation Status
The current README is careful about what exists today. The implemented pieces include 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. The README also says the local always-running service is not implemented yet, and that the CLI currently runs the local pipeline directly.
That distinction matters for accurate operations. The design documents describe the intended small local service plus thin CLI architecture, with a reserved localhost endpoint at 127.0.0.1:37661. The current implementation still enforces the core separation through axiowl.exe, the message pipeline, the registry, the MCP server, evidence logs, and provider edges, even before the always-running service form is complete.
Why This Helps Operators
Operator control without agent autonomy becomes brittle orchestration. Agent autonomy without operator control becomes an untraceable set of chat windows. AxiOwl sits between those extremes.
The operator gets:
- Named targets instead of copied session ids in every message.
- Registry rows that say which provider and session are actually sendable.
- Explicit CLI and MCP entry points.
- Receipts that distinguish AxiOwl acceptance from provider acceptance.
- Evidence logs and last-error fields instead of silent routing guesses.
- Provider-specific delivery without letting provider-specific behavior leak into the common message body policy.
The agent gets:
- A visible message, not a hidden command stream.
- A clear sender name when AxiOwl can prove it.
- A reply tool call only when a real return route exists.
- The ability to decide whether a reply is needed.
- No requirement to invent sender identity or construct raw relay commands.
The Practical Boundary
The practical boundary is simple: AxiOwl controls delivery of visible messages between registered sessions; agents control their own next turn.
That is why the product contract says AxiOwl resolves names, builds one final visible body, selects one provider edge, records evidence, and returns an honest receipt. It also says AxiOwl must not invent unknown sender names, silently fall back to another provider family, wait for provider-generated replies as part of send success, or store hidden durable retry rows.
For day-to-day use, that makes AxiOwl a routing and coordination tool rather than an invisible automation authority. Operators can tell one agent to message another, audit the route, and understand what was proven. The agents remain autonomous participants: they receive visible context and respond only by starting their own explicit AxiOwl message when the task calls for it.