Zum Hauptinhalt springen
connic
Verbindungen

Webhooks

HTTP Webhooks ermöglichen externen Systemen, Agenten über HTTP-Anfragen zu starten. Sie unterstützen JSON, Formulardaten und Datei-Uploads.

Zuletzt aktualisiert
Inbound Mode
Fire-and-forget-Trigger für asynchrone Agent Runs. Der Webhook gibt sofort Run-IDs zurück, während die Agenten im Hintergrund arbeiten.

Einrichtung

  1. Verbindung erstellen

    Öffne den Agenten, klicke im Verbindungsflussdiagramm auf Add inbound connector, dann auf Create New Connector und wähle HTTP Webhook.

  2. Inbound (Fire & Forget) auswählen und Zugangsdaten kopieren

    Wähle den Mode und klicke auf Create. Der Detail-Drawer öffnet sich automatisch und zeigt unter Configuration die Webhook URL und das Secret. Um sie später anzuzeigen, bewege den Mauszeiger im Verbindungsflussdiagramm über die Verbindung und klicke auf das Augensymbol.

  3. Anfragen senden

    Sende Anfragen aus der Anwendung an die URL. Wenn die Verbindungsauthentifizierung aktiviert ist, übermittle das Secret im Header X-Connic-Secret.

So funktioniert Inbound

Wenn ein Inbound Webhook eine Anfrage empfängt, stellt er den Agenten-Run in die Warteschlange und gibt eine Antwort mit den Run-IDs zurück. Der Agent arbeitet im Hintergrund. Das eignet sich für Hintergrundverarbeitung, Ingestion mit hohem Volumen und ereignisgesteuerte Architekturen.

Antwortformat

response.json
{
  "status": "ok",
  "dispatched_to": 2,
  "run_ids": [
    "550e8400-e29b-41d4-a716-446655440000",
    "550e8400-e29b-41d4-a716-446655440001"
  ]
}

Anfragen senden

Webhooks akzeptieren GET- und POST-Anfragen mit verschiedenen Inhaltstypen.

JSON-Anfragen

Die häufigste Methode zum Auslösen von Webhooks. Sende eine POST-Anfrage mit einem JSON-Body (application/json). JSON-Felder werden als Input an den Agenten übergeben. Für Inline-Dateien unter files gelten die unten beschriebenen Limits.

terminal
curl -X POST <webhook-url> \
  -H "Content-Type: application/json" \
  -H "X-Connic-Secret: <your-secret-key>" \
  -d '{
    "prompt": "Analysiere diese Daten",
    "data": {"key": "value"}
  }'

Formulardaten-Anfragen

Geeignet für einfache Integrationen oder wenn das Quellsystem Formulardaten sendet (application/x-www-form-urlencoded). Jedes Formularfeld wird zu einem Schlüssel-Wert-Paar in der Payload.

terminal
curl -X POST <webhook-url> \
  -H "X-Connic-Secret: <your-secret-key>" \
  -F "message=Verarbeite diese Rechnung" \
  -F "customer_id=12345"

GET-Anfragen

Verwende für einfache Trigger GET-Anfragen mit Query-Parametern. Alle Query-Parameter außer secret werden an den Agenten übergeben.

terminal
curl "<webhook-url>?secret=<your-secret-key>&prompt=hallo"

Webhook URL und Secret abrufen

Die Webhook URL enthält die Verbindungs-ID; das Secret für den Header X-Connic-Secret wird beim Erstellen der Verbindung generiert. Die Authentifizierung ist standardmäßig aktiviert. Deaktiviere Require Authentication nur für einen bewusst nicht authentifizierten Endpoint.

  1. Öffne im Bereich Agenten die Detailseite des Agenten

  2. Füge über den Button + im Verbindungsflussdiagramm eine Webhook-Verbindung hinzu oder wähle eine vorhandene aus

  3. Klicke auf das Augensymbol der Verbindung, um ihre Details zu öffnen

  4. Kopiere Webhook URL und Secret aus den Verbindungsdetails

Dateien hochladen

Sende Dateien mit multipart/form-data an Agenten. Jede angenommene Datei wird mit dem Agent-Input an das Modell übergeben.

