
Hasta donde yo sé, Streamlit es la forma más rápida de poner en marcha una aplicación web personalizable. Si quieres crear un agente de IA y desplegarlo en tu propio front-end, no se me ocurre una opción mejor.
La única pega es la biblioteca de elementos de chat. Están específicamente adaptados a la API de OpenAIy al cliente Python.
Lo cual es estupendo: un par de líneas de código para interactuar con una de las tecnologías más prestigiosas del momento es... estupendo.
Pero no lo es todo.
¿Y si quieres tener más control sobre tu bot? Por ejemplo, es posible que desee un flujo de trabajo de varios pasos, o la generación de recuperación aumentada (RAG). Estas capas añadidas de funcionalidad suelen implicar la unión de bibliotecas con todo tipo de dependencias.
¿O no?
En este tutorial, voy a construir un cliente de chatbot alojado en Streamlit. Te mostraré una interfaz para chatbots de iteración rápida y altamente personalizables. Luego, aprenderás cómo integrar el chatbot usando un cliente Python personalizado OpenAI.
Si estás creando prototipos, las dependencias y los tecnicismos no deberían frenarte.
Y, en aras de una rápida creación de prototipos, si quieres saltarte el tutorial y empezar a juguetear, el código está en GitHub.
Bombas de distancia 💣
Paso 1: Crea la lógica del chatbot
Ya sea para la automatización del flujo de trabajo o para un chatbot de reserva de citas, el mundo es realmente su ostra aquí.
Si buscas inspiración, te animo a que explores la gran variedad de casos de uso de los chatbots de GenAI. En aras de la simplicidad, volveré con mi, espero que ya famosa, sumiller Winona.
Nuestro sofisticado y útil pequeño bot se puede conseguir en unos pocos pasos. Seré breve, pero hay muchos tutoriales extensos y ultra útiles que puedes consultar.
1. Déle instrucciones
En el estudio, navegaremos a Inicio en la barra lateral izquierda.

Debería ver la sección Instrucciones en primer plano. Haga clic en ella para añadir o modificar las instrucciones en texto sin formato.

Esto le da a nuestro bot directivas, personalidad y guardarraíles. Utilizando un lenguaje sencillo, puedes dirigir tu bot con bastante eficacia hacia el comportamiento deseado. Haz que suene más humano, y
2. Crea el flujo
Aquí es donde viven las tuercas y los tornillos de la personalidad del bot: acceso a información específica, pasos rígidos, ejecución de código, etc.
No subestimes el poder de la simplicidad. Un único nodo autónomo rivaliza en funcionalidad con los agentes de razonamiento. Yo tengo uno conectado a mi Base de Conocimientos (KB).

3. Añadir la base de conocimientos
Si las instrucciones se refieren a las vibraciones, la base de conocimientos se refiere a los hechos. En mi caso, los hechos en cuestión son los vinos del conjunto de datos Wine Reviews, una lista de vinos, descripciones y precios. Lo trataré como un inventario de vinos de facto para que nuestro bot lo convierta en sommelier.
Haré clic en Tablas en el panel izquierdo y pulsaré Nueva tabla en la parte superior izquierda de la página, y le daré un nombre descriptivo.

Haz clic en la elipsis vertical (⋮) de la parte superior derecha y pulsa Importar.

Arrastra tu .csv al modal que aparece y sigue los pasos que aparecen en pantalla.
Para que su bot pueda acceder a la tabla, vaya a Bases de conocimientos en la barra lateral izquierda.

Haz clic en el pequeño icono verde de tabla y selecciona la fuente correspondiente. Haz clic en Añadir tablas.

Asegúrate de que tu flujo tiene acceso a la Base de conocimientos y listo.

Paso 2: Añadir la integración de la API de Chat
El punto de contacto entre el bot y nuestro cliente local es la API de Chat . Para añadirlo a nuestro bot, me desplazaré hasta Canales de comunicación y pulsaré . .. Más.

Echa un vistazo a las integraciones si quieres. Buscamos Chat. Tuve que desplazarme un poco para encontrarlo.

Haga clic en la integración y pulse Instalar integración en el modal que aparece.

