JSON Reference

JSON Configuration Reference

This page is the reference for the JSON files in tools/. You’ll rarely need to touch them by hand, most of the time the configuration UI is quicker and catches mistakes as you type.

You don’t need JSON to use Tools. Keep using the UI unless you want Git-friendly diffs, you’re copying config between environments, or you’re doing bulk edits.

File structure

Configuration files are stored in the tools/ directory at your project root:

my-project/
├── schema.keel
└── tools/
    ├── get-order.json       # Tool-specific config
    ├── list-orders.json
    ├── create-order.json
    └── _fields.json         # Global field formatting

Each tool has its own file named using the tool's ID (action name in kebab-case). The _fields.json file contains field-level formatting that applies across all tools.

Action tool schema

{
  "id": "get-order",
  "action_name": "getOrder",
  "name": "View Order",
  "title": "Order #{{$.reference}}",
  "help_text": "Displays the full details of a single order",
  "icon": "shopping-cart",
  "entity_single": "order",
  "entity_plural": "orders",
  "capabilities": {
    "comments": true,
    "audit": true
  },
  "inputs": {},
  "response": {},
  "sections": [],
  "external_links": [],
  "display_layout": {},
  "embedded_tools": [],
  "entry_activity_actions": [],
  "related_actions": [],
  "get_entry_action": {},
  "create_entry_action": {},
  "filter_config": {},
  "pagination": {}
}

Top-level fields

FieldTypeDescription
idstringUnique identifier, typically kebab-case of action name
action_namestringThe schema action name (e.g. getOrder)
namestringDisplay name in the Console sidebar
titlestringTitle template, supports {{$.field}} placeholders
help_textstringDescription below the title, supports markdown
iconstringIcon name from the icon library
entity_singlestringSingular noun (e.g. "order")
entity_pluralstringPlural noun (e.g. "orders")

Capabilities

{
  "capabilities": {
    "comments": true,
    "audit": true
  }
}
CapabilityDescription
commentsEnable comments section on records
auditEnable audit trail showing record history

Flow tool schema

{
  "id": "process-refund",
  "flow_name": "processRefund",
  "name": "Process Refund",
  "help_text": "Initiates the refund workflow",
  "icon": "refresh-cw",
  "completion_redirect": {
    "tool_id": "get-order"
  },
  "inputs": {}
}
FieldTypeDescription
idstringUnique identifier
flow_namestringThe schema flow name
namestringDisplay name in the Console
help_textstringDescription below the title
iconstringIcon name
completion_redirectobjectTool to redirect to after completion
inputsobjectInput field configuration

Input configuration

Configure input fields in the inputs object. Keys are JSON paths to each field.

{
  "inputs": {
    "$.reference": {
      "display_name": "Order Reference",
      "help_text": "A unique identifier for this order",
      "placeholder": "ORD-001",
      "display_order": 1
    },
    "$.customer.id": {
      "display_name": "Customer",
      "lookup_action": {
        "tool_id": "list-customers"
      }
    },
    "$.internalNotes": {
      "visible": false
    }
  }
}

Input field options

FieldTypeDescription
display_namestringLabel shown above the input
display_ordernumberPosition in form (lower = first)
visiblebooleanWhether field is shown (default: true)
help_textstringGuidance text below input
placeholderstringPlaceholder text inside input
lockedbooleanPrevents editing when true
default_valueobjectPre-populated value
visible_conditionstringCEL expression for conditional visibility
section_namestringGroups input into a named section
lookup_actionobjectLink to list action for selecting values
get_entry_actionobjectLink to get action for previewing selected values

Default values

{
  "inputs": {
    "$.quantity": {
      "default_value": { "int_value": 1 }
    },
    "$.status": {
      "default_value": { "string_value": "pending" }
    },
    "$.isActive": {
      "default_value": { "bool_value": true }
    },
    "$.discount": {
      "default_value": { "float_value": 0.0 }
    }
  }
}
Value typeDescription
string_valueText and enum values
int_valueWhole numbers
float_valueDecimal numbers
bool_valueBoolean values
null_valueExplicitly null

