Muxiva system overview and core concepts
Muxiva is a real-time multimodal Agent Runtime. A developer uses a typed Graph to describe how audio, video, text, bytes, and control messages move. Rust Core owns validation, scheduling, concurrency, backpressure, lifecycle, shutdown, and observability. Replaceable Nodes provide ASR, LLM, TTS, RTC, and other application capabilities.
The central idea is: Core defines stable execution mechanisms, Nodes provide replaceable capabilities, and a Graph composes both into an executable system.
System overview

Download the editable Draw.io source
The diagram has five layers. Read the boundaries first, then the connections. Solid blue lines represent data or calls, dashed magenta lines represent Signal control, and dotted gray lines represent process-local NotificationBus telemetry.
1. Product and developer surfaces
- The
muxivaCLI creates, validates, runs, and diagnoses projects for terminals, scripts, and CI. - Muxiva Studio edits Graphs, wires Ports, displays Node source, configures local Connections, and observes the current Runtime.
- Language SDKs let Rust, C++, Python, and TypeScript developers build Graphs or implement Nodes.
- A project web app / Voice Room owns the end-user microphone, speaker, chat, and barge-in presentation.
The project web app is an independent client, not part of Studio. It communicates with the Agent through RTC or an application Transport. It does not call Runtime lifecycle APIs or poll the process-local NotificationBus.
2. Definition, discovery, and configuration
This layer answers three questions: what should run, where is its implementation, and how is it configured?
- Graph v1 declares Nodes, named Ports, Edges, types, queue capacities, and policies. It is a blueprint and contains no threads, sockets, secrets, or live objects.
- A Node Manifest declares
node_type, language, Factory version, capabilities, configuration schema, and exact input/output schemas. - Registry and Discovery collect built-in, official, and project Nodes and select the exact Factory requested by a Graph. The Runtime never guesses from a similar name.
- Connections and Secrets provide shared local connection settings to Nodes.
Development values may live in a project
.envignored by Git; production values should come from a secret or token service.
3. Vendor-neutral Rust Runtime Core
This is Muxiva's stable kernel. It has no dependency on Agora, Qwen, or another vendor.
- The Graph Compiler checks schemas, topology, Port direction, and compatibility before creating a Node, then materializes the declaration into an executable plan.
- The Concurrent Graph Runtime manages
prepare → process → signal → finish / abort, worker scheduling, cancellation, and bounded shutdown. - The data plane uses immutable Frames, typed Ports, and bounded Edge queues for audio, video, text, and bytes, with backpressure controlling latency and memory.
- The control and observability plane routes adjacent Signals and publishes Notifications to process-local observers. Core supplies mechanisms but does not hard-code interruption, turn, or vendor policy.
4. Unified Node extension layer
Muxiva has one executable extension concept: the Node. A built-in integration or vendor adapter is a Node that follows the same contract, not another Runtime entity.
- Rust built-in Nodes fit resampling, VAD, cancellation gates, and general utilities.
- The Python Node Host fits Qwen Realtime, ASR, LLM, TTS, and fast-moving algorithms.
- C++ ABI Node Packs fit Agora RTC, codecs, device SDKs, and other native integrations.
- TypeScript and project Nodes live under an Agent project's
.muxiva/nodes/, run through a managed async Host, and use the same Manifest, Factory, and Frame contracts.
Each language Host isolates threads, objects, and exceptions. A Graph always sees the same Node, Port, and Frame model, regardless of implementation language.
Agent is a reusable Node capability, not a Core primitive
An Agent adds long-lived conversation state, Tool Calls, steering, and model-specific
streaming above a text model. Those policies vary too quickly to belong in Rust Core.
Muxiva therefore provides a vendor-neutral @muxiva/agent TypeScript contract with
stable prompt, tick, cancellation, text, and lifecycle Event Ports. A small driver can
wrap Pi, another Agent harness, or application code without changing the Graph.
Demo 2 proves this boundary: Qwen ASR emits a completed prompt, the project-local
Pi Agent Node owns session state and tools, the original Markdown branches
to the client, and builtin.speech_formatter derives natural plain text for Qwen TTS. Pi stays an
optional TypeScript dependency; the Runtime sees only ordinary Nodes.
5. External services and the production boundary
External models, RTC networks, and token services are not part of Core. The voice application in the diagram uses Alibaba Cloud Model Studio and Agora as one composition; developers can replace those Nodes without changing the Runtime. A browser receives only short-lived RTC tokens, while model credentials remain server-side. In the current voice deployment model, one Runtime process represents one Agent RTC session, preventing mutable playback or generation state from leaking across sessions.
Connect the core objects
Think of Muxiva as a controlled real-time factory:
| Concept | Plain-language model | Responsibility |
|---|---|---|
| Frame | An item on the production line | Immutable data with an audio, video, text, or byte payload plus a traceable header |
| Node | A machine | Consumes Frames in lifecycle callbacks and emits zero or more outputs or control messages through NodeContext |
| Port | A typed socket | Constrains a Node's input or output by name, direction, Frame Type, and schema |
| Edge | A bounded conveyor | Connects one output Port to one input Port and defines capacity, backpressure, and overflow policy |
| Graph | The factory blueprint | Declares Nodes, Edges, configuration, and a static DAG; it stores no live state |
| Manifest | A machine specification | Declares Node identity, version, language, capabilities, configuration, and I/O schemas |
| Factory | A machine builder | Creates one independent instance for each Graph Node ID from a Manifest and configuration |
| Registry | The available machine catalog | Discovers Factories and selects an exact type, language, and version for a Graph |
| Runtime | The factory control system | Materializes, starts, schedules, limits, cancels, stops, and converges failures |
| NodeContext | A controlled Node console | Provides named output, Signal, Event, cancellation, and runtime context without direct downstream calls |
The relationship compresses to:
Manifest + Factory → Registry → Graph Compiler → Runtime
│
Frame → Node.output Port → bounded Edge → Node.input Port
How a Graph becomes a running system
- A developer defines Nodes and Edges through an SDK, JSON Graph v1, or Studio.
muxiva validateand the Graph Compiler check Node identity, configuration schemas, Ports, Frame Types, queue policies, and DAG topology without starting a Node or connecting to an external service.- The Registry selects an exact Factory for each Graph Node ID, and the Runtime creates independent Node instances.
- The Runtime calls every Node's
on_prepare, then starts Sources, workers, and bounded Edge queues. - In
on_process(frame, ctx), a Node callsctx.emit(port, frame)for results. One invocation may emit nothing or emit through several named Ports. - Normal completion calls
on_finish; errors, cancellation, or deadlines callon_abort, followed by bounded waits for foreign execution domains and callbacks.
Why data, control, and observation are separate
A real-time Agent has three kinds of communication. They must not collapse into a single universal message bus:
| Channel | Propagation | Intended content | Must not become |
|---|---|---|---|
| Frame + Edge | Explicit Graph topology and bounded queues | Audio, video, ASR text, LLM output, and client interaction messages | A global broadcast |
| Signal | Runtime delivery along the current Node's adjacent Edges | Interruption, cancellation, and stale-playback clearing that changes related Node state | Remote client transport |
| NotificationBus notification | Process-local observers | Logs, metrics, Studio diagnostics, transcript-ready telemetry | A browser protocol or business data path |
For barge-in, VAD emits an observational Event when speech starts. ASR final text enters
builtin.voice_turn_controller, which rejects fillers, admits a new turn, and exclusively emits
muxiva.turn.cancelled. The Runtime delivers it to related model and playback Nodes. The model
cancels the old generation and rejects late fragments; the playback Node clears stale
audio. If a remote Voice Room must display “user is speaking,” a Transport Node sends
a client event as a Frame or byte protocol—the browser never reaches into NotificationBus.
Current voice interruption mechanism

