8gent Code.Docs
Device Kit (8DK), Preview

The manifest

How a device describes itself. Every capability can read the world or can do something in it.

A manifest is the device's description of itself: who it is, and a list of capabilities. The person reads it at pairing. The agent reads it as tool descriptions. A manifest that arrives from a device is untrusted input, so the vessel validates it before anyone sees it.

{
  id: "desk-lamp",
  name: "Desk lamp",
  kind: "lamp",
  version: "0.1.0",
  capabilities: [
    { name: "read_light", kind: "sensor", description: "Is the lamp on, and how bright." },
    {
      name: "set_light",
      kind: "actuator",
      description: "Turn the lamp on or off.",
      params: { on: { type: "boolean", required: true }, brightness: { type: "number" } },
    },
    { name: "strobe", kind: "actuator", description: "Flash the lamp.", confirm: true },
  ],
}

Can read and Can do

Every capability has a kind, and there are two:

In these docskindMeansExample
Can readsensorReads the world and changes nothingread_light
Can doactuatorChanges something in the worldset_light, strobe

The person sees the kind of every capability before allowing it, and so does the agent: a tool description starts with [DEVICE Desk lamp (lamp) sensor] or ... actuator]. Policy rules can match on it too, for example "ask me before any Can do capability" (Capabilities as agent tools).

The kind is what the device declares. 8DK cannot check that a capability marked Can read really changes nothing. See Security model.

Ask every time: confirm

A capability with confirm: true asks the person on every call, even after it is allowed. Use it for anything you would not want done twice by accident: a door lock, a payment, the strobe above.

Fields

FieldRule
idLower case letters and digits in words joined by -, for example desk-lamp. At most 24 characters. Stable for the device.
nameShown to the person at pairing. At most 80 characters.
kindFree text, for example lamp, glasses, phone. At most 40 characters.
versionFree text. At most 40 characters.
capabilitiesAt least 1, at most 32. Names unique.

Each capability:

FieldRule
nameLower snake case, starting with a letter, never containing __. At most 30 characters.
kindsensor or actuator.
descriptionShown to the person and to the agent. At most 500 characters.
paramsOptional. At most 16. Each name is lower snake case (at most 30 characters), each type is string, number or boolean, with an optional description (at most 200 characters) and required.
confirmOptional. true asks the person on every call.

Text fields are refused, never cleaned up, if they contain any control or invisible formatting character: newline, tab and escape, zero-width characters, direction-changing characters, Unicode tag characters and variation selectors. That also refuses an emoji written with a variation selector. A consent prompt has to show exactly what a person would read.

Checking a manifest

FunctionDoes
validateManifest(input)Checks untrusted input and returns a frozen copy, or throws ManifestError.
defineDevice(manifest, handlers)Validates, then requires exactly one handler per capability: none missing, none extra.
manifestDigest(manifest)A SHA-256 of the validated manifest. authenticate compares it, so a changed manifest fails and the device must pair again.
validateInput(capability, input)Checks a call's input: an object, no unknown keys, required keys present, each value the declared type (numbers must be finite). Returns an error message or null.
validateManifest({ id: "Desk Lamp", name: "x", kind: "x", version: "1", capabilities: [] });
// throws ManifestError: manifest id "Desk Lamp" must be lower case words joined by "-"

Next: Pairing.