Skip to content

Securing AI Agent Tool Calls in Azure: Identity, Authorization, and Verified Execution

When an agent can use tools, untrusted content can influence requests to access sensitive data or change external systems. A retrieved document might tell the agent to send a file to an external address. An attacker-controlled log field might suggest disabling a security setting. A tool result might redirect the next action.


The application must establish who is acting, authorize each requested operation, constrain execution, and verify what happened. System instructions, content filters, and model evaluations help reduce unsafe proposals. Token validation, retrieval permissions, business authorization, execution limits, and disclosure checks govern what the application actually permits.


This article uses an Agent Control Loop as a design-review framework for placing those checks at five observable handoffs:


Input → Context → Tool Request → Execution → Output


Agent Control Loop: Input uses token validation and request limits; Context uses retrieval permissions and provenance; Tool Request uses argument validation and business authorization; Execution uses approval checks and a least-privilege identity; Output uses outcome verification and disclosure checks. Tool results return to Context.


Tool results return to Context because they can influence another model decision. They need the same attention to source permissions, provenance, and untrusted content as retrieved documents.


The framework should fit the workload. A read-only assistant needs strong retrieval and disclosure checks when it handles sensitive information. A routine transaction may need only service-side authorization and safe retry handling. A delayed, high-impact operation may also need approval, expiry, current-state checks, and recovery procedures. Choose safeguards according to data sensitivity, action scope, reversibility, delay, and the consequence of failure.


In this article: Input  |  Context  |  Tool Request  |  Execution  |  Output  |  Review questions


Guide and test the model’s proposals


Model behavior remains an important part of the design:



  • Guide the model with system instructions, task boundaries, and a limited tool set.

  • Ground its decisions in permitted sources with provenance metadata.

  • Review observable artifacts such as tool arguments, citations, assumptions, uncertainty, and concise decision summaries.

  • Test behavior with offline evaluations and adversarial regression tests.


These measures reduce the likelihood of a poor proposal. The receiving service must still validate its arguments and authorize the requested operation.


Authorization also has limits. A request can satisfy business rules while conflicting with the user’s intent. Narrow workflow scope, cumulative action limits, and review when consequences justify it help address that remaining risk.



Token validation, authorization rules, and execution limits must run outside model-controlled context. Every path to a protected capability—including direct API calls, background jobs, and retries—must pass through the applicable checks.



1. Input: validate identity and enforce request limits


Input includes the user’s prompt, attachments, conversation state, and request metadata. For an authenticated enterprise workflow, establish the caller’s identity before loading protected conversation state or retrieving enterprise data.


Validate the token’s signature, issuer, audience, and lifetime. Check the expected tenant, client application, and required claims. Derive the acting principal and tenant from validated identity information, and resolve application permissions through trusted server logic.


Keep this authorization context separate from model-editable content. A tenant name in a prompt or a role asserted in an attachment must not change the caller’s permissions.


Apply request-size limits, attachment-type restrictions, rate limits, and relevant data-handling rules before content reaches the model. These checks protect application capacity and reduce avoidable exposure of sensitive content.


Microsoft Entra ID can authenticate users and workloads. Azure API Management can enforce token-validation policies, required claims, quotas, and rate limits. Azure AI Content Safety Prompt Shields can add detection for direct prompt attacks.


A detection result may trigger rejection, isolation, or additional review. Passing that check does not authorize a later tool call. A missed attack must still encounter the tool service’s argument validation and authorization checks.


Authentication establishes who submitted the request. It does not establish that the request is accurate, appropriate, or within the caller’s business authority.


2. Context: enforce retrieval permissions and preserve provenance


Context can contain system instructions, retrieved documents, database records, conversation history, memory, and tool results. These sources have different trust properties.


For example, an Azure log record may have authenticated provenance while containing a filename, URI, process argument, or user-agent string chosen by an attacker. The logging service can accurately preserve that value without making it a valid instruction.


A registered tool can return the same kind of content. Its response may include attacker-controlled text, unrelated sensitive information, or evidence that contradicts another source.


Enforce source permissions before content enters model context. Scope retrieval to the authorized tenant and permitted documents or records. Limit tables, indexes, fields, result counts, and time windows. Construct security filters from trusted identity information, and prevent model-generated queries from removing mandatory restrictions.


For Azure AI Search, use supported document-level access controls or security filters enforced by the application. Authentication to the search service alone does not establish permission to read every document in an index. Microsoft documents this distinction in its security-filter guidance.


For Azure Monitor and other query tools, constrain the accessible resources and query scope through service permissions and application logic. Query templates should parameterize permitted inputs while preserving mandatory tenant and resource restrictions.


Preserve source identifiers, timestamps, classification, and tenant metadata. Keep application instructions separate from retrieved evidence, and label externally influenced text as untrusted data. These labels help the model interpret content; retrieval authorization remains the service’s responsibility.


Require citations when conclusions depend on retrieved evidence. For consequential decisions, verify that the cited material supports the conclusion and corroborate it against another source or current system state where practical.


