Release announcements, helpful tips, and community discussion



Cerb (9.6) is a feature upgrade released on August 08, 2020. It includes more than 73 new features and improvements from community feedback.

To check if you qualify for this release as a free update, view Setup » Configure » License. If your software updates expire on or after May 31, 2020 then you can upgrade without renewing your license. Cerb Cloud subscribers will be upgraded automatically.

Important Release Notes


We created a new human-friendly text syntax called KATA (“Key Annotated Tree of Attributes”) for declaring structured data.

KATA is used throughout Cerb for configuration, UI customization, and powerful upcoming features like automations. It replaces our prior usage of YAML and avoids many of its pitfalls.


For instance, the following brief KATA on a dashboard:

  label: Date range:
  default: first day of this month -12 months

  label: By:
  default: month

  label: Groups:
    context: group
    single@bool: no

Produces this interactive toolbar:

One of the major strengths of KATA is that it’s easy to generate automatically without caveats (e.g. excessive escaping, type coercion).

Visual programming tools can generate KATA “behind the scenes”. For instance, an interface builder can use a visual representation of buttons, picklists, and menus, that are dragged into a desired order using the browser. These elements can then be configured with a helpful, graphical interface. Those tools output KATA, and Cerb reads KATA. This brings consistency to how various features are implemented.

Bots can use KATA to create dynamic interfaces based on the data they need to collect, even when the structure is not known ahead of time.

KATA fragments are also easy to share compared to UI instructions, and it can be managed through version control.


Threaded replies to comments

On record profiles, it’s now possible to reply directly to a top-level comment with threading. This makes it much easier for separate conversations to take place on a record.

Previously, all comments were at the top-level of the record timeline, which interleaved multiple conversations and made it difficult to read.

