Skip to main content
Cuando el agente ejecuta una accion (service o action), el SDK renderiza automaticamente una tarjeta con el resultado. Con customCardRenderers puedes reemplazar las cards por defecto o agregar nuevas para tus propios intents.

Como Funciona

  1. El agente ejecuta una accion con un intent especifico (ej: buscar_producto)
  2. El SDK busca si existe un renderer custom para ese intent
  3. Si existe, renderiza tu componente. Si no, usa la card generica del SDK

Uso

import { PlazbotProvider, Chat } from 'plazbot/react'

const ProductCard = ({ action }) => {
  const data = action.result as {
    name: string
    price: number
    image: string
    stock: boolean
  }

  if (!data) return null

  return (
    <div style={{
      border: '1px solid #e5e7eb',
      borderRadius: 6,
      padding: 12,
      display: 'flex',
      gap: 12,
      alignItems: 'center',
    }}>
      {data.image && (
        <img src={data.image} alt={data.name}
          style={{ width: 56, height: 56, borderRadius: 4, objectFit: 'cover' }} />
      )}
      <div>
        <p style={{ fontWeight: 600 }}>{data.name}</p>
        <p style={{ color: '#6b7280', fontSize: 13 }}>
          ${data.price.toFixed(2)} {data.stock ? '- En stock' : '- Agotado'}
        </p>
      </div>
    </div>
  )
}

<PlazbotProvider sdk={sdk} agentId="ag_xxxx">
  <Chat
    customCardRenderers={{
      buscar_producto: ProductCard,
    }}
  />
</PlazbotProvider>

Props del Renderer

Cada componente custom recibe un unico prop action:
interface ActionProps {
  action: ActionExecuted
}

interface ActionExecuted {
  name?: string      // Nombre descriptivo de la accion
  intent?: string    // Identificador del intent
  result?: unknown   // Datos retornados por el servicio/accion
}

Ejemplo: Card de Cita

const AppointmentCard = ({ action }) => {
  const data = action.result as {
    date: string
    time: string
    doctor: string
    confirmed: boolean
  }

  if (!data) return null

  return (
    <div style={{
      border: '1px solid #e5e7eb',
      borderRadius: 6,
      padding: 12,
      background: data.confirmed ? '#f0fdf4' : '#fef2f2',
    }}>
      <p style={{ fontWeight: 600, marginBottom: 4 }}>
        {data.confirmed ? 'Cita confirmada' : 'Cita pendiente'}
      </p>
      <p style={{ fontSize: 13, color: '#374151' }}>
        {data.date} a las {data.time} con {data.doctor}
      </p>
    </div>
  )
}

Ejemplo: Card de Pedido

const OrderCard = ({ action }) => {
  const data = action.result as {
    orderId: string
    items: { name: string; qty: number }[]
    total: number
    status: string
  }

  if (!data) return null

  return (
    <div style={{ border: '1px solid #e5e7eb', borderRadius: 6, padding: 12 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
        <strong>Pedido #{data.orderId}</strong>
        <span style={{
          fontSize: 11,
          padding: '2px 8px',
          borderRadius: 4,
          background: data.status === 'confirmed' ? '#dcfce7' : '#fef9c3',
          color: data.status === 'confirmed' ? '#166534' : '#854d0e',
        }}>
          {data.status}
        </span>
      </div>
      {data.items.map((item, i) => (
        <p key={i} style={{ fontSize: 13, color: '#6b7280' }}>
          {item.qty}x {item.name}
        </p>
      ))}
      <p style={{ fontWeight: 600, marginTop: 8 }}>Total: ${data.total.toFixed(2)}</p>
    </div>
  )
}

Multiples Renderers

Puedes registrar tantos renderers como necesites. Cada uno se asocia al intent de un servicio o accion del agente:
<Chat
  customCardRenderers={{
    buscar_producto: ProductCard,
    agendar_cita: AppointmentCard,
    crear_pedido: OrderCard,
    consultar_saldo: BalanceCard,
  }}
/>

Cards por Defecto del SDK

Si no defines un renderer custom, el SDK usa sus cards internas:
TipoCardDescripcion
action.tagActionCardMuestra la accion ejecutada.
action.asignContactCardInformacion de asignacion.
action.event.*EventCardEventos de calendario.
action.stageActionCardCambio de etapa.
Service responseServiceResultCardResultado generico de servicio.
SourcesSourceCardFuentes de informacion (RAG).
FallbackGenericCardCard generica para datos no mapeados.

Callback de Acciones

Ademas de las cards, puedes escuchar cuando se ejecutan acciones:
<Chat
  customCardRenderers={{ ... }}
  onActionExecuted={(action) => {
    console.log('Intent:', action.intent)
    console.log('Result:', action.result)

    // Ejemplo: tracking analytics
    analytics.track('agent_action', {
      intent: action.intent,
      success: !!action.result,
    })
  }}
/>