Swiss AI Hub Bot SDK: connect users to AI agents via MS Teams, Slack, and web chat.
Project description
swiss-ai-hub-bot
The bot integration SDK for Swiss AI Hub — bring your agents to users in MS Teams, Slack, and web chat.
What is Swiss AI Hub?
Swiss AI Hub is an open-source, self-hosted AI platform for enterprises. One
docker compose up starts ~30 integrated containers — LLM gateway (LiteLLM), vector search (Milvus), data pipelines
(Dagster), SSO (Keycloak), observability (Langfuse), a chat UI (Open-WebUI), and more. You build agents with the Python
SDK; this package puts them in the chat tools your users already live in.
What is this package?
swiss-ai-hub-bot is a Bot Framework application (built on the microsoft-agents-*
SDK) that connects collaboration channels to Swiss AI Hub. It receives messages from MS Teams, Slack, and web chat,
handles the channel-specific quirks (threads, mentions, file attachments, markdown, typing indicators, streaming), and
routes each conversation to its destination:
AgentChatBot— routes a conversation to a Swiss AI Hub agent over NATS, streaming the agent's response back into the channel.OpenaiChatBot— talks directly to an LLM through the platform's LiteLLM gateway (no agent), for simple chat-with-a-model endpoints.- Bot-in-the-loop (BITL) — when an agent needs a human, the bot delivers the question to a Slack/Teams channel and feeds the human's reply back into the agent's workflow.
It builds on swiss-ai-hub-core (installed automatically) and pairs with
swiss-ai-hub-agent (the agents it surfaces).
Should you use this package?
Probably not directly — most deployments use the pre-built Docker image, which ships the bot ready to go:
# docker-compose.yml
services:
bot:
image: ghcr.io/bbvch-ai/aihub-core/bot:latest
Use this PyPI package when you want to compose a custom bot — mount only the handlers you need, add your own channel handler, or change how conversations are routed. It's an SDK for building a custom chat front-end on top of Swiss AI Hub, not just a standalone server.
Installation
pip install swiss-ai-hub-bot
# or
uv add swiss-ai-hub-bot
Requires Python 3.13.
Quick start
A bot is a BotRunner with the channel controllers you mount — the same shape as the production entry point:
# app.py
from swiss_ai_hub.core.auth.dependencies.keycloak_auth_handler import KeycloakAuthHandler
from swiss_ai_hub.core.routes import HealthController
from swiss_ai_hub.bot.routes import AgentChatController, OpenaiChatController, BotInTheLoopController
from swiss_ai_hub.bot.runners import BotRunner
runner = BotRunner()
auth = KeycloakAuthHandler() # a fail-closed safety net; channel authenticity is verified per-endpoint (see below)
runner.mount(
HealthController(auth=auth).get_health(),
AgentChatController(auth=auth).completions_json().completions_stream(), # chat → agent (NATS)
OpenaiChatController(auth=auth).json_chat_completion().stream_chat_completion(), # chat → LLM (direct)
BotInTheLoopController(auth=auth).bot_in_the_loop_response(), # human replies → agent
)
app = runner.create_app()
Serve it like any ASGI app (the platform ships it on port 8001):
uvicorn app:app --host 0.0.0.0 --port 8001
This exposes the Bot Framework messaging endpoints — /api/v1/agent/chat/completions/{agent_class}/{agent_id}/json (and
/stream), the OpenAI-style /api/v1/openai/chat/completions/json, and /api/v1/bot_in_the_loop/response. Health is
at /api/v1/health.
Connecting a channel
Each bot endpoint is keyed by its URL path in MongoDB via a PathEntity, which holds that endpoint's Azure Bot
credentials (APP_ID, APP_PASSWORD, tenant), an optional system message, and a Slack token. To wire up a real
channel:
- Register a bot in Azure Bot Service (the SDK's
setup_azure_bothelper creates the AD app registration + Bot resource and stores the credentials), then add the Teams or Slack channel in the Azure portal. - Point the channel's messaging endpoint at your bot's public URL.
- The
PathEntityfor that path is seeded automatically bysetup_azure_bot(or manually viaadd_path_entityfor local development).
RoutesService.get_adapter(path) then loads the credentials, builds a cached Bot Framework adapter per endpoint, and
verifies the authenticity of every incoming activity.
Development
The dev stack runs the platform infrastructure (NATS, FerretDB, Valkey, LiteLLM, …) in Docker and exposes it on
localhost; the bot runs on your host:
# 1. Start the platform infrastructure (from a Swiss AI Hub checkout)
docker compose --env-file .env -f infra/docker-compose.dev.yml up -d
# 2. Load the dev connection settings into your shell
set -a && source .env && set +a
# 3. Run the bot — it connects to NATS + MongoDB and serves on :8001
uvicorn app:app --host 0.0.0.0 --port 8001
The bot connects to NATS and MongoDB, subscribes for bot-in-the-loop requests, and is ready to receive activities. Two ways to drive messages locally:
- Bot Framework Emulator — connect it to
http://localhost:8001/api/v1/messages(leave App ID/Password empty). - Real channels — expose your local bot to the internet with a tunnel (Azure Dev Tunnels, ngrok, …) and set that URL as the channel's messaging endpoint, so Teams/Slack can reach it.
Settings are not auto-loaded from the environment. The SDK reads connection settings only when constructed, so make sure the variables above are exported in the process that runs the bot (
set -a && source .env && set +a).
Production
In production the bot runs as a container behind Traefik (so channels can reach its webhook), reaching other services by container hostname.
1. Containerize it — install the SDK from PyPI and serve with Gunicorn + Uvicorn workers:
FROM python:3.13-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
COPY pyproject.toml uv.lock ./ # your project, depending on swiss-ai-hub-bot
RUN uv sync --frozen --no-dev
COPY . .
ENV PATH="/app/.venv/bin:$PATH" PYTHONUNBUFFERED=1
EXPOSE 8001
ENTRYPOINT ["gunicorn", "-w", "1", "-k", "uvicorn.workers.UvicornWorker", \
"--forwarded-allow-ips=*", "-b", "0.0.0.0:8001", "app:app"]
2. Run it alongside the platform on the right networks. The bot receives channel webhooks (Traefik → proxy),
routes conversations to agents over NATS and keeps conversation state in MongoDB (data), and reaches the LLM
gateway (backend):
# docker-compose.my-bot.yml — deployed alongside the platform
services:
my-bot:
image: registry.example.com/my-bot:1.0.0
restart: always
environment:
NATS_ENDPOINT: nats://nats:4222
NATS_TOKEN: ${NATS_TOKEN}
MONGO_CONNECTION_STRING: mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@ferretdb:27017/
LITE_LLM_PROXY_BASE_URL: http://litellm:4000
LITE_LLM_PROXY_API_KEY: ${LITELLM_MASTER_KEY}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8001/api/v1/health"]
interval: 30s
timeout: 10s
retries: 3
labels: # expose the messaging endpoint through the platform's Traefik
- "traefik.enable=true"
- "traefik.http.services.my-bot.loadbalancer.server.port=8001"
networks: [proxy, backend, data]
networks:
proxy: { external: true }
backend: { external: true }
data: { external: true }
docker compose -f docker-compose.my-bot.yml up -d
Reuse the platform's secrets (from its .env) for the ${…} values, and match the actual network names of your
deployment.
Network reference.
proxy= external ingress via Traefik (where channel webhooks arrive).data= NATS, FerretDB.backend= LiteLLM. The bot needs nostoragenetwork.
What you get
| Capability | Detail |
|---|---|
| Channels | MS Teams, Slack, and web chat — with channel-specific thread/mention/file/markdown handling |
| Agent chat | AgentChatBot routes a conversation to an agent over NATS and streams the reply back |
| Direct LLM | OpenaiChatBot talks straight to LiteLLM for simple chat-with-a-model endpoints |
| Streaming | Token-by-token updates in the channel (falls back to non-streaming where the channel can't update messages) |
| Bot-in-the-loop | Delivers an agent's question to a human in Slack/Teams and feeds the reply back into the workflow |
| Conversation state | Per-endpoint config + conversation history in MongoDB, with a configurable TTL |
| Testing | BotTestRunner and SimulatedAgentBotTestRunner for capturing outbound activities and faking an agent over NATS |
See the documentation for the full handler/streaming/BITL reference.
Links
- Source & issues: https://github.com/bbvch-ai/aihub-core
- Documentation: https://bbvch-ai.github.io/aihub-core/
- The full SDK (meta package): https://pypi.org/project/swiss-ai-hub/
License
Apache-2.0 — see packages/bot/LICENSE. For the full per-package license matrix, see LICENSES.md.
Part of Swiss AI Hub. Built in Switzerland by bbv Software Services.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file swiss_ai_hub_bot-0.292.1.tar.gz.
File metadata
- Download URL: swiss_ai_hub_bot-0.292.1.tar.gz
- Upload date:
- Size: 38.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
335ac7d68eb2789c4e331c050a7751c29b1c552cc519e35638c01c4334cc0ede
|
|
| MD5 |
6358fe49e9baae966852412c737bf68e
|
|
| BLAKE2b-256 |
da45ba754964a78fc810ddc4172fcfac6c12b1afbdcb1cf0ca446d992a0d3c55
|
File details
Details for the file swiss_ai_hub_bot-0.292.1-py3-none-any.whl.
File metadata
- Download URL: swiss_ai_hub_bot-0.292.1-py3-none-any.whl
- Upload date:
- Size: 55.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9bd1387b0fd89e18fd080acc6ca872592a9c556e7816d5eda99ce987daa11024
|
|
| MD5 |
c8965975b9d492ba332245d4eca8919e
|
|
| BLAKE2b-256 |
8b82179a9c5158d99f965ea9fa87800b26fa5a0ede252329c09c33ecc56fb883
|