Why AxiOwl Coordinates Real Sessions Instead of Simulated Subagents

AxiOwl is built around a simple operating idea: route messages between real AI provider sessions that already exist, can be addressed, and can reply with their own session identity. It is not trying to make one model pretend to be a room full of workers inside a single transcript. The difference matters because real coordination needs more than generated role-play. It needs a target session, a provider-specific delivery path, a sender identity, a receipt boundary, and evidence that the message actually moved through the provider surface.

That is the shape of the current AxiOwl C++ repo. The source-of-truth architecture document describes AxiOwl as a local Windows coordinator with a CLI, MCP server, durable registry, provider discovery, provider-specific delivery edges, delivery logs, and provider proof. The implementation follows that contract in files such as apps/windows-desktop/src/message_pipeline.cpp, apps/windows-desktop/src/registry.cpp, apps/windows-desktop/src/mcp_server.cpp, and apps/windows-desktop/src/provider_edges.cpp.

A Real Session Has Addressable State

The registry model is the first reason AxiOwl coordinates actual sessions. In apps/windows-desktop/src/models.hpp, an AgentRecord is not just a friendly name. It includes display_name, aliases, provider, provider_session_id, node_id, sendable, source, last_seen_at, last_verified_at, and last_error.

That set of fields makes the target concrete. A human can send to a readable chat name, but AxiOwl still needs the provider-owned session identifier underneath it. apps/windows-desktop/src/registry.cpp preserves that distinction: lookup can match a display name or an exact session id, prefers sendable rows, and keeps enough metadata to resolve a sender back to a registered provider session when a reply arrives.

A simulated subagent does not have that operational identity. It can be named in a prompt, but it does not have a Codex thread id, Cursor composer id, VS Code chat session, MCP sender metadata, install state, or delivery evidence. AxiOwl's registry is designed for those real identifiers because those are the things provider edges can actually deliver to.

The Send Pipeline Refuses to Guess

MessagePipeline::send in apps/windows-desktop/src/message_pipeline.cpp is deliberately strict about what has to be known before a message leaves AxiOwl. It validates the target and body, resolves the sender, performs one targeted discovery repair if a target is missing or stale, rejects unresolved sender identity, checks whether the target row is sendable, and only then creates the final visible body and hands delivery to the worker.

That flow is important because a guessed route is worse than a failed route. If AxiOwl cannot resolve a sender, it returns a loud failure such as a missing explicit sender or unresolved sender session. If a target is found but not sendable, it reports that instead of pretending delivery occurred. If discovery finds weak evidence but no sendable exact row, that is also reported as a failed target resolution.

The current docs make the same point. docs/reference/provider-support-matrix.md says a provider is not supported merely because AxiOwl can write a config file or start a process. The support bar includes discovery, install/config, send, provider receive, provider MCP reply, and correct sender identity.

Provider Edges Deliver to Provider-Owned Sessions

AxiOwl keeps the middle of the system small and pushes provider-specific behavior to provider edges. apps/windows-desktop/src/provider_edges.cpp dispatches delivery by provider name to concrete implementations such as Codex, Codex CLI, VS Code native, VS Code Copilot-backed, Antigravity, Cursor, Claude Code CLI, Copilot CLI, and OpenCode CLI paths.

The concrete edges show why simulated subagents are not enough. In apps/windows-desktop/src/provider_codex.cpp, Codex delivery requires provider_session_id to be the Codex thread id. The Codex Desktop IPC path sends frames such as thread-follower-steer-turn or thread-follower-start-turn against a real conversation id. The Codex CLI path resumes or creates real Codex threads and records returned thread/session identifiers.

Cursor has a different reality. apps/windows-desktop/src/provider_cursor.cpp addresses Cursor Agent Window / Composer sessions through cursor:composer:<uuid> identifiers, bridge command JSON files, a command watcher, and a URI wake-up fallback. The provider page at docs/providers/cursor-agents.md documents that the preferred path is AxiOwl provider edge to command JSON file to Cursor bridge watcher to the submit hook to the Cursor composer.