Una vez instalado, verás el ID de la API deChat al final de la URL webhook . Lo necesitarás para más adelante.
Paso 3: Escribir el cliente Python
La API de Chat expone una serie de puntos finales para realizar operaciones con usuarios, conversaciones y mensajes. Como prometí, voy a envolver estos en un cliente Python que puede reemplazar a un cliente OpenAI .
1. Añada sus credenciales
class BotpressClient:
def __init__(self, api_id=None, user_key=None):
self.api_id = api_id or os.getenv("CHAT_API_ID")
self.user_key = user_key or os.getenv("USER_KEY")
self.base_url = f"{BASE_URI}/{self.api_id}"
self.headers = {
**HEADERS,
"x-user-key": self.user_key,
}
Eres libre de añadir tu ID de la API de Chat a un archivo .env - ayuda con la depuración, pero no es estrictamente necesario. Nos ocuparemos del ID de la API y de la clave de usuario cuando creemos la aplicación Streamlit.
Sigo BASE_URI
y TITULARES
en un constantes.py
para el desorden.
# constants.py
BASE_URI = "https://chat.botpress.cloud"
HEADERS = {
"accept": "application/json",
"Content-Type": "application/json",
}
2. Crear los métodos de solicitud
def _request(self, method, path, json=None):
url = f"{self.base_url}{path}"
try:
response = requests.request(method, url, headers=self.headers, json=json)
response.raise_for_status()
return response.json()
except requests.HTTPError:
return response.status_code, response.text
# --- Core API Methods ---
def get_user(self):
return self._request("GET", "/users/me")
def create_user(self, name, id):
user_data = {"name": name, "id": id}
return self._request("POST", "/users", json=user_data)
def set_user_key(self, key):
self.user_key = key
self.headers["x-user-key"] = key
def create_and_set_user(self, name, id):
new_user = self.create_user(name, id)
self.set_user_key(new_user["key"])
def create_conversation(self):
return self._request("POST", "/conversations", json={"body": {}})
def list_conversations(self):
return self._request("GET", "/conversations")
def get_conversation(self, conversation_id):
return self._request("GET", f"/conversations/{conversation_id}")
def create_message(self, message, conversation_id):
payload = {
"payload": {"type": "text", "text": message},
"conversationId": conversation_id,
}
return self._request("POST", "/messages", json=payload)
def list_messages(self, conversation_id):
return self._request("GET", f"/conversations/{conversation_id}/messages")
Como se ha mencionado, casi todos estos mapas a un punto final en la API. Sólo estoy envolviéndolos en una clase.
3. Crear un receptor SSE
Este es el alcance de la piratería. Para escuchar las actualizaciones de la conversación y el bucle en un front-end Streamlit, el cliente necesita un método para escuchar y producir eventos enviados por el servidor de nuestro bot.
def listen_conversation(self, conversation_id):
url = f"{self.base_url}/conversations/{conversation_id}/listen"
for event in sseclient.SSEClient(url, headers=self.headers):
print(event.data)
if event.data == "ping":
continue
data = json.loads(event.data)["data"]
yield {"id": data["id"], "text": data["payload"]["text"]}
Esta función toma el conversation_id (al que se accederá mediante programación dentro de la aplicación) y devuelve los datos entrantes a medida que se producen.
Paso 4: Crear la aplicación Streamlit
Con nuestros patos en fila, es hora de construir el chatbot. Ten en cuenta que estoy siguiendo la guía de Streamlit para crear una aplicación de chat LLM ,con algunas características añadidas.
1. Adaptar el código fuente
En teoría, puedes conseguir que la aplicación funcione con cambios mínimos en la plantilla del ejemplo de Streamlit.
# app.py
from client import BotpressClient
import streamlit as st
from constants import CONVERSATION_ID
st.title("Botpress Front-end for Streamlit")
client = BotpressClient(
api_id=st.secrets["CHAT_API_ID"], user_key=st.secrets["USER_KEY"]
)
if "messages" not in st.session_state:
messages = client.list_messages(CONVERSATION_ID)
next_token = messages["meta"]["nextToken"]
st.session_state.messages = messages["messages"][::-1]
for message in st.session_state.messages:
with st.chat_message(message["userId"]):
st.markdown(message["payload"]["text"])
if prompt := st.chat_input("*wine*-d it up"):
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
client.create_message(prompt, conversation_id=CONVERSATION_ID)
with st.chat_message("assistant"):
response_box = st.empty()
last_rendered = ""
for message in client.listen_conversation(CONVERSATION_ID):
message_id = message["id"]
message_text = message["text"]
if message_id != last_rendered:
last_rendered = message_id
response_box.markdown(message_text)
st.session_state.messages.append(
{"role": "assistant", "content": message_text}
)
Estamos leyendo variables secretas aquí. Así que crea un archivo .streamlit/secrets.toml y coloca tus variables dentro:
CHAT_API_ID = "YOUR_API_ID
CLAVE_USUARIO = "TU_CLAVE_USUARIO
El trabajo pesado se está realizando en:
with st.chat_message("assistant"):
response_box = st.empty()
last_rendered = ""
for message in client.listen_conversation(CONVERSATION_ID):
message_id = message["id"]
message_text = message["text"]
if message_id != last_rendered:
last_rendered = message_id
response_box.markdown(message_text)
st.session_state.messages.append(
{"role": "assistant", "content": message_text}
)
donde el cliente se engancha a los elementos del chat para entregar y recibir mensajes.
Esto funciona, pero no es lo ideal por varias razones:
- Tienes que haber creado una nueva conversación por separado.
- Los mensajes antiguos tendrán un formato diferente a los nuevos, porque no tienen la designación de rol (usuario o asistente).
- No puedes alternar conversaciones.
2. Crear conversaciones dinámicamente
Partiendo de cero, crearé automáticamente una nueva conversación o abriré la más reciente:
# app.py
from client import BotpressClient
import streamlit as st
st.title("Botpress Front-end for Streamlit")
client = BotpressClient(
api_id=st.secrets["CHAT_API_ID"], user_key=st.secrets["users"][0]["key"]
)
# user info
user = client.get_user()
user_id = user["user"]["id"]
conversations = client.list_conversations()["conversations"]
conversation_ids = [conv["id"] for conv in conversations]
# conversation
def create_conversation():
res = client.create_conversation()
print(f"Created new conversation: {res}")
conversation_id = res["conversation"]["id"]
st.session_state.active_conversation = conversation_id
st.session_state.messages = []
st.rerun()
if not conversations:
create_conversation()
if "active_conversation" not in st.session_state:
st.session_state["active_conversation"] = conversations[0]["id"]
Ten en cuenta que he modificado las claves secretas para poder almacenar múltiples usuarios. Usted querrá modificar su .streamlit/secretos.toml
para reflejarlo:
[[usuarios]]
clave = "tu_clave_usuario"
Puedes repetir este bloque tanto como quieras, almacenando los usuarios como un array de tablas.
3. Permitir a los usuarios crear y alternar entre conversaciones
Como dice el título, esto crea un desplegable en la parte superior con un botón que te permite elegir tu conversación.
col1, col2 = st.columns([5, 1])
with col1:
conversation_id = st.selectbox(
"Select Conversation",
options=[conv["id"] for conv in conversations],
index=conversation_ids.index(st.session_state.active_conversation),
)
with col2:
st.markdown("<div style='height: 1.9em'></div>", unsafe_allow_html=True)
if st.button("➕"):
create_conversation()
selected_conversation = client.get_conversation(conversation_id)
4. Asignar la función correcta a los mensajes anteriores
Resolveremos el problema de formato anterior asignando el rol de usuario o asistente a cada uno de los mensajes anteriores:
if (
"messages" not in st.session_state
or st.session_state.get("active_conversation") != conversation_id
):
st.session_state.active_conversation = conversation_id
st.session_state.messages = []
messages = client.list_messages(conversation_id)
next_token = messages["meta"].get("nextToken")
for message in messages["messages"][::-1]:
role = "user" if message["userId"] == user_id else "assistant"
text = message["payload"]["text"]
st.session_state.messages.append({"role": role, "content": text})
Esto ajusta nuestro código a la estructura que Streamlit espera.
5. Añadir la lógica de mensajería
Es más o menos lo mismo que antes, adaptado a la nueva estructura.
# display chat history
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
if prompt := st.chat_input("*wine*-d it up"):
st.session_state.messages.append({"role": "user", "content": prompt})
client.create_message(prompt, conversation_id=conversation_id)
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
stream = client.listen_conversation(conversation_id=conversation_id)
response = st.write_stream(stream)
st.session_state.messages.append({"role": "assistant", "content": response})
5. Crear un usuario
La lógica está lista, pero tendrás que crear un usuario para ejecutar la aplicación. Elegí añadir esto por separado para simular la experiencia de darse de alta en un servicio. Afortunadamente para ti, también escribí un script:
# create_user.py
import argparse
from pathlib import Path
from client import *
from constants import *
secrets_path = Path(".streamlit") / "secrets.toml"
template = """[[users]]
key="{}"
"""
client = BotpressClient()
def create_user(name, id, add_to_secrets=True):
res = client.create_user(name, id)
if not add_to_secrets:
return res
secrets_path.touch(exist_ok=True)
with open(secrets_path, "a") as f:
f.write(template.format(res["user"]["id"], res["key"]))
return res
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Create a Botpress user and optionally store secrets."
)
parser.add_argument("--name", required=True, help="Display name of the user.")
parser.add_argument(
"--id", required=True, help="User ID. If omitted, one is generated by the API."
)
parser.add_argument("--chat_api_id", help="ID for the Botpress Chat API integration. Taken from `.env` file if not provided.")
parser.add_argument(
"--no-secrets",
action="store_true",
help="Do not append to .streamlit/secrets.toml.",
)
args = parser.parse_args()
print(f"Creating user: {args.name} (ID: {args.id or 'auto-generated'})")
result = create_user(name=args.name, id=args.id, add_to_secrets=not args.no_secrets)
print("✅ User created:")
print(result)
Siempre que disponga de su ID de API de Chat , puede ejecutarlo:
python create_user.py -name TU_NOMBRE -id SOME_USER_ID -chat_api_id TU_CHAT_API_ID
Esto se ocupará de crear el usuario y añadirlo a su archivo de secretos.
Paso 5: Ejecutar la aplicación
Con tu lógica construida y tu usuario creado, es hora de darle una vuelta a esta aplicación. Instala las dependencias y ejecútala:
streamlit run app.py
Y así de fácil, verás a nuestro bot en todo su esplendor.

Ejecute hoy mismo un chatbot de Streamlit
Si estás creando prototipos con Streamlit, sabes que la personalización no debe ir en detrimento de la comodidad. Los chatbots están ahí para resolver problemas, no para crearlos.
Botpress viene con un constructor visual de arrastrar y soltar, docenas de integraciones oficiales y puntos finales de API accesibles. De este modo, puedes crear, iterar y desplegar en muchos canales de comunicación.
Empieza a construir hoy mismo. Es gratis.