Lookup actions

{
  "inputs": {
    "$.supplier.id": {
      "lookup_action": {
        "tool_id": "list-suppliers",
        "data_mapping": [
          {
            "key": "$.where.category.id.equals",
            "path": { "path": "$.category.id" }
          }
        ]
      },
      "get_entry_action": {
        "tool_id": "get-supplier"
      }
    }
  }
}

Response configuration

Configure response fields in the response object. Keys are JSON paths.

{
  "response": {
    "$.reference": {
      "display_name": "Order Ref",
      "display_order": 1
    },
    "$.internalNotes": {
      "visible": false
    },
    "$.totalAmount": {
      "help_text": "Total including tax"
    },
    "$.productImage": {
      "image_preview": true
    }
  }
}

Response field options

FieldTypeDescription
display_namestringLabel shown for the field
display_ordernumberOrder of appearance
visiblebooleanWhether field is shown
help_textstringHelp text for the field
image_previewbooleanDisplay file fields as inline images
visible_conditionstringCEL expression for conditional visibility
section_namestringGroups field into a section
linkobjectLink configuration to other tools

Response field links

{
  "response": {
    "$.customer.id": {
      "link": {
        "tool_id": "get-customer",
        "data_mapping": [
          {
            "key": "id",
            "path": { "path": "$.customer.id" }
          }
        ]
      }
    }
  }
}

Sections

Group fields into collapsible sections:

{
  "sections": [
    {
      "name": "details",
      "title": "Order Details",
      "description": "Basic order information",
      "display_order": 1,
      "visible": true
    },
    {
      "name": "shipping",
      "title": "Shipping Information",
      "display_order": 2,
      "visible": true,
      "visible_condition": "$.shippingRequired == true"
    }
  ],
  "response": {
    "$.reference": { "section_name": "details" },
    "$.shippingAddress": { "section_name": "shipping" }
  }
}
FieldTypeDescription
namestringUnique identifier referenced by fields
titlestringDisplay title
descriptionstringOptional description below title
display_ordernumberOrder among sections
visiblebooleanWhether section is shown
visible_conditionstringCEL expression for conditional visibility

Display layouts

Grid (table)

{
  "display_layout": {
    "config": {
      "type": "GRID",
      "gridConfig": {
        "title": { "template": "{{$.reference}}" },
        "description": { "template": "{{$.customer.name}}" },
        "editable": true,
        "updateAction": { "toolId": "update-order" }
      }
    }
  }
}

Inbox

{
  "display_layout": {
    "config": {
      "type": "INBOX",
      "inboxConfig": {
        "getTool": { "toolId": "get-order" },
        "title": { "template": "Order #{{$.reference}}" },
        "description": { "template": "{{$.customer.name}}" },
        "contextField": { "template": "{{$.totalAmount}}" },
        "avatarEnabled": true,
        "avatarUrl": { "template": "{{$.customer.avatarUrl}}" },
        "avatarFallback": { "template": "{{$.customer.initials}}" }
      }
    }
  }
}

Board (Kanban)

{
  "display_layout": {
    "config": {
      "type": "BOARD",
      "boardConfig": {
        "getTool": { "toolId": "get-order" },
        "title": { "template": "{{$.reference}}" },
        "description": { "template": "{{$.customer.name}}" },
        "groupByField": { "path": "$.status" },
        "updateAction": { "toolId": "update-order" }
      }
    }
  }
}

Gallery

{
  "display_layout": {
    "config": {
      "type": "GALLERY",
      "galleryConfig": {
        "title": { "template": "{{$.name}}" },
        "description": { "template": "{{$.sku}}" },
        "image": {
          "fileField": { "path": "$.thumbnail" },
          "alt": { "template": "{{$.name}}" }
        }
      }
    }
  }
}

Record (with progress indicator)

