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. Call it, read what it costs and see the API, all on one page: arch-e.world/lander.
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.
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.
A company accounts export goes in, the record comes out filled, and a person rates each criterion 1 to 5. The gate reports the weighted mean times twenty, so 0 to 100. We did not write a single criterion. Move one weight and the ranking changes, which means the weights are the investment policy, so they live in the model as data and the code that averages them does not know what any of them mean.
The first real export found three bugs, and the worst was not in the scoring. The parser assumed the newest year is printed first. That file printed oldest first, so nothing failed: it handed over a reversed series and the function that takes the latest year took the oldest. Headcount read 72 instead of 230 and net debt 3,6 M€ instead of 12,3. The fixture only ever built the descending case, which is exactly why the bug survived.
164 tests across 12 files, 21 migrations, a six sheet export. How it was built, at arch-e.world/deals. No client, no portfolio company and no criterion appears on that page, because none of those are mine to publish.
One email, Friday morning. I read the week in AI and agents anyway, so the digest is the by-product of work I was doing regardless. A script builds it from one file per week, and the rule that decides what gets in is short: a paper with no number in it does not get in.
The same email carries whatever else moved that week:
The address is used for this and nothing else. No tracking pixel, no second email, and one line back to me takes you off it. Every week is public anyway, so you can read it without giving me anything.
Loading the pieces…
jamesarchibal@gmail.com
English, Spanish and Catalan, with experience working in the UK and Spain.