InstaTunnel
Navigationsmenu umschalten
Tutorial
19 min read
66 views

Ihre Agentenkarte benötigt eine öffentliche URL: A2A-Push-Benachrichtigungen auf localhost testen

Ihre A2A-Agentenkarte benötigt eine öffentliche URL. Lernen Sie, Push-Benachrichtigungen auf localhost mit einem stabilen Tunnel und SSRF-sicheren Webhook-Registrierungen zu testen.

IT
InstaTunnel Team
Published by the InstaTunnel team | Editorial policy
Ihre Agentenkarte benötigt eine öffentliche URL: A2A-Push-Benachrichtigungen auf localhost testen

Quick answer

Test A2A Push-Benachrichtigungen auf localhost (Agentenkarten-URL): quick comparison answer

Choose the tunnel tool based on the network model: public HTTPS URLs for webhooks and demos, private mesh access for internal apps, and managed infrastructure when policy controls matter most.

Which tunnel tool is best for public webhook testing?

Use a public HTTPS localhost tunnel with stable URLs. InstaTunnel focuses on webhook testing, demos, OAuth callbacks, and MCP endpoint workflows.

When should I choose a private network tool instead?

Choose a private mesh or Zero Trust tool when every user and service should stay inside a controlled private network.

Das Agent2Agent (A2A) Protokoll ist schnell gewachsen. Google kündigte es im April 2025 an, die Linux Foundation übernahm es im Juni 2025, und die stabile v1.0-Spezifikation ging am 12. März 2026 in die Veröffentlichung. Im August 2026 wurde es zu einem gehosteten Projekt der Agentic AI Foundation (AAIF). Zwei Bausteine sind für lokale Entwicklungen relevant. Push-Benachrichtigungen sind einfache Webhooks: Der Agentenserver sendet einen HTTP POST an eine URL, die der Client registriert hat. Die Agentenkarte ist ein JSON-Dokument, das von einem gut bekannten Pfad bereitgestellt wird.

Beide Hälften stoßen auf dieselbe Hürde auf einem Laptop. Remote-Clients können localhost nicht erreichen, und ein sorgfältig aufgebauter Agentenserver verweigert möglicherweise das POSTen dorthin. Dieser Leitfaden erklärt, warum, wie man A2A-Push-Benachrichtigungen von der eigenen Maschine durch einen öffentlichen Tunnel testet und wie man Webhooks registriert, ohne eine SSRF-Lücke zu öffnen.

Es geht um Agent-to-Agent-Callbacks und sichere Webhook-Registrierung. OAuth-Erkennung und Autorisierungsserver-Flows werden absichtlich übersprungen.

Wo A2A im November 2026 steht

  • v1.0 wurde am 12. März 2026 veröffentlicht. Der eigene Blog des Projekts und der Turing Post führen darauf hin, und im Mai wird ein v1.0.1-Patch erwähnt. Version 1.0 war die erste stabile, produktionsreife Spezifikation. Ihre protobuf-Definition, a2a.proto, ist die normative Quelle, aus der JSON-, gRPC- und REST-Formen generiert werden.
  • Governance in zwei Schritten. Google übergab A2A im Juni 2025 an die Linux Foundation. Am 17. August 2026 wurde es als gehostetes AAIF-Projekt angekündigt, dem der AAIF als Organ der Linux Foundation, der 2025 rund um MCP, goose und AGENTS.md gestartet wurde, angehört. Die Ankündigung beschreibt A2A als Wachstumsprojekt des AAIF. Die Berichterstattung fand zwischen dem 17. und 20. August statt. Es gab keinen Eigentümerwechsel. Google hatte die Spezifikation bereits übergeben, und jedes AAIF-Projekt behält eigene Maintainer und Release-Zeitpläne.
  • Das Ökosystem ist breit. Die Linux Foundation meldete zum einjährigen Projektstand mehr als 150 unterstützende Organisationen. Offizielle SDKs existieren für Python, Go, JavaScript, Java, .NET und Rust. Das JavaScript SDK (@a2a-js/sdk) erreichte am 22. Juli 2026 die allgemeine Verfügbarkeit 1.0.0, mit optionaler v0.3-Kompatibilität für gestaffelte Migrationen.
  • v1.0 definiert drei Standardprotokoll-Bindungen: JSON-RPC 2.0 über HTTP(S), gRPC und HTTP+JSON/REST.

