Introduction
AI agents are moving from generating answers to performing actions.
An agent can call an API, query a database, create a file, send a message, update a record, deploy infrastructure, or execute code. Once an agent can perform these operations, identity and authorization become part of the agent architecture rather than a concern limited to traditional application users.
The security problem becomes more complicated when an agent acts on behalf of a human.
Consider this request:
Create a support ticket for my account
and attach the latest diagnostic report.
There are now several identities involved:
Human User
↓
AI Agent
↓
Tool
↓
Backend Service
Each layer needs to answer a different question:
Who is the human?
Which agent is acting?
Which tool is being invoked?
What operation is allowed?
Which resources can be accessed?
Is the operation read-only or mutating?
Does the action require human approval?
A secure agent architecture should not allow the model itself to decide these questions.
Authorization should exist outside the model's reasoning process.
AWS's current guidance for secure agent tool usage recommends authorizing every tool invocation against a defined policy while propagating both agent identity and originating user context through the authorization chain.
The Problem With Blanket Agent Permissions
A simple implementation might give an agent one broad identity:
Agent
↓
IAM Role
↓
All Required Services
The agent can then call multiple tools using the same permissions.
This creates a large blast radius.
If the agent is manipulated or a tool is misused, the attacker may gain access to every resource available to the agent.
A better model is:
User
↓
Agent Identity
↓
Tool Authorization
↓
Specific Resource
The agent receives only the capabilities required for its current task.
Identity Is Not the Same as Authorization
Authentication answers:
Who are you?
Authorization answers:
What are you allowed to do?
For agentic systems, there is an additional question:
Who are you acting for?
This produces three useful identity dimensions:
User Identity
+
Agent Identity
+
Transaction Context
For example:
User: user-1837
Agent: support-agent
Operation: CreateTicket
Resource: ticket-system/account-1837
The authorization system can evaluate all of these attributes.
Separate Human and Agent Identities
An agent should not simply become the human user.
Suppose:
User: Alice
Agent: SupportAgent
The system should preserve both identities:
Alice
↓
SupportAgent
↓
CreateSupportTicket
This makes auditing possible.
Instead of recording:
Created by: Alice
the system can record:
User: Alice
Agent: SupportAgent
Action: CreateSupportTicket
Resource: Ticket-8421
That distinction becomes important when the same user employs multiple agents with different capabilities.
AWS's agent security guidance explicitly recommends separating agent and human-user permission boundaries rather than allowing an agent to assume the human operator's identity or permissions.
Use a Dedicated Agent Identity
A production agent should have its own identity.
For example:
OrderAgent
SupportAgent
ReportingAgent
DeploymentAgent
Each identity can have a different capability set.
SupportAgent
├── ReadCustomer
├── CreateTicket
└── AddComment
DeploymentAgent
├── ReadDeployment
├── StartDeployment
└── ReadLogs
This is safer than:
GenericAgent
└── Full Application Access
AWS Bedrock AgentCore provides workload identities as stable identities for agents across deployment environments and authentication mechanisms.
Think in Terms of Capabilities
Instead of asking:
What can this agent access?
ask:
What capability does this specific operation require?
For example:
Capability: ReadOrder
Resource: Order/123
Capability: CancelOrder
Resource: Order/123
These should not necessarily have the same authorization requirements.
A read operation might execute automatically.
A cancellation might require:
Human Approval
This creates a capability hierarchy:
Read
↓
Modify
↓
Delete
↓
Financial / Irreversible Action
The higher the potential impact, the stronger the authorization controls should become.
Authorize Every Tool Call
One of the most important rules for agentic systems is:
Never assume that because an agent was authorized once, every subsequent tool call is authorized.
Consider:
Agent
↓
Tool A
↓
Tool B
↓
Tool C
Each invocation should be evaluated.
Conceptually:
Tool Call
↓
Identify Agent
↓
Identify User
↓
Identify Tool
↓
Validate Parameters
↓
Evaluate Policy
↓
Allow / Deny
AWS's Agentic AI security guidance recommends this externally enforced authorization model and a default-deny approach for higher maturity implementations.
Do Not Let the Model Be the Policy Engine
A model might reason:
The user probably wants me to
delete this record.
That reasoning is not authorization.
The model should propose an action:
{
"tool": "delete_customer",
"customerId": "123"
}
A policy engine should decide whether the action is permitted.
Model Decision
↓
Tool Request
↓
Authorization Policy
↓
Allow / Deny
This is a critical architectural boundary.
The model determines what it wants to do.
The authorization system determines what it is allowed to do.
Validate Tool Parameters
Authorization should not stop at the tool name.
Consider:
{
"tool": "refund_payment",
"amount": 100000
}
An agent may have permission to issue refunds, but that does not mean it should be able to issue an unlimited refund.
The policy should consider parameters:
Tool:
refund_payment
Allowed:
amount <= $500
Requires Approval:
amount > $500
This creates parameter-aware authorization.
AWS recommends schema and policy checks on tool parameters so generated arguments remain within defined boundaries.
Use Schema Validation Before Execution
Define strict tool contracts.
For example:
public sealed record RefundRequest(
string PaymentId,
decimal Amount,
string Currency);
Then validate:
if (request.Amount <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(request.Amount));
}
Additional policy checks can verify:
Currency is allowed
Payment belongs to user
Amount is within limit
Payment is refundable
Agent has refund capability
This prevents the model from turning an otherwise legitimate tool into an unrestricted execution channel.
Use Resource-Level Authorization
An agent should not receive access to every instance of a resource simply because it can use the resource type.
For example:
Allowed:
Customer/123
Denied:
Customer/456
The authorization decision should include resource identity.
A useful policy model is:
Principal
+
Action
+
Resource
+
Context
For example:
Principal = SupportAgent
Action = ReadCustomer
Resource = Customer/123
Context = User/123
Only then should the policy return:
ALLOW
Propagate User Context
When an agent acts on behalf of a user, the user context should travel with the request.
Conceptually:
User Request
↓
Identity Provider
↓
Agent
↓
Tool Gateway
↓
Backend
The backend should be able to determine:
Original User
Agent
Requested Operation
This prevents a common security problem where the downstream service sees only the agent identity and loses the context of the user who initiated the action.
Amazon Bedrock AgentCore workload access tokens can carry both user and agent identity information, providing this type of binding across the authorization flow.
Avoid Passing User Credentials to the Agent
A dangerous pattern is:
User
↓
Username + Password
↓
Agent
↓
Tool
The agent should not need direct possession of a user's credentials.
A stronger model is:
User
↓
Authenticated Session
↓
Agent Identity + User Context
↓
Scoped Authorization
↓
Tool
The agent receives a capability or token appropriate for the operation rather than the user's long-lived credentials.
Prefer Temporary Credentials
Long-lived credentials increase the impact of compromise.
Prefer credentials that:
AWS recommends temporary credentials and dynamic permission boundaries for agentic workloads to reduce the impact of a compromised or misprompted agent.
The basic model is:
Need Access
↓
Issue Temporary Credential
↓
Perform Operation
↓
Credential Expires
Separate Service Identity From Transaction Identity
An agent can have a stable identity:
Agent = DeploymentAgent
while individual transactions have narrower context:
Transaction:
User = Alice
Environment = Staging
Application = Orders
Action = Deploy
This allows the system to keep broad capabilities at the service level while applying tighter restrictions to individual operations.
A useful conceptual model is:
Agent Identity
↓
Service Permissions
↓
Transaction Context
↓
Dynamic Restrictions
AWS's security guidance describes these as separate identity layers and recommends applying permission scoping at each layer.
Use Human Approval for High-Risk Actions
Not every operation should be fully autonomous.
Consider:
Read Documentation
↓
No Approval
Create Draft
↓
No Approval
Modify Customer Data
↓
Maybe Approval
Delete Customer
↓
Approval
Transfer Money
↓
Approval
High-risk operations should have an explicit human checkpoint when appropriate.
The agent can prepare the operation:
Agent
↓
Prepare Refund
↓
Human Review
↓
Approve
↓
Execute
This keeps the agent useful without giving it unrestricted authority.
Add Rate Limits
Authorization determines whether an action is allowed.
Rate limiting determines how much impact can occur within a period.
Consider a compromised agent repeatedly calling:
delete_file()
Even if the tool is technically authorized, unrestricted invocation can create significant damage.
Add limits such as:
100 reads / minute
10 writes / minute
3 financial operations / minute
The exact values depend on the application.
AWS's secure tool-use guidance also recommends rate limits to limit the impact of runaway agent behavior.
Use Tool Registries
Agents should not automatically discover and invoke arbitrary tools.
Maintain a controlled registry:
Tool
├── Name
├── Version
├── Owner
├── Permissions
├── Data Classification
├── Risk Level
└── Review Date
For example:
create_ticket
Version: 2.1
Risk: Low
Permission: Ticket.Write
and:
delete_customer
Version: 1.4
Risk: Critical
Permission: Customer.Delete
Approval: Required
AWS recommends registering tools and MCP servers with documented permissions, data classification, versioning, and review information.
Secure MCP-Based Tools
Model Context Protocol servers can expose many useful tools to agents.
But adding an MCP server should not automatically grant unrestricted access.
Use:
Agent
↓
Tool Registry
↓
Authorization Gateway
↓
MCP Server
↓
Backend
rather than:
Agent
↓
Any MCP Server
The gateway can enforce:
Authentication
Authorization
Parameter validation
Rate limits
Logging
Tool allowlists
Version restrictions
Build a Policy Model
A simple policy might look like:
{
"agent": "support-agent",
"action": "customer.update",
"resource": "customer/*",
"conditions": {
"userContextRequired": true,
"approvalRequired": false
}
}
A high-risk policy could look like:
{
"agent": "support-agent",
"action": "customer.delete",
"resource": "customer/*",
"conditions": {
"userContextRequired": true,
"approvalRequired": true
}
}
The important point is that these rules exist outside the model.
Example .NET Authorization Boundary
A simplified application-level authorization component might look like:
public sealed record ToolRequest(
string AgentId,
string UserId,
string Tool,
string Resource);
public sealed class ToolAuthorizer
{
public bool IsAllowed(ToolRequest request)
{
if (request.AgentId != "support-agent")
{
return false;
}
if (request.Tool == "customer.delete")
{
return false;
}
return request.Tool switch
{
"customer.read" => true,
"ticket.create" => true,
"ticket.comment" => true,
_ => false
};
}
}
This is intentionally simple.
Production authorization should normally use a dedicated policy model rather than embedding every rule inside application code.
The important architectural property is that the tool request passes through authorization before execution.
Log Authorization Decisions
Every important tool invocation should produce an audit record.
For example:
Timestamp: 2026-08-14T09:30:00Z
User: user-1837
Agent: support-agent
Tool: ticket.create
Resource: account-1837
Decision: ALLOW
Policy: support-ticket-v2
For denied requests:
Decision: DENY
Reason: Missing capability
Do not log sensitive credentials or raw secrets.
The audit record should provide enough context to reconstruct the authorization decision without exposing confidential data.
Monitor Agent Behavior
Authorization logs become particularly valuable when combined with behavioral monitoring.
Look for patterns such as:
Normal:
10 tool calls / minute
Abnormal:
2,000 tool calls / minute
Or:
Normal:
Read → Read → Update
Abnormal:
Delete → Delete → Delete → Delete
These patterns can indicate:
A circuit breaker can stop an agent when behavior exceeds defined thresholds.
Test Identity Confusion
Security testing should deliberately attempt to confuse identity boundaries.
Test scenarios such as:
Agent A tries to use Agent B's tool
User A asks an agent to access User B's resource
Agent attempts to assume a human operator role
Tool request omits user context
Tool request modifies the resource identifier
Every test should produce:
Expected → DENY
Actual → DENY
If the result is ALLOW, the authorization boundary needs investigation.
Common Mistakes
Giving Agents Broad IAM Roles
A broad role creates a large blast radius.
Letting the Model Decide Authorization
LLM reasoning should never replace policy enforcement.
Losing User Context
Downstream services need to know who initiated the action.
Passing User Credentials to Agents
Agents should use scoped identities and temporary credentials instead.
Authorizing Only the Tool Name
Parameters and resources must also be checked.
Allowing Unlimited Tool Calls
Rate limits reduce the impact of runaway behavior.
Skipping Human Approval
High-impact operations should have explicit approval boundaries where appropriate.
Failing to Log Denied Actions
Denied requests are valuable security signals.
Trusting Every MCP Tool
Tools should be reviewed, registered, versioned, and governed before agents can invoke them.
Best Practices
Give every production agent a dedicated identity.
Keep human and agent identities separate.
Propagate the originating user context.
Authorize every tool invocation.
Use a default-deny authorization model.
Validate tool parameters against strict schemas.
Apply resource-level authorization.
Use temporary and narrowly scoped credentials.
Never give agents unnecessary production credentials.
Require human approval for high-risk mutations.
Apply rate limits and circuit breakers.
Maintain a governed tool and MCP registry.
Log authorization decisions and tool activity.
Monitor unusual agent behavior.
Test cross-user and cross-agent authorization failures.
Reassess permissions whenever an agent gains a new tool.
Frequently Asked Questions
Should an AI agent have its own identity?
Yes. A dedicated identity makes permissions, auditing, and lifecycle management much clearer.
Should the agent use the user's IAM role?
Generally, no. Human and agent identities should remain separate, with the user's context propagated through a controlled authorization mechanism.
Can the model authorize its own tool calls?
No. The model can propose an action, but authorization should be enforced outside the model.
Should every tool call require human approval?
No. Low-risk operations can often remain automated. Human approval is more appropriate for high-impact or irreversible operations.
Why is user context important?
Without user context, a backend may know which agent performed an operation but not which user the agent was acting for. That weakens authorization and auditing.
Is an IAM role enough for an agent?
An IAM role provides an important service-level permission boundary, but agentic systems often need additional transaction context, resource constraints, user binding, tool policies, and behavioral controls.
Conclusion
Agentic applications introduce a new identity problem because one action can involve multiple principals:
Human User
↓
AI Agent
↓
Tool
↓
Service
↓
Resource
Treating all of these as one identity creates weak authorization boundaries.
A stronger architecture keeps the identities distinct:
User Identity
+
Agent Identity
+
Transaction Context
+
Tool Policy
+
Resource Policy
Every tool invocation should then pass through an authorization boundary before execution.
The most important principle is simple:
An agent should never receive more authority merely because its model believes an action is appropriate.
The model proposes.
The policy decides.
The tool executes.
That separation creates a much stronger foundation for secure autonomous systems, especially as agents move from read-only assistants toward systems that modify business data, invoke infrastructure APIs, execute code, and perform financial or operational actions.
For modern agentic architectures, identity should therefore be treated as a first-class design concern rather than an authentication detail added after the agent is built.