DEV Community

Cover image for Voice Is a Mode, Not a Channel

Voice Is a Mode, Not a Channel

Voice Is a Mode, Not a Channel

A lot of agent systems turn voice into a separate product category.

That usually looks neat in a UI, but it creates the wrong abstraction.

In APC and APX, the cleaner model is simpler: APC carries durable project context, and APX decides how that context is used at runtime. Inside that runtime, voice works better as a mode layered on top of a surface, not as a separate channel with its own identity.

That distinction is small, but it prevents a surprising amount of drift.

APC is the portable context layer. It defines project agents, project rules, skills, and other repository-owned facts. APX is the daily-use runtime and tooling layer. It serves the CLI, web admin, desktop app, routines, and other execution paths. So when APX decides how to speak, format, or segment an answer, that decision belongs to runtime behavior, not to portable project structure.

The code reflects that directly.

In src/core/constants/channels.js, APX keeps channel names as surfaces such as telegram, cli, web, desktop, and code, and the file comments state the rule plainly: voice is not a channel, but a mode layered through channelMeta.voice. In src/core/agent/prompt-builder.js, CHANNEL_PROMPT_FILES maps surfaces to channels/<surface>.md, while voice instructions come later through a separate voice-mode block. The prompt builder computes voice from channelMeta.voice and then conditionally appends modes/voice.md behavior.

That split matters for three practical reasons.

First, it prevents duplicated prompt trees.

If voice becomes its own channel, every surface suddenly needs a second version: cli and voice-cli, deck and voice-deck, desktop and voice-desktop, maybe later telegram and voice-telegram. That explodes maintenance cost. Small instruction changes stop being global and start fragmenting across near-duplicate channel prompts. By keeping one surface block plus one optional voice layer, APX preserves one prompt tree per surface and one shared voice behavior layer.

Second, it keeps logging and runtime state honest.

Channels answer the question "where did this interaction happen?" Modes answer a different question: "how should this reply behave?" Those are not the same dimension. A desktop interaction is still a desktop interaction whether the answer is spoken aloud or not. A deck interaction is still a deck interaction whether TTS reads it or the user scans it silently. If voice became the channel, logs would start hiding the actual surface where the work happened.

Third, it keeps APC clean.

APC should not need to care whether a reply is spoken, whispered, segmented for TTS, or tagged for emotional delivery. Those are runtime concerns. APC defines the project contract that another compatible runtime can also read. APX decides whether one local surface needs voice formatting today. That boundary is exactly why APC stays portable while APX stays useful.

The desktop path is a good example. In src/core/constants/channels.js, desktop is still the surface. In the APX dev guide, desktop is described as always running in voice mode. That means the system can preserve desktop-specific context while still layering voice-specific formatting and delivery rules only when needed. Same surface, extra mode.

There is a test for this idea too. tests/channel-coherence.test.js checks that every surface keeps the same super-agent role, keeps its own context block, and only gets extra prompt content when voice mode is active. That is a better invariant than inventing a fake channel just because audio is involved.

The deeper thesis is simple.

APC should describe stable project meaning.

APX should describe runtime execution.

And inside APX, voice should stay a modifier on top of a real surface, not a replacement for one.

That model keeps prompts smaller, logs clearer, surfaces easier to evolve, and project context free from runtime-specific noise.

Top comments (1)

Collapse
 
alexshev profile image
Alex Shev

“Voice is a mode” is a useful distinction. The interface can be spoken, but the product still needs state, permissions, memory boundaries, and a way to confirm irreversible actions. Voice changes the interaction shape, not the safety requirements.