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 formattingEach 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
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier, typically kebab-case of action name |
action_name | string | The schema action name (e.g. getOrder) |
name | string | Display name in the Console sidebar |
title | string | Title template, supports {{$.field}} placeholders |
help_text | string | Description below the title, supports markdown |
icon | string | Icon name from the icon library |
entity_single | string | Singular noun (e.g. "order") |
entity_plural | string | Plural noun (e.g. "orders") |
Capabilities
{
"capabilities": {
"comments": true,
"audit": true
}
}| Capability | Description |
|---|---|
comments | Enable comments section on records |
audit | Enable 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": {}
}| Field | Type | Description |
|---|---|---|
id | string | Unique identifier |
flow_name | string | The schema flow name |
name | string | Display name in the Console |
help_text | string | Description below the title |
icon | string | Icon name |
completion_redirect | object | Tool to redirect to after completion |
inputs | object | Input 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
| Field | Type | Description |
|---|---|---|
display_name | string | Label shown above the input |
display_order | number | Position in form (lower = first) |
visible | boolean | Whether field is shown (default: true) |
help_text | string | Guidance text below input |
placeholder | string | Placeholder text inside input |
locked | boolean | Prevents editing when true |
default_value | object | Pre-populated value |
visible_condition | string | CEL expression for conditional visibility |
section_name | string | Groups input into a named section |
lookup_action | object | Link to list action for selecting values |
get_entry_action | object | Link 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 type | Description |
|---|---|
string_value | Text and enum values |
int_value | Whole numbers |
float_value | Decimal numbers |
bool_value | Boolean values |
null_value | Explicitly 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
| Field | Type | Description |
|---|---|---|
display_name | string | Label shown for the field |
display_order | number | Order of appearance |
visible | boolean | Whether field is shown |
help_text | string | Help text for the field |
image_preview | boolean | Display file fields as inline images |
visible_condition | string | CEL expression for conditional visibility |
section_name | string | Groups field into a section |
link | object | Link 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" }
}
}| Field | Type | Description |
|---|---|---|
name | string | Unique identifier referenced by fields |
title | string | Display title |
description | string | Optional description below title |
display_order | number | Order among sections |
visible | boolean | Whether section is shown |
visible_condition | string | CEL 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
| Type | Use case |
|---|---|
GRID | Tabular data with sorting and inline editing |
INBOX | Items requiring detailed inspection with sidebar |
BOARD | Workflow management with drag-and-drop |
GALLERY | Visual content with images |
RECORD | Single 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
| Field | Type | Description |
|---|---|---|
tool_id | string | ID of the target tool |
title | string | Custom button/link text |
description | string | Tooltip or description |
as_dialog | boolean | Open in a modal dialog |
display_order | number | Position among links |
visible_condition | string | CEL expression for visibility |
data_mapping | array | Map values to target inputs |
skip_confirmation | boolean | Skip confirmation for mutations |
emphasize | boolean | Highlight as primary action |
deleted | boolean | Remove 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" }
}
]
}| Field | Description |
|---|---|
key | Target input path in destination tool |
path | Source response path from current tool |
value | Literal scalar value (alternative to path) |
object | Nested 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
}
}
]
}
]
}| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the group |
title | string | Section heading |
display_order | number | Order among groups |
visible | boolean | Whether group is shown |
tools | array | Embedded 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
}
]
}| Field | Type | Description |
|---|---|---|
label | string | Link text (supports templates) |
href | string | URL (supports templates) |
icon | string | Optional icon name |
display_order | number | Order among links |
visible_condition | string | CEL 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:
[
{
"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
| Mode | Description | Example |
|---|---|---|
DECIMAL | Standard decimal (default) | 1,234.56 |
RAW | No formatting | 1234.56 |
CURRENCY | Currency with symbol | £1,234.56 |
PERCENTAGE | Percentage | 12.5% |
UNIT | With unit suffix | 150 kg |
{
"id": "Order.totalAmount",
"format": {
"number_config": {
"mode": "CURRENCY",
"currency_code": "USD",
"colourise": "NORMAL"
}
}
}| Option | Type | Description |
|---|---|---|
mode | string | DECIMAL, RAW, CURRENCY, PERCENTAGE, UNIT |
currency_code | string | ISO 4217 code (for CURRENCY) |
unit_code | string | Unit identifier (for UNIT) |
locale | string | Locale code for formatting |
prefix | string | Text prepended to value |
suffix | string | Text appended to value |
sensitive | boolean | Mask until hovered |
colourise | string | NONE, 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" }
]
}
}
}| Option | Type | Description |
|---|---|---|
value | string | Actual enum value in schema |
display_value | string | UI label (defaults to value) |
colour | string | Hex colour for badge |
display_order | number | Order 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
}
}
}| Option | Type | Description |
|---|---|---|
prefix | string | Text prepended to value |
suffix | string | Text appended to value |
text_colour | string | Hex colour for text |
show_url_preview | boolean | Render URLs as clickable links |
sensitive | boolean | Mask 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: ==, !=, &&, ||, !, >, <, >=, <=