{
  "display_layout": {
    "config": {
      "type": "RECORD",
      "recordConfig": {
        "progressIndicator": {
          "enabled": true,
          "stepperField": { "path": "$.status" },
          "steps": [
            { "displayOrder": 1, "title": { "template": "Placed" }, "value": ["Placed"] },
            { "displayOrder": 2, "title": { "template": "Processing" }, "value": ["Picking", "Packing"] },
            { "displayOrder": 3, "title": { "template": "Shipped" }, "value": ["Shipped"] },
            { "displayOrder": 4, "title": { "template": "Delivered" }, "value": ["Delivered"] }
          ]
        }
      }
    }
  }
}

Layout type reference

TypeUse case
GRIDTabular data with sorting and inline editing
INBOXItems requiring detailed inspection with sidebar
BOARDWorkflow management with drag-and-drop
GALLERYVisual content with images
RECORDSingle record detail views

Tool links

Entry activity actions

{
  "entry_activity_actions": [
    {
      "tool_id": "update-order",
      "display_order": 1
    },
    {
      "tool_id": "ship-order",
      "title": "Ship Order",
      "as_dialog": true,
      "display_order": 2,
      "emphasize": true,
      "data_mapping": [
        { "key": "$.orderId", "path": { "path": "$.id" } }
      ],
      "skip_confirmation": true
    },
    {
      "tool_id": "delete-order",
      "visible_condition": "$.status == 'Draft'",
      "display_order": 3
    }
  ]
}

Link options

FieldTypeDescription
tool_idstringID of the target tool
titlestringCustom button/link text
descriptionstringTooltip or description
as_dialogbooleanOpen in a modal dialog
display_ordernumberPosition among links
visible_conditionstringCEL expression for visibility
data_mappingarrayMap values to target inputs
skip_confirmationbooleanSkip confirmation for mutations
emphasizebooleanHighlight as primary action
deletedbooleanRemove auto-generated link

Get entry action

{
  "get_entry_action": {
    "tool_id": "get-order",
    "data_mapping": [
      { "key": "$.id", "path": { "path": "$.results[*].id" } }
    ]
  }
}

Create entry action

{
  "create_entry_action": {
    "tool_id": "create-order",
    "title": "New Order",
    "as_dialog": true,
    "data_mapping": [
      { "key": "$.customer.id", "path": { "path": "$.id" } }
    ]
  }
}

Related actions

{
  "related_actions": [
    { "tool_id": "list-pending-orders", "title": "Pending", "display_order": 1 },
    { "tool_id": "list-completed-orders", "title": "Completed", "display_order": 2 }
  ]
}

Data mapping

Data mapping passes values between tools:

{
  "data_mapping": [
    {
      "key": "$.where.id.equals",
      "path": { "path": "$.id" }
    },
    {
      "key": "$.status",
      "value": { "string_value": "Processing" }
    }
  ]
}
FieldDescription
keyTarget input path in destination tool
pathSource response path from current tool
valueLiteral scalar value (alternative to path)
objectNested mappings for complex structures

Nested mapping

{
  "data_mapping": [
    {
      "key": "$.where",
      "object": [
        { "key": "$.order.id.equals", "path": { "path": "$.id" } },
        { "key": "$.status.equals", "value": { "string_value": "Pending" } }
      ]
    }
  ]
}

Embedded tools

Embed related list tools within get tools:

{
  "embedded_tools": [
    {
      "id": "order-lines",
      "title": "Order Lines",
      "display_order": 1,
      "visible": true,
      "tools": [
        {
          "action_link": {
            "tool_id": "list-order-lines",
            "data_mapping": [
              { "key": "$.where.order.id.equals", "path": { "path": "$.id" } }
            ]
          },
          "response_overrides": {
            "$.results[*].orderId": false
          }
        }
      ]
    }
  ]
}
FieldTypeDescription
idstringUnique identifier for the group
titlestringSection heading
display_ordernumberOrder among groups
visiblebooleanWhether group is shown
toolsarrayEmbedded tool configurations

Response overrides

Hide columns from embedded lists:

{
  "response_overrides": {
    "$.results[*].orderId": false
  }
}

External links

