| name | azure-connectornamespace-aca-sandbox |
| description | Azure Connector Namespace — ACA sandbox edition. Manage connector namespaces,
connections, and triggers that wire external services (Office 365, Teams, Forms,
SharePoint, OneDrive, GitHub, Azure Blob) into ACA sandbox apps via event-driven
triggers or direct API calls using connection runtime URLs.
Use when:
- Managing connector namespaces and connections for ACA sandboxes
- Creating trigger configs whose callbacks target sandbox endpoints
- Wiring event sources to ACA sandbox callbacks via gatewayConnections
- Building sandbox apps that call connector APIs (send email, post Teams message, etc.)
- Reacting to events from one service and calling another
Triggers: "create trigger", "trigger config", "webhook trigger", "connector namespace",
"connector", "connection", "email trigger", "send email", "onedrive", "sharepoint",
"teams", "teams message", "microsoft forms", "form response", "aca sandbox",
"sandbox group", "container apps sandbox", "notify", "automate", "when", "on new"
|
Azure Connector Namespace — ACA sandbox edition
Manage connectors, connections, and triggers — connect external services
to sandbox apps via direct API calls or event-driven triggers.
Common scenarios
| User request | Pattern | Connectors involved |
|---|
| "Send a Teams message when a form is submitted" | Trigger (Forms) + Direct API (Teams) | microsoftforms, teams |
| "Notify a channel when a file is uploaded" | Trigger (OneDrive/Blob) + Direct API (Teams) | onedriveforbusiness/azureblob, teams |
| "Send an email when a SharePoint list item changes" | Trigger (SharePoint) + Direct API (Office 365) | sharepointonline, office365 |
| "Post to Teams when a new email arrives" | Trigger (Office 365) + Direct API (Teams) | office365, teams |
| "Save form responses to SharePoint" | Trigger (Forms) + Direct API (SharePoint) | microsoftforms, sharepointonline |
Rules (MUST follow)
| Rule | Details |
|---|
| No hallucination | Check references/ for details. Use az rest --help for syntax. |
| No generated notebooks/scripts | Do NOT generate a notebook or standalone script for the user. Walk through interactively. (Reference scripts in scripts/ and labs/ exist for learning.) |
| No MCP configs | Sandbox apps call runtime URL directly via HTTP. If you reach mcp-config create, STOP. |
| No guessing dynamic values | x-ms-dynamic-* → call API, present results, STOP. Never assume a team/channel/folder/site. |
| Execute, don't ask | Gather inputs → execute immediately → report. Never say "Can I run this?" |
| No az extensions | Gateway = az rest. Sandbox = aca CLI. Do NOT use az connectorgateway/sandbox/sandboxgroup. |
Always @$tmpFile | For az rest --body in PowerShell — inline JSON breaks. Bash examples in references/ use inline for brevity (shell quoting works in bash). See gotchas.md. |
| Trigger body schema | Uses metadata + notificationDetails (callbackUrl/body/auth). operationName+parameters at properties root. callbackTarget does NOT exist. See Step 5B template. |
| Handler deploy | Write to local file → aca sandbox fs write. Never inline Python in PowerShell. |
| SSL/stderr | REQUESTS_CA_BUNDLE preferred. verify=False needs disable_warnings(). stderr = trigger failure. See handler-guide.md. |
| Parallel execution | Run independent ops (connections, ACLs, gatewayConnections wiring, dynamic values) as parallel tool calls. |
|
When to STOP and ask the user: Any parameter with dynamic values (teams, channels, folders, sites, lists), choosing integration pattern, OAuth consent. You must NEVER skip this — always fetch the list and present it.
When to EXECUTE immediately: creating gateways/connections/triggers/policies, wiring gatewayConnections, deploying handlers, installing deps.
Step 0: Prerequisites & Azure context
-
Check az account show and aca --version. If missing, see prerequisites.md.
-
Select subscription — list available subscriptions, ask the user to pick:
az account list --query "[].{name:name, id:id, isDefault:isDefault}" -o table
Present the list and ask: "Which subscription do you want to use?"
If the user picks a non-default subscription, set it:
az account set --subscription "{selected_subscription_id}"
Store the subscription ID for all subsequent commands.
-
Select resource group — ask: "Do you have an existing resource group, or should I create one?"
- If existing: list and let user pick:
az group list --query "[].{name:name, location:location}" -o table
- If new: ask for name + location, then create:
az group create --name {rg} --location {location}
Stop and wait for the user's answers before continuing.
Step 1: Understand the scenario
Ask the user:
- "What event do you want to trigger on?" (new email, SharePoint list item, file upload, etc.)
- Map the answer to a connector using this table:
| User says | Connector name | Common triggers |
|---|
| Email, Outlook | office365 | OnNewEmailV3, OnFlaggedEmail |
| SharePoint, list | sharepointonline | OnNewItem, OnUpdatedItem |
| OneDrive, files | onedriveforbusiness | OnNewFile, OnUpdatedFile |
| Teams | teams | OnNewChannelMessage |
| Forms, survey, quiz | microsoftforms | OnFormResponse, OnNewResponse |
| Azure Blob | azureblob | OnNewBlob, OnUpdatedBlob |
- Ask if they already know the trigger operation, or want to discover available ones.
Stop and wait for the user's answer before continuing.
Step 2: Gateway setup
⚡ Parallel batch: Once you know the gateway name, run ALL of these in one parallel call:
- Get gateway info (principalId, tenantId, location)
- List existing connections (names, statuses, runtime URLs)
- Get sandbox group identity (if sandbox already exists)
This avoids sequential round-trips and saves ~2 minutes.
ARM base URL: https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGateways
API version: api-version=2026-05-01-preview
Use the subscription and resource group selected in Step 0.
Ask the user:
- "Do you have an existing connector, or should I create a new one?"
- If existing: ask for the gateway name, then retrieve it (using sub/rg from Step 0):
az rest --method GET \
--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGateways/{gw}?api-version=2026-05-01-preview" \
--query "{name:name, principalId:identity.principalId, tenantId:identity.tenantId}"
- If new: ask for gateway name + location, then create it
immediately with a SystemAssigned managed identity (required for trigger callbacks):
$gwBody = @{ location = "{location}"; identity = @{ type = "SystemAssigned" } } | ConvertTo-Json -Compress
$tmp = New-TemporaryFile; Set-Content $tmp $gwBody
az rest --method PUT `
--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGateways/{gw}?api-version=2026-05-01-preview" `
--body "@$tmp" `
--query "{name:name, principalId:identity.principalId, tenantId:identity.tenantId}"
Remove-Item $tmp
- Always capture
principalId and tenantId — they are needed later for
access policies and InvokePort auth.
- List existing connections:
az rest --method GET \
--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGateways/{gw}/connections?api-version=2026-05-01-preview" \
--query "value[].{name:name, status:properties.statuses[0].status, connector:properties.connectorName}"
Once you have the gateway info, proceed immediately to Step 3.
Step 3: Create connection(s) + authenticate
Create ALL needed connections in parallel, then consent all at once:
# Create connections (parallel tool calls if multiple):
$connBody = @{ properties = @{ connectorName = "office365" }; location = "{location}" } | ConvertTo-Json -Compress
$tmp = New-TemporaryFile; Set-Content $tmp $connBody
az rest --method PUT `
--url "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/connectorGateways/{gw}/connections/o365-conn?api-version=2026-05-01-preview" `
--body "@$tmp"
Remove-Item $tmp
# Repeat for additional connections (onedriveforbusiness, sharepointonline, etc.)
Generate consent links and open in browser. → Exact format: See consent.md
⚠️ Use Start-Process to open links. Body MUST use parameters array with
objectId/tenantId from the connection. Do NOT try other formats or print the URL.
Ask user to authenticate (use ask_user), then verify:
az rest --method GET \
--url ".../{gw}/connections?api-version=2026-05-01-preview" \
--query "value[].{name:name, status:properties.statuses[0].status}"
Step 4: Choose integration pattern
Ask the user:
- A) Direct API calls — call connector operations on demand via
dynamicInvoke
(send email, read list, create file). If deploying to sandbox, also wires the connection to the sandbox group + sandbox via gatewayConnections[].
- B) Event-driven triggers — gateway pushes notifications to sandbox when
events happen. Handler can then use direct API calls for additional actions.
Stop and wait for the user's answer.
- If A → Step 5A
- If B → Step 5B
Step 5A: Direct API calls via dynamicInvoke
→ Full details: direct-api.md | Swagger discovery: swagger-discovery.md | Dynamic values: dynamic-values.md
- Fetch the connector Swagger and pick an operation — see swagger-discovery.md.
- Call
dynamicInvoke on the connection with the resolved method + path
- If parameters have
x-ms-dynamic-* → resolve via dynamicInvoke, show display names to user, store values
If deploying to sandbox: Wire the connection declaratively (sandbox-group gatewayConnections[] PATCH + per-sandbox PUT body referencing the same connection) → gateway-connections.md. The platform proxy injects Bearer auth on every runtime-URL call automatically; the handler makes plain requests.get(...) calls with no auth header.
→ Skip to Final verification checklist.
Step 5B: Event-driven triggers
→ Full trigger setup (Steps 5B–9B): trigger-setup.md | Swagger discovery: swagger-discovery.md | Dynamic values: dynamic-values.md
- Discover trigger operations — fetch the Swagger and filter paths whose operation has
x-ms-trigger set. See swagger-discovery.md.
- If trigger type is
batch (polling): inform user it polls every ~3 minutes by default. Ask if they want a different interval.
- Collect parameters (resolve
x-ms-dynamic-* via Swagger + dynamicInvoke)
- Ask user: sandbox (existing/new) + callback type (ShellCommand / ExecuteCommand / InvokePort)
- Create trigger + access policy + role assignment (run in parallel) — canonical template in trigger-setup.md Step 8B
- Verify trigger state is
Enabled
⚠️ Do NOT use callbackTarget — that field does not exist. Correct schema: metadata + notificationDetails. See trigger-setup.md.
| Target | Callback URL | Notes |
|---|
| ShellCommand | https://management.{region}.azuredevcompute.io/.../executeShellCommand | Auto-resumes sandbox; needs RBAC c24cf47c-... on sandbox group. Regional host required (unregional → 404 GlobalSandboxNotFound). |
| ExecuteCommand | https://management.{region}.azuredevcompute.io/.../executeCommand | Same as above, no shell interpretation. Regional host required. |
| InvokePort | https://{id}--{port}.proxy.azuredevcompute.io/... | Sandbox must be running; needs port auth |
After trigger creation → deploy handler. See handler-guide.md.
Final verification checklist
For Direct API calls (path A):
- ✅ Gateway exists, connection
Connected, connectionRuntimeUrl available
- ✅ Access policies on connection:
gateway-acl (gateway MI) AND sandbox-acl (sandbox-group MI)
- ✅ Sandbox group has SystemAssigned MI (
aca sandboxgroup identity assign --name {sg} --system-assigned if principalId is null)
- ✅ Sandbox-group
properties.gatewayConnections[] includes an entry with this connection's {resourceId, connectionRuntimeUrl, authentication.type=SystemAssignedManagedIdentity} (PATCH; merge-don't-clobber)
- ✅ Each sandbox was created with
gatewayConnections: [{resourceId}] in its data-plane PUT body (the aca CLI doesn't expose --gateway-connection; use az rest data-plane PUT)
- ✅ Test call from sandbox works (no auth header needed — platform proxy injects Bearer)
For Event-driven triggers (path B):
- ✅ Gateway has SystemAssigned identity, connection
Connected
- ✅ Trigger state is
Enabled, gateway-acl exists (gateway MI → connection)
- ✅ RBAC role on sandbox group (ShellCommand) OR port auth (InvokePort)
- ✅ If handler calls runtime URL: also needs
sandbox-acl + sandbox-group gatewayConnections[] entry + per-sandbox gatewayConnections[{resourceId}] (same as path A)
After setup → deploy the handler app. See handler-guide.md.
Quick reference
az rest --method GET --url ".../connectorGateways/{gw}?api-version=2026-05-01-preview"
az rest --method GET --url ".../connectorGateways/{gw}/connections?api-version=2026-05-01-preview"
az rest --method POST --url ".../connectorGateways/{gw}/connections/{conn}/dynamicInvoke?api-version=2026-05-01-preview" --body '{"request":{"method":"GET","path":"/..."}}'
az rest --method GET --url ".../connectorGateways/{gw}/triggerConfigs?api-version=2026-05-01-preview"
az rest --method GET --url ".../connectorGateways/{gw}/triggerConfigs/{name}?api-version=2026-05-01-preview" --query "properties.state"
References