# Rutster

The open-source engine for building the **AI-era contact center** — self-hostable, AI-native,
memory-safe Rust. A spiritual successor to Asterisk's *place in the world*, not its protocols
or its architecture.

> Not a port of Asterisk. rutster inherits the role Asterisk held — *the self-hostable engine a
> technical builder uses to stand up a contact center* — and re-aims it at a category AI is
> actively disrupting, instead of a PBX category UCaaS already ate.

## Quickstart

```bash
# Prereqs: Rust (rustup), libopus dev headers (libopus-dev / opus-devel / brew install opus)
cargo run
# listening on http://0.0.0.0:8080
```

Open <http://localhost:8080/> → click "Start call" → grant mic → hear yourself echo.
Full walkthrough + troubleshooting: **[`docs/QUICKSTART.md`](docs/QUICKSTART.md)**.

### Slice 3 dev loop — OpenAI Realtime brain

The dev loop *without* real OpenAI credentials (no API key required):

```
cargo run -p rutster-brain-realtime --features=mock   # brain on :8082
cargo run                                            # core on :8080
```

Open <http://localhost:8080/> → click "Start call" → speak → hear the
mock-brain reply within ~250 ms (the mock echoes audio back, no real OpenAI
RTT; this exercises the full brain→core audio round-trip + the new
function_call dispatch path).

With real OpenAI Realtime:

```
export OPENAI_API_KEY=sk-...    # or OPENAI_API_KEY_FILE=/var/secrets/openai
cargo run -p rutster-brain-realtime
cargo run
```

