James Archidona · Technical founder · Sapere aude Sapere aude, Latin for dare to know. Written by Horace in Epistles I.2, around 20 BC, as advice to stop waiting and begin. Immanuel Kant made it the motto of the Enlightenment in 1784, in What is Enlightenment?, where it means: have the courage to use your own understanding instead of borrowing someone else’s. Horace, Epistles I.2.40 · Kant, 1784 · Europe
Innovation is progress. I dedicate my life to it: more than ten years building and selling technology, from Apple to my own startups. Below is my current state of mind.
It answers a real phone number in Spanish, Catalan and English, declares that it is an AI before anything else, works out what the caller wants, handles it with tools against a CRM, a ticket system and a calendar, and hands over to a human with a spoken summary when it should.
Five specialised agents, not one prompt. One agent with one 18 KB prompt tried to be a receptionist, a salesperson, a support desk and a screener at once, and blurred all four. Each agent now carries only its own role prompt and only the tools it is allowed to use, and hands off by returning the next agent from a tool call. The support agent cannot quote a price. The sales agent cannot read a candidate's file. That is a containment decision, not an organisational one: the narrower the tool surface, the smaller the set of things a prompt injection in a caller's utterance can reach.
Cascaded on purpose, not speech-to-speech. A speech-to-speech model is faster and sounds better, and gives you no text to assert on. This agent quotes prices and reads back application statuses in a hiring context, which is high risk under Annex III of the EU AI Act. The latency cost of the cascade is the price of being able to test it.
Source: the repository, published with the prompts and the client's data removed from the whole history.
The question was whether to move speech to text from Deepgram to ElevenLabs Scribe. The obvious test is to run both over clean audio and compare word error rate. Two things are wrong with the obvious test: clean 16 kHz audio is not what arrives down a phone line, and batch transcription is not the mode that runs in a live call. So the harness degrades the audio to 8 kHz mu-law, G.711, which is what the trunk delivers, and measures streaming separately from batch.
| Engine | Mode | WER |
|---|---|---|
| Scribe v1 / v2 | batch | 3,3% |
| Deepgram nova-3 | streaming | 5,8% |
| Scribe v2 realtime | streaming | 14,9% |
Batch Scribe wins by a wide margin and is irrelevant, because batch is not a mode a phone call has. The engine that would actually have run is the last row, nearly three times worse than the incumbent. The errors are not evenly spread noise either, they are content: a l'any became a Lenny, Visc a Barcelona became Visca Barcelona. In one case the interim hypothesis was better than the final one, so the closing pass actively degraded the result.
Source: six Catalan screening phrases, commit a56ba00 on branch
lab/stt-benchmark, in
the repository.
Production was showing 2,38 to 2,43 s to first token. The system prompt was 18 KB. The obvious conclusion is that the prompt is the cost, and the obvious fix is to trim it. Measured against the API directly, over the same five-turn conversation:
| Prompt | Size | Mean TTFT |
|---|---|---|
| Full | 18.118 chars | 0,68 s |
| Trimmed | 5.740 chars | 0,57 s |
So the whole prompt costs 0,68 s, not 2,4 s, and cutting two thirds of it buys 0,11 s. The missing 1,8 s was somewhere else: cold start, because the worker scales to zero, plus end-of-turn detection, which is an endpointing delay plus a model inference per turn.
Source: commit 8778abc on branch lab/stt-benchmark, in
the repository.
A caller does not experience time to first token. They experience the gap between finishing their sentence and hearing a voice. The latency meter parses the per-turn metrics the agent logs, reports p50, p95 and max per phase against a budget written down once, and exits non-zero on a breach so it can gate a deploy.
| Phase | Budget at p95 |
|---|---|
| End of utterance delay | 0,8 s |
| Time to first token | 1,2 s |
| Time to first byte of audio | 1,0 s |
| Response gap, the felt silence | 2,5 s |
Separately, a judge model grades the agent's text behaviour against 24 saved scenarios before every deploy, in about thirty seconds and a few cents. Two of the 24 are permanent known false negatives, because the opening AI disclosure is static synthesised audio that a text harness cannot observe. They are excluded by name and reported as N/A, because an ignored failure nobody can explain later is worse than a documented one.
Source: evals/latency.py and evals/selftest.py in
the repository.
Spain's commercial registry gazette is published daily and is effectively unqueryable. The build loads it into an index: 741.233 companies and 1.182.206 corporate acts, 503 days of gazette, in four minutes, at no cost, because the summary exposes structured XML per province and nobody needs to parse the PDFs.
The design decision is the redaction, not the parser. The gazette names natural persons. The index never stores one: the rule runs before anything is written, and the four measurements that shaped it are in the header of the file that implements it, so the next reader changes it with the evidence in front of them.
Live at joblanders.ai/coarchive, free, no account.
Everything I have built myself, with its state today. Each line links to the thing that is running. Where the code is not public yet, the line says so rather than linking to nothing.
jamesarchibal@gmail.com
Right to work in the UK, six years in London. English, Spanish and Catalan.