Skip to content
BotServBotServ
Microsoft TeamsBotKI-BotOllamaBot FrameworkEnterpriseAzure

Microsoft-Teams-Bot mit lokaler KI

Teams-Bot mit Ollama bauen: Bot Framework, Azure Bot Service, Adaptive Cards, Teams-Nachrichten und lokale KI im Enterprise-Umfeld.

S

schutzgeist

6 min read
Microsoft-Teams-Bot mit lokaler KI

Microsoft-Teams-Bot mit lokaler KI

Was dieser Artikel behandelt

  • Wie Du einen Teams-Bot mit dem Bot Framework und Ollama baust.
  • Azure Bot Service vs. lokale Alternativen, was zwingend in Azure sein muss.
  • Adaptive Cards, Mentions, Teams-Channels und Proaktiv-Messaging.
  • Erweiterungen: RAG auf SharePoint/M365-Daten, Meeting-Zusammenfassungen.
  • Warum Teams-Bots das Enterprise-Biest unter den Chat-Plattformen sind.

Einleitung

Microsoft Teams ist in Unternehmen mit Microsoft-365-Umgebungen Standard und der einzige Chat, für den Du den Bot nicht einfach „irgendwo registrierst”. Teams-Bots brauchen zwingend eine Azure Bot Resource als Vermittler: Teams spricht nie direkt mit Deinem Server, sondern immer über Azure Bot Service.

Das macht den Einstieg aufwendiger: App-Registration, Azure Bot, Teams-Manifest, Channel-Config. Dafür bekommst Du Enterprise-Features: Adaptive Cards, Graph-API-Anbindung, SSO mit Entra ID. Die KI selbst kann trotzdem lokal laufen, nur der Nachrichten-Transport geht über Azure.

Typische Anwendungsszenarien

  • Interner Helpdesk-Bot: IT-Fragen aus dem Firmen-Wiki per RAG beantworten.
  • HR-Assistent: Urlaubsregeln, Benefits, Formulare: Mitarbeiter fragen den Bot.
  • DevOps-Assistent: Build-Status, Deployment-Fragen, Incident-Support.
  • Meeting-Assistent: Transkripte zusammenfassen (in Kombination mit Graph API).
  • Compliance-sicherer KI-Chat: KI bleibt lokal, nur der Kanal ist Microsoft.

Voraussetzungen

  • Microsoft 365 Tenant mit Teams
  • Azure-Subscription (Bot Service ist kostenlos im Free-Tier)
  • Öffentlich erreichbarer HTTPS-Endpoint für den Bot (Azure ruft Deinen Server auf) oder Tunnel wie devtunnel/cloudflared für Entwicklung
  • Python oder C# (Bot Framework SDK gibt es für beide)
  • Ollama mit Modell

Schritt 1: Azure Bot Resource anlegen

  1. Azure Portal → „Azure Bot” erstellen → Type „Single Tenant” oder „Multi Tenant”
  2. Microsoft App ID wird generiert + Client Secret erstellen
  3. Channels → „Microsoft Teams” aktivieren
  4. Messaging-Endpoint setzen: https://bots.deine-domain.de/api/messages

.env:

APP_ID=deine-app-id
APP_PASSWORD=dein-client-secret
APP_TYPE=MultiTenant
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=llama3.1:8b

Schritt 2: Bot mit Bot Framework (Python)

pip install botbuilder-core botbuilder-schema aiohttp ollama python-dotenv

bot.py:

import os
import ollama
from aiohttp import web
from dotenv import load_dotenv
from botbuilder.core import (
    BotFrameworkAdapterSettings, BotFrameworkAdapter, TurnContext, ActivityHandler
)
from botbuilder.schema import Activity, ActivityTypes

load_dotenv()

SETTINGS = BotFrameworkAdapterSettings(
    os.environ["APP_ID"], os.environ["APP_PASSWORD"]
)
ADAPTER = BotFrameworkAdapter(SETTINGS)
ollama_client = ollama.Client(host=os.environ["OLLAMA_URL"])
MODEL = os.environ.get("OLLAMA_MODEL", "llama3.1:8b")

SYSTEM = ("Du bist der interne KI-Assistent der Firma. "
          "Antworte kurz, auf Deutsch, hilfreich.")

# Konversations-Kontext pro Teams-Konversation
conversations = {}


