APIM пры агентным вызовах Foundry з выкарыстоўваннем модэлі RBAC з мінімальнымі правамі.
Модэлі фронт-энду, якія выкарыстоўваюць API Management, кераванне ідэнтычнасцю, спецыяльныя ролі на плане дадзэнняў і бэкенды Function App.
Што мы створаем
AI Foundry можа разміщваць многа сем’і модэляў. Стварэнне агентаў на ўсім гэтым становіцца цікавым — але і складным — калі кожны модэль мае разныя способы аутентыкаціі і калі дапэўнаюць правіла PII/PCI. Azure API Management (APIM) паўсаблівае правыя доступу з мінімумам прывілеў, ствараючы адну єдыную точку входу.
Частка 1 — Фундамент
Забезпечыце ресурсы Foundry/OpenAI, Function App, які будзе вызываць модэляў, а таксама APIM, які будзе кераваць цым функциям. Заздалегідь выберыце рэгіоны і прыватную сетевую структуру.
Частка 2 — Размешчэнне модэляў
Разместіце тыя чат-модэляў, якія вам действительна патрэбны. Запісвайце назвы размешчэння окрема ад назв базовых модэляў.
ЧАСТКА 2: Індывідуальныя правыя доступу з мінімумам прывілеў
OpenAI — толькі даполнення чату
Індывідуальныя ролі, якія дазволяюць толькі тые дзеяння з дадзеннямі, якія патрэбны вашай функциі, є кращымі за шырокія назначэння ролей Cognitive Services Contributor.
Anthropic — ролі, які включаюць вялася дзеяння з дадзенням, можа не падржаць
Дзеянне дэякіх трэціх-сторонняых модэляў выклікае патрэбу ў дадацьных дзеяннях; пераканайцеся, выкарыстоўваючы тэкст памилкі неудачнага вызову, а потым выправьце ролю — а не наадворс.
RG="rg-foundry-func-demo"
LOCATION="eastus2"
UMI_NAME="umi-foundry-func"
FOUNDRY_NAME="foundry-func-demo"
STORAGE_NAME="stfoundryfuncdemo"
FUNC_NAME="func-foundry-py-$RANDOM"
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
az group create --name $RG --location $LOCATION
az identity create --name $UMI_NAME --resource-group $RG
UMI_CLIENT_ID=$(az identity show --name $UMI_NAME --resource-group $RG --query clientId -o tsv)
UMI_PRINCIPAL_ID=$(az identity show --name $UMI_NAME --resource-group $RG --query principalId -o tsv)
UMI_RESOURCE_ID=$(az identity show --name $UMI_NAME --resource-group $RG --query id -o tsv)
az cognitiveservices account create \
--name $FOUNDRY_NAME \
--resource-group $RG \
--location $LOCATION \
--kind AIServices \
--sku S0 \
--custom-domain $FOUNDRY_NAME \
--yes
FOUNDRY_ENDPOINT=$(az cognitiveservices account show \
--name $FOUNDRY_NAME --resource-group $RG \
--query properties.endpoint -o tsv)
FOUNDRY_ID=$(az cognitiveservices account show \
--name $FOUNDRY_NAME --resource-group $RG --query id -o tsv)
az cognitiveservices account deployment create \
--name $FOUNDRY_NAME \
--resource-group $RG \
--deployment-name gpt-5-mini \
--model-name gpt-5-mini \
--model-version "2025-08-07" \
--model-format OpenAI \
--sku-name GlobalStandard \
--sku-capacity 10
{
"etag": "\"c39e7d0e-7c32-48a2-ba62-8a897265efbb\"",
"id": "/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/resourceGroups/rg-foundry-func-demo/providers/Microsoft.CognitiveServices/accounts/foundry-func-demo-01/deployments/gpt-5-mini",
"name": "gpt-5-mini",
"properties": {
"callRateLimit": null,
"capabilities": {
"agentsV2": "true",
"area": "US",
"assistants": "true",
"chatCompletion": "true",
"responses": "true"
},
"capacitySettings": null,
"currentCapacity": 10,
"deploymentState": "Running",
"dynamicThrottlingEnabled": null,
"model": {
"callRateLimit": null,
"format": "OpenAI",
"name": "gpt-5-mini",
"publisher": null,
"source": null,
"sourceAccount": null,
"version": "2025-08-07"
},
"parentDeploymentName": null,
"provisioningState": "Succeeded",
"raiPolicyName": "Microsoft.DefaultV2",
"rateLimits": [
{
"count": 10.0,
"dynamicThrottlingEnabled": null,
"key": "request",
"matchPatterns": null,
"minCount": null,
"renewalPeriod": 60.0
},
{
"count": 10000.0,
"dynamicThrottlingEnabled": null,
"key": "token",
"matchPatterns": null,
"minCount": null,
"renewalPeriod": 60.0
}
],
"routing": null,
"scaleSettings": null,
"serviceTier": null,
"spilloverDeploymentName": null,
"versionUpgradeOption": "OnceNewDefaultVersionAvailable"
},
"resourceGroup": "rg-foundry-func-demo",
"sku": {
"capacity": 10,
"family": null,
"name": "GlobalStandard",
"size": null,
"tier": null
},
"systemData": {
"createdAt": "2026-07-05T18:03:12.346795+00:00",
"createdBy": "krishnan.sriram@hotmail.com",
"createdByType": "User",
"lastModifiedAt": "2026-07-05T18:03:12.346795+00:00",
"lastModifiedBy": "krishnan.sriram@hotmail.com",
"lastModifiedByType": "User"
},
"tags": null,
"type": "Microsoft.CognitiveServices/accounts/deployments"
}
FOUNDRY_ID=$(az cognitiveservices account show \
--name $FOUNDRY_NAME --resource-group $RG --query id -o tsv)
az resource create \
--id "$FOUNDRY_ID/deployments/claude-opus-4-6" \
--api-version 2025-10-01-preview \
--is-full-object \
--properties '{
"location": "eastus2",
"properties": {
"model": {
"format": "Anthropic",
"name": "claude-opus-4-6",
"version": "1"
},
"modelProviderData": {
"organizationName": "SRK Tech",
"countryCode": "US",
"industry": "technology"
}
},
"sku": {
"name": "GlobalStandard",
"capacity": 10
}
}'
# execution Results
{
"etag": "\"a5b65a53-a65a-494b-9059-b16dc700b743\"",
"extendedLocation": null,
"id": "/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/resourceGroups/rg-foundry-func-demo/providers/Microsoft.CognitiveServices/accounts/foundry-func-demo-01/deployments/claude-opus-4-6",
"identity": null,
"kind": null,
"location": null,
"managedBy": null,
"name": "claude-opus-4-6",
"plan": null,
"properties": {
"capabilities": {
"agentsV2": "true",
"chatCompletion": "true"
},
"currentCapacity": 10,
"deploymentState": "Running",
"model": {
"format": "Anthropic",
"name": "claude-opus-4-6",
"version": "1"
},
"modelProviderData": {
"countryCode": "US",
"industry": "technology",
"organizationName": "SRK Tech"
},
"provisioningState": "Succeeded",
"raiPolicyName": "Microsoft.DefaultV2",
"rateLimits": [
{
"count": 10,
"key": "request",
"renewalPeriod": 60
},
{
"count": 10000,
"key": "token",
"renewalPeriod": 60
}
],
"versionUpgradeOption": "OnceNewDefaultVersionAvailable"
},
"resourceGroup": "rg-foundry-func-demo",
"sku": {
"capacity": 10,
"family": null,
"model": null,
"name": "GlobalStandard",
"size": null,
"tier": null
},
"systemData": {
"createdAt": "2026-07-05T18:06:43.6897129Z",
"createdBy": "krishnan.sriram@hotmail.com",
"createdByType": "User",
"lastModifiedAt": "2026-07-05T18:06:43.6897129Z",
"lastModifiedBy": "krishnan.sriram@hotmail.com",
"lastModifiedByType": "User"
},
"tags": null,
"type": "Microsoft.CognitiveServices/accounts/deployments"
}
az cognitiveservices account deployment list \
--name $FOUNDRY_NAME --resource-group $RG -o table
Name ResourceGroup
--------------- --------------------
gpt-5-mini rg-foundry-func-demo
claude-opus-4-6 rg-foundry-func-demo
cat > /tmp/foundry-openai-role.json << EOF
{
"Name": "Foundry OpenAI Chat Inference User",
"IsCustom": true,
"Description": "Minimal data-plane access to call chat completions on a Microsoft Foundry OpenAI deployment.",
"Actions": [],
"DataActions": [
"Microsoft.CognitiveServices/accounts/OpenAI/deployments/chat/completions/action"
],
"AssignableScopes": ["/subscriptions/$SUBSCRIPTION_ID"]
}
EOF
az role definition create --role-definition /tmp/foundry-openai-role.json
# Execution results
{
"assignableScopes": [
"/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe"
],
"createdBy": null,
"createdOn": "2026-07-05T18:22:39.111105+00:00",
"description": "Minimal data-plane access to call chat completions on a Microsoft Foundry OpenAI deployment.",
"id": "/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/providers/Microsoft.Authorization/roleDefinitions/c7035712-c66d-482d-9fd5-0fc116a2d9f4",
"name": "c7035712-c66d-482d-9fd5-0fc116a2d9f4",
"permissions": [
{
"actions": [],
"condition": null,
"conditionVersion": null,
"dataActions": [
"Microsoft.CognitiveServices/accounts/OpenAI/deployments/chat/completions/action"
],
"notActions": [],
"notDataActions": []
}
],
"roleName": "Foundry OpenAI Chat Inference User",
"roleType": "CustomRole",
"type": "Microsoft.Authorization/roleDefinitions",
"updatedBy": "28567f42-a049-464e-9211-8f1b270cdf6a",
"updatedOn": "2026-07-05T18:22:39.111105+00:00"
}
az role assignment create \
--assignee-object-id $UMI_PRINCIPAL_ID \
--assignee-principal-type ServicePrincipal \
--role "Foundry OpenAI Chat Inference User" \
--scope $FOUNDRY_ID
# Execution results
{
"condition": null,
"conditionVersion": null,
"createdBy": null,
"createdOn": "2026-07-05T18:23:42.642379+00:00",
"delegatedManagedIdentityResourceId": null,
"description": null,
"id": "/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/resourceGroups/rg-foundry-func-demo/providers/Microsoft.CognitiveServices/accounts/foundry-func-demo-01/providers/Microsoft.Authorization/roleAssignments/580a3b61-aaad-456e-9b3e-6ced977dd378",
"name": "580a3b61-aaad-456e-9b3e-6ced977dd378",
"principalId": "a114ced5-b53e-4c42-8949-bddd053610cc",
"principalType": "ServicePrincipal",
"resourceGroup": "rg-foundry-func-demo",
"roleDefinitionId": "/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/providers/Microsoft.Authorization/roleDefinitions/c7035712-c66d-482d-9fd5-0fc116a2d9f4",
"scope": "/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/resourceGroups/rg-foundry-func-demo/providers/Microsoft.CognitiveServices/accounts/foundry-func-demo-01",
"type": "Microsoft.Authorization/roleAssignments",
"updatedBy": "28567f42-a049-464e-9211-8f1b270cdf6a",
"updatedOn": "2026-07-05T18:23:42.913375+00:00"
}
cat > /tmp/foundry-anthropic-role.json << EOF
{
"Name": "Foundry Anthropic Inference User",
"IsCustom": true,
"Description": "Minimal data-plane access to invoke Claude models on a Microsoft Foundry AIServices resource.",
"Actions": [],
"DataActions": [
"Microsoft.CognitiveServices/accounts/AIServices/providers/action",
"Microsoft.CognitiveServices/accounts/OpenAI/*/read"
],
"AssignableScopes": ["/subscriptions/$SUBSCRIPTION_ID"]
}
EOF
az role definition create --role-definition /tmp/foundry-anthropic-role.json
# Execution results
{
"assignableScopes": [
"/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe"
],
"createdBy": null,
"createdOn": "2026-07-05T18:26:14.247654+00:00",
"description": "Minimal data-plane access to invoke Claude models on a Microsoft Foundry AIServices resource.",
"id": "/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/providers/Microsoft.Authorization/roleDefinitions/323e0475-0098-4161-b03d-69bce7452c9c",
"name": "323e0475-0098-4161-b03d-69bce7452c9c",
"permissions": [
{
"actions": [],
"condition": null,
"conditionVersion": null,
"dataActions": [
"Microsoft.CognitiveServices/accounts/AIServices/providers/action",
"Microsoft.CognitiveServices/accounts/OpenAI/*/read"
],
"notActions": [],
"notDataActions": []
}
],
"roleName": "Foundry Anthropic Inference User",
"roleType": "CustomRole",
"type": "Microsoft.Authorization/roleDefinitions",
"updatedBy": "28567f42-a049-464e-9211-8f1b270cdf6a",
"updatedOn": "2026-07-05T18:26:14.247654+00:00"
}
az role assignment create \
--assignee-object-id $UMI_PRINCIPAL_ID \
--assignee-principal-type ServicePrincipal \
--role "Foundry Anthropic Inference User" \
--scope $FOUNDRY_ID
# Execution Results
{
"condition": null,
"conditionVersion": null,
"createdBy": null,
"createdOn": "2026-07-05T18:28:12.789555+00:00",
"delegatedManagedIdentityResourceId": null,
"description": null,
"id": "/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/resourceGroups/rg-foundry-func-demo/providers/Microsoft.CognitiveServices/accounts/foundry-func-demo-01/providers/Microsoft.Authorization/roleAssignments/18e509dc-b539-49d8-a2e6-65a12415e206",
"name": "18e509dc-b539-49d8-a2e6-65a12415e206",
"principalId": "a114ced5-b53e-4c42-8949-bddd053610cc",
"principalType": "ServicePrincipal",
"resourceGroup": "rg-foundry-func-demo",
"roleDefinitionId": "/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/providers/Microsoft.Authorization/roleDefinitions/323e0475-0098-4161-b03d-69bce7452c9c",
"scope": "/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/resourceGroups/rg-foundry-func-demo/providers/Microsoft.CognitiveServices/accounts/foundry-func-demo-01",
"type": "Microsoft.Authorization/roleAssignments",
"updatedBy": "28567f42-a049-464e-9211-8f1b270cdf6a",
"updatedOn": "2026-07-05T18:28:13.050559+00:00"
}
az storage account create \
--name $STORAGE_NAME \
--resource-group $RG \
--location $LOCATION \
--sku Standard_LRS
az functionapp create \
--name $FUNC_NAME \
--resource-group $RG \
--storage-account $STORAGE_NAME \
--consumption-plan-location $LOCATION \
--runtime python \
--runtime-version 3.12 \
--functions-version 4 \
--os-type Linux
az functionapp identity assign \
--name $FUNC_NAME \
--resource-group $RG \
--identities $UMI_RESOURCE_ID
# Execution results
{
"principalId": null,
"tenantId": null,
"type": "UserAssigned",
"userAssignedIdentities": {
"/subscriptions/a509ec7e-2297-419d-8587-ca08543e3cbe/resourcegroups/rg-foundry-func-demo/providers/Microsoft.ManagedIdentity/userAssignedIdentities/umi-foundry-func": {
"clientId": "e7c8a6b7-bd4e-43c7-b49b-d9d6a9e01821",
"principalId": "a114ced5-b53e-4c42-8949-bddd053610cc"
}
}
}
az functionapp config appsettings set \
--name $FUNC_NAME \
--resource-group $RG \
--settings \
FOUNDRY_ENDPOINT="$FOUNDRY_ENDPOINT" \
FOUNDRY_DEPLOYMENT="gpt-5-mini" \
FOUNDRY_API_VERSION="2024-12-01-preview" \
CLAUDE_BASE_URL="https://${FOUNDRY_NAME}.services.ai.azure.com/anthropic" \
CLAUDE_OPUS_DEPLOYMENT="claude-opus-4-6" \
LANGUAGE_ENDPOINT="$FOUNDRY_ENDPOINT" \
LANGUAGE_API_VERSION="2024-11-01" \
UMI_CLIENT_ID="$UMI_CLIENT_ID"
az functionapp config appsettings list \
--name $FUNC_NAME --resource-group $RG \
--query "[].name" -o tsv
# Execution results
FUNCTIONS_WORKER_RUNTIME
FUNCTIONS_EXTENSION_VERSION
AzureWebJobsStorage
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
WEBSITE_CONTENTSHARE
AzureWebJobsDashboard
FOUNDRY_ENDPOINT
FOUNDRY_DEPLOYMENT
FOUNDRY_API_VERSION
CLAUDE_BASE_URL
CLAUDE_OPUS_DEPLOYMENT
LANGUAGE_ENDPOINT
LANGUAGE_API_VERSION
UMI_CLIENT_ID
mkdir foundry-llm-function-py && cd foundry-llm-function-py
func new --name AskLLM --template "HTTP trigger" --authlevel function
azure-functions
azure-identity
openai
anthropic
requests
import azure.functions as func
import json
import logging
import os
from azure.identity import ManagedIdentityCredential, get_bearer_token_provider
from openai import AzureOpenAI
from anthropic import AnthropicFoundry
app = func.FunctionApp()
# --- Shared config ---
FOUNDRY_ENDPOINT = os.environ.get("FOUNDRY_ENDPOINT")
FOUNDRY_API_VERSION = os.environ.get("FOUNDRY_API_VERSION", "2024-12-01-preview")
CLAUDE_BASE_URL = os.environ.get("CLAUDE_BASE_URL")
UMI_CLIENT_ID = os.environ.get("UMI_CLIENT_ID")
# --- Per-model deployment names ---
GPT_DEPLOYMENT = os.environ.get("FOUNDRY_DEPLOYMENT") # e.g. "gpt-5-mini"
CLAUDE_OPUS_DEPLOYMENT = os.environ.get("CLAUDE_OPUS_DEPLOYMENT") # e.g. "claude-opus-4-6"
DEFAULT_MODEL = "gpt"
# --- Single UMI credential, shared by both clients ---
_credential = ManagedIdentityCredential(client_id=UMI_CLIENT_ID)
_openai_token_provider = get_bearer_token_provider(
_credential, "https://cognitiveservices.azure.com/.default"
)
_claude_token_provider = get_bearer_token_provider(
_credential, "https://cognitiveservices.azure.com/.default"
)
_openai_client = AzureOpenAI(
azure_endpoint=FOUNDRY_ENDPOINT,
api_version=FOUNDRY_API_VERSION,
azure_ad_token_provider=_openai_token_provider,
)
_claude_client = AnthropicFoundry(
azure_ad_token_provider=_claude_token_provider,
base_url=CLAUDE_BASE_URL,
)
# --- Model registry: alias -> (provider, deployment name) ---
MODEL_REGISTRY = {
"gpt": ("openai", GPT_DEPLOYMENT),
"opus": ("anthropic", CLAUDE_OPUS_DEPLOYMENT),
}
def _call_openai(deployment: str, query: str, user_context: str | None) -> str:
messages = []
if user_context:
messages.append({"role": "system", "content": str(user_context)})
messages.append({"role": "user", "content": query})
result = _openai_client.chat.completions.create(
model=deployment,
messages=messages,
)
return result.choices[0].message.content or ""
def _call_claude(deployment: str, query: str, user_context: str | None) -> str:
kwargs = {
"model": deployment,
"max_tokens": 1024,
"messages": [{"role": "user", "content": query}],
}
if user_context:
kwargs["system"] = [{"type": "text", "text": str(user_context)}]
result = _claude_client.messages.create(**kwargs)
return "".join(block.text for block in result.content if block.type == "text")
@app.route(route="ask", methods=["POST"], auth_level=func.AuthLevel.FUNCTION)
def AskLLM(req: func.HttpRequest) -> func.HttpResponse:
try:
body = req.get_json()
except ValueError:
return func.HttpResponse(
json.dumps({"error": "Request body must be valid JSON"}),
status_code=400,
mimetype="application/json",
)
query = body.get("query")
user_context = body.get("context")
model_alias = (body.get("model") or DEFAULT_MODEL).strip().lower()
if not query or not isinstance(query, str):
return func.HttpResponse(
json.dumps({"error": '"query" (string) is required in the request body'}),
status_code=400,
mimetype="application/json",
)
if model_alias not in MODEL_REGISTRY:
return func.HttpResponse(
json.dumps({
"error": f'"model" must be one of: {", ".join(MODEL_REGISTRY.keys())}',
}),
status_code=400,
mimetype="application/json",
)
provider, deployment = MODEL_REGISTRY[model_alias]
if not deployment:
return func.HttpResponse(
json.dumps({"error": f'No deployment configured for model "{model_alias}"'}),
status_code=500,
mimetype="application/json",
)
try:
if provider == "openai":
answer = _call_openai(deployment, query, user_context)
else:
answer = _call_claude(deployment, query, user_context)
return func.HttpResponse(
json.dumps({"answer": answer, "model": model_alias}),
status_code=200,
mimetype="application/json",
)
except Exception as e:
logging.exception(f"Foundry call failed for model={model_alias}")
return func.HttpResponse(
json.dumps({"error": "Failed to get a response from the LLM", "detail": str(e)}),
status_code=500,
mimetype="application/json",
)
func azure functionapp publish $FUNC_NAME
Getting site publishing info...
[2026-07-05T23:43:36.764Z] Starting the function app deployment...
Removing WEBSITE_CONTENTAZUREFILECONNECTIONSTRING app setting.
Removing WEBSITE_CONTENTSHARE app setting.
Creating archive for current directory...
Performing remote build for functions project.
Creating placeholder blob for linux consumption function app...
.....................
.....................
.....................
SCM_RUN_FROM_PACKAGE placeholder blob scm-latest-func-foundry-py-19514.zip located
Uploading built content /home/site/artifacts/functionappartifact.squashfs for linux consumption function app...
Resetting all workers for func-foundry-py-19514.azurewebsites.net
Deployment successful. deployer = Push-Deployer deploymentPath = Functions App ZipDeploy. Extract zip. Remote build.
Remote build succeeded!
[2026-07-05T23:44:23.731Z] Syncing triggers...
Functions in func-foundry-py-19514:
AskLLM - [httpTrigger]
Invoke url: https://func-foundry-py-19514.azurewebsites.net/api/ask
FUNC_KEY=$(az functionapp keys list \
--name $FUNC_NAME --resource-group $RG \
--query "functionKeys.default" -o tsv)
curl -X POST "https://$FUNC_NAME.azurewebsites.net/api/ask?code=$FUNC_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "What is the capital of France?"}'
# Execution results
{"answer": "The capital of France is Paris.", "model": "gpt"}
curl -X POST "https://$FUNC_NAME.azurewebsites.net/api/ask?code=$FUNC_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "What is the capital of France?", "model": "opus"}'
# Execution results
{"answer": "The capital of France is **Paris**.", "model": "opus"}
az group delete --name $RG --yes --no-wait
az role definition delete --name "Foundry OpenAI Chat Inference User"
az role definition delete --name "Foundry Anthropic Inference User"
ЧАСТЬ 3 — Azure Function
1–2. Сховішча + Python Function App
3. Прыўязка адмініструемай ідэнтычнасці, выданай корыстнікам
4. Наладжэнні аплікацыі
URL-адрэсы канцаўак, назвы развяртання, ключы APIM або наладжэнні аудыянсы — ніколі не зберагаюце секрэты.
5–7. Каркас, requirements.txt, function_app.py, развяртанне
8. Тэставанне чераз APIM
Звоніце пацэўкі APIM, а не URL функцыі, каб правілы (обмежэнне частоты вызываў, JWT, фільтрацыя IP) дзе-небудзь прымелі эфект.
Справака для адлучэння прычын
Коды 401/403 зазвычай означаюць проблемы з RBAC або некоректным іменем развёртывання. Код 404 часта указвае на несувяз между регіонам і модэлем. Проблэмы з таймаутамі часта выступаюць наследкам холаднага запуску функцыі, калі таймаут бэкенду APIM занадта низькі.
Усвойленыя урокі
Центрырацыя доступу да модэляў через APIM; выкарыстоўванне кераваных ідэнтытацый для модэляў; строгае прымененне спецыяльных правил RBAC; тэставанне дзейнасцей з дадзеннямі кожнай новай групы модэляў; логаванне ідэнтыфікатораў сувязі ад APIM да функцыі і да вызыва модэля.
Развітак без API-фронтдору ведае да розсейвання ключоў. APIM — гэта тое месца, дзе трафік агента стае кераваным.
Парадакт палітыкі: разместыце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цыкл агента не могаў перакануцься за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместыце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цыкл агента не могаў перакануцца за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместыце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цыкл агента не могаў перакануцца за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместіце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цыкл агента не могаў перакануцься за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместіце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цыкл агента не могаў перакануцца за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместіце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цыкл агента не могаў перакануцца за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместіце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб цікл ненормальна працуючага агента не могў перакануць ліміты на рэвэрсе аплікацыі, вызываючы функцыю безпасэродзе — заблокавайце безпасэродзейны вызыв функцый у працоўных сетках.
Парадакт палітыкі: разместіце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб цікл ненормальна працуючага агента не могў перакануць ліміты на рэвэрсе аплікацыі, вызываючы функцыю безпасэродзе — заблокавайце безпасэродзейны вызыв функцый у працоўных сетках.
Парадакт палітыкі: разместіце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб цікл ненормальна працуючага агента не могў перакануць ліміты на рэвэрсе аплікацыі, вызываючы функцыю безпасэродзе — заблокавайце безпасэродзейны вызыв функцый у працоўных сетках.
Парадакт палітыкі: разместыце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цыкл агента не могаў перакануцься за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместыце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цыкл агента не могаў перакануцца за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместыце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цыкл агента не могаў перакануцца за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместіце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб цікл ненормальна працуючага агента не могў перакануць ліміты на рэвэрсе аплікацыі, вызываючы функцыю безпасэродзе — заблокавайце безпасэродзейны вызыв функцый у працоўных сетках.
Парадакт палітыкі: разместіце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб цікл ненормальна працуючага агента не могў перакануць ліміты на рэвэрсе аплікацыі, вызываючы функцыю безпасэродзе — заблокавайце безпасэродзейны вызыв функцый у працоўных сетках.
Парадакт палітыкі: разместіце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб цікл ненормальна працуючага агента не могў перакануць ліміты на рэвэрсе аплікацыі, вызываючы функцыю безпасэродзе — заблокавайце безпасэродзейны вызыв функцый у працоўных сетках.
Парадакт палітыкі: разместыце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цикл агента не могаў перакануцься за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместыце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цикл агента не могаў перакануцца за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадакт палітыкі: разместыце бюджэты токенаў і ліміты частоты на аднаго прынцыпала ў APIM, каб неадекватны цикл агента не могаў перакануцца за ліміты на рэвэле аплікацыі, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцыі ў працоўных сетках.
Парадыгматыя: разместіце бюджэты токенаў і ліміты частоты на аднае працоўнай екзэкватыбулі ў APIM, каб агенты з ненармальным паведаннем не моглі абйść ліміты на рэвэлюцыянай ступені, вызываючы функцыю безпосередна — заблокавайце безпасэродны вызыв функцый у працоўных сетках.
Парадыгматыя: разместіце бюджэты токенаў і ліміты частоты на аднае працоўнай екзэкватыбулі ў APIM, каб агенты з ненармальным паведаннем не моглі абйść ліміты на рэвэлюцыянай ступені, вызываючы функцыю безпасэродна — заблокавайце безпасэродны вызыв функцый у працоўных сетках.
Разныя сераўысы трэбуюць разных продуктав APIM і айдэнтытаў. Аднарадковае выкарыстоўванне адной разгалошэння Foundry ў сераўысе разработкі і працоўнай сетцы для “зямлеі” зазвычай прыводзіць да вытэкання інфармацыі і нарушэння ізоляцыі межаў.
Запісавайце, якія працоўнай екзэкватыбулі могу ствараць разгалошэння модэляў, а якія можу толькі іх вызываць. Права на вызыв без прав на разгалошэнне — гэта стандартны здаровы падзел.
Калі дадаецца новая сямейка модэляў, трэба апцэнзаваць спецыяльную ролю, бэкенд APIM, настройкі функцыі і тэст на адпаведнасць у той жа PR. Частыя апдэйты — гэта прычына, чаму канфлікты 403 з’яўляюцца толькі у пятніцу.
Лепш выкарыстоўваць заголовкі карэляцыі з APIM через функцыю ў логі SDK модэля, каб адна заявка на падтрымку магла выяўіць весь шлях.
Разныя среды трэбуюць разных продуктав APIM і айдэнтыкаў. Аднае развертанне Foundry між режымамі разработкі і працы зазвычай ведае до вытэкання інформаціі і нарушэння ізоляцыі.
Дакументаваць, якія прынцыпалы могу ствараць развертання модэляў, а якія толькі іх запускаць. Права на запуск без прав на развертанне — гэта стандартны здаровы падзел.
Калі дадаецца новая сямейка модэляў, трэба апцэнзаваць спецыяльную ролю, бэкенд APIM, настройкі функцыі і тэст на адпаведнасць у той жа PR. Частыя апдэйты — гэта прычына, чаму канфлікты 403 з’яўляюцца толькі у пятніцу.
Лепшае выкарыстоўванне заголовакаў карэляцыі з APIM через функцыю ў логівы модэльскага SDK, каб адна заява на падтрымку могла склець усю шляхавую структуру.
Разныя среды выклікаюць патрэбу ў разных продуктах та ідэнтыфікаторах APIM. Адна і тая ж разгортка Foundry між режымамі разработкі та працы зазвычай ведае до вытэкання інформаціі та нарушэння ізоляцыі разных сектараў.
Запісуйце, якія прынцыпалы могу ствараць разгорткі модэляў, а якія можаць толькі іх вызываць. Права на вызыв без прав на разгорткі — гэта стандартны здаровы падзел прав.
Калі дадаеце новую сям’ю модэляў, апдэйтавайце спецыяльную ролю, бэкенд APIM, настройкі функцыі та атрыбуты для тэстування ў той жа PR. Частковыя разгорткі — гэта прычына, чаму праблемы 403 з’яўляюцца толькі у пятніцу.
Лепшае выкарыстоўванне заголовакаў карэляцыі з APIM через функцыю ў логівы модэльскага SDK, каб адна заява на падтрымку могла склець усю шляхавую структуру.
Для разных сэрвісаў патрабуюцься адзінаковыя продукты APIM і ідэнтыфікаторы. Аднаўленне Foundry для разработчыцкай і працоўнай среды з метой “зямлі выгод” часта прыводзіць да выкрадання паведамленняў і нарушэння ізоляцыі разных сэрвісаў.