Skip to content
  • There are no suggestions because the search field is empty.

Helpers and the Semantic Layer in .NET

Use the helper methods (EnsureAsync, FindAsync, UpdateAsync, ResolveAsync, CreateApiAsync …) for multi-call tasks, and Planner.PlanRotation / PlanEscalation plus ao.Semantic.ApplyBlueprintAsync to build a verified on-call stack that rolls back on failure.

Overview

Relevant for Developers automating multi-step AlertOps configuration

Helpers are composite operations that sit on the same resources as the endpoints. Examples:

  • ao.Groups.EnsureAsync (find or create).
  • ao.Schedules.UpdateFieldsAsync (read, merge, write the whole shift).
  • ao.Alerts.ResolveAsync (close, or cancel what cannot be closed).

The semantic layer goes further: pure planners turn intent ("after-hours rotation, primary then secondary after 15 minutes") into exact payloads that follow AlertOps' scheduling and escalation invariants. An executor then applies them, verifies every write by reading it back, and rolls back on failure. All of it is ported from the Python reference and replays Python's recorded traces.

Key benefits:

  • Fewer calls to get right: whole-record writes, alert_type naming and member sequencing are handled for you.
  • Invariants enforced:
  • Shifts end on :59.
  • Starts align to the prior Monday.
  • End dates are 5 years out.
  • The escalation ladder starts with Primary.
  • Safe to apply: drift is reported, and a failed blueprint deletes what it created.

Helper conventions

Relevant for Developers calling helpers

Helpers take Python's positional parameters as method parameters. Keyword-only parameters and extra fields go in one trailing Kwargs, keyed by the Python names. Examples:

  • ao.Alerts.ListRecentAsync(3, new Kwargs { ["view_all"] = false, ["status"] = "Open" }).
  • ao.Inbound.CreateApiAsync("Prod API", new Kwargs { ["escalation_policy_id"] = 5, ["recipient_groups"] = new[] { "NOC" } }).

Helpers are the hand-written half of the generated partial resource classes, so they appear in IntelliSense next to the endpoints.

HelperWhat it does
ao.Groups.EnsureAsync(name, fields?)Returns (Group, Created).
ao.Users.FindByUsernameAsync(name)The user, or null (maps 400 "Invalid User" and 404).
ao.EscalationPolicies.UpdateAsync(id, changes)GET basic, then merge, then PUT the whole record. Returns the re-read record.
ao.Schedules.CreateShiftAsync(groupId, name, users, options)Builds an invariant-clean shift (Shifts.ShiftPayload) and resolves an IANA time_zone.
ao.Inbound.CreateApiAsync(name, options)API integration with a unique source. A random one is used if omitted.
ao.Ingest.PostToUrlAsync(apiUrl, payload)Posts an alert payload to an integration URL. Returns the request id.
ao.Alerts.ResolveAsync(alertId, userId, resolution)Closes the alert, or cancels it when it cannot be closed.
ao.Auth.ActOnLinkAsync(link)Runs the action behind a notification link (acknowledge, assign, escalate, close). This is how acknowledgement works end to end.

The inbound integration URL routes by source
Two integrations with the same source share an ingest URL, and alerts can land on the wrong one. CreateApiAsync and CloneUniqueAsync always give each integration its own source.

Plan a rotation and an escalation

Relevant for Developers turning on-call intent into configuration

Planners make no API calls. Inspect their output before you apply it.

using AlertOps.Semantic;

var rotation = Planner.PlanRotation(new RotationSpec("NOC", new[] { new Member(101, "Ann", "Lee"), new Member(102, "Bo", "Ma") })
{
Coverage = new Coverage("after_hours"), // Mon–Fri 17:00 → 07:59, weekly rotation
});
var escalation = Planner.PlanEscalation(new[] { new Step(0, "primary", 101), new Step(5, "primary", 102), new Step(15, "secondary", 101) });
Console.WriteLine($"{escalation.Mode}: {escalation.Reason}"); // escalation_policy: Escalation policy Primary → Secondary …
Console.WriteLine(Planner.ValidateDesign(rotation, escalation).Count); // 0 when clean

PlanEscalation chooses an escalation policy when the timeline fits its four timing levers. It falls back to a response play, with per-step waits, when it doesn't: more than 4 distinct intervals, or unequal gaps within one role.

Apply a verified stack

Relevant for Developers creating an on-call setup in a tenant

var report = await ao.Semantic.ApplyBlueprintAsync(new Blueprint("NOC")
{
Rotation = rotation, Escalation = escalation, Integration = new IntegrationSpec("NOC API"),
});
Console.WriteLine(report.Summary()); // OK: created 4 … (+ group, + schedule, + escalation_policy, + inbound_integration)
if (!report.Ok) Console.WriteLine(string.Join("\n", report.Drift));
await ao.Semantic.RollbackAsync(report); // remove everything the report created
Report memberMeaning
Created / ReusedObjects made by this call, and objects it found and reused. Rollback only deletes Created.
DriftDifferences between the plan and what the tenant read back. Ok is false when there is any drift.
ReviewItemsPlanner and validator notes. block items stop the apply.
RolledBackTrue after RollbackAsync.
Ids(kind) / Summary()Ids of one kind, in order, and the same text summary as Python's Report.summary().

Blocking review items stop the apply
A blueprint whose integration has no escalation policy, or a rotation with no Primary in week 1, throws ValueError before anything is created.

Troubleshooting

Relevant for Anyone whose helper or apply fails

ValueError: group has a shift: roles are set on the shift

  • Once a group has a shift, AlertOps rejects Primary and Secondary on members. Call ao.Semantic.EnsureMembersAsync without roles, or with ["Manager"].

The report shows drift

  • Read the drift line: it names the field, the planned value and the value read back. A shift that reads back continuous=True was saved differently by the server. Adjust the plan and apply again.

Related Articles

Need help?

Email support@alertops.com or contact your AlertOps representative.