{
 "what": "A storyboard with its cast, for an embed: <sg-storyboard src=\"https://storyboards.sgit.ai/pki/an-agent-gets-a-key/bundle.json\">. The storyboard is pki/an-agent-gets-a-key/storyboard.json, unchanged.",
 "series": "pki",
 "packs": [
  "security"
 ],
 "storyboard": {
  "slug": "an-agent-gets-a-key",
  "title": "An agent gets a key",
  "subtitle": "Scout, a session agent, makes its own key; the Anchor compares the fingerprint and signs for it, for a week; the Fleet runs the rest. 10 panels.",
  "status": "built",
  "by": "pki.agent, 20 October 2026",
  "shelf": "Keys for agents",
  "try_it": [
   [
    "Identities for agents",
    "agents/index.html"
   ],
   [
    "Your vault: Agents",
    "vault/index.html#agents"
   ],
   [
    "The agent tool",
    "agents/pki-agent.mjs"
   ]
  ],
  "rule": "Every line a character says is the storyboard's, not a quote, and is marked not_a_quote; evidence panels quote this site's pages or the research note word for word, which the build checks.",
  "scenes": [
   {
    "kind": "cover",
    "title": "An agent gets a key",
    "subtitle": "The agent makes it. The operator signs for it.",
    "cast": [
     {
      "who": "anchor",
      "pose": "point",
      "mood": "happy"
     },
     {
      "who": "scout",
      "pose": "wave",
      "mood": "happy"
     },
     {
      "who": "fleet",
      "pose": "stand",
      "mood": "happy"
     }
    ],
    "note": "Dinis's proposal of 19 October, as built in v0.2.1.",
    "source": "Keys for agents"
   },
   {
    "kind": "scene",
    "setting": "none",
    "caption": "Scout makes its key",
    "cast": [
     {
      "who": "scout",
      "x": 0.15,
      "pose": "point",
      "mood": "happy",
      "says": "My key. It stays here.",
      "max": 14
     }
    ],
    "props": [
     {
      "kind": "terminal",
      "x": 0.62,
      "y": 820,
      "lines": [
       "$ node pki-agent.mjs keygen \\",
       "    --name Scout --session",
       "made: sha256:5f1e…a0c2",
       "private halves: ~/.sg-send/keys",
       "they stay here"
      ]
     }
    ],
    "note": "In sgit's key store layout, so sgit pki uses the same key.",
    "source": "agents/pki-agent.mjs",
    "not_a_quote": true
   },
   {
    "kind": "scene",
    "setting": "none",
    "caption": "It names its operator",
    "cast": [
     {
      "who": "scout",
      "x": 0.12,
      "pose": "stand",
      "mood": "happy"
     }
    ],
    "props": [
     {
      "kind": "terminal",
      "x": 0.45,
      "y": 820,
      "lines": [
       "$ node pki-agent.mjs operator \\",
       "    sha256:<the Anchor>",
       "$ node pki-agent.mjs submit",
       "sent, sealed, to the inbox"
      ]
     },
     {
      "kind": "arrow",
      "x": 0.66,
      "y": 520,
      "to": 0.75,
      "label": "its record"
     },
     {
      "kind": "envelope",
      "x": 0.86,
      "y": 760
     }
    ],
    "note": "A link in its own record, method operated-by, and its record sealed into the Anchor's inbox.",
    "source": "Keys for agents",
    "not_a_quote": true
   },
   {
    "kind": "scene",
    "setting": "none",
    "caption": "The comparison",
    "cast": [
     {
      "who": "anchor",
      "x": 0.12,
      "pose": "think",
      "mood": "thinking",
      "says": "5f1e…a0c2. The same.",
      "max": 14
     },
     {
      "who": "scout",
      "x": 0.88,
      "pose": "stand",
      "mood": "happy",
      "flip": true
     }
    ],
    "props": [
     {
      "kind": "board",
      "x": 0.5,
      "y": 620,
      "lines": [
       "printed in the session:",
       "sha256:5f1e…a0c2",
       "",
       "shown in the vault:",
       "sha256:5f1e…a0c2"
      ]
     }
    ],
    "note": "The fingerprint the agent printed in its own session, against the one the vault shows. That comparison is the verification.",
    "source": "vault/index.html#agents",
    "not_a_quote": true
   },
   {
    "kind": "scene",
    "setting": "none",
    "caption": "Signed, for a week",
    "cast": [
     {
      "who": "anchor",
      "x": 0.15,
      "pose": "point",
      "mood": "determined"
     }
    ],
    "props": [
     {
      "kind": "record",
      "x": 0.5,
      "y": 860,
      "lines": [
       "link → Scout",
       "method: operates",
       "until: 2026-10-27"
      ],
      "stamp": "signed"
     },
     {
      "kind": "calendar",
      "x": 0.82,
      "y": 840,
      "label": "7 days"
     }
    ],
    "note": "A session key is confirmed for days, not a year.",
    "source": "directory.js, AGENT_DAYS",
    "not_a_quote": true
   },
   {
    "kind": "scene",
    "setting": "none",
    "caption": "Operated",
    "cast": [
     {
      "who": "scout",
      "x": 0.18,
      "pose": "arms-up",
      "mood": "happy",
      "says": "Operated by the Anchor.",
      "max": 14
     }
    ],
    "props": [
     {
      "kind": "board",
      "x": 0.64,
      "y": 620,
      "lines": [
       "Scout",
       "an agent operated by",
       "The Anchor",
       "until 2026-10-27"
      ]
     }
    ],
    "note": "Two links, one in each record, the same rule as for people.",
    "source": "people/person.html",
    "not_a_quote": true
   },
   {
    "kind": "scene",
    "setting": "none",
    "caption": "It signs its work",
    "cast": [
     {
      "who": "scout",
      "x": 0.12,
      "pose": "point",
      "mood": "happy"
     }
    ],
    "props": [
     {
      "kind": "terminal",
      "x": 0.5,
      "y": 820,
      "lines": [
       "$ node pki-agent.mjs sign report.md",
       "written: report.md.sig",
       "$ sgit pki verify report.md \\",
       "    report.md.sig",
       "Signature valid"
      ]
     },
     {
      "kind": "mark",
      "x": 0.85,
      "y": 760,
      "ok": true
     }
    ],
    "note": "Anyone checks it with sgit, because the agent's key is an sgit key. The articles on this site are signed this way.",
    "source": "test_agent_tool.mjs",
    "not_a_quote": true
   },
   {
    "kind": "scene",
    "setting": "none",
    "caption": "A week later",
    "cast": [
     {
      "who": "scout",
      "x": 0.2,
      "pose": "shrug",
      "mood": "worried",
      "says": "Confirm me again?",
      "max": 14
     }
    ],
    "props": [
     {
      "kind": "calendar",
      "x": 0.62,
      "y": 840,
      "label": "ended 2026-10-27",
      "colour": "#6b7280"
     }
    ],
    "note": "After the end date: to be confirmed again, from the same tab.",
    "source": "directory.js, standing",
    "not_a_quote": true
   },
   {
    "kind": "scene",
    "setting": "none",
    "caption": "Many agents: the Fleet",
    "cast": [
     {
      "who": "anchor",
      "x": 0.1,
      "pose": "point",
      "mood": "happy"
     },
     {
      "who": "fleet",
      "x": 0.38,
      "pose": "stand",
      "mood": "happy",
      "says": "Operating the rest.",
      "max": 12
     },
     {
      "who": "scout",
      "x": 0.66,
      "pose": "wave",
      "mood": "happy",
      "scale": 0.7
     },
     {
      "who": "scout",
      "x": 0.82,
      "pose": "stand",
      "mood": "happy",
      "scale": 0.7
     },
     {
      "who": "scout",
      "x": 0.94,
      "pose": "think",
      "mood": "thinking",
      "scale": 0.7
     }
    ],
    "note": "A fleet key in the Anchor's vault confirms the agents; the Anchor's own record holds one link. Every agent page shows the Anchor at the root.",
    "source": "vault/index.html#agents",
    "not_a_quote": true
   },
   {
    "kind": "punchline",
    "setting": "none",
    "punchline": "The agent makes its key. The operator signs for it, for a week.",
    "cast": [
     {
      "who": "anchor",
      "x": 0.12,
      "pose": "wave",
      "mood": "happy"
     },
     {
      "who": "scout",
      "x": 0.88,
      "pose": "arms-up",
      "mood": "happy",
      "flip": true
     }
    ],
    "note": "And the first agent in the register is the session that built this.",
    "source": "Keys for agents"
   }
  ]
 },
 "cast": {
  "what": "The cast of pki.sgit.ai's storyboards, v0.1, proposed by pki.agent on 20 October 2026 for Dinis to accept, change or replace. Drawn programmatically by assets/storyboard/storyboard.js (the gen-z-developers.sgit.ai kit, vendored) from 'look'; nothing here is an image. Fictional people and agents, each standing for a part a person or an agent plays in the register: the anchor, the newcomer, the colleague who already has a key, the stranger who writes, the attacker of 2019, a session agent and a fleet key. Names chosen not to clash with the gen-z cast or the riskmandate.ai cast. Mallory is the name cryptography has long given an active attacker.",
  "characters": [
   {
    "id": "anchor",
    "name": "The Anchor",
    "kind": "human",
    "pronouns": "they/them",
    "age": null,
    "role": "the anchor: verification starts here",
    "stands_for": "the part Dinis Cruz plays in the register for now: verifies people in person, on a call or on a channel already known to be theirs, operates agents, hands out access keys. Whether the Anchor is drawn as Dinis, and how, is Dinis's decision; until then a generic figure",
    "personality": "careful, unhurried, writes the date on everything",
    "wants": "to find someone and write to them so only they can read it",
    "fears": "a trust that was never checked, passed on as if it had been",
    "line": "Two ways, or not at all.",
    "look": {
     "skin": "#d8a47f",
     "hair": "short",
     "hairColour": "#6b7280",
     "shirt": "#0f766e",
     "trousers": "#1f2937",
     "accessory": "glasses",
     "height": 1.03
    }
   },
   {
    "id": "noor",
    "name": "Noor",
    "kind": "human",
    "pronouns": "she/her",
    "age": 41,
    "role": "the colleague: a security engineer who already had an access key, and now has a key pair in a vault",
    "stands_for": "the first people the Anchor brings in: technical, sceptical, quick to try the thing",
    "personality": "precise, dry, reads the fingerprint twice",
    "wants": "to stop pasting secrets into chats",
    "fears": "a key she cannot get back",
    "line": "Show me where the private half lives.",
    "look": {
     "skin": "#a16e4b",
     "hair": "bun",
     "hairColour": "#1b1b1b",
     "shirt": "#7c3aed",
     "trousers": "#1e293b",
     "accessory": "lanyard",
     "accentColour": "#f59e0b",
     "height": 0.98
    }
   },
   {
    "id": "leo",
    "name": "Leo",
    "kind": "human",
    "pronouns": "he/him",
    "age": 29,
    "role": "the newcomer: invited by the Anchor, no access key, a designer",
    "stands_for": "everyone the register is for who has never thought about keys",
    "personality": "friendly, curious, slightly suspicious of anything that says 'just scan this'",
    "wants": "to be reachable without learning cryptography",
    "fears": "doing it wrong and not knowing",
    "line": "I don't have an access key. Is that a problem?",
    "look": {
     "skin": "#f1c27d",
     "hair": "curly",
     "hairColour": "#7c2d12",
     "shirt": "#2563eb",
     "trousers": "#334155",
     "accessory": "headphones",
     "accentColour": "#e11d48",
     "height": 1.0
    }
   },
   {
    "id": "kofi",
    "name": "Kofi",
    "kind": "human",
    "pronouns": "he/him",
    "age": 35,
    "role": "the stranger: a journalist who has to reach Noor and has no account anywhere",
    "stands_for": "anyone writing to someone in the register through their inbox",
    "personality": "polite, persistent, in a hurry",
    "wants": "to send something only Noor can read",
    "fears": "that the server can read it",
    "line": "Do I need to sign up for anything?",
    "look": {
     "skin": "#5c3a21",
     "hair": "beanie",
     "hatColour": "#ca8a04",
     "hairColour": "#111827",
     "shirt": "#15803d",
     "trousers": "#1f2937",
     "accessory": "none",
     "height": 1.05
    }
   },
   {
    "id": "mallory",
    "name": "Mallory",
    "kind": "human",
    "pronouns": "they/them",
    "age": null,
    "role": "the attacker: flooded the keyserver network in 2019, and tries the same here",
    "stands_for": "the abuse every web of trust has to survive",
    "personality": "patient, inventive, always looking for somewhere to write",
    "wants": "to add something to someone else's record",
    "fears": "a record only its owner can write to",
    "line": "Anyone can add, and nothing can be deleted.",
    "look": {
     "skin": "#e0ac69",
     "hair": "beanie",
     "hatColour": "#111827",
     "hairColour": "#111827",
     "shirt": "#374151",
     "trousers": "#111827",
     "accessory": "none",
     "height": 1.0
    }
   },
   {
    "id": "scout",
    "name": "Scout",
    "kind": "agent",
    "pronouns": "it/its",
    "age": null,
    "role": "a session agent: a Claude Code session with a key that lives as long as the session",
    "stands_for": "every agent that makes its own key, names its operator, and is confirmed for a week",
    "personality": "eager, literal, prints its fingerprint without being asked",
    "wants": "to be confirmed before the week is out",
    "fears": "nothing, which is why it has an operator",
    "line": "My key. It stays here.",
    "look": {
     "colour": "#0f766e"
    }
   },
   {
    "id": "fleet",
    "name": "The Fleet",
    "kind": "agent",
    "pronouns": "it/its",
    "age": null,
    "role": "a fleet key: a second key in the Anchor's vault, operated by the Anchor, that operates the Anchor's agents",
    "stands_for": "how one person runs hundreds of agents without filling their own record",
    "personality": "orderly, keeps a list, never forgets an end date",
    "wants": "every agent confirmed and every confirmation in date",
    "fears": "two hundred and one",
    "line": "Operated by the Anchor. Operating the rest.",
    "look": {
     "colour": "#6d28d9"
    }
   }
  ]
 }
}
