Contact-Centre Automation
You look after the Unified Contact Center for your company and you are tired of a supervisor dragging every WhatsApp conversation onto somebody’s desk by hand. By the end of this page you will know what BigLedger already does with a new conversation on the day the applet is installed (less than you think), what the queue, skill, rule and action screens actually change, and how to build the one rule most contact centres need — these chats go to that team — in a way the routing engine will actually run. Building it takes about twenty minutes. Seeing it fire takes up to fifteen more, for a reason explained below.
Meet GadgetSphere
GadgetSphere Online Sdn Bhd (GSO) answers customers on WhatsApp and web chat from 9 to 9. Six agents work the desk in two teams: Orders (four people — where is my parcel, change my delivery address) and Technical (two people — the laptop will not boot, is this charger compatible). On a normal day about 250 conversations arrive; on a launch day, 900. Today every one of them lands in the inbox unassigned and a team leader hands them out. The team leader would like her mornings back.
What every tenant already has
The contact-centre tables are populated by the platform’s database migrations, so a tenant has routing configuration before anyone opens the applet. In 88 of the 90 tenants it is exactly this, and in 87 of them it has never been touched:
| Seeded record | Code | What it means in plain English |
|---|---|---|
| One queue | DEFAULT_QUEUE | The holding area every task goes into. “Default Queue to be used when no skill or an unlinked skill is selected” |
| One skill | DEFAULT | A label a task can carry and an agent can hold. It points at the default queue. “Default skill to be used when no skill or an unlinked skill is selected” |
| One rule set (the applet calls it an Automation Rule) | SKILL_BASED_TASK_ASSIGNMENT_AUTOMATION_RULE | The family of rules the routing engine runs. It is the only family the engine looks for |
| One rule | DEFAULT_RULE | A parent rule with no conditions at all, priority 10. The engine uses it by name when nothing else matched |
| One rule action | DEFAULT_RULE_ACTION_LINK_… | Ties the default rule to the action below |
| Four actions | ASSIGN_TO_ANY_AGENT_WITH_LEAST_TASKS (the default), ASSIGN_TO_AVAILABLE_AGENT_WITH_LEAST_TASKS, ASSIGN_TO_ANY_AGENT_AT_RANDOM, KEEP_IN_THE_QUEUE | What a matched rule does. “Least tasks” means fewest assignments in the last 24 hours; “available” means the agent’s browser is connected and marked available right now; “keep in the queue” puts the task back for the next run |
So out of the box the intent is: every task goes to whichever agent has had the fewest tasks today. Read on for why, on almost every tenant, that never happens.
How a chat becomes a task on someone’s desk
flowchart LR
AR[bl_alg_cc_automation_rule_hdr<br/>the rule set]
R[bl_alg_cc_rule_hdr<br/>parent rule]
RC[bl_alg_cc_rule_hdr<br/>child rule = one condition]
RA[bl_alg_cc_rule_action_hdr]
A[bl_alg_cc_action_hdr]
Q[bl_alg_cc_queue_hdr]
QR[bl_alg_cc_queue_rule_link]
SK[bl_alg_cc_skill_hdr]
LS[bl_alg_cc_login_subject_skill_link]
U[app_login_subject<br/>the agent]
T[bl_alg_cc_task_hdr]
TQ[bl_alg_cc_task_queue_hdr<br/>the assignment]
G[app_mst_grp_hdr<br/>the team]
R -->|automation_rule_hdr_guid| AR
RC -->|parent_guid| R
RA -->|rule_hdr_guid| R
RA -->|action_guid| A
QR -->|queue_guid| Q
QR -->|rule_guid| R
SK -->|queue_guid| Q
LS -->|skill_guid| SK
LS -->|login_subject_guid| U
T -->|queue_guid| Q
TQ -->|task_hdr_guid| T
TQ -->|login_subject_guid| U
TQ -->|group_hdr_guid| G
Every arrow is a foreign key in kb/schema/foreign-keys.tsv. Read it left to right with a conversation in hand:
- The chat-flow creates the task. Nothing routes a raw message. The bot flow that answers the customer has an element — assign to agent or invoke automation rule — and when the conversation reaches it, a task is created carrying the element’s skill and a bag of facts about the conversation: the channel code, the endpoint, the virtual contact, the project, the skill.
- The skill decides the queue. The task’s queue is the skill’s queue. No skill on the element → the
DEFAULTskill; a skill with no queue → the default queue. - The task waits for the poll. Creating the task drops a row on a processing queue. A scheduled job reads that queue every fifteen minutes, ten tasks at a time. This is the latency: a task created at 10:01 is looked at around 10:15. Nothing you configure changes the interval.
- The engine picks a rule. It collects the rules linked to the task’s queue (the Rule tab on the queue, under Task Router), keeps the parent rules in this rule set, sorts by priority — highest number first — and takes the first whose conditions all hold. A parent rule with no conditions never holds; the seeded default rule is reached only by name, when no linked rule matched.
- The rule’s action runs. For a STANDARD rule the engine reads the action code and does that. For a CUSTOM rule it ignores the action code and reads the target: a team, or one person.
- Who counts as an agent. For the “assign to agent” actions the candidates are the people linked to the task’s skill (Configurations → Agents → Skill) who also hold the applet at rank
MEMBER. Nobody linked to the skill → no candidates → the action fails → the default rule is tried with the same empty list → the task staysCREATEDin All Task Queue. - The assignment is written as a task-queue row naming the person or the team, the task’s status becomes
AGENT_ASSIGNEDorTEAM_ASSIGNED, and a task event records which rule matched (RULE_MATCHED) and what happened (AGENT_ASSIGNED,TEAM_ASSIGNED).
Step 6 is the whole story of the adoption numbers. In 87 of 88 tenants no agent has ever been linked to a skill and no rule has ever been linked to a queue, so the engine wakes up every fifteen minutes, finds no candidates, and leaves the task where it was. Team leaders then assign by hand from the desk, which is what the SYS_APPLET events in the aggregate are. The three tenants whose events show RULE_MATCHED are the three that did Steps 2 and 4 below.
TASK_TEAM_ASSIGNMENT_AUTOMATION_RULE_SET and OUTBOUND_TASK_ASSIGNMENT_AUTOMATION_RULE_SET — are never seeded and the skill-based engine never looks for them. A rule created under either is never evaluated for an inbound chat. Put every rule under SKILL_BASED_TASK_ASSIGNMENT_AUTOMATION_RULE.What a condition can test, and what an action can do
A condition is a child rule: a field, an operator, a value. The screen offers four fields — Channel, Project, Virtual Contact and Skill — and six operators: equal, not equal, less than, less than or equal, greater than, greater than or equal. For the four fields only equal and not equal make sense; the ordering operators exist because the engine compares numbers and dates too, but the screen never gives you a number or a date to compare. All conditions on one rule must hold together (AND). There is no “contains”, no “or”, and no condition on the message text.
An action is what happens. Two lists matter and they do not agree:
| Where | Choices | Does the inbound engine run it? |
|---|---|---|
| The four seeded actions (usable through a STANDARD rule; the Action screen is commented out of the menu, so these are the only ones you have unless someone created more through the API or the unlisted create-action route) | ASSIGN_TO_ANY_AGENT_WITH_LEAST_TASKS, ASSIGN_TO_AVAILABLE_AGENT_WITH_LEAST_TASKS, ASSIGN_TO_ANY_AGENT_AT_RANDOM, KEEP_IN_THE_QUEUE | Yes — all four. Note that “at random” is not random: it always picks the first candidate |
| The Rule Action drop-down on a rule | ASSIGN_TO_TEAM (with a team picker) and CREATE_ISSUE | ASSIGN_TO_TEAM — only on a CUSTOM rule, where the engine reads the team you picked. On a STANDARD rule the code is not one the engine handles and the rule fails over to the default. CREATE_ISSUE — never: it writes a target the engine does not accept (LB8-P05) |
So the rule you want — WhatsApp goes to Technical — is a CUSTOM rule with a Channel condition and an ASSIGN_TO_TEAM action, linked to the default queue. That is the procedure.
Step 1: Create the skills and make sure they point at the queue
Unified Contact Center → Configurations → Skill → + ; then Task Router → Router Queue → Default Queue → Skill tab
The outcome: ORDERS and TECH exist and both belong to the default queue.
Create two skills: name Orders, code ORDERS, priority 5; name Technical, code TECH, priority 5. Then open the default queue under Task Router and add both skills on its Skill tab — this is what writes the skill’s queue link. (There is a separate queue–skill link table in the database; the screen does not use it, and neither does the engine. The link that counts is the one on the skill record.)
The most common failure here is skipping the queue step. A skill with no queue is treated as the default skill, which still works, but only because everything falls back to the one queue. Do it properly so that later queues behave.
Step 2: Link each agent to a skill
Configurations → Agents → (agent) → Skill → +
The outcome: the four Orders agents hold ORDERS, the two Technical agents hold TECH.
Open each agent record and add the skill. This writes the agent–skill link the engine reads. Two checks while you are there: the person must hold the Unified Contact Center applet at rank MEMBER (Tenant Admin → Tenant Users → that person’s applets), because the engine filters candidates by that rank; and if you intend to use the “available agent” action, they must be signed in with the desk open, because availability is live browser presence, not a setting.
The most common failure: an agent record exists but the person’s applet link is at a different rank. The engine silently treats them as not there.
Step 3: Create the rule and its condition
Configurations → Rule → + ; then the rule’s Expressions tab → +
The outcome: a parent rule WhatsApp to Technical with one condition.
Rule Type CUSTOM. Automation Rule: SKILL_BASED_TASK_ASSIGNMENT_AUTOMATION_RULE. Rule Name WhatsApp to Technical, Rule Code WA-TECH, Priority 9 (below the seeded default’s 10 does not matter — the default is reached by name, not by priority — but keep your own rules ordered: a higher number wins). Save.
Open the rule and add a condition: Condition Channel, Operator Equal, value WhatsApp from the channel list. Save. This creates a child rule under the parent; without at least one child the parent can never match.
Step 4: Give the rule its action
The rule → Rule Action tab → +
The outcome: the rule assigns to the Technical team.
Choose ASSIGN_TO_TEAM and pick the Technical team (teams are the platform groups you created under Configurations → Teams). Save. Behind the screen this records the team’s table and its guid as the rule’s target — which is exactly what a CUSTOM rule executes.
Step 5: Link the rule to the queue — the step everyone misses
Task Router → Router Queue → Default Queue → Rule tab → +
The outcome: the engine can see your rule.
Add WA-TECH to the default queue. Until this row exists the rule is invisible to the engine: it only ever collects rules linked to the task’s queue. This is the single row that separates the one tenant with working routing from the other 87.
Step 6: Send a test message and wait for the poll
Send a WhatsApp message to GSO’s support number from a phone that is not an agent’s, answer the bot far enough to reach the assign to agent element, then open Task Router → Tasks. The task appears at once with status CREATED. Wait — up to fifteen minutes — and refresh. It should now read TEAM_ASSIGNED, and the Team Task Queue of the Technical agents shows it.
What success looks like
Open the test task and read its events from the bottom: TASK_CREATED, then RULE_MATCHED naming WhatsApp to Technical, then TEAM_ASSIGNED. Three lines, in that order, within fifteen minutes of the message. If the second line names DEFAULT_RULE_FOR_SKILL_BASED_TASK_ASSIGNMENT instead, your rule did not match (go through Steps 3 and 5); if there is only the first line, the poll has not run yet, or the rule ran and found nobody (Step 2).
Common mistakes
| Symptom | Cause | Fix |
|---|---|---|
Every task stays CREATED; events show only TASK_CREATED | No agent is linked to the task’s skill, so every action finds no candidates | Step 2 — and check the applet rank is MEMBER |
Events show RULE_MATCHED for the default rule, never for yours | Your rule is not linked to the queue, or its rule set is not the skill-based one | Step 5; and re-create it under SKILL_BASED_TASK_ASSIGNMENT_AUTOMATION_RULE |
Your rule matches, then RULE_MATCH_BUT_NO_APPLICABLE_AGENT_AND_DEFAULT_ACTION_PERFORMED | The action could not be executed — usually ASSIGN_TO_TEAM on a STANDARD rule, or CREATE_ISSUE | Make the rule CUSTOM with ASSIGN_TO_TEAM; do not use CREATE_ISSUE |
| A parent rule with conditions never matches | It has no child condition, or one condition tests a field the task does not carry | Add at least one condition on Channel, Project, Virtual Contact or Skill |
| “Assignment is instant for the team leader but takes ages for the engine” | The poll runs every fifteen minutes; manual assignment from the desk does not wait for it | Expected. KEEP_IN_THE_QUEUE retries in fifteen-minute steps too |
| “Random” assignment always lands on the same person | The random action returns the first candidate | Use least tasks instead |
| Old tasks disappear | A nightly job sweeps tasks untouched for fifteen days | Complete or cancel tasks; do not rely on the queue as an archive |
Related documentation
- Unified Contact Center Applet — the reference page: menus, permissions, endpoints, task statuses, the full processor list and the twelve declared action codes.
- Contact Keys — how the customer on the other end of the chat resolves to an entity and a contact.
- Tenant Admin Applet — applet ranks per user, which the engine reads.
- Digital CRM Module — where this applet sits among the customer-facing ones.