Skip to content
RoutineOS
Esc
↑↓navigate↵open⌘Jpreview
On this page

Definition schema

Every key in definition.json (types, fields, identity, merge, links, setting filters, views, learning, inbox), what lint refuses, and the shape of the compiled meta/definition. Taken from definition.py.

definition.json declares what a routine records and how the Desk shows it. definition.py lints it and compiles one or more definitions into the meta/definition document the Desk and the write step read. See Definition for the concept.

Top level

Key Type Required Meaning
version integer yes 1 or more. Raise it when the definition changes
label text no The producer’s label on the Desk. Falls back to the routine name
inbox bool no The producer writes Inbox messages. Then max_inbox_per_run must be a number setting
types object yes Record types, keyed by type name
views list no Views shipped with the routine
learning object no Learning block. Absent means learning is off

Types

A type name is lowercase letters and digits with single hyphens (^[a-z][a-z0-9]*(-[a-z0-9]+)*$).

Key Type Required Meaning
label text no Singular label
plural text no Plural label
identity text yes domain, name or field:<field>
merge text no merge (default) or separate
fields object yes At least one field
links list no Type names this type links to. Each must be declared
settingFilters list no {setting, field} pairs

Identity rules

Rule Key
field:<name> The value of that field, for example field:url for a role
domain The record’s key, else values.domain, else values.name. A value that is not a domain once normalised uses the name rule
name The normalised name

The entity id is <type>--<slug(key)>. Slugs are lowercase [a-z0-9-], at most 120 characters, with a SHA-1 suffix for longer keys. Two keys that slug the same fail the plan with both named. With merge policy separate, the id is <type>--<slug(producerId--key)>.

Fields

Key Type Required Meaning
type text yes text, number, date, url, choice, list, bool
label text no Shown on the Desk
summary bool no Shown in summaries
choices list choice only Non-empty

Setting filters

"settingFilters": [{"setting": "title_keywords", "field": "title"}]

The setting must be declared in routine.toml, be a list, and have a role of include or exclude. The field must be declared on the type. Text fields match case-insensitive substrings; other types match whole values, case-insensitive for strings. A filtered record is kept with status: "dropped" and a dropReason such as not in title_keywords.

Views

Key Type Values
id text ^[a-z0-9][a-z0-9-]*$
type text A declared type
name text Shown on the Desk
filters object q, status, starred, tag, source, reason, fields
filters.status text all, active, dropped
filters.fields object {field: value}, the one value a declared field must equal
window text all, week, month, last-month
sort object {field, dir}, dir asc or desc
group text A field name
columns list Field names

Besides declared fields, a view may name the meta fields lastSeen, firstSeen, seenCount, status and dropReason. A field filter at the top level of filters is an error. Views that people save and views the agent proposes use the same shape. See Views.

Learning

Key Default Range
enabled required bool
signals all on {signal: bool}; signals override, uncaptured_term, dead_item, source_health, limit_pressure, connections, edit_drift, manual_repetition
limits [] max_inbox_per_run, declared as a number setting
minSample 5 at least 1
minEffect 0.6 above 0, at most 1
cooldownDays 14 at least 0
maxPerRun 3 0 to 10
deadAfterRuns 10 at least 2

Since 0.5.0: a ninth signal, people_drop.

Example: Hiring Signals

From templates/jobs-watch/definition.json, fields shortened:

{
  "version": 1,
  "label": "Jobs watch",
  "inbox": true,
  "types": {
    "company": {
      "label": "Company", "plural": "Companies",
      "identity": "domain", "merge": "merge",
      "fields": {"name": {"label": "Name", "type": "text", "summary": true},
                 "domain": {"label": "Domain", "type": "url", "summary": true}},
      "settingFilters": [{"setting": "excluded_companies", "field": "domain"}]
    },
    "role": {
      "label": "Role", "plural": "Roles",
      "identity": "field:url", "merge": "merge",
      "links": ["company"],
      "fields": {"title": {"label": "Title", "type": "text", "summary": true},
                 "market": {"label": "Market", "type": "choice", "choices": ["AU", "US", "CA", "NZ", "PH", "GB", "DE"], "summary": true},
                 "url": {"label": "URL", "type": "url"}},
      "settingFilters": [{"setting": "markets", "field": "market"},
                         {"setting": "title_keywords", "field": "title"},
                         {"setting": "excluded_companies", "field": "company_domain"}]
    }
  },
  "views": [
    {"id": "new-roles", "type": "role", "name": "New roles", "filters": {"status": "active"},
     "sort": {"field": "firstSeen", "dir": "desc"}, "columns": ["title", "company", "market", "posted"]}
  ],
  "learning": {"enabled": true}
}

The full role type also has company, company_domain, location, remote, salary_max, posted, seniority and summary. The template ships two more views, dropped-roles and hiring-companies.

What lint checks

  • version is a whole number of 1 or more; types is a non-empty object.
  • Each type: a valid name, at least one field, known field types, a choices list on choice fields, a valid identity rule naming a declared field, a known merge policy, links to declared types.
  • Each setting filter names a declared list setting with a role, and a declared field.
  • Each view passes the view rules above.
  • The learning block has only known keys, known signals and in-range numbers, and limits names declared number settings it can tune.
  • No never-learnable setting (a name containing push, gate, send, alert, permission, budget, maxruns or capoverride, ignoring case and separators) is bound while learning is on.
  • inbox: true needs a number setting max_inbox_per_run.

Each problem prints as FAIL definition.json: <problem>.

The compiled meta/definition

compile merges every producer’s definition into one document with the keys producers, schema, types, version and views. Each entry in producers carries the producer’s id, label, schedule, definitionVersion, inbox, its type names, its settings schema, and its learning config with every default filled in. version is a short hash of the compiled content, printed by compile (for example eda3cea96ab1). A compiled document over 256 KiB is refused.

Was this page helpful?