Skip to content

Integration: SageOx (ox)

Status: Design-locked · Implementation: Phased; L1 + L2 in Vox v1, L3 in v1.1, L4 deferred.

SageOx (ox) is agentic context infrastructure — a git-tracked ledger of team-context atoms ("murmurs") that AI coding agents consume before they act. Vox plugs in as the local audio recording engine ox doesn't ship: capture spoken intent from any source, transcribe locally (BYOK or fully local), write murmurs into the ox ledger, and have them auto-available to every team member's AI coworker via ox agent prime.

This document is the single source of truth for the Vox ↔ ox integration: architecture, contract mapping, performance constraints, and the open conversations we need to have with the upstream ox team.


What ox is, in one paragraph

ox (MIT, Go, github.com/sageox/ox, $15M funded as of 2026) orchestrates adapters that read each AI tool's session format (Claude Code, Codex, Gemini, Aider, OpenCode, Cursor, Windsurf, Pi, Amp, Copilot, Cline). Adapters are separate binaries implementing a versioned public protocol (pkg/adapterprotocol, ProtocolVersion = 1). Team context is stored as murmurs — small JSON files in data/murmurs/YYYY-MM-DD/HH/<id>.json under the ledger directory, synced via a git remote with GitHub backend support. The web app at sageox.ai handles team management, dashboards, and currently audio recording + transcription of team discussions. Local CLI users have no locally-driven audio path today.


The gap Vox fills

ox's audio capture lives in the web app. Local CLI users cannot today:

  • Record a Zoom / Meet / Teams call's system audio + their own mic
  • Capture an in-person meeting via lapel / array mic
  • Dictate into the ledger from the terminal
  • Capture audio when offline

Vox is the local recording engine ox doesn't have. The intent envelope maps almost 1:1 onto ox's murmur format, making ox murmurs a near-native sink.


The four-layer integration model

Vox can integrate with ox at four layers, of increasing depth and effort. We ship the first two in Vox v1, the third in v1.1, defer the fourth.

Layer What it is Effort Phase
L1. Direct murmur file writer Vox writes JSON files directly into data/murmurs/YYYY-MM-DD/HH/<id>.json inside the ox ledger directory. Zero-dependency on the ox CLI running Low v1
L2. First-class ox-ledger sink in sink/v1 Configurable Vox sink type (templated topic / importance / scope, filterable, batches git commits) Medium v1
L3. cmd/ox-adapter-vox/ compliant adapter binary Implements pkg/adapterprotocol. Surfaces in ox status, ox doctor. Registered upstream Medium v1.1
L4. Bidirectional — Vox routes informed by recent ox murmurs Vox's router reads recent ox murmurs to make better intent-classification decisions High Deferred

L1 underlies L2 — L2 is the configuration and lifecycle layer; L1 is the file-write mechanic. L3 is the formal handshake with ox so Vox shows up as a first-class citizen. L4 closes the loop and is the future work.


Murmur format mapping

ox's MurmurFile schema (from internal/ledger/murmur.go):

type MurmurFile struct {
    SchemaVersion string            // "1"
    ID            string            // UUIDv7
    Timestamp     time.Time
    AgentID       string
    AgentType     string            // "claude-code", "vox", etc.
    PrincipalID   string            // who the agent works for
    PrincipalType string            // "human" for now
    Topic         string
    Importance    string            // "critical", "normal", "ambient"
    Content       string
    Metadata      map[string]string
    Tags          []string
    Scope         string            // "ledger" or "team"
}

Maps from a Vox IntentEnvelope (from sink/v1):

ox murmur field Source in Vox envelope Default rendering
schema_version (constant) "1"
id EnvelopeID (UUID, already compatible with UUIDv7 conventions)
timestamp StartedAt RFC3339 UTC
agent_id sink config agent_id_template vox-{{ .InstanceID }}
agent_type sink config agent_type (constant) "vox"
principal_id Speaker.Label (when present) empty if unknown
principal_type derived from Speaker.SourceKind self"human"; online/in-person"human"; file"recording"
topic sink config topic_template voice/{{ .Envelope.Speaker.SourceKind }}/{{ .Envelope.Intent.Kind }}
importance sink config importance_template {{ if gt .Envelope.Intent.Confidence 0.8 }}normal{{ else }}ambient{{ end }}
content Transcript UTF-8, no transformation
metadata Custom keys namespaced vox.* + key envelope fields See below
tags derived [vox, source:<kind>, intent:<kind>] plus filtered tags from envelope
scope sink config scope "team"

metadata payload (mapping to murmur.Metadata, a map<string,string>)

