agentleFS
Microsoft AzureKnown publisherAzure/azure-functions-connector-extension/.github/skills/poll-trigger-registration/SKILL.md

poll-trigger-registration

Skill1 starsChanged 37 days agoMITView on GitHub

Register Connector Namespace trigger configs for Azure Functions host-pull Poll delivery. USE WHEN: creating deliveryMode Poll trigger configs, obtaining pollingEndpoints, deriving <Connection>__pollingEndpoint and TriggerConfigName settings, configuring Poll identity access, enabling Poll triggers, or troubleshooting Poll registration. NOT FOR: callback/Webhook notificationDetails (use webhook-trigger-registration), connection creation or OAuth consent (use connection-setup), or extension internals.

The file

We split this skill into the rules it gives an agent

5 rules. About 0 are common, 2 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Ask whether the Function App, Poll binding, and connection access policy are ready.

    line 55
  2. Very specific:

    Do not add notificationDetails, a callback URL, or callback authentication.

    line 127
  3. Distinctive:

    Create the Trigger Config enabled unless the user explicitly chooses disabled because the Function is not ready.

    line 129
  4. Very specific:

    Use the PUT response when it contains properties.pollingEndpoints.

    line 133
  5. Distinctive:

    Never return credentials, bearer tokens, lock tokens, connector payloads, or signed linked-output URLs.

    line 320

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Connector Poll Trigger Registration for Azure Functions

Registers a Connector Namespace Trigger Config with deliveryMode: Poll, returns the service-generated pollingEndpoints, and configures the values required by the Azure Functions Connector extension.

When to Use

  • The Function binding uses DeliveryMode = Poll.
  • The Function host must receive and acknowledge leased Connector events.
  • A Poll Trigger Config must be created through ARM because the current portal and az connector-namespace trigger create command do not expose the Poll delivery contract.
  • The user needs the generated Poll endpoints and ready-to-copy Function app settings.

For Connector Namespace callback delivery, use the webhook-trigger-registration skill.

Prerequisites

  • Azure CLI authenticated with permission to manage the Connector Namespace.
  • An existing connected Connector Namespace connection. Use connection-setup first if needed.
  • A Function App identity for Azure deployments, or a signed-in developer identity for local development.
  • The identity must have a connection-level access policy on the connection referenced by the Trigger Config.

Required Inputs

Collect:

$subscriptionId = "<subscription-id>"
$resourceGroup = "<resource-group>"
$namespaceName = "<connector-namespace-name>"
$triggerConfigName = "<trigger-config-name>"
$connectionName = "<connection-name>"
$connectorName = "<connector-name>"       # e.g. office365
$operationName = "<operation-name>"       # e.g. OnNewEmailV3
$connectionPrefix = "ConnectorNamespace"  # ConnectorTrigger.Connection
$triggerConfigSetting = "OnNewEmailTriggerConfigName"

Connector-specific operation parameters are also required. For example:

$parameters = @(
    @{
        name = "folderPath"
        value = "Inbox"
    }
)

Step 1: Create the Poll Trigger Config

Ask whether the Function App, Poll binding, and connection access policy are ready. Use Enabled by default. If the Function is not ready, ask the user whether to create the Trigger Config as Disabled; do not choose the disabled state without confirmation.

Set the confirmed initial state, then build the ARM resource ID and request body:

$initialState = "Enabled" # Use "Disabled" only when the user confirms.
$apiVersion = "2026-05-01-preview"
$namespaceResourceId = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Web/connectorGateways/$namespaceName"
$triggerConfigResourceId = "$namespaceResourceId/triggerConfigs/$triggerConfigName"

function Set-PollTriggerConfig {
    param(
        [Parameter(Mandatory)]
        [string] $ResourceId,

        [Parameter(Mandatory)]
        [string] $ApiVersion,

        [Parameter(Mandatory)]
        [string] $Body
    )

    $bodyFile = Join-Path $env:TEMP "$([IO.Path]::GetRandomFileName()).json"
    try {
        [IO.File]::WriteAllText(
            $bodyFile,
            $Body,
            [Text.UTF8Encoding]::new($false))

        $response = az rest `
            --method put `
            --uri "$ResourceId?api-version=$ApiVersion" `
            --body "@$bodyFile" `
            -o json
        if ($LASTEXITCODE -ne 0) {
            throw "Failed to create or update the Connector Namespace Poll Trigger Config."
        }

        return $response | ConvertFrom-Json
    }
    finally {
        Remove-Item $bodyFile -ErrorAction SilentlyContinue
    }
}