class KIBot(ActivityHandler):
    async def on_message_activity(self, turn_context: TurnContext):
        conv_id = turn_context.activity.conversation.id
        text = turn_context.activity.text or ""

        # Teams liefert <at>Bot-Name</at> in Mentions — entfernen
        text = text.replace("<at>", "").replace("</at>", "")
        for entity in turn_context.activity.entities or []:
            if entity.type == "mention":
                text = text.replace(entity.text, "")
        text = text.strip()

        if not text:
            return

        history = conversations.setdefault(conv_id, [])
        history.append({"role": "user", "content": text})
        history = history[-10:]

        # Tippen-Indikator
        await turn_context.send_activity(Activity(type=ActivityTypes.typing))

        try:
            resp = ollama_client.chat(model=MODEL, messages=[
                {"role": "system", "content": SYSTEM}] + history)
            answer = resp["message"]["content"]
            history.append({"role": "assistant", "content": answer})
            conversations[conv_id] = history
            await turn_context.send_activity(answer[:28000])
        except Exception as e:
            await turn_context.send_activity("Fehler: KI-Backend nicht erreichbar.")


BOT = KIBot()

async def messages(request):
    body = await request.json()
    auth_header = request.headers.get("Authorization", "")
    activity = Activity().deserialize(body)
    response = await ADAPTER.process_activity(
        activity, auth_header, BOT.on_turn
    )
    return web.Response(status=200)

app = web.Application()
app.router.add_post("/api/messages", messages)
web.run_app(app, host="0.0.0.0", port=3978)

Schritt 3: Teams-Manifest und App-Paket

Teams braucht ein App-Paket (ZIP mit manifest.json + Icons):

{
  "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.16/MicrosoftTeams.schema.json",
  "manifestVersion": "1.16",
  "version": "1.0.0",
  "id": "deine-app-id-vom-azure-bot",
  "developer": {
    "name": "Deine Firma",
    "websiteUrl": "https://deine-domain.de",
    "privacyUrl": "https://deine-domain.de/privacy",
    "termsOfUseUrl": "https://deine-domain.de/terms"
  },
  "name": {"short": "KI-Assistent"},
  "description": {"short": "Interner KI-Bot", "full": "KI-Assistent mit lokalem Modell"},
  "icons": {"color": "color.png", "outline": "outline.png"},
  "accentColor": "#FFFFFF",
  "bots": [{
    "botId": "deine-app-id-vom-azure-bot",
    "scopes": ["personal", "team", "groupChat"],
    "supportsFiles": false,
    "isNotificationOnly": false
  }],
  "permissions": ["identity", "messageTeamMembers"],
  "validDomains": []
}

ZIP packen → Teams → Apps → „Manage your apps” → „Upload a custom app”. In Firmen-Tenants muss der Admin das Sideloaden erlauben bzw. die App im Admin Center freigeben.

Erweiterungen

Adaptive Cards (Buttons, Formulare)

card = {
    "type": "AdaptiveCard", "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.4",
    "body": [{"type": "TextBlock", "text": "War die Antwort hilfreich?"}],
    "actions": [
        {"type": "Action.Submit", "title": "👍", "data": {"vote": "up"}},
        {"type": "Action.Submit", "title": "👎", "data": {"vote": "down"}},
        {"type": "Action.Submit", "title": "An Menschen weiterleiten",
         "data": {"escalate": True}},
    ]
}
await turn_context.send_activity(Activity(
    type=ActivityTypes.message,
    attachments=[{"contentType": "application/vnd.microsoft.card.adaptive",
                  "content": card}]
))

Button-Klicks kommen als on_message_activity mit value statt text, dort auswerten.

RAG auf SharePoint / interne Doku

SharePoint-Dokumente per Graph API exportieren → chunken → in Qdrant → Bot beantwortet aus Firmenwissen. Alternativ lokale Dokumente wie in Lokales RAG beschrieben.

Proaktive Nachrichten

Der Bot kann Nutzer anschreiben (z. B. „Dein Ticket wurde gelöst”), braucht die conversationReference, die beim ersten Kontakt gespeichert wird:

async def on_members_added_activity(self, members_added, turn_context):
    # Konversations-Referenz für später speichern
    ref = TurnContext.get_conversation_reference(turn_context.activity)
    save_ref(turn_context.activity.from_property.id, ref)

# später, proaktiv:
await ADAPTER.continue_conversation(ref, callback)

Entra ID / SSO

Da der Bot ohnehin im Microsoft-Ökosystem läuft, kannst Du User-Identität via Entra ID bekommen: Bot sieht dann, wer fragt, und kann Antworten personalisieren bzw. Berechtigungen prüfen.