Key Source Notes
vox.session_id SessionID Group voice envelopes by session
vox.stream_id StreamID Per-stream identifier
vox.parent_id ParentID For derived envelopes (LLM responses)
vox.source_kind Speaker.SourceKind self/in-person/online/file
vox.intent_kind Intent.Kind prompt/command/etc.
vox.intent_confidence Intent.Confidence Stringified float
vox.asr_backend Provenance.ASRBackend e.g., whisper-cpp
vox.captured_at Provenance.CapturedAt Original audio time
vox.pipeline_version Provenance.Pipeline e.g., vox/0.1.0
vox.audio_ref_location AudioRef.Location (if present) S3 URL or similar
vox.duration_ms Duration In milliseconds

User-supplied Custom["vox.*"] keys override / extend the defaults.


Performance — git commit batching is critical

The ledger directory is a git repository. Per-envelope git commit would balloon repo size, slow ledger operations, and stress the GitHub sync path ox uses for team distribution.

Required behavior of the ox-ledger sink:

  • Write murmur files immediately. File I/O is cheap; per-envelope writes are fine.
  • Batch git commits. Default flush interval 30 seconds, configurable via git_commit_interval. A single commit covers all murmur files written in that window.
  • Never push automatically. Push is the user's choice (or ox's daemon's choice, when it's running). The Vox sink writes + commits locally and stops there.
  • Coordinate with ox's daemon when present. ox's internal/daemon/ likely handles ledger writes via IPC to prevent contention. When the ox daemon is running, Vox should defer to it via the adapter protocol (Layer 3) instead of writing files directly. Layer 1 (direct write) is the fallback when ox daemon is absent.

This pattern matches ledger.WriteMurmurRaw() (in internal/ledger/murmur.go), which exists specifically so the daemon can delegate file I/O via IPC. Vox's adapter (Layer 3) should call into this path; Layer 1 standalone falls back to direct file writes when no daemon is reachable.


Versioning compatibility

ox's pkg/adapterprotocol declares ProtocolVersion = 1. The contract:

  • Vox's adapter binary MUST declare protocol_version: 1 in its info response.
  • If the local ox CLI has a higher minimum supported version than Vox's adapter declares, ox refuses the adapter at registration time.
  • When pkg/adapterprotocol bumps to v2, Vox publishes a v2-capable adapter alongside (or replacing, depending on whether the breaking change matters to our usage).
  • The murmur schema (SchemaVersion: "1") is independently versioned. Vox writes schema_version: "1" murmurs until ox publishes a "2".

Both versions are gates Vox checks at startup. Mismatch fails fast with a clear error pointing the user at the upgrade path.


Upstream conversations needed

Four items to surface with the sageox team before sinking implementation effort. The full GitHub Discussion text is in ox-github-discussion-draft.md.

1. Conflict with their roadmap

ox may already plan to ship local audio capture. A 5-minute conversation up front prevents working at cross-purposes. The likely outcomes:

  • They have a local-audio plan and welcome contribution. Best case — we contribute the recording engine instead of building a parallel one.
  • They have a local-audio plan and prefer to ship their own. Vox positions as a complement (broader capture sources, more sinks) rather than as the recording engine.
  • They have no local-audio plan. Greenlight to ship Vox + integration as designed.

Action: open a GitHub Discussion on sageox/ox before writing the adapter binary. Discussion draft prepared.

2. Trademark / branding

"ox" / "SageOx" are upstream's marks; "Vox" / "Blackrim Vox" are ours. The combination ("Vox is an ox adapter") is fine but worth being explicit in the README, docs, and any marketing:

Vox is a third-party adapter for SageOx. Not affiliated with SageOx Inc.

This phrasing belongs in: - Vox's README "See also" section (already mentions Blackrim, will add ox) - The Vox docs integration page (this file — see footer) - The ox-adapter-vox binary's info response (in the Description field) - Any blog post / launch announcement

3. Murmur write performance (technical coordination)

Documented above. Worth raising in the GitHub Discussion so: - The upstream team can confirm or correct our understanding of the daemon's role. - We agree on a contention model (file locks? IPC delegation? both?). - We agree on a reasonable default git_commit_interval.

4. Versioning compatibility (technical coordination)

