Tutorial
A2A-1.0-Agent-Card-JSON in der Praxis: Fähigkeitsangaben, Skill-Form und Cross-Agent-Daten prüfen
Scheitert die Prüfung, zuerst die Schicht nennen: es parst, es passierte das generierte Schema, oder es traf die Pflichtfelder der Spec.
Der letzte Text, der Discovery-Ablauf, ist well-known, Katalog, dann Card zu Ende gegangen. Wie die Felder geschrieben werden, steht im früheren Agent-Card-Feldtutorial. Heute füllen wir keine Felder nach und gehen keine Hops erneut. Ihr haltet schon eine Karte, oder habt gerade eine GET. Die Frage: wie behauptet ihr, sie sei legal, und wird der Task, den ihr schickt, als Müll behandelt? Der Text steht in der A2A-1.0-Spezifikation §4.4 und §3.3.4. Das a2a.json der Site sagt es selbst: ein nicht-normatives JSON-Schema-Bündel aus Proto. Der Zug 0.3 → 1.0 steht unter was in v1.0 neu ist.
Grün ist kein Pass
Das generierte Bündel in Ajv werfen, auf die Wurzel zeigen, Grün sehen — der häufigste falsche Pass in der Review. Die Wurzel ist keine Card. AgentCard, AgentSkill, Task und Message leben unter $defs. Die Bundle-Wurzel zu prüfen prüft nichts. Der richtige Zeiger ist #/$defs/AgentCard. Verkehr nutzt #/$defs/Task oder #/$defs/Message. Wickelt einen Task nicht in das Card-Schema.
Selbst mit richtigem Zeiger fehlt dem generierten Bündel oft required. Die September-2026-Kopie von AgentCard und AgentSkill auf der Site setzt additionalProperties: false, listet die Pflichtfelder der Spec-Tabelle aber nicht. Ein leeres name, ein Skill ohne tags, kann trotzdem grün werden. Quelle der Pflicht ist die Spec-Tabelle: name, description, version, supportedInterfaces, capabilities, defaultInputModes, defaultOutputModes, skills. Jeder Skill braucht weiter id / name / description / tags.
Also mindestens zweimal prüfen. Erster Durchlauf: es parst, und das generierte AgentCard explodiert nicht an Extra-Keys. Zweiter: die Spec-Tabelle behauptet Nicht-Leer. Nur der erste fängt eine 0.3-Rest-url oben über additionalProperties: false; ein Skill ohne Tags rutscht durch. Nur der zweite, ohne Bündel, verpasst ein verirrtes inputSchema. Ihr braucht beide.
| Diese Schicht | Was sie fängt | Was sie verpasst |
|---|---|---|
| JSON.parse | Kaputte Syntax, Abbruch, trailing commas | Ob die Form stimmt |
Generiertes #/$defs/AgentCard | 0.3-Top-Level-url, inputSchema am Skill | Ob Spec-Pflichtfelder geschrieben wurden |
| Pflichtfelder §4.4 | Leeres name, fehlende tags, leere skills | Ob Flags zur Operation passen, die ihr senden wollt |
Vier Schichten, jede fängt eine Fehlerklasse
Schicht drei sind Fähigkeitsflags. Spec §3.3.4 ist klar: streaming falsch und ihr abonniert trotzdem — der Agent MUSS UnsupportedOperationError liefern. pushNotifications falsch und trotzdem Webhook: PushNotificationNotSupportedError. extendedAgentCard falsch und trotzdem erweiterte Karte: dieselbe Klasse. Schema grün, Pflicht da, der nächste Hop kann trotzdem zurückwerfen. Das Fixture muss „Karte legal“ und „diese Operation ist durch Flags erlaubt“ in zwei Schritten schreiben.
Schicht vier ist Verkehr. Ihr sendet einen Task oder eine Message. Ihr POSTet die Card nicht erneut. InvalidAgentResponseError betrifft die Antwortform, nicht die Visitenkarte. MIME muss defaultInputModes oder inputModes des Skills treffen; ein Treffer daneben ist ContentTypeNotSupportedError. Prüft einen A2A-Skill nicht mit MCP-inputSchema. Hinweise in 1.0 sind examples und MIME.
Das generierte Bündel trägt auch snake_case-patternProperties (supported_interfaces, default_input_modes). Spec-JSON ist camelCase. Neue Karten folgen der Spec-Tabelle. Nimmt CI beide Schlüsselsätze, wird Diff zuerst schmutzig. Kopiert Proto-Feldnamen nicht auf eine öffentliche Karte, außer ihr betreibt bewusst eine Kompatibilitätsschicht und das Fixture sagt das.
Die Card: auf AgentCard zeigen, nicht auf die Bundle-Wurzel
Pinnt eine Kopie von a2a.json ins Repo, ausgerichtet an einer veröffentlichten Bundle-Version. CI soll keine treibende latest-URL treffen. Ajv (oder jede 2020-12-Implementierung) bekommt Schema-Zeiger #/$defs/AgentCard. Die Instanz ist die gerade geholte Karte oder agent-card.json im Repo. Gebt path und keyword aus. Passt der Pfad nicht zum Fixture, verdächtigt zuerst den Zeiger, dann die Karte.
Der wertvollste Reject im ersten Durchlauf ist ein Extra-Key. In 1.0 sitzt der Endpoint in supportedInterfaces. Eine restliche Top-Level-url, protocolVersion oder supportsAuthenticatedExtendedCard wird unter additionalProperties: false rot. Das ist 0.3-Rest, nicht „mehr Felder, sicherer“. Das Feldtutorial hat den Umzug geschrieben. Heute nur: der Validator muss diese Schlüssel als Fehler markieren, nicht ignorieren.
Jedes Interface braucht drei Checks: Produktions-url ist absolutes HTTPS (gRPC ist host:port), protocolBinding spricht der Client, protocolVersion ist eine Protokollversion wie 1.0 — nicht die eigene version des Agenten. Beide heißen version. Das Fixture muss sie getrennt behaupten. Der erste Eintrag ist bevorzugt. Kein gemeinsames Binding, kein Gespräch.
Skills: die Spec verlangt Felder, die das Schema oft überspringt
Generiertes AgentSkill hat oft ebenfalls kein required. Ein Skill ohne tags kann in Ajv grün sein und trotzdem eine leere Suchfläche haben — der Discovery-Text hat das gesagt. Heutige Behauptung: jeder Skill hat nicht-leeres id, name, description und mindestens ein Tag. Ein leeres skills-Array fällt durch die Spec-Tabelle. Ein NO_SPEC-Nur-Host-Eintrag soll vor der Registrierung rot werden, nicht nachdem ein Keyword-Hop ins Leere trifft.
Ein Skill darf kein inputSchema tragen. additionalProperties: false behandelt es als Extra-Key. Das gehört zu MCP-Tools; siehe den Schema-Text auf der Site. Ein 1.0-Skill zeigt examples und MIME. Eine Funktionsparametertabelle in die Karte gießen — der erste Durchlauf soll scheitern. Scheitern bei der Prüfung ist billiger als Klären nach dem Task.
Die Karte darunter soll auf Durchlauf eins oder zwei rot werden. Sie ist kein „fast nutzbarer“ Entwurf. Sie mischt eine 0.3-Top-Level-url, einen Skill ohne Tags und ein MCP-inputSchema. Diff neben Returns Specialist im Repo. Die drei Roten sollen auf drei Pfade fallen.
{
"name": "Returns Specialist",
"description": "Classifies return requests.",
"version": "1.0.3",
"url": "https://agents.example.com/returns/a2a",
"protocolVersion": "1.0",
"supportedInterfaces": [
{
"url": "https://agents.example.com/returns/a2a",
"protocolBinding": "JSONRPC",
"protocolVersion": "1.0"
}
],
"capabilities": {
"streaming": true
},
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
"skills": [
{
"id": "classify-return",
"name": "Classify a return",
"description": "Decide the request type.",
"inputSchema": {
"type": "object",
"required": ["orderId"],
"properties": {
"orderId": { "type": "string" }
}
}
}
]
}
| Prüfung | Wie Scheitern aussieht | Nächster Hop |
|---|---|---|
| Parse + AgentCard-Zeiger | Trailing comma; Top-Level-url; Skill-inputSchema | JSON reparieren / 0.3-Schlüssel streichen |
| Spec-Pflicht / nicht leer | Leeres name; Skill ohne tags; leere skills | Felder aus §4.4 füllen |
| Flags vs Operation | Abonnieren bei streaming false; undeklarierte erweiterte Karte holen | Client ändern oder Card-Flags ändern |
Verkehr: ein Task ist keine Visitenkarte
Erst wenn die Card durch ist, message/send. Der Body folgt dem Binding — JSON-RPC, gRPC oder HTTP+JSON. Das Geschäftsobjekt darin ist Message oder Task, kein AgentCard. Eine Anfrage gegen die Card-Definition prüfen scheitert sinnlos. Das generierte Bündel hat eigene Task-, Message-, Part- und Artifact-Defs. Verkehrs-Fixtures wechseln den Zeiger. Die Card-Zeile nicht wiederverwenden.
Die Antwort auch prüfen. Die Spec faltet eine nicht konforme Agent-Antwort in InvalidAgentResponseError. Die Zustandsmaschine ist submitted / working / completed / failed / canceled / rejected plus unterbrochenes input-required und auth-required. Nur completed als Erfolg zu sehen macht „bitte einen Satz mehr“ zum Störschein. Diese Schlüssel stehen nicht auf der Card. Discovery geklappt, Gespräch gescheitert — der Schein muss die Schicht nennen.
Das JSON darunter ist ein Prüfbericht-Fixture, kein offizielles Katalog- oder A2A-RPC. Es faltet die vier Schichten in ein Objekt, damit ihr es neben der Repo-Card und einer message/send-Anfrage diffen könnt. Signaturprüfungen behaupten nur die Form: jedes signatures[]-Item braucht protected und signature (RFC-7515-JWS). Echte Schlüssel und echte Verify bleiben in einer Security-Review. Keinen Private Key ins Fixture.
{
"kind": "card-validation-report",
"note": "CI/review fixture — not an official A2A RPC",
"target": "agent-card.json",
"schema": {
"bundle": "https://a2a-protocol.org/latest/spec/a2a.json",
"pointer": "#/$defs/AgentCard",
"normative": false
},
"parse": true,
"schemaPass": false,
"schemaErrors": [
{ "path": "/url", "keyword": "additionalProperties" },
{ "path": "/skills/0/inputSchema", "keyword": "additionalProperties" }
],
"specChecks": [
{ "id": "required-name", "pass": true },
{ "id": "skills-tags-nonempty", "pass": false },
{ "id": "no-top-level-url", "pass": false }
],
"capability": {
"streaming": true,
"clientWillStream": true,
"ok": true
},
"next": "fix-card"
}
Signaturen, Fixtures, lokale Diffs
Die Spec erlaubt signatures in RFC-7515-Form. Ist das Array da, zuerst die zwei Pflichtstrings als nicht leer behaupten, dann entscheiden ob verifiziert wird. Kein Array macht die Karte nicht illegal — das Feld ist optional. Die öffentliche Karte so schreiben, als würde sie abgeholt. Kein statisches Geheimnis, kein Intranetpasswort in die Card. Eine erweiterte Karte folgt der Sitzung. Keinen gemeinsamen „schon geprüft“-Cache mit der öffentlichen Karte.
Schüttet kein Plugin-SKILL.md und kein MCP-tools/list in dieselbe Card-Prüfung. Skills in der Box gehören zu einem Coding-Agenten in diesem Repo. Die Selbstbeschreibung des anderen Teams ist die Card. Beides in eine capability.json pressen, und drei gescheiterte Schichten landen in derselben Ticketzeile.
Im Browser fertig: JSON formatieren, ob Karte und Bericht parsen; JSON-Schema prüfen, das offizielle Bündel auf AgentCard zeigen, dann den Zeiger für einen Task wechseln; JSON Diff, legale Karte gegen rote Karte, Extra-Keys und fehlende Tags fangen. Daten bleiben auf diesem Rechner. Weiterlesen: das Agent-Card-Feldtutorial und der Discovery-Ablauf. Was ein Katalog ist: der Registry-Überblick.
Verwandt: A2A Agent Card JSON Schema, Wie Agenten einander finden, Google Agent Registry.
FAQ
Ajv wurde grün auf a2a.json. Brauche ich den zweiten Durchlauf noch?
Ja. Das Site-Bündel nennt sich nicht-normativ, und generierte Defs lassen required oft weg. Die Spec-Tabelle ist die Pflichtquelle. Grün heißt nur: keine Extra-Keys und Typen getreten.
Kann ein Schema Card und Task prüfen?
Nein. Zeiger wechseln. AgentCard und Task sind zwei $defs. Eine Anfrage in die Card wickeln, und die Fehlermeldung schickt den nächsten Hop falsch.
Darf ein Skill ein JSON Schema als Eingabe hängen?
Ein 1.0-Skill nimmt kein inputSchema. Das ist ein MCP-Tool. Das generierte Bündel behandelt es als Extra-Key. Deterministische Parameter bleiben am Tool-Hop. Nicht in die Karte schreiben.
Ist eine Karte ohne signatures illegal?
Nein. signatures ist optional. Ist das Array da, die zwei JWS-Pflichtstrings behaupten. Fehlt es, trotzdem §4.4-Pflicht und Flags.
Fazit und nächste Schritte
2026 lässt sich „eine Agent Card prüfen“ auf vier Schichten falten: parsen, Bundle-Zeiger, Spec-Pflichttabelle, dann Flags und Verkehr. Katalog und Discovery sind die Tür herein. Prüfung ist der Wächter, der entscheidet ob delegiert werden darf.
Lieferreihenfolge: a2a.json pinnen, Zeiger AgentCard; Spec-Tabelle Nicht-Leer laufen lassen; Flags und MIME prüfen bevor ihr einen Task sendet; Verkehrs-Fixtures auf Task / Message umstellen. Felder schreiben: Feldtutorial. Wie ihr die Karte gefunden habt: Discovery-Text. Legale Karte, rote Karte und Bericht in JSONVue gegeneinander halten.