{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "v": {
      "type": "number",
      "const": 1,
      "description": "Protocol major version."
    },
    "type": {
      "type": "string",
      "const": "agent.attached"
    },
    "id": {
      "type": "string",
      "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
      "description": "The event's own id. Stable across a retry of the same event."
    },
    "ts": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "description": "When it happened, by Chips' clock. Stamped on the way in; a value the sender writes is replaced."
    },
    "workspace_id": {
      "type": "string",
      "pattern": "^ws_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
      "description": "A workspace identifier: `ws_` followed by a ULID."
    },
    "space_id": {
      "description": "The space, when the event belongs to one.",
      "type": "string",
      "pattern": "^spc_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
    },
    "run_id": {
      "description": "The run, when the event belongs to one.",
      "type": "string",
      "pattern": "^run_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
    },
    "seq": {
      "description": "Assigned by the server on append, monotonic per workspace. Absent on the way in.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "idempotency_key": {
      "description": "Required on every client-originated write. Sending the same key twice is a no-op.",
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "actor": {
      "type": "object",
      "properties": {
        "kind": {
          "type": "string",
          "enum": [
            "person",
            "harness",
            "agent",
            "system"
          ],
          "description": "Whether a person, a harness, one of a harness's agents or Chips itself acted."
        },
        "id": {
          "type": "string",
          "minLength": 1,
          "description": "The participant id, or `system` for Chips."
        },
        "harness_id": {
          "description": "For an agent: the harness it speaks through, whose budget and runs are the agent's (ADR 0087). Filled in by Chips.",
          "type": "string",
          "pattern": "^hrn_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
        }
      },
      "required": [
        "kind",
        "id"
      ],
      "description": "The participant an event is attributed to."
    },
    "agent_id": {
      "type": "string",
      "pattern": "^agt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
      "description": "The agent, in the room this event's `space_id` names."
    },
    "by": {
      "description": "Who put it there: a person, its harness, or Chips (`system`).",
      "type": "string",
      "minLength": 1,
      "maxLength": 120
    },
    "moved_from": {
      "description": "The room it left for this one, when moved.",
      "type": "string",
      "pattern": "^spc_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
    },
    "fork_of": {
      "description": "The `agent.fork` this copy answers, when it is a fork's copy (ADR 0087, Fork).",
      "type": "string",
      "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
    },
    "made_for": {
      "description": "The `agent.asked` this new agent answers, when a person asked for it (ADR 0108).",
      "type": "string",
      "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
    },
    "catch_up": {
      "description": "The room's last lines before the agent joined, within the budget its harness gave in `hello` (ADR 0088, point 5). Added as it is sent to the harness; the log does not keep it.",
      "type": "object",
      "properties": {
        "lines": {
          "maxItems": 200,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "seq": {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991,
                "description": "Where in the log it happened."
              },
              "at": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "description": "When."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "said",
                  "joined",
                  "left",
                  "renamed",
                  "archived",
                  "unarchived"
                ],
                "description": "`said`: a message, addressed to this harness or not. `joined` and `left`: somebody came into the room or went. `renamed`: somebody took a new name, or the room a new title. `archived` and `unarchived`: the room was put away or brought back."
              },
              "from": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "Their participant id, or `system`."
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "person",
                      "harness",
                      "agent",
                      "system"
                    ]
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "What they go by now."
                  },
                  "role": {
                    "description": "Their standing in this room, when they are in it (SEC-15).",
                    "type": "string",
                    "enum": [
                      "owner",
                      "member",
                      "guest"
                    ]
                  },
                  "workspace_role": {
                    "description": "A person's standing in the workspace (SEC-15): the plain form says it after the name, so a guest's line reads as a guest's. Absent for an agent or a harness.",
                    "type": "string",
                    "enum": [
                      "owner",
                      "admin",
                      "member",
                      "guest"
                    ]
                  }
                },
                "required": [
                  "id",
                  "kind",
                  "name"
                ],
                "description": "Who: the one who said it, came, went or took the new name; for the room's own lines, who retitled, archived or unarchived it."
              },
              "message_id": {
                "description": "On `said`: the message.",
                "type": "string",
                "pattern": "^msg_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
              },
              "text": {
                "description": "On `said`: the words as they read now, so an edited message reads edited; a deleted one is not a line. Cut with an ellipsis when the one line is longer than the whole budget.",
                "type": "string",
                "maxLength": 64000
              },
              "transcript": {
                "description": "On `said`: what a voice note said, as the server heard it (ADR 0054).",
                "type": "string",
                "maxLength": 50000
              },
              "files": {
                "description": "On `said`: the names of the files it carried.",
                "maxItems": 20,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 255
                }
              },
              "addressed_to": {
                "description": "On `said`: the agents it was for (ADR 0081, ADR 0087), so a harness can leave out a line one of its agents already took a turn on. Absent on a message from before Chips said so.",
                "maxItems": 64,
                "type": "array",
                "items": {
                  "type": "string",
                  "pattern": "^(?:agt|hrn)_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                  "description": "An agent identifier (`agt_`, ADR 0087), or a harness's (`hrn_`) for one written before agents."
                }
              },
              "held": {
                "description": "On `said`: the guard held it (ADR 0081), so it was for nobody.",
                "type": "boolean",
                "const": true
              },
              "name": {
                "description": "On `renamed`, for a participant: the name they took.",
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "previous": {
                "description": "On `renamed`, for a participant: the name they went by until then.",
                "type": "string",
                "minLength": 1,
                "maxLength": 120
              },
              "title": {
                "description": "On `renamed`, for the room: its new title.",
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              }
            },
            "required": [
              "seq",
              "at",
              "kind",
              "from"
            ],
            "description": "One line of a room: something said, or something that happened to who is in it."
          },
          "description": "Oldest first, the newest that fit the budget."
        },
        "since_seq": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "description": "Where they start: after this `seq`. With a message, where the turn that said the harness's own last message in the room began (ADR 0105), else its joining; from the pull route, 0."
        },
        "truncated": {
          "type": "boolean",
          "description": "Whether older lines after `since_seq` were left out to fit the budget."
        },
        "before": {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991,
          "description": "A cursor: `GET /v1/spaces/:id/context?before=` this reads what came before these lines."
        },
        "files": {
          "description": "The room's files at their current version, newest first, the 20 newest (ADR 0099): with a message, as of it, its own files included; from the pull route, as of now. Each with a URL for this harness. Absent from a Chips before files, and when the room has none.",
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255,
                "description": "The file's name, which its versions share."
              },
              "version": {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991,
                "description": "Which version this is: 1 for the first, counting each change of its bytes."
              },
              "attachment_id": {
                "type": "string",
                "pattern": "^att_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
                "description": "The attachment that is this version: what a post names in `replaces` when it changes it."
              },
              "sha256": {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$",
                "description": "Lowercase hex digest of this version's bytes."
              },
              "byte_size": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Size in bytes."
              },
              "mime_type": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255,
                "description": "Sniffed from the bytes on upload."
              },
              "by": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "Their participant id."
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "person",
                      "harness",
                      "agent",
                      "system"
                    ]
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "What they go by now."
                  }
                },
                "required": [
                  "id",
                  "kind",
                  "name"
                ],
                "description": "Who posted this version, as a line's `from` says it."
              },
              "at": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                "description": "When this version was posted."
              },
              "message_id": {
                "description": "The message that posted this version.",
                "type": "string",
                "pattern": "^msg_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
              },
              "width": {
                "description": "Pixels, for a photo or a video.",
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991
              },
              "height": {
                "description": "Pixels, for a photo or a video.",
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991
              },
              "duration_ms": {
                "description": "Milliseconds, for a sound or a video.",
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "replaces": {
                "description": "In one name's versions (`?name=`): the version this one was made from, as its post said (`message.post.replaces`). Absent where the post said nothing, or named no version of this file.",
                "type": "string",
                "pattern": "^att_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
              },
              "url": {
                "description": "For a harness: a signed URL for this version, bound to its token, as a message's attachments are. Absent for a person, who fetches it by id.",
                "type": "string",
                "format": "uri"
              },
              "url_expires_at": {
                "description": "When `url` stops working.",
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
              }
            },
            "required": [
              "name",
              "version",
              "attachment_id",
              "sha256",
              "byte_size",
              "mime_type",
              "by",
              "at"
            ],
            "description": "One of a room's files at one of its versions: the current one, in the room's list (ADR 0099)."
          }
        },
        "spend": {
          "description": "What the room's job has spent, as of the message (for one Chips held, as of its hand-over, when a new job began), against what the room allows a job (ADR 0117). With a message only; the room note says it in words. Absent from a Chips before it.",
          "type": "object",
          "properties": {
            "ceiling_usd": {
              "type": "number",
              "exclusiveMinimum": 0,
              "description": "What the room allows a job, in US dollars: its own ceiling, or the default (3) when nobody has set one."
            },
            "spent_usd": {
              "type": "number",
              "minimum": 0,
              "description": "What the room's runs reported costing since the job began, in US dollars, every harness's together."
            },
            "since_seq": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991,
              "description": "Where the job began: the `seq` of the last thing a person did in the room, or of the last brief handed into it, whichever is later; 0 when neither has happened."
            },
            "uncounted_runs": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991,
              "description": "How many of the job's runs reported no cost, and so count nothing."
            }
          },
          "required": [
            "ceiling_usd",
            "spent_usd",
            "since_seq",
            "uncounted_runs"
          ]
        }
      },
      "required": [
        "lines",
        "since_seq",
        "truncated",
        "before"
      ]
    }
  },
  "required": [
    "v",
    "type",
    "id",
    "ts",
    "workspace_id",
    "actor",
    "agent_id"
  ],
  "description": "An agent was put in a room: added, moved in, or brought back. Its harness is handed the room's last lines with it.",
  "$id": "https://chipschat.ai/schema/v1/agent.attached.json",
  "title": "AgentAttached"
}
