Skip to content
BotServBotServ
SignalBotKI-BotOllamasignal-cliE2EEPrivacySelf-Hosting

Signal-Bot mit lokaler KI

Signal-Bot mit signal-cli und Ollama bauen: E2E-verschlüsselte KI-Chats, JSON-RPC, Gruppen und Docker-Setup.

S

schutzgeist

5 min read
Signal-Bot mit lokaler KI

Signal-Bot mit lokaler KI

Was dieser Artikel behandelt

  • Wie Du einen Signal-Bot mit signal-cli und Ollama baust.
  • Registrierung einer Bot-Nummer und Geräte-Kopplung.
  • Empfangen und Senden via JSON-RPC und Daemon-Modus.
  • Erweiterungen: Gruppen, RAG, Anhänge, Reaktionen.
  • Warum Signal die Privacy-stärkste Bot-Plattform ist.

Einleitung

Signal ist die einzige Mainstream-Plattform mit echter Ende-zu-Ende-Verschlüsselung für alles auch für Bot-Nachrichten. Wer einen KI-Bot für vertrauliche Kommunikation will (Journalisten, Anwälte, Firmeninterna), landet bei Signal.

Der Haken: Es gibt keine offizielle Bot-API. Der Standard-Weg ist signal-cli, ein Java-CLI, das das Signal-Protokoll implementiert und einen Daemon-Modus mit JSON-RPC anbietet. Dein Bot ist dann technisch ein „Signal-Client”, der wie ein normales Gerät funktioniert.

Typische Anwendungsszenarien

  • Vertraulicher KI-Assistent: Chats bleiben E2E-verschlüsselt bis zu Deinem Server, ideal für sensible Fragen.
  • Familien-/Team-Bot: Interne Kommunikation ohne Meta/Google/Cloud.
  • Alarmierung: Monitoring-Alerts E2E-verschlüsselt ans Handy (besser als E-Mail).
  • Dokumenten-Assistent: Vertrauliche Dokumente per Signal schicken, lokal verarbeiten lassen.
  • Redaktioneller Kontakt: Quellen können anonym mit der KI sprechen.

Voraussetzungen

  • Eine Telefonnummer für den Bot (Festnetz geht: Verifizierung per Anruf; oder zweite SIM/eSIM)
  • Java 17+ (signal-cli ist Java) oder das Docker-Image
  • Ollama mit einem Modell (llama3.1:8b o. ä.)
  • Python für die Bot-Logik

Schritt 1: signal-cli installieren und registrieren

# Binary-Release (Linux)
wget https://github.com/AsamK/signal-cli/releases/download/v0.13.x/signal-cli-0.13.x-Linux.tar.gz
sudo tar xf signal-cli-*.tar.gz -C /opt
sudo ln -s /opt/signal-cli-*/bin/signal-cli /usr/local/bin/signal-cli