Download the editable Draw.io source
The diagram follows the actual Qwen Realtime + Agora RTC Graph:
- Browser microphone uplink remains active while the Agent is playing an answer, which provides the input side of full duplex.
- Qwen Server VAD reports
input_audio_buffer.speech_started; the ASR Node emits it as an observation and does not cancel work. - After a final transcript passes Voice Turn Controller admission, the controller emits one
muxiva.turn.cancelledSignal plus a same-sequence Prompt. Runtime follows explicit Signal Edges. - Agent/TTS reject old generations. Audio Sink clears unsent PCM, advances its cancellation sequence watermark, and drops old Audio Frames at or below that watermark. This is a second guard after the Qwen Node's late-chunk filter.
speech.startedleaves Qwen as an observational Event Frame. The project-local Voice Room Encoder maps those Events—and transcript/response Text Frames—before Agora Data Sink sends application bytes to the remote Voice Room.publish_notificationonly reaches the process-local NotificationBus for logs, metrics, and Studio diagnostics.
There is a physical boundary: audio already inside the Agora network or browser playback buffer cannot be recalled. Low-latency interruption therefore also depends on short PCM packets, bounded Audio Sink queues, and shallow client playback buffers. Core neither switches application Turns nor contains Qwen- or Agora-specific interruption policy.
Validate the model with the voice path
Browser microphone
→ Agora RTC network
→ C++ Agora Audio Source Node
→ Audio Resampler / Qwen ASR
→ optional Pi TypeScript Agent / Qwen TTS
→ text and audio Frames
→ C++ Agora Data / Audio Sink Node
→ browser chat bubbles and speaker
Agora does not know how the Graph is scheduled. Qwen does not know how the browser captures audio. The browser never receives the model key, and Rust Core contains no vendor business code. The layers cooperate through Manifest, Frame, Port, Edge, Signal, and lifecycle contracts.
Architectural boundaries to remember
- A Graph is a declaration; a Runtime is a live instance. JSON cannot contain executable code or secrets.
- Every application capability is a Node. “Provider” may organize documentation, but it is not a new Runtime abstraction.
- NotificationBus is process-local observability. Cross-machine messages use Transport Nodes or an application protocol.
- Core does not understand vendors or voice business rules. Turn, barge-in, ASR, and TTS policy live in Nodes.
- Studio is a local development surface, not a production client. A project web app and Runtime may run on different machines.
- Queues and shutdown are bounded. A real-time system cannot hide failure behind unlimited buffering or waiting.
Recommended reading order
- Rust Core and core objects for Frame, Node, Port, Edge, and Graph;
- Graph and typed Ports for Graph v1;
- Real-time flow and control for backpressure, Signal, NotificationBus, and interruption;
- Node extensibility, multi-language execution, and TypeScript Agent Nodes;
- the unified Node architecture;
- CLI, Studio, and project web apps; and
- the end-to-end voice path and runnable voice demo.