Inspiration
A supplier's mailbox gets compromised and accounts payable receives a polite note: we have moved our banking, please update before the next payment run. The next invoice goes to the attacker. FBI IC3 counted $2.77B of BEC losses in 2024; AFP reports 74% of US organisations were hit by BEC in 2025. Every advisory prescribes the same control: call the phone number you already had on file, never the number in the email. It gets skipped constantly because it is fifteen minutes of awkward phone work per change, landing on the most junior person at month end. That is exactly the kind of phone work an agent should do.
What it does
Known Number is a CLI workflow on the CALL-E Developer API:
- Policy gates, no network. The vendor must exist in the vendor master; the phone number on file must predate the request by 30+ days (an attacker who can change your bank details can usually change your phone number first); the callback number the requester supplied is logged as a fraud indicator and never dialed; a live call needs a named approver.
- Phone leg, collects nothing. CALL-E dials the number on file, discloses it is automated and recorded, asks for a named authorised contact, then asks three yes/no questions: did you request a change, does the written notice we sent to your address on file describe it, did it come through your normal channel. Then it gives the contact a six-character callback reference. No bank name, no digits, no code ever crosses the voice channel in either direction.
- Deterministic reconciliation. CALL-E's schema-validated
structured_resultplus its evidence quotes go through a fail-closed matrix into one of six verdicts: CONFIRMED, PENDING_WRITTEN_REPLY, DENIED_BY_VENDOR, MISMATCH, ESCALATE, INCONCLUSIVE. A clean phone leg only produces PENDING. - Written leg closes. When the vendor replies from the address on file quoting the reference,
known-number closeproduces CONFIRMED, the only verdict that releases the change, plus an audit memo with request fingerprint, masked number, call id, reasons and evidence.
Verified live: a real CALL-E call over the international line to an Indian mobile completed the phone leg with 0.93 completion confidence; the written reply closed it as CONFIRMED. The demo video shows the actual transcript.
How we built it
Python 3.11, the official calle-ai SDK, stdlib otherwise. task.py builds the payment-free task text and a closed result_schema; policy.py holds the gates; reconcile.py is the verdict matrix; store.py persists the call id before the first poll (mode 0600) so a crash resumes with status instead of dialing again; render.py writes the audit record and memo. Eleven fixtures, one per outcome, drive known-number demo and 36 tests with no network. Repository validation passes. PR #378 on CALLE-AI/awesome-phone-call-agents.
Challenges we ran into
The protocol is on its third design, and CALL-E forced both rewrites, correctly. Draft one asked the contact to read back the last four digits of the new account: the planner refused ("I can't plan a call that asks the recipient to provide or confirm bank account/payment details, even partially"). Draft two asked them to read back a one-time code from the written notice: refused again ("no verification code, OTP, password"). Those are the two classic phone-scam scripts, and the refusal is the right default. The protocol got stronger for obeying it: proof of channel control moved to the written leg, where it can be filed.
Two smaller ones: the first international dial failed at the carrier with SIP 480 before ringing (hence --attempt), and CALL-E binds an idempotency key to the first request body it sees even when the planner rejects it (hence the key now hashes the task text).
Accomplishments that we're proud of
A control that finance teams are told to run and don't, reduced to one command with a live-verified call, an audit trail a regulator would accept, and a phone leg that cannot leak or collect anything even if the wrong person answers.
What we learned
Designing for a phone agent that refuses scam-shaped scripts pushes you toward protocols where the voice channel only carries questions and references, and where every sensitive fact travels on a channel you can file. That is a better design than the one we started with.
What's next for Known Number
Ticketing-system integration so inbound replies are matched by reference automatically; dual-contact confirmation above a threshold (the reconciliation already reads recipient-level results); feeding DENIED and MISMATCH verdicts to the security team as confirmed BEC attempts against the supply chain.
AI tooling (Claude) was used to assist development.
Built With
- call-e
- httpx
- python
Log in or sign up for Devpost to join the conversation.