{
  "$id": "https://hupe1980.github.io/agentplane/agent.schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "additionalProperties": false,
  "definitions": {
    "Approval": {
      "description": "What a human decides on **before the run continues**.",
      "oneOf": [
        {
          "const": "required",
          "description": "Every answer waits for a person.",
          "type": "string"
        },
        {
          "const": "tools-only",
          "description": "Only the tool calls that ask for it wait; the answer returns unattended.",
          "type": "string"
        },
        {
          "const": "none",
          "description": "Nothing waits. The run completes and `Oversight::triage` decides what a person is shown afterwards.",
          "type": "string"
        }
      ]
    },
    "Boundary": {
      "description": "An effect kind a rule can name.",
      "enum": [
        "model.complete",
        "tool.call",
        "event.await",
        "media.fetch",
        "memory.recall"
      ],
      "type": "string"
    },
    "Budgets": {
      "additionalProperties": false,
      "description": "Ceilings, in the manifest's own vocabulary.",
      "properties": {
        "max_denials": {
          "description": "How many times the policy may refuse this run before it is stopped.",
          "format": "uint32",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "max_effects": {
          "description": "Externally visible operations of **every** kind — a tool call, a clock read and a model completion each cost one, so this is not a model ceiling.",
          "format": "uint",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "max_egress_bytes": {
          "description": "Bytes this agent may send into sinks in one run.",
          "format": "uint64",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "max_minor_units": {
          "description": "Money in minor units — cents, not euros. A float here would make a budget that fails to bind by a rounding error, and money is the one number nobody accepts \"approximately\" for.",
          "format": "uint64",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "max_parallel_steps": {
          "description": "How many of a plan's ready steps may run at once.",
          "format": "uint",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "max_replans": {
          "description": "How many times the run may change its plan.",
          "format": "uint32",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "max_steps": {
          "description": "Plan nodes this run may execute, checked before each one starts.",
          "format": "uint",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "max_tokens": {
          "description": "Metered units consumed, compared against the run's total before **every** effect — including effects that consume no tokens at all.",
          "format": "uint64",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "max_wallclock_secs": {
          "description": "Seconds. Named for its unit so a manifest cannot mean minutes.",
          "format": "uint64",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        }
      },
      "type": "object"
    },
    "Capabilities": {
      "additionalProperties": false,
      "description": "What this agent offers, as capability strings.",
      "properties": {
        "provides": {
          "default": [],
          "items": {
            "type": "string"
          },
          "type": "array"
        }
      },
      "type": "object"
    },
    "Case": {
      "enum": [
        "fold"
      ],
      "type": "string"
    },
    "CheckAction": {
      "description": "What a category a check reports does. Neither can admit or lower.",
      "oneOf": [
        {
          "enum": [
            "refuse"
          ],
          "type": "string"
        },
        {
          "additionalProperties": false,
          "description": "Join the value's sensitivity with this one.",
          "properties": {
            "classify": {
              "$ref": "#/definitions/Sensitivity"
            }
          },
          "required": [
            "classify"
          ],
          "type": "object"
        }
      ]
    },
    "Condition": {
      "description": "One field of the answer, and one thing that must be true of it.",
      "oneOf": [
        {
          "description": "Deep JSON equality against a constant.",
          "properties": {
            "equals": true
          },
          "required": [
            "equals"
          ],
          "type": "object"
        },
        {
          "description": "Deep JSON equality against any of several constants.",
          "properties": {
            "in": {
              "items": true,
              "type": "array"
            }
          },
          "required": [
            "in"
          ],
          "type": "object"
        },
        {
          "description": "A number at or above this. Non-numbers do not match.",
          "properties": {
            "at_least": {
              "format": "double",
              "type": "number"
            }
          },
          "required": [
            "at_least"
          ],
          "type": "object"
        },
        {
          "description": "A number at or below this. Non-numbers do not match.",
          "properties": {
            "at_most": {
              "format": "double",
              "type": "number"
            }
          },
          "required": [
            "at_most"
          ],
          "type": "object"
        },
        {
          "description": "The pointer selects something — anything, including `null`.",
          "properties": {
            "exists": {
              "type": "boolean"
            }
          },
          "required": [
            "exists"
          ],
          "type": "object"
        }
      ],
      "properties": {
        "path": {
          "description": "RFC 6901 pointer into the answer, e.g. `/deadline_status`.",
          "type": "string"
        }
      },
      "required": [
        "path"
      ],
      "type": "object"
    },
    "Content": {
      "additionalProperties": false,
      "description": "`spec.security.content`: the rules a deployment holds this agent's values to.",
      "properties": {
        "checks": {
          "description": "Uses of a registered `ContentChecker`: a classifier describes the value in categories, and the declared `on` table decides.",
          "items": {
            "$ref": "#/definitions/ContentCheck"
          },
          "type": "array"
        },
        "rules": {
          "default": [],
          "items": {
            "$ref": "#/definitions/ContentRule"
          },
          "type": "array"
        }
      },
      "type": "object"
    },
    "ContentCheck": {
      "additionalProperties": false,
      "description": "A declared use of a registered checker.",
      "properties": {
        "at": {
          "allOf": [
            {
              "$ref": "#/definitions/Positions"
            }
          ],
          "description": "Sinks, and the outputs of model and tool calls: a check runs as an effect of the step, so it judges what a step sends or what one of its calls returns."
        },
        "checker": {
          "description": "The `ContentChecker::name` of a checker registered on the builder.",
          "type": "string"
        },
        "id": {
          "description": "Unique among the manifest's rules and checks; what a refusal names.",
          "type": "string"
        },
        "on": {
          "additionalProperties": {
            "$ref": "#/definitions/CheckAction"
          },
          "description": "From the checker's declared categories to what each one does.",
          "type": "object"
        }
      },
      "required": [
        "id",
        "checker",
        "at",
        "on"
      ],
      "type": "object"
    },
    "ContentRule": {
      "additionalProperties": false,
      "description": "One declared rule: a matcher, where it applies, and its one action.",
      "properties": {
        "at": {
          "$ref": "#/definitions/Positions"
        },
        "fields": {
          "description": "JSON pointers narrowing which subtrees are read. Empty reads the whole value.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "id": {
          "description": "Unique within the manifest; what a refusal names.",
          "type": "string"
        },
        "match": {
          "$ref": "#/definitions/Matcher"
        },
        "then": {
          "allOf": [
            {
              "$ref": "#/definitions/RuleAction"
            }
          ],
          "description": "`refuse`, `{classify: <sensitivity>}` or `{redact: <token>}` — a map, not a YAML tag, in every format the manifest is read from."
        }
      },
      "required": [
        "id",
        "match",
        "at",
        "then"
      ],
      "type": "object"
    },
    "ContextGrants": {
      "additionalProperties": false,
      "properties": {
        "prompts": {
          "default": [],
          "items": {
            "$ref": "#/definitions/ContextPrompt"
          },
          "type": "array"
        },
        "resources": {
          "default": [],
          "items": {
            "$ref": "#/definitions/ContextResource"
          },
          "type": "array"
        },
        "task_input": {
          "default": [],
          "description": "Servers this agent may answer `tasks/update` input requests on.",
          "items": {
            "$ref": "#/definitions/ContextTaskInput"
          },
          "type": "array"
        }
      },
      "type": "object"
    },
    "ContextPrompt": {
      "additionalProperties": false,
      "properties": {
        "max_input_sensitivity": {
          "allOf": [
            {
              "$ref": "#/definitions/Sensitivity"
            }
          ],
          "default": "public"
        },
        "name": {
          "type": "string"
        },
        "output_sensitivity": {
          "allOf": [
            {
              "$ref": "#/definitions/Sensitivity"
            }
          ],
          "default": "public"
        },
        "server": {
          "type": "string"
        }
      },
      "required": [
        "server",
        "name"
      ],
      "type": "object"
    },
    "ContextResource": {
      "additionalProperties": false,
      "properties": {
        "output_sensitivity": {
          "allOf": [
            {
              "$ref": "#/definitions/Sensitivity"
            }
          ],
          "default": "public"
        },
        "server": {
          "type": "string"
        },
        "uri": {
          "type": "string"
        }
      },
      "required": [
        "server",
        "uri"
      ],
      "type": "object"
    },
    "ContextTaskInput": {
      "additionalProperties": false,
      "description": "One server this agent may send task input responses to.",
      "properties": {
        "max_input_sensitivity": {
          "allOf": [
            {
              "$ref": "#/definitions/Sensitivity"
            }
          ],
          "default": "public"
        },
        "server": {
          "type": "string"
        }
      },
      "required": [
        "server"
      ],
      "type": "object"
    },
    "DataSubject": {
      "description": "Whose data a run takes in: `$input/<RFC 6901 pointer>` or `$case`. A literal and a correlation key are refused.",
      "pattern": "^\\$(case|input(/.*)?)$",
      "type": "string"
    },
    "Execution": {
      "additionalProperties": false,
      "description": "How a declarative agent runs.",
      "properties": {
        "kind": {
          "allOf": [
            {
              "$ref": "#/definitions/ExecutionKind"
            }
          ],
          "description": "Which built-in behaviour runs this agent."
        },
        "max_turns": {
          "default": 8,
          "description": "How many model turns a tool-calling agent may take.",
          "format": "uint32",
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "kind"
      ],
      "type": "object"
    },
    "ExecutionKind": {
      "description": "The built-in behaviours a manifest may ask for.",
      "oneOf": [
        {
          "const": "completion",
          "description": "One model call, answered in the declared `Output` shape.",
          "type": "string"
        },
        {
          "const": "tool-calling",
          "description": "Call tools until the model stops asking, then answer.",
          "type": "string"
        },
        {
          "const": "planned",
          "description": "Plan first over trusted input, then execute without the model.",
          "type": "string"
        },
        {
          "const": "call",
          "description": "Dispatch the one granted tool, with the run's input as its arguments.",
          "type": "string"
        }
      ]
    },
    "Expiry": {
      "description": "What happens when the approval window closes.",
      "oneOf": [
        {
          "const": "deny",
          "description": "Refuse the answer. The safe default, and the default here.",
          "type": "string"
        },
        {
          "const": "escalate",
          "description": "Widen the audience and keep waiting.",
          "type": "string"
        },
        {
          "const": "proceed",
          "description": "Return the answer with nobody having looked.",
          "type": "string"
        }
      ]
    },
    "Identity": {
      "additionalProperties": false,
      "description": "The words an agent is given about itself.",
      "properties": {
        "constraints": {
          "default": "",
          "description": "How it must behave. Kept separate from `role`(Self::role) because the two are reviewed by different people and change on different schedules.",
          "type": "string"
        },
        "role": {
          "description": "What the agent is for, in one line.",
          "type": "string"
        }
      },
      "required": [
        "role"
      ],
      "type": "object"
    },
    "Input": {
      "additionalProperties": false,
      "description": "The shape a caller must send.",
      "properties": {
        "schema": {
          "description": "A JSON Schema, carried opaquely — never parsed as a schema by this crate, only checked to be a non-empty object."
        }
      },
      "required": [
        "schema"
      ],
      "type": "object"
    },
    "Justification": {
      "description": "Why collaboration is worth its cost.",
      "oneOf": [
        {
          "const": "parallel-disjoint",
          "description": "Sub-tasks operate on provably disjoint inputs.",
          "type": "string"
        },
        {
          "const": "distinct-authority",
          "description": "Sub-tasks require strictly different capabilities.",
          "type": "string"
        }
      ]
    },
    "Matcher": {
      "additionalProperties": false,
      "description": "Exactly one of `pattern`, `contains` or `invisible`.",
      "properties": {
        "case": {
          "anyOf": [
            {
              "$ref": "#/definitions/Case"
            },
            {
              "type": "null"
            }
          ],
          "description": "With `contains`: `fold` matches regardless of case."
        },
        "contains": {
          "description": "Literal substrings; any one matches.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "invisible": {
          "description": "The code points that render as nothing: tag characters, variation selectors, zero-width and bidirectional controls.",
          "type": "boolean"
        },
        "luhn": {
          "description": "With `pattern`: a match counts only when its digits pass the Luhn check, so a card-number rule skips order numbers of the same length.",
          "type": "boolean"
        },
        "pattern": {
          "description": "A regular expression under the linear-time engine: no backreferences, no look-around.",
          "type": [
            "string",
            "null"
          ]
        }
      },
      "type": "object"
    },
    "Memory": {
      "additionalProperties": false,
      "description": "A declarative agent's two halves of durable memory: what it reads, and what it writes.",
      "properties": {
        "formation": {
          "anyOf": [
            {
              "$ref": "#/definitions/MemoryFormation"
            },
            {
              "type": "null"
            }
          ],
          "description": "Form bounded durable facts from each answer."
        },
        "recall": {
          "anyOf": [
            {
              "$ref": "#/definitions/MemoryRecall"
            },
            {
              "type": "null"
            }
          ],
          "description": "Read memories into the prompt, before the model is called."
        }
      },
      "type": "object"
    },
    "MemoryFormation": {
      "additionalProperties": false,
      "properties": {
        "access_retention_seconds": {
          "format": "uint64",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "instruction": {
          "type": "string"
        },
        "max_items": {
          "default": 3,
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "max_sensitivity": {
          "allOf": [
            {
              "$ref": "#/definitions/Sensitivity"
            }
          ],
          "default": "public"
        },
        "purpose": {
          "type": "string"
        },
        "retention_seconds": {
          "format": "uint64",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "subject": {
          "allOf": [
            {
              "$ref": "#/definitions/MemorySubject"
            }
          ],
          "description": "Where the formed memories are filed."
        }
      },
      "required": [
        "subject",
        "purpose",
        "instruction"
      ],
      "type": "object"
    },
    "MemoryRecall": {
      "additionalProperties": false,
      "description": "What a declarative agent is given to remember, before it answers.",
      "properties": {
        "limit": {
          "default": 5,
          "description": "How many, at most.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "purpose": {
          "description": "Restrict to memories kept for one purpose.",
          "type": [
            "string",
            "null"
          ]
        },
        "refresh_access": {
          "default": false,
          "description": "Slide each selected memory's access-retention window forward.",
          "type": "boolean"
        },
        "subject": {
          "allOf": [
            {
              "$ref": "#/definitions/MemorySubject"
            }
          ],
          "description": "Which pile to read, with the same three bindings formation writes under. See `MemorySubject`."
        }
      },
      "required": [
        "subject"
      ],
      "type": "object"
    },
    "MemorySubject": {
      "description": "A memory scope: a literal name, or a run binding — `$correlation/<namespace>`, `$case`, or `$input/<RFC 6901 pointer>`. Write `$$` for a literal that really begins with a dollar sign; any other `$` spelling is refused rather than read as a constant.",
      "minLength": 1,
      "type": "string"
    },
    "Metadata": {
      "additionalProperties": false,
      "description": "Who this agent is, for the record.",
      "properties": {
        "annotations": {
          "additionalProperties": {
            "type": "string"
          },
          "description": "Facts about this agent that the runtime never reads.",
          "type": "object"
        },
        "name": {
          "type": "string"
        },
        "version": {
          "description": "Free-form, and compared only for equality. The crate does not parse semver: it has no version-ordering decision to make, and pretending to understand a scheme it never checks would invite one.",
          "type": "string"
        }
      },
      "required": [
        "name",
        "version"
      ],
      "type": "object"
    },
    "ModelRef": {
      "additionalProperties": false,
      "description": "One model, named the way a provider names it.",
      "properties": {
        "max_input_tokens": {
          "description": "A per-call input ceiling: the most tokens one call may send, cached ones included.",
          "format": "uint32",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "max_tokens": {
          "description": "A per-call output ceiling, if this role needs one.",
          "format": "uint32",
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "model": {
          "description": "The provider's own model identifier, pinned exactly.",
          "type": "string"
        },
        "pricing": {
          "anyOf": [
            {
              "$ref": "#/definitions/Pricing"
            },
            {
              "type": "null"
            }
          ],
          "description": "What this model's tokens cost, in minor units per million tokens."
        },
        "provider": {
          "description": "The driver: `anthropic`, `openai`, or whatever an embedder registered.",
          "type": "string"
        },
        "reasoning_effort": {
          "anyOf": [
            {
              "$ref": "#/definitions/ReasoningEffort"
            },
            {
              "type": "null"
            }
          ],
          "description": "Explicit reasoning depth. Omitted uses the selected model's default."
        }
      },
      "required": [
        "provider",
        "model"
      ],
      "type": "object"
    },
    "Models": {
      "additionalProperties": false,
      "description": "The models an agent runs on, by role.",
      "properties": {
        "privileged": {
          "anyOf": [
            {
              "$ref": "#/definitions/ModelRef"
            },
            {
              "type": "null"
            }
          ],
          "description": "The model trusted with tool calls and decisions."
        },
        "quarantined": {
          "anyOf": [
            {
              "$ref": "#/definitions/ModelRef"
            },
            {
              "type": "null"
            }
          ],
          "description": "The model that reads untrusted material and holds no authority."
        }
      },
      "type": "object"
    },
    "Output": {
      "additionalProperties": false,
      "description": "The shape an agent promises its callers.",
      "properties": {
        "schema": {
          "description": "A JSON Schema, carried opaquely."
        }
      },
      "required": [
        "schema"
      ],
      "type": "object"
    },
    "Oversight": {
      "additionalProperties": false,
      "description": "Human oversight, declared rather than remembered.",
      "properties": {
        "allow_unattended": {
          "default": false,
          "description": "Explicit consent to act with no human when the window closes.",
          "type": "boolean"
        },
        "approval": {
          "allOf": [
            {
              "$ref": "#/definitions/Approval"
            }
          ],
          "description": "What a human decides **before** the run continues."
        },
        "approvers": {
          "default": [],
          "description": "Who may decide. Empty means anyone — a choice worth making on purpose rather than by omission.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "deadline": {
          "allOf": [
            {
              "$ref": "#/definitions/OversightDeadline"
            }
          ],
          "description": "The obligation that bounds the wait."
        },
        "escalate_to": {
          "description": "Who is added to the audience when an unanswered task escalates.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "on_expiry": {
          "allOf": [
            {
              "$ref": "#/definitions/Expiry"
            }
          ],
          "default": "deny",
          "description": "What happens when the window closes."
        },
        "triage": {
          "description": "Tasks opened **beside** a completed answer, not in front of it.",
          "items": {
            "$ref": "#/definitions/TriageRule"
          },
          "type": "array"
        }
      },
      "required": [
        "approval",
        "deadline"
      ],
      "type": "object"
    },
    "OversightDeadline": {
      "additionalProperties": false,
      "description": "The obligation that bounds an oversight wait.",
      "properties": {
        "kind": {
          "description": "The resolution rule, e.g. `hours`, `days`, `working-days`.",
          "type": "string"
        },
        "name": {
          "description": "What the obligation is called on the case.",
          "type": "string"
        },
        "params": {
          "default": null,
          "description": "Parameters for that rule, e.g. `{ n: 2 }`."
        }
      },
      "required": [
        "name",
        "kind"
      ],
      "type": "object"
    },
    "Positions": {
      "additionalProperties": false,
      "description": "Where a rule applies.",
      "properties": {
        "admission": {
          "description": "The run's input, before it is admitted.",
          "type": "boolean"
        },
        "sinks": {
          "description": "A value about to be sent, before the effect is announced.",
          "items": {
            "$ref": "#/definitions/Boundary"
          },
          "type": "array"
        },
        "sources": {
          "description": "An effect's output, as it is recorded.",
          "items": {
            "$ref": "#/definitions/Boundary"
          },
          "type": "array"
        }
      },
      "type": "object"
    },
    "Pricing": {
      "additionalProperties": false,
      "description": "What a model's tokens cost, as the deployment states it.",
      "properties": {
        "cache_read": {
          "description": "Input tokens served from a cache.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "cache_write": {
          "description": "Input tokens written into a cache.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "input": {
          "description": "Ordinary input tokens — neither written to nor read from a cache.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "output": {
          "description": "Generated tokens, reasoning included.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "input",
        "output",
        "cache_read",
        "cache_write"
      ],
      "type": "object"
    },
    "ProtectedField": {
      "additionalProperties": false,
      "description": "A stricter information-flow rule for one JSON field sent to a sink.",
      "properties": {
        "allowed_sources": {
          "items": {
            "$ref": "#/definitions/SourceId"
          },
          "type": "array",
          "uniqueItems": true
        },
        "max_sensitivity": {
          "anyOf": [
            {
              "$ref": "#/definitions/Sensitivity"
            },
            {
              "type": "null"
            }
          ]
        },
        "one_of": {
          "description": "The closed set of values this field may carry, when one is declared.",
          "items": true,
          "type": "array"
        },
        "path": {
          "type": "string"
        },
        "require_trusted": {
          "default": false,
          "type": "boolean"
        }
      },
      "required": [
        "path"
      ],
      "type": "object"
    },
    "RateLimit": {
      "additionalProperties": false,
      "description": "A cross-run ceiling on one tool: see `ToolGrant::rate_limit`.",
      "properties": {
        "count": {
          "description": "Calls admitted per window. At least one.",
          "format": "uint32",
          "minimum": 0,
          "type": "integer"
        },
        "window_seconds": {
          "description": "The window, in seconds. At least one, at most 31 days.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "count",
        "window_seconds"
      ],
      "type": "object"
    },
    "ReasoningEffort": {
      "description": "Provider-neutral reasoning depth.",
      "enum": [
        "none",
        "minimal",
        "low",
        "medium",
        "high",
        "x-high",
        "max"
      ],
      "type": "string"
    },
    "Role": {
      "description": "What an agent is within an arrangement.",
      "oneOf": [
        {
          "const": "specialist",
          "description": "Does one thing and hands off to nobody.",
          "type": "string"
        },
        {
          "const": "orchestrator",
          "description": "Decomposes a task, delegates to specialists, assembles the result.",
          "type": "string"
        }
      ]
    },
    "RuleAction": {
      "description": "What a matching rule does. None of these can admit, trust or lower.",
      "oneOf": [
        {
          "enum": [
            "refuse"
          ],
          "type": "string"
        },
        {
          "additionalProperties": false,
          "description": "Join the value's sensitivity with this one.",
          "properties": {
            "classify": {
              "$ref": "#/definitions/Sensitivity"
            }
          },
          "required": [
            "classify"
          ],
          "type": "object"
        },
        {
          "additionalProperties": false,
          "description": "Replace each match with this token. Sinks only.",
          "properties": {
            "redact": {
              "type": "string"
            }
          },
          "required": [
            "redact"
          ],
          "type": "object"
        }
      ]
    },
    "Security": {
      "additionalProperties": false,
      "description": "The constraints a runtime enforces.",
      "properties": {
        "content": {
          "anyOf": [
            {
              "$ref": "#/definitions/Content"
            },
            {
              "type": "null"
            }
          ],
          "description": "Rules over a value's content, applied at admission, where an effect's output arrives, and at sinks. They may refuse a value, raise its sensitivity or redact it at a sink — never admit, trust or lower it."
        },
        "max_delegation_depth": {
          "description": "How far authority may be re-delegated. Checked both against the runtime's configured identity and against every delegating sink before dispatch.",
          "format": "uint8",
          "maximum": 255,
          "minimum": 0,
          "type": [
            "integer",
            "null"
          ]
        },
        "max_sensitivity_egress": {
          "anyOf": [
            {
              "$ref": "#/definitions/Sensitivity"
            },
            {
              "type": "null"
            }
          ],
          "description": "The highest sensitivity any value may reach an outward sink at. Combined with the sink's own ceiling at dispatch; the stricter limit wins."
        },
        "max_sensitivity_journaled": {
          "anyOf": [
            {
              "$ref": "#/definitions/Sensitivity"
            },
            {
              "type": "null"
            }
          ],
          "description": "The highest sensitivity a value may reach an effect **whose arguments the journal records**."
        }
      },
      "type": "object"
    },
    "Sensitivity": {
      "description": "How much damage disclosure would do.",
      "enum": [
        "public",
        "internal",
        "confidential",
        "secret"
      ],
      "type": "string"
    },
    "SourceId": {
      "description": "Where a value came from. Free-form so the engine stays domain-agnostic; the runtime stamps tool refs, peer ids, and collection names.",
      "type": "string"
    },
    "Spec": {
      "additionalProperties": false,
      "description": "The declaration proper.",
      "properties": {
        "budgets": {
          "anyOf": [
            {
              "$ref": "#/definitions/Budgets"
            },
            {
              "type": "null"
            }
          ],
          "description": "Absent means *unbounded*, and that is a decision the manifest has to state out loud — see `Manifest::validate`."
        },
        "capabilities": {
          "allOf": [
            {
              "$ref": "#/definitions/Capabilities"
            }
          ],
          "default": {
            "provides": []
          }
        },
        "context": {
          "allOf": [
            {
              "$ref": "#/definitions/ContextGrants"
            }
          ],
          "description": "External context this agent may retrieve."
        },
        "data_subjects": {
          "description": "Whose data a run of this agent takes in, read from the run.",
          "items": {
            "$ref": "#/definitions/DataSubject"
          },
          "type": "array"
        },
        "execution": {
          "anyOf": [
            {
              "$ref": "#/definitions/Execution"
            },
            {
              "type": "null"
            }
          ],
          "description": "How this agent runs — and whether it needs any code at all."
        },
        "identity": {
          "anyOf": [
            {
              "$ref": "#/definitions/Identity"
            },
            {
              "type": "null"
            }
          ],
          "description": "Who the agent is told it is."
        },
        "input": {
          "anyOf": [
            {
              "$ref": "#/definitions/Input"
            },
            {
              "type": "null"
            }
          ],
          "description": "The shape of what this agent takes."
        },
        "memory": {
          "anyOf": [
            {
              "$ref": "#/definitions/Memory"
            },
            {
              "type": "null"
            }
          ],
          "description": "What this agent reads from and writes to durable memory."
        },
        "model": {
          "anyOf": [
            {
              "$ref": "#/definitions/ModelRef"
            },
            {
              "type": "null"
            }
          ],
          "description": "Shorthand for `models: { privileged: … }`, the single-model case."
        },
        "models": {
          "anyOf": [
            {
              "$ref": "#/definitions/Models"
            },
            {
              "type": "null"
            }
          ],
          "description": "Which models this agent runs on."
        },
        "output": {
          "anyOf": [
            {
              "$ref": "#/definitions/Output"
            },
            {
              "type": "null"
            }
          ],
          "description": "The shape of what this agent returns."
        },
        "oversight": {
          "anyOf": [
            {
              "$ref": "#/definitions/Oversight"
            },
            {
              "type": "null"
            }
          ],
          "description": "Whether a human decides before this agent's answer is returned."
        },
        "security": {
          "allOf": [
            {
              "$ref": "#/definitions/Security"
            }
          ],
          "default": {}
        },
        "tools": {
          "default": [],
          "description": "Tools this agent may call. An empty list grants nothing.",
          "items": {
            "$ref": "#/definitions/ToolGrant"
          },
          "type": "array"
        },
        "topology": {
          "anyOf": [
            {
              "$ref": "#/definitions/Topology"
            },
            {
              "type": "null"
            }
          ],
          "description": "What this agent is in a multi-agent arrangement."
        }
      },
      "type": "object"
    },
    "ToolGrant": {
      "additionalProperties": false,
      "description": "One tool this agent may call, and on what terms.",
      "properties": {
        "arguments": {
          "description": "A JSON Schema for the arguments, carried opaquely."
        },
        "description": {
          "description": "What this tool does, in the words the **model** is given.",
          "type": [
            "string",
            "null"
          ]
        },
        "max_sensitivity": {
          "anyOf": [
            {
              "$ref": "#/definitions/Sensitivity"
            },
            {
              "type": "null"
            }
          ],
          "description": "The highest sensitivity this tool may be shown."
        },
        "mutates": {
          "default": true,
          "description": "Whether calling it changes the world.",
          "type": "boolean"
        },
        "preview": {
          "description": "A read-only tool that computes what this call *will do*, shown to the reviewer beside the call itself.",
          "type": [
            "string",
            "null"
          ]
        },
        "protected_fields": {
          "description": "Authority-bearing JSON arguments and the lineage each is allowed to derive from. These rules are part of the canonical manifest digest.",
          "items": {
            "$ref": "#/definitions/ProtectedField"
          },
          "type": "array"
        },
        "rate_limit": {
          "anyOf": [
            {
              "$ref": "#/definitions/RateLimit"
            },
            {
              "type": "null"
            }
          ],
          "description": "At most `count` calls to this tool in any `window_seconds`, across every run of the tenant."
        },
        "ref": {
          "description": "Which tool, as `tool://server/name`.",
          "type": "string"
        },
        "requires_approval": {
          "description": "Whether a person approves each call, before it happens.",
          "type": "boolean"
        }
      },
      "required": [
        "ref"
      ],
      "type": "object"
    },
    "Topology": {
      "additionalProperties": false,
      "description": "Where this agent sits in a multi-agent arrangement.",
      "properties": {
        "mode": {
          "allOf": [
            {
              "$ref": "#/definitions/TopologyMode"
            }
          ],
          "default": "single",
          "description": "How many agents, and therefore how much coordination risk."
        },
        "reason": {
          "anyOf": [
            {
              "$ref": "#/definitions/Justification"
            },
            {
              "type": "null"
            }
          ],
          "description": "Why collaboration is warranted."
        },
        "role": {
          "allOf": [
            {
              "$ref": "#/definitions/Role"
            }
          ],
          "default": "specialist",
          "description": "What this agent is within that shape."
        }
      },
      "type": "object"
    },
    "TopologyMode": {
      "description": "How many agents contribute to one task.",
      "oneOf": [
        {
          "const": "single",
          "description": "One agent, one context, many tools. Inter-agent failure is structurally absent, which is why it is the default.",
          "type": "string"
        },
        {
          "const": "collaborative",
          "description": "Several agents contribute to one task. The full failure surface.",
          "type": "string"
        }
      ]
    },
    "TriagePriority": {
      "description": "How a triage task is ranked in a worklist.",
      "enum": [
        "low",
        "normal",
        "high",
        "urgent"
      ],
      "type": "string"
    },
    "TriageRule": {
      "additionalProperties": false,
      "description": "One reason to put an answer in front of a person, and who.",
      "properties": {
        "audience": {
          "default": [],
          "description": "Roles that may act on the task. Empty means anyone, which is a choice worth making on purpose rather than by omission.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "deadline": {
          "allOf": [
            {
              "$ref": "#/definitions/OversightDeadline"
            }
          ],
          "description": "The obligation that bounds the task."
        },
        "name": {
          "description": "What the task is called, so a worklist can be filtered on it.",
          "type": "string"
        },
        "priority": {
          "allOf": [
            {
              "$ref": "#/definitions/TriagePriority"
            }
          ],
          "default": "normal",
          "description": "How urgent the row is."
        },
        "summary": {
          "description": "What the worklist row says, in the words a reviewer reads.",
          "type": "string"
        },
        "when": {
          "description": "Every condition that must hold. Conjunctive, and an empty list is refused — a rule matching everything is a task per run written as a filter.",
          "items": {
            "$ref": "#/definitions/Condition"
          },
          "type": "array"
        }
      },
      "required": [
        "name",
        "when",
        "summary",
        "deadline"
      ],
      "type": "object"
    }
  },
  "description": "The shape of an agentplane Agent manifest. The crate's parser stays authoritative: this schema refuses unknown fields, missing fields, and wrong types exactly as the parser does, but the parser's semantic refusals (an unstated budget, a declared control nothing performs) run only there — `agentplane validate` is the full check.",
  "properties": {
    "apiVersion": {
      "description": "Which schema this document claims to be.",
      "type": "string"
    },
    "kind": {
      "description": "What kind of object. `Agent`.",
      "type": "string"
    },
    "metadata": {
      "$ref": "#/definitions/Metadata"
    },
    "spec": {
      "$ref": "#/definitions/Spec"
    }
  },
  "required": [
    "apiVersion",
    "kind",
    "metadata",
    "spec"
  ],
  "title": "agentplane Agent manifest",
  "type": "object"
}