Deployment

Teams ruft Deinen Endpoint, der Bot-Server braucht öffentliches HTTPS:

services:
  teams-bot:
    build: ./bot
    restart: always
    env_file: .env
    ports: ["127.0.0.1:3978:3978"]
    # Reverse Proxy (Caddy/Nginx) macht TLS + leitet weiter

Entwicklungs-Tipp: devtunnel (Microsoft) oder cloudflared als temporärer Tunnel, ohne DNS/Proxy zu konfigurieren.

Sicherheit und Compliance

  • Hybrid-Datenschutz: Nachrichten gehen Teams → Azure Bot Service → Dein Server. Die KI-Verarbeitung bleibt lokal, aber Microsoft sieht den Verkehr.
  • App Secret: Client Secret in Azure Key Vault / .env, nie im Manifest.
  • Tenant-Validierung: APP_TYPE korrekt setzen (SingleTenant für nur Deine Firma).
  • Berechtigungen: Der Bot sieht nur Konversationen, in die er eingeladen wurde, gut.
  • DSGVO: Teams ist EU-konform nutzbar (EU Data Boundary); der Azure Bot Service leitet durch, für höchste Vertraulichkeit Mattermost on-premise.

Typische Stolpersteine

  • 401 Unauthorized: App ID/Secret falsch, oder APP_TYPE passt nicht zum Tenant-Typ.
  • Bot antwortet in Channels nicht: Bot muss in den Channel/das Team eingeladen werden (@mention reicht als Aktivierung für das Team).
  • Mention-Markup: <at>-Tags im Text entfernen, sonst landen sie im Prompt.
  • App nicht installierbar: Sideloading im Tenant deaktiviert: Admin muss freigeben.
  • Endpoint muss HTTPS: Azure akzeptiert nur TLS mit gültigem Zertifikat, kein self-signed.

Key Takeaways:

  • Teams-Bots brauchen zwingend Azure Bot Service als Vermittler, kein direkter Weg.
  • Setup: Azure Bot + App Registration + Teams-Manifest, aufwendiger als Slack/Telegram.
  • Nachrichten-Transport über Azure, KI-Verarbeitung kann lokal bleiben (Hybrid).
  • Adaptive Cards und Graph-API sind die starken Enterprise-Features.
  • Für M365-Firmen der einzig sinnvolle Weg; für alle anderen zu komplex.

FAQ

Muss der Bot wirklich über Azure laufen?

Der Bot-Code läuft auf Deinem Server, aber der Nachrichten-Transport geht zwingend über den Azure Bot Service. Ohne Azure-Ressource gibt es keinen Teams-Bot. Die Azure-Bot-Ressource selbst ist im Free-Tier kostenlos.

Was kostet ein Teams-Bot?

Azure Bot Service: Free-Tier kostenlos (10.000 Nachrichten/Monat Premium-Kanal). Teams selbst braucht M365-Lizenzen. Deine lokale KI: nur Hardware. Keine Bot-Nutzungskosten wie bei GPT-APIs.

Python oder C# für den Bot?

Beide haben offizielle SDKs. C# ist die Referenz-Implementierung mit den meisten Beispielen; Python (botbuilder-core) ist einfacher für KI-Integration (Ollama, LangChain etc. sind Python-first).

Wie bekomme ich die App in den Firmen-Tenant?

Als ZIP über „Upload a custom app”, wenn der Tenant Sideloading erlaubt. Sonst: Admin lädt sie im Teams Admin Center hoch oder verteilt sie per App-Policy. Für Firmen-Rollout: im Admin Center veröffentlichen lassen.

Teams-Bot oder Slack-Bot?

Wenn die Firma M365 nutzt: Teams, die User sind schon da, SSO gratis. Slack ist einfacher zu entwickeln (kein Azure-Zwang). Für komplette Datenhoheit: Mattermost.

Sieht Microsoft die Bot-Nachrichten?

Der Transport läuft über Teams/Azure, technisch ja, als Durchleitung. Die KI-Verarbeitung und Dokumente bleiben lokal. Für maximal vertrauliche Inhalte ist ein reines On-Premise-System (Mattermost/Matrix) besser.

Kann der Bot Nutzer anschreiben?

Ja, proaktives Messaging ist möglich, braucht aber eine gespeicherte conversationReference vom ersten Kontakt. Für Alerting und Benachrichtigungen nützlich.

Quellen und weiterführende Literatur

Zurück zum KI Blog
Share:

Ähnliche Beiträge