$triggerProperties = @{
    connectionDetails = @{
        connectionName = $connectionName
        connectorName = $connectorName
    }
    deliveryMode = "Poll"
    description = "Poll delivery - $connectorName $operationName"
    operationName = $operationName
    parameters = $parameters
    state = $initialState
    type = "NotSpecified"
}

$requestBody = @{
    properties = $triggerProperties
} | ConvertTo-Json -Depth 8 -Compress

$triggerConfig = Set-PollTriggerConfig `
    -ResourceId $triggerConfigResourceId `
    -ApiVersion $apiVersion `
    -Body $requestBody

if ($triggerConfig.properties.state -ne $initialState) {
    throw "Connector Namespace Poll Trigger Config was not created in the requested state."
}

Do not add notificationDetails, a callback URL, or callback authentication. Those properties belong to Webhook delivery.

Create the Trigger Config enabled unless the user explicitly chooses disabled because the Function is not ready. Configure the Function settings immediately after retrieving its service-generated endpoints.

Step 2: Retrieve and Share pollingEndpoints

Use the PUT response when it contains properties.pollingEndpoints; otherwise retrieve the resource:

if ($null -eq $triggerConfig.properties.pollingEndpoints) {
    $triggerConfig = az rest `
        --method get `
        --uri "$triggerConfigResourceId?api-version=$apiVersion" `
        -o json | ConvertFrom-Json
}

$pollingEndpoints = $triggerConfig.properties.pollingEndpoints
if ($null -eq $pollingEndpoints -or
    [string]::IsNullOrWhiteSpace($pollingEndpoints.receiveUri)) {
    throw "Connector Namespace did not return properties.pollingEndpoints.receiveUri."
}

$pollingEndpoints | ConvertTo-Json -Depth 4

Share the complete service-generated object with the requesting user:

  • receiveUri
  • acknowledgeUri
  • hasMessagesUri
  • approximateQueueDepthUri

These values are application configuration. Show them directly to the user, but do not commit them, copy them into issue reports, or include them in general logs or summaries.

Step 3: Derive the Function Settings

Derive the connection setting from pollingEndpoints.receiveUri using these two forms:

Receive URIConnection pollingEndpoint
https://<connector-namespace-host>/api/triggerconfigs/<name>/receivehttps://<connector-namespace-host>
https://<host>/api/connectorGateways/<id>/triggerconfigs/<name>/receivehttps://<host>/api/connectorGateways/<id>

Supply the Trigger Config name separately. The extension constructs all operation paths and supplies maxEvents on Receive requests. Preserve the service-provided authority; do not configure a query string or a standalone /api base.

Both connection endpoint forms accept one optional trailing slash; the extension removes it before constructing operation paths.

