Runbook: Escalation Routing Management¶
Manage escalation reference data: business areas, services, topics, subtopics, and routing rows. Two interfaces are available — the CLI for individual changes, and an Excel bulk load for replacing the full dataset at once. Both target the same tables.
Prerequisite: complete CLI Setup before proceeding. The bulk load also requires a database connection string and VPN access — see Bulk Load from Excel for details.
Background¶
- Business areas — top-level organisational groupings (e.g. "Employment Benefits").
- Services — categories of work (e.g. "Renewals"). Topics are assigned to services.
- Topics — specific subjects within a service (e.g. "Annual Renewal"). The LLM matches the user's intent against the list of topics.
- Subtopics — optional further refinement under a topic (e.g. "Late Submission").
- Routing rows — link a business area + topic (+ optional subtopic) to contact details (email, phone, context text, notes). When the system classifies a request it looks up the matching routing row to determine where to send it.
CLI Management¶
All commands below target PROD. Swap --profile prod for --profile uat to target UAT.
Business Areas¶
List all business areas¶
altaforge-ra-cli --profile prod api admin escalation-business-area list
[
{ "id": 1, "name": "Employment Benefits" },
{ "id": 2, "name": "Housing Services" }
]
Add a business area¶
altaforge-ra-cli --profile prod api admin escalation-business-area add "New Business Area"
Rename a business area¶
altaforge-ra-cli --profile prod api admin escalation-business-area update <BUSINESS_AREA_ID> "Updated Name"
Delete a business area¶
altaforge-ra-cli --profile prod api admin escalation-business-area delete <BUSINESS_AREA_ID>
Warning: Only delete a business area after removing all routing rows that reference it. Deleting a business area still referenced by routing rows will produce an error. Delete routing rows first (see Routing rows).
Services¶
List all services¶
altaforge-ra-cli --profile prod api admin escalation-service list
[
{ "id": 1, "name": "Renewals" },
{ "id": 2, "name": "New Applications" }
]
Add a service¶
altaforge-ra-cli --profile prod api admin escalation-service add "New Service"
Rename a service¶
altaforge-ra-cli --profile prod api admin escalation-service update <SERVICE_ID> "Updated Service Name"
Delete a service¶
altaforge-ra-cli --profile prod api admin escalation-service delete <SERVICE_ID>
Warning: Deleting a service cascade-deletes all topics under it, and their subtopics. Any routing rows that reference those topics must be deleted first — they are not removed automatically. Run
escalation-routing list --service "<SERVICE_NAME>"to find them, delete each one, then delete the service.
Topics¶
Topics are assigned to a service at creation time and cannot be reassigned. To move a topic to a different service, delete the old topic and recreate it under the new service.
List topics¶
altaforge-ra-cli --profile prod api admin escalation-topic list
Filter by service:
altaforge-ra-cli --profile prod api admin escalation-topic list --service-id <SERVICE_ID>
[
{ "id": 10, "serviceId": 1, "name": "Annual Renewal" },
{ "id": 11, "serviceId": 1, "name": "Mid-Year Adjustment" }
]
Add a topic¶
altaforge-ra-cli --profile prod api admin escalation-topic add <SERVICE_ID> "Topic Name"
Rename a topic¶
altaforge-ra-cli --profile prod api admin escalation-topic update <TOPIC_ID> "Updated Topic Name"
Delete a topic¶
altaforge-ra-cli --profile prod api admin escalation-topic delete <TOPIC_ID>
Warning: Deleting a topic cascade-deletes all subtopics under it. Any routing rows that reference this topic must be deleted first. Run
escalation-subtopic list --topic-id <TOPIC_ID>to review subtopics andescalation-routing list --topic "<TOPIC_NAME>"to find routing rows.
Subtopics¶
List subtopics¶
altaforge-ra-cli --profile prod api admin escalation-subtopic list
Filter by topic:
altaforge-ra-cli --profile prod api admin escalation-subtopic list --topic-id <TOPIC_ID>
[
{ "id": 20, "topicId": 10, "name": "Late Submission" },
{ "id": 21, "topicId": 10, "name": "Change of Circumstances" }
]
Add a subtopic¶
altaforge-ra-cli --profile prod api admin escalation-subtopic add <TOPIC_ID> "Subtopic Name"
Rename a subtopic¶
altaforge-ra-cli --profile prod api admin escalation-subtopic update <SUBTOPIC_ID> "Updated Subtopic Name"
Delete a subtopic¶
altaforge-ra-cli --profile prod api admin escalation-subtopic delete <SUBTOPIC_ID>
Warning: You cannot delete a subtopic while routing rows reference it. Delete or repoint the routing rows first (see Routing rows).
Routing Rows¶
A routing row joins a business area and a topic (with an optional subtopic) to contact details. When the escalation classifier matches a user's request to a topic, the system finds the corresponding routing row to determine where to route it.
List routing rows¶
altaforge-ra-cli --profile prod api admin escalation-routing list
Filter by service name (exact match) or topic name (partial match):
altaforge-ra-cli --profile prod api admin escalation-routing list --service "Renewals"
altaforge-ra-cli --profile prod api admin escalation-routing list --topic "Annual"
altaforge-ra-cli --profile prod api admin escalation-routing list --service "Renewals" --topic "Annual"
[
{
"id": 30,
"businessAreaId": 1,
"topicId": 10,
"subtopicId": null,
"email": "renewals@example.com",
"phone": "1-800-555-0100",
"context": "For annual renewal enquiries",
"requiredInformation": "Please have your file number ready.",
"attachments": [{ "name": "Renewal Form", "link": "https://example.com/form.pdf" }],
"resources": [{ "name": "Policy Guide", "link": "https://example.com/guide" }],
"notes": "Route to Team A on Tuesdays",
"extraFields": null,
"fieldOverrides": { "reference_number": { "label": "File Number", "required": true } }
}
]
Inspect a single routing row¶
altaforge-ra-cli --profile prod api admin escalation-routing get <ROUTING_ID>
Add a routing row¶
Required positional arguments: BUSINESS_AREA_ID and TOPIC_ID. All other arguments are optional.
altaforge-ra-cli --profile prod api admin escalation-routing add \
<BUSINESS_AREA_ID> <TOPIC_ID> \
--subtopic-id <SUBTOPIC_ID> \
--email EMAIL \
--phone PHONE \
--context "Context text shown to the user" \
--required-information "Body text shown in the escalation panel" \
--attachments '[{"name": "Form A", "link": "https://example.com/form.pdf"}]' \
--resources '[{"name": "Policy Guide", "link": "https://example.com/guide"}]' \
--notes "Internal notes for operators" \
--extra-fields '{"key": "value"}' \
--field-overrides '{"reference_number": {"label": "File Number", "required": true}}'
--field-overrides currently supports one key: reference_number. Set it to override the default
reference label shown in the escalation panel (e.g. "File Number" instead of the default):
altaforge-ra-cli --profile prod api admin escalation-routing add 1 10 \
--field-overrides '{"reference_number": {"label": "File Number", "required": true}}'
Example — route topic 10 under business area 1 with contact details and body text:
altaforge-ra-cli --profile prod api admin escalation-routing add 1 10 \
--email renewals@example.com \
--phone "1-800-555-0100" \
--context "Contact the renewals team for assistance." \
--required-information "Please have your file number and last notice ready." \
--attachments '[{"name": "Renewal Form", "link": "https://example.com/renewal.pdf"}]'
Update a routing row¶
At least one argument must be provided. Pass --business-area-id or --topic-id to repoint the
row; pass any combination of the other flags to update individual fields:
altaforge-ra-cli --profile prod api admin escalation-routing update <ROUTING_ID> \
--email new-contact@example.com \
--phone "1-800-555-0200"
altaforge-ra-cli --profile prod api admin escalation-routing update <ROUTING_ID> \
--required-information "Updated body text." \
--attachments '[{"name": "New Form", "link": "https://example.com/new.pdf"}]'
altaforge-ra-cli --profile prod api admin escalation-routing update <ROUTING_ID> \
--business-area-id 2 --topic-id 15
Delete a routing row¶
altaforge-ra-cli --profile prod api admin escalation-routing delete <ROUTING_ID>
Common Workflows¶
Add a new topic and wire up its routing¶
- Find or create the service:
altaforge-ra-cli --profile prod api admin escalation-service list altaforge-ra-cli --profile prod api admin escalation-service add "Service Name" # if needed - Add the topic under the service. Note the
idin the output.altaforge-ra-cli --profile prod api admin escalation-topic add <SERVICE_ID> "Topic Name" - Optionally add subtopics:
altaforge-ra-cli --profile prod api admin escalation-subtopic add <TOPIC_ID> "Subtopic Name" - Find the business area ID:
altaforge-ra-cli --profile prod api admin escalation-business-area list - Create the routing row:
altaforge-ra-cli --profile prod api admin escalation-routing add <BUSINESS_AREA_ID> <TOPIC_ID> \ --email contact@example.com
Update a contact address on a routing row¶
- Find the routing row:
altaforge-ra-cli --profile prod api admin escalation-routing list --topic "Topic Name" - Note the
id, then update:altaforge-ra-cli --profile prod api admin escalation-routing update <ROUTING_ID> \ --email new-contact@example.com
Remove a topic and its routing¶
- Find all routing rows that reference the topic:
altaforge-ra-cli --profile prod api admin escalation-routing list --topic "Topic Name" - Delete each routing row:
altaforge-ra-cli --profile prod api admin escalation-routing delete <ROUTING_ID> - Delete the topic (subtopics cascade-delete automatically):
altaforge-ra-cli --profile prod api admin escalation-topic delete <TOPIC_ID>
Apply the same change to UAT first¶
Replace --profile prod with --profile uat in any command above. UAT and PROD are independent;
changes to one do not affect the other.
Bulk Load from Excel¶
Use the bulk load when replacing the full dataset from a master Excel spreadsheet rather than making individual CLI changes. The script connects directly to the database — you must be on VPN.
Prerequisites¶
- The
govlab-ls-research-assistantrepository is cloned locally. uvis installed and onPATH.- You have the
DATABASE_URLconnection string for the target environment. Obtain this from a developer or the deployment documentation. - You have the master Excel spreadsheet (
.xlsx) for the client.
1. Configure scripts/.env¶
The script reads database credentials from scripts/.env at the repository root. Create or
update it before each run if targeting a different environment.
DATABASE_URL=postgresql+asyncpg://<user>:<password>@<host>:5432/<database>
| Engine | URL format |
|---|---|
| PostgreSQL | postgresql+asyncpg://user:password@host:5432/dbname |
| MSSQL (Azure AD auth) | mssql+aioodbc://host:1433/dbname?driver=ODBC+Driver+18+for+SQL+Server&authentication=ActiveDirectoryInteractive |
| MSSQL (SQL auth) | mssql+aioodbc://user:password@host:1433/dbname?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes |
The database is not publicly accessible. You must be connected to the virtual network (VPN or equivalent) to reach it.
2. Prepare the Excel spreadsheet¶
The script reads the first sheet of the .xlsx file. Column names must appear in the first row.
topic is required — rows without a topic are silently skipped (counted in the info output only,
no warning emitted). business_area and service are also required; rows with a topic but missing
either of these are skipped with a warning in the script output. All other columns are optional.
| Column | Description |
|---|---|
topic |
Required. The escalation topic (e.g. "Benefits Renewal"). |
business_area |
Required. Business area owning the topic. |
service |
Required. Service name. Rows missing business_area or service are skipped with a warning in the script output. |
email |
Support team email address for this topic. See UAT warning below. |
phone |
Phone number for escalation. |
subtopic |
More specific categorisation under the topic. |
context |
Additional context shown to the user. |
body_1, body_2, body_3 |
Required information fields — combined into a single block. |
note_1, note_2, note_3 |
Internal notes — combined into a single block. |
attachment_1, attachment_1_link |
First attachment name and URL. |
attachment_2, attachment_2_link |
Second attachment name and URL. |
resource_1, resource_1_link |
Resource name and URL. |
request_id |
Original request ID from the source system (stored for reference). |
reference |
Reference number label override. |
UAT warning: replace email addresses before loading¶
The email column contains real support team addresses used to route escalation notifications.
Do not load a spreadsheet containing production email addresses into UAT — doing so risks
sending test traffic to live support teams.
Before loading into UAT, replace every value in the email column with a safe test address, for
example request.testing@aara.ca. Use a separate copy of the spreadsheet for this — do not
modify the master.
3. Load the data¶
The standard workflow is a full replace: the script atomically deletes all existing routing rows for the client and inserts the new ones in a single transaction. If the insert fails for any reason, the original data is left intact.
Warning:
CLEAR=--clearpermanently removes all existing routing rows for the client before loading. Any routing row not present in the spreadsheet will be lost. Before running, confirm that the spreadsheet is the complete and authoritative dataset — not just the rows you are adding or changing.Note:
CLEAR=--clearclears routing rows only. The dimension tables (business areas, services, topics, subtopics) are always upserted and are not removed by--clear. This means dimensions added by earlier loads persist even after a full replace.
Always use CLEAR=--clear unless you have been explicitly told to append.
PROD¶
make load-escalation-requests \
EXCEL="path/to/Request Table for Email Escalation.xlsx" \
CLIENT=AARA \
CLEAR=--clear
UAT¶
Ensure email addresses in the spreadsheet have been replaced (see above) before running.
make load-escalation-requests \
EXCEL="path/to/Request Table for Email Escalation - UAT.xlsx" \
CLIENT=AARA \
CLEAR=--clear
The script prints the number of records loaded on success:
Successfully loaded 42 records for client "AARA".
Append mode (avoid unless instructed)¶
Omitting CLEAR=--clear inserts new records without removing existing ones. This causes
duplicates if the same spreadsheet is loaded more than once. Only use append mode if a developer
has explicitly instructed you to.
4. Verify the load¶
After loading, confirm the record count in the script output looks correct. If you are unsure, ask a developer to verify via the application's escalation endpoint.
If the script exits with an error before printing the success message, the database has not been modified — the transaction was rolled back. Check the error output and escalate to a developer if you cannot resolve it.
Escalation¶
If a command returns an unexpected error, escalate to the development team with:
- The exact command run (or make target and arguments).
- The full error output.
- The environment (UAT or PROD) and approximate time.
- The client name (
CLIENT=) if running a bulk load.