Eine Datei hochladen:

terminal
curl -X POST <webhook-url> \
  -H "X-Connic-Secret: <your-secret-key>" \
  -F "instructions=Wie hoch ist der Gesamtbetrag dieser Rechnung?" \
  -F "file=@/path/to/invoice.pdf"

Lade mehrere Dateien in einer einzigen Anfrage hoch:

terminal
curl -X POST <webhook-url> \
  -H "X-Connic-Secret: <your-secret-key>" \
  -F "message=Vergleiche diese beiden Dokumente" \
  -F "file1=@document1.pdf" \
  -F "file2=@document2.pdf"

Multipart-Anfragen landen in context["payload"] als normalisiertes Dictionary: Textteile stehen als Schlüssel auf oberster Ebene, Uploads unter files (die Bytes jeder Datei sind Base64-kodiert). Der für das LLM bestimmte content wird automatisch rekonstruiert: Jede Datei wird zu einem Binärteil; der führende Textteil ist die Payload, aus der lediglich files entfernt wurde.

payload shape
# context["payload"] innerhalb von middleware before()
{
  "customer_id": "12345",      # Multipart-Textfelder stehen auf der obersten Ebene
  "tag": ["a", "b"],           # Wiederholte Schlüssel werden in einer Liste gruppiert
  "message": "Verarbeite diese Rechnung",
  "files": [
    {
      "name": "invoice.pdf",     # ursprünglicher Dateiname
      "field_name": "file",      # Name des Formularfelds
      "mime_type": "application/pdf",
      "data": "<base64-bytes>",  # immer Base64-kodiertes ASCII
      "size": 12345              # Byte
    }
  ]
}

# Ausgelassene Dateien stehen unter "file_issues". Formularfelder bleiben
# auch dann verfügbar, wenn keine Datei akzeptiert wurde.

Pro Input sind bis zu 10 Dateien mit höchstens 10 MiB je Datei und 10 MiB insgesamt erlaubt. Sobald eine Datei das Größen- oder Anzahl-Limit überschreitet, bleiben zuvor akzeptierte Dateien erhalten; weitere Dateien werden nicht mehr angenommen. Formularfelder bleiben auch dann verfügbar, wenn keine Datei akzeptiert wurde. Nicht unterstützte MIME-Typen werden mit einer Begründung unter file_issues ausgelassen.

Bei Anhängen enthält die Antwort accepted, omitted und issues. Dateien sind standardmäßig optional. Mit Dateien erforderlich am Agenten-Link oder files_required: true in dessen Konfiguration schlägt der Run vor der Ausführung fehl, wenn eine Datei fehlt oder ausgelassen wurde. Die anschließende Input-Prüfung kann optionale Dateiinhalte auslassen, die ihr Prüfbudget überschreiten.

Unterstützte Dateitypen

Bilder

JPEG, PNG, GIF, WebP, HEIC/HEIF

Dokumente

PDF, Word, RTF, OpenDocument, EPUB, Klartext, HTML, Markdown

Daten & Office

CSV, TSV, JSON, XML, Excel, PowerPoint