Those details are not interchangeable. A Codex thread id cannot be treated as a Cursor composer id. A Cursor bridge command cannot be treated as a VS Code native chat command. This is why AxiOwl coordinates real sessions through provider edges instead of flattening everything into a generic pretend worker model.

MCP Replies Prove More Than Receipts

AxiOwl also separates handoff from proof. The send receipt can say accepted_by_axiowl, but that only means AxiOwl accepted the request and handed it to the delivery layer. It does not prove the provider displayed, processed, or replied to the message.

That boundary is present in the code and tests. apps/windows-desktop/src/models.hpp has separate receipt fields for accepted_by_axiowl and accepted_by_provider. apps/windows-desktop/src/message_pipeline.cpp sets the normal immediate receipt to accepted_by_axiowl before the background delivery worker finishes provider delivery. apps/windows-desktop/tests/core_tests.cpp has a test named test_send_returns_axiowl_receipt_then_starts_delivery_handoff that asserts the sender receipt path should be accepted by AxiOwl without reporting provider acceptance.

The stronger proof is a reply through AxiOwl MCP with provider-owned sender identity. apps/windows-desktop/src/mcp_server.cpp resolves identity from MCP call metadata, registers the sender, refuses no-session sends, and records inbound MCP send receipts with fields such as sender session id, sender name, sender provider, host kind, and identity source. That means a reply is not just text; it is text associated with the real session that sent it.

Discovery Repairs Reality, It Does Not Invent It

Discovery is another place where AxiOwl avoids simulation. apps/windows-desktop/src/discovery.cpp merges discovered rows into the registry only when required identity fields are present and the row proves sendability. Evidence-only Codex rows are counted and logged, but not promoted into sendable targets. Manual rows are protected from discovery downgrade. Stale rows can be repaired, but unsupported paths are not quietly treated as working paths.

The Codex discovery code reads real Codex state candidates under the user's .codex data, session index material, global state, and Desktop IPC ownership where available. Cursor discovery and provider delivery read real composer inventory and bridge state. The point is not to create an idealized list of agents. The point is to maintain a registry that reflects provider sessions AxiOwl can actually address.

That also explains the installer behavior. docs/reference/installer-behavior-matrix.md says provider checkboxes should default from discovery, unchecked provider features should not be patched or configured as collateral damage, and selected provider features should fail loudly when they cannot be installed safely. A real-session coordinator has to respect what is installed, selected, and reachable on the machine.

Practical Value for Operators and Developers

For operators, real sessions make routing inspectable. axiowl list agents can show registry rows. axiowl status can report registry, node registry, log, runtime, and activation paths. Delivery logs and evidence logs can distinguish target resolution, delivery worker handoff, provider write success, provider write failure, and unverified handoff.

For developers, real sessions keep provider work contained. The shared pipeline resolves sender and target, builds the final visible body once, and records the receipt boundary. Provider adapters handle only provider-specific delivery. When a provider changes its internal state, patch surface, session metadata, or command behavior, the fix belongs at that provider edge instead of leaking into the whole system.

For users, the main benefit is honesty. AxiOwl can route between supported provider sessions, but it does not claim support just because a path looks plausible. The current support matrix marks surfaces as supported, target, experimental, unsupported, or removed, and it ties supported status to response-backed proof or active working evidence.

Real Coordination Beats Pretend Delegation

Simulated subagents can be useful for brainstorming inside a single model conversation, but they do not solve the operational problem AxiOwl is built to solve. AxiOwl needs to know which real session is sending, which real session is receiving, which provider edge owns the route, and whether the result is only a local handoff or a provider-backed proof.

That is why AxiOwl coordinates real sessions. The product value is not that it invents more agents in text. The value is that it gives existing provider sessions a common local coordination layer with registry-backed addressing, MCP reply identity, provider-specific delivery, loud failure modes, and evidence that can be inspected when something changes.