Lander.
Inbound voiceVoz de entrada · ES · CA · EN Live on a real number En marcha en un número real

Your best receptionist.
Two minutes to hire.
Tu mejor recepcionista.
Dos minutos de alta.

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.

5
Agents, one number Agentes, un número
3
Languages, a cloned voice each Idiomas, una voz clonada en cada uno
2,5 s
p95 felt silence Silencio percibido p95
30 s
Graded evals per deploy Evals graduadas por deploy
API & MCP In design En diseño

One block to paste, then four questions

Un bloque que pegar, y luego cuatro preguntas

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.

01

Copy the block

Copia el bloque

{ "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
02

Paste it where your model reads its servers

Pégalo donde tu modelo lee sus servidores

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.

03

Answer four questions, in the chat

Contesta cuatro preguntas, en el chat

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.

How it works
Cómo funciona

Five specialised agents, not one prompt

Cinco agentes especializados, no un 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.

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.

01

The support agent cannot quote a price

El agente de soporte no puede dar un precio

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.

02

Cascaded on purpose, not speech-to-speech

En cascada a propósito, no voz a voz

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.

03

Facts come from one place

Los datos vienen de un solo sitio

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.

PythonLiveKit AgentsDeepgram Claude HaikuElevenLabsSIP
The tool surface, as shipped
La superficie de herramientas, tal cual

Nine functions, and no tenth one

Nueve funciones, y no hay una décima

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.
Evidence
Evidencia

Two measurements that changed the product

Dos medidas que cambiaron el producto

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 clean benchmark pointed the wrong way

El benchmark limpio apuntaba al lado equivocado

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 / v2batchlote3,3%
Deepgram nova-3streaming5,8%
Scribe v2 realtimestreaming14,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.

Kept Deepgram. The clean batch benchmark, which is the one most people would have run and published, pointed the other way.
Se queda Deepgram. El benchmark limpio en lote, que es el que la mayoría habría hecho y publicado, apuntaba al otro lado.

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.

The felt silence is the metric

La métrica es el silencio percibido

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_delay0,8 s
ttft1,2 s
ttfb1,0 s
response_gap, the felt silenceel silencio percibido 2,5 s
The bug worth reporting is in the harness, not the agent. An unmatched scenario silently fell back to feeding the scenario sentence to the model, so it still scored and still printed a number. Eleven cases degraded that way at once, because the Spanish was typed without accents. There is now a free offline check in CI that fails on it.
El bug que merece reportarse está en el harness, no en el agente. Un escenario sin coincidencia caía en silencio a darle al modelo la propia frase del escenario, así que seguía puntuando y seguía imprimiendo un número. Once casos se degradaron así a la vez, porque el español se escribió sin acentos. Ahora hay una comprobación offline y gratis en CI que falla por eso.

Source: evals/latency.py and evals/selftest.py in the repository. Fuente: evals/latency.py y evals/selftest.py en el repositorio.

Compliance
Cumplimiento

Because hiring is Annex III

Porque contratar es anexo III

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.

EU AI Act art. 50

Disclosure, first

Informar, primero

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.

Our own ruleRegla propia

Human escape

Salida humana

Always available, honoured immediately, never argued with.

Siempre disponible, atendida de inmediato, sin discutirla nunca.

Our own ruleRegla propia

Warm transfer with consent

Transferencia en caliente con consentimiento

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ó.

Our own ruleRegla propia

Inbound only

Solo entrada

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.

Pricing
Precio

The code is free. The phone number is the work.

El código es gratis. El número de teléfono es el trabajo.

Self-hostAutoalojado Works todayFunciona hoy
0 €
  • The whole agent, five roles, the prompts' structure
  • El agente entero, cinco roles, la estructura de los prompts
  • Both benchmarks, the latency meter, the eval suite
  • Los dos benchmarks, el medidor de latencia, las evals
  • You bring the keys and the SIP trunk
  • Tú traes las claves y el trunk SIP
Clone itClonarlo
Hosted numberNúmero alojado PlannedPlaneado
Per minute
Por minuto
  • A number, a trunk and the five roles, configured
  • Un número, un trunk y los cinco roles, configurados
  • Call records with the disclosure timestamp
  • Registros de llamada con la marca de tiempo del aviso
  • The latency gate wired into your deploys
  • La puerta de latencia conectada a tus deploys
Ask about itPreguntar
Deployed with youDesplegado contigo
Talk
Hablamos
  • Your prompts, your knowledge layer, your tools
  • Tus prompts, tu capa de conocimiento, tus herramientas
  • Scenarios written against your actual calls
  • Escenarios escritos contra tus llamadas reales
  • An Annex III file you can hand to a regulator
  • Un expediente de anexo III que puedes entregar a un regulador
Get in touchContactar
# 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.