DEV Community

Sonam
Sonam

Posted on

Build an Outage Hotline with Telnyx Decision Models at the Edge

During an outage, the difficult problem is not collecting one report. It is turning a sudden flood of short, inconsistent reports into decisions your application can act on.

Is the caller reporting no service, degraded service, billing trouble, or something else? How severe is it? Does it describe the active incident, or a new problem?

Those are decision problems, not open-ended writing tasks.

The Regional Outage-Reporting Hotline uses Telnyx Decision Models to answer all three questions in one structured request. Telnyx Edge Compute then gives those decisions regional context: one Stateful Actor per region, private SQLDB history, and a small KV record containing the known active issue.

Why use a decision model here?

A general chat completion can return JSON, but the application still has to prompt for a schema, validate free-form output, and decide what each number means.

The Telnyx decision-model endpoint is designed around named, typed questions evaluated against shared state:

  • choice selects one category from a supplied set.
  • score rates an ordered rubric and returns an expected, potentially fractional index.
  • noul evaluates a yes/no condition and returns the positive outcome's score from 0 to 1.

The outage hotline sends one report plus the region's active-incident context as state, then asks:

{
  issue_type: {
    type: "choice",
    instructions: "Classify the type of outage being reported.",
    criteria: {
      no_service: "Complete loss of service",
      degraded: "Service works but is impaired",
      billing: "Billing or account issue",
      other: "None of the supplied categories"
    }
  },
  severity: {
    type: "score",
    instructions: "Rate the operational severity of this report.",
    criteria: ["Low", "Normal", "High", "Critical"]
  },
  is_duplicate: {
    type: "noul",
    instructions: "Does this describe the same already-known regional outage?"
  }
}
Enter fullscreen mode Exit fullscreen mode

The function posts that payload to:

POST https://api.telnyx.com/v2/ai/typesafe/v1/systemone
Enter fullscreen mode Exit fullscreen mode

The sample sends state and questions. Because it does not explicitly set a model, the endpoint uses telnyx/decision-flash, the documented default intended for low-cost, low-latency, high-volume decisions. Telnyx also provides telnyx/decision-pro for decisions that need longer context.

The response is a complete JSON object with answers keyed by the names above. There is no free-form assistant message to parse.

Make every primitive earn its place

The model supplies typed decisions. The Edge architecture makes those decisions useful during a regional spike.

One Stateful Actor per region

The intake route derives an actor key from the region:

const id = env.REGIONS.idFromName(`region-${region}`);
const actor = env.REGIONS.get(id);
Enter fullscreen mode Exit fullscreen mode

Every report for the same region reaches the same actor. If actors were keyed by caller, every report would live alone and there would be nothing meaningful to aggregate.

SQLDB for operational history

Each actor owns a private SQLite database containing raw reports, typed model answers, rounded severity buckets, escalation decisions, and optional ground-truth labels.

That gives the dashboard real relational queries: reports during the last hour, severity breakdowns, distinct issue types, and evaluation metrics. This is GROUP BY work, not a reason to scan a KV dump.

KV for the hot incident context

The actor also keeps one small active_issue record in KV. It is read before every classification and included in the model state:

Caller report from region 415: "Internet is still down."
Known active issue in this region: no_service, first seen ..., still active.
Enter fullscreen mode Exit fullscreen mode

That context gives the is_duplicate question something concrete to compare against without querying the report database on every intake.

Scores need application policy

The API documentation makes two important distinctions.

First, a score result is the expected zero-based position on the supplied rubric. For Low, Normal, High, and Critical, the range is 0 to 3 and may be fractional. The sample stores the raw value for evaluation, then rounds it only when it needs an operational severity bucket.

Second, the confidence returned for choice and score describes how concentrated the option scores are. It is not a calibrated probability that the answer is correct. The hotline therefore does not escalate simply because confidence looks high. It combines the chosen issue type, a severity rule, and an application-defined duplicate threshold.

That separation is important: the model produces structured evidence; the application owns the policy.

Measure instead of assuming

The repository includes loadgen.mjs, which sends a labeled 13-report scenario covering a seed outage, repeat reports, billing noise, degraded service, and a distinct critical incident.

The sample stores expected labels alongside model results and exposes an evaluation dashboard with:

  • issue-type accuracy and a confusion matrix
  • severity mean absolute error and bucket accuracy
  • duplicate accuracy across several thresholds
  • confidence-versus-correctness bins

This is especially useful for decision models because option wording, taxonomy, context, and thresholds all affect application behavior. The right threshold comes from representative examples, not from copying a number out of a tutorial.

The taxonomy is also runtime configuration. You can add an issue category, change the severity rubric, or adjust policy thresholds without redeploying the function. Every stored report records the schema version used for its classification.

Run the example

Set a Telnyx API key as an Edge secret and deploy:

telnyx-edge secrets add TELNYX_API_KEY "<YOUR_API_KEY>"
npm install
telnyx-edge ship
Enter fullscreen mode Exit fullscreen mode

Then run the labeled scenario against the deployed URL:

node loadgen.mjs \
  --url https://edge-outage-hotline-typescript-<id>.telnyxcompute.com \
  --region 415 \
  --reset
Enter fullscreen mode Exit fullscreen mode

The core sample accepts reports through POST /intake; it does not require a phone number. You can place Voice, messaging, or another intake channel in front of that route when adapting the pattern to a production hotline.

Resources

This example is useful beyond outages. The same pattern can classify support requests, score urgency, detect repeated incidents, route operational events, or evaluate any high-volume stream where your application needs typed decisions rather than generated prose.

Top comments (0)