Skip to main content

QRG Workflow

Overview

The QRG workflow supports both generation (creating new QRGs from EOP annexes) and editing (modifying existing QRG sections). Both expose async toolchains: kickoff → status → result.

Generation vs Editing

QRG Generation:

  • Processes entire Emergency Operation Plan (EOP) to generate Quick Reference Guides
  • Fetches annex forms from MOEOP API
  • Resolves exact General User Tag Categories from the compiled EOP
  • Builds every annex × category target and uses one agent to recommend/generate the guide
  • Classifies annex names deterministically; there is no AI group extraction or role mapping
  • Tracks category target decisions and processing status per annex
  • Logs all errors to qrg_execution_errors table
  • Supports both DISTRICT and FACILITY generation scopes
  • dryRun: true still persists internal request and tracking rows; it only skips K12 platform writes
  • Saves the exact category ID and leaves generalUserTagIds empty

QRG Editing:

  • Modifies individual QRG sections (BEFORE/DURING/AFTER)
  • Requires quickReferenceGuide metadata object
  • Single AI call to transform content based on prompt
  • Stores result in qrg_edits table

Form Processing & Validation

The QRG generation workflow processes annex forms with these principles:

  1. Snapshot selection: Forms are fetched from the compiled EOP snapshot, optionally filtered by K12_ANNEX_FORM_TYPE_IDS.
  2. Target-level handling: Empty annex content produces an audited skip for every selected category without a model call.
  3. FormStatus tracking: The source status is retained in per-annex evidence for diagnosis.

Why this approach?

  • Database traceability: All processed forms appear in qrg_generation_annexes
  • Error debugging: target decisions in qrg_generation_annexes, AI calls, and qrg_execution_errors show what skipped or failed and why
  • User transparency: Can query "which forms were skipped vs errored"

Error Logging Architecture

Two complementary error tables:

  1. qrg_ai_calls - Individual AI call failures

    • Tracks each LLM invocation
    • Records prompt, response, tokens, duration
    • Status: success/error/timeout
  2. qrg_execution_errors - Workflow-level failures

    • Empty form validation failures
    • MOEOP API errors
    • Workflow step failures
    • Links to specific annex via (RequestId, AnnexId)

Use vw_qrg_error_summary for joined error analysis with request/annex context.

Public tool endpoints (APIM)

  • Base URL (K12 Azure Dev APIM): https://dev-k12-aitools-t27p-apim.azure-api.net
  • Endpoint template: POST /ai/api/tools/{toolId}/execute
  • Payload shape: { "data": { ... } }
  • Required headers (APIM):
    • Authorization: Bearer {access_token}
    • Ocp-Apim-Subscription-Key: {subscription_key}

Note: Examples on this page use APIM subscription keys for quick curl snippets; for tenant-hosted automation and production workflows, prefer OAuth bearer tokens (client credentials) issued by the Azure Entra tenant. - Content-Type: application/json

When calling a local dev server without APIM/auth, auth headers may be omitted.

Payload contract & required fields

  • userId (UUID) — requestor identifier
  • roleId (UUID) — persona performing the edit
  • sectionBEFORE|DURING|AFTER
  • content — current HTML content for the specified section
  • prompt — requested transformation (short, imperative)
  • quickReferenceGuide — metadata object (name, type, instructionFor, organization, tags)

Flow

The QRG editing surface is exposed as three tools to be called in sequence (kickoff → status → result). An optional cancel tool is also available.

1) Kickoff

  • Tool ID: k12-qrg-editing-kickoff
  • Endpoint: POST /ai/api/tools/k12-qrg-editing-kickoff/execute
  • Purpose: Enqueues a QRG editing job, persists the payload, and launches the workflow.

Notes:

  • requestId is server-generated; do not provide it.
  • sessionId is required and can be null to start a new session.

Example (cURL — kickoff):