Prompt Shields can add detection for indirect prompt attacks in document content. Microsoft Purview classification can inform filtering and disclosure decisions where classification is available and integrated into the application.


Retrieved content may inform a proposed action. It must not modify the caller’s identity, broaden retrieval permissions, or grant authority to another tool.


3. Tool Request: validate arguments and authorize the exact action


The model produces an observable request: a tool name, target, and arguments. The receiving service must decide whether that exact request is permitted.


Use a narrow tool definition. For example, a refund tool can accept an order identifier and an amount without accepting an arbitrary payment destination or caller-selected authorization limit.


The following function-definition fragment describes a workflow for USD refunds. Amounts use integer cents:


JSON | Refund tool definition


{
“name”: “issue_refund”,
“description”: “Request a USD refund to the order’s original payment method.”,
“strict”: true,
“parameters”: {
“type”: “object”,
“additionalProperties”: false,
“required”: [“order_id”, “amount_minor”],
“properties”: {
“order_id”: {
“type”: “string”,
“description”: “The order identifier.”
},
“amount_minor”: {
“type”: “integer”,
“description”: “The refund amount in USD cents.”
}
}
}
}

The surrounding API format and supported schema constraints depend on the provider and model. Azure’s structured-output guidance and OpenAI’s guidance document different support for some constraints. Confirm compatibility with the deployment, and enforce all required validation in the receiving service.


Here is an illustrative Pydantic v2 validation and authorization fragment. It assumes that principal comes from trusted authentication and permission resolution, and that order is loaded from the authoritative store through a tenant-scoped lookup.


Python | Request validation and refund authorization


from pydantic import BaseModel, ConfigDict, Field

class RefundRequest(BaseModel):
model_config = ConfigDict(extra=”forbid”, strict=True)

order_id: str = Field(pattern=r”^ord_[A-Za-z0-9]{12}$”)
amount_minor: int = Field(gt=0, le=50_000) # USD cents: at most $500

class AuthorizationError(Exception):
pass

def authorize_refund(request: RefundRequest, principal, order) -> None:
if order.tenant_id != principal.tenant_id or order.id != request.order_id:
raise AuthorizationError(“order is outside the requested scope”)

if not principal.can_issue_refunds:
raise AuthorizationError(“caller cannot issue refunds”)

if order.customer_id != principal.customer_id:
raise AuthorizationError(“caller does not own the order”)

if order.currency != “USD”:
raise AuthorizationError(“this workflow supports USD orders only”)

if not order.is_refundable or order.account_fraud_blocked:
raise AuthorizationError(“order is not eligible for a refund”)

if request.amount_minor > principal.refund_limit_usd_minor:
raise AuthorizationError(“amount exceeds caller authority”)

if request.amount_minor > order.remaining_refundable_minor:
raise AuthorizationError(“amount exceeds the refundable balance”)


The service must parse the incoming arguments with RefundRequest.model_validate(…) before calling this function. The example assumes a customer refund workflow; a support-agent workflow would use its own delegated permissions and order-access rules.


The payment destination comes from the authoritative payment record and must satisfy the refund policy. It is not selected from model-generated arguments.


These checks do not reserve funds or prevent concurrent refunds. The service must couple authorization to an atomic transaction or conditional reservation so competing requests cannot consume the same refundable balance. For systems that allow partial refunds, the available balance should account for both completed refunds and active reservations.


Derive the acting principal and allowed scope from trusted server context. If a tool accepts a target user or tenant, treat that value as an untrusted target selector and authorize it independently.


Authenticating a workload also does not establish the authority of the user it represents. A domain service must enforce either the represented user’s permissions or an explicitly defined service workflow’s authority.


An Azure Function, App Service API, or another domain service can perform these checks. An external policy engine can help when rules need independent ownership or consistent reuse. Azure RBAC separately limits which Azure operations the executor’s identity can perform.


4. Execution: bind approval, recheck state, and constrain privileges


An authorized request can become stale before execution. The caller’s permissions may change, a refund balance may shrink, or a resource may be modified while a request waits for approval.


For an immediate operation within one transactional system, authorize and apply the change in the same transaction where possible. An external API call introduces a separate failure boundary and may require idempotency and reconciliation.


When human approval is required, store an approval record that binds the decision to the exact operation, canonical target, parameters, requester, tenant, and expiry. Validate the approver’s authority, and require a new decision if the approved action changes.


Before execution, check approval validity where applicable, re-evaluate current authorization, and re-read the state relevant to the operation. Use conditional writes when the target API supports the required concurrency condition.


A single-use approval claim prevents approval reuse. It does not by itself prevent duplicate external effects. A worker can submit a payment and crash before recording the result. Where supported, bind a downstream idempotency key to the authorized action and reuse that key for retries. If the outcome is uncertain, reconcile with the downstream system before submitting another operation.


Use an executor identity with only the resource scope and API permissions the workflow requires. A separate managed identity is useful when execution needs privileges that the model-facing component should not hold. Restrict outbound destinations and the data that may be sent to each destination.


Example: verify an Azure Storage configuration change


The following execution fragment changes one Storage account property. It assumes that the service has already loaded a trusted execution record, validated any required approval, and authorized the exact subscription and resource target. The expected state comes from that record.


Python | Azure Storage execution and verification


import os

from azure.identity import ManagedIdentityCredential
from azure.mgmt.storage import StorageManagementClient
from azure.mgmt.storage.models import StorageAccountUpdateParameters

def disable_public_network_access(command):
client = StorageManagementClient(
credential=ManagedIdentityCredential(
client_id=os.environ[“EXECUTOR_MANAGED_IDENTITY_CLIENT_ID”]
),
subscription_id=command.subscription_id,
)

before = client.storage_accounts.get_properties(
command.resource_group,
command.account_name,
)
if before.public_network_access != command.expected_public_network_access:
raise RuntimeError(“resource state changed after authorization”)

client.storage_accounts.update(
command.resource_group,
command.account_name,
StorageAccountUpdateParameters(public_network_access=”Disabled”),
)

after = client.storage_accounts.get_properties(
command.resource_group,
command.account_name,
)

return {
“operation”: “storage.disable_public_network_access”,
“target”: after.id,
“status”: (
“configuration_verified”
if after.public_network_access == “Disabled”
else “verification_pending”
),
“observed_public_network_access”: after.public_network_access,
}


This verifies the property reported by the management API. It does not establish that every access path is blocked. Azure documents that previously configured trusted-service and resource-instance exceptions can remain effective, and that Storage firewall restrictions apply to data-plane operations. If the objective is containment, verification must also account for the relevant exceptions and access paths. See Storage network-security limitations.


The Storage Accounts Update reference for API version 2025-08-01 does not document an If-Match header. The initial read can detect a difference from the expected state, but another writer can still change the resource between that read and the update. The example does not provide an atomic compare-and-update operation.


If verification remains pending or a network failure obscures the result, retain the action record and reconcile current state. Do not report verified completion or blindly resubmit a new action.


The Azure services involved each have a specific role:



  • Managed identities provide credentials without embedding application secrets.

  • Azure RBAC limits resource scope and permitted operations. A broad resource-write permission may still allow more property changes than this function exposes.

  • Azure Policy deny rules can reject covered resource changes that violate configured policies.

  • Private endpoints and egress restrictions constrain connectivity; application logic must still authorize destinations and payloads.

  • Durable Functions can coordinate an approval wait and execution workflow.

  • Cosmos DB conditional writes can protect an approval claim or action record against competing updates.


The domain service remains responsible for deciding whether the business action is permitted. Workflow coordination and restricted credentials do not replace that decision.


5. Output: verify outcomes, authorize disclosure, and record evidence


Output includes the tool result returned to the model, the final user response, and operational evidence. Each has a different audience and disclosure policy.


Keep separate records of what the model requested, what the service authorized, what a human approved when required, what the downstream API returned, and what verification subsequently observed.


A successful API response may describe an intermediate state. A refund may be accepted but not settled. A message may be queued but not delivered. A resource property may be updated while the broader containment objective remains unverified.


Define the postcondition for the workflow and report the state actually observed. Use explicit statuses such as submitted, pending verification, completed, failed, or outcome unknown. For delayed outcomes, retain the action identifier and update its status as evidence becomes available.


Authorize disclosure before returning data to the model or user. Apply equivalent checks before tools transmit data to another service. A response filter cannot recover information already sent in an outbound tool request.


Remove secrets and unrelated personal or tenant data from tool responses, final answers, and telemetry. Collect the identifiers, decision reasons, timestamps, and verification results needed to investigate the action without retaining unrestricted prompts or credentials.


Read target state through the relevant API and correlate the result with Azure Monitor or Application Insights telemetry. Microsoft Sentinel can consume the evidence when the workflow supports security operations. Use access-controlled or immutable records where audit requirements justify them.


Recovery must reflect the consequence of the action. Retrying an idempotent evidence write can be appropriate. Automatically reversing a containment action because a later annotation failed can create a new security problem. Preserve partial failures and uncertain outcomes so operators can make an informed recovery decision.


Logs record observations. They do not establish every aspect of the real-world outcome. State what was verified, when it was observed, and what remains unresolved.


Review the five handoffs


For an agentic application, ask:



  1. Input: Which token checks establish the caller, and which request limits apply?

  2. Context: Which retrieval permissions restrict the evidence, and how are its source and trust represented?

  3. Tool Request: Which argument checks and business rules authorize this operation, target, amount, and acting principal?

  4. Execution: Are approval and authorization still valid, how are competing actions and retries handled, and what can the executor change or transmit?

  5. Output: Which postcondition was observed, who may receive the result, and what evidence remains available?


Continue improving the model’s instructions, grounding, and evaluations. At each handoff, make the responsible service and its checks explicit.



The model proposes; trusted services validate requests, authorize actions, constrain execution, and verify outcomes.


Microsoft Tech Community originally posted this article on 14 September 2026 at 5:15 AM.

Leave a Reply