{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://privycdp.org/tools/agent-rail-card.schema.json",
  "title": "AI agent rail card",
  "description": "Validates the shape of a rail card: the one-page spec for one AI agent doing one job on customer data. It checks that fields exist and are filled in, not that the answers are true or enforced. This is a vendor-neutral method, not a product API. Method: https://privycdp.org/tools/agent-rail-card",
  "type": "object",
  "required": [
    "rail",
    "version",
    "agent",
    "function",
    "level",
    "risk",
    "job",
    "trigger",
    "data_scope",
    "tool_scope",
    "output_contract",
    "gate",
    "limits",
    "ledger",
    "evaluation",
    "main_metric",
    "owner",
    "kill_switch",
    "never",
    "where_it_runs"
  ],
  "additionalProperties": false,
  "patternProperties": {
    "^x_[a-z0-9_]+$": {
      "description": "Your own extension keys, such as numeric limits. They must start with x_."
    }
  },
  "properties": {
    "rail": {
      "description": "Short lowercase name with hyphens, one per job.",
      "type": "string",
      "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
      "examples": ["segment-drafter"]
    },
    "version": {
      "description": "Card version as a quoted string. Change it on every edit.",
      "type": "string",
      "pattern": "^[0-9]+\\.[0-9]+(\\.[0-9]+)?$",
      "examples": ["1.0"]
    },
    "agent": {
      "description": "A job name, never a persona.",
      "$ref": "#/$defs/filledText"
    },
    "function": {
      "description": "The team that owns the job.",
      "$ref": "#/$defs/filledText"
    },
    "level": {
      "description": "Rail level for this job: L0 Off, L1 Read, L2 Propose, L3 Execute after approval, L4 Act within bounds. A range or a named exception is allowed.",
      "type": "string",
      "pattern": "^L[0-4]( to L[0-4]|, L[0-4] [a-z ]+| on [a-z ]+)?$",
      "examples": ["L2", "L2 to L3", "L1, L4 pause", "L4 on routing only"]
    },
    "risk": {
      "description": "Risk of this job.",
      "enum": ["low", "medium", "high"]
    },
    "job": {
      "description": "Field 1. One sentence, one outcome.",
      "$ref": "#/$defs/filledText"
    },
    "trigger": {
      "description": "Field 2. What starts a run, and what must never start one.",
      "$ref": "#/$defs/filledText"
    },
    "data_scope": {
      "description": "Field 3. Objects and fields it may read, masking, consent filters, working copies and exclusions.",
      "$ref": "#/$defs/filledText"
    },
    "tool_scope": {
      "description": "Field 4. Allow-listed tools by verb. Write None. where a verb has no tools.",
      "type": "object",
      "required": ["read", "propose", "execute"],
      "additionalProperties": false,
      "properties": {
        "read": {
          "description": "Tools or views it may read.",
          "$ref": "#/$defs/filledText"
        },
        "propose": {
          "description": "What it may draft. Nothing changes until a person acts.",
          "$ref": "#/$defs/filledText"
        },
        "execute": {
          "description": "The one named action it may run, through a service that holds the credentials.",
          "$ref": "#/$defs/filledText"
        }
      }
    },
    "output_contract": {
      "description": "Field 5. What must come back, and in what shape.",
      "$ref": "#/$defs/filledText"
    },
    "gate": {
      "description": "Field 6. Who approves what evidence, and what happens on a timeout. The approver is never the requester.",
      "$ref": "#/$defs/filledText"
    },
    "limits": {
      "description": "Field 7. Blast radius, rate, budget, time window and allowed destinations. Words are allowed: each team sets its own numbers.",
      "$ref": "#/$defs/filledText"
    },
    "ledger": {
      "description": "Field 8. What every run records, written outside the agent.",
      "$ref": "#/$defs/filledText"
    },
    "evaluation": {
      "description": "Field 9. Evaluation set, what it covers and how it is run.",
      "$ref": "#/$defs/filledText"
    },
    "main_metric": {
      "description": "Field 9, continued. The honest measure or measures for this rail.",
      "$ref": "#/$defs/filledText"
    },
    "owner": {
      "description": "Field 10. The accountable role.",
      "$ref": "#/$defs/filledText"
    },
    "kill_switch": {
      "description": "Field 10, continued. How to stop the rail, what pauses it automatically and what happens to the work.",
      "$ref": "#/$defs/filledText"
    },
    "never": {
      "description": "What this rail must never do, even if asked.",
      "$ref": "#/$defs/filledText"
    },
    "where_it_runs": {
      "description": "Model placement: a private model, or an external model with masking and contract cover.",
      "$ref": "#/$defs/filledText"
    },
    "profile": {
      "description": "Optional link to documentation for this rail.",
      "type": "string",
      "format": "uri"
    }
  },
  "$defs": {
    "filledText": {
      "type": "string",
      "pattern": "\\S"
    }
  }
}
