HyperBrickCaseOps / tasks.py
modelbuilderhq's picture
Upload folder using huggingface_hub
4f129c9 verified
raw
history blame
18 kB
"""Task registry for the SupportDesk environment."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
from models import KnowledgeSnippet, SupportTicket
ALL_QUEUES = [
"billing_ops",
"trust_and_safety",
"platform_engineering",
"compliance_ops",
"general_support",
]
ALL_PRIORITIES = ["low", "normal", "high", "urgent"]
ALL_STATUSES = ["new", "waiting_on_customer", "resolved", "escalated"]
ALL_ISSUE_TYPES = [
"duplicate_charge",
"account_compromise",
"production_incident",
"regulated_exception",
"general_question",
]
@dataclass(frozen=True)
class SupportTaskSpec:
"""Immutable definition of a single support triage task."""
task_id: str
difficulty: Literal["easy", "medium", "hard"]
title: str
objective: str
ticket: SupportTicket
knowledge_base: tuple[KnowledgeSnippet, ...]
gold_queue: str
gold_priority: str
gold_issue_type: str
gold_status: str
gold_resolution_code: str
required_requested_fields: tuple[str, ...]
required_reply_markers: tuple[tuple[str, ...], ...]
required_note_markers: tuple[tuple[str, ...], ...]
forbidden_reply_markers: tuple[str, ...] = ()
risk_flags: tuple[str, ...] = ()
follow_up_outcome: Literal["none", "partial", "complete", "incorrect"] = "none"
follow_up_message: str = ""
follow_up_provided_fields: tuple[str, ...] = ()
follow_up_wrong_fields: tuple[str, ...] = ()
sla_step_cost: int = 15
over_escalation_queues: tuple[str, ...] = ()
under_escalation_deadline_step: int | None = None
max_steps: int = 6
TASKS: dict[str, SupportTaskSpec] = {
"billing_refund_easy": SupportTaskSpec(
task_id="billing_refund_easy",
difficulty="easy",
title="Duplicate charge refund triage",
objective=(
"Triage a duplicate-charge billing ticket, send the correct customer response, "
"and close the case only if no further customer information is required."
),
ticket=SupportTicket(
customer_name="Riya Shah",
customer_tier="pro",
company="PixelNorth Studio",
subject="Charged twice after I canceled",
body=(
"I canceled our Pro annual workspace yesterday, but my card was charged again "
"this morning and I still see the old invoice. We only had one workspace, "
"so this looks like a duplicate charge. Please fix it quickly."
),
region="ap-south-1",
affected_users=12,
sla_minutes_remaining=240,
business_impact="Finance ops are blocked from closing the monthly books until the duplicate invoice is fixed.",
secondary_concerns=["The customer also wants confirmation that the canceled workspace will stay deactivated."],
attachments=["invoice_7741.pdf"],
),
knowledge_base=(
KnowledgeSnippet(
article_id="KB-101",
title="Duplicate charges and same-day cancellations",
content=(
"If a customer reports a duplicate charge and the subscription is already "
"canceled, route the ticket to billing_ops with high priority. Billing can "
"approve the refund immediately without requesting extra information when an "
"invoice is attached."
),
),
KnowledgeSnippet(
article_id="KB-102",
title="Refund communication checklist",
content=(
"Customer replies for approved duplicate-charge refunds must confirm that a "
"refund is being processed, mention the duplicate charge, and set the "
"expectation that funds typically appear within 5-7 business days."
),
),
KnowledgeSnippet(
article_id="KB-103",
title="When to close a billing case",
content=(
"Close the case as resolved only after the refund path is clear and no more "
"customer details are needed."
),
),
),
gold_queue="billing_ops",
gold_priority="high",
gold_issue_type="duplicate_charge",
gold_status="resolved",
gold_resolution_code="refund_approved",
required_requested_fields=(),
required_reply_markers=(
("refund", "refunded", "reimburse"),
("duplicate charge", "charged twice", "double charge"),
("5-7 business days", "5 to 7 business days", "within 7 business days"),
),
required_note_markers=(
("duplicate charge", "double charge"),
("refund", "refund approved"),
),
forbidden_reply_markers=("chargeback", "security team"),
risk_flags=("finance_close_risk", "avoid_unnecessary_back_and_forth"),
over_escalation_queues=("trust_and_safety", "platform_engineering", "compliance_ops"),
sla_step_cost=10,
max_steps=6,
),
"account_takeover_medium": SupportTaskSpec(
task_id="account_takeover_medium",
difficulty="medium",
title="Suspicious login recovery triage",
objective=(
"Handle a potential account-compromise case, request the missing verification "
"details, communicate safe next steps, and keep the case open until the customer replies. "
"The agent must protect account safety without promising an unsafe immediate unlock."
),
ticket=SupportTicket(
customer_name="Marcus Lee",
customer_tier="pro",
company="Northline Analytics",
subject="Locked out after strange login alert",
body=(
"Our workspace admin got a login alert from a country none of us have visited, "
"and now I can't get back into the account. Please unlock it ASAP. The billing "
"email is still ours, but I'm worried someone got in."
),
region="us-east-1",
affected_users=34,
sla_minutes_remaining=90,
business_impact="The admin is locked out of the analytics workspace ahead of the Monday executive review.",
secondary_concerns=["The customer wants the account unlocked immediately, but the verification flow cannot be skipped."],
attachments=[],
),
knowledge_base=(
KnowledgeSnippet(
article_id="SEC-201",
title="Account compromise routing",
content=(
"Potential account-takeover reports route to trust_and_safety with urgent "
"priority. Do not resolve the case immediately."
),
),
KnowledgeSnippet(
article_id="SEC-202",
title="Verification details before unlock",
content=(
"Before access can be restored, ask the customer for the workspace_id, the "
"last successful login time, and the billing email on file. Keep the status "
"waiting_on_customer until the details arrive."
),
),
KnowledgeSnippet(
article_id="SEC-203",
title="Customer response checklist",
content=(
"Security replies should tell the customer to reset their password, scan "
"their device for malware, and explain that the trust team is reviewing the case."
),
),
),
gold_queue="trust_and_safety",
gold_priority="urgent",
gold_issue_type="account_compromise",
gold_status="waiting_on_customer",
gold_resolution_code="verification_needed",
required_requested_fields=("workspace_id", "last_successful_login", "billing_email"),
required_reply_markers=(
("reset your password", "change your password"),
("scan", "malware", "device check"),
("trust team", "security team", "trust and safety"),
),
required_note_markers=(
("suspicious login", "strange login"),
("locked out", "can't get back", "cannot get back"),
),
risk_flags=("unsafe_unlock_request", "identity_verification_required"),
follow_up_outcome="partial",
follow_up_message=(
"Customer follow-up: workspace_id=ws_9021 and billing email confirmed, "
"but they could not provide the last successful login time yet."
),
follow_up_provided_fields=("workspace_id", "billing_email"),
sla_step_cost=18,
under_escalation_deadline_step=2,
max_steps=7,
),
"api_incident_hard": SupportTaskSpec(
task_id="api_incident_hard",
difficulty="hard",
title="Production API incident escalation",
objective=(
"Triage a high-pressure enterprise incident, ask for the right diagnostics, notify "
"the customer that engineering is engaged, and escalate instead of resolving. "
"The agent must prioritize the outage over a tempting secondary compliance question."
),
ticket=SupportTicket(
customer_name="Asha Verma",
customer_tier="enterprise",
company="Kairo Health",
subject="EU rollout blocked by intermittent 500s",
body=(
"We're launching our EU workspace tonight. Since enabling EU data residency we "
"see intermittent HTTP 500 responses from /v1/exports in production. Our "
"compliance lead is also asking whether this affects the audit trail, but the "
"main issue is the outage. We need help immediately."
),
region="eu-west-1",
affected_users=1800,
sla_minutes_remaining=25,
business_impact="A production launch and a customer-facing compliance review are both at risk tonight if the outage persists.",
secondary_concerns=["The compliance lead is asking whether audit trails are affected, but the live outage is the primary incident."],
attachments=["error_screenshot.png"],
),
knowledge_base=(
KnowledgeSnippet(
article_id="INC-301",
title="Production availability incidents",
content=(
"Any active production 5xx incident for a paying customer routes to "
"platform_engineering with urgent priority and should be escalated, not resolved."
),
),
KnowledgeSnippet(
article_id="INC-302",
title="Minimum diagnostics for API incidents",
content=(
"Before engineering can investigate, request concrete examples including "
"request_ids, UTC timestamps, and the affected region."
),
),
KnowledgeSnippet(
article_id="INC-303",
title="Customer communication during an incident",
content=(
"The reply should acknowledge an incident, say the on-call engineering team "
"is engaged, and ask for the diagnostics needed to speed investigation."
),
),
KnowledgeSnippet(
article_id="INC-304",
title="Primary issue triage rule",
content=(
"When a production outage appears alongside a secondary compliance or audit "
"question, resolve the live outage first and avoid treating the secondary "
"question as the primary queue-driving issue."
),
),
),
gold_queue="platform_engineering",
gold_priority="urgent",
gold_issue_type="production_incident",
gold_status="escalated",
gold_resolution_code="incident_opened",
required_requested_fields=("request_ids", "timestamp_utc", "region"),
required_reply_markers=(
("incident", "outage", "investigating"),
("on-call", "engineering team", "engineering is engaged"),
("request id", "request_ids"),
("utc", "timestamp"),
),
required_note_markers=(
("eu data residency", "eu rollout"),
("500", "http 500"),
("launch tonight", "tonight"),
),
risk_flags=("sev1_launch_risk", "secondary_issue_distraction", "engineering_escalation_required"),
follow_up_outcome="complete",
follow_up_message=(
"Customer follow-up: request_ids=req_991, req_998; UTC timestamps=2026-04-01T19:20Z, "
"2026-04-01T19:27Z; region=eu-west-1."
),
follow_up_provided_fields=("request_ids", "timestamp_utc", "region"),
sla_step_cost=25,
under_escalation_deadline_step=2,
max_steps=8,
),
"regulated_export_exception_hard": SupportTaskSpec(
task_id="regulated_export_exception_hard",
difficulty="hard",
title="Regulated export exception triage",
objective=(
"Handle a regulated export-access request where the customer wants a manual bypass. "
"The agent must avoid escalating to engineering just because an export error is mentioned, "
"route to compliance operations, request the right legal details, and keep the case open "
"until the required approvals are supplied."
),
ticket=SupportTicket(
customer_name="Dr. Elena Kovacs",
customer_tier="enterprise",
company="NorthSea Clinics",
subject="Need urgent export unlock before audit review",
body=(
"Our audit team needs tonight's export package, but after enabling EU residency the "
"export workflow now shows a policy block. Can you temporarily disable the restriction "
"or give us a manual bypass just for this audit? We are under pressure and can share "
"screenshots if needed."
),
region="eu-central-1",
affected_users=240,
sla_minutes_remaining=55,
business_impact="A regulated healthcare audit review may slip tonight if the export path remains blocked.",
secondary_concerns=[
"The customer suggests an engineering workaround, but legal approval is the real gating factor."
],
attachments=["policy_block.png"],
),
knowledge_base=(
KnowledgeSnippet(
article_id="CMP-401",
title="Export policy exceptions",
content=(
"Requests to bypass region or export restrictions route to compliance_ops. "
"Do not promise a manual engineering workaround before approvals are verified."
),
),
KnowledgeSnippet(
article_id="CMP-402",
title="Minimum legal details for export review",
content=(
"Ask for the tenant_region, dpa_amendment_id, and legal_contact_email before "
"compliance can review an export exception."
),
),
KnowledgeSnippet(
article_id="CMP-403",
title="Customer response rules for regulated exceptions",
content=(
"Replies must explain that no temporary bypass can be granted yet, mention the "
"compliance review, and request the required legal approval details."
),
),
),
gold_queue="compliance_ops",
gold_priority="high",
gold_issue_type="regulated_exception",
gold_status="waiting_on_customer",
gold_resolution_code="legal_approval_required",
required_requested_fields=("tenant_region", "dpa_amendment_id", "legal_contact_email"),
required_reply_markers=(
("no temporary bypass", "cannot provide a bypass", "can’t provide a bypass"),
("compliance review", "compliance team"),
("tenant_region", "tenant region"),
("dpa_amendment_id", "dpa amendment", "amendment id"),
),
required_note_markers=(
("audit", "audit review"),
("eu residency", "policy block"),
("manual bypass", "workaround"),
),
forbidden_reply_markers=("engineering workaround", "disable the restriction", "temporary unlock approved"),
risk_flags=("regulated_data_risk", "unsafe_shortcut_pressure", "over_escalation_risk"),
follow_up_outcome="incorrect",
follow_up_message=(
"Customer follow-up: sent a screenshot and export job ID, but did not include the DPA "
"amendment ID or legal contact."
),
follow_up_wrong_fields=("screenshot", "job_id"),
sla_step_cost=16,
over_escalation_queues=("platform_engineering",),
max_steps=8,
),
}
def get_task(task_id: str) -> SupportTaskSpec:
"""Return a task definition or raise a helpful error."""
try:
return TASKS[task_id]
except KeyError as exc: # pragma: no cover - defensive
valid = ", ".join(sorted(TASKS))
raise ValueError(f"Unknown task_id '{task_id}'. Valid task ids: {valid}") from exc
def list_task_ids() -> list[str]:
"""List tasks in a stable evaluation order."""
return list(TASKS)