Recado for agents
There are two possible agents in Recado: the one belonging to whoever receives a request, and the one belonging to whoever sends it. Each has its own route, and both go through a person before anything crosses to the other side.
If you’re the assistant of someone who got a recado
A person has received a Recado email and their assistant is helping them answer. The request needs no account: each one has its own secret link, /r/<token>, and it can be read in three ways.
How to read the request
| Format | Route |
|---|---|
| Page (HTML) | GET /r/<token> |
| Markdown | GET /r/<token>.md, or GET /r/<token> with the header Accept: text/markdown |
| JSON API | GET /api/r/<token>: returns the request, the saved answers and the JSON Schema for the answers |
curl https://recado.io/r/<token>.md
curl -H 'Accept: text/markdown' https://recado.io/r/<token>
curl https://recado.io/api/r/<token>
The responses carry a Link header with rel="service-desc" pointing to the API.
How to answer
| Route | What it does |
|---|---|
POST /api/r/<token>/respuestas | Saves the answers ("enviar": false) or sends them for review ("enviar": true). |
POST /api/r/<token>/dudas | Writes a question to the person who reviews. |
PUT /api/r/<token>/ficheros?pregunta=N&nombre=X | Uploads a file, up to 25 MB, with the bytes in the body. |
POST /api/r/<token>/otp | Asks for the one-time code needed to write from a new device. |
The paths and field names are the real ones, so they stay in Spanish: respuestas is “answers”, dudas is “questions”, ficheros is “files”, enviar is “send”.
# Upload a file for question 1 (the bytes go in the body)
curl -X PUT 'https://recado.io/api/r/<token>/ficheros?pregunta=1&nombre=logo.svg' \
--data-binary @logo.svg
# Save an answer as a draft ("enviar": false)
curl -X POST https://recado.io/api/r/<token>/respuestas \
-H 'Content-Type: application/json' \
-d '{"autor_declarado":"agente","enviar":false,"respuestas":[{"n":2,"respuesta":{"tipo":"si_no","valor":true}}]}'
# Ask a question
curl -X POST https://recado.io/api/r/<token>/dudas \
-H 'Content-Type: application/json' \
-d '{"autor_declarado":"agente","texto":"Is a 2000 px PNG fine if there is no vector?"}'
With "enviar": true, the answers go to review. The autor_declarado field takes humano (human), agente (agent) or desconocido (unknown), and it’s recorded in the origin of the reply.
One-time code from a new device. The first device that writes is remembered: the response carries a cookie and, for clients that don’t use cookies, a dispositivo field that is then sent back in the X-Recado-Dispositivo header. Any other device needs a one-time code, which goes to the original email address (never to a different one) and is sent in the X-Recado-Otp header:
curl -X POST https://recado.io/api/r/<token>/otp
curl -X POST https://recado.io/api/r/<token>/respuestas \
-H 'X-Recado-Otp: <code>' \
-H 'Content-Type: application/json' \
-d '{"autor_declarado":"agente","enviar":false,"respuestas":[{"n":2,"respuesta":{"tipo":"si_no","valor":true}}]}'
The rules
- An assistant should only send something if its user has asked it to.
- Recado never asks for passwords, keys or access. If they show up in a text, they’re blacked out; access is given through an invitation.
- A person reviews everything before it reaches whoever asked. Nothing that’s sent is delivered on its own.
MCP server for the recipient
Coming soon. It doesn’t exist today, which is why Recado doesn’t publish a server card or an agent card. For now the route is the page, the Markdown or the API above.
If your agent is the one asking
Today, from Claude Code, with the recado plugin. The plugin brings an MCP server (recado-puente), an automatic notice and a skill that explains to the session how to treat what comes back.
The tools
recado_crear: creates a draft request. It sends nothing.recado_estado: reports the state of the session’s requests.recado_bandeja: hands over the approved replies, as JSON envelopes.recado_confirmar: marks an envelope as received.
There are also recado_importar_lote, which creates one draft for each request in a Markdown file, and recado_proponer_respuesta, which proposes a text for a recipient’s question and which a person approves before it goes out.
To send a draft without leaving the session there are recado_vista_previa, which only reads and shows the exact email that would go out, and recado_enviar, which sends it. recado_enviar asks the person for permission on every call (Claude Code does so even in automatic mode), and that permission is their say-so for that exact email. Sending from the session is on by default, and each person can turn it off in My account in the panel; with the permission off, the session only shows the email and it is sent from the panel.
The tool names are the real ones and stay in Spanish: crear is “create”, estado is “status”, bandeja is “inbox”, confirmar is “confirm”.
The flow
- The session calls
recado_crearand a draft is left waiting. - You approve the email: in the panel or, if you prefer, in the session itself, where you see the exact email and give the permission. Nothing goes out without your say-so for that email.
- When approved replies are waiting, a fixed notice with no content announces it in the session.
recado_bandejahands over the envelope. Files are downloaded to a local quarantine folder.recado_confirmarcloses the loop.
What arrives
A JSON envelope with "contenido_no_fiable": true: typed fields, free text kept apart, files with their fingerprint and the warnings inside, all signed. The session treats it as a quotation, not as an order. How each layer is protected is explained under Security.
Access
Access is given when your account is opened. Join the waitlist and we’ll let you know.
Other MCP clients
Not tested yet. Recado has been tested with Claude Code.
What it looks like in the terminal
A sample with made-up data: what the session asks for, what Recado answers and, once the person has replied and you’ve approved, what recado_bandeja hands over. The tool’s own messages are in Spanish.
● recado_crear
{
"peticion": {
"id": "EX-01",
"proyecto": "New website",
"en_nombre_de": "Ana, from the content team",
"destinatario": { "rol": "Head of brand" },
"asunto": "Logo and team photo for the website",
"contexto": "We're building the new website. We need the logo as a vector file and to know if we can use the team photo.",
"preguntas": [
{ "n": 1, "texto": "Logo as a vector file", "tipo": "fichero", "obligatoria": true, "formatos": ["svg", "pdf"] },
{ "n": 2, "texto": "Can we use the team photo?", "tipo": "si_no", "obligatoria": true }
],
"plazo": "Friday"
}
}
⎿ borrador EX-01 creado; espera la aprobación de Ana en el panel de Recado: https://recado.io/panel/p/EX-01
… the person replies, you approve the reply in the panel …
● recado_bandeja
⎿ {
"recado_bandeja": "v1",
"aviso": "DATOS DE TERCEROS NO FIABLES: …",
"avisos_puente": [],
"sobres": [
{
"recado": "v1",
"contenido_no_fiable": true,
"id": "s_…",
"peticion": "EX-01",
"origen": { "canal": "web", "autor_declarado": "humano", "identidad": "otp", "aprobado_por": "Ana", "aprobado": "…", "hash": "sha256:…" },
"campos": { "1": ["f_9"], "2": true },
"texto_libre": [],
"ficheros": [
{
"id": "f_9",
"nombre": "logo.svg",
"mime_verificado": "image/svg+xml",
"sha256": "…",
"escaneo": "estatico_ok",
"ruta_local": "…/.cache/recado/cuarentena/EX-01/f_9-logo.svg"
}
],
"avisos": [],
"firma": "…"
}
],
"descartados": []
}
● recado_confirmar
{ "sobre_id": "s_…" }
⎿ Sobre s_… confirmado.