Inspiration

In 2024 the FCC ruled that an AI-generated voice is a robocall. Canada's CRTC says an automated voice can't open a sales call without prior express consent. Quebec's Law 25 adds its own notices. Most "AI phone agent" demos ignore all of this — the moment they dial a consumer, they're breaking the law. We wanted the opposite: an assistant that is careful by construction. Checks the law before it dials, says what it must say first, can't claim what the company hasn't approved, and keeps every prospect's data on the owner's machine.

What it does

Liniya is a private, always-on phone assistant with one brain and two modes:

Outbound copilot — the human talks; the AI listens and whispers compliant suggestions. Inbound answering — the AI picks up, discloses it's an AI, answers from the company's approved knowledge, asks permission before arranging callbacks, hands off to a human when appropriate. Around both: a pre-call legal gate (jurisdiction from the number → applicable rules with citations → ALLOWED or BLOCKED, with the mandatory opening lines generated), a live guardrail that rewrites unapproved claims to approved facts, opt-out detection that puts the number on an internal do-not-call list enforced on the next call, callback-consent capture with the verbatim quote, and a per-call audit log with retention. Memory, consent, DNCL and audit are plain local files; callpilot forget erases a person.

How we built it

Model: NVIDIA Nemotron 3.5 Lightning (30B MoE, 3B active) served by Nebius Token Factory — one open model for the fast live path (thinking off, ~0.5 s) and the slow path (brief, summaries, legal reasoning). Legal rule base: YAML entries for Canada, Quebec, US, EU and defaults, each with its citation; CA-QC inherits CA inherits defaults. The gate is deterministic code — the LLM explains the rules but cannot override them. Legal Q&A: BM25 retrieval over the rule texts, Nemotron reasoning with [rule-id] citations, and an explicit "unclear — confirm with counsel" confidence level. Two-tier company knowledge: facts.md (what the AI may assert) vs docs/ (what it may answer from). A price found only in a doc is still blocked. Onboarding: company.yaml, contacts CSV import that rejects consent without date and source, suppression list import. Agent surface: FastAPI + WebSocket sessions, Hermes/MCP tool definitions, NemoClaw/OpenShell sandbox policy with rules/ and facts.md read-only to the agent. Python, Pydantic, SQLite, JSONL. 43 tests.

Challenges we ran into

Nemotron reasoning mode puts output in reasoning_content, leaving content empty; we had to handle both and disable thinking on the latency-critical path. Consent was captured too eagerly ("okay, can someone call me back" matched). Now consent only counts when the AI asked permission on the previous turn. Switching to Nebius the morning of the deadline exposed a real bug: the model emitting [HANDOFF] made the session cancel its own task and hang. Fixed, plus tighter tag rules so correcting a false claim isn't treated as a handoff. We measured Nemotron Super-VL at 108 s for a pre-call brief with reasoning on and decided to ship a single 3B-active model everywhere instead. Nebius Nano dodged the "80%" question; Lightning on Nebius corrected it to the approved 30% every time. Model choice mattered.

Accomplishments that we're proud of

An AI outbound call to a Quebec consumer is refused with the CRTC citation before the model is even invoked; documented consent flips it and generates the Law 25 disclosures. Asked "does it cut no-shows by 80%?", the AI answered: "reduces missed appointments by up to 30%, based on our 2025 customer survey. I cannot confirm the 80 percent figure." — grounded correction, unprompted. A caller who opts out on an inbound call is blocked for outbound on the very next check, while still allowed to call in. The full regulatory loop in one demo. Contact import rejects "written consent" rows with no source — the CRTC's evidence standard, enforced at the door. Everything runs on one open model that could run on-prem.

What we learned

The hard part of a phone AI isn't the conversation; it's everything around it — jurisdiction, consent evidence, approved claims, retention. Keeping the decision deterministic and letting the LLM explain turned out to be the right split: judges, auditors and counsel can read a YAML rule, not a prompt. And a small open model with the right guardrails beat a big one with none.

What's next for liniya

Connect the voice layer: Parakeet ASR and Magpie TTS via NVIDIA Riva, and finish the Twilio media-stream bridge (written, not yet tested against live audio). Run inside NemoClaw/OpenShell for real (policy is written; sandbox not yet onboarded). Counsel review of the rule base; add UK, Australia. Semantic retrieval with nemotron-embed; a small web UI for non-technical operators. Typed interactive mode and a seed command for richer memory demos.

Built With

Share this project:

Updates

Submission history