trigger-registration
Skill3 starsChanged 15 days agoMITView on GitHub
Register Connector Namespace trigger configs for SDK-supported connectors. USE WHEN: setting up polling triggers (e.g., OnNewEmail, OnNewFile, OnUpdatedFile) that call back to an Azure Function when events occur, creating a .NET Function App project with ConnectorTrigger, or wiring post-deploy trigger config scripts. Covers function app scaffolding, trigger config creation, callback URL wiring, parameter discovery, and binary vs metadata payload handling. NOT FOR: connection setup (use connection-setup skill).
2 other projects use a version of this, 2 of them edited.
Adopted by
Most recently taken up by
- Azure/azure-functions-python-extensionsedited, first seen Oct 29, 2026
- Azure/connectors-python-sdkedited, first seen Oct 27, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 2
- Azure/azure-functions-python-extensions★ 714% same
- Azure/connectors-python-sdk★ 019% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository2 other files it gives its agents.
- .github/copilot-instructions.mdCopilot instructions
- connection-setupSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 70
If the connector generates a *Triggers.Operations dictionary, that dictionary only maps metadata triggers (those with typed payloads).
- Very specific: line 119
Use the [ConnectorTrigger] attribute with SDK typed payloads for POCO binding.
- Distinctive: line 288
Check function app logs:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Connector Namespace Trigger Registration
Registers polling trigger configs on a Connector Namespace so that connector events (new email, new file, etc.) call back to your Azure Function endpoint. Also covers scaffolding a .NET Function App project with the connector extension packages.
When to Use
- Developer needs a connector trigger (e.g., "when a new file is created in OneDrive")
- Developer has an existing Connector Namespace connection (use the
connection-setupskill first if not) - Developer needs to wire up the callback URL from a deployed Azure Function
- Developer needs to understand binary vs metadata trigger payload shapes
Prerequisites
- Azure CLI installed and authenticated (
az login) - Connector Namespace with a connected connector (see
connection-setupskill) - The Connector Namespace must have a system-assigned managed identity enabled (required for trigger callback authentication)
- Deployed Azure Function App with a connector trigger function
- Supported regions for Connector Namespace:
brazilsouth,centraluseuap,eastus2euap,centralusstage,eastusstage. Only the Connector Namespacelocationmust be in a supported region; the Function App can be in any region. - For .NET: the Function App project must reference:
Microsoft.Azure.Functions.Worker.Extensions.Connector— provides the[ConnectorTrigger]attributeAzure.Connectors.Sdk— provides typed connector clients and trigger payload types
Key Concepts
Trigger Config vs Connection
Connections (managed by the connection-setup skill) authenticate your app to the connector API. Trigger configs tell the Connector Namespace to poll the connector for events and POST callbacks to your function when events occur.
Connector Namespace
├── connections/
│ └── onedrive-test ← auth + runtime URL (connection-setup skill)
└── triggerConfigs/
└── onedrive-newfile ← poll + callback config (THIS skill)Binary vs Metadata Triggers
Some connectors offer two variants of the same trigger:
| Variant | Example | Payload Shape | Body Field |
| File content (binary) | OnNewFileV2 | {"body":"<base64-string>"} | String — base64-encoded file bytes |
| Properties only (metadata) | OnNewFilesV2 | {"body":{"value":[{...}]}} | Object — array of typed metadata items |
Critical: Both variants arrive with Content-Type: application/json. You cannot use content-type to distinguish them. Instead, parse the JSON and inspect whether body is a string or an object.
Identifying binary triggers in the SDK
In the generated *TriggerOperations class, binary triggers lack a Payload type: annotation in their XML doc comment, while metadata triggers reference their typed payload class:
// Binary — no payload type annotation
/// <summary>When a file is created.</summary>
public const string OnNewFile = "OnNewFileV2";
// Metadata — has payload type annotation
/// <summary>
/// When a file is created (properties only).
/// Payload type: <see cref="OnedriveforbusinessOnNewFilesTriggerPayload"/>.
/// </summary>
public const string OnNewFiles = "OnNewFilesV2";If the connector generates a *Triggers.Operations dictionary, that dictionary only maps metadata triggers (those with typed payloads). If an operation name is not in the dictionary, it is a binary trigger.
Some connectors may not generate a *Triggers registry at all. When *Triggers.Operations is unavailable, check the XML doc comment on the *TriggerOperations constant: a Payload type: annotation indicates a metadata trigger, while no annotation indicates a binary trigger.
.NET Function App with Connector Extension
Scaffolding a New Project
There is no ConnectorTrigger template yet. Use azd with an HTTP trigger template and replace the trigger:
Initialize with the Azure Functions .NET quickstart:
azd init -t functions-quickstart-dotnet-azd- Replace the HTTP trigger with a
[ConnectorTrigger]function. Delete any sample HTTP functions and create your trigger function (see example below). Add packages to the Function App
.csproj:<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Connector" Version="0.1.0-alpha" />For SDK typed payloads, also add:
<PackageReference Include="Azure.Connectors.Sdk" Version="*" />Note: If
Azure.Connectors.Sdkis not yet published on NuGet, use a project reference to the local SDK repo instead:<ProjectReference Include="..\..\Connectors-NET-SDK\src\Azure.Connectors.Sdk\Azure.Connectors.Sdk.csproj" />Build and deploy:
azd up
Packages
Microsoft.Azure.Functions.Worker.Extensions.Connector— provides the[ConnectorTrigger]attribute and POCO converter. See azure-functions-connector-extension.Azure.Connectors.Sdk— typed connector clients and trigger payload types (e.g.,Office365OnNewEmailTriggerPayload,TeamsClient)
Example: ConnectorTrigger Function
Use the [ConnectorTrigger] attribute with SDK typed payloads for POCO binding. Payload types are in the Azure.Connectors.Sdk.<Connector> namespace:
using Azure.Connectors.Sdk.Office365;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
public class EmailTrigger(ILogger<EmailTrigger> logger)
{
[Function("OnNewEmailReceived")]
public void OnNewEmailReceived(
[ConnectorTrigger] Office365OnNewEmailTriggerPayload payload)
{
var emails = payload.Body?.Value ?? [];
foreach (var email in emails)
{
logger.LogInformation("Subject: {Subject}, From: {From}", email.Subject, email.From);
}
}
}The connector extension registers a webhook endpoint on the Function App at:
POST /runtime/webhooks/connector?functionName={FunctionName}&code={connector_extension_key}The connector_extension system key is auto-generated when the extension loads. Use this URL as the callback when creating trigger configs (see Step 1 below).
Procedure
Step 1: Get the Callback URL
The connector extension exposes a webhook endpoint on the Function App. Build the callback URL using the connector_extension system key:
$resourceGroup = "<resource-group>"
$functionAppName = "<function-app-name>"
$functionName = "<connector-trigger-function-name>"
$connectorExtensionKey = az functionapp keys list -g $resourceGroup -n $functionAppName --query "systemKeys.connector_extension" -o tsv
$callbackUrl = "https://$functionAppName.azurewebsites.net/runtime/webhooks/connector?functionName=$functionName&code=$connectorExtensionKey"Important: The
functionNamequery parameter must exactly match the[Function("...")]attribute name in your code. A mismatch means the connector extension cannot route the callback to your function.
Step 2: Get Trigger Parameters
Each trigger operation requires specific parameters. Find them in the SDK's generated *TriggerParameters class:
// Example: OneDrive OnNewFileV2 parameters
OnedriveforbusinessTriggerParameters.OnNewFile.FolderId // Required — folder to watch
OnedriveforbusinessTriggerParameters.OnNewFile.IncludeSubfolders // Optional, default: false
OnedriveforbusinessTriggerParameters.OnNewFile.InferContentType // Optional, default: trueFor folder IDs, use the connector's list operations to discover them:
Note: Listing folders requires a data-plane call to the connection runtime URL. If you skipped access policies in the
connection-setupskill (trigger-only flow), you must first add a local-dev access policy (connection-setupStep 5) to avoid 403 errors.
$runtimeUrl = "<connection-runtime-url>" # from connection-setup skill Step 4
az rest --method GET `
--uri "$runtimeUrl/datasets/default/folders" `
--resource "https://apihub.azure.com" -o jsonStep 3: Create Trigger Config
$subscriptionId = "<subscription-id>"
$resourceGroup = "<resource-group>"
$namespaceName = "<namespace-name>"
$nsId = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Web/connectorGateways/$namespaceName"
$triggerName = "<trigger-config-name>" # e.g., "onedrive-newfile-binary"
$connectionName = "<connection-name>" # e.g., "onedrive-test"
$connectorName = "<connector-name>" # e.g., "onedriveforbusiness"
$operationName = "<operation-name>" # e.g., "OnNewFileV2"Build and send the PUT request. Use Invoke-WebRequest (not az rest) because az rest silently swallows error responses from this API:
$token = az account get-access-token `
--resource "https://management.core.windows.net/" `
--query "accessToken" -o tsv
$body = @{
properties = @{
operationName = $operationName
connectionDetails = @{
connectorName = $connectorName
connectionName = $connectionName
}
notificationDetails = @{
callbackUrl = $callbackUrl
httpMethod = "Post"
}
parameters = @(
@{ name = "folderId"; value = "<folder-id-from-step-2>" }
@{ name = "includeSubfolders"; value = "false" }
)
}
} | ConvertTo-Json -Depth 4
$uri = "https://management.azure.com/$($nsId.TrimStart('/'))/triggerConfigs/${triggerName}?api-version=2026-05-01-preview"
try {
$response = Invoke-WebRequest -Uri $uri -Method PUT -Body $body `
-ContentType "application/json" `
-Headers @{ Authorization = "Bearer $token" }
Write-Output "Status: $($response.StatusCode)"
} catch {
Write-Output "Error: $($_.Exception.Response.StatusCode) $($_.Exception.Response.ReasonPhrase)"
$_.ErrorDetails.Message
}Alternative: Using az rest
$bodyFile = [System.IO.Path]::GetTempFileName()
$body | Out-File -FilePath $bodyFile -Encoding utf8
az rest --method PUT --url $uri --body "@$bodyFile" --headers "Content-Type=application/json"
Remove-Item $bodyFile -ErrorAction SilentlyContinueExpected: HTTP 201 Created.
Step 4: Verify Trigger Config
az rest --method GET `
--uri "https://management.azure.com/$($nsId.TrimStart('/'))/triggerConfigs/${triggerName}?api-version=2026-05-01-preview" `
--query "properties.{operation:operationName, state:state, hasCallback:notificationDetails.callbackUrl!=null}" `
-o tableExpected: state = Enabled, hasCallback = True.
Step 5: List All Trigger Configs
az rest --method GET `
--uri "https://management.azure.com/$($nsId.TrimStart('/'))/triggerConfigs?api-version=2026-05-01-preview" `
--query "value[].{name:name, operation:properties.operationName, state:properties.state}" `
-o tableStep 6: Fire the Trigger
Upload or create content in the watched location to trigger the callback:
# Example: upload a file to OneDrive to fire OnNewFileV2
# Set $baseUrl to your deployed Function App, e.g.:
# $baseUrl = "https://<function-app-name>.azurewebsites.net/api"
$uploadBody = '{"folderPath":"/Documents","fileName":"trigger-test.txt","content":"Hello from trigger test"}'
Invoke-RestMethod -Uri "$baseUrl/onedrive/upload?code=$functionKey" `
-Method POST -Body $uploadBody -ContentType "application/json"The Connector Namespace polls the connector every 1-5 minutes. After polling detects the new content, it POSTs the trigger payload to your callback URL.
Step 7: Verify Callback Received
Check function app logs:
az webapp log download -g $resourceGroup -n $functionAppName --log-file "$env:TEMP/func-logs.zip"
Expand-Archive -Path "$env:TEMP/func-logs.zip" -DestinationPath "$env:TEMP/func-logs" -Force
Get-ChildItem "$env:TEMP/func-logs" -Recurse -Filter "*.log" |
Sort-Object LastWriteTime -Descending |
Select-Object -First 3 |
ForEach-Object { Select-String -Path $_.FullName -Pattern "TriggerCallback" }API Schema Reference
TriggerConfig PUT Body
{
"properties": {
"operationName": "OnNewFileV2",
"connectionDetails": {
"connectorName": "onedriveforbusiness",
"connectionName": "onedrive-test"
},
"notificationDetails": {
"callbackUrl": "https://my-func.azurewebsites.net/runtime/webhooks/connector?functionName=OnNewFile&code=<connector-extension-key>",
"httpMethod": "Post"
},
"parameters": [
{ "name": "folderId", "value": "<folder-id>" },
{ "name": "includeSubfolders", "value": "false" }
]
}
}Property Names (Validated)
| Property | Notes |
properties.connectionDetails | Not connectionName at top level |
properties.connectionDetails.connectorName | Required — the API connector name |
properties.connectionDetails.connectionName | Required — the connection resource name |
properties.notificationDetails.callbackUrl | Missing = trigger has no target — trigger provisions but never calls back |
properties.notificationDetails.httpMethod | "Post" |
parameters[].name | Not parameterName |
parameters[].value | String value |
Common Errors
| Error | Cause | Fix |
Could not find member 'connectionName' | Used connectionName instead of connectionDetails | Use connectionDetails with nested connectorName + connectionName |
Could not find member 'callbackUrl' | Put callbackUrl at properties level | Wrap in notificationDetails |
Could not find member 'parameterName' | Used parameterName in parameter array | Use name |
Cannot deserialize... into ConnectorGatewayOperationsParameter[] | Parameters as object, not array | Use [{"name":"...","value":"..."}] array |
missing required property 'folderId' | Required trigger parameter not provided | Add to parameters array |
| Trigger provisions but never fires callback | Missing notificationDetails or empty notificationDetails.callbackUrl | Add notificationDetails with a non-empty callbackUrl and httpMethod |
az rest PUT returns no output/error | az rest swallows non-2xx responses silently | Use Invoke-WebRequest instead for PUT operations |
Handling Trigger Payloads in Code
Binary Content Triggers (e.g., OnNewFileV2)
using var document = JsonDocument.Parse(body);
var root = document.RootElement;
if (root.TryGetProperty("body", out var bodyElement) &&
bodyElement.ValueKind == JsonValueKind.String)
{
// Binary trigger — body is base64-encoded file content.
// NOTE: The base64 string may be wrapped in extra quotes
// from the Logic Apps expression engine. Strip them.
var base64Content = bodyElement.GetString()?.Trim('"') ?? string.Empty;
if (!string.IsNullOrWhiteSpace(base64Content))
{
var maximumDecodedLength = (base64Content.Length / 4) * 3;
var fileBytesBuffer = new byte[maximumDecodedLength];
if (Convert.TryFromBase64String(base64Content, fileBytesBuffer, out var bytesWritten))
{
var fileBytes = fileBytesBuffer.AsSpan(0, bytesWritten).ToArray();
// fileBytes contains the actual file content
}
else
{
// Invalid base64 payload — handle gracefully
}
}
}Metadata Triggers (e.g., OnNewFilesV2)
// Callback JSON shape: {"body":{"value":[{...BlobMetadata...}]}}
// Deserialize using the SDK's typed trigger payload class.
var payload = JsonSerializer.Deserialize<OnedriveforbusinessOnNewFilesTriggerPayload>(
body, jsonOptions);
var files = payload?.Body?.Value;Detecting the Variant at Runtime
using var document = JsonDocument.Parse(body);
if (document.RootElement.TryGetProperty("body", out var bodyElement))
{
if (bodyElement.ValueKind == JsonValueKind.String)
{
// Binary content trigger (OnNewFileV2, OnUpdatedFileV2)
}
else if (bodyElement.ValueKind == JsonValueKind.Object)
{
// Metadata trigger (OnNewFilesV2, OnUpdatedFilesV2)
}
}Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