Der praktische Schluss ist, dass die Spezifikation stabil genug ist, um Tooling- und Sicherheitsarbeiten zu investieren. Viele implementierte Agenten verwenden jedoch noch Pre-1.0-Kartenformen, prüfen Sie daher vor dem Test die Version jedes Peers.

Zwei öffentliche URLs, nicht eine

Der Titel sagt: „Ihre Agentenkarten benötigen eine öffentliche URL.“ Das trifft zu, aber nur die eine Hälfte eines lokalen A2A-Tests benötigt sie. Wenn Sie beide Hälften vermischen, entsteht viel Verwirrung.

1. Die Agentenkarten-URL (Serveradresse). A2A-Server veröffentlichen ihre Karte unter https://{server_domain}/.well-known/agent-card.json. Der gut bekannte Pfad folgt RFC 8615. Ältere Server nutzten oft /.well-known/agent.json, und Tools wie a2aops greifen bei Kartenprüfungen auf diesen Legacy-Pfad zurück.

Die Karte listet Endpunkte auf, die Clients aufrufen sollten, in supportedInterfaces. Dies ist ein geordentes Array, dessen erster Eintrag die bevorzugte Schnittstelle darstellt. Jeder Eintrag enthält eine url, einen protocolBinding (JSONRPC, GRPC oder HTTP+JSON) und eine protocolVersion, optional tenant. Die Spezifikation verlangt, dass eine Schnittstellen-URL in der Produktion eine absolute HTTPS-URL ist.

Wenn Ihr Server lokal läuft und Remote-Clients ihn erreichen müssen (gehosteter Orchestrator, Teamkollege, Cloud-Demo), müssen Karte und Schnittstellen-URLs öffentlich erreichbar sein.

2. Die Webhook-URL (Clientadresse). Push-Benachrichtigungen verlaufen in die andere Richtung. Der Client registriert einen Webhook, und der Server POSTet darauf. Entwickeln Sie den Client lokal und testen Sie gegen einen entfernten Agenten, benötigt Ihr Webhook eine öffentliche Adresse.

Wenn Sie zwei lokale Agenten betreiben, die über verschiedene Netzwerke kommunizieren, benötigen Sie beide: zwei stabile öffentliche Hostnamen.

Wie A2A-Push-Benachrichtigungen funktionieren

Push-Benachrichtigungen existieren auch für lang laufende Tasks (Minuten, Stunden oder Tage) und für Clients, die keine Streaming-Verbindung offen halten können. Der Agent kündigt Unterstützung mit capabilities.pushNotifications: true in seiner Karte an. Ist das Flag falsch oder fehlt, muss PushNotificationNotSupportedError zurückgegeben werden.

  1. Konfiguration registrieren. Der Client sendet eine TaskPushNotificationConfig inline im SendMessage-Request (unter configuration, mit leerer Task-ID) oder separat über die Erzeugung einer bestehenden Task. Die v1.0-Spezifikation definiert Create-, Get-, List- und Delete-Operationen. In JSON-RPC heißen sie CreateTaskPushNotificationConfig, GetTaskPushNotificationConfig, ListTaskPushNotificationConfigs und DeleteTaskPushNotificationConfig. In REST liegen sie unter /tasks/{id}/pushNotificationConfigs.
  2. Was die Konfiguration trägt. Sie enthält eine Webhook-URL (url), optional ein token zur clientseitigen Validierung und optionale authentication-Details (scheme und credentials), die dem Server mitteilen, wie er sich bei Ihrem Webhook authentifiziert. Außerdem enthält sie optional id und taskId.
  3. Der Server POSTet bei Statusänderungen. Der Body ist ein StreamResponse, dieselbe Form wie beim Streaming. Er enthält genau eines der Felder task, message, statusUpdate oder artifactUpdate.
  4. Ihr Empfänger überprüft es. Das im Normfall gezeigte Beispiel zeigt, dass der Server einen Authorization-Header sendet, der aus Ihren authentication-Einstellungen aufgebaut ist, plus X-A2A-Notification-Token, das das von Ihnen bereitgestellte token trägt.