curl -X POST "$BASE_URL/ai/api/tools/k12-qrg-editing-kickoff/execute" \
-H "Authorization: Bearer $TOKEN" \
-H "Ocp-Apim-Subscription-Key: $SUBSCRIPTION_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"roleId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"sessionId": null,
"section": "BEFORE",
"content": "<ul><li>Know evacuation routes</li></ul>",
"prompt": "Add a bullet about checking fire extinguisher locations",
"quickReferenceGuide": {
"name": "Fire Safety Procedures",
"type": "FUNCTIONAL",
"instructionFor": "FIRE",
"generalUserTagManagementType": "ASSIGN_SELECTED",
"generalUserTags": []
}
}
}'

Example response (accepted):

{ "status": "accepted", "requestId": "qrg-req-001", "message": "QRG generation started" }

2) Status polling

  • Tool ID: k12-qrg-editing-status
  • Endpoint: POST /ai/api/tools/k12-qrg-editing-status/execute
  • Request shape: { "data": { "requestIds": ["..."] } }

Example (cURL — status poll):

curl -X POST "$BASE_URL/ai/api/tools/k12-qrg-editing-status/execute" \
-H "Authorization: Bearer $TOKEN" \
-H "Ocp-Apim-Subscription-Key: $SUBSCRIPTION_KEY" \
-H "Content-Type: application/json" \
-d '{"data": {"requestIds": ["$REQUEST_ID"]}}'

Example response:

[
{
"requestId": "9fd2055d-42ab-4c29-bf0d-51bd8f7db3ec",
"sessionId": "0e1a5e3f-3a3c-4d1f-bbc6-0e76b1c4a8c7",
"status": "processing"
}
]

3) Result retrieval

  • Tool ID: k12-qrg-editing-result
  • Endpoint: POST /ai/api/tools/k12-qrg-editing-result/execute

Example (cURL — result fetch):

curl -X POST "$BASE_URL/ai/api/tools/k12-qrg-editing-result/execute" \
-H "Authorization: Bearer $TOKEN" \
-H "Ocp-Apim-Subscription-Key: $SUBSCRIPTION_KEY" \
-H "Content-Type: application/json" \
-d '{"data": {"requestId": "$REQUEST_ID"}}'

Example response (success):

{
"requestId": "9fd2055d-42ab-4c29-bf0d-51bd8f7db3ec",
"sessionId": "0e1a5e3f-3a3c-4d1f-bbc6-0e76b1c4a8c7",
"status": "success",
"message": "<p>Edited QRG section content...</p>",
"isEdit": true
}

4) Cancel job (optional)

  • Tool ID: k12-qrg-cancel
  • Endpoint: POST /ai/api/tools/k12-qrg-cancel/execute

Example (cURL — cancel):

curl -X POST "$BASE_URL/ai/api/tools/k12-qrg-cancel/execute" \
-H "Authorization: Bearer $TOKEN" \
-H "Ocp-Apim-Subscription-Key: $SUBSCRIPTION_KEY" \
-H "Content-Type: application/json" \
-d '{"data": {"requestId": "$REQUEST_ID"}}'

Note: For EOP cancellation, use the separate k12-cancel-task-request tool which operates on the EOP task tables.

Kickoff payload example (QRG)

{
"userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"roleId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"sessionId": null,
"section": "BEFORE",
"content": "<ul><li>Know evacuation routes</li></ul>",
"prompt": "Add a bullet about fire extinguisher locations",
"quickReferenceGuide": {
"name": "Fire Safety Procedures",
"type": "FUNCTIONAL",
"instructionFor": "FIRE"
}
}

Tests

  • QRG tool unit tests: packages/domain-k12/tests/tools/qrg-tools.test.ts
  • E2E tests: tests/e2e/k12/annex-editing.e2e.test.ts
  • Bruno tests: npm run bruno:test:k12

Reference & samples

  • Endpoint docs and sample cURL in docs/reference/workflows/k12/k12-qrg-editing-tool-endpoints.md