eeshwar143
Clean submission history
e4accbb
"""Deterministic task catalog for the support triage environment."""
from __future__ import annotations
from pydantic import BaseModel, ConfigDict, Field
from support_queue_env.models import Difficulty, Disposition, Priority, QueueName
class TicketSpec(BaseModel):
model_config = ConfigDict(extra="forbid")
ticket_id: str
subject: str
body: str
customer_tier: str
product_area: str
sla_hours: int
recent_events: list[str] = Field(default_factory=list)
expected_priority: Priority
expected_queue: QueueName
expected_disposition: Disposition
acceptable_queues: list[QueueName] = Field(default_factory=list)
acceptable_dispositions: list[Disposition] = Field(default_factory=list)
summary_keywords: list[str] = Field(default_factory=list)
response_keywords: list[str] = Field(default_factory=list)
disallowed_keywords: list[str] = Field(default_factory=list)
class TaskSpec(BaseModel):
model_config = ConfigDict(extra="forbid")
task_id: str
title: str
difficulty: Difficulty
description: str
instructions: str
tickets: list[TicketSpec]
TASKS: list[TaskSpec] = [
TaskSpec(
task_id="easy_inbox_cleanup",
title="Inbox Cleanup",
difficulty="easy",
description="Two straightforward tickets covering access and billing triage.",
instructions=(
"You are a SaaS support triage agent. For each ticket, choose priority, routing queue, "
"and the next best disposition. Write a short internal summary plus the first reply you "
"would send to the customer."
),
tickets=[
TicketSpec(
ticket_id="E-101",
subject="Locked out after password reset",
body=(
"I reset my password this morning and now the admin portal says my account is locked. "
"We need to finish payroll before noon."
),
customer_tier="starter",
product_area="auth",
sla_hours=24,
recent_events=["Password reset completed 2 hours ago", "No prior incidents on status page"],
expected_priority="P3",
expected_queue="technical",
expected_disposition="respond",
summary_keywords=["account", "locked", "password"],
response_keywords=["verify", "unlock", "reset"],
disallowed_keywords=["refund", "breach"],
),
TicketSpec(
ticket_id="E-102",
subject="We were charged twice for March",
body=(
"Our card shows two identical charges from your company for invoice INV-4481. "
"Please confirm whether one of them will be refunded."
),
customer_tier="growth",
product_area="billing",
sla_hours=8,
recent_events=["Invoice INV-4481 marked paid yesterday"],
expected_priority="P2",
expected_queue="billing",
expected_disposition="respond",
summary_keywords=["duplicate", "charge", "invoice"],
response_keywords=["refund", "investigate", "billing"],
disallowed_keywords=["ignore", "security incident"],
),
],
),
TaskSpec(
task_id="medium_sla_defense",
title="SLA Defense",
difficulty="medium",
description="Three tickets that mix urgent escalation with an ambiguity check.",
instructions=(
"Prioritize by customer impact and risk. Security events and broad service degradation should "
"be escalated immediately. If the customer has not given enough evidence to act safely, ask for "
"the minimum details needed to proceed."
),
tickets=[
TicketSpec(
ticket_id="M-201",
subject="Suspicious email asking admins to re-enter credentials",
body=(
"Several admins received an email that looks like your login page and asks us to "
"re-authenticate. One teammate clicked it but says they closed the tab before typing anything."
),
customer_tier="enterprise",
product_area="security",
sla_hours=1,
recent_events=["Customer SSO is enabled", "No status page incident posted"],
expected_priority="P1",
expected_queue="security",
expected_disposition="escalate",
summary_keywords=["phishing", "credentials", "admins"],
response_keywords=["security", "escalated", "do not click"],
disallowed_keywords=["send password", "share secrets"],
),
TicketSpec(
ticket_id="M-202",
subject="Webhook deliveries are failing after yesterday's rollout",
body=(
"Every webhook call since 06:15 UTC has returned HTTP 500. This is blocking our downstream "
"fulfillment pipeline. Can you investigate urgently?"
),
customer_tier="growth",
product_area="integrations",
sla_hours=4,
recent_events=["Customer is on API version 2025-11", "Platform release went out last night"],
expected_priority="P2",
expected_queue="technical",
expected_disposition="escalate",
acceptable_queues=["success"],
summary_keywords=["webhook", "500", "rollout"],
response_keywords=["engineering", "logs", "investigate"],
disallowed_keywords=["duplicate charge", "unsubscribe"],
),
TicketSpec(
ticket_id="M-203",
subject="Maybe double charged? Not fully sure",
body=(
"My finance teammate thinks we were double billed, but I can only find one invoice in the portal. "
"Could you explain what happened and what details you need from me?"
),
customer_tier="growth",
product_area="billing",
sla_hours=12,
recent_events=["One paid invoice visible in portal", "No payment failures recorded"],
expected_priority="P3",
expected_queue="billing",
expected_disposition="request_info",
acceptable_dispositions=["respond"],
summary_keywords=["billing", "unclear", "invoice"],
response_keywords=["invoice", "last four", "amount"],
disallowed_keywords=["breach", "status page"],
),
],
),
TaskSpec(
task_id="hard_exec_escalations",
title="Executive Escalations",
difficulty="hard",
description="Four high-stakes tickets that require precise triage under pressure.",
instructions=(
"You are covering an executive escalation queue during a busy incident window. Optimize for "
"business continuity, account safety, and clean handoffs. Use P1 only for severe production or "
"security impact. Ask for more detail only when it materially changes the next safe action."
),
tickets=[
TicketSpec(
ticket_id="H-301",
subject="All agents see 502 during login",
body=(
"Our entire support floor is blocked from logging in. Every browser gets a 502 after "
"submitting the sign-in form. The public status page still says operational."
),
customer_tier="enterprise",
product_area="auth",
sla_hours=1,
recent_events=["50+ seats on account", "Issue started 18 minutes ago"],
expected_priority="P1",
expected_queue="technical",
expected_disposition="escalate",
summary_keywords=["login", "502", "all agents"],
response_keywords=["incident", "engineering", "urgent"],
disallowed_keywords=["refund only", "close ticket"],
),
TicketSpec(
ticket_id="H-302",
subject="Unknown OAuth app connected after employee departure",
body=(
"An OAuth app named 'SyncFast' appeared in our workspace this morning from an IP we don't recognize. "
"The only recent account change is that one contractor left yesterday."
),
customer_tier="enterprise",
product_area="security",
sla_hours=1,
recent_events=["Customer has audit logs enabled", "Former contractor account was deactivated yesterday"],
expected_priority="P1",
expected_queue="security",
expected_disposition="escalate",
summary_keywords=["oauth", "unknown", "contractor"],
response_keywords=["security", "revoke", "escalated"],
disallowed_keywords=["share api key", "ignore"],
),
TicketSpec(
ticket_id="H-303",
subject="Renewal quote lost our committed discount",
body=(
"Our renewal quote is missing the 18% discount your sales team committed in writing. "
"Our CFO will freeze procurement tomorrow if this isn't corrected."
),
customer_tier="enterprise",
product_area="commercial",
sla_hours=6,
recent_events=["Renewal date in 2 days", "Account owner is on PTO"],
expected_priority="P2",
expected_queue="success",
expected_disposition="escalate",
acceptable_queues=["billing"],
summary_keywords=["renewal", "discount", "cfo"],
response_keywords=["account manager", "quote", "escalated"],
disallowed_keywords=["security breach", "reset password"],
),
TicketSpec(
ticket_id="H-304",
subject="Need cancellation plus data export",
body=(
"We're planning to cancel next month for budget reasons, but first I need a data export for "
"our records. Please tell me exactly what you need from me to start."
),
customer_tier="starter",
product_area="retention",
sla_hours=24,
recent_events=["No open invoices", "Account is owner-managed"],
expected_priority="P3",
expected_queue="success",
expected_disposition="request_info",
acceptable_queues=["billing"],
summary_keywords=["cancel", "data export", "verification"],
response_keywords=["verify", "export", "owner"],
disallowed_keywords=["breach", "status page"],
),
],
),
]
TASK_INDEX = {task.task_id: task for task in TASKS}