Interfaz visual Canvas y A2UI
Qué podrás hacer al completar esta lección
Al completar esta lección, podrás:
- Configurar Canvas Host e implementar interfaces personalizadas de HTML/CSS/JS
- Usar la herramienta
canvaspara controlar Canvas en nodos (mostrar, ocultar, navegar, ejecutar JS) - Dominar el protocolo A2UI para que la IA envíe actualizaciones de UI dinámicamente
- Capturar capturas de pantalla de Canvas para el contexto de la IA
- Entender los mecanismos de seguridad y control de acceso de Canvas
Tu situación actual
Tienes un asistente de IA, pero solo puede interactuar contigo a través de texto. Quieres:
- Que la IA muestre interfaces visuales, como tablas, gráficos, formularios
- Ver interfaces dinámicas generadas por Agentes en dispositivos móviles
- Crear una experiencia interactiva tipo "aplicación" sin desarrollar independientemente
Cuándo usar esta técnica
Canvas + A2UI es adecuado para estos escenarios:
| Escenario | Ejemplo |
|---|---|
| Visualización de datos | Mostrar gráficos estadísticos, barras de progreso, líneas de tiempo |
| Formularios interactivos | Pedir al usuario que confirme acciones, seleccione opciones |
| Paneles de estado | Mostrar el progreso de tareas en tiempo real, estado del sistema |
| Juegos y entretenimiento | Mini juegos simples, demostraciones interactivas |
A2UI vs. HTML estático
- A2UI(Agent-to-UI): La IA genera y actualiza la UI dinámicamente, adecuado para datos en tiempo real
- HTML estático: Interfaces predefinidas, adecuado para diseños fijos e interacciones complejas
🎒 Preparativos
Antes de comenzar, asegúrate de haber completado:
- [ ] Gateway iniciado: Canvas Host se inicia automáticamente con Gateway por defecto (puerto 18793)
- [ ] Nodos emparejados: Nodos macOS/iOS/Android conectados a Gateway
- [ ] Nodos compatibles con Canvas: Confirma que el nodo tiene capacidad
canvas(clawdbot nodes list)
Conocimientos previos
Este tutorial asume que ya conoces:
Conceptos clave
El sistema Canvas incluye tres componentes principales:
┌─────────────────┐
│ Canvas Host │ ────▶ Servidor HTTP (puerto 18793)
│ (Gateway) │ └── Sirve archivos ~/clawd/canvas/
└─────────────────┘
│
│ Comunicación WebSocket
│
┌─────────────────┐
│ Node App │ ────▶ WKWebView renderiza Canvas
│ (iOS/Android) │ └── Recibe envíos vía A2UI
└─────────────────┘
│
│ Eventos userAction
│
┌─────────────────┐
│ AI Agent │ ────▶ Llamadas a herramienta canvas
│ (pi-mono) │ └── Envía actualizaciones A2UI
└─────────────────┘Conceptos clave:
Canvas Host(lado Gateway)
- Proporciona servicio de archivos estáticos:
http://<gateway-host>:18793/__clawdbot__/canvas/ - Aloja host A2UI:
http://<gateway-host>:18793/__clawdbot__/a2ui/ - Soporta recarga en caliente: actualización automática después de modificar archivos
- Proporciona servicio de archivos estáticos:
Canvas Panel(lado nodo)
- Nodos macOS/iOS/Android incrustan WKWebView
- Conectan a Gateway vía WebSocket (recarga en tiempo real, comunicación A2UI)
- Soportan
evalpara ejecutar JS,snapshotpara capturar pantalla
Protocolo A2UI(v0.8)
- El Agente envía actualizaciones de UI vía WebSocket
- Soporta:
beginRendering,surfaceUpdate,dataModelUpdate,deleteSurface
Sigue los pasos
Paso 1: Verificar el estado de Canvas Host
Por qué Asegura que Canvas Host esté ejecutándose para que los nodos puedan cargar contenido Canvas.
# Verificar si el puerto 18793 está en escucha
lsof -i :18793Deberías ver:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 12345 user 16u IPv6 0x1234 0t0 TCP *:18793 (LISTEN)Rutas de configuración
- Directorio raíz Canvas:
~/clawd/canvas/(modificable porcanvasHost.root) - Puerto:
18793=gateway.port + 4(modificable porcanvasHost.port) - Recarga en caliente: Habilitado por defecto(deshabilitable por
canvasHost.liveReload: false)
Paso 2: Crear la primera página Canvas
Por qué Crear una interfaz HTML personalizada para mostrar tu contenido en el nodo.
# Crear directorio raíz Canvas (si no existe)
mkdir -p ~/clawd/canvas
# Crear archivo HTML simple
cat > ~/clawd/canvas/hello.html <<'EOF'
<!doctype html>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hello Canvas</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
padding: 20px;
background: #000;
color: #fff;
text-align: center;
}
h1 { color: #24e08a; }
</style>
<h1>🎉 Hello from Canvas!</h1>
<p>Esta es tu primera página Canvas.</p>
<button onclick="alert('¡Botón clickeado!')">Haz clic aquí</button>
EOFDeberías ver:
Archivo creado: ~/clawd/canvas/hello.htmlPaso 3: Mostrar Canvas en el nodo
Por qué Hacer que el nodo cargue y muestre la página que acabas de crear.
Primero encuentra tu ID de nodo:
clawdbot nodes listDeberías ver:
ID Name Type Capabilities
──────────────────────────────────────────────────────────────────────────
abc123-def456-ghi789 iOS Phone canvas, camera, screen
jkl012-mno345-pqr678 Android Tab canvas, cameraLuego muestra el Canvas (usando el nodo iOS como ejemplo):
# Método 1: Vía comando CLI
clawdbot nodes canvas present --node abc123-def456-ghi789 --target http://127.0.0.1:18793/__clawdbot__/canvas/hello.htmlDeberías ver:
- Un panel sin bordes emerge en el dispositivo iOS mostrando tu contenido HTML
- El panel aparece cerca de la barra de menús o posición del mouse
- El contenido está centrado con un título verde y un botón
Ejemplo de llamada de IA:
IA: He abierto un panel Canvas en tu dispositivo iOS mostrando la página de bienvenida.Formato de URL Canvas
- Archivo local:
http://<gateway-host>:18793/__clawdbot__/canvas/hello.html - URL externa:
https://example.com(requiere permisos de red del nodo) - Volver a predeterminado:
/o cadena vacía, muestra la página de andamiaje integrada
Paso 4: Usar A2UI para enviar UI dinámica
Por qué La IA puede enviar actualizaciones de UI directamente a Canvas sin modificar archivos, adecuado para datos en tiempo real e interacción.
Método A: Envío rápido de texto
clawdbot nodes canvas a2ui push --node abc123-def456-ghi789 --text "Hello from A2UI"Deberías ver:
- Canvas muestra interfaz A2UI azul
- Texto centrado mostrando:
Hello from A2UI
Método B: Envío completo JSONL
Crea archivo de definición A2UI:
cat > /tmp/a2ui-demo.jsonl <<'EOF'
{"surfaceUpdate":{"surfaceId":"main","components":[{"id":"root","component":{"Column":{"children":{"explicitList":["title","status","button"]}}}},{"id":"title","component":{"Text":{"text":{"literalString":"Demo A2UI"},"usageHint":"h1"}}},{"id":"status","component":{"Text":{"text":{"literalString":"Estado del sistema: Ejecutando"},"usageHint":"body"}}},{"id":"button","component":{"Button":{"label":{"literalString":"Botón de prueba"},"onClick":{"action":{"name":"testAction","sourceComponentId":"demo.test"}}}}}]}
{"beginRendering":{"surfaceId":"main","root":"root"}}
EOFEnvía A2UI:
clawdbot nodes canvas a2ui push --node abc123-def456-ghi789 --jsonl /tmp/a2ui-demo.jsonlDeberías ver:
┌────────────────────────────┐
│ Demo A2UI │
│ │
│ Estado del sistema: Ejecutando │
│ │
│ [ Botón de prueba ] │
└────────────────────────────┘Explicación del formato JSONL A2UI
JSONL (JSON Lines) contiene un objeto JSON por línea, adecuado para actualizaciones en streaming:
{"surfaceUpdate":{...}} // Actualizar componentes de superficie
{"beginRendering":{...}} // Iniciar renderizado
{"dataModelUpdate":{...}} // Actualizar modelo de datos
{"deleteSurface":{...}} // Eliminar superficiePaso 5: Ejecutar JavaScript de Canvas
Por qué Ejecutar JS personalizado en Canvas, como modificar DOM, leer estado.
clawdbot nodes canvas eval --node abc123-def456-ghi789 --js "document.title"Deberías ver:
"Hello from Canvas"Ejemplos de ejecución JS
- Leer elemento:
document.querySelector('h1').textContent - Modificar estilo:
document.body.style.background = '#333' - Calcular valor:
innerWidth + 'x' + innerHeight - Ejecutar cierre:
(() => { ... })()
Paso 6: Capturar captura de pantalla de Canvas
Por qué Permitir que la IA vea el estado actual de Canvas para comprensión de contexto.
# Formato por defecto (JPEG)
clawdbot nodes canvas snapshot --node abc123-def456-ghi789
# Formato PNG + límite de ancho máximo
clawdbot nodes canvas snapshot --node abc123-def456-ghi789 --format png --max-width 1200
# JPEG de alta calidad
clawdbot nodes canvas snapshot --node abc123-def456-ghi789 --format jpg --quality 0.9Deberías ver:
Canvas snapshot saved to: /var/folders/.../canvas-snapshot.jpgLa ruta del archivo se genera automáticamente por el sistema, usualmente en el directorio temporal.
Paso 7: Ocultar Canvas
Por qué Cerrar el panel Canvas para liberar espacio en pantalla.
clawdbot nodes canvas hide --node abc123-def456-ghi789Deberías ver:
- El panel Canvas en el dispositivo iOS desaparece
- El estado del nodo se recupera (si estaba ocupado anteriormente)
Punto de control ✅
Verificar que las funciones de Canvas funcionen correctamente:
| Elemento de verificación | Método de verificación |
|---|---|
| Canvas Host ejecutándose | lsof -i :18793 tiene salida |
| Capacidad de nodo Canvas | clawdbot nodes list muestra canvas |
| Página cargada con éxito | El nodo muestra contenido HTML |
| Envío A2UI exitoso | Canvas muestra interfaz A2UI azul |
| Ejecución JS devuelve resultado | El comando eval devuelve valor |
| Captura de pantalla generada | El directorio temporal tiene archivo .jpg o .png |
Advertencias
Limitaciones primer plano/fondo
- Nodos iOS/Android: Los comandos
canvas.*ycamera.*deben ejecutarse en primer plano - Las llamadas en segundo plano devolverán:
NODE_BACKGROUND_UNAVAILABLE - Solución: Despertar el dispositivo al primer plano
Precauciones de seguridad
- Protección contra recorrido de directorio: Las URL de Canvas prohíben
..para acceder a directorios superiores - Scheme personalizado:
clawdbot-canvas://limitado solo a uso interno del nodo - Restricciones HTTPS: Las URL HTTPS externas requieren permisos de red del nodo
- Acceso a archivos: Canvas Host solo permite acceder a archivos bajo
canvasHost.root
Consejos de depuración
- Ver registros de Gateway:
clawdbot gateway logs - Ver registros de nodo: iOS Configuración → Debug Logs, Registros dentro de la aplicación Android
- Probar URL: Acceda directamente en el navegador a
http://<gateway-host>:18793/__clawdbot__/canvas/
Resumen de la lección
En esta lección aprendiste:
- Arquitectura Canvas: Entender la relación entre Canvas Host, Node App y protocolo A2UI
- Configurar Canvas Host: Ajustar directorio raíz, puerto y configuración de recarga en caliente
- Crear páginas personalizadas: Escribir HTML/CSS/JS e implementar en nodos
- Usar A2UI: Enviar actualizaciones de UI dinámica vía JSONL
- Ejecutar JavaScript: Ejecutar código en Canvas, leer y modificar estado
- Capturar capturas de pantalla: Permitir que la IA vea el estado actual de Canvas
Puntos clave:
- Canvas Host se inicia automáticamente con Gateway, no requiere configuración adicional
- A2UI es adecuado para datos en tiempo real, HTML estático para interacciones complejas
- Los nodos deben estar en primer plano para ejecutar operaciones Canvas
- Usar
canvas snapshotpara pasar el estado de UI a la IA
Próxima lección
En la próxima lección aprenderemos Despertar por voz y texto a voz.
Aprenderás:
- Configurar palabras clave de despertar Voice Wake
- Usar Talk Mode para conversaciones de voz continuas
- Integrar múltiples proveedores TTS (Edge, Deepgram, ElevenLabs)
Apéndice: Referencia de código fuente
Haz clic para ver la ubicación del código fuente
Fecha de actualización: 2026-01-27
| Función | Ruta de archivo | Número de línea |
|---|---|---|
| Servidor Canvas Host | src/canvas-host/server.ts | 372-441 |
| Procesamiento de protocolo A2UI | src/canvas-host/a2ui.ts | 150-203 |
| Definición de herramienta Canvas | src/agents/tools/canvas-tool.ts | 52-179 |
| Constantes de ruta Canvas | src/canvas-host/a2ui.ts | 8-10 |
Constantes clave:
A2UI_PATH = "/__clawdbot__/a2ui": Ruta del host A2UICANVAS_HOST_PATH = "/__clawdbot__/canvas": Ruta de archivos CanvasCANVAS_WS_PATH = "/__clawdbot__/ws": Ruta de recarga en caliente WebSocket
Funciones clave:
createCanvasHost(): Iniciar servidor HTTP Canvas (puerto 18793)injectCanvasLiveReload(): Inyectar script de recarga en caliente WebSocket en HTMLhandleA2uiHttpRequest(): Manejar solicitudes de recursos A2UIcreateCanvasTool(): Registrar herramientacanvas(present/hide/navigate/eval/snapshot/a2ui_push/a2ui_reset)
Acciones Canvas compatibles:
present: Mostrar Canvas (URL, posición, tamaño opcionales)hide: Ocultar Canvasnavigate: Navegar a URL (ruta local/HTTP/file://)eval: Ejecutar JavaScriptsnapshot: Capturar captura de pantalla (PNG/JPEG, maxWidth/quality opcionales)a2ui_push: Enviar actualizaciones A2UI (JSONL o texto)a2ui_reset: Restablecer estado A2UI
Schema de configuración:
canvasHost.root: Directorio raíz Canvas (predeterminado~/clawd/canvas)canvasHost.port: Puerto HTTP (predeterminado 18793)canvasHost.liveReload: Habilitar recarga en caliente (predeterminado true)canvasHost.enabled: Habilitar Canvas Host (predeterminado true)
Mensajes compatibles con A2UI v0.8:
beginRendering: Iniciar renderizado de superficie específicasurfaceUpdate: Actualizar componentes de superficie (Column, Text, Button, etc.)dataModelUpdate: Actualizar modelo de datosdeleteSurface: Eliminar superficie específica