Speak → end-to-end speech-to-speech with OpenAI Realtime within ~700 ms
(slice-1's 200 ms + tap round-trip + OpenAI latency + 100 ms playout buffer).

For the foreign-language brain demo (Python, not in CI):

```
pip install -r examples/openai_realtime_brain/requirements.txt
OPENAI_API_KEY=sk-... python examples/openai_realtime_brain/openai_realtime_brain.py
```

> **Status:** Slices 1–4 (WebRTC media core, WS tap, OpenAI Realtime brain,
> barge-in / VAD-driven playout kill) are merged to `main`. Slice 4½
> (sim/benchmark harness, [ADR-0010](docs/adr/0010-spearhead-benchmark-sim-harness.md))
> + step 5 (PSTN via rented Twilio Media Streams transport,
> [ADR-0007](docs/adr/0007-trunk-rented-transport.md)) are the active build targets,
> in flight on their respective branches. ADR-0007 honored: rutster parses zero
> SIP bytes. See the
> [slice-5 design](docs/superpowers/specs/2026-07-05-slice-5-rented-transport-design.md).

## Documentation

| Doc | For when you want to… |
|---|---|
| [`docs/QUICKSTART.md`](docs/QUICKSTART.md) | Run it in 5 minutes |
| [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md) | Iterate on the codebase (workspace layout, per-crate testing, dev loop) |
| [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | Understand the fused per-call vertical + composable platform + agent tap |
| [`docs/PORT_PLAN.md`](docs/PORT_PLAN.md) | See every Asterisk subsystem mapped to a disposition (capability checklist, not template) |
| [`docs/adr/`](docs/adr/) | Load-bearing architecture decisions |
| [`AGENTS.md`](AGENTS.md) | Project orientation for any agent (human/AI/hybrid) working in the repo |
| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Trunk-based dev workflow, CI gates, commit style, review checklist |
| [`LEARNING.md`](LEARNING.md) | Index of "to learn concept X, read file Y" (learner-facing codebase) |

## Why it exists

Asterisk won because contact centers were **built on it** (Vicidial, GOautodial, a thousand
integrator builds) — it never tried to *be* Five9. rutster inherits that position: it is a
**framework / engine, not a turnkey product**.

The white space no incumbent fills:

| Competitor | What they are | rutster's edge |
|---|---|---|
| **LiveKit** | Horizontal real-time media infra (Go) | rutster owns the **contact-center domain** (ACD, IVR, queues, recording, CDR, dialer, supervisor) LiveKit will never ship |
| **Cloud CCaaS** (Five9, Genesys, NICE, Amazon Connect, Twilio Flex) | Proprietary, AI bolted on | Self-hostable, AI-**native**, no per-seat/minute lock-in |
| **Cloud AI-voice** (Vapi, Retell, Bland) | Cheap managed voice bots | You own your **calls and training data**; it's a *contact center* (escalation, queues), not a single bot |
| **The brain vendor direct** (OpenAI Realtime SIP, Gemini Live) | Point a SIP trunk straight at the model API | Everything *around* the call: queues/ACD, human takeover, recording/CDR you own, containment analytics, multi-vendor brains — and the phone still answers when the vendor is down |
| **Dated OSS** (Vicidial, FreePBX) | Self-hostable, Asterisk-era | Modern, AI-native, memory-safe Rust |

The wedge is a **coherent combination, not a silver bullet**:

1. **No-GC real-time determinism** — tight turn-taking / barge-in / jitter in a no-GC loop.
2. **One secure auditable boundary** — media + local reflexes + spend/abuse control + the tap +
   audit in a single memory-safe trust domain. One thing to certify (strongest for PCI / HIPAA / TCPA).
   The carrier trunk is rented (or out-of-tree); bringing PSTN media *inside* the boundary is the
   on-prem **graduation** ([ADR-0007](docs/adr/0007-trunk-rented-transport.md)), not a day-one claim.
3. **Operational simplicity** — one binary, one bill, one deploy.

**Honest caveat:** the agent *brain* (STT/LLM/TTS) is necessarily external — audio leaves the box
to reach it, same as LiveKit. The real-time edge therefore lives in the **local reflexes that don't
need the brain** (VAD killing TTS the instant the caller speaks, barge-in, jitter, pacing, DTMF),
not the brain round-trip. The moat is the *whole*.

## Who it's for

The modern equivalent of the 2006 Linux-nerd-who-stood-up-Asterisk-for-an-SMB: the
**CLI/IDE/AI-comfortable self-hosting technical builder** — runs Claude Code in a terminal, lives
in an editor with an AI pair, versions everything in git, self-hosts on principle. *Not* the no-code
admin clicking a flow-designer canvas. The builder serves the non-technical operator downstream,
exactly as integrators did on top of Asterisk.

## What it is / isn't

- **Is:** a Rust media core owning the **per-call vertical** (RTP/SRTP media termination + local real-time reflexes + a clean
  audio tap to an external brain + in-boundary spend/abuse control; the carrier trunk is *rented
  transport*, not first-party — [ADR-0007](docs/adr/0007-trunk-rented-transport.md)); a programmable call model exposed as a REST/gRPC API + event stream; WebRTC-first human
  ingress; a library of contact-center capabilities (ACD, IVR, queues, recording, CDR, dialer,
  supervisor) delivered as services around the core.
- **Isn't:** a TDM/PSTN-hardware PBX — *and not a SIP stack.* No DAHDI, no Sangoma/Digium cards, no
  ISDN/SS7, no IAX2/H.323/SCCP/MGCP/Unistim — and **no first-party SIP**
  ([ADR-0007](docs/adr/0007-trunk-rented-transport.md)). PSTN reach is **rented transport** (a CPaaS
  raw-media fork, or an out-of-tree SBC for on-prem media). Inbound SIP *endpoint* registration (desk
  phones) likewise stays out-of-tree — not the browser/SSO UX rutster targets.

## Core design pillars

1. **Memory-safe by construction** — Rust everywhere on the hot path; fuzzed sans-IO protocol
   parsers. rutster **parses no SIP at all** ([ADR-0007](docs/adr/0007-trunk-rented-transport.md)): its
   entire first-party wire surface is WebRTC/RTP/SRTP + the WebSocket tap/ingress protocol — all
   memory-safe Rust. The carrier-SIP interop tail lives *outside* the trust boundary (rented transport
   or an out-of-tree SBC), so the buffer-overflow/RCE CVE class is designed out of rutster's own surface.
2. **Security-as-product** — the single auditable boundary *is* the moat. TLS/SRTP mandatory,
   deny-by-default routing, built-in toll-fraud controls, mTLS gRPC admin (no plaintext AMI), hard
   multi-tenancy. Compliance is a buying criterion, not a row.
3. **In-boundary spend / abuse control** — spend caps and abuse/pacing control live **inside the
   trust boundary**, co-located with the tap and the provider call-control client. The brain
   never holds provider credentials, and the gate is unskippable for everything rutster mediates
   — which is everything the brain can do
   ([ADR-0009](docs/adr/0009-spend-gate-honest-rescope.md); pair with provider-side caps for
   defense in depth).
4. **Data ownership** — calls and training data never leave the operator's infra. The self-host
   wedge *and* the fuel for the ML self-improvement loop.
5. **Degradation, deterministic, observable** — no-GC real-time loop; OpenTelemetry traces that
   follow a single call across the boundary; config-as-data, not `.conf` files edited on a box.
6. **Operational simplicity** — one binary, one bus, one deploy (`compose up`).

## Layout

- [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — the fused per-call vertical + composable
  horizontal platform; the agent tap as the central interface.
- [`docs/PORT_PLAN.md`](docs/PORT_PLAN.md) — the capability *checklist* (what a telephony system
  must handle), *not* an architecture template. Every Asterisk subsystem mapped to a disposition
  with rationale.
- [`docs/adr/`](docs/adr/) — decisions. Highlights:
  - [0002](docs/adr/0002-north-star-and-fused-core.md) — north star + fused vertical
  - [0007](docs/adr/0007-trunk-rented-transport.md) — rent the trunk transport; no first-party SIP stack (supersedes [0003](docs/adr/0003-sip-rust-native-trunk.md))
  - [0004](docs/adr/0004-license.md) — GPL-3.0-or-later
  - [0005](docs/adr/0005-event-bus.md) — Valkey (bus + state store)
  - [0006](docs/adr/0006-ingress-posture.md) — WebRTC-first ingress; SIP endpoint deferred
  - [0009](docs/adr/0009-spend-gate-honest-rescope.md) — spend-gate guarantees re-scoped post-0007 (amends 0002)
  - [0010](docs/adr/0010-spearhead-benchmark-sim-harness.md) — spearhead step 4½: benchmark + simulation harness; escalation pulled forward

## Status

Slices 1–4 (WebRTC media core, WS tap, OpenAI Realtime brain, barge-in /
VAD-driven playout kill) are merged to `main`; spearhead steps 4½ (sim/benchmark
harness, [ADR-0010](docs/adr/0010-spearhead-benchmark-sim-harness.md)) + 5 (PSTN
via rented transport, [ADR-0007](docs/adr/0007-trunk-rented-transport.md)) + 6
(spend cap) remain. The
[vision revision](docs/superpowers/specs/2026-06-26-vision-revision-design.md)
and ADRs define the architecture; the
[slice-5 design](docs/superpowers/specs/2026-07-05-slice-5-rented-transport-design.md)
documents the active build. ADR-0007 honored: rutster parses zero SIP bytes.

## First proof (the spearhead)

The full thin slice, sequenced so each step is its own proof — never a big bang:

1. **WebRTC media loopback** (terminate RTP/SRTP, echo audio to a browser) — proves the media core
2. **Add the tap** (route audio to an external echo process and back) — proves the tap interface
3. **Swap echo for the brain** (ideally a single speech-to-speech API, e.g. OpenAI Realtime, to
   collapse STT+LLM+TTS into one integration) — proves agent integration
4. **Add barge-in** (VAD-driven playout kill) — proves the reflex
   - **4½ — Benchmark + simulation harness** ([ADR-0010](docs/adr/0010-spearhead-benchmark-sim-harness.md)):
     synthetic callers drive p50/p99 mouth-to-ear latency + barge-in kill-time under concurrent
     load, in CI — proves the reflex *measurably*; seeds `rutster-sim`
5. **Add a real phone number via rented transport** (a CPaaS raw-media fork, e.g. Twilio Media
   Streams) — proves a PSTN call reaches the reflex loop, no first-party SIP ([ADR-0007](docs/adr/0007-trunk-rented-transport.md))
6. **Add the spend cap** (hard-stop at threshold) — proves the boundary

Steps 1–4 *are* the reflex loop — the hard, most-differentiating part proves itself before trunk
integration piles on. "I called my Rust box and an AI answered the phone" is the momentum fuel a
solo multi-year build needs. Post-review re-sequencing
([ADR-0010](docs/adr/0010-spearhead-benchmark-sim-harness.md)): after step 4½, **rung-2
escalation (human takeover) is pulled forward ahead of steps 5–6** — it is the white space no
competitor ships (see the [2026-07-03 reviews](docs/reviews/)).

## Capability ladder (the grand vision, incrementally)

| Rung | Capability | Reuses |
|---|---|---|
| 1 | **Self-serve** — AI answers, contains the call | the thin-slice first proof |
| 2 | **Escalation** — human agent barges in / takes over when AI breaks down | the audiohook/barge primitive |
| 3 | **Measurement** — containment rate, where/why AI failed | CDR + analytics on calls *you own* |
| 4 | **Self-improvement** — every takeover → auto-labeled training data → loop | rungs 1–3 compounding |

## License

**GPL-3.0-or-later** ([ADR-0004](docs/adr/0004-license.md)). Strong copyleft in the Asterisk lineage,
modernized one notch. The license is the *floor*, not the moat — the wedge is.
