Para desarrolladores
Un paquete npm y tus usuarios van a poder usar tu producto desde WhatsApp — con seguridad, aprobaciones y auditoría incluidas.
Un plugin es un paquete npm que le enseña a Dale a hablar con tu API. Tiene dos partes: un conector (habla con tu API) y un pack (define qué puede hacer el usuario). Dale se encarga del resto: WhatsApp, aprobaciones, seguridad y auditoría.
Arquitectura
┌─────────────────────────────────────────┐
│ tu-empresa-dale-plugin │ ← UN paquete npm
│ │
│ ┌──────────────┐ ┌─────────────────┐ │
│ │ Connector │ │ Pack │ │
│ │ (HTTP a │ │ (flujo + params │ │
│ │ tu API) │ │ + keywords) │ │
│ └──────────────┘ └─────────────────┘ │
│ │
│ export installMiPlugin(ctx) → {} │ ← UNA función pública
└─────────────────────────────────────────┘
│
│ installMiPlugin({ connectors, packs })
▼
┌─────────────────────────────────────────┐
│ Dale Core OS │
│ ✓ Brain (IA) — extrae params del chat │
│ ✓ HITL — aprobaciones humanas │
│ ✓ Vault — credenciales encriptadas │
│ ✓ Evidence — ledger de auditoría │
│ ✓ WhatsApp — canal listo para usar │
└─────────────────────────────────────────┘
│
│ HTTP call en runtime
▼
┌─────────────────────────────────────────┐
│ TU API (tus servidores) │
│ Tu lógica · Tu data · Tu control │
└─────────────────────────────────────────┘Tu API corre en tus servidores. Dale solo la llama. Tu infraestructura, tu data, tu control.
Conceptos clave
Habla con tu API. Define las acciones disponibles (crear reserva, consultar saldo, etc). Recibe credenciales del vault de Dale, nunca maneja secretos directamente.
Define el flujo conversacional. Qué frases lo activan, qué pasos sigue, y cuáles necesitan aprobación del usuario.
Declarás qué datos necesita cada acción. Dale los extrae del mensaje del usuario automáticamente y pregunta lo que falte.
Dale maneja las credenciales encriptadas, pide aprobación para acciones sensibles, y registra todo en un ledger de auditoría. Tu plugin no toca nada de eso.
Crear un plugin en 5 pasos
¿Qué puede hacer tu API? Listá las acciones (ej: 'crearReserva', 'consultarEstado'). Cada acción recibe parámetros y devuelve un resultado.
Creá una clase que implemente DaleConnectorAdapter. Un switch por acción, llamás a tu API, devolvés el resultado normalizado.
Usá paramsSchema para decirle a Dale qué datos necesita cada acción. Dale los extrae del mensaje o se los pregunta al usuario.
Definí el grafo (flujo de pasos), las frases que lo activan, y qué acciones necesitan aprobación humana (policy: 'confirm').
Exportá una función installTuPlugin(ctx) y publicá. Los operadores lo instalan desde el dashboard.
Paso 1 — El conector
El conector habla con tu API. Implementa DaleConnectorAdapter con un execute() que rutea por acción.
import type {
DaleConnectorAdapter,
ConnectorCapability,
ConnectorCallRequest,
ConnectorCallResponse,
} from '@dale/core-types';
const BASE_URL = 'https://api.tu-servicio.com/v1';
export class MiConnector implements DaleConnectorAdapter {
readonly capability: ConnectorCapability = {
connectorId: 'mi-saas',
supportedActions: ['listar', 'crear', 'cancelar'],
requiresApproval: false,
};
async execute(request: ConnectorCallRequest): Promise<ConnectorCallResponse> {
const token = request.resolvedCredential
? new TextDecoder().decode(request.resolvedCredential)
: undefined;
try {
switch (request.action) {
case 'listar': {
const res = await fetch(`${BASE_URL}/items`, {
headers: token ? { Authorization: `Bearer ${token}` } : {},
});
if (!res.ok) return { success: false, errorCode: 'api_error' };
const data = await res.json();
return { success: true, data: { items: data.items } };
}
case 'crear': {
const res = await fetch(`${BASE_URL}/items`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
body: JSON.stringify(request.params),
});
if (!res.ok) return { success: false, errorCode: 'create_failed' };
const created = await res.json();
return { success: true, data: { id: created.id }, externalRef: created.id };
}
default:
return { success: false, errorCode: 'action_not_supported' };
}
} catch (err) {
return { success: false, errorCode: 'network_error',
errorMessage: err instanceof Error ? err.message : 'Error de conexión' };
}
}
}Paso 2 — Declarar parámetros
Con paramsSchema le decís a Dale qué datos necesita cada acción. Dale los extrae del mensaje automáticamente.
{
id: 'crear-entidad',
type: 'action',
policy: 'confirm',
connectorId: 'mi-saas',
connectorAction: 'crear',
paramsSchema: {
name: { type: 'string', required: true, description: 'Nombre', example: 'Acme SA' },
country: { type: 'string', required: true, description: 'País', example: 'Argentina' },
tax_id: { type: 'string', required: false, description: 'CUIT/CUIL', example: '30-71234567-8' },
plan: { type: 'enum', required: true, description: 'Plan',
enumValues: ['starter', 'pro', 'enterprise'], example: 'pro' },
},
}| Tipo | Descripción | Ejemplo |
|---|---|---|
| string | Texto libre | Nombre, email |
| number | Valor numérico | Monto, cantidad |
| boolean | Sí o no | Activo, confirmado |
| enum | Uno de un set fijo | Estado, categoría, país |
Paso 3 — El pack
El pack define el flujo conversacional: qué frases lo activan, qué pasos sigue, y cuáles necesitan aprobación.
import type { DalePackManifest, Graph } from '@dale/core-types';
const mainGraph: Graph = {
id: 'mi-saas/crear-v1',
version: '1.0',
nodes: [
{ id: 'start', type: 'start', policy: 'auto' },
{
id: 'crear-entidad',
type: 'action',
policy: 'confirm', // pausa para aprobación
label: 'Crear entidad en Mi SaaS',
connectorId: 'mi-saas',
connectorAction: 'crear',
paramsSchema: {
name: { type: 'string', required: true, description: 'Nombre', example: 'Acme SA' },
country: { type: 'string', required: true, description: 'País', example: 'Argentina' },
},
},
{ id: 'end', type: 'end', policy: 'auto' },
],
edges: [
{ from: 'start', to: 'crear-entidad' },
{ from: 'crear-entidad', to: 'end' },
],
};
export const miPack: DalePackManifest = {
id: 'mi-saas',
name: 'Mi SaaS Pack',
version: '1.0.0',
intents: [
{ id: 'crear_entidad', keywords: ['crear entidad', 'nueva entidad'], graphId: 'mi-saas/crear-v1' },
],
graphs: [mainGraph],
};| Policy | Qué pasa | Cuándo usar |
|---|---|---|
| auto | Dale ejecuta sin parar | Consultas, búsquedas, lecturas |
| confirm | Dale pausa y pide aprobación | Crear, modificar, pagar, eliminar |
Paso 4 — La función de instalación
Exportá una función que registra todo. Dale la llama al instalar tu plugin.
import type { DalePluginContext, DalePluginInstaller } from '@dale/core-types';
import { MiConnector } from './connector';
import { miPack } from './pack';
export const installMiPlugin: DalePluginInstaller = (ctx: DalePluginContext) => {
ctx.connectors.register(new MiConnector());
ctx.packs.register(miPack);
return {
pluginId: 'mi-saas-plugin',
name: 'Mi SaaS Plugin',
version: '1.0.0',
connectors: ['mi-saas'],
packs: ['mi-saas'],
docsUrl: 'https://docs.tu-servicio.com',
};
};Estructura del paquete
mi-saas-dale-plugin/ ├── src/ │ ├── connector.ts ← implementa DaleConnectorAdapter │ ├── pack.ts ← define Graph + PackManifest + paramsSchema │ └── index.ts ← exporta la función de instalación ├── tests/ │ ├── connector.test.ts │ └── install.test.ts ├── package.json └── tsconfig.json
Qué te da Dale sin costo adicional
Reglas de seguridad
Dale le da superpoderes a tu producto. Tus usuarios van a poder usarlo desde WhatsApp, con seguridad, aprobaciones y auditoría incluidas. Todo con un paquete npm.
Escribinos →