{
  "external_links": [
    {
      "label": "View in Stripe",
      "href": "https://dashboard.stripe.com/payments/{{$.stripePaymentId}}",
      "icon": "external-link",
      "display_order": 1
    },
    {
      "label": "Tracking Page",
      "href": "{{$.trackingUrl}}",
      "visible_condition": "$.trackingUrl != null",
      "display_order": 2
    }
  ]
}
FieldTypeDescription
labelstringLink text (supports templates)
hrefstringURL (supports templates)
iconstringOptional icon name
display_ordernumberOrder among links
visible_conditionstringCEL expression for visibility

Filter configuration

{
  "filter_config": {
    "quick_search_field": "$.where.reference.contains"
  }
}

Pagination

{
  "pagination": {
    "page_size": {
      "default_value": 25
    }
  }
}

Field formatting (_fields.json)

Global field formatting applies across all tools:

tools/_fields.json
[
  {
    "id": "Order.totalAmount",
    "format": {
      "number_config": {
        "mode": "CURRENCY",
        "currency_code": "GBP"
      }
    }
  },
  {
    "id": "OrderStatus",
    "format": {
      "enum_config": {
        "values": [
          { "value": "Pending", "colour": "#f59e0b" },
          { "value": "Shipped", "colour": "#3b82f6" },
          { "value": "Delivered", "colour": "#22c55e" }
        ]
      }
    }
  }
]

Number formatting

ModeDescriptionExample
DECIMALStandard decimal (default)1,234.56
RAWNo formatting1234.56
CURRENCYCurrency with symbol£1,234.56
PERCENTAGEPercentage12.5%
UNITWith unit suffix150 kg
{
  "id": "Order.totalAmount",
  "format": {
    "number_config": {
      "mode": "CURRENCY",
      "currency_code": "USD",
      "colourise": "NORMAL"
    }
  }
}
OptionTypeDescription
modestringDECIMAL, RAW, CURRENCY, PERCENTAGE, UNIT
currency_codestringISO 4217 code (for CURRENCY)
unit_codestringUnit identifier (for UNIT)
localestringLocale code for formatting
prefixstringText prepended to value
suffixstringText appended to value
sensitivebooleanMask until hovered
colourisestringNONE, NORMAL, INVERTED

Enum formatting

{
  "id": "OrderStatus",
  "format": {
    "enum_config": {
      "values": [
        { "value": "Pending", "display_value": "Awaiting Processing", "colour": "#f59e0b" },
        { "value": "Shipped", "colour": "#8b5cf6" },
        { "value": "Delivered", "colour": "#22c55e" }
      ]
    }
  }
}
OptionTypeDescription
valuestringActual enum value in schema
display_valuestringUI label (defaults to value)
colourstringHex colour for badge
display_ordernumberOrder in dropdowns

Boolean formatting

{
  "id": "StockItem.inStock",
  "format": {
    "bool_config": {
      "positive_value": "In Stock",
      "positive_colour": "#22c55e",
      "negative_value": "Out of Stock",
      "negative_colour": "#ef4444"
    }
  }
}

String formatting

{
  "id": "Order.reference",
  "format": {
    "string_config": {
      "prefix": "ORD-",
      "text_colour": "#3b82f6",
      "show_url_preview": true,
      "sensitive": false
    }
  }
}
OptionTypeDescription
prefixstringText prepended to value
suffixstringText appended to value
text_colourstringHex colour for text
show_url_previewbooleanRender URLs as clickable links
sensitivebooleanMask until hovered

String templates

Many fields support templates using {{$.fieldPath}} syntax:

{
  "title": "Order #{{$.reference}} - {{$.customer.name}}",
  "help_text": "Created on {{$.createdAt}}"
}

Conditional visibility (CEL)

CEL expressions control visibility of fields, sections, and links:

{
  "visible_condition": "$.status == 'Pending' && $.total > 1000"
}

The expression has access to:

  • Response fields via $.fieldName
  • User context via ctx.identity

Common operators: ==, !=, &&, ||, !, >, <, >=, <=