Skip to content
handupbeta
Download

Event schema

View as Markdown

Generated by handup schema event (make docs) into docs/public/schema/event.schema.json. Raw file: /schema/event.schema.json.

Fields

FieldTypeRequiredDescription
vintegeryesEnvelope version, currently 1.
typeEventTypeyes
idstringyesEvent identifier (ULID), distinct from the request identifier.
timestringyesEvent time in RFC3339 UTC.
dataEventDatayes

Definitions

EventType

"request.created" | "request.decided" | "request.expired" | "request.cancelled" | "request.reminder" | "request.expiring"

EventData

FieldTypeRequired
requestEventRequestyes
decisionDecision | null

EventRequest

FieldTypeRequired
idstringyes
titlestringyes
riskRiskyes
agentstring | null
sourceSourceyes
statusStatusyes
urlstringyes
deep_linkstringyes
contentEventContent | null

Risk

"low" | "medium" | "high"

Source

FieldTypeRequired
integrationstring | null
agentstring | null
sessionstring | null
session_titlestring | null
cwdstring | null
repostring | null
branchstring | null
hoststring | null

Status

"pending" | "approved" | "denied" | "answered" | "dismissed" | "expired" | "cancelled"

EventContent

FieldTypeRequired
summarystring | null
previewsPreview[]yes

Preview

FieldTypeRequired
typePreviewTypeyes
titlestring | null
langstring | null
inlinestring | null
blobstring | null
mimestring | null
namestring | null
sizeinteger | null
filesPreviewFile[] | null
entrystring | null
commandCommand | null
emailEmail | null
before_blobstring | null
after_blobstring | null

PreviewType

"text" | "markdown" | "code" | "diff" | "files" | "command" | "json" | "html" | "image" | "video" | "audio" | "file" | "pdf" | "email"

PreviewFile

FieldTypeRequired
pathstringyes
blobstringyes
mimestringyes
sizeintegeryes
langstring | null

Command

FieldTypeRequired
shellstring | null
argvstring[] | null
cwdstring | null
env_keysstring[]

Email

An email draft for review. handup never sends it: on approval the agent sends the draft (or the edited `decision.fields`) with its own mail tool.

FieldTypeRequired
fromstring | null
tostring[]
ccstring[]
bccstring[]
reply_tostring | null
subjectstring
datestring | null
bodystring
body_htmlstring | null
attachmentsEmailAttachment[]
in_reply_toEmailQuote | null

EmailAttachment

FieldTypeRequired
namestringyes
mimestring | null
sizeinteger | null
blobstring | null

EmailQuote

FieldTypeRequired
fromstring | null
datestring | null
bodystring

Decision

FieldTypeRequired
optionstringyes
feedbackstring | null
fieldsDecisionFields | null
content_hashstringyes
decided_bystring | null
decided_atinteger | null
outcomeOutcome | null
rule_idstring | null
scopestring | null
run_resultRunResult | null

DecisionFields

Decision `fields`. Question requests carry only `answers`, keyed by question id; other requests carry answers to `input.fields` or edited tool input.

FieldTypeRequired
answersobject | null

Answer

The human's answer to one question.

FieldTypeRequired
selectedstring[]
textstring | null

Outcome

"approve" | "deny"

RunResult

Outcome of running a command request in the handup desktop app. The command already ran: an agent must not run it again. Output is the redacted tail of each stream.

FieldTypeRequired
exit_codeinteger | null
stdout_tailstring
stderr_tailstring
duration_msinteger
truncatedboolean
elevatedboolean
errorstring | null

JSON Schema

