Per-session vs per-call approval for agent actions
Choose per-session vs per-call approval for AI agents by weighing task duration, credential scope, repeat damage, data exposure, and rollback.

An AI agent does not need unrestricted access to become useful. It needs enough authority for the current job, for a period you can explain, with a human decision placed where another call would change the risk. That is the practical difference between per-session and per-call approval.
I have seen teams make two opposite mistakes. One approves every harmless lookup and teaches people to click through warnings without reading them. The other grants a long-lived session to a coding agent, then acts surprised when a loop creates fifty tickets, triggers several deployments, or exports far more data than anyone intended. Neither failure comes from an exotic exploit. Both come from putting the approval boundary in the wrong place.
The primary keyword phrase, per-session vs per-call approval, describes a choice that needs three inputs: how long the work runs, how much authority the credential carries, and what a repeated valid request can do. The HTTP verb, the agent's claimed plan, and the fact that a developer is watching are weaker signals than those three.
Approval is a permission to act within a defined boundary
Per-session approval grants an identified agent process authority to use a credential for the life of that run. Per-call approval asks for a decision every time that credential is used. They answer different questions, and treating them as interchangeable creates either blind trust or useless friction.
A session decision says: "I recognize this process, I accept this narrow run, and the actions available through this credential are safe enough to repeat during that run." That is a reasonable decision for an agent checking a few issue records while it investigates a bug. It is a poor decision for an agent that can make production changes whenever its own reasoning decides another mutation would help.
A call decision says: "I accept this exact use of this credential now." It is slower by design. The prompt should represent a point where a person can recognize the consequence and decline it without losing the entire task. If the prompt does not convey a meaningful choice, the approval design is wrong. If it appears before an irreversible action, the extra second is usually cheap.
Do not confuse this with authentication. Authentication tells the local system who can unlock the credential store. Authorization answers whether an agent run may use a specific credential. Per-call control adds a third question: whether this use, at this moment, deserves a fresh human decision.
That distinction matters during an ordinary coding task. An agent may use one API token to read build status and another to trigger a release. The same process can be trustworthy enough to inspect the first and still need an explicit decision for the second. Process identity does not flatten the risk of every endpoint it can reach.
A useful approval boundary has four properties:
- A person can say what work the agent is doing.
- The credential scope matches that work rather than the agent's entire possible job list.
- The approval ends when the work or its identified process ends.
- The person can describe the worst plausible result if the agent repeats an allowed action.
The fourth property catches more bad designs than most checklists. If the answer is "it would make another harmless request," session approval may fit. If the answer includes money, customer communication, production state, deletion, access changes, or a large export, keep a human decision close to each action.
Task duration changes how much a session promise means
A session is safest when it is short, bounded by a single task, and tied to one process that exits when the task finishes. A session that quietly survives unrelated work is a standing permission with a friendlier name.
Duration affects risk because an agent does not stop reasoning after it completes its first intended action. It may retry, pursue a newly discovered subtask, inspect another repository, or follow a bad instruction retrieved from a file or ticket. The longer the process lives, the less useful your original mental model becomes. A ten-minute run to inspect failing tests has a comprehensible purpose. A process running all afternoon has accumulated context, changed goals, and more opportunities to encounter hostile or misleading input.
Use the task boundary rather than a clock whenever possible. Process exit is an honest end condition: the approved agent is gone. A fixed timeout is a fallback, not an equivalent control. At the fifteen-minute mark, an agent may still be running the original work, or a different tool may have inherited the same authority. Time alone cannot tell you which.
For a bounded session, write down the unit of work before you approve it. A good description is concrete: "inspect the failing continuous-integration run and open a draft comment with findings." A poor description is "help with the release." Broad language gives the agent room to transform a small diagnostic job into release work.
Consider these task shapes:
| Task shape | Session approval fit | Why |
|---|---|---|
| Read a defined set of build logs during one agent run | Usually good | The process exits, the data set is bounded, and the operation should not change remote state. |
| Search internal documentation while preparing a patch | Often good | The credential can be narrow and the expected operations are repetitive reads. |
| Triage a production alert | Conditional | Read access may use a session; any mutating recovery action needs its own decision. |
| Run a migration | Usually poor | The agent may issue many state-changing requests, and retries can create a second migration path. |
| Manage a shared inbox or customer account | Poor | Each send, edit, or export can create an external commitment or expose private information. |
The popular shortcut is to approve a session for every task because people hate interruptions. The complaint is legitimate when prompts fire on low-consequence calls. The fix is to reduce prompts by narrowing credentials and grouping routine work into real sessions, not by turning a long agent run into an all-access window.
Agent restarts deserve the same caution. A restart may look like continuity to a person who launched the command, but it is a new process and may load different instructions, code, or plugins. Ask for new session authorization after a restart. This is not bureaucracy. The original decision attached to a specific executable authority and run, not to the developer's vague intention for the afternoon.
Credential sensitivity starts with capability, not secret type
A credential is sensitive because of what it can cause, reveal, or delegate, not because it has a particular name. An API key used only to read one public build artifact can be less dangerous than a token that invites administrators to a private workspace. An SSH key that reaches a deployment host has a different failure mode from a token that calls a billing API, but both may need per-call control.
Classify each credential against the remote system's actual permissions. Do not accept a label such as "read token" without checking what the API regards as a read. Some services expose export endpoints as reads. Others allow a supposedly read-only endpoint to start report generation, consume scarce capacity, or return data that the agent should never see in bulk.
I use four questions before choosing an approval level:
- Can this credential change state outside the local machine?
- Can it reveal information that cannot be safely placed in the agent's context or output?
- Can it grant more access, directly or through a workflow it can trigger?
- Can a caller spend money, consume a quota, or create a contractual or reputational commitment?
A yes to any question does not always force per-call approval. It does mean that session approval needs a narrower task, tighter scope, and a plausible rollback. If several answers are yes, asking every time is usually the honest choice.
Use scope as the first reduction, approval as the second. A token that can only read a single repository gives you a much better session decision than a token that reads every repository in the organization. A credential limited to one staging environment is safer to hand to a session than a credential that can operate production. Human approval cannot repair an absurdly broad token after the agent already has the authority to make expensive requests.
SSH deserves special treatment because people routinely call it "just shell access." Shell access is a transport into a large and changing action surface. The actual risk depends on the account, host, network reachability, available commands, deployment hooks, and files the account can read. A restricted account that can run one diagnostic command may fit a session. A deployment account, a host with customer data, or an account that can alter access controls should sit behind per-call approval until you can narrow it.
Do not let credential rotation hide this analysis. A freshly minted key with broad production rights remains broad production rights. Rotating it after a bad run limits future abuse; it does not reverse the remote calls that already succeeded.
Repetition turns a tolerable action into a costly one
A request can be individually acceptable and still become unsafe when an agent repeats it. Classify the repeated action, not only the first action shown in a prompt.
This is where teams lean too heavily on HTTP method names. RFC 9110 says that safe methods are intended to be read-only: GET, HEAD, OPTIONS, and TRACE. It also warns that a client cannot be held accountable when a server exposes unsafe behavior through a safe method, because the resource owner chooses that behavior. That wording matters. A GET endpoint may be semantically intended to retrieve information, yet the application can make it expensive, expose a massive export, update an audit field, or trigger downstream work. Method names help you start an investigation. They do not complete it.
Idempotence is another term people misuse. A request is idempotent when repeating it has the same intended effect on server state as making it once. It does not mean repeating it is harmless. A PUT request that sets a flag to true may be idempotent but still activate a production feature. A DELETE may be idempotent after the first deletion but still remove something that mattered. A GET may be safe in the protocol sense and still exhaust a rate limit when an agent loops.
Test an endpoint's repeat behavior in a disposable account or staging environment. Send the same request twice, inspect both remote state and side effects, then ask what happens if the agent sends it a hundred times. Do not stop at the response body. Check messages sent, jobs queued, audit records created, quota consumed, webhooks fired, and any data copied elsewhere.
For an endpoint that creates objects, use an idempotency key if the service supports it. This request shape prevents a network retry from creating a second payment, ticket, or provisioning request when the first response gets lost:
POST /v1/provisioning-requests HTTP/1.1
Authorization: Bearer injected-by-gateway
Idempotency-Key: agent-run-8b2f1-request-17
Content-Type: application/json
{"environment":"staging","version":"2025.04.18"}
A service should return the original result when it receives the same idempotency key again. The response often has the same object identifier and a success status rather than a new object. Confirm that behavior in the service's documentation and test it yourself. An idempotency key reduces duplicate creation from retries; it does not make an inappropriate deployment appropriate, and it does not prevent an agent from generating a new key for each misguided attempt.
Per-call approval fits actions with any of these repeat profiles:
- Each call creates a new thing, such as an invoice, account, ticket, message, or order.
- Each call changes live state and the previous state is hard to reconstruct.
- Each call can disclose another page, another archive, or another customer's data.
- Each call can create a public or customer-facing effect.
- Each call can trigger work that costs money or occupies limited capacity.
A session fits repeated calls when the remote side treats repeats as low consequence, the credential's scope is small, and the task has a clear exit. The burden is on the team to establish that claim. "The agent probably will not loop" is not a property of the endpoint.
A read-only label does not settle the risk
Read access can create privacy, operational, and prompt-injection risk even when it cannot mutate a remote record. Treat data exposure as an action with consequences, especially when the agent can summarize, copy, or use what it retrieved to decide its next move.
Suppose an agent has permission to search a support system. A session may be reasonable for a task restricted to one ticket and its attachments. The same credential becomes much harder to approve for a run that can enumerate every ticket, retrieve exports, or pull private customer conversations into a local context. The endpoint may use GET throughout. The data boundary, not the verb, defines the risk.
The awkward question is whether the agent itself is allowed to see the returned result. A credential gateway that keeps tokens out of the agent does not automatically make every result safe to return. Secrets often leak through responses: configuration endpoints return connection strings, user records include personal data, command output includes environment variables, and error responses expose internal paths or identifiers.
Choose per-call approval for a read when any one result can reveal a sensitive class of information or when the agent's request can expand its own search space. This includes broad search, exports, secret retrieval, account enumeration, and commands such as cat over directories whose contents vary. A person needs the chance to see the target before releasing that data into the run.
For routine reads, constrain the request shape. Prefer a credential limited to a project, a repository, an environment, or an API resource group. Set server-side page limits where the service offers them. Give the agent a query mechanism that accepts explicit identifiers rather than an unrestricted search endpoint when possible. These choices reduce the number of approval prompts because the allowed call itself is smaller.
A failure pattern appears in incident response. An agent starts with a harmless request to inspect logs, finds a token in a log line, then searches for every occurrence of that token across a broad archive. The original session approval covered troubleshooting in a human's mind, but the credential scope and query shape allowed collection. The operator sees no mutation in the activity list and assumes the run was safe. The sensitive act was retrieval.
Keep a separate record of what was requested, what credential was used, and whether the call was approved as a session action or a per-call action. That record helps an investigator distinguish a compromised agent from a poor approval choice. It also exposes the credentials that need less scope. Logging only successful mutations leaves the hardest retrieval failures invisible.
Make prompts correspond to decisions a person can actually make
Approval fatigue is a design failure when prompts arrive too often to be read or too vaguely to be judged. Per-call approval works only when each prompt tells the reviewer enough to accept or reject a concrete consequence.
A useful prompt identifies the calling process, the credential or action category, the destination, and the material effect. "Allow API request" does not let anyone make a good decision. "Signed agent process requests production deployment using the release credential" does. For a sensitive read, the prompt should name the data set or target rather than merely saying "GET request." For SSH, show the host and the command or a meaningful command class.
Do not solve prompt overload by hiding the destination. A developer who approves a request based on a friendly task name cannot detect a typo, a malicious instruction, or an agent that changed course. The prompt needs enough specificity to catch a mismatch between intended work and actual action.
At the same time, do not demand that people parse a raw HTTP body for each routine request. That produces ceremonial approvals. Put repeated, low-impact calls inside a bounded session and reserve per-call prompts for the operations that cross a real decision boundary. The person should see fewer prompts, but each remaining prompt should matter.
Use a short approval note beside each credential configuration. It is not a policy language and does not need to become one. A sentence such as "session only for one repository's build-status reads; approve each production release" makes later reviews concrete. If a team cannot write a sentence that separates ordinary work from a consequential action, the credential is probably too broad.
The process identity shown at session authorization also deserves attention. Humans should approve the executable authority, not only a command line that can be copied or altered. A signed parent process and an unsigned helper are different trust decisions. The right response to an unfamiliar authority is to stop the run, identify why it changed, and approve it only if the change is expected. Clicking because the task is urgent trains the organization to accept an impersonation path.
Use a decision matrix before you flip the approval setting
A small matrix prevents arguments based on personal tolerance for prompts. Score the action according to consequence, then choose the stricter level whenever the score points in two directions.
| Question | Favors per-session approval | Favors per-call approval |
|---|---|---|
| How long will this run live? | One bounded task, ending with process exit | Long running, restarted, scheduled, or loosely defined work |
| What can the credential reach? | One narrow project or environment | Production, many tenants, privileged accounts, or broad exports |
| What does one request do? | Retrieves limited routine information or makes a reversible low-impact update | Sends, deletes, publishes, provisions, deploys, changes access, or transfers value |
| What does repetition do? | Repeats have little consequence and server controls duplicate effects | Each call adds cost, creates another object, or widens disclosure |
| Can an operator undo it? | A clear rollback exists and data loss is unlikely | Rollback is partial, expensive, or impossible |
When the table gives mixed answers, separate the workflow instead of splitting the difference. Give the agent a session-approved credential for diagnostics and a per-call credential for remediation. That arrangement often feels more natural than repeatedly approving reads or granting a broad session to avoid approvals on mutations.
Here is a worked example. An agent investigates a failed deployment. It needs to read build logs, retrieve the status of a specific staging environment, and possibly restart one service.
The logs and status calls can run under session approval if the token reaches only that project and the process will exit after diagnosis. The restart should use a different credential with per-call approval because it changes running state. Even if restarting the service is usually safe, repeated restarts can interrupt active work, conceal a root cause, and trigger automatic recovery loops. The fact that the agent discovered the restart as a sensible fix does not make it routine.
Now change one detail: the status API can query every production environment, and log retrieval can fetch unredacted customer payloads. Session approval no longer fits the diagnostic credential. The team should narrow that access first. Moving the same broad credential behind per-call approval limits one kind of failure, but a reviewer cannot reliably evaluate every retrieval request if the data selector remains unconstrained.
This is why a single setting per agent is a bad model. Approval belongs to the action channel and credential scope. One agent run can safely combine both levels if you draw the boundaries deliberately.
Audit trails explain a bad decision but cannot reverse it
A tamper-evident record lets you investigate an agent run, revoke an active session, and establish whether the agent repeated an action. It does not stop a remote service from accepting a call that you already approved.
Keep two views of activity. A session record answers who ran, when the run began, what process authority it had, and whether someone revoked it. A call record answers which credential path the agent used, what destination it contacted, and whether the call had a session authorization or a fresh approval. Teams need both. A list of sessions cannot prove which action caused a problem, while a pile of calls without process context cannot explain who initiated them.
Make audit integrity testable rather than a slogan. A hash-chained log should fail verification if someone changes, removes, or reorders records in the stored sequence. The test is simple: verify a known-good copy, alter one byte in a copy, then verify again. The verifier should report that the chain no longer validates, while the original still verifies. Do this in a test fixture, never by editing your production audit store.
Sallyport projects its Sessions and Activity journals from a write-blind encrypted, hash-chained audit log, and sp audit verify checks that chain offline over ciphertext without needing a vault key. That separation is useful when the person checking records should not receive the credentials or action payloads that the vault protects.
Logs also expose a common approval mistake: treating a session as an excuse to stop looking. Review runs that used unusually many calls, contacted a new destination, ran far longer than their task description, or used a credential outside its usual category. You do not need a rules engine to spot those patterns. A weekly human review of a small sample will catch scope creep before it becomes a normal operating habit.
When an agent acts badly, preserve the process identity, task input, session record, call sequence, and remote service logs before changing the configuration. Then ask a narrower question than "was the agent compromised?" Was the action allowed by credential scope? Did the approval level fit the repeat risk? Did the prompt provide enough information to reject it? Did the process change after authorization? Those answers lead to fixes. A generic ban on autonomy does not.
A narrow start beats a broad exception
Begin with one workflow whose impact you can describe without hand-waving, then assign per-call approval to the credential that can cause the most harm. Watch several real runs before moving the routine portion into a bounded session.
For a Mac-based agent setup, Sallyport keeps API and SSH credentials in its encrypted vault and executes the action rather than passing the secret into the agent. That reduces credential exposure, but you still must choose the approval boundary with the same care because the remote action remains real.
The first configuration should make a developer mildly impatient, not blind. If every run produces a stack of prompts for build-status reads, the scope or task grouping needs work. If an agent can alter production for an hour after one approval, the session is too broad. Adjust the credential and task boundary before you tune the human out of the loop.
Write the next approval choice in operational terms: this signed process, for this task, may make these low-impact calls until it exits; this other credential requires a fresh decision because each use can alter something we cannot casually undo. That sentence gives reviewers a standard they can apply under pressure. Anything vaguer will eventually turn into a permanent exception.
FAQ
When should I use per-session approval instead of per-call approval for an AI agent?
Use per-session approval when one identifiable agent process will perform a bounded run of routine, reversible actions and the credential has a narrow scope. Use per-call approval when each use can create an external commitment, disclose sensitive data, or cause damage if repeated. The deciding factor is the consequence of another valid call, not how annoying the prompt feels.
Is per-session approval safe for autonomous coding agents?
No. A session approval verifies that you accept a particular process and its bounded period of work; it does not make every action inside that process equally safe. A read request and a production deletion can share a process while requiring very different human oversight.
Which credentials should require approval every time?
Put credentials that can transfer money, change production state, delete records, publish messages, expose private data, or broaden permissions behind per-call approval. A narrow read-only credential may fit session approval if the task is short and the receiving system cannot turn reads into costly work. Scope still matters more than the credential's label.
How do repeated agent actions increase risk?
Repeated calls multiply damage when the operation is non-idempotent, irreversible, expensive, externally visible, or sensitive to timing. Examples include creating invoices, inviting users, triggering deployments, sending email, and repeatedly querying metered endpoints. Test the endpoint's behavior with the same request twice before you choose an approval level.
Are GET requests safe enough for session approval?
A read method is only a useful clue, not proof of safety. RFC 9110 defines GET as safe in intent, but an application can still log sensitive data, generate a costly report, or implement a GET endpoint with side effects. Classify the endpoint by what the service actually does and what it returns.
Does per-call approval make incident response too slow?
Per-call approval can work during an incident when each prompt controls a meaningful boundary, such as each production mutation or credential use. Operators should prepare narrow emergency credentials and a short rollback plan before the pressure starts. Do not approve a broad session merely because the queue is long.
What should I do when an agent starts from a new process?
Treat a new process identity as a new session until you have confirmed why it changed. Rebuilds, wrappers, copied binaries, and a changed signing authority all alter the trust question. Approving the old process does not automatically justify the new one.
Should agent approvals expire after a fixed time?
A timeout helps, but it is weaker than tying approval to process exit. Time does not tell you whether the original agent is still the only actor using the authority. End a session when the run ends and require a fresh decision for the next run.
Can audit logs replace approval prompts for AI agents?
Audit logs help you reconstruct what happened and revoke a session that is still active, but they do not undo a request that already reached a remote service. Use logs to investigate scope failures and refine future approvals. Preventive approval remains necessary for actions with immediate impact.
How can I roll out approval controls without blocking developers?
Start by putting a single credential with clear, high-impact consequences behind per-call approval and observe the workflow for several real runs. Then move only the repetitive, reversible portion of that workflow to session approval. If you cannot state the rollback and maximum repeat damage in one sentence, keep the stricter setting.