Agent skill
Omnichannel Chat Operator
Especialista en gestión de conversaciones multi-canal (WhatsApp, Instagram, Facebook) para Platform AI Solutions.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/omnichannel-chat-operator-adriangmrraa-multiagents-platform
SKILL.md
Omnichannel Chat Operator - Platform AI Solutions
1. Arquitectura de Comunicación
Canales Soportados
- WhatsApp: Via Meta Cloud API o YCloud
- Instagram: Via Meta Graph API
- Facebook Messenger: Via Meta Graph API
- Web Widget: Canal directo (Chatwoot optional)
Flujo Híbrido de Sincronización
Frontend (Chats.tsx)
↓
Polling (10s) → GET /admin/chats/summary
↓
Chat Selected → Loop (3s) → GET /admin/chats/{id}/messages
↓
Delta Sync (solo nuevos mensajes)
2. Gestión de Conversaciones
Cargar Lista de Chats
// Polling cada 10 segundos
const loadChats = async () => {
const response = await useApi<Contact[]>({
method: 'GET',
url: '/admin/chats/summary',
params: {
human_filter: 'all', // 'all', 'human_only', 'bot_only'
channel: 'whatsapp', // Filtro opcional
limit: 20
}
});
};
// Response structure
interface Contact {
id: string; // UUID
customer_phone: string;
display_name: string;
last_message: string;
timestamp: string;
channel_source: 'whatsapp' | 'instagram' | 'facebook' | 'web';
unread_count: number;
is_locked: boolean; // Human override activo
platform_origin: string; // Cuenta específica de Meta
}
Cargar Mensajes de Conversación
// Loop de 3 segundos cuando chat está seleccionado
const loadMessages = async (chatId: string) => {
const messages = await useApi<Message[]>({
method: 'GET',
url: `/admin/chats/${chatId}/messages`
});
// Ordenar por timestamp (puede venir desordenado)
messages.sort((a, b) =>
new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
);
};
// Message structure
interface Message {
id: number;
conversation_id: string;
sender: 'user' | 'agent';
content: string;
timestamp: string;
attachments?: Attachment[]; // Multimedia
correlation_id?: string; // Link con logs de IA
}
interface Attachment {
type: 'image' | 'video' | 'audio' | 'document';
url: string;
filename?: string;
}
3. Envío de Mensajes (Unified Outbox)
Send Tunnel
const sendMessage = async (
conversationId: string,
message: string,
channelSource: string
) => {
await useApi({
method: 'POST',
url: '/admin/whatsapp/send',
data: {
conversation_id: conversationId,
message: message,
channel_source: channelSource // CRÍTICO para routing
}
});
};
Backend Routing (Orchestrator v6.2.9)
# orchestrator_service/app/api/v1/endpoints/chats.py
@router.post("/whatsapp/send")
async def send_message(
payload: SendMessageRequest,
current_user = Depends(verify_admin_token)
):
# 1. Resolver tenant e ID de conversación
tenant_id = await resolve_tenant(current_user.id)
# 2. Delegar al Universal Delivery Relay (v6.2.9)
# Se centraliza en whatsapp_service para aplicar Spacing (4s) y Auth Dinámica.
relay_payload = {
"to": payload.to_number,
"text": payload.message,
"provider": resolve_provider(payload.channel_source),
"channel_source": payload.channel_source,
"tenant_id": tenant_id,
"conversation_id": payload.conversation_id
}
await delivery_relay.post("/messages/relay", json=relay_payload)
# 3. Guardar en DB para auditoría
# ... persistencia ...
return {"status": "sent"}
4. Human Override (Intervención Humana)
Activar Chat Lock
const toggleHumanOverride = async (
chatId: string,
locked: boolean
) => {
await useApi({
method: 'POST',
url: `/admin/conversations/${chatId}/human-override`,
data: { locked }
});
};
Backend Implementation
@router.post("/conversations/{conversation_id}/human-override")
async def set_human_override(
conversation_id: str,
payload: HumanOverrideRequest,
session: AsyncSession = Depends(get_session)
):
# Actualizar flag
stmt = update(ChatConversation).where(
ChatConversation.id == conversation_id
).values(is_locked=payload.locked)
await session.execute(stmt)
await session.commit()
# El bot dejará de responder automáticamente
# hasta que is_locked = false
return {"locked": payload.locked}
### Detección Automática de Ecos (Chatwoot Dash)
Si un humano responde directamente desde la interfaz de Chatwoot, el `whatsapp_service` captura el evento `message_created` (outgoing) y lo marca como `is_echo = True`. Al llegar al Orchestrator, este activa el bloqueo de IA automáticamente para ese chat.
5. Templates HSM (Meta 24h Window)
Regla de Meta
- Ventana de 24h: Después de la última interacción del usuario, solo puedes responder con texto libre durante 24 horas
- Re-enganche: Pasadas 24h, debes usar plantillas HSM pre-aprobadas por Meta
UI Template Selector
interface Template {
id: string;
name: string;
language: string;
status: 'APPROVED' | 'PENDING' | 'REJECTED';
category: 'MARKETING' | 'UTILITY' | 'AUTHENTICATION';
components: TemplateComponent[];
}
const sendTemplate = async (
conversationId: string,
templateId: string,
parameters: string[]
) => {
await useApi({
method: 'POST',
url: '/admin/templates/send',
data: {
conversation_id: conversationId,
template_id: templateId,
parameters: parameters
}
});
};
Sincronizar Templates
# Sync con Meta para obtener status actualizado
@router.post("/templates/sync")
async def sync_templates(tenant_id: int):
# Obtener credenciales de Meta
waba_token = await get_tenant_credential(
tenant_id=tenant_id,
category="whatsapp_cloud"
)
# Llamar a Meta Graph API
response = requests.get(
f"https://graph.facebook.com/v18.0/{waba_id}/message_templates",
headers={"Authorization": f"Bearer {waba_token}"}
)
templates = response.json()['data']
# Actualizar DB local
for template in templates:
# Upsert en tabla templates
pass
return {"synced": len(templates)}
6. Multimedia (Attachments)
Renderizar Adjuntos
const renderAttachment = (attachment: Attachment) => {
switch (attachment.type) {
case 'image':
return <img src={attachment.url} alt="Attachment" />;
case 'video':
return <video src={attachment.url} controls />;
case 'audio':
return <audio src={attachment.url} controls />;
case 'document':
return <a href={attachment.url} download>{attachment.filename}</a>;
}
};
Backend Storage
# Attachments se guardan como JSONB en chat_messages.attachments
attachments = [
{
"type": "image",
"url": "https://cdn.whatsapp.net/...",
"mime_type": "image/jpeg"
}
]
msg = ChatMessage(
conversation_id=conv_id,
sender='user',
content='[Image]',
attachments=attachments # JSONB column
)
7. Indicadores Visuales (UI)
Estado Online
const isOnline = (lastInteraction: string): boolean => {
const diff = Date.now() - new Date(lastInteraction).getTime();
return diff < 5 * 60 * 1000; // < 5 minutos = online
};
Borde de Color por Canal
const getBorderColor = (channel: string) => {
switch (channel) {
case 'whatsapp': return 'border-green-500';
case 'instagram': return 'border-pink-500';
case 'facebook': return 'border-blue-500';
case 'web': return 'border-purple-500';
}
};
8. Traceability (Correlation ID)
Link con AI Logs
# Al crear mensaje del agente
correlation_id = str(uuid.uuid4())
msg = ChatMessage(
conversation_id=conv_id,
sender='agent',
content=response,
correlation_id=correlation_id
)
# En logs del agent_service
logger.info(
f"AI Response",
extra={
"correlation_id": correlation_id,
"reasoning": reasoning_steps,
"tools_used": tool_calls
}
)
Frontend Debugging
// Ver logs de razonamiento del agente
const viewAIReasoning = async (correlationId: string) => {
const logs = await useApi({
method: 'GET',
url: `/admin/logs/ai/${correlationId}`
});
// Mostrar en modal
};
9. Paginación y Scroll Infinito
Implementación
const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
// Detectar bottom
if (scrollHeight - scrollTop === clientHeight) {
if (!loading && hasMore) {
loadMoreChats();
}
}
};
const loadMoreChats = async () => {
const newChats = await useApi({
method: 'GET',
url: '/admin/chats/summary',
params: {
offset: contacts.length,
limit: 20
}
});
setContacts([...contacts, ...newChats]);
};
10. Troubleshooting
"El bot no responde"
# Checklist de diagnóstico
1. Verificar is_locked = false en chat_conversations
2. Verificar tenant_id del mensaje entrante coincide con agent.tenant_id
3. Verificar credenciales OpenAI válidas para el tenant
4. Revisar logs: docker logs orchestrator_service --tail 100
"Error sending message"
# Causas comunes:
- Falta channel_source en payload
- Token de Meta expirado
- 24h window expirada (usar template)
- Número no registrado en WABA
"Mensajes desordenados"
// SIEMPRE ordenar en frontend
messages.sort((a, b) =>
new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
);
11. Multi-Tenant Security
Filtrado Obligatorio
# Backend SIEMPRE debe filtrar por tenant
stmt = select(ChatConversation).where(
ChatConversation.tenant_id == tenant_id
)
# El usuario del tenant 1 NUNCA debe ver chats del tenant 2
12. Checklist de Features
Vista Chats.tsx
- Polling de conversaciones activo
- Loop de mensajes cuando chat seleccionado
- Envío de mensajes con channel_source correcto
- Toggle human override funcional
- Renderizado de multimedia (attachments)
- Paginación con scroll infinito
- Indicadores visuales (online, canal)
- Filtros (human_filter, channel)
Backend
- Routing multi-canal (WhatsApp/IG/FB)
- Human override persistence
- Template management
- Attachment storage (JSONB)
- Correlation ID logging
- Multi-tenant isolation
- Delta sync optimization
Tip: Para debugging en producción, usar correlation_id para trazar el flujo completo desde el mensaje del usuario → razonamiento del agente → respuesta final.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?