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_errorstable - Supports both
DISTRICTandFACILITYgeneration scopes dryRun: truestill persists internal request and tracking rows; it only skips K12 platform writes- Saves the exact category ID and leaves
generalUserTagIdsempty
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:
- Snapshot selection: Forms are fetched from the compiled EOP snapshot, optionally filtered by
K12_ANNEX_FORM_TYPE_IDS. - Target-level handling: Empty annex content produces an audited skip for every selected category without a model call.
- 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, andqrg_execution_errorsshow what skipped or 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