Schema · agent/signal
Agent signal frame
One sensor reading an agent sends on its session WebSocket (PRD 0152, PRD 0117): a JSON text frame with type signal, accepted only when the welcome's accepts list names signal. The agents service reads it, bounds it, and forwards it as one reading into SensorsService Register and Ingest as svc:agents (the forwarded reading is $defs/reading). One frame is one reading; there is no batch of frames on the wire, a batch is IngestRequest.readings (sensors/ingest). A reading is a number and a level, never content: the object is closed so a body, a prompt, a target, a path or a credential is refused. The fields template, series and host are what the dataplane agent sends besides the core's four; the agents service ignores them, and the host label of the forwarded reading is the agent id from the verified session, never the frame's host. Draft line: it may still be corrected.
https://schemas.inorbit.hr/agent/signal/v0.jsonEach version is a file at its own address. The raw file is plain JSON, served without a sign-in.
- v0draftMay still be corrected; kept for five minutes.schemas.inorbit.hr/agent/signal/v0.json ↗
Fields of v0, the newest version, by path. A name ending in [] is each item of a list. Every field not listed is refused.
typestringrequiredThe frame tag.
Always
"signal"sensorstringrequiredThe sensor's name on the agent: a letter or digit first, then letters, digits, underscore, dot or hyphen. The agents service lowercases it and registers it as <name>.<agent ulid>, at most 64 characters, so the name is at most 37.
pattern ^[A-Za-z0-9][A-Za-z0-9_.-]*$at least 1 charactersat most 37 characterstemplatestringoptionalThe probe template the reading was made from (host-probe, error-rate). Sent by the dataplane agent; the agents service does not read it.
pattern ^[A-Za-z0-9][A-Za-z0-9_.-]*$at least 1 charactersat most 64 charactersvaluenumberoptionalThe value judged, a finite number. Absent when there is none (no series, a failed run); a frame without one is accepted on the session and not forwarded.
levelenumrequiredThe agent's judgement of the value against its thresholds: ok, warn, crit, or unknown when there is no value. The agents service reads any other word as unknown; this schema refuses it.
One of
"ok""warn""crit""unknown"seriesintegeroptionalHow many series the reading was made from. Sent by the dataplane agent; the agents service does not read it.
0 to 1000000atstringrequiredWhen the agent took the reading, RFC 3339, the agent's clock. The sensors service flags a reading whose time and its own are more than 5 minutes apart.
pattern ^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]{1,9})?(Z|[+-]([01][0-9]|2[0-3]):[0-5][0-9])$at most 40 charactershoststringoptionalThe agent's own id on its host probes (agt_ and a ULID); absent on readings from a policy sensor. Never trusted: the forwarded host label comes from the session.
pattern ^agt_[0-9A-Za-z]{10,40}$at most 64 characters
Valid documents with made-up values, as the repository's tests check them.
{
"type": "signal",
"sensor": "host.load_1m",
"template": "host-probe",
"value": 0.5,
"level": "ok",
"series": 1,
"at": "2026-10-21T00:00:00Z",
"host": "agt_01M5C76Q26AB3CD4EF5GH6JK7M"
}The repository's tests also check 13 documents that this schema must refuse.
Replace the file name with yours.
"json.schemas": [
{ "fileMatch": ["my-file.json"], "url": "https://schemas.inorbit.hr/agent/signal/v0.json" }
]check-jsonschema --schemafile https://schemas.inorbit.hr/agent/signal/v0.json my-file.jsonajv validate --spec=draft2020 -s <(curl -s https://schemas.inorbit.hr/agent/signal/v0.json) -d my-file.jsoncurl -s https://schemas.inorbit.hr/agent/signal/v0.jsonThe raw file of v0, as published.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.inorbit.hr/agent/signal/v0.json",
"title": "Agent signal frame",
"description": "One sensor reading an agent sends on its session WebSocket (PRD 0152, PRD 0117): a JSON text frame with type signal, accepted only when the welcome's accepts list names signal. The agents service reads it, bounds it, and forwards it as one reading into SensorsService Register and Ingest as svc:agents (the forwarded reading is $defs/reading). One frame is one reading; there is no batch of frames on the wire, a batch is IngestRequest.readings (sensors/ingest). A reading is a number and a level, never content: the object is closed so a body, a prompt, a target, a path or a credential is refused. The fields template, series and host are what the dataplane agent sends besides the core's four; the agents service ignores them, and the host label of the forwarded reading is the agent id from the verified session, never the frame's host. Draft line: it may still be corrected.",
"type": "object",
"additionalProperties": false,
"required": [
"type",
"sensor",
"level",
"at"
],
"properties": {
"type": {
"description": "The frame tag.",
"const": "signal"
},
"sensor": {
"description": "The sensor's name on the agent: a letter or digit first, then letters, digits, underscore, dot or hyphen. The agents service lowercases it and registers it as <name>.<agent ulid>, at most 64 characters, so the name is at most 37.",
"type": "string",
"minLength": 1,
"maxLength": 37,
"pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]*$"
},
"template": {
"description": "The probe template the reading was made from (host-probe, error-rate). Sent by the dataplane agent; the agents service does not read it.",
"type": "string",
"minLength": 1,
"maxLength": 64,
"pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]*$"
},
"value": {
"description": "The value judged, a finite number. Absent when there is none (no series, a failed run); a frame without one is accepted on the session and not forwarded.",
"type": "number"
},
"level": {
"description": "The agent's judgement of the value against its thresholds: ok, warn, crit, or unknown when there is no value. The agents service reads any other word as unknown; this schema refuses it.",
"enum": [
"ok",
"warn",
"crit",
"unknown"
]
},
"series": {
"description": "How many series the reading was made from. Sent by the dataplane agent; the agents service does not read it.",
"type": "integer",
"minimum": 0,
"maximum": 1000000
},
"at": {
"description": "When the agent took the reading, RFC 3339, the agent's clock. The sensors service flags a reading whose time and its own are more than 5 minutes apart.",
"type": "string",
"maxLength": 40,
"pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]{1,9})?(Z|[+-]([01][0-9]|2[0-3]):[0-5][0-9])$"
},
"host": {
"description": "The agent's own id on its host probes (agt_ and a ULID); absent on readings from a policy sensor. Never trusted: the forwarded host label comes from the session.",
"type": "string",
"maxLength": 64,
"pattern": "^agt_[0-9A-Za-z]{10,40}$"
}
},
"$defs": {
"reading": {
"title": "Forwarded reading",
"description": "The reading the agents service sends to SensorsService Ingest for an accepted frame (proto iohr.sensors.v1.SignalReading, JSON names as the API writes them): the agent's time, the finite value, and exactly two labels, host (the agent id from the verified session) and level (ok, warn, crit, or unknown for any other word). It is one reading in IngestRequest.readings; the sensors/reading schema covers the stored form.",
"type": "object",
"additionalProperties": false,
"required": [
"produced_at",
"value",
"labels"
],
"properties": {
"produced_at": {
"description": "The frame's at, as sent.",
"type": "string",
"maxLength": 40,
"pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]{1,9})?(Z|[+-]([01][0-9]|2[0-3]):[0-5][0-9])$"
},
"value": {
"description": "The frame's value; always present and finite on a forwarded reading.",
"type": "number"
},
"labels": {
"type": "object",
"additionalProperties": false,
"required": [
"host",
"level"
],
"properties": {
"host": {
"description": "The agent id from the verified session.",
"type": "string",
"maxLength": 64,
"pattern": "^agt_[0-9A-Za-z]{10,40}$"
},
"level": {
"description": "The frame's level, or unknown.",
"enum": [
"ok",
"warn",
"crit",
"unknown"
]
}
}
}
}
}
}
}