When notifications and activity logs refer to a comment, they now use a label like “Janey’s comment”. Previously comments lacked a name, so notifications about them didn’t have a direct link (e.g. “Kina commented on comment” rather than “Kina commented on Janey’s comment”). [#1345]


Modernized the style of ticket profile pages

Modernized and improved readability on ticket profile pages:

  • A left margin considerably improves the visual separation between messages.
  • The sender avatar images are slightly smaller, and sender names are consistently sized, regardless of whether a message is expanded or collapsed.
  • Sticky notes and comments are condensed, providing more differentiation with email messages.
  • Notes on messages and drafts appear threaded.

Improved usability on collapsed messages

On ticket profiles, collapsed messages in the timeline now display a ‘Read message’ button with the size of the message.

Previously it wasn’t intuitive to some users that historical messages were collapsed (instead, they assumed something was wrong when their content was missing).

Improved display of multiple unread messages

On ticket profiles, all inbound messages since the last outgoing message are expanded. [#712]

A notification is also displayed above the conversation noting “There are N new messages since our last response”, with links to the messages.

This makes it much harder to accidentally overlook multiple client messages in a row. Previously, only the latest message was expanded.

Drafts up top

On ticket profiles, in the ‘Conversation’ widget, drafts now always show up at the top of the timeline regardless of their updated date.

Previously older drafts could be lost in a long timeline.

On a message card popup, or in notifications and the activity log, links to a message now open the parent ticket profile page and focus the message in the conversation timeline.

On a draft card popup, or in notifications and the activity log, links to a draft now open the parent ticket profile page and focus the draft in the conversation timeline.

Improved previews on compose and reply

When composing and replying to mail, the ‘Preview’ feature is now available as a tab rather than a new popup. This resolves some issues with people pressing ESC to close the preview and closing the reply popup. It also makes it easier to enforce previewing formatted messages before sending them.

Preserve Markdown in plaintext parts

When composing and replying to email with formatting enabled, Cerb now sends and saves the original Markdown formatting as the plaintext part. [#699] [#817] [#1328]

Previously, Markdown formatting was being up-converted to HTML and then down-converted back to text. This lossy process caused many issues: corrupting formatted on bulleted lists, rewriting links, destroying table markup, etc.

The plaintext version should now be exactly what you see in the email editor, with the sole exception being inline images referring to internal file URLs that are rewritten as [Image example.png] to match their attachments.

We now properly use the separate plaintext and HTML signatures for each part.

Validation when saving drafts

When composing and replying to mail, the form is now also validated when saving a draft and errors are displayed. Previously it was only validated when sending. This could lead to a silent discrepancy in the resumed draft.

Original message placeholder

Added a #original_message command when replying to email. This inserts the entire original message, including HTML formatting. It can be added after the #signature in environments where this is desirable. [#1092]

Email signatures on HTML templates

On email template records, the signature field is now a link to an email signature record. This allows text and HTML signatures to be used independently on the same sent message. Existing template signatures are migrated to new email signature records.

Compose shortcut on cards

In the card widget library, added a package for a contextual ‘Compose’ button for address, contact, and organization records. This creates an email draft and opens it in the compose editor. On the first use it creates a ‘Compose Bot’ with an interaction behavior. On subsequent uses it reuses the existing behavior. For addresses and contacts, it adds the email to the ‘To:’ recipient, and begins the draft with Hi {{first_name}},. On organizations, it recommends common recipients from that org. For any other record type, the compose button opens without pre-filling any fields. The behavior can be easily customized.


Time limits for intensive searches

Worklist searches are now constrained by a time limit (default 10 seconds). [#1022]

Previously a long-running search could last 30+ seconds, at which point many gateways (app/web servers) hang up. The search would continue to run on the database server even though the eventual results would no longer be returned.

This change helps prevent several long-running query from affecting performance (as workers have a tendency to repeat them multiple times if they take too long).

Advanced date range filtering

In search queries, date-based filters may use an optional advanced parameterized expression, with the format:

created:(since:"-1 week" until:now days:[Weekdays] times:9a-5p)

The since: option sets the beginning of the date range (default big bang).

The until: option sets the end of the date range (default now).

The days: option accepts a comma-delimited list of days to include within in the range (default everything). You can use aliases for weekdays and weekends, and any unique prefix on English days of the week (e.g. Mon,Wed,Fri, m,w,f, thu,f).

The times: option accepts a comma-delimited list of time ranges to include for the given days (e.g. 8a-noon,1-6p).

For instance, this makes it much easier to query only working hours within a date range. It’s still possible to use a simple string for filtering by date range (e.g. created:"-1 week to now").

Thanks to 1Password for the feature request.

Form Interactions

Form interaction widgets on cards

Implemented ‘Form interaction’ widgets on cards. This allows custom features and shortcuts to be added to the card of any record type. [#759] [#1072]

For instance, on ‘Public Key’ records, an ‘Encrypt’ form interaction could generate encrypted messages using the key.

On task records, a ‘Mark completed’ interaction could quickly close the task without having to open its editor.

KATA toolbars for form interaction widgets

On cards, profiles, and workspaces, ‘Form interaction’ widgets are now configured with KATA toolbar syntax rather than obtuse YAML.

Existing widgets still support the deprecated YAML format during 9.x (and are prefixed with ---) but should be updated to the new KATA format before the 10.0 release.

A widget’s available interactions are now displayed using toolbar syntax. Interactions can be launched from buttons or menus/submenus.

A hidden: property conditionally determines whether to display a toolbar item (e.g. by worker permissions or record properties).

An event/done: outcome can use the refresh_widgets@list: action to refresh any combination of widgets by name (leave blank to refresh everything, omit to refresh nothing).

When configuring widgets, a preview icon displays the toolbar, and an ‘add’ icon assists with creating menus and interactions.

Prompt with sheet

In form interactions, added a new ‘Prompt with sheet’ action. This allows single and multiple selection from a formatted tabular list of options using arbitrary data sources. [#1090] [#1250]

The data source is an array of key/value objects in JSON format. This can come from anywhere – a hardcoded value, a variable, an API call, etc.

The sheet is a KATA schema.

A ‘selection key’ determines which values are returned by selected rows.

This prompt:

Is created by this action:

Prompt with email reply

On bot form interactions, added a ‘Prompt with email reply’ action. This opens the reply editor popup and optionally accepts a draft ID to resume.

For instance, the form interaction could first create a draft with the desired defaults and then open the reply popup.

The action sets a placeholder with the record dictionary of the new reply message or saved draft. This can be used in subsequent steps of the form interaction (e.g. displaying a sheet, redirecting the page, taking actions based on custom field values).

Improved cursor placement in text prompts with defaults

In bot form interactions, when a ‘Prompt with text’ action has default text, the cursor is now positioned at the end of the default text.

For instance, this can be used in a Twitter integration to start typing after the @mention reply prefix.


Replaced ext/imap

Cerb no longer requires or uses the abandoned ext/imap PHP extension for downloading mail from POP3/IMAP mailboxes. We now use ‘Horde/Imap_Client’ which is faster, modern, and more extensible.

This also simplifies installation in environments where ext/imap is not available (e.g. Amazon Linux).

Support for XOAUTH2 authentication in POP3 and IMAP

IMAP mailboxes may now authenticate using the SASL/XOAUTH2 authentication method rather than legacy passwords. An optional linked connected account is used to securely store/retrieve an access token. [#1108]

This approach will soon be required by Google (Gmail), Microsoft (Office365), and other major email services.

The password may be left blank to require XOAUTH2. If a password and connected account are provided, XOAUTH2 will be preferred, and plaintext logins will be used as a fallback.

In major email providers, the password is usually now an ‘app-specific password’.

STARTTLS support for POP3 and IMAP

POP3 and IMAP mailboxes may now be configured to specifically use STARTTLS or implied TLS. Previously Cerb only supported implied TLS (e.g. encrypted port 995 vs unencrypted port 110 for POP3). Now a mail connection may upgrade to encryption after connecting to the standard port. In some mail services or firewalls this is the only option.


Data query placeholders

In packages, added a data_query placeholder type. This dynamically populates a placeholder with the results of an arbitrary data query from the target environment. [#1251]

For instance, it can discover the default tab on worker records, or build a list of administrators.

The parameters are:

  • query (the data query)
  • selector (a bot scripting template to return from the query results)
  • format (json for structured objects, or omitted for text)
  • validate (a bot scripting template where any output is considered an error)


  "package": {
    "name": "Example Package",
    "configure": {
      "placeholders": [
          "type": "data_query",
          "key": "ticket_profile_tab_id",
          "params": {
            "query": "type:worklist.records of:profile_tab query:(name:\"Overview\" record:\"cerberusweb.contexts.ticket\" format:dictionaries limit:1)",
            "selector": "{{|}}",
            "format": "json",
            "validate": "{% if| is empty %}Ticket profile tab record not found.{% endif %}"
  "records": [
      "uid": "widget_001",
      "_context": "profile_widget",
      "name": "Example Widget",
      "profile_tab_id": "{{{ticket_profile_tab_id}}}",
      "extension_id": ""

PGP public key in package library

On PGP Public Key records, added a ‘Public Key’ card widget to the package library. This displays the public key in ASCII format for easier sharing.


PGP encryption action

Added an ‘Execute PGP encrypt’ action to bot behaviors. This targets one or more public keys by chooser and/or ID. An arbitrary message is encrypted and saved to a placeholder in PGP ASCII format. [#263]

This makes it easy to implement an ‘Encrypt’ form interaction on public key records. It could also be used by customer-facing forms to encrypt form responses.

In bot behaviors, ‘Record Links’ custom fields can now be the target of ‘On:’ actions (e.g. schedule behavior, comment). This will apply to the entire list of linked records in the variable.

Set all custom field types

In all bot behaviors, implemented the ‘Set’ action for the following custom fields:

  • Currency
  • Decimal
  • File
  • Files
  • Latitude/Longitude
  • Record Link [#1318]
  • Record Links
  • Slider

Access the eventual Message-Id before sending

In bots with ‘Before message sent by worker’ behaviors, the {{message_id}} placeholder from the Message-Id: header is now properly set for composed messages.

Previously, this only worked properly for replies.

Set ticket and message custom fields before sending

When composing and replying to mail, ‘Before message sent’ bot behaviors can now set ticket and message custom fields on the eventually created records (i.e. when mail is delivered successfully). [#1308]

Previously it was only possible to set custom ticket fields when replying.

This makes it much easier to implement classification tagging, personalized links, and more.

Replace text in sent or saved message

In bot behaviors on the ‘Before message sent’ event, the ‘Replace text in message content’ action now allows content to be replaced independently in the sent message, saved message, or both. [#1303]

For instance, personalized links to a customer satisfaction survey could be sent to the recipient, but not the saved copy of the message in Cerb.

Multiple prepends, appends, and replacements

In bot behaviors on the ‘Before message sent’ event, the content-related actions for prepend, append, and replace are now queued and applied in their defined order when a message is sent (not during the behavior). [#1148]

Previously, replacements were applied immediately, then prepends, then appends. Now it is possible to prepend/append content, then include it in a subsequent replacement action.


KATA for dashboard prompts

Dashboard prompts now use KATA rather than YAML to define their schema. The format is much more readable. Existing prompts are automatically converted during the update.

  label: Date range:
  default: today -1 week
        label: today
        query: today to now
        query: -1 month
        query: jan 1 to now
        query: big bang to now

  label: By:
  default: day
    options@csv: day, week, month, year

  label: Groups:
    context: group
    single@bit: false

Configurable presets on date_range

On dashboards, date_range prompts now offer configurable presets.

Previously these were built-in (e.g. 1d, 1wk, 1mo, 6mo, 1yr, ytd, all) and not customizable.

  label: Date range:
  default: today -1 week
        label: today
        query: today to now
        query: -1 month
        query: jan 1 to now
        query: big bang to now

Improved UX on refreshing widgets

On dashboards, loading/reloading widgets are now dimmed until updated. This is consistent with how worklists work, and is less jarring than drastically changing their dimensions.

Previously, widgets cleared their content while updating and only displayed a spinner.


KATA for snippet prompts

Snippets prompts now use KATA rather than YAML for their schema. This is much more readable. Existing prompts are automatically migrated during the update.

Picklist prompts in snippets

In snippets, added a ‘picklist’ prompt type. This allows a selection from a predefined list of options.

Previously, only ‘text’ prompts were supported, which required workers to type potentially inconsistent freeform text.

Improved UX for inserting snippets

When inserting snippets, the text editor now scrolls down to show up to 5 lines below the cursor.

Previously, the cursor was inserted at the end of the snippet but the editor didn’t scroll.

HTML in sheet card columns

On sheets, card columns may now use sanitized HTML in the label_template parameter.

Custom Fields

Emoji in text custom fields

‘Multiple line text’ custom fields may now contain emoji and other utf8mb4 characters. [#1301]

Added more metadata to custom field dictionaries

In ‘custom field’ record dictionaries, a new type_label placeholder returns a human-friendly label for the custom field type (e.g. “Picklist”).

On ‘Record Links’ custom fields, a custom_<ID>_records placeholder is now available in dictionaries. This is a list of the linked records which supports key expansion.

Connected Services

Automatic OAuth2 token refreshing

OAuth2-based connected services now automatically manage the use of refresh tokens.

Previously this functionality was built into the ‘Execute HTTP request’ action in bot behaviors for use with external APIs. OAuth authentication is now also available in identity providers (IdP) and IMAP mailboxes.


KATA for sheet schemas

On form interaction widgets, the ‘Respond with sheet’ action now describes the sheet in KATA rather than YAML.

On dashboards, sheet widgets now specify their schema using KATA rather than YAML. The widget editor provides shortcuts for adding new column types. Existing widgets are automatically converted to the new format.

  style: table
  headings@bool: yes
  paging@bool: yes

    label: Worker
      image@bool: yes
      bold@bool: yes

    label: # Replies
      label_key: count
      context_key: count_query_context
      query_key: count_query

Improved sheet widget editors

Improved sheet widget editors on cards, profiles, and dashboards:

  • Added a toolbar to the query editor with buttons for ‘test’ and ‘help’.
  • The ‘Simulate placeholders’ section is now always visible, where previously it required running the query first.
  • Added a ‘remove’ icon to the query tester output.
  • Added a toolbar to the sheet editor with ‘preview’ and ‘add’ buttons.
  • The ‘add’ column button includes KATA examples for each type (e.g. card, date, link, slider, text).

Sheet refresh on record editors

On dashboards, sheet widgets now properly refresh when one of their records is edited from their card. [#990]


New spinner animation

Modernized the “spinner” animation when data is loading.

Owner picker usability

When using the owner picker control on records (e.g. workspace pages), the menu is now more usable when there are a lot of records (bots, roles, groups, workers). The sub-menus will be 50% of the viewport width, and broken into multiple columns for every 200px of horizontal space. When there are fewer than 15 items, a single column is always used.


Per-worker idle timeout

It’s now possible to set a per-worker idle timeout when seats are fully occupied and someone tries to log in. The most idle worker is kicked first to free up a seat. [#1287]

Previously, workers were considered idle after 10 minutes of inactivity. Now this idle threshold can be raised or lowered for each worker.

For instance, admins may be permitted to remain idle longer, while infrequent workers (e.g. temps/volunteers/interns) are considered idle more quickly.