$receiveUri = [Uri]$pollingEndpoints.receiveUri
$pathMatch = [regex]::Match(
    $receiveUri.AbsolutePath,
    "^(?<base>/api(?:/connectorGateways/[^/]+)?)/triggerConfigs/[^/]+/receive$",
    [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)

if (-not $pathMatch.Success) {
    throw "The service-generated receiveUri does not match the supported Connector Namespace Poll path."
}

$endpointBuilder = [UriBuilder]$receiveUri
$endpointBuilder.Path = if ($pathMatch.Groups["base"].Value -eq "/api") {
    ""
} else {
    $pathMatch.Groups["base"].Value
}
$endpointBuilder.Query = ""
$pollingEndpoint = $endpointBuilder.Uri.AbsoluteUri

Write-Output ""
Write-Output "Function settings:"
Write-Output "${connectionPrefix}__pollingEndpoint=$pollingEndpoint"
Write-Output "$triggerConfigSetting=$triggerConfigName"

Preserve the service-generated authority and gateway identifier exactly. Do not derive them from the Connector Namespace resource ID or copy operation query parameters into the connection setting.

The resulting binding is:

[ConnectorTrigger(
    DeliveryMode = ConnectorTriggerDeliveryMode.Poll,
    Connection = "ConnectorNamespace",
    TriggerConfigName = "%OnNewEmailTriggerConfigName%")]

For Python 3.13+ with azure-functions>=2.4.0b1, use the native decorator:

from typing import List

@app.connector_trigger(
    arg_name="payloads",
    delivery_mode=func.DeliveryMode.POLL,
    connection="ConnectorNamespace",
    trigger_config_name="%OnNewEmailTriggerConfigName%",
    cardinality=func.Cardinality.MANY,
    max_batch_size=4,
)
def on_new_email_poll(payloads: List[str]) -> None:
    ...

Here app is a func.FunctionApp() and func is azure.functions. Use typing.List[str]: the 2.4.0b1 SDK type check does not accept the built-in list[str] annotation. Each list element is one Poll event's JSON, not one email from an event's body. For single-event delivery, use func.Cardinality.ONE, a str parameter, and max_batch_size=1. Omit max_concurrent_calls for batched delivery.

Step 4: Configure Identity and Access

Connector Namespace identity

The Connector Namespace managed identity polls the connector operation. Grant that identity its own connection-level access policy:

$namespacePrincipalId = az resource show `
    --ids $namespaceResourceId `
    --query "identity.principalId" `
    -o tsv
$tenantId = az account show --query "tenantId" -o tsv

if ([string]::IsNullOrWhiteSpace($namespacePrincipalId)) {
    throw "The Connector Namespace does not have a system-assigned managed identity."
}

az connector-namespace connection access-policy create `
    -g $resourceGroup `
    --namespace $namespaceName `
    --connection-name $connectionName `
    -n namespace-trigger-runtime `
    --principal "identity.object-id=$namespacePrincipalId identity.tenant-id=$tenantId type=ActiveDirectory"
if ($LASTEXITCODE -ne 0) {
    throw "Failed to grant the Connector Namespace identity access to the connection."
}

This policy authorizes Connector Namespace to run the connector trigger. It is separate from the policy for the identity that calls the Poll runtime endpoints.

Function or developer identity

For Azure, configure managed identity:

az functionapp config appsettings set `
    -g $resourceGroup `
    -n "<function-app-name>" `
    --settings `
        "${connectionPrefix}__pollingEndpoint=$pollingEndpoint" `
        "${connectionPrefix}__credential=managedidentity" `
        "$triggerConfigSetting=$triggerConfigName"

For local development, omit ${connectionPrefix}__credential; the extension uses the standard Functions developer credential behavior.

Grant the selected identity an access policy on the connection referenced by the Trigger Config. There is no namespace-level access policy.

Step 5: Enable a Trigger Config Created Disabled

Skip this step when the Trigger Config was created enabled. If the user chose Disabled because the Function was not ready, confirm that the Function settings and both connection access policies are now complete, then enable it:

if ($triggerConfig.properties.state -eq "Disabled") {
    $triggerProperties.state = "Enabled"
    $requestBody = @{
        properties = $triggerProperties
    } | ConvertTo-Json -Depth 8 -Compress

    $triggerConfig = Set-PollTriggerConfig `
        -ResourceId $triggerConfigResourceId `
        -ApiVersion $apiVersion `
        -Body $requestBody

    if ($triggerConfig.properties.state -ne "Enabled") {
        throw "Connector Namespace Poll Trigger Config was not enabled."
    }
}

Required Final Output

Always return:

  1. The Trigger Config resource ID and current state. If it remains disabled, explain that the Function will not receive events until it is enabled.
  2. The complete properties.pollingEndpoints object.
  3. The derived gateway-level setting:

    <Connection>__pollingEndpoint=<gateway-level-base>
  4. The binding-level setting:

    <TriggerConfigSetting>=<trigger-config-name>
  5. Whether the Connector Namespace and Function/developer connection-level access policies and Function app settings were configured.

Never return credentials, bearer tokens, lock tokens, connector payloads, or signed linked-output URLs.

Troubleshooting

SymptomCauseFix
Poll binding reports missing pollingEndpointThe named connection section is incompleteConfigure <Connection>__pollingEndpoint with the derived gateway-level base
Poll binding reports missing TriggerConfigNameBinding metadata or its app-setting expression is missingSet TriggerConfigName and ensure the referenced app setting resolves
Runtime returns 403 ForbiddenThe caller is authenticated but lacks connection authorizationAdd a connection-level access policy for the selected identity
Runtime route returns 404 or 410Stale endpoint or Trigger Config nameRetrieve the current pollingEndpoints and verify the derived settings
No events arriveTrigger Config is disabled or the connector operation parameters are wrongVerify properties.state, operation name, and connector-specific parameters

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.