Contract

Agent Card schema v1

Strict JSON Schema (draft 2020-12). additionalProperties is false on every object. One schema covers software agents and robots. Experimental fields belong in metadata.extensions — never on the root. Serve this document at GET /api/v1/schema.

Do not put API keys, tokens, passwords, or private keys in Agent Card JSON. Record only endpoint URL, protocol, and auth type. Credentials stay with the owner’s runtime.

Lab → live

Lab cards stay off the public index (status: private). When utility is proven, set status active, searchable true, privacy restricted. Restricted is the default for listed specialists. Public privacy is for open, non-sensitive callers only.

FieldLabLive specialist
statusprivateactive
discovery.searchablefalsetrue
privacy.levelconfidentialrestricted

The public index lists status: active and searchable: true. status: private never appears. privacy.level (including confidential) is data handling, not the hide switch.

Required

  • id
    Stable unique identifier for the agent
  • name
    Human-readable agent name
  • version
    Semantic version of this Agent Card
  • description
    See schema for constraints.
  • type
    See schema for constraints.
  • status
    Lifecycle. private = lab, off the public index. active = live specialist listing state. Independent of privacy.level.
  • capabilities
    See schema for constraints.
  • endpoints
    See schema for constraints.
  • discovery
    See schema for constraints.
  • privacy
    See schema for constraints.
  • metadata
    See schema for constraints.

Optional attachment points

  • identity
    See schema for constraints.
  • economic
    See schema for constraints.
  • trust
    See schema for constraints.
  • resources
    See schema for constraints.
  • interfaces
    See schema for constraints.
  • embodiment
    See schema for constraints.
  • location
    See schema for constraints.
  • safety
    See schema for constraints.
  • hardware
    See schema for constraints.
  • connectivity
    See schema for constraints.
  • identityLinks
    See schema for constraints.
  • tooling
    MCP attachments this agent consumes. Distinct from endpoints[].protocol=mcp, which is a server this agent exposes.
  • toolPolicy
    Least-privilege MCP tool policy. Missing profile defaults to restricted-write (software) or read-only (physical).
  • $schema
    See schema for constraints.

Invariants

  • id is immutable. Updates preserve id and metadata.created; metadata.updated is rewritten.
  • version is semver (MAJOR.MINOR.PATCH, optional pre-release). Updates must not decrease version.
  • At least one capability and one endpoint.
  • discovery.searchable and privacy.level are required. They are separate controls: searchable + status hide from /agents; privacy.level is data handling.
  • status: private never appears on the public index. confidential + active + searchable is allowed (not an accidental leak).
  • The public index lists status: active and searchable: true. status: private never appears. privacy.level (including confidential) is data handling, not the hide switch.
  • Physical types (robot, mobile-manipulator, fixed-arm, humanoid, drone, agv, ugv, auv, other-physical) require embodiment.class.
  • privacy.level = confidential requires trust.auditStatus (none | pending | passed | failed). Aliases: unverified → none, verified → passed, unreviewed → pending.
  • tooling.mcpServers is optional. If present, each server needs id, name, transport, status. This is consumed MCP, not endpoints[].protocol=mcp.
  • Do not store API keys, tokens, passwords, or private keys on the card. Auth type labels such as apiKey are allowed; credential values are not.
  • Task evidence packs (orchestrator.evidence.v1) are filtered audit JSON. They omit credential-shaped keys.
  • Audit events carry eventSchemaVersion (MAJOR.MINOR, currently 1.0). Missing on historical rows is read as 1.0; rows are never rewritten. Distinct from producerVersion and agent version. New writes use a unified envelope (type, reasonCode, correlation, subject, data, final) behind per-family flags; unknown 1.x types and codes are stored and displayed.
  • Unique items on keyword, category, namespace, tag, and badge arrays.

