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
- Uses 4-step AI pipeline per annex: classify → extract → map → generate
- Tracks processing status per annex with FormStatus for traceability
- Logs all errors to
qrg_execution_errorstable - Saves QRGs to K12 only for FACILITY organizations (DISTRICT requires
skipK12OrgValidation=trueor no-save mode) dryRun: truestill persists internal request and tracking rows; it only skips K12 platform writes- QRG role mapping uses the EOP-selected role set and skips organization-wide role-universe fetches
QRG Editing:
- Modifies individual QRG sections (BEFORE/DURING/AFTER)
- Requires
quickReferenceGuidemetadata object - Single AI call to transform content based on prompt
- Stores result in
qrg_editstable
Form Processing & Validation
The QRG generation workflow processes annex forms with these principles:
- Permissive Selection: Forms are fetched from MOEOP regardless of content state
- Validation at Processing: Empty forms (
data: {}) are caught during workflow execution - FormStatus Tracking: Distinguishes between:
IN_PROGRESS+ empty data → Error (user hasn't started)COMPLETED+ empty data → Valid (user accepted defaults)- Any status + has content → Process normally
Why this approach?
- Database traceability: All processed forms appear in
qrg_generation_annexes - Error debugging:
qrg_execution_errorscaptures exactly which forms failed and why - User transparency: Can query "which forms were skipped vs errored"
Error Logging Architecture
Two complementary error tables:
-
qrg_ai_calls- Individual AI call failures- Tracks each LLM invocation
- Records prompt, response, tokens, duration
- Status: success/error/timeout
-
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 identifierroleId(UUID) — persona performing the editsection—BEFORE|DURING|AFTERcontent— current HTML content for the specified sectionprompt— 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:
requestIdis server-generated; do not provide it.sessionIdis required and can benullto 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-requesttool 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