# Runtime: Contactos

> Listar, paginar y filtrar contactos desde un worker con plz.contacts

Fuente: https://developers.plazbot.com/cli/workers/runtime-contactos/

Dentro de cualquier worker (`defineTool`, `defineWorker`, `defineWebhook`, `defineSchedule`, `defineSync`) el contexto `plz` expone el módulo `plz.contacts` para trabajar con los contactos del workspace.

## Listar contactos

```ts
// Los 20 contactos con actividad más reciente
const contacts = await plz.contacts.list();

// Con límite, offset y filtros
const pendientes = await plz.contacts.list({
filter: { isSolved: false },
limit: 200,
});
```

### Parámetros de `list`

| Parámetro | Tipo | Descripción |
|-----------|------|-------------|
| `limit` | `number` | Máximo de contactos a devolver. Default `20`, tope `1000`. |
| `offset` | `number` | Cuántos contactos saltar antes de empezar a devolver. |
| `filter` | `object` | Filtros opcionales (ver tabla). |

### Filtros disponibles

| Filtro | Tipo | Coincide con... |
|--------|------|------------------|
| `tags` | `string[]` | Contactos que tienen **todas** las etiquetas (por id o por nombre). |
| `stage` | `string` | El `stageId` del contacto. |
| `isSolved` | `boolean` | Conversación resuelta o pendiente. |
| `assignedAgentId` | `string` | El agente asignado. |
| `search` | `string` | Texto contenido en nombre, email o teléfono. |

Los contactos vienen ordenados por última actividad (`lastMessageDate` descendente).

## Recorrer todos los contactos (paginación por cursor)

Para recorrer el universo completo del workspace usa `listPage` y repite con `nextCursor` hasta recibir `null`:

```ts
import { defineSchedule } from 'plazbot/workers';

export default defineSchedule({
name: 'export-diario',
reference: 'Recorre todos los contactos del workspace',
cron: '0 6 * * *',
async handler(plz) {
  let cursor: string | null = null;
  let total = 0;

  do {
    const page = await plz.contacts.listPage({ cursor, pageSize: 100 });

    for (const contact of page.items) {
      // procesar cada contacto
      total++;
    }

    cursor = page.nextCursor;
  } while (cursor);

  plz.log.info(`Contactos recorridos: ${total}`);
},
});
```

### Parámetros de `listPage`

| Parámetro | Tipo | Descripción |
|-----------|------|-------------|
| `pageSize` | `number` | Tamaño de página, entre 1 y 100. Default `20`. |
| `cursor` | `string \| null` | El `nextCursor` de la página anterior. Omitir para la primera página. |

### Respuesta

```ts
{
items: Contact[];          // los contactos de la página
nextCursor: string | null; // pasar a la siguiente llamada; null = no hay mas
}
```

## list vs listPage

| Usa... | Cuando... |
|--------|-----------|
| `list` | Necesitas un conjunto acotado (los últimos N, los que cumplen un filtro). |
| `listPage` | Necesitas recorrer o exportar **todos** los contactos del workspace. |

`list` con `limit`/`offset` itera páginas internamente por ti; para volumenes grandes `listPage` es más eficiente y predecible.

## Rate limits

Las llamadas de `plz.contacts` cuentan contra el [límite de la API del workspace](https://developers.plazbot.com/sdk/rate-limits) (120 req/min). Con `pageSize: 100`, recorrer 50.000 contactos son 500 llamadas ; dentro del límite tarda unos 5 minutos.