Documented above. Worth confirming with upstream: - Their cadence for protocol version bumps (we want stable v1 for at least Vox's v1 lifetime). - Their stance on backporting protocol fixes (if v2 breaks something for v1 adapters, do v1 adapters get a fix window?). - Whether new capability constants (audio_capturer, murmur_writer) are welcome additions to pkg/adapterprotocol.


Capability constants — proposed additions

Vox needs two new capability constants in pkg/adapterprotocol. Both are additive (non-breaking):

// Existing
const (
    CapSessionReader      = "session_reader"
    CapHookInstaller      = "hook_installer"
    CapIncrementalReader  = "incremental_reader"
    CapFileWatcher        = "file_watcher"
    CapSessionImporter    = "session_importer"
    CapServeMode          = "serve_mode"
    CapSubagentController = "subagent_controller"
    CapRulesInstaller     = "rules_installer"
    CapCommandsInstaller  = "commands_installer"
    CapCapturePrior       = "capture_prior"
)

// Proposed additions
const (
    CapAudioCapturer = "audio_capturer"   // Adapter captures live audio (mic, system audio, etc.)
    CapMurmurWriter  = "murmur_writer"    // Adapter writes murmurs directly into the ledger
)

These are tiny PRs to sageox/ox and pose no risk to existing adapters. Submitted alongside the ox-adapter-vox registry entry.


Registration paths

Two options for where ox-adapter-vox lives in ox's registry:

Option A — In sageox/ox-adapters (the external adapter repo):

# Added to internal/adapter/registry.yaml in sageox/ox
- name: vox
  display_name: Vox
  description: Local audio capture + transcription → murmurs in the ledger
  type: session
  bundled: false
  binary: ox-adapter-vox
  repo: sageox/ox-adapters
  capabilities: [audio_capturer, murmur_writer, hook_installer, serve_mode]
  detect_commands: [vox]

Pros: standard path for non-bundled adapters; sageox curates. Cons: sageox-controlled release cadence; small lag for our updates.

Option B — In jsgerman-oss/blackrim-vox (Vox's own repo):

- name: vox
  display_name: Vox
  description: Local audio capture + transcription → murmurs in the ledger
  type: session
  bundled: false
  binary: ox-adapter-vox
  repo: jsgerman-oss/blackrim-vox
  capabilities: [audio_capturer, murmur_writer, hook_installer, serve_mode]
  detect_commands: [vox]

Pros: we own the release cadence; the adapter ships with the main Vox binary; one source of truth. Cons: sageox has to be comfortable trusting a third-party repo field.

Recommendation: Option B. Vox owns the adapter, sageox curates the registry. Confirms in the GitHub Discussion.


Implementation phases

v1 (initial Vox release)

  • L1 (direct file writer): implemented inside the ox-ledger sink.
  • L2 (ox-ledger sink): full sink/v1 implementation with templating, filter block, git commit batching.
  • Detection: ox-ledger sink auto-detects ledger dir from ~/.sageox/config.yaml or OX_LEDGER_DIR env var; falls back to user-configured path.

v1.1 (formal adapter handshake)

  • L3 (cmd/ox-adapter-vox/): compliant adapter binary implementing the full ox protocol. When present, Vox prefers daemon IPC over direct file writes.
  • Registry entry: PR landed in sageox/ox against internal/adapter/registry.yaml.
  • Capability constants: PR for CapAudioCapturer + CapMurmurWriter in pkg/adapterprotocol.

v2+ (deferred)

  • L4 (bidirectional): Vox's router subscribes to recent ox murmurs to improve intent classification.
  • Session writer: in addition to per-envelope murmurs, write a session-level summary that ox's session viewer treats as a first-class voice session.
  • Bidirectional sync: Vox's S3 archive becomes addressable from ox via a vox.audio_ref_location resolver.

Configuration sketch (full)

The ox-ledger sink config in a Vox sinks: block:

sinks:
  - name: team-ledger
    type: ox-ledger
    ledger_dir: ~/.sageox/ledger            # auto-detected from ~/.sageox/config.yaml when blank
    agent_id_template: "vox-{{ .InstanceID }}"
    agent_type: vox
    topic_template: "voice/{{ .Envelope.Speaker.SourceKind }}/{{ .Envelope.Intent.Kind }}"
    importance_template: "{{ if gt .Envelope.Intent.Confidence 0.8 }}normal{{ else }}ambient{{ end }}"
    scope: team                              # "team" | "ledger"
    schema_version: "1"
    git_commit_interval: 30s
    git_auto_push: false
    prefer_daemon_ipc: true                  # use ox daemon IPC when reachable; fall back to direct file write
    filter:
      intent_kinds: [prompt, command, todo, note, summary, llm_response]
      source_kinds: [self, in-person, online]
      min_confidence: 0.6
      include_derived: true

Files in this integration

Path Purpose
ox.md (this file) Integration design + upstream conversation tracking
ox-github-discussion-draft.md Text to post on sageox/ox Discussions
../extensions/sink-v1.md Sink contract; includes ox-ledger as a built-in sink
../../cmd/ox-adapter-vox/ Compliant adapter binary (skeleton)
../../internal/sinks/oxledger/ Implementation of the ox-ledger sink type (post-implementation)

Posture

Vox is a third-party adapter for SageOx. Not affiliated with SageOx Inc. "SageOx", "ox", and the SageOx logo are trademarks of SageOx Inc. and used here under their permitted-reference policy.