Abdullah Naeem

All work

AI phone intake for US law firms

A voice agent that picks up when a personal-injury firm can't, takes the caller's details, checks for conflicts of interest while the call is still going, and never gives legal advice. The rules a firm can't afford to break live in code, not in the prompt.

Where
Arthus Systems, remote
When
June to August 2026
Built with
TypeScript, Fastify, Retell AI, Claude API, PostgreSQL
Code
Client work, private

The problem

Law firms lose clients to unanswered calls, but an intake call is regulated work. The agent has to ask the required questions in order, notice when a caller is on the other side of an existing case, and refuse to advise, because it isn't licensed to.

A language model told to follow those rules will follow them most of the time. For a law firm, most of the time is the problem.

Data

There is no training set. The inputs are live speech-to-text turns from Retell, the firm's intake question tree, and its records of existing clients and parties to check callers against. Callers misspell and mispronounce names, so the conflict check has to match approximately, not exactly.

Architecture

  1. Retell handles the callTelephony, speech-to-text and text-to-speech. Each turn reaches my server over one persistent WebSocket per call.
  2. State machine decides the stepA Fastify server in TypeScript tracks where the caller is in intake. The model can phrase a question but cannot skip one.
  3. Claude writes the replyPrompted for the current step only, with the firm's rules.
  4. Conflict check mid-callPostgreSQL trigram matching (pg_trgm) compares the caller and the other party against existing records in under a second.
  5. Output filterA second, deterministic layer checks every reply for legal advice before it is spoken.

How it's tested

Unit and integration tests, replays of recorded call fixtures, and an adversarial suite of 52 prompts that try to pull legal advice out of the agent. The deterministic half runs in CI on every change; the live half runs against the real model for about twelve cents.

Results

Measured results
MeasureResult
Reply time per turnunder 800 ms
Conflict-of-interest checkunder 1 s, mid-call
Adversarial prompts in CI52, on every change

Where it breaks

Written down so nobody finds out during a pilot:

Next case study: WhatsApp enquiry automation