Das Normieren der Details stimmt nicht immer überein, daher bauen Sie den Empfänger defensiv:

  • Die normative Textform nennt keinen Token-Header. Das gezeigte Beispiel verwendet X-A2A-Notification-Token. Andere Implementierungen verwenden sowohl X-A2A-Notification-Token als auch ein unpräfixiertes A2A-Notification-Token, also akzeptieren Sie beides.
  • In der Spezifikation werden zwei verschiedene Medienarten gemischt angezeigt: Einmal application/a2a+json und einmal application/json. Analysieren Sie den JSON-Body, ohne sich auf einen bestimmten Mediatype festzulegen.

Eine Registrierung sieht grob so aus. Es ist vereinfacht, also prüfen Sie die genaue Feldanordnung gegen a2a.proto für Ihre SDK-Version:

{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "CreateTaskPushNotificationConfig",
  "params": {
    "taskId": "task-123",
    "url": "https://a2a-client-dev.example.com/webhooks/a2a",
    "token": "per-task-secret-value",
    "authentication": { "scheme": "Bearer", "credentials": "webhook-credential" }
  }
}

Senden Sie die A2A-Version: 1.0-Header mit jeder Anforderung. Die Spezifikation verlangt, dass Clients dies senden, damit ein Upgrade des Agents später kein verhaltensänderndes Stillstehen verursacht.

Ein minimalistischer v1.0-Fragment einer Agentenkarte zeigt, wo die öffentliche Adresse lebt. Eine vollständige Karte benötigt zusätzlich defaultInputModes, defaultOutputModes und skills:

{
  "name": "Flight Booking Agent",
  "description": "Handles flight reservations.",
  "version": "1.0.0",
  "supportedInterfaces": [
    {
      "url": "https://a2a-agent-dev.example.com/a2a",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    }
  ],
  "capabilities": { "streaming": true, "pushNotifications": true }
}

Was die Spezifikation von Sendern und Empfängern verlangt

  • Server müssen mindestens einmal versuchen zu liefern und können mit exponentiellem Backoff erneut versuchen. Sie sollten eine Webhook-Timeout von ca. 10–30 Sekunden verwenden und nach wiederholtem Fehlschlagen stoppen.
  • Empfänger müssen mit einem 2xx-Status antworten, um die Lieferung zu bestätigen, sollten idempotent arbeiten, da Duplikate auftreten können, und müssen prüfen, ob die Task-ID zu einer erwarteten Task gehört.
  • A2A’s asynchroner Leitfaden besagt, dass nach der Verifizierung der Authentizität einer Benachrichtigung der Client typischerweise GetTask mit der Task-ID der Benachrichtigung aufruft, um den vollständigen, aktuellen Zustand abzurufen. Behandle die Payload als Trigger und hole die Task erneut ab, bevor du etwas Wichtiges machst.

Warum localhost A2A Push-Benachrichtigungen scheitern

Drei eigenständige Fehler verstecken sich hinter dem Spruch „Es funktioniert auf meinem Rechner“.

Die Karte bewirbt eine Adresse, die niemand sonst erreichen kann. Viele Frameworks bauen die Karte aus der Bind-Adresse, sodass die Karte http://localhost:8000/a2a aussagt. Ein Remote-Client holt sich die Karte (falls er überhaupt darauf zugreifen kann) und folgt supportedInterfaces[0].url zu seiner eigenen Loopback-Schnittstelle. Die Lösung ist, die öffentliche Basis-URL des Servers explizit zu setzen, damit die Karte den Tunnel-Hostname widerspiegelt.

Der Agent kann Ihren Webhook nicht erreichen. Falls Ihr Webhook http://localhost:9000/hook ist, löst der Remote-Agent ihn auf sich selbst auf und es kommt nichts an.

