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

The definition

definition.json declares the record types a routine produces, how each record is identified, which settings filter which fields, the default views, and learning.

What it is

definition.json is the data model of a routine. It declares the record types the routine writes, the fields on each, how a record is identified across runs, which settings filter which fields, the views the Desk shows by default, whether the routine uses the Inbox, and how it learns.

The Desk knows nothing about jobs, roles or companies. Everything it shows (navigation labels, columns, filters, setting controls) comes from the compiled definition.

Why it exists

Without a declared model, every run invents its own shape and nothing can be compared week to week. A definition lets code do the exact work: mint the same id for the same role every run, apply the same filter every run, and show the same columns every run. It also gives learning its only lever: a setting filter is the binding learning may change.

How it works

  1. You write definition.json in the routine folder.
  2. lint checks it: type names, identity rules, field types, views, learning keys.
  3. compile (or seed, which compiles) merges the definitions of every producer on the workspace into one document, meta/definition, with a 12 character version hash.
  4. The Desk and the write step read meta/definition. Each run records the definitionVersion it used.

When two producers share a workspace and declare the same type, compile requires the same identity rule, the same merge default and the same type for any shared field. Fields are unioned in declared order; links and setting filters are combined.

Worked example

Hiring Signals declares two types. A trimmed copy:

{
  "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}
}

Read it as: a company is the same company when its domain is the same; a role is the same role when its URL is the same. A role links to a company. Three settings filter roles. The Desk opens on new roles, newest first.

Compile it:

python3 skills/routineos/scripts/routineos.py compile hiring-signals --out md.json
ok: 1 producer(s), version eda3cea96ab1, wrote md.json

Reference

Top level

Key Type Notes
version number Your version of the definition
label string Shown on the Desk for this producer
inbox bool Whether the producer writes Inbox messages
types object Type name to type; names match ^[a-z][a-z0-9]*(-[a-z0-9]+)*$
views list Default views; see Views
learning object See Learning

Type

Key Notes
label, plural Display names; plural labels the Desk list
identity domain, name or field:<field>; see Records
merge merge (default) or separate; see Merges
fields Field name to field
links Types this type links to
settingFilters [{setting, field}]: which setting filters which field

Field

Key Notes
label Column and form label
type text, number, date, url, choice, list, bool
summary true shows the field on the record summary
choices For choice fields

Common pitfalls

  • Identity on a field that changes. A role keyed on title would split every time a title is reworded. Key on something stable: a URL, a domain.
  • A filter on an undeclared setting. Each settingFilters entry must name a [[setting]] in routine.toml with a role of include or exclude.
  • Expecting a definition change to re-key records. Ids are minted when a record is first written. Changing identity or merge policy affects new ids only; existing documents are never re-keyed.
  • A compiled definition over 256 KiB. Compile refuses it. Very large choice lists belong in a setting, not a field.

Was this page helpful?