No switchboard to buy and no project to run. You paste one block of JSON into the tool you already use, answer four questions in the chat, and a real number starts answering in Spanish, Catalan and English. It works your CRM, your tickets and your calendar, and hands a human a spoken summary when it should.
Ni centralita que comprar ni proyecto que montar. Pegas un bloque de JSON en la herramienta que ya usas, contestas cuatro preguntas en el chat, y un número real empieza a contestar en español, catalán e inglés. Trabaja contra tu CRM, tus tickets y tu calendario, y pasa a una persona con un resumen hablado cuando toca.
The code is public and free, so the only bill is the one your own providers send. It says it is an AI in the first second, because hiring is high risk under Annex III of the EU AI Act.
El código es público y gratuito, así que la única factura es la de tus proveedores. Dice que es una IA en el primer segundo, porque la contratación es de alto riesgo según el anexo III del Reglamento Europeo de IA.
Nothing to adopt: Lander is a tool surface your own model calls, so the setup is one block of JSON and a short conversation. The tools exist in the agent today, the MCP wrapper does not.
Nada que adoptar: Lander es una superficie de herramientas que llama tu modelo, así que el montaje es un bloque de JSON y una conversación corta. Las herramientas ya existen en el agente, el envoltorio MCP no.
{ "mcpServers": { "lander": { "command": "npx", "args": ["-y", "@joblanders/lander-mcp"], "env": { "LANDER_API_KEY": "sk_live_…" } } } } # or in one line: claude mcp add lander -- npx -y @joblanders/lander-mcp
claude_desktop_config.json, .mcp.json, or the equivalent
file in whichever tool you use. Restart it. That is the whole installation.
claude_desktop_config.json, .mcp.json o el fichero
equivalente de la herramienta que uses. Reiniíciala. Esa es toda la
instalación.
No settings screen. Each answer writes one real knob in the agent.
Sin pantalla de ajustes. Cada respuesta escribe un ajuste real del agente.
Which number do I answer?
¿Qué número contesto?Your SIP trunk, or ours. Inbound only. Tu trunk SIP, o el nuestro. Solo entrada.
Which of the five roles picks up?
¿Cuál de los cinco roles descuelga?The rest are reached by a handoff. A los otros se llega por traspaso.
Where do the facts live?
¿Dónde viven los datos?The only source it may quote. La única fuente que puede citar.
Who does it transfer to?
¿A quién transfiere?And what it says to them, privately, first. Y qué le dice antes, en privado.
It reads what was said; it never places a call. Today's working path is self-host.
Lee qué se dijo; nunca hace una llamada. La vía que funciona hoy es autoalojarlo.
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.
Un solo agente con un prompt de 18 KB intentaba ser recepcionista, comercial, soporte y reclutador a la vez, y difuminaba los cuatro. Ahora cada agente lleva solo su prompt de rol y solo las herramientas que tiene permitidas, y traspasa devolviendo el siguiente agente desde una llamada a herramienta.
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. The sales agent cannot read a candidate's file either.
Es una decisión de contención, no de organigrama. Cuanto más estrecha es la superficie de herramientas, más pequeño es el conjunto de cosas que puede alcanzar una inyección de prompt en lo que dice quien llama. El agente de ventas tampoco puede leer la ficha de un candidato.
A speech-to-speech model is faster and sounds better, and gives you no text to assert on. Lander quotes prices and reads back application statuses, so it needs a transcript per turn to regression-test, to log, and to show a client who asks what the agent told their candidate. The latency cost of the cascade is the price of being able to test it.
Un modelo de voz a voz es más rápido y suena mejor, y no te deja texto sobre el que aseverar. Lander da precios y lee estados de candidatura, así que necesita una transcripción por turno para hacer test de regresión, para registrar y para enseñarle a un cliente qué le dijo el agente a su candidato. El coste en latencia de la cascada es el precio de poder probarla.
The agent never states a price, a status or an availability from its own weights. The knowledge layer and the tools are the only sources, and a miss returns “I do not have that” rather than a plausible sentence. An agent that invents a salary band in a hiring call has made a statement the company is liable for.
El agente nunca dice un precio, un estado o una disponibilidad desde sus propios pesos. La capa de conocimiento y las herramientas son las únicas fuentes, y un fallo devuelve «eso no lo tengo» en lugar de una frase plausible. Un agente que se invente una banda salarial en una llamada de contratación ha hecho una afirmación de la que responde la empresa.
These are the real names in the published repository, not an invented API. The list is short on purpose: it is the complete set of things a caller's sentence can reach.
Estos son los nombres reales del repositorio publicado, no una API inventada. La lista es corta a propósito: es el conjunto completo de cosas que puede alcanzar una frase de quien llama.
get_product_info
Product and pricing facts the sales agent is allowed to quote. A miss returns nothing, never a guess.
Datos de producto y precio que el agente de ventas puede citar. Un fallo no devuelve nada, nunca una conjetura.
get_support_info
The same contract over the support FAQ, scoped to one category at a time.
El mismo contrato sobre el FAQ de soporte, limitado a una categoría a la vez.
lookup_application_status
A candidate's application status by reference, read back as stored. This is the call that makes the whole thing Annex III.
El estado de una candidatura por referencia, leído tal cual está guardado. Es la llamada que convierte todo esto en anexo III.
identify_by_email
Matches a caller whose number is not in the CRM, so caller-ID is never the only identity check.
Identifica a quien llama desde un número que no está en el CRM, para que el identificador de llamada no sea la única comprobación.
log_lead
Writes one qualified inbound lead to the CRM. Best-effort: a failed write is reported, not swallowed.
Escribe un lead de entrada cualificado en el CRM. Al mejor esfuerzo: un fallo de escritura se reporta, no se traga.
book_demo
Books a real slot on a real calendar, with the caller on the invitation.
Reserva un hueco real en un calendario real, con quien llama en la invitación.
transfer_to_human
Dials the human, speaks a summary to them privately, asks whether they will take it, and relays a decline back to the caller.
Marca a la persona, le dice un resumen en privado, pregunta si la coge y le devuelve la negativa a quien llama.
pasar_a_ventas
Handoff. Returns the next agent, which is the whole mechanism: a role change is a tool result, not a branch in a prompt.
Traspaso. Devuelve el siguiente agente, que es todo el mecanismo: un cambio de rol es el resultado de una herramienta, no una rama en un prompt.
finalizar_llamada
Short goodbye, then hang up. Separate from the handoff so the agent cannot end a call it meant to pass on.
Despedida corta y colgar. Separado del traspaso para que el agente no pueda terminar una llamada que quería pasar.
Both published in full, with the commit. One says the author's hypothesis was wrong.
Las dos publicadas enteras, con el commit. Una dice que la hipótesis del autor estaba equivocada.
The question was whether to move speech to text from Deepgram to ElevenLabs Scribe. The obvious test runs both over clean audio and compares 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 a mode a live call has. 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.
La pregunta era si mover el reconocimiento de voz de Deepgram a ElevenLabs Scribe. El test obvio pasa los dos por audio limpio y compara la tasa de error de palabra. Dos cosas fallan en el test obvio: el audio limpio a 16 kHz no es lo que llega por una línea de teléfono, y la transcripción en lote no es un modo que tenga una llamada en vivo. Así que el harness degrada el audio a 8 kHz mu-law, G.711, que es lo que entrega el trunk, y mide streaming aparte del lote.
| EngineMotor | ModeModo | WER |
|---|---|---|
| Scribe v1 / v2 | batchlote | 3,3% |
| Deepgram nova-3 | streaming | 5,8% |
| Scribe v2 realtime | streaming | 14,9% |
Batch Scribe wins by a wide margin and is irrelevant. 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.
Scribe en lote gana por mucho y es irrelevante. El motor que de verdad habría corrido es la última fila, casi tres veces peor que el que ya estaba. Y los errores no son ruido repartido, son contenido: a l'any se convirtió en a Lenny, Visc a Barcelona en Visca Barcelona.
Source: six Catalan screening phrases, commit a56ba00 on branch lab/stt-benchmark.
Fuente: seis frases de cribado en catalán, commit a56ba00 en la rama lab/stt-benchmark.
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.
Quien llama no percibe el tiempo hasta el primer token. Percibe el hueco entre terminar su frase y oír una voz. El medidor de latencia lee las métricas por turno que registra el agente, reporta p50, p95 y máximo por fase contra un presupuesto escrito una vez, y sale con código distinto de cero si se incumple, para poder bloquear un deploy.
| PhaseFase | Budget at p95Presupuesto en p95 |
|---|---|
end_of_utterance_delay | 0,8 s |
ttft | 1,2 s |
ttfb | 1,0 s |
response_gap, the felt silenceel silencio percibido |
2,5 s |
Source: evals/latency.py and evals/selftest.py in the repository.
Fuente: evals/latency.py y evals/selftest.py en el repositorio.
Not a policy page. Four behaviours in the code, each one testable, and one obligation that does not apply and is named anyway.
No es una página de políticas. Cuatro comportamientos en el código, cada uno comprobable, y una obligación que no aplica y se nombra igual.
The agent states it is an AI on pickup, before anything else. Logged with a timestamp, because “we disclose” is a claim and a timestamp is evidence.
El agente dice que es una IA al descolgar, antes de nada. Registrado con marca de tiempo, porque «informamos» es una afirmación y una marca de tiempo es prueba.
Always available, honoured immediately, never argued with.
Siempre disponible, atendida de inmediato, sin discutirla nunca.
The agent dials the human, speaks a summary privately, asks whether they will take it, and relays a decline. Nobody is bridged into a call they did not agree to take.
El agente marca a la persona, le dice un resumen en privado, pregunta si la coge y devuelve la negativa. Nadie entra en una llamada que no aceptó.
So no Lista Robinson scrubbing, which is an outbound obligation. Named here because an unlisted obligation looks like an overlooked one.
Así que no hay cruce con la Lista Robinson, que es una obligación de salida. Se nombra aquí porque una obligación no listada parece una obligación olvidada.
# Shipped. The code that ran on a real number, with client data and prompts removed. git clone https://github.com/jamesjoblanders/voiceagent-public pip install -r requirements.txt && cp .env.example .env python agent.py console # local mic, no telephony python agent.py dev # worker on a SIP trunk python evals/run.py # graded, costs cents python evals/selftest.py # offline, free
console needs only Anthropic, Deepgram and ElevenLabs keys. The voice IDs,
trunk and LiveKit project in the repository are placeholders.
console solo necesita claves de Anthropic, Deepgram y ElevenLabs. Las voces,
el trunk y el proyecto de LiveKit del repositorio son marcadores de posición.