Nummer registrieren (Captcha nötig: Link aus https://signalcaptchas.org/ holen):

signal-cli -a +4917612345678 register
signal-cli -a +4917612345678 verify 123456
signal-cli -a +4917612345678 updateProfile --name "KI-Assistent"

Alternative: Als verknüpftes Gerät an Deinen bestehenden Account koppeln, der Bot sendet dann als Du (für persönliche Assistenten okay, für öffentliche Bots nicht):

signal-cli link -n "Bot-Server"
# gibt sgnl:// Link → auf dem Handy als QR-Code anzeigen lassen (z.B. mit qrencode) und scannen

Schritt 2: Daemon-Modus mit JSON-RPC

signal-cli kann als JSON-RPC-Daemon laufen: Dein Python-Code kommuniziert über TCP oder HTTP:

# TCP-Daemon
signal-cli -a +4917612345678 daemon --tcp 127.0.0.1:7583

# oder HTTP (REST-ish)
signal-cli -a +4917612345678 daemon --http 127.0.0.1:8080

JSON-RPC-Methoden (Auswahl): send, receive, listGroups, sendTyping, addReaction, updateProfile.

Schritt 3: Bot-Logik mit Ollama

Einfachster Weg: receive-Loop per CLI-Aufruf (gut für den Start):

#!/usr/bin/env python3
import json
import subprocess
import ollama

BOT_NUMBER = "+4917612345678"
MODEL = "llama3.1:8b"
ALLOWED = {"+491701234567"}          # Wer darf den Bot nutzen
conversations = {}

client = ollama.Client(host="http://localhost:11434")

def send(recipient, text):
    subprocess.run([
        "signal-cli", "-a", BOT_NUMBER, "send",
        "-m", text, recipient
    ], check=False)

def ask_ollama(user, text):
    history = conversations.setdefault(user, [])
    history.append({"role": "user", "content": text})
    history = history[-10:]
    resp = client.chat(
        model=MODEL,
        messages=[{"role": "system", "content":
                   "Du bist ein hilfsbereiter Assistent. Antworte kurz."}] + history,
    )
    answer = resp["message"]["content"]
    history.append({"role": "assistant", "content": answer})
    conversations[user] = history
    return answer

def main():
    proc = subprocess.Popen(
        ["signal-cli", "-a", BOT_NUMBER, "receive", "-t", "-1",
         "--output", "json"],
        stdout=subprocess.PIPE, text=True,
    )
    for line in proc.stdout:
        line = line.strip()
        if not line:
            continue
        try:
            envelope = json.loads(line)
        except json.JSONDecodeError:
            continue
        msg = envelope.get("envelope", {})
        source = msg.get("sourceNumber") or msg.get("source")
        data = msg.get("dataMessage")
        if not data or source not in ALLOWED:
            continue
        text = data.get("message")
        if not text:
            continue
        print(f"[{source}] {text}")
        answer = ask_ollama(source, text)
        # Signal-Limit ~64k, aber kurze Antworten sind besser
        send(source, answer[:6000])

if __name__ == "__main__":
    main()

Das funktioniert sofort: Polling-Modus, kein Webhook nötig.

Erweiterungen

Gruppen-Betrieb

signal-cli kann Gruppen verwalten. Der Bot reagiert in Gruppen nur auf Erwähnung oder Präfix:

data = msg.get("dataMessage")
group = data.get("groupInfo")          # {"groupId": "...", "type": "..."}
text = data.get("message") or ""

if group:
    if not text.startswith("!ki"):
        continue
    text = text[3:].strip()
    # Antwort geht an die Gruppe:
    subprocess.run(["signal-cli", "-a", BOT_NUMBER, "send",
                    "-g", group["groupId"], "-m", answer])

Gruppen erstellen/verwalten per CLI:

signal-cli -a +49... updateGroup -n "Team-KI" -m +491701234567 +491702345678
signal-cli -a +49... listGroups

Reaktionen und Typing-Indikator

# Tippen anzeigen
signal-cli -a +49... sendTyping +491701234567

# Reaktion senden
signal-cli -a +49... sendReaction -e "👍" -a +491701234567 -t 1695123456789 +491701234567

Anhänge: Bilder an Vision-Modell

dataMessage.attachments enthält Dateipfade: Bilder an minicpm-v oder llava, Audio an Whisper:

for att in data.get("attachments", []):
    if att.get("contentType", "").startswith("image/"):
        resp = client.chat(model="minicpm-v", messages=[{
            "role": "user",
            "content": "Was ist auf diesem Bild?",
            "images": [att["file"]],
        }])
        send(source, resp["message"]["content"])

RAG wie bei Telegram

Identisches Muster: Embedding der Nachricht → Qdrant → Kontext in den System-Prompt. Siehe Telegram-Bot RAG und Lokales RAG.

Deployment

Docker: signal-cli als Daemon

services:
  signal-cli:
    image: registry.gitlab.com/morph027/signal-cli-daemon:latest
    volumes:
      - signal_data:/home/.local/share/signal-cli
    environment:
      - MODE=json-rpc
      - SIGNAL_NUMBER=+4917612345678
    ports:
      - "127.0.0.1:7583:7583"
    restart: always

  signal-bot:
    build: ./bot
    restart: always
    depends_on: [signal-cli, ollama]

  ollama:
    image: ollama/ollama:latest
    volumes: [ollama_data:/root/.ollama]

volumes:
  signal_data:
  ollama_data:

systemd ohne Docker

[Unit]
Description=Signal-KI-Bot
After=network-online.target

[Service]
Type=simple
User=signalbot
WorkingDirectory=/opt/signal-bot
ExecStart=/usr/bin/python3 bot.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Datenschutz, der eigentliche Grund für Signal

  • E2EE komplett: Nachrichten sind zwischen Sender und Bot-Server verschlüsselt. Signal-Server sehen nur Metadaten (und minimiert die sogar).
  • Keine Werbung, kein Tracking: Signal ist ein gemeinnütziger Verein.
  • Open Source: Client, Server und signal-cli sind Open Source.
  • Grenze: Der Bot selbst entschlüsselt auf Deinem Server, dort gelten Deine Regeln. Und Metadaten (wer wann schreibt) sieht Signal trotzdem.

Typische Stolpersteine

  • Registration-Captcha: Signal verlangt Captchas bei Registrierung: Workaround: Account zuerst auf einem Handy registrieren, dann als Linked Device koppeln.
  • Nummer gesperrt: Wenn Signal die Nummer sperrt (selten): signal-cli ... register erneut.
  • Daemon crasht: signal-cli ist Java, bei OOM JAVA_OPTS="-Xmx512m" setzen.
  • Empfang verschluckt sich: Im receive-Loop langsame Antworten blockieren den Loop: Ollama-Calls in Thread/Async auslagern.
  • Sealed Sender: Nachrichten von unbekannten Kontakten brauchen Trust: signal-cli trust -a <nummer> für Kontakte.

Key Takeaways:

  • Signal-Bots laufen über signal-cli (Daemon + JSON-RPC), nicht über eine offizielle Bot-API.
  • Einzige Plattform mit kompletter E2EE, ideal für vertrauliche Bots.
  • Setup: Nummer registrieren oder als Linked Device koppeln, dann receive-Loop.
  • Erweiterungen wie überall: Gruppen, RAG, Vision, Whisper.
  • Für öffentliche Bots umständlich: Telegram ist einfacher, Signal ist privater.

FAQ

Gibt es eine offizielle Signal-Bot-API?

Nein. signal-cli (von AsamK) ist der inoffizielle Standard, ein vollständiger Signal-Client als CLI/Daemon. Er ist Open Source und seit Jahren gepflegt, aber ohne offizielle Unterstützung durch Signal.

Brauche ich eine eigene Nummer?

Nicht zwingend: Du kannst den Bot als Linked Device an Deinen Account koppeln (sendet dann als Du). Für einen eigenständigen Bot: eigene Nummer nötig: Festnetz oder zweite SIM reicht.

Sind Bot-Nachrichten wirklich verschlüsselt?

Ja: Signal verschlüsselt alles E2E, auch Bot-Chats. Die Nachricht wird erst auf Deinem Server entschlüsselt. Das macht Signal zur besten Wahl für vertrauliche Bot-Kommunikation.

Die Registrierung scheitert am Captcha, was tun?

Captcha auf signalcaptchas.org lösen und den Token an register übergeben. Alternativ: Nummer erst auf einem echten Handy registrieren, dann den Bot als verknüpftes Gerät koppeln (umgeht den Prozess).

Funktioniert der Bot in Gruppen?

Ja: Bot zur Gruppe hinzufügen, dann kommen Gruppen-Nachrichten mit groupInfo im Envelope. Der Bot kann in die Gruppe antworten, Mitglieder verwalten (updateGroup) und reagieren.

Ist signal-cli schnell genug?

Für Bots ja: Nachrichten kommen in unter einer Sekunde an. Der Flaschenhals ist wie immer die lokale KI-Inferenz, nicht der Transport. Nur der Java-Overhead braucht ~200-400 MB RAM.

Signal oder Matrix für private Bots?

Signal: bessere E2EE (auch Metadaten-minimiert), aber inoffizielle API. Matrix: offizielle Bot-API (matrix-nio), selbst-hostbarer Server, E2EE optional. Für reine Privacy Signal, für Integration und Kontrolle Matrix.

Quellen und weiterführende Literatur

Zurück zum KI Blog
Share:

Ähnliche Beiträge