JSON Schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://agentcard.schema/v1",
  "title": "AgentCard",
  "description": "Strict schema for Agent Card identity and capability records",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "id",
    "name",
    "version",
    "description",
    "type",
    "status",
    "capabilities",
    "endpoints",
    "discovery",
    "privacy",
    "metadata"
  ],
  "properties": {
    "$schema": {
      "type": "string",
      "const": "https://agentcard.schema/v1"
    },
    "id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 256,
      "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._:/-]*$",
      "description": "Stable unique identifier for the agent"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "description": "Human-readable agent name"
    },
    "version": {
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.]+)?$",
      "description": "Semantic version of this Agent Card"
    },
    "description": {
      "type": "string",
      "minLength": 1,
      "maxLength": 2048
    },
    "type": {
      "type": "string",
      "enum": [
        "agent",
        "orchestrator",
        "service",
        "meta-agent",
        "other",
        "robot",
        "mobile-manipulator",
        "fixed-arm",
        "humanoid",
        "drone",
        "agv",
        "ugv",
        "auv",
        "other-physical"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "deprecated",
        "maintenance",
        "private"
      ],
      "description": "Lifecycle. private = lab, off the public index. active = live specialist listing state. Independent of privacy.level."
    },
    "identity": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "did": {
          "type": "string",
          "minLength": 1
        },
        "owner": {
          "type": "string",
          "minLength": 1
        },
        "controller": {
          "type": "string",
          "minLength": 1
        },
        "verificationMethods": {
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "credentials": {
          "type": "array",
          "items": {
            "type": "object"
          }
        }
      }
    },
    "capabilities": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "description"
        ],
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1024
          },
          "inputs": {
            "type": "object"
          },
          "outputs": {
            "type": "object"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "uniqueItems": true
          },
          "skills": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "uniqueItems": true
          }
        }
      }
    },
    "endpoints": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "url",
          "protocol",
          "auth",
          "privacy"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048
          },
          "protocol": {
            "type": "string",
            "enum": [
              "a2a",
              "mcp",
              "http",
              "grpc",
              "custom"
            ]
          },
          "auth": {
            "type": "string",
            "enum": [
              "none",
              "apiKey",
              "oauth",
              "zk",
              "mTLS",
              "custom"
            ]
          },
          "privacy": {
            "type": "string",
            "enum": [
              "public",
              "authenticated",
              "confidential"
            ]
          },
          "priority": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "default": 1
          }
        }
      }
    },
    "discovery": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "searchable"
      ],
      "properties": {
        "keywords": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "uniqueItems": true
        },
        "categories": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "uniqueItems": true
        },
        "namespaces": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "uniqueItems": true
        },
        "searchable": {
          "type": "boolean",
          "description": "Public-index switch with status. false keeps the card off /agents even if status is active. Independent of privacy.level."
        }
      }
    },
    "economic": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "pricingEndpoint": {
          "type": "string",
          "minLength": 1
        },
        "pricingModel": {
          "type": "string",
          "enum": [
            "fixed",
            "dynamic",
            "auction",
            "freemium",
            "custom"
          ]
        },
        "currency": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "uniqueItems": true
        },
        "royaltyPolicy": {
          "type": "string"
        },
        "license": {
          "type": "string"
        }
      }
    },
    "trust": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "scoreProvider": {
          "type": "string"
        },
        "score": {
          "type": "number",
          "minimum": 0,
          "maximum": 100
        },
        "badges": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "uniqueItems": true
        },
        "auditStatus": {
          "type": "string",
          "enum": [
            "none",
            "pending",
            "passed",
            "failed"
          ]
        }
      }
    },
    "privacy": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "level"
      ],
      "properties": {
        "level": {
          "type": "string",
          "enum": [
            "public",
            "restricted",
            "confidential"
          ],
          "description": "Data handling, not the public-index hide switch. Lab uses confidential. Listed specialists default to restricted. public is for open, non-sensitive callers only."
        },
        "supportedEnvironments": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "agent",
              "secret",
              "zano",
              "xmr",
              "twin",
              "other"
            ]
          },
          "uniqueItems": true
        },
        "dataHandling": {
          "type": "string",
          "maxLength": 1024
        }
      }
    },
    "resources": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "memory": {
          "type": "string"
        },
        "compute": {
          "type": "string"
        },
        "tools": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "uniqueItems": true
        }
      }
    },
    "interfaces": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "supportedProtocols": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "uniqueItems": true
        },
        "inputSchema": {
          "type": "object"
        },
        "outputSchema": {
          "type": "object"
        },
        "streaming": {
          "type": "boolean",
          "default": false
        }
      }
    },
    "metadata": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "created",
        "updated"
      ],
      "properties": {
        "created": {
          "type": "string",
          "format": "date-time"
        },
        "updated": {
          "type": "string",
          "format": "date-time"
        },
        "ttl": {
          "type": "integer",
          "minimum": 0,
          "description": "Time-to-live in seconds"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "uniqueItems": true
        },
        "schemaVersion": {
          "type": "string",
          "const": "v1"
        },
        "extensions": {
          "type": "object",
          "description": "Controlled extension point for experimental or domain-specific fields"
        }
      }
    },
    "embodiment": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "class": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64
        },
        "form": {
          "type": "string",
          "maxLength": 128
        },
        "dof": {
          "type": "integer",
          "minimum": 0,
          "maximum": 64
        },
        "massKg": {
          "type": "number",
          "minimum": 0
        },
        "payloadKg": {
          "type": "number",
          "minimum": 0
        },
        "notes": {
          "type": "string",
          "maxLength": 1024
        }
      }
    },
    "location": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "siteId": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128
        },
        "zone": {
          "type": "string",
          "maxLength": 128
        },
        "geo": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "lat",
            "lon"
          ],
          "properties": {
            "lat": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            },
            "lon": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            },
            "altM": {
              "type": "number"
            }
          }
        },
        "indoor": {
          "type": "boolean"
        },
        "frame": {
          "type": "string",
          "maxLength": 64
        }
      }
    },
    "safety": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "eStop": {
          "type": "boolean"
        },
        "certified": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "uniqueItems": true
        },
        "maxSpeedMps": {
          "type": "number",
          "minimum": 0
        },
        "humanProximity": {
          "type": "string",
          "enum": [
            "none",
            "supervised",
            "collaborative"
          ]
        },
        "notes": {
          "type": "string",
          "maxLength": 1024
        }
      }
    },
    "hardware": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "vendor": {
          "type": "string",
          "maxLength": 128
        },
        "model": {
          "type": "string",
          "maxLength": 128
        },
        "serial": {
          "type": "string",
          "maxLength": 128
        },
        "firmware": {
          "type": "string",
          "maxLength": 64
        },
        "sensors": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "uniqueItems": true
        },
        "actuators": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "uniqueItems": true
        }
      }
    },
    "connectivity": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "radios": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "uniqueItems": true
        },
        "bandwidth": {
          "type": "string",
          "maxLength": 64
        },
        "latencyClass": {
          "type": "string",
          "enum": [
            "lan",
            "wan",
            "intermittent"
          ]
        },
        "lastSeen": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "identityLinks": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "oem": {
          "type": "string",
          "maxLength": 128
        },
        "fleetId": {
          "type": "string",
          "maxLength": 128
        },
        "twinId": {
          "type": "string",
          "maxLength": 256
        },
        "did": {
          "type": "string",
          "maxLength": 256
        },
        "uris": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "uniqueItems": true
        }
      }
    },
    "tooling": {
      "type": "object",
      "additionalProperties": false,
      "description": "MCP attachments this agent consumes. Distinct from endpoints[].protocol=mcp, which is a server this agent exposes.",
      "required": [
        "mcpServers"
      ],
      "properties": {
        "mcpServers": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "transport",
              "status"
            ],
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128
              },
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128
              },
              "transport": {
                "type": "string",
                "enum": [
                  "stdio",
                  "http",
                  "sse",
                  "other"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "active",
                  "disabled",
                  "unknown"
                ]
              },
              "url": {
                "type": "string",
                "minLength": 1,
                "maxLength": 2048
              },
              "auth": {
                "type": "string",
                "enum": [
                  "none",
                  "apiKey",
                  "oauth",
                  "zk",
                  "mTLS",
                  "custom",
                  "secretRef"
                ]
              },
              "secretRef": {
                "type": "string",
                "minLength": 1,
                "maxLength": 256,
                "description": "Named secret reference only — never the credential value"
              },
              "tools": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name"
                  ],
                  "properties": {
                    "name": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 128
                    },
                    "description": {
                      "type": "string",
                      "maxLength": 1024
                    },
                    "sideEffect": {
                      "type": "string",
                      "enum": [
                        "read",
                        "write",
                        "destructive",
                        "unknown"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "toolPolicy": {
      "type": "object",
      "additionalProperties": false,
      "description": "Least-privilege MCP tool policy. Missing profile defaults to restricted-write (software) or read-only (physical).",
      "properties": {
        "profile": {
          "type": "string",
          "enum": [
            "read-only",
            "restricted-write",
            "production-restricted",
            "unrestricted"
          ]
        },
        "maxSideEffect": {
          "type": "string",
          "enum": [
            "read",
            "write",
            "destructive"
          ]
        },
        "allowServers": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "uniqueItems": true
        },
        "denyTools": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "uniqueItems": true
        },
        "allowUnknown": {
          "type": "boolean",
          "default": false
        }
      }
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "type": {
            "enum": [
              "robot",
              "mobile-manipulator",
              "fixed-arm",
              "humanoid",
              "drone",
              "agv",
              "ugv",
              "auv",
              "other-physical"
            ]
          }
        },
        "required": [
          "type"
        ]
      },
      "then": {
        "required": [
          "embodiment"
        ],
        "properties": {
          "embodiment": {
            "required": [
              "class"
            ]
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "privacy": {
            "properties": {
              "level": {
                "const": "confidential"
              }
            },
            "required": [
              "level"
            ]
          }
        },
        "required": [
          "privacy"
        ]
      },
      "then": {
        "required": [
          "trust"
        ],
        "properties": {
          "trust": {
            "required": [
              "auditStatus"
            ]
          }
        }
      }
    },
    {
      "if": {
        "required": [
          "location"
        ]
      },
      "then": {
        "properties": {
          "location": {
            "anyOf": [
              {
                "required": [
                  "siteId"
                ]
              },
              {
                "required": [
                  "geo"
                ]
              }
            ]
          }
        }
      }
    }
  ]
}