Der Connector nimmt diese Typen an. Ob das Modell eine Datei lesen kann, hängt vom Modell ab: siehe Datei-Input für connic/*-Modelle.

Limit für die Anfragegröße: Maximal 16 MiB einschließlich Feldern, Dateien, Base64-Kodierung und Multipart-Overhead. Größere Anfragen werden vor der Verarbeitung mit HTTP 413 und request_too_large abgelehnt; der Absender muss eine kleinere Anfrage senden.

Authentifizierung

Schütze Webhooks mit Secret-basierter Authentifizierung. Inbound und Sync Webhooks erfordern dieses Secret standardmäßig. Deaktiviere Require Authentication nur, wenn sich Aufrufer nicht authentifizieren müssen.

Secret übermitteln

Jeder Webhook besitzt einen eindeutigen Secret Key, der beim Erstellen generiert wird. Ist Require Authentication aktiviert, lässt sich das Secret auf drei Arten übermitteln:

  • X-Connic-Secret Header (empfohlen) – Am sichersten; das Secret steht in den Headern
  • Authorization: Bearer Header – Standardmäßiger Bearer Token im OAuth-Stil
  • Query Parameter (?secret=...) – Weniger sicher; in Logs sichtbar
terminal
# X-Connic-Secret-Header verwenden (empfohlen)
curl -X POST <webhook-url> \
  -H "X-Connic-Secret: <your-secret-key>" \
  -d '{"message": "hallo"}'

# Authorization: Bearer-Header verwenden
curl -X POST <webhook-url> \
  -H "Authorization: Bearer <your-secret-key>" \
  -d '{"message": "hallo"}'

# Query-Parameter verwenden (weniger sicher)
curl -X POST "<webhook-url>?secret=<your-secret-key>" \
  -d '{"message": "hallo"}'

Absender prüfen

Manche Absender signieren ihre Anfragen, etwa mit einem HMAC-Signatur-Header oder einem JWT in Authorization. Jeder Webhook-Run enthält die ursprüngliche Anfrage in context["request"], damit Middleware die Signatur prüfen kann, bevor der Agent läuft: Methode, Header mit kleingeschriebenen Namen, Query-Parameter und den unveränderten Body als body_base64.

Aufbau der Anfrage
# context["request"] in Middleware, Tools und Hooks
{
    "method": "POST",
    "headers": {"content-type": "application/json", "x-hub-signature-256": "sha256=..."},
    "query": {},
    "body_base64": "eyJhY3Rpb24iOiJvcGVuZWQifQ=="
}

connic entfernt das eigene Secret (X-Connic-Secret, einen passenden Authorization-Header und den Query-Parameter secret) sowie Header, die das eigene Netzwerk hinzufügt. Der unveränderte Body ist bis 1 MiB und nicht bei Multipart-Anfragen enthalten; sonst ist body_omitted true. Die Run-Details zeigen den Body sowie die Header Authorization, Proxy-Authorization, Cookie und X-API-Key als [REDACTED]. Anders gestartete Runs, etwa erneute Runs und Tests, haben keine Anfrage.

Eine HMAC-Signatur prüfen, etwa X-Hub-Signature-256 von GitHub:

middleware/github-events.py
import base64
import hashlib
import hmac
import os

from connic import StopProcessing


async def before(content, context):
    request = context.get("request")
    if request is None:  # Nicht durch eine Webhook-Anfrage gestartet, etwa ein erneuter Run
        return content
    body = base64.b64decode(request.get("body_base64") or "")
    digest = hmac.new(os.environ["GITHUB_WEBHOOK_SECRET"].encode(), body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(f"sha256={digest}", request["headers"].get("x-hub-signature-256", "")):
        raise StopProcessing("Invalid signature", publish_outbound=False)
    return content

Ein signiertes JWT prüfen, etwa das Bot-Framework-Token, das Microsoft Teams sendet. Teams kann das connic-Secret nicht als Header senden, daher ?secret= an die URL des Messaging-Endpunkts anhängen.

middleware/teams-bot.py
# requirements.txt: PyJWT[crypto]
import asyncio
import os

import jwt
from connic import StopProcessing

keys = jwt.PyJWKClient("https://login.botframework.com/v1/.well-known/keys")


async def before(content, context):
    request = context.get("request")
    if request is None:  # Nicht durch eine Webhook-Anfrage gestartet, etwa ein erneuter Run
        return content
    token = request["headers"].get("authorization", "").removeprefix("Bearer ")
    try:
        key = await asyncio.to_thread(keys.get_signing_key_from_jwt, token)
        claims = jwt.decode(
            token, key.key, algorithms=["RS256"], audience=os.environ["MICROSOFT_APP_ID"],
            issuer="https://api.botframework.com", leeway=300,
        )
    except jwt.PyJWTError:
        raise StopProcessing("Invalid token", publish_outbound=False)
    if claims.get("serviceUrl") != context["payload"].get("serviceUrl"):
        raise StopProcessing("Invalid token", publish_outbound=False)
    return content
Die Prüfung läuft beim Start des Runs. Eine Anfrage, die sie nicht besteht, wird trotzdem angenommen und erzeugt einen Run, den die Middleware dann stoppt. Ein Token kann außerdem ablaufen, während sein Run in der Warteschlange wartet.

Fehlerantworten

401

Ungültiger Secret Key

Das angegebene Secret stimmt nicht überein. Prüfe die Authentifizierungseinstellungen.

404

Webhook nicht gefunden

Die Webhook URL existiert nicht. Prüfe, ob die URL korrekt ist.

400

Reiner Outbound Webhook

Dieser Webhook ist ausschließlich für outbound konfiguriert und kann nicht ausgelöst werden.

Outbound Mode
Verwende diese Verbindung im automatischen, im Agent-Tool- oder im Middleware-Modus.

Einrichtung

  1. Endpoint einrichten

    Erstelle auf dem Server einen Endpoint, der POST-Anfragen empfangen kann.

  2. Verbindung erstellen

    Öffne den Agenten, klicke auf Add outbound connector, dann auf Create New Connector und wähle HTTP Webhook.

  3. Konfigurieren und erstellen

    Wähle den Mode Outbound, gib die Ziel-URL ein, an die connic Ergebnisse per POST senden soll, wähle optional eine Bridge für den Zugriff auf ein privates Netzwerk und klicke auf Create. Ergebnisse verknüpfter Agenten werden mit Signatur-Headern per POST an die konfigurierte URL gesendet.

So funktioniert Outbound

Automatische Outbound-Webhooks senden Agent-Ergebnisse nach Abschluss eines Runs an eine externe URL. Agent-Tool- und Middleware-Outbound-Webhooks senden, wenn sie während eines Runs aufgerufen werden. Die Verbindung verwendet eine konfigurierte Ziel-URL, an die connic die Ergebnisse per POST sendet. Leite ausgehende Anfragen an private Endpoints über eine connic Bridge. Das eignet sich zum Senden von Ergebnissen an externe APIs, zur Integration von Drittanbieterdiensten und zum Aufbau von Ereignis-Pipelines.

Hinweis
Reine Outbound-Webhooks akzeptieren keine eingehenden HTTP-Anfragen. Sie senden ausschließlich über eine konfigurierte automatische, Agent-Tool- oder Middleware-Outbound-Verbindung.

Automatische Payload

Automatische Outbound-Verbindungen senden den Wrapper des abgeschlossenen Runs per POST. Bei bestehenden Verknüpfungen werden weiterhin alle abgeschlossenen Runs automatisch gesendet, solange ihr Modus oder Quellenfilter nicht geändert wird.

payload.json
{
  "run_id": "550e8400-e29b-41d4-a716-446655440000",
  "agent_name": "invoice-processor",
  "status": "completed",
  "output": "Der Rechnungsbetrag beträgt $1,234.56",
  "error": null,
  "started_at": "2024-01-15T10:30:00Z",
  "ended_at": "2024-01-15T10:30:05Z",
  "token_usage": {
    "input_tokens": 150,
    "output_tokens": 50,
    "thinking_tokens": 0,
    "cached_input_tokens": 0,
    "total_tokens": 200
  }
}

Agent-Tool- und Middleware-Outbound-Verbindungen

Agent-Tool-Outbound-Verbindungen stellen einen bearbeitbaren Tool-Namen bereit, standardmäßig send_to_<connector_name>. Rufe Middleware-Outbound-Verbindungen mit send_connector(action_name, payload) unter ihrem konfigurierten Namen auf. Beide verwenden dasselbe von der Verbindung definierte Payload-Schema: Übermittle den JSON-Body unter payload.

connector-payload.json
{
  "payload": {
    "invoice_id": "inv_123",
    "status": "approved"
  }
}

connic sendet den verschachtelten Wert per POST und verwendet URL, konfigurierte Header, HMAC-Signatur, Wiederholungsstrategie und Bridge-Routing der Verbindung. Diese Einstellungen werden dem Modell nicht offengelegt.

Signatur prüfen

Jede Outbound-Webhook-Anfrage enthält eine HMAC-SHA256-Signatur. Prüfe sie, um die Echtheit der Anfragen sicherzustellen.

Request Header

  • X-Connic-Signature – Hex-kodierte HMAC-SHA256-Signatur
  • X-Connic-Timestamp – Unix-Zeitstempel in Sekunden für den Signaturzeitpunkt der Anfrage

Signatur prüfen

  1. Rufe das Signing Secret aus den Verbindungseinstellungen ab

  2. Extrahiere Zeitstempel und Signatur aus den Headern

  3. Verkette Zeitstempel + "." + rohen Request Body

  4. Berechne HMAC-SHA256 für den verketteten String mit dem Secret

  5. Vergleiche die berechnete mit der empfangenen Signatur

  6. Prüfe optional, ob der Zeitstempel innerhalb von 5 Minuten liegt, um Replay-Angriffe zu verhindern

Python-Beispiel

verify_webhook.py
import hmac
import hashlib
import time

def verify_webhook(payload: bytes, signature: str, timestamp: str, secret: str) -> bool:
    """Signatur eines connic Webhooks prüfen."""
    # Prüfen, ob der Zeitstempel zu alt ist (5-Minuten-Fenster)
    if abs(time.time() - int(timestamp)) > 300:
        return False

    # Signierte Payload erstellen
    signed_payload = f"{timestamp}.".encode() + payload

    # Erwartete Signatur berechnen
    expected = hmac.new(
        secret.encode(),
        signed_payload,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(expected, signature)

# Verwendung in Flask
@app.route("/webhook", methods=["POST"])
def handle_webhook():
    signature = request.headers.get("X-Connic-Signature", "")
    timestamp = request.headers.get("X-Connic-Timestamp", "")

    if not verify_webhook(request.data, signature, timestamp, SIGNING_SECRET):
        return "Ungültige Signatur", 401

    # Webhook verarbeiten ...
    return "OK", 200

Node.js-Beispiel

verify_webhook.js
import crypto from 'crypto';

function verifyWebhook(payload, signature, timestamp, secret) {
  // Prüfen, ob der Zeitstempel zu alt ist (5-Minuten-Fenster)
  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - parseInt(timestamp)) > 300) {
    return false;
  }

  // Signierte Payload erstellen
  const signedPayload = `${timestamp}.${payload}`;

  // Erwartete Signatur berechnen
  const expected = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

// Verwendung in Express
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-connic-signature'];
  const timestamp = req.headers['x-connic-timestamp'];

  if (!verifyWebhook(req.body.toString(), signature, timestamp, SIGNING_SECRET)) {
    return res.status(401).send('Ungültige Signatur');
  }

  // Webhook verarbeiten ...
  res.send('OK');
});
Bewährte Vorgehensweisen für Sicherheit
  • Prüfe Signaturen im Produktivbetrieb immer
  • Verwende einen Vergleich mit konstanter Laufzeit, um Timing-Angriffe zu verhindern
  • Lehne Anfragen mit Zeitstempeln ab, die älter als 5 Minuten sind
  • Speichere das Signing Secret sicher in Umgebungsvariablen
Sync Mode
Request-Response-Muster mit sofortigem Ergebnis. Der Webhook wartet auf den Abschluss des Agenten und gibt das Ergebnis in derselben Antwort zurück.

So funktioniert Sync

Sync Webhooks warten auf den Abschluss des Agenten und geben das Ergebnis in derselben HTTP-Antwort zurück – ein klassisches Request-Response-Muster. Das eignet sich für REST-API-Integrationen, interaktive Anwendungen und kurz laufende Aufgaben.

Timeout
Das Standard-Timeout beträgt 5 Minuten. Verwende für längere Aufgaben den Inbound Mode und frage die Ergebnisse ab.

Einrichtung

  1. Verbindung erstellen

    Öffne den Agenten, klicke im Verbindungsflussdiagramm auf Add inbound connector, dann auf Create New Connector und wähle HTTP Webhook.

  2. Sync (Request-Response) auswählen und Zugangsdaten kopieren

    Wähle den Mode und klicke auf Create. Der Detail-Drawer öffnet sich automatisch und zeigt unter Configuration die Webhook URL und das Secret. Um sie später anzuzeigen, bewege den Mauszeiger im Verbindungsflussdiagramm über die Verbindung und klicke auf das Augensymbol.

  3. Anfragen senden

    Sende JSON per POST an die Webhook URL. Die HTTP-Anfrage bleibt bis zum Abschluss des Agenten offen und erhält das Ergebnis direkt als Antwort.

Antwortformat

response.json
{
  "status": "ok",
  "result": {
    "run_id": "550e8400-e29b-41d4-a716-446655440000",
    "agent_name": "invoice-processor",
    "status": "completed",
    "output": "Der Rechnungsbetrag beträgt $1,234.56",
    "error": null
  }
}

Schlägt der Agenten-Run fehl, enthält die Antwort status: "failed" und die Fehlermeldung; auch der Verbindungs-Run wird als fehlgeschlagen erfasst.

Client-Beispiele

sync_request.py
import requests

url = "<webhook-url>"
secret = "<your-secret-key>"

payload = {"query": "Wie ist der Status der Bestellung 123?"}
resp = requests.post(
    url,
    json=payload,
    headers={"X-Connic-Secret": secret},
    timeout=310,
)
resp.raise_for_status()
print(resp.json()["result"]["output"])
sync_request.js
import fetch from "node-fetch";

const url = "<webhook-url>";
const secret = "<your-secret-key>";

const resp = await fetch(url, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Connic-Secret": secret,
  },
  body: JSON.stringify({ query: "Fasse das neueste Ticket zusammen" }),
});

if (!resp.ok) throw new Error(await resp.text());
const data = await resp.json();
console.log(data.result.output);

Anfragen senden

Webhooks akzeptieren GET- und POST-Anfragen mit verschiedenen Inhaltstypen.

JSON-Anfragen

Die häufigste Methode zum Auslösen von Webhooks. Sende eine POST-Anfrage mit einem JSON-Body (application/json). JSON-Felder werden als Input an den Agenten übergeben. Für Inline-Dateien unter files gelten die unten beschriebenen Limits.

terminal
curl -X POST <webhook-url> \
  -H "Content-Type: application/json" \
  -H "X-Connic-Secret: <your-secret-key>" \
  -d '{
    "prompt": "Analysiere diese Daten",
    "data": {"key": "value"}
  }'

Formulardaten-Anfragen

Geeignet für einfache Integrationen oder wenn das Quellsystem Formulardaten sendet (application/x-www-form-urlencoded). Jedes Formularfeld wird zu einem Schlüssel-Wert-Paar in der Payload.

terminal
curl -X POST <webhook-url> \
  -H "X-Connic-Secret: <your-secret-key>" \
  -F "message=Verarbeite diese Rechnung" \
  -F "customer_id=12345"

GET-Anfragen

Verwende für einfache Trigger GET-Anfragen mit Query-Parametern. Alle Query-Parameter außer secret werden an den Agenten übergeben.

terminal
curl "<webhook-url>?secret=<your-secret-key>&prompt=hallo"

Webhook URL und Secret abrufen

Die Webhook URL enthält die Verbindungs-ID; das Secret für den Header X-Connic-Secret wird beim Erstellen der Verbindung generiert. Die Authentifizierung ist standardmäßig aktiviert. Deaktiviere Require Authentication nur für einen bewusst nicht authentifizierten Endpoint.

  1. Öffne im Bereich Agenten die Detailseite des Agenten

  2. Füge über den Button + im Verbindungsflussdiagramm eine Webhook-Verbindung hinzu oder wähle eine vorhandene aus

  3. Klicke auf das Augensymbol der Verbindung, um ihre Details zu öffnen

  4. Kopiere Webhook URL und Secret aus den Verbindungsdetails

Dateien hochladen

Sende Dateien mit multipart/form-data an Agenten. Jede angenommene Datei wird mit dem Agent-Input an das Modell übergeben.

Eine Datei hochladen:

terminal
curl -X POST <webhook-url> \
  -H "X-Connic-Secret: <your-secret-key>" \
  -F "instructions=Wie hoch ist der Gesamtbetrag dieser Rechnung?" \
  -F "file=@/path/to/invoice.pdf"

Lade mehrere Dateien in einer einzigen Anfrage hoch:

terminal
curl -X POST <webhook-url> \
  -H "X-Connic-Secret: <your-secret-key>" \
  -F "message=Vergleiche diese beiden Dokumente" \
  -F "file1=@document1.pdf" \
  -F "file2=@document2.pdf"

Multipart-Anfragen landen in context["payload"] als normalisiertes Dictionary: Textteile stehen als Schlüssel auf oberster Ebene, Uploads unter files (die Bytes jeder Datei sind Base64-kodiert). Der für das LLM bestimmte content wird automatisch rekonstruiert: Jede Datei wird zu einem Binärteil; der führende Textteil ist die Payload, aus der lediglich files entfernt wurde.

payload shape
# context["payload"] innerhalb von middleware before()
{
  "customer_id": "12345",      # Multipart-Textfelder stehen auf der obersten Ebene
  "tag": ["a", "b"],           # Wiederholte Schlüssel werden in einer Liste gruppiert
  "message": "Verarbeite diese Rechnung",
  "files": [
    {
      "name": "invoice.pdf",     # ursprünglicher Dateiname
      "field_name": "file",      # Name des Formularfelds
      "mime_type": "application/pdf",
      "data": "<base64-bytes>",  # immer Base64-kodiertes ASCII
      "size": 12345              # Byte
    }
  ]
}

# Ausgelassene Dateien stehen unter "file_issues". Formularfelder bleiben
# auch dann verfügbar, wenn keine Datei akzeptiert wurde.

Pro Input sind bis zu 10 Dateien mit höchstens 10 MiB je Datei und 10 MiB insgesamt erlaubt. Sobald eine Datei das Größen- oder Anzahl-Limit überschreitet, bleiben zuvor akzeptierte Dateien erhalten; weitere Dateien werden nicht mehr angenommen. Formularfelder bleiben auch dann verfügbar, wenn keine Datei akzeptiert wurde. Nicht unterstützte MIME-Typen werden mit einer Begründung unter file_issues ausgelassen.

Bei Anhängen enthält die Antwort accepted, omitted und issues. Dateien sind standardmäßig optional. Mit Dateien erforderlich am Agenten-Link oder files_required: true in dessen Konfiguration schlägt der Run vor der Ausführung fehl, wenn eine Datei fehlt oder ausgelassen wurde. Die anschließende Input-Prüfung kann optionale Dateiinhalte auslassen, die ihr Prüfbudget überschreiten.

Unterstützte Dateitypen

Bilder

JPEG, PNG, GIF, WebP, HEIC/HEIF

Dokumente

PDF, Word, RTF, OpenDocument, EPUB, Klartext, HTML, Markdown

Daten & Office

CSV, TSV, JSON, XML, Excel, PowerPoint

Der Connector nimmt diese Typen an. Ob das Modell eine Datei lesen kann, hängt vom Modell ab: siehe Datei-Input für connic/*-Modelle.

Limit für die Anfragegröße: Maximal 16 MiB einschließlich Feldern, Dateien, Base64-Kodierung und Multipart-Overhead. Größere Anfragen werden vor der Verarbeitung mit HTTP 413 und request_too_large abgelehnt; der Absender muss eine kleinere Anfrage senden.

Authentifizierung

Schütze Webhooks mit Secret-basierter Authentifizierung. Inbound und Sync Webhooks erfordern dieses Secret standardmäßig. Deaktiviere Require Authentication nur, wenn sich Aufrufer nicht authentifizieren müssen.

Secret übermitteln

Jeder Webhook besitzt einen eindeutigen Secret Key, der beim Erstellen generiert wird. Ist Require Authentication aktiviert, lässt sich das Secret auf drei Arten übermitteln:

  • X-Connic-Secret Header (empfohlen) – Am sichersten; das Secret steht in den Headern
  • Authorization: Bearer Header – Standardmäßiger Bearer Token im OAuth-Stil
  • Query Parameter (?secret=...) – Weniger sicher; in Logs sichtbar
terminal
# X-Connic-Secret-Header verwenden (empfohlen)
curl -X POST <webhook-url> \
  -H "X-Connic-Secret: <your-secret-key>" \
  -d '{"message": "hallo"}'

# Authorization: Bearer-Header verwenden
curl -X POST <webhook-url> \
  -H "Authorization: Bearer <your-secret-key>" \
  -d '{"message": "hallo"}'

# Query-Parameter verwenden (weniger sicher)
curl -X POST "<webhook-url>?secret=<your-secret-key>" \
  -d '{"message": "hallo"}'

Absender prüfen

Manche Absender signieren ihre Anfragen, etwa mit einem HMAC-Signatur-Header oder einem JWT in Authorization. Jeder Webhook-Run enthält die ursprüngliche Anfrage in context["request"], damit Middleware die Signatur prüfen kann, bevor der Agent läuft: Methode, Header mit kleingeschriebenen Namen, Query-Parameter und den unveränderten Body als body_base64.

Aufbau der Anfrage
# context["request"] in Middleware, Tools und Hooks
{
    "method": "POST",
    "headers": {"content-type": "application/json", "x-hub-signature-256": "sha256=..."},
    "query": {},
    "body_base64": "eyJhY3Rpb24iOiJvcGVuZWQifQ=="
}

connic entfernt das eigene Secret (X-Connic-Secret, einen passenden Authorization-Header und den Query-Parameter secret) sowie Header, die das eigene Netzwerk hinzufügt. Der unveränderte Body ist bis 1 MiB und nicht bei Multipart-Anfragen enthalten; sonst ist body_omitted true. Die Run-Details zeigen den Body sowie die Header Authorization, Proxy-Authorization, Cookie und X-API-Key als [REDACTED]. Anders gestartete Runs, etwa erneute Runs und Tests, haben keine Anfrage.

Eine HMAC-Signatur prüfen, etwa X-Hub-Signature-256 von GitHub:

middleware/github-events.py
import base64
import hashlib
import hmac
import os

from connic import StopProcessing


async def before(content, context):
    request = context.get("request")
    if request is None:  # Nicht durch eine Webhook-Anfrage gestartet, etwa ein erneuter Run
        return content
    body = base64.b64decode(request.get("body_base64") or "")
    digest = hmac.new(os.environ["GITHUB_WEBHOOK_SECRET"].encode(), body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(f"sha256={digest}", request["headers"].get("x-hub-signature-256", "")):
        raise StopProcessing("Invalid signature", publish_outbound=False)
    return content

Ein signiertes JWT prüfen, etwa das Bot-Framework-Token, das Microsoft Teams sendet. Teams kann das connic-Secret nicht als Header senden, daher ?secret= an die URL des Messaging-Endpunkts anhängen.

middleware/teams-bot.py
# requirements.txt: PyJWT[crypto]
import asyncio
import os

import jwt
from connic import StopProcessing

keys = jwt.PyJWKClient("https://login.botframework.com/v1/.well-known/keys")


async def before(content, context):
    request = context.get("request")
    if request is None:  # Nicht durch eine Webhook-Anfrage gestartet, etwa ein erneuter Run
        return content
    token = request["headers"].get("authorization", "").removeprefix("Bearer ")
    try:
        key = await asyncio.to_thread(keys.get_signing_key_from_jwt, token)
        claims = jwt.decode(
            token, key.key, algorithms=["RS256"], audience=os.environ["MICROSOFT_APP_ID"],
            issuer="https://api.botframework.com", leeway=300,
        )
    except jwt.PyJWTError:
        raise StopProcessing("Invalid token", publish_outbound=False)
    if claims.get("serviceUrl") != context["payload"].get("serviceUrl"):
        raise StopProcessing("Invalid token", publish_outbound=False)
    return content
Die Prüfung läuft beim Start des Runs. Eine Anfrage, die sie nicht besteht, wird trotzdem angenommen und erzeugt einen Run, den die Middleware dann stoppt. Ein Token kann außerdem ablaufen, während sein Run in der Warteschlange wartet.

Fehlerantworten

401

Ungültiger Secret Key

Das angegebene Secret stimmt nicht überein. Prüfe die Authentifizierungseinstellungen.

404

Webhook nicht gefunden

Die Webhook URL existiert nicht. Prüfe, ob die URL korrekt ist.

400

Reiner Outbound Webhook

Dieser Webhook ist ausschließlich für outbound konfiguriert und kann nicht ausgelöst werden.