Skip to main content
INS // Insights

Just-in-Time Access for AI Agents

Updated October 2026 · 8 min read

Just in time access for ai agents means the agent receives a credential that exists for one tool call and then is gone from the process. The credential is an IAM role session. The session policy on that call allows the one action the tool needs, on the one resource the request named. The agent runtime does not keep an access key in its environment, and it does not reuse the session for the next tool. Who the agent is, as a principal you can name and disable, is the subject of AI agent identity. This article is the lifetime of the credential that principal uses when it actually calls an API.

Rutagon builds that handoff for SOC 2 teams putting an agent next to production AWS APIs. A standing key in the agent configuration is the pattern we remove. It is the same class of secret as any other long-lived access key, with a worse blast radius, because the process that holds it will attempt whatever the prompt and the tools allow. AWS documents the session in the AssumeRole API. DurationSeconds has a floor of 900 seconds. We do not pretend the API will mint a 30-second password. The narrowness is the session policy and the fact that the process drops the keys when the call returns. The clock runs to 15 minutes because that is the minimum AssumeRole allows.

How just in time access for ai agents is issued

The runtime role and the tool role are different roles. The runtime role is what the agent process starts with. It can write its own logs and it can call sts:AssumeRole on a small set of tool roles. It cannot read the customer bucket itself. The tool role can read the bucket, and its trust policy allows only the runtime role to assume it. A prompt that convinces the model to call a different API still has to get past the session policy on that assumption, and the runtime role was never granted the API directly.

At the start of a tool call the runtime assumes the tool role. It passes a session policy that allows one action and one resource, derived from the tool definition and the arguments that already passed the tool allowlist. It passes session tags: the agent id, the tool name, and the request id. It sets the duration to 900 seconds. The returned access key, secret, and session token are handed to the client that performs that one call. When the call returns, the process clears those values. The session remains valid until the 900 seconds elapse, which is the residual window, and CloudTrail will show any use of it. Nothing in the agent stores the triple for the next turn.

action: sts:AssumeRole
role_arn: arn:aws:iam::111122223333:role/agent-tool-read
duration_seconds: 900
session_policy: s3:GetObject on the one object key the tool resolved
session_tags:
  agent: support-reader
  tool: get_object
  request_id: req-7781
trust: runtime role only
retained_after_call: no

The example account is the documentation sample. The session policy is an inline policy on the AssumeRole request, and it can only remove permissions the tool role already has. It cannot grant a new action. That is the property we rely on. The tool role is built narrow, and the session policy is built narrower for the specific key, prefix, or queue URL of this request. A tool role that already has s3:* on * is a poor base. The session policy helps, and the role should still not start from there. Least privilege for AI agents is the standing policy design. Just-in-time access is what happens at call time on top of it.

The allowlist decides which tool may run before any credential is minted. A tool that is not on the list never reaches AssumeRole. MCP tool security and the tool allowlist for SOC 2 are that gate. This article starts after the gate has allowed the call. Minting a broad session and hoping the model behaves is the design we do not ship.

Human time-boxed access in IAM Identity Center is a permission set a person holds for a few hours. The agent assumes a tool role for the call. When a person must approve a sensitive tool, that approval happens before AssumeRole, and the ticket id is a session tag.

What CloudTrail shows, and what the agent must not log

The assumption appears as AssumeRole by the runtime role, with the session name set to the request id. Later data-plane calls appear as the tool role session. The session tags are the join key between the agent log line that says "tool get_object, request req-7781" and the CloudTrail events for that session. We set the session name to the request id for the same reason. A session name of agent reused for every call makes the quarter's logs unreadable.

The agent log stores the request id, the tool name, the role ARN, and the outcome. It does not store the access key, the secret, or the session token. Those values are in memory for the length of the client call. A debug flag that dumps the boto environment is a defect, and we test that the log redaction drops any field that looks like a temporary key. The 15-minute residual window is why redaction matters. A token written to a ticket is a token until the duration ends, and the ticket lives longer.

The runtime role's permission to assume is conditioned on the tag. The caller must pass aws:RequestTag/tool with a value in the allowlist of tools that role may mint, and sts:TagSession is required. A bug that assumes the tool role without the tag fails. A bug that assumes it with a tool name the runtime is not allowed to mint fails. The condition is in the runtime role's identity policy, in Terraform, next to the trust on the tool role. Console changes drift, and the next review catches drift by comparing the policy hash to the last approved review. Agent roles belong in the privileged access population because they can reach production data, even though they reach it for one object at a time.

The task definition has no static access keys, and the only role reachable from instance metadata is the runtime role. On ECS that is the task role. On EC2, IMDSv2 is required. A node role that can already read the data is a standing credential beside the per-call session, so that path comes out before the design is called just-in-time.

What we record for the control

The evidence for a period is the set of tool roles, the trust that names the runtime role, the identity policy that limits AssumeRole by tag, a sample CloudTrail assumption with its session policy hash, and a statement that the task definition has no static keys. The sample is one real request id from the period, with the agent log line beside the CloudTrail events. A design diagram is not the sample. The GRC platform links the export. The export is regenerated from IAM and from CloudTrail, the same way the other evidence jobs work.

A standing key found in the environment fails the collect. The remediation is to remove the key, rotate it if it was used, and confirm the next tool call shows AssumeRole in CloudTrail. We do not accept a compensating control of "the key is in a secret manager" if the process still loads it at startup and keeps it for the life of the task. That is a standing credential with a nicer disk path.

Session length stays at 900 seconds unless the tool role's maximum session duration is lower, in which case AssumeRole fails and we fix the role setting. We do not raise the request toward the role maximum to be safe. Longer sessions widen the residual window after the process has dropped the keys. If a tool genuinely runs longer than 15 minutes, the work belongs in a job that is not an interactive agent turn, with its own role and its own review. Stretching the agent session to an hour so a slow tool can finish is how just-in-time becomes a standing hour-long admin.

Rutagon's deliverable is the split between runtime role and tool role, the AssumeRole call with a session policy and tags, the log redaction, and the evidence that shows a real request id flowing through CloudTrail. The agent's identity is the other article. The credential it holds for a tool call is this one, and it is not a key in the environment.

Frequently Asked Questions

Why is the session 15 minutes if the tool call is shorter?

AssumeRole's minimum DurationSeconds is 900. We set that minimum and we drop the keys from the process when the call returns. The session policy limits the residual window to the one action and resource. We do not raise the duration toward the role maximum to make the call more convenient.

Can the session policy grant extra access?

No. A session policy can only narrow the tool role. The tool role itself is built for one class of read or write, and the session policy pins the resource for this request. If the tool role is s3:* on *, fix the role, because the session policy is not a substitute for that fix.

How do we tie a CloudTrail event to an agent request?

The runtime passes the request id as the role session name and as a session tag, along with the agent id and the tool name. The agent log stores the same request id and omits the temporary keys. The evidence sample is one request id shown in both places.

Where does human approval fit?

Approval happens before AssumeRole, for tools that require it. The session is created after the approval, still at 900 seconds, still with a session policy. The ticket id is a session tag. The agent does not hold a permission set all day in case a person might approve something later.

What if the agent can read instance metadata?

The metadata path should yield only the runtime role, with IMDSv2 required on EC2. The runtime role can assume tool roles and cannot read the data plane itself. A node role that already has the data access is a standing credential, and we remove that path before calling the design just-in-time.

Ask for a credential diagnostic of the keys your agents hold and the role sessions minted per tool call. Contact Rutagon at rutagon.com/contact, 907-841-8407, or contact@rutagon.com.