fai-azure-event-grid-setup — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited fai-azure-event-grid-setup (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Sets up Event Grid topics and subscriptions for event-driven AI workflows. Routes blob uploads to embedding pipelines, model evaluations to notification services, and failures to dead-letter queues. Prevents the friction of polling-based workflows: wasted compute, race conditions, and N-minute latency before action.
| Signal | Example |
|---|---|
| Polling for new documents exists | Cron job checks blob storage every 5 minutes |
| End-to-end latency is high | Document uploaded at 10:00, indexed at 10:05 |
| Failure handling is manual | Failed embeding jobs accumulate in a folder |
| Cross-service coordination is complex | Embedding → RAG index → refresh dashboard |
// infra/event-grid.bicep
param location string
param topicName string
resource topic 'Microsoft.EventGrid/topics@2023-12-15-preview' = {
name: topicName
location: location
identity: { type: 'SystemAssigned' }
properties: {
publicNetworkAccess: 'Disabled'
inputSchema: 'CloudEventSchema'
}
}
// System topic for Blob Storage events
resource blobTopic 'Microsoft.EventGrid/systemTopics@2023-12-15-preview' = {
name: '${storageAccountName}-blob-topic'
location: location
properties: {
source: storageAccountId
topicType: 'Microsoft.Storage.StorageAccounts'
}
}// Subscription 1: Route blob uploads to embedding pipeline
resource embeddingSubscription 'Microsoft.EventGrid/topics/eventSubscriptions@2023-12-15-preview' = {
parent: blobTopic
name: 'to-embedding-queue'
properties: {
destination: {
endpointType: 'ServiceBusQueue'
properties: {
resourceId: embeddingQueueId
}
}
filter: {
subjectBeginsWith: '/blobServices/default/containers/documents'
subjectEndsWith: '.pdf'
includedEventTypes: ['Microsoft.Storage.BlobCreated']
}
retryPolicy: {
maxDeliveryAttempts: 30
eventTimeToLiveInMinutes: 1440 // 24 hours
}
deadLetterDestination: {
endpointType: 'StorageBlob'
properties: {
resourceId: deadLetterStorageId
blobContainerName: 'event-grid-deadletter'
}
}
}
}
// Subscription 2: Route completion events to notification service
resource notificationSubscription 'Microsoft.EventGrid/topics/eventSubscriptions@2023-12-15-preview' = {
parent: topic
name: 'to-notifications'
properties: {
destination: {
endpointType: 'WebHook'
properties: {
endpointUrl: 'https://notification-service.azurewebsites.net/webhooks/embedding-complete'
}
}
filter: {
advancedFilters: [
{
operatorType: 'StringIn'
key: 'data.status'
values: ['completed']
},
{
operatorType: 'NumberGreaterThan'
key: 'data.embedding_count'
value: 100
}
]
}
}
}from azure.eventgrid import EventGridPublisherClient, CloudEvent
from azure.identity import DefaultAzureCredential
import json
client = EventGridPublisherClient(
endpoint=EVENT_GRID_ENDPOINT,
credential=DefaultAzureCredential(),
)
# Publish embedding completion event
event = CloudEvent(
type="ai.embedding.completed",
source="/embeddings/batch-001",
data={
"batch_id": "batch-001",
"document_id": "doc-12345",
"embedding_count": 250,
"status": "completed",
"duration_ms": 3420,
"cost_usd": 0.15,
}
)
client.send(event)from azure.storage.queue import QueueClient
from azure.identity import DefaultAzureCredential
import json
queue_client = QueueClient(
account_url=f"https://{STORAGE_ACCOUNT}.queue.core.windows.net",
queue_name="eventgrid-deadletter",
credential=DefaultAzureCredential(),
)
def process_deadletter():
"""Retry or log failed events."""
while True:
message = queue_client.receive_message()
if not message:
break
event_data = json.loads(message.content)
print(f"Dead-lettered event: {event_data['data']['eventType']}")
print(f" Reason: {event_data.get('deadLetterReason')}")
print(f" Details: {event_data.get('deadLetterErrorCode')}")
# Log to monitoring system or retry with backoff
queue_client.delete_message(message)# Send test event
az eventgrid topic event-subscription test \
--resource-group $RG_NAME \
--topic-name $TOPIC_NAME
# Verify events in dead-letter storage
az storage blob list \
--account-name $DLQ_STORAGE \
--container-name event-grid-deadletter \
--query "[].name"
# Monitor subscription metrics
az monitor metrics list \
--resource "/subscriptions/$SUB_ID/resourceGroups/$RG_NAME/providers/Microsoft.EventGrid/topics/$TOPIC_NAME" \
--metric MatchedEventCount DeliveryFailureCount \
--interval PT5M| Filter | Example | Use Case |
|---|---|---|
| Subject prefix | /documents/raw | Only documents in specific folder |
| Event type | Microsoft.Storage.BlobCreated | Only new uploads, not deletes |
| Advanced filter | data.priority = "high" | Route based on custom event properties |
| Setting | Default | Recommended |
|---|---|---|
| Max delivery attempts | 30 | 30 (exponential backoff to 3600s) |
| Event TTL minutes | 1440 (24h) | 1440 (let Event Grid store for 24h) |
| Dead-letter on first failure | false | true (capture and inspect failures) |
| Pillar | Contribution |
|---|---|
| Reliability | Exponential backoff + dead-letter prevents event loss; retry policy handles transient failures |
| Operational Excellence | Event Grid logs all deliveries; audit trail for compliance |
| Performance Efficiency | Event-driven avoids polling overhead; triggers fire in <5s of event publish |
Storage Blob Data Contributor~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.