Sign in

← All schemas

Schema · agent/signal

draft

Agent signal frame

One sensor reading an agent sends on its session WebSocket: a JSON text frame with type signal, accepted only when the welcome's accepts list names signal. The platform reads it, bounds it, and records it as one reading of a sensor registered for the agent (the recorded reading is $defs/reading). One frame is one reading; there is no batch of frames on the wire, a batch is the readings list of the ingest body (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 platform ignores them, and the host label of the recorded reading is the agent id from the verified session, never the frame's host.

https://schemas.inorbit.hr/agent/signal/v0.json
01Versions

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

What changed

One version so far. When a second is published, this is where it is compared with v0, field by field.

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, the agent's clock. The platform 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

Documents with made-up values, the same ones our tests check against the schema: the ones it accepts and the ones it must refuse.

4 valid documentsshow
{
  "type": "signal",
  "sensor": "host.load_1m",
  "template": "host-probe",
  "value": 0.5,
  "level": "ok",
  "series": 1,
  "at": "2026-10-21T00:00:00Z",
  "host": "agt_00000000000000000000000001"
}
13 documents the schema must refuseshow

Each file name says what is wrong with it. Paste one into the check below to see the schema refuse it.

{
  "type": "signal",
  "sensor": "api-errors",
  "value": 7.0,
  "level": "ok",
  "at": "yesterday at noon"
}
04Check a file against it

Paste a document to check it against v0 here, or use the address in your editor or CI.

Checked in your browser. The document is not sent anywhere.
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: a JSON text frame with type signal, accepted only when the welcome's accepts list names signal. The platform reads it, bounds it, and records it as one reading of a sensor registered for the agent (the recorded reading is $defs/reading). One frame is one reading; there is no batch of frames on the wire, a batch is the readings list of the ingest body (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 platform ignores them, and the host label of the recorded 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 platform 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 recorded for an accepted frame (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 the ingest body's readings list; 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"
              ]
            }
          }
        }
      }
    }
  }
}