Ein gut gebauter Server verweigert den Versuch. Die Spezifikation sagt, dass Server nicht blind an eine clientseitig bereitgestellte URL POSTen sollten, da dies SSRF- und DDoS-Verstärkungsangriffe ermöglicht. Reale Implementierungen reagieren unterschiedlich:

  • Die Rust-Bibliothek a2a-protocol-server (0.15.0) validiert Webhook-URLs sowohl bei der Config-Erstellung als auch bei der Lieferung. Sie lehnt Loopback-, private- und link-local-Ziele ab, ebenso wie localhost, .local und .internal-Namen. Der Escape-Hatch allow_private_urls() ist als Testzweck dokumentiert und dient dem Deaktivieren des SSRF-Schutzes.
  • Ein PR gegen das offizielle Python SDK (#1164) beschreibt zwei verbleibende Risiken. DNS-Rebinding zwischen Validierung und POST bleibt möglich, weil Lookup und Verbindung den Namen getrennt auflösen. Ein Reviewer merkte auch an, dass Redirects nicht erneut validiert werden, sodass der HTTP-Client follow_redirects=False beibehalten muss.

Ob localhost als Webhook funktioniert, hängt von der SDK-Version Ihres Servers ab. Wenn es klappt, passiert dies, weil der Schutz fehlt. Das Deaktivieren des Schutzes, damit 127.0.0.1 funktioniert, führt zu einem Codepfad, den Sie in der Produktion nie ausführen würden. Ein öffentlicher Tunnel gibt Ihrem Webhook eine echte, global routbare HTTPS-Adresse, die dieselbe Validierung durchläuft wie ein Produktionsendpunkt.

Der Sicherheitskontext: Webhook-SSRF

Der Webhook ist per Definition Eingabe, die vom Angreifer beeinflusst werden kann. Wer eine Push-Konfiguration registriert, bestimmt, wohin Ihr Server HTTP-Anfragen sendet. Tyks Sicherheitsleitfaden (Juni 2026) bezeichnet die Webhook-URL als eigene Angriffsfläche, mit SSRF, falls ausgehende Ziele nicht auf einer Allowlist stehen, und Spoofing, falls der Empfänger Benachrichtigungen nicht authentifiziert.

Die A2A-Dokumentation listet Maßnahmen auf: Allowlisting vertrauenswürdiger Domains, Besitznachweis (Challenge-Response) und Netzwerkkontrollen wie Ausgungs-Firewalls. Für Empfänger heißt es, der Endpunkt muss sicherstellen, dass Benachrichtigungen wirklich vom legitimen Server kommen, mithilfe von Signaturen, Tokens oder dem registrierten token. Außerdem sollten Benachrichtigungen einen Zeitstempel tragen, um veraltete zu verweigern, und eindeutige IDs für wichtige Ereignisse, um Replays zu erkennen. Die Dokumentation beschreibt auch einen optionalen JWT-plus-JWKS-Flow.

Die Apache Camel-Advisory zeigt, wie ein Validator falsch arbeiten kann:

  • CVE-2026-71569 (Apache Camel, veröffentlicht 29. Oktober 2026). Der WebhookUrlValidator der Komponente camel-a2a klassifizierte Hosts an zwei Stellen, die nicht übereinstimmten. Ein Host als IP-Literal schrieb, wurde gegen Präfixe gematcht, die fc00::/7 einschließen. Ein Name, der aufgelöst wurde, wurde mit JDK-Prädikaten geprüft; diese decken fc00::/7 nicht ab. Ein Name, der zu fc00::/7 auflöste, passte durch eine Firewall.
  • Der Dispatcher sandte auch jeden konfigurierten Authorization-Header an diese Adresse. Der Angreifer liefert Schema und Credentials, sodass dies kein Leck der Secrets des Opfers ist.
  • Betroffen sind Versionen von 4.21.0 bis einschließlich 4.21.x; Fixes erscheinen in 4.22.2 und 4.23.0; 4.21.x-Linie ist End-of-Life ohne Fix. Die Komponente wurde 4.21.0 eingeführt und ist als Preview gekennzeichnet.
  • Die Anfrage ist blind, da die Antwort dem Anfragenden nicht zurückgegeben wird. Exploitation erfordert zusätzlich, dass der Name zu fc00::/7 auflöst, ein HTTPS-Dienst dort lauscht und ein gültiges TLS-Zertifikat für Ihren Hostname präsentiert wird.
  • Der Vorab-Check war auch falsch in die andere Richtung: Er matchte den rohen Host-String, ohne zuerst zu prüfen, ob es sich um ein IP-Literal handelt, sodass legitime Namen wie fcm.googleapis.com blockiert wurden.
  • Die Behebung klassifiziert Adressen aus Rohbytes in einem gemeinsamen Klassifikator. Sie umfasst fc00::/7, 100.64.0.0/10, sowie IPv4-kompatible, NAT64 und 6to4-Adressen. Der Hersteller empfiehlt, Authentifizierung vor den Push-Config-Pfad zu setzen und ausgehenden Traffic zu fc00::/7 zu verweigern. Die Lehre lautet: Jeder Codepfad muss denselben Klassifikator verwenden.
  • Das offizielle Python SDK. PR #1164 benennt zwei verbleibende Risiken: DNS-Rebinding zwischen Validierung und POST bleibt möglich; Redirects werden nicht erneut validiert, daher follow_redirects=False beizubehalten.

Eine SSRF-sichere Webhook-Registrierung-Checkliste

Wenn Sie einen A2A-Server bauen oder betreiben, validieren Sie in Schichten:

  1. Nur HTTPS. Ablehnen andere Schemata und URLs mit eingebetteten Credentials. Einige SDK-Sicherheitsmechanismen erlauben auch http. Für die Produktion entsprechend einschränken.
  2. Ports einschränken. 443 zulassen, außer Sie haben einen dokumentierten Grund.
  3. Auflösen und klassifizieren Sie jede Adresse. Eine falsche Antwort reicht, um die gesamte URL scheitern zu lassen. Die Auflösung deckt dezimale, hexadezimale und oktale Host-Schreibweisen ab; entpacke IPv4-zu-IPv6-mapped, NAT64 und 6to4-Adressen, bevor du klassifizierst, und stelle sicher, dass fc00::/7 und 100.64.0.0/10 abgedeckt sind.
  4. Validieren bei Registrierung und Lieferung. Configs können via Inline-Requests oder über dedizierte Operationen ankommen; DNS kann sich ändern.
  5. Schließe das Rebinding-Fenster. Wenn der HTTP-Client es zulässt, verbinde dich mit der validierten Adresse und behalte den ursprünglichen Hostname für TLS und den Host-Header bei. Die Rust-Crate geht hier anders vor. Sie pinnt die IP nicht; Rebinding auf private Adressen kann TLS-Handshakes fehlschlagen, da kein gültiges Zertifikat vorliegt.
  6. Kein Redirect-Following bei Push-Lieferung.
  7. Eigentum verifizieren mit einer Challenge, bevor echte Ereignisse gesendet werden.
  8. Kein Anhäufen von Credentials an unbestätigte Ziele. Füge einen ausgehenden Proxy oder eine Netzwerkrichtlinie hinzu.
  9. Header-Injektion ablehnen. Verwerfe CR- oder LF-Zeichen in token und authentication vor dem Einfügen in Header.

Ein Python-Starthilfe für Schritte 1 bis 3 folgt. Ich habe es mit Python 3.13 getestet. Es lehnt Loopback-, private-, link-local-, CGNAT- und unique-local-Ziele, integer-kodierte Hosts, localhost, IPv4-zu-IPv6-getauschte und IPv4-kompatible IPv6, NAT64 und 6to4-Adressen, die privaten IPv4 kapseln, ab. Es akzeptiert öffentliche Hosts. Die is_global-Regeln von Python haben sich zwischen Versionen geändert, testen Sie also mit Ihrer Version neu.

import ipaddress
import socket
from urllib.parse import urlsplit

ALLOWED_PORTS = {443}
NAT64 = ipaddress.ip_network("64:ff9b::/96")


def unwrap(ip):
    """Return the IPv4 hidden inside an IPv6 address, if there is one."""
    if isinstance(ip, ipaddress.IPv6Address):
        if ip.ipv4_mapped:                      # ::ffff:a.b.c.d
            return ip.ipv4_mapped
        if ip in NAT64:                         # 64:ff9b::/96
            return ipaddress.IPv4Address(int(ip) 6 0xFFFFFFFF)
        if ip.sixtofour:                        # 2002::/16
            return ip.sixtofour
        if int(ip)  32 == 0 and int(ip)  1:  # deprecated ::a.b.c.d
            return ipaddress.IPv4Address(int(ip) 6 0xFFFFFFFF)
    return ip


def check_webhook_url(url: str) -e list[str]:
    parts = urlsplit(url)
    if parts.scheme != "https" or not parts.hostname:
        raise ValueError("webhook must be an https URL with a host")
    if parts.username or parts.password:
        raise ValueError("credentials in the URL are not allowed")
    try:
        port = parts.port or 443
    except ValueError:
        raise ValueError("invalid port")
    if port not in ALLOWED_PORTS:
        raise ValueError("port not allowed")

    public_ips = []
    for *_, sockaddr in socket.getaddrinfo(parts.hostname, port, type=socket.SOCK_STREAM):
        ip = ipaddress.ip_address(sockaddr[0].split("%")[0])
        # is_global rejects private, loopback, link-local, unique-local and CGNAT.
        if not unwrap(ip).is_global:
            raise ValueError(f"{ip} is not a public address")
        public_ips.append(str(ip))
    return public_ips  # connect to one of these, not to a fresh DNS lookup

Auf der Empfangsseite vergleichen Sie das Token in konstanter Zeit, akzeptieren beide Header-Schreibweisen, antworten schnell und holen den Zustand separat ab. Ich habe diesen FastAPI-Handler getestet. Er gibt 401 zurück, wenn Token fehlt oder falsch ist, und 200 für beide Header-Namen:

import hmac
import os

from fastapi import FastAPI, Header, HTTPException, Request

app = FastAPI()
EXPECTED = os.environ["A2A_WEBHOOK_TOKEN"]


@app.post("/webhooks/a2a")
async def a2a_webhook(
    request: Request,
    x_a2a_notification_token: str = Header(default=""),
    a2a_notification_token: str = Header(default=""),
):
    token = x_a2a_notification_token or a2a_notification_token
    if not hmac.compare_digest(token.encode(), EXPECTED.encode()):
        raise HTTPException(status_code=401)
    event = await request.json()  # accepts application/json or application/a2a+json
    # enqueue event; re-fetch the task with GetTask before acting on it
    return {"received": True}

Wenn Ihr Server auch einen Authorization-Header aus authentication sendet, überprüfen Sie ihn ebenfalls. Das Token beweist nur, dass der Sender ein per-Task-Geheimnis kannte.

Tests von A2A-Push-Benachrichtigungen auf localhost mit einem Tunnel

Ein Tunnel verleiht Ihrem lokalen Port einen öffentlichen HTTPS-Hostnamen, damit Sie den echten Ablauf durchführen können. Jedes Tunneling-Tool funktioniert. Wichtige Eigenschaften sind HTTPS, ein stabiler Hostname und Unterstützung für einfache, nicht-interaktive POST-Anfragen.

Schritt 1: Einen stabilen Hostnamen reservieren. Zufällige URLs pro Sitzung stören A2A-Tests. Clients cachen Karten; die Spezifikation verlangt das Senden von Cache-Control- und ETag-Headern und Clients, diese zu respektieren. Registrierte Push-Konfigurationen halten Ihre Webhook-URL. Wenn der Hostname sich ändert, zeigen sie auf Nichts.

Ein Wegwerf-Tunnel ist für einen ersten Smoke-Test ausreichend. cloudflared tunnel --url http://localhost:8000 erzeugt eine zufällige trycloudflare.com-URL ohne Konto. Cloudflare beschreibt mehrere Limits für diese Quick Tunnels:

  • Es gibt keine Betriebszeitgarantie.
  • Jeder Tunnel unterstützt bis zu 200 gleichzeitige Anfragen; zusätzliche Anfragen führen zu 429.
  • Der Hostname ändert sich jedes Mal.
  • Server-Sent Events werden nicht unterstützt. A2A-Streaming verwendet SSE; Quick Tunnels können Push-Webhooks und einfache Request/Response-Aufrufe tragen, aber kein Streaming testen.
  • Quick Tunnels funktionieren nicht, wenn eine config.yaml in ~/.cloudflared existiert.
  • Quick Tunnels haben jetzt ein optionales --allowed-mail-Flag, das die URL hinter einer E-Mail-Einmal-PIN sperrt. Cloudflare sagt, es brauche eine interaktive Browser-Session und unterstützt keine nicht interaktiven Clients. Ein Agenten-Server, der an Ihren Webhook postet, kann dies nicht abschließen. Deaktivieren Sie dies für A2A-Callbacks.

Für alles Iterative verwenden Sie einen benannten Tunnel oder eine Subdomain eines anderen Anbieters.

Schritt 2: Lassen Sie die Karte die öffentliche Adresse anzeigen. Konfigurieren Sie die öffentliche Basis-URL Ihres Agents über eine Umgebungvariablen und erstellen Sie die Karte daraus neu. Prüfen Sie sie dann außerhalb Ihres Netzwerks:

curl -s https://a2a-agent-dev.example.com/.well-known/agent-card.json | jq '.supportedInterfaces'

Sie sollten den Tunnel-Hostnamen sehen, nicht localhost. Wenn ein Peer eine Pre-1.0-Kartenform verwendet, zeigt a2aops compat <base-url> eine Migration von v0.x zu v1.0 an. Es ist ein kleines Drittanbieter-Beta-Tool; behandeln Sie dessen Ausgabe als Hinweis.

Schritt 3: Tunnel den Webhook-Empfänger. Führen Sie den Empfänger oben auf eigenem Port mit eigenem öffentlichen Hostnamen oder einem Pfad-gerichteten aus.

Schritt 4: Registrieren und Triggern. Erstellen Sie die Push-Konfiguration für eine lang laufende Aufgabe, dann starten Sie die Aufgabe. Beobachten Sie den Request-Inspektor des Tunnels (die meisten Tools bieten ihn) auf die genauen Header und den Body, die der Server sendet.

Schritt 5: Führen Sie die negativen Tests aus. Diese sind genauso wichtig wie der positive Pfad:

  • Registrieren Sie https://127.0.0.1/hook und https://localhost/hook. Ein gehärteter Server sollte beide ablehnen.
  • Registrieren Sie einen Hostnamen, den Sie kontrollieren und der auf eine private Adresse auflöst, sowie einen dezimal kodierten Loopback-Host wie https://2130706433/hook. Beide sollten abgelehnt werden.
  • Senden Sie eine Anfrage mit falschem oder fehlendem Token. Ihr Empfänger sollte 401 zurückgeben.
  • Wiederholen Sie eine alte Benachrichtigung. Ihr Empfänger sollte sie als veraltet oder Duplikat ablehnen.
  • Geben Sie beim Empfänger einmal eine 5xx-Antwort zurück und bestätigen Sie, dass der Server erneut versucht. Dann geben Sie 401 zurück und sehen, ob es stoppt. Retry-Verhalten variiert; die Rust-Crate versucht nur 408, 429 und 5xx-Antworten erneut.

Häufige Fallstricke

  • Karten- und Tunnel-Drift. Starten Sie den Tunnel neu, ändert sich der Hostname, und die Karte (und jede gespeicherte Push-Konfiguration) bewahrt den alten.
  • Pre-1.0-Karten. Ein Peer kann /.well-known/agent.json oder ein älteres Schema bedienen. v1.0 führte breaking changes ein, darunter eine einheitliche Part-Struktur, umbenannte Methoden und neue Feldtypen in der Karten-Schnittstelle.
  • Public Tunnel, public Agent. Ein Tunnel setzt Ihren Entwicklungsserver dem Internet aus. Legen Sie keine Secrets in der Karte ab, setzen Sie keine Produktionsdaten hinter einem Developer-Agenten ein, und schließen Sie den Tunnel, wenn Sie fertig sind.
  • Langsame Webhook-Handler. Bestätigen Sie zügig und verarbeiten Sie asynchron. Die Rust-Crate setzt standardmäßig einen 10-Sekunden-Timeout; die Spezifikation empfiehlt 10–30 Sekunden. Ein langsamer Handler führt zu Retries und Duplikatlieferungen.
  • Gemeinsame Tokens. Verwenden Sie für jede Push-Konfiguration ein eindeutiges, zweckgebundenes Token.

FAQs

Muss eine A2A-Agentenkarte eine öffentliche URL haben? Ja, damit remote Clients sie finden können. Sie wird unter /.well-known/agent-card.json auf der Domain des Agents bereitgestellt; die internen Schnittstellen-URLs müssen erreichbar sein. Karten können auch aus einem Registry bezogen oder direkt konfiguriert werden.

Warum lehnt mein A2A-Server meinen localhost Webhook ab? Wahrscheinlich ist SSRF-Schutz aktiv. Gehärtete Server blockieren private, Loopback- und Link-Local-Ziele standardmäßig. Verwenden Sie stattdessen einen öffentlichen HTTPS-Tunnel, statt den Guard zu deaktivieren.

Welcher Header trägt das A2A Push-Benachrichtigungstoken? Das im Beispiel gezeigte Header-Beispiel verwendet X-A2A-Notification-Token, befüllt mit dem bei der Registrierung angegebenen token. Die normative Textstelle nennt keinen Header; einige Implementierungen senden auch A2A-Notification-Token, daher sollten Sie beide akzeptieren.

Kann ich A2A-Streaming über einen Cloudflare Quick Tunnel testen? Nein. Cloudflare bescheinigt, dass Quick Tunnels keine Server-Sent Events unterstützen, die von A2A-Streaming verwendet werden. Push-Webhooks funktionieren jedoch.

Ist A2A stabil genug, um darauf aufzubauen? v1.0 ist die aktuelle stabile Spezifikation, governed durch die Linux Foundation und gehostet vom AAIF seit August 2026. SDKs und Integrationen reifen weiter; testen Sie die Versionunterstützung, optionale Fähigkeiten und Authentifizierung End-to-End mit jedem Peer.

Kernpunkte

  • Ein lokaler A2A-Test kann zwei öffentliche Adressen benötigen: Die Karten-Schnittstellen-URL für den Server und die Webhook-URL für den Client.
  • Ob ein localhost-WebHook funktioniert, hängt von der SDK-Version Ihres Servers ab. Gehärtete Server verweigern private Ziele, und ein Tunnel testet den realistischen Pfad, bei dem das Deaktivieren des Guards nicht funktioniert.
  • Webhook-Registrierung ist eine SSRF-Schnittstelle. Lösen und klassifizieren Sie jede Adresse mit einem gemeinsamen Klassifikator, validieren Sie bei Registrierung und Lieferung, entscheiden Sie, wie Sie das Rebinding-Fenster schließen, und verweigern Sie Redirects.
  • Verwenden Sie einen stabilen Tunnel-Hostname, authentifizieren Sie jede Benachrichtigung, behandeln Sie die Payload als Trigger, um GetTask aufzurufen, und führen Sie die negativen Tests durch.

Quellen

Continue from this article into the most relevant product guides and workflows.

Related Topics

#A2A protocol#agent2agent protocol#A2A push notifications#A2A webhook#A2A agent card#agent card public URL#agent card well-known path#.well-known/agent.json#A2A localhost testing#test A2A locally#A2A v1.0#A2A Linux Foundation#Agentic AI Foundation#agent to agent communication#agent-to-agent callbacks#AI agent interoperability#multi-agent systems#AI agent webhooks#webhook testing localhost#webhook SSRF#SSRF prevention#SSRF-safe webhooks#webhook registration security#A2A security#AI agent security#webhook security best practices#localhost tunneling#expose localhost to internet#localhost public URL#stable public URL for localhost#static tunnel URL#persistent tunnel URL#ngrok alternative#Cloudflare Tunnel#localtunnel#tunneling tools comparison#local development tunnel#webhook tunnel#HTTPS tunnel localhost#reverse tunnel#developer infrastructure#cloud-native development#DevOps tools#agentic AI development#AI agent development#build AI agents#A2A server setup#A2A client example#A2A SDK#A2A task streaming#A2A server-sent events#long-running agent tasks#async agent notifications#webhook callback URL#webhook signature verification#allowlist webhook URLs#private IP blocking#MCP vs A2A#agent discovery#InstaTunnel

Keep building with InstaTunnel

Read the docs for implementation details or compare plans before you ship.

Share this article

More InstaTunnel Insights

Discover more tutorials, tips, and updates to help you build better with localhost tunneling.

Browse All Articles