docs/public/schema/event.schema.json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "EventEnvelope",
"type": "object",
"properties": {
"v": {
"description": "Envelope version, currently 1.",
"type": "integer",
"format": "uint8",
"minimum": 0,
"maximum": 255
},
"type": {
"$ref": "#/$defs/EventType"
},
"id": {
"description": "Event identifier (ULID), distinct from the request identifier.",
"type": "string"
},
"time": {
"description": "Event time in RFC3339 UTC.",
"type": "string"
},
"data": {
"$ref": "#/$defs/EventData"
}
},
"additionalProperties": false,
"required": [
"v",
"type",
"id",
"time",
"data"
],
"$defs": {
"EventType": {
"type": "string",
"enum": [
"request.created",
"request.decided",
"request.expired",
"request.cancelled",
"request.reminder",
"request.expiring"
]
},
"EventData": {
"type": "object",
"properties": {
"request": {
"$ref": "#/$defs/EventRequest"
},
"decision": {
"anyOf": [
{
"$ref": "#/$defs/Decision"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"required": [
"request"
]
},
"EventRequest": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"title": {
"type": "string"
},
"risk": {
"$ref": "#/$defs/Risk"
},
"agent": {
"type": [
"string",
"null"
]
},
"source": {
"$ref": "#/$defs/Source"
},
"status": {
"$ref": "#/$defs/Status"
},
"url": {
"type": "string"
},
"deep_link": {
"type": "string"
},
"content": {
"anyOf": [
{
"$ref": "#/$defs/EventContent"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"required": [
"id",
"title",
"risk",
"source",
"status",
"url",
"deep_link"
]
},
"Risk": {
"type": "string",
"enum": [
"low",
"medium",
"high"
]
},
"Source": {
"type": "object",
"properties": {
"integration": {
"description": "Server-verified integration token name; caller values are overwritten.",
"type": [
"string",
"null"
],
"default": null
},
"agent": {
"type": [
"string",
"null"
],
"default": null
},
"session": {
"type": [
"string",
"null"
],
"default": null
},
"session_title": {
"description": "Display-only session name; scoped rules always use the session ID.",
"type": [
"string",
"null"
]
},
"cwd": {
"type": [
"string",
"null"
],
"default": null
},
"repo": {
"type": [
"string",
"null"
],
"default": null
},
"branch": {
"type": [
"string",
"null"
],
"default": null
},
"host": {
"type": [
"string",
"null"
],
"default": null
}
},
"additionalProperties": false
},
"Status": {
"type": "string",
"enum": [
"pending",
"approved",
"denied",
"answered",
"dismissed",
"expired",
"cancelled"
]
},
"EventContent": {
"type": "object",
"properties": {
"summary": {
"type": [
"string",
"null"
]
},
"previews": {
"type": "array",
"items": {
"$ref": "#/$defs/Preview"
}
}
},
"additionalProperties": false,
"required": [
"previews"
]
},
"Preview": {
"type": "object",
"properties": {
"type": {
"$ref": "#/$defs/PreviewType"
},
"title": {
"type": [
"string",
"null"
]
},
"lang": {
"type": [
"string",
"null"
]
},
"inline": {
"type": [
"string",
"null"
]
},
"blob": {
"type": [
"string",
"null"
]
},
"mime": {
"type": [
"string",
"null"
]
},
"name": {
"type": [
"string",
"null"
]
},
"size": {
"type": [
"integer",
"null"
],
"format": "uint64",
"minimum": 0
},
"files": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/PreviewFile"
}
},
"entry": {
"type": [
"string",
"null"
]
},
"command": {
"anyOf": [
{
"$ref": "#/$defs/Command"
},
{
"type": "null"
}
]
},
"email": {
"anyOf": [
{
"$ref": "#/$defs/Email"
},
{
"type": "null"
}
]
},
"before_blob": {
"type": [
"string",
"null"
]
},
"after_blob": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false,
"required": [
"type"
]
},
"PreviewType": {
"type": "string",
"enum": [
"text",
"markdown",
"code",
"diff",
"files",
"command",
"json",
"html",
"image",
"video",
"audio",
"file",
"pdf",
"email"
]
},
"PreviewFile": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"blob": {
"type": "string"
},
"mime": {
"type": "string"
},
"size": {
"type": "integer",
"format": "uint64",
"minimum": 0
},
"lang": {
"type": [
"string",
"null"
],
"default": null
}
},
"additionalProperties": false,
"required": [
"path",
"blob",
"mime",
"size"
]
},
"Command": {
"type": "object",
"properties": {
"shell": {
"type": [
"string",
"null"
],
"default": null
},
"argv": {
"type": [
"array",
"null"
],
"items": {
"type": "string"
},
"default": null
},
"cwd": {
"type": [
"string",
"null"
],
"default": null
},
"env_keys": {
"type": "array",
"items": {
"type": "string"
},
"default": []
}
},
"additionalProperties": false
},
"Email": {
"description": "An email draft for review. handup never sends it: on approval the agent\nsends the draft (or the edited `decision.fields`) with its own mail tool.",
"type": "object",
"properties": {
"from": {
"type": [
"string",
"null"
]
},
"to": {
"type": "array",
"items": {
"type": "string"
}
},
"cc": {
"type": "array",
"items": {
"type": "string"
}
},
"bcc": {
"type": "array",
"items": {
"type": "string"
}
},
"reply_to": {
"type": [
"string",
"null"
]
},
"subject": {
"type": "string",
"default": ""
},
"date": {
"description": "Date shown in the header, as the agent formats it (e.g. RFC 2822).",
"type": [
"string",
"null"
]
},
"body": {
"description": "Message body as Markdown (plain text renders as-is).",
"type": "string",
"default": ""
},
"body_html": {
"description": "Optional HTML alternative; rendered only in the sandboxed HTML preview frame.",
"type": [
"string",
"null"
]
},
"attachments": {
"type": "array",
"items": {
"$ref": "#/$defs/EmailAttachment"
}
},
"in_reply_to": {
"description": "The message this draft replies to, shown collapsed under the body.",
"anyOf": [
{
"$ref": "#/$defs/EmailQuote"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"EmailAttachment": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"mime": {
"type": [
"string",
"null"
]
},
"size": {
"type": [
"integer",
"null"
],
"format": "uint64",
"minimum": 0
},
"blob": {
"description": "Uploaded blob hash (`POST /v1/blobs`) so the reviewer can open the file.",
"type": [
"string",
"null"
]
}
},
"additionalProperties": false,
"required": [
"name"
]
},
"EmailQuote": {
"type": "object",
"properties": {
"from": {
"type": [
"string",
"null"
]
},
"date": {
"type": [
"string",
"null"
]
},
"body": {
"description": "Plain text of the earlier message (or a snippet of it).",
"type": "string",
"default": ""
}
},
"additionalProperties": false
},
"Decision": {
"type": "object",
"properties": {
"option": {
"type": "string"
},
"feedback": {
"type": [
"string",
"null"
],
"default": null
},
"fields": {
"anyOf": [
{
"$ref": "#/$defs/DecisionFields"
},
{
"type": "null"
}
],
"default": null
},
"content_hash": {
"type": "string"
},
"decided_by": {
"type": [
"string",
"null"
],
"default": null
},
"decided_at": {
"type": [
"integer",
"null"
],
"format": "uint64",
"minimum": 0,
"default": null
},
"outcome": {
"anyOf": [
{
"$ref": "#/$defs/Outcome"
},
{
"type": "null"
}
],
"default": null
},
"rule_id": {
"type": [
"string",
"null"
]
},
"scope": {
"type": [
"string",
"null"
]
},
"run_result": {
"description": "The desktop app ran the request's command for the human: this is how\nit ended. Present only on approved command requests decided by Run.",
"anyOf": [
{
"$ref": "#/$defs/RunResult"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"required": [
"option",
"content_hash"
]
},
"DecisionFields": {
"description": "Decision `fields`. Question requests carry only `answers`, keyed by question\nid; other requests carry answers to `input.fields` or edited tool input.",
"type": "object",
"properties": {
"answers": {
"type": [
"object",
"null"
],
"additionalProperties": {
"$ref": "#/$defs/Answer"
}
}
}
},
"Answer": {
"description": "The human's answer to one question.",
"type": "object",
"properties": {
"selected": {
"description": "Chosen option labels; at most one unless the question is `multi`.",
"type": "array",
"items": {
"type": "string"
},
"default": []
},
"text": {
"description": "Typed answer; only when the question allows free text.",
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
},
"Outcome": {
"type": "string",
"enum": [
"approve",
"deny"
]
},
"RunResult": {
"description": "Outcome of running a command request in the handup desktop app. The\ncommand already ran: an agent must not run it again. Output is the\nredacted tail of each stream.",
"type": "object",
"properties": {
"exit_code": {
"description": "Process exit status; absent when it never started or a signal ended it.",
"type": [
"integer",
"null"
],
"format": "int32"
},
"stdout_tail": {
"description": "Last bytes of standard output (at most 64 KiB), credentials redacted.",
"type": "string",
"default": ""
},
"stderr_tail": {
"description": "Last bytes of standard error (at most 64 KiB), credentials redacted.",
"type": "string",
"default": ""
},
"duration_ms": {
"description": "Wall time from start to exit, in milliseconds.",
"type": "integer",
"format": "uint64",
"minimum": 0,
"default": 0
},
"truncated": {
"description": "Earlier output was dropped from either tail.",
"type": "boolean",
"default": false
},
"elevated": {
"description": "Ran with administrator rights (pkexec on Linux, osascript on macOS).",
"type": "boolean",
"default": false
},
"error": {
"description": "Why it did not finish normally: timeout, cancellation, signal, or a\nstart failure (for example pkexec missing or authentication refused).",
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
}
}