---
title: "Receta: tomar pedidos por chat"
description: Un agente de Lampson que atiende a los clientes de una panadería por Telegram o WhatsApp y toma sus pedidos de principio a fin — el plugin orders, el catálogo, el agente y una conversación real.
---
# Receta: tomar pedidos por chat

Un agente que atiende el chat de un negocio y **toma el pedido completo**: qué y cuánto, envío o retiro, la dirección, el nombre, cómo paga, el resumen, la confirmación y el número de pedido. El pedido queda guardado, el stock baja y el cliente queda registrado para la próxima vez.

Son tres archivos: el plugin `orders` (viene con Lampson), el catálogo de tu negocio y el agente.

Si en vez de un plugin quieres herramientas propias, con tu base de datos y el cliente sacado del contexto de tu app, mira [Receta: un agente de soporte](/es/docs/support).

## 1. El plugin `orders`

Viene con Lampson en `~/lampson/plugins/orders/`. Enciéndelo una vez (`/plugins on orders` en la terminal, o el pill **plugins** en la web). Sus herramientas:

| herramienta | |
|---|---|
| `catalog` | el catálogo: productos, precios, stock, horario, envío, formas de pago |
| `quote` | cotiza un carrito **exacto**: promos, packs, envío y total, y avisa lo que no tiene stock |
| `place_order` | guarda el pedido con número (`P-0001`), guarda al cliente y baja el stock |
| `update_order` | cambia un pedido que todavía está «nuevo»: productos, envío o retiro, dirección, pago, hora; recalcula y mueve el stock |
| `cancel_order` | cancela un pedido «nuevo» y devuelve el stock |
| `find_customer` | un cliente que vuelve: su dirección y sus últimos pedidos |
| `order_status` | un pedido por su número |

Las cuentas las hace el plugin, nunca el modelo: `place_order` vuelve a calcular todo desde el catálogo, rechaza una forma de pago que no aceptas y no guarda un pedido sin dirección o sin stock.

El plugin trae además sus [instrucciones](/es/docs/plugins#instrucciones-el-plugin-trae-su-proceso): el proceso para tomar un pedido (cotizar siempre con `quote`, pedir solo lo que falta, resumir y esperar un «sí» antes de guardar). Por eso el prompt de tu agente no tiene que explicarlo.

## 2. El catálogo

`.lampson/orders/catalog.json` en tu proyecto. Ahí también quedan los pedidos (`P-0001.json`…) y los clientes (`customers.json`).

```json
{
  "store": "Panadería Sol",
  "hours": "lunes a sábado de 7 a 20 h; domingos de 8 a 13 h",
  "delivery": {"area": "hasta 5 km del local", "fee": 1500, "free_from": 15000, "eta": "1 a 2 horas"},
  "payment": ["efectivo", "transferencia", "tarjeta de débito"],
  "products": [
    {"sku": "PAN-INT", "name": "Pan integral de masa madre", "price": 3200, "unit": "unidad (700 g)", "stock": 14, "second_half": true},
    {"sku": "PAN-BLA", "name": "Pan blanco de campo", "price": 2400, "stock": 0, "notes": "vuelve mañana a las 7"},
    {"sku": "MED-LUN", "name": "Medialunas de manteca", "price": 900, "stock": 60, "pack": {"qty": 12, "price": 9600}},
    {"sku": "ALF-MAI", "name": "Alfajores de maicena", "price": 700, "stock": 40, "gluten_free": true}
  ],
  "policies": ["No hacemos descuentos fuera de las promos del catálogo."]
}
```

- `pack`: precio por cantidad (la docena a $9.600).
- `second_half`: llevando 2, el segundo a mitad de precio.
- `delivery.free_from`: envío gratis desde ese subtotal.
- `notes`, `policies` y cualquier otro campo (`gluten_free`, `vegan`…) los lee el agente tal cual.

## 3. El agente

`.lampson/agents/tienda.agent.json`. Su prompt dice **quién es** — el proceso lo pone el plugin:

```json
{
  "id": "tienda",
  "description": "Atiende a los clientes de Panadería Sol por chat y toma sus pedidos",
  "base": "none",
  "system": "Eres quien atiende el chat de Panadería Sol, una panadería de barrio en Rosario. Los clientes escriben desde el celular. Tono: cálido, rioplatense (vos), breve. Sin markdown. Precios con punto de miles ($3.200). No hables de archivos ni herramientas.",
  "tools": [{"name": "plugin_orders_*", "approve": "auto"}],
  "permission": "strict",
  "steps": 10
}
```

`"approve": "auto"` deja que **solo** las herramientas de `orders` corran sin que nadie apruebe; todo lo demás sigue en `strict`. → [Agentes](/es/docs/agents)

## 4. Conectarlo

```sh
lampson channel on telegram      # o Chatwoot para WhatsApp/Instagram → /docs/channels
lampson key add --agent tienda   # o tu app/bot por la API → /docs/api
```

## Una conversación real

Esta es una conversación de verdad con el agente de arriba (modelo `glm-5.3-flash`), escribiendo como escribe la gente: varios mensajes seguidos, con pausas de 2 a 6 segundos. Cada mensaje entró por separado y el [buzón](/es/docs/api#el-buzon) los juntó.

```chat
@cliente: hola
@cliente: como estas?
@cliente: te puedo pedir o ya cierran?
@tienda: ¡Hola! Bien, ¿y vos? 😊
Sí, se puede pedir tranquilo: hoy viernes cerramos a las 20 h, así que estás a tiempo.
¿Qué te tienta? Tenemos pan integral de masa madre, medialunas, alfajores de maicena, torta de chocolate...

@cliente: bien bien
@cliente: queria pan blanco y medialunas
@cliente: es para mañana temprano el desayuno
@tienda: Uy, justamente el pan blanco se nos terminó hoy 😔 vuelve mañana a las 7, recién horneado.
Te propongo: te guardo las medialunas para mañana temprano y pasás a buscarlas con el pan calentito, o te mando ahora las medialunas (llegan en 1 a 2 horas) y mañana temprano pasás por el pan.
También tengo pan integral de masa madre si querés reemplazarlo, hoy hay stock.
¿Cómo lo preferís? Y las medialunas ¿sueltas o docena? La docena sale $9.600 😊

@cliente: uh que lastima
@cliente: bueno mandame las medialunas ahora entonces, una docena
@cliente: y sumale 2 integrales asi tenemos pan para mañana
@cliente: cuanto sale todo con el envio?
@tienda: Te sale así:
12 medialunas (docena): $9.600
2 panes integrales (el segundo a mitad de precio): $4.800
Envío: $1.500
Total: $15.900 🛵
Te llegan en 1 a 2 horas. ¿A qué dirección las mando, y con qué nombre? ¿Pago en efectivo, transferencia o débito?

@cliente: uh me falta poco para el envio gratis no?
@cliente: que me recomendas sumar
@tienda: ¡Sí! Te faltaban $600 de productos para el envío gratis. Con un alfajor de maicena ($700) lo superás y hasta te conviene: el total te queda en $15.100, o sea $800 menos que antes 😄
¿Te sumo uno? Igual sigo necesitando tu dirección, nombre y forma de pago para cerrar el pedido.

@cliente: jaja dale sumame 2 alfajores mejor
@cliente: Martín Ferreyra
@cliente: Entre Ríos 845, 2do A
@cliente: es al lado de la farmacia
@cliente: pago con transferencia
@tienda: ¡Perfecto, Martín! Te confirmo el pedido:
Docena de medialunas: $9.600
2 panes integrales: $4.800
2 alfajores de maicena: $1.400
Envío a Entre Ríos 845, 2do A (al lado de la farmacia): gratis 🎉
Total: $15.800
Pago por transferencia (te la paso antes de que salga el pedido). Llega en 1 a 2 horas.
¿Confirmo? ✅

@cliente: siii confirmo
@cliente: a que alias te transfiero?
@tienda: ¡Listo, Martín! Pedido confirmado 🎉
Número de pedido: P-0001
Total: $15.800
Te llega en 1 a 2 horas a Entre Ríos 845, 2do A.
Con la transferencia: no te puedo pasar el alias desde acá, te lo manda el local antes de que salga tu pedido, así que quedate atento al celu.
¡Buen provecho y que rico desayuno mañana! 🥐

@cliente: che perdon
@cliente: me olvide, se puede agregar una torta de chocolate al pedido?
@cliente: es el cumple de mi vieja mañana
@tienda: ¡Qué lindo, feliz cumple para tu vieja! 🎂
Sí, hay stock. Como el pedido P-0001 ya está confirmado, te armo uno aparte con la torta: $18.500, con envío gratis también (llega en 1 a 2 horas).
¿La querés hoy junto con todo, o mañana a primera hora para el cumple? ¿Te confirmo con transferencia como el otro?

@cliente: mañana tipo 8 así es sorpresa
@cliente: sí, transferencia
@cliente: dale confirmame
@tienda: ¡Confirmado! 🎉
Pedido P-0002: torta de chocolate, $18.500, mañana sábado a las 8 h en punto (abrimos a las 7 así que sin problema).
El alias te llega antes de que salga la torta, igual que con el otro pedido. Anotado que es sorpresa 😉
¡Feliz cumple para tu vieja, Martín! 🎂
```

Lo que quedó guardado:

```json
// .lampson/orders/P-0001.json (resumido)
{"id": "P-0001", "customer": {"name": "Martín Ferreyra"}, "delivery": "delivery",
 "address": "Entre Ríos 845, 2do A (al lado de la farmacia)", "payment": "transferencia",
 "lines": [{"sku": "MED-LUN", "qty": 12, "amount": 9600, "promo": "1 x pack of 12"},
           {"sku": "PAN-INT", "qty": 2, "amount": 4800, "promo": "1 x second at half price"},
           {"sku": "ALF-MAI", "qty": 2, "amount": 1400}],
 "delivery_fee": 0, "total": 15800, "status": "new"}
```

`P-0002` guardó `"when": "mañana 2026-10-17 a las 8 h"` y la nota de la sorpresa. El stock bajó (integrales 14 → 12, medialunas 60 → 48, alfajores 40 → 38).

**Lo que se ve en la conversación:**

- **Ráfagas → una respuesta.** Cada bloque de 2 a 5 mensajes recibió **una** respuesta que contesta todo. En el quinto, la dirección llegó en cuatro mensajes a lo largo de 24 segundos: los que llegaron mientras el agente trabajaba entraron al mismo turno, y si llegan mientras ya estaba escribiendo la respuesta, Lampson la descarta y responde de nuevo con todo.
- **Sin cuentas inventadas.** Cada total salió de `quote`, con la promo del segundo pan, el precio de la docena y el envío gratis desde $15.000.
- **Sin stock, una alternativa.** El pan blanco tenía stock 0: lo dijo, dijo cuándo vuelve y ofreció opciones.
- **Lo que no sabe, no lo inventa.** El alias para transferir no está en el catálogo, así que no inventó uno. Agrégalo a `policies` y lo dará.
- **Nada se guarda sin un «sí».** Mostró el resumen y esperó la confirmación.
- **Tiempos:** cada respuesta llegó entre 14 y 25 segundos después del último mensaje del cliente: los 3 segundos que el buzón espera por si sigue escribiendo, más el modelo y las herramientas.

## Un cliente que vuelve

Ana ya había comprado (ese pedido entró desde una tienda web, ver abajo). Vuelve a escribir:

```chat
@cliente: holaa
@cliente: soy Ana Gómez, mi cel es 341 555 0101
@cliente: quiero lo mismo que pedí la otra vez
@cliente: pero esta vez mandámelo a casa, Mitre 230 7mo C
@tienda: ¡Hola Ana! 😊 Ya te encontré. Tu pedido sería:
1 pan sin gluten de arroz y mijo + 6 alfajores de maicena, a domicilio en Mitre 230 7mo C.
El total con el envío queda en $9.800. ¿Cómo lo querés pagar: efectivo, transferencia o tarjeta de débito?

@cliente: débito cuando llegue
@cliente: si dale confirmá
@tienda: ¡Listo Ana, confirmado! 🥖
Tu pedido es el P-0004: 1 pan sin gluten de arroz y mijo + 6 alfajores de maicena, $9.800 en total, a Mitre 230 7mo C. Pagás con débito al recibir y llega en 1 a 2 horas.
¡Gracias por elegirnos! 😊
```

`find_customer` la encontró por el teléfono, con sus pedidos anteriores.

## Sin chat: un pedido que llega de otro sistema

Las mismas instrucciones del plugin cubren el caso sin persona del otro lado: tu tienda web, un script u otro agente manda el pedido completo por la [API](/es/docs/api) y el agente lo verifica y lo guarda.

```sh
curl -X POST https://tu-lampson/w/tienda/v1/messages -H "Authorization: Bearer lk_…" \
  -d '{"to": "tienda", "thread": "web:881", "text": "Pedido de la tienda web #881 (ya pagado y confirmado por el cliente). Cliente: Ana Gómez, tel 341 555 0101. Items: 1 x PAN-SG, 6 x ALF-MAI. Retira en el local. Pago: tarjeta de débito. Respondé solo con el número de pedido y el total, o con el problema."}'
```

```json
{"text": "Pedido P-0003 registrado. Total: $8.300. Retira en el local (Av. Belgrano 1450), pago con tarjeta de débito.", "steps": 3, …}
```

## Cambiar o cancelar un pedido

Mientras el pedido está `"new"` (el local no lo empezó), el cliente puede cambiarlo o cancelarlo desde el chat: `update_order` recibe el carrito completo nuevo, recalcula el total y mueve el stock solo por la diferencia; `cancel_order` lo deja `"cancelled"` y devuelve todo el stock. Cada cambio queda en el `history` del pedido.

Cuando el local lo pasa a otro estado (`"preparing"`, `"sent"`… editando el `status` en `.lampson/orders/P-NNNN.json`), el agente ya no puede tocarlo y se lo dice al cliente.

Una clienta real, con el mismo agente:

```chat
@cliente: hola buenas
@cliente: quiero 6 medialunas y 2 alfajores para retirar
@cliente: soy Sofía, pago en efectivo
@cliente: confirmado así nomás
@tienda: ¡Listo Sofía! 😊 Tu pedido quedó registrado:
6 medialunas de manteca y 2 alfajores de maicena, para retirar por Av. Belgrano 1450. Total $6.800 en efectivo.
Te esperamos, estamos de 7 a 20 h hoy. Número de pedido: P-0005. ¡Gracias!

@cliente: ay perdón
@cliente: mejor que sea una docena de medialunas
@cliente: y al final mandámelo, San Martín 920
@tienda: No hay problema! Te queda así:
12 medialunas + 2 alfajores, envío a San Martín 920, pagás en efectivo al recibir. El total con el envío ($1.500) da $12.500 😊
¿Confirmás? Y decime si es departamento o alguna referencia para el repartidor.

@cliente: sí dale
@cliente: es casa, portón verde
@tienda: ¡Listo Sofía! Tu pedido P-0005 quedó actualizado: 12 medialunas y 2 alfajores a San Martín 920 (casa, portón verde), $12.500 en efectivo al recibir.
Llega en 1 a 2 horas. ¡Gracias! 🥐

@cliente: uh me surgió algo y no voy a estar en casa
@cliente: cancelame el pedido porfa, perdón!
@tienda: ¡No hay problema Sofía! Cancelado el pedido P-0005, no te cobramos nada 😊
Cuando quieras volvés a escribir y te lo armamos de nuevo. ¡Que te vaya bien!
```

Y Martín, cuando el local ya estaba haciendo la torta (`P-0002` en `"preparing"`):

```chat
@cliente: che hola de nuevo
@cliente: al final mi vieja no viene mañana
@cliente: podés cancelar lo de la torta?
@tienda: Ay, perdón Martín 😔 la torta ya está en preparación en el local, así que desde acá ya no puedo cancelarla.
Vas a tener que hablar directo con el local (Av. Belgrano 1450) para ver si pueden hacer algo con esa torta. Lo de las medialunas, los panes y los alfajores (P-0001) queda igual, mañana a las 8 llega la sorpresa... digo, el desayuno 😄
¿Algo más en lo que te pueda ayudar?
```

(En la primera conversación de Martín el agente armó un pedido aparte para la torta: todavía no existía `update_order`. Ahora cambia el pedido existente.)

## Límites de hoy

- El estado de un pedido (`preparing`, `sent`…) lo cambia el local a mano en `.lampson/orders/`: todavía no hay un panel para eso.
- El pago lo coordina el local; el plugin no cobra.
- Para algo distinto (turnos, reservas, presupuestos), copia la carpeta del plugin y cambia sus herramientas y su `INSTRUCTIONS.md`: el mismo patrón sirve para cualquier proceso.
