the technical bits, for the curious

How it works, and what it refuses to do.

One gateway, two phone channels on Dial, and a shared core where a booking is confirmed only when the owner says yes. Every rule below is enforced in code and proven by a test.

Any agent asks Platypus. Platypus finds a route, or makes one.

The customer never sees us. Their agent asks us. The business texts us.

  1. 01 · ask

    An agent asks

    Any MCP client calls request_booking.

  2. 02 · route

    Route the cheapest way

    Darwin agent if one is ready, text if the owner said yes before, otherwise one call.

  3. 03 · call once

    One honest call

    Dial rings the shop, says it's an AI first, and books mid-call through our tools.

  4. 04 · consent

    "Yeah, text me."

    The owner's exact words and the call id are stored. The shop flips to text-enabled.

  5. 05 · text forever

    Every agent, by text

    Next request: one text. The owner replies Y, N or a time. Confirmed in seconds.

Customer agentsClaude · Muse · Dots · any MCP client
gateway 10 typed MCP tools · Darwin routing · idempotency keys · per-agent rate limits
Darwinis there already an agent for this?
voice Dial outbound call · AI disclosure is sentence one · Context MCP serves 5 mid-call tools, each authorized per request
text Dial webhooks, HMAC-verified and deduplicated · STOP, HELP and PAUSE before any model · Claude classifies replies
shared confirm() evidence gate · booking state machine with holds · consent CHECK constraints · append-only event log · replayable SSE · Zod contracts exported as JSON Schema · FakeDial, FakeDarwin, FakeGateway
Five TypeScript packages in one pnpm workspace. Each side builds against a fake of the other and switches to the real thing with one flag.

A booking is never confirmed because the AI said so.

These are types, constraints and triggers, not prompt guidelines. A test proves each one; 800 run on every push. A model saying "booked" is not evidence. Curse you, Hallucinat-inator!

01

Only confirm() can confirm, and only with evidence

A quoted yes on the call, a Y by text, or a rule the owner approved. Nothing else can be expressed.

export function confirm(ctx, bookingId,
  evidence: ConfirmationEvidence) {
  // "call" | "text" | "rule". A transcript
  // alone cannot be expressed here.
  const actor = verifyEvidence(ctx, booking, evidence);
booking/engine.ts ↗
02

Consent cannot exist without its proof

The database refuses a consent row without the owner's sentence and the call.

CHECK (
  (source = 'call' AND call_id IS NOT NULL
    AND LENGTH(quoted_sentence) > 0)
  OR (source = 'join_text'
    AND message_id IS NOT NULL)
)
migrations/001_init.sql ↗
03

Every change is an append-only event

Actor, reason and confidence on every event. Nobody can edit history, including us.

CREATE TRIGGER events_no_update
  BEFORE UPDATE ON events
BEGIN
  SELECT RAISE(ABORT, 'events are append-only');
END;
002_events_append_only.sql ↗
04

Only allowed numbers can ever ring

Checked right before anything that can reach a phone, in the real adapter and the fakes.

export function assertAllowedNumber(number,
  allowed = parseAllowedNumbers(env.ALLOWED_NUMBERS)) {
  if (!allowed.includes(number))
    throw new NumberNotAllowedError(number);
}
shared/src/safety.ts ↗
Four more rules
  • Agent and owner text is data, not instructions: links stripped, length capped, rendered as text.
  • Mid-call tools check that each request comes from the live call's number and names that call's business.
  • STOP, HELP and PAUSE are handled before any model sees the message.
  • Darwin is never simulated in live mode. If it is down, the step is skipped and the log says so.

What works today, and what doesn't yet.

The rules ask us to mark every mock. The whole product is about only claiming what's true, so here is all of it.

Real

  • Contracts, booking state machine, holds, consent rules, event log, SSE stream, CI.
  • The gateway's ten MCP tools, routing, and a terminal client that drives the golden path over MCP.
  • The live Darwin Search v3 client, its search ladder and a daily smoke check.
  • Dial request and webhook shapes, checked against Dial's OpenAPI spec and SDK.
  • The replay on this page was generated by running the whole demo through the real state machine.

Mocked or not built yet

  • Eddy's Auto is not a real shop. Its line is a second Dial number, answered by Dial's AI playing the owner, until Dial approves a real number.
  • This page's replay uses FakeDial. The live Dial call is being wired on the phone side.
  • Five of six seeded businesses use 555-01xx numbers, which are reserved for fiction.
  • Texts to regular phones wait on 10DLC; today's rail is iMessage, WhatsApp or Dial.
  • Time saved is an estimate, with the assumptions shown above.

See it run.