> This page is for Inicio.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://signalcore.ai/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://signalcore.ai/docs/_mcp/server.

# Chat web

Dos formas, según dónde lo pongas:

|                                                  | Para                                   | Quién habla                                     |
| ------------------------------------------------ | -------------------------------------- | ----------------------------------------------- |
| **El widget** `<signalcore-chat>`                | Cualquier web, sin React: una etiqueta | Visitantes anónimos, con una clave publicable   |
| **Los componentes de React** de `@signalcore/ui` | Tu producto                            | Tus usuarios, con un token que crea tu servidor |

En los dos el cliente escribe o, si el agente tiene voz, habla con él en el mismo panel. No ve
los pasos internos del agente, y lo que necesita un sí lo decide tu negocio desde la app.

> **Note**
>
> El widget lo sirve SignalCore en `https://signalcore.ai/v1/widget.js` y se actualiza con cada
> versión. Para React, `@signalcore/ui` 1.0 está en beta.

Cada componente, en vivo y con sus props, está en [signalcore.ai/ui](https://signalcore.ai/ui):
pruébalos ahí con tu color y tus esquinas antes de ponerlos. Qué es cada uno, en
[Componentes](/guias/componentes).

## El widget

### Con el canal Web (sin código)

En la página del agente, **Canales → Conectar → Web**: di en qué webs irá y SignalCore te da una
línea para pegar antes de `</body>` en cada página:

```html
<script src="https://signalcore.ai/v1/widget.js" data-key="pk_…" async></script>
```

Su aspecto (color, letra, esquinas, tema, posición, tamaños y tu propio CSS) se cambia en el
panel del canal, con una vista previa en vivo en escritorio y móvil, o pidiéndoselo al builder.
Cada web lo lleva al cargar: no hay que volver a pegar nada. Las conversaciones salen en la
Bandeja con la marca Web.

### A mano

Necesitas una **clave publicable** (`pk_…`): sirve para un agente y solo desde las webs que
indiques. Ver [cómo crear claves](/guias/api#claves).

```html
<script src="https://signalcore.ai/v1/widget.js"></script>

<signalcore-chat
  base-url="https://signalcore.ai/v1"
  agent="agt_…"
  publishable-key="pk_…"
></signalcore-chat>
```

Aparece un botón redondo en la esquina que abre el chat (a pantalla completa en el móvil). El
visitante encuentra su conversación cuando vuelve.

| Atributo          |                                                               |
| ----------------- | ------------------------------------------------------------- |
| `base-url`        | La API, con `/v1`.                                            |
| `agent`           | El id del agente.                                             |
| `publishable-key` | La clave publicable. O `token`, para uno de tus usuarios.     |
| `locale`          | `es` o `en`. Si no, el idioma de la página.                   |
| `theme`           | `light` o `dark`. Si no, el de la página.                     |
| `mode`            | `inline` para ponerlo dentro de la página en vez de flotando. |
| `header`          | Muestra el nombre y el rol del agente arriba.                 |

### Que parezca tuyo

El widget toma la tipografía y el color de texto de tu página. El resto lo cambias con variables
CSS y partes:

```html
<style>
  signalcore-chat {
    --sc-accent: #0f766e;
    --sc-accent-fg: #fff;
    --sc-radius: 6px;
  }
  signalcore-chat::part(message-person) {
    background: #0f766e;
    color: #fff;
  }
</style>
```

## En tu producto, con React

Tu servidor crea un **token de persona** para el usuario que ha iniciado sesión (una hora, solo
los agentes que nombres), y la página lo pide cuando lo necesita.

**`Tu servidor (FastAPI)`**

```python title="Tu servidor (FastAPI)"
@app.get("/signalcore/token")
async def signalcore_token(user=Depends(current_user)):
    async with httpx.AsyncClient() as http:
        answer = await http.post(
            "https://signalcore.ai/v1/tokens",
            headers={"Authorization": f"Bearer {SIGNALCORE_KEY}"},
            json={"agents": ["agt_…"], "external_id": user.id, "name": user.name},
        )
    answer.raise_for_status()
    return answer.json()  # {"token": "…", "expires_at": "…"}
```

```bash
npm install @signalcore/ui@1.0.0-beta.0 react react-dom
```

**`Tu página`**

```tsx title="Tu página"
import { AgentSpace, SPACE_MESSAGES_ES, createClient } from "@signalcore/ui";
import "@signalcore/ui/styles.css";

const client = createClient({
  baseUrl: "https://signalcore.ai/v1",
  getToken: async () => (await (await fetch("/signalcore/token")).json()).token,
});

export function Ayuda() {
  return <AgentSpace client={client} agentId="agt_…" messages={SPACE_MESSAGES_ES} />;
}
```

`AgentSpace` es el chat y, si el agente tiene voz, la llamada. Si solo quieres el chat de una
conversación, usa `AgentChat`. React 19.2 o posterior.

## Cada usuario es un contacto

Cada usuario de tu producto que habla con el agente con su token es un **contacto** de tu
organización, como quien escribe por WhatsApp: se crea en su primera conversación, por el
`external_id` que pones en el token (con su `name` y su `email`). Así lo que el agente recuerda de
él y las tareas que le programa son solo suyas, y nunca se le cuentan a otro usuario.

* **Lo que recuerda**: lo que el agente aprende hablando con un usuario lo tiene en cuenta solo con
  él. Lo ves y lo borras en su ficha de contacto, en SignalCore.
* **Sus tareas**: si el usuario le pide algo para más adelante («recuérdame revisar el pedido el
  lunes», «escríbeme cada mes»), el agente programa una tarea y, a su hora, le escribe en su
  conversación. `AgentSpace` le muestra «Tienes 1 tarea programada» encima del chat: al pulsarlo
  ve **Tus tareas**, con cada vez que se hizo, y puede pausarlas o quitarlas.

Desde tu servidor, con tu clave, o desde la página, con el token del usuario (que solo ve las
suyas):

```bash
curl https://signalcore.ai/v1/agents/agt_…/tasks -H "Authorization: Bearer $TOKEN"
curl -X PATCH https://signalcore.ai/v1/agents/agt_…/tasks/tsk_… -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"on": false}'
curl -X DELETE https://signalcore.ai/v1/agents/agt_…/tasks/tsk_… -H "Authorization: Bearer $TOKEN"
```

Si dibujas tu propia pantalla, `client.tasks.list(agentId)` te da lo mismo, y `AgentTasks` es la
lista que usa `AgentSpace`. Un visitante del widget, sin token, no es nadie conocido hasta que da
su email en un formulario.

## Tus propias herramientas en la página

El agente puede llamar a una función de tu página, por ejemplo abrir una ficha. Declárala en el
agente con `PUT /v1/agents/{id}/tools/{name}` y `mode: "client"`, y respóndela con `onTool`:

```tsx
<AgentSpace
  client={client}
  agentId="agt_…"
  onTool={async ({ name, input }) => {
    if (name === "abrir_ficha") {
      router.push(`/fichas/${String(input.ficha)}`);
      return { abierta: true };
    }
    throw new Error(`Esta página no tiene ${name}`);
  }}
/>
```