Sign in

← All schemas

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.

Canonical $id, draft
https://schemas.inorbit.hr/agent/signal/v0.json
01Versions

Each version is a file at its own address. The raw file is plain JSON, served without a sign-in.

02Fields

Fields of v0, the newest version, by path. A name ending in [] is each item of a list. Every field not listed is refused.

  • typestringrequired

    The frame tag.

    Always"signal"

  • sensorstringrequired

    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.

    pattern ^[A-Za-z0-9][A-Za-z0-9_.-]*$at least 1 charactersat most 37 characters

  • templatestringoptional

    The 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 characters

  • valuenumberoptional

    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.

  • levelenumrequired

    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.

    One of"ok""warn""crit""unknown"

  • seriesintegeroptional

    How many series the reading was made from. Sent by the dataplane agent; the agents service does not read it.

    0 to 1000000

  • atstringrequired

    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.

    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 characters

  • hoststringoptional

    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.

    pattern ^agt_[0-9A-Za-z]{10,40}$at most 64 characters

03Examples

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.

04Check a file against it

Replace the file name with yours.

VS Code, JetBrains: settings
"json.schemas": [
  { "fileMatch": ["my-file.json"], "url": "https://schemas.inorbit.hr/agent/signal/v0.json" }
]
check-jsonschema
check-jsonschema --schemafile https://schemas.inorbit.hr/agent/signal/v0.json my-file.json
ajv-cli
ajv validate --spec=draft2020 -s <(curl -s https://schemas.inorbit.hr/agent/signal/v0.json) -d my-file.json
curl
curl -s https://schemas.inorbit.hr/agent/signal/v0.json
05The schema itself

The raw file of v0, as published.

schemas.inorbit.hr/agent/signal/v0.json
{
  "$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"
              ]
            }
          }
        }
      }
    }
  }
}