Agent identity vs credential identity: stop hiding actors
Agent identity vs credential identity explains how to approve AI agent runs, protect secrets, audit actions, and revoke the right actor.

An AI agent that holds a production credential creates two identity problems at once. The agent can act as the account, and the team later has to pretend that the account name explains who acted. It does not. An API request authenticated as deploy-bot tells you that somebody possessed the credential for deploy-bot. It does not tell you whether the caller was the approved coding agent, a copied shell script, a malicious dependency, or a process left running after a test.
Teams need to identify the process that asked for an action separately from the account authorized to carry it out. This is not audit-log polish. It decides whether you can approve a specific agent run, stop it without disrupting unrelated work, investigate a bad deployment, and contain a leaked credential without guessing.
A credential identifies authority, not the caller
A credential identifies the authority a service will grant, while agent identity identifies the process that requested that authority. Mixing them makes every later security decision too coarse.
Consider a request that deletes an object in cloud storage. The receiving API may see a bearer token and map it to a service account called release-publisher. That account answers an authorization question: may this account delete this object? It does not answer an attribution question: which local process used the token, who started it, what code did it run, and did anyone approve that run?
Those questions sound similar during calm periods because the expected process and the account often have the same owner. They diverge under pressure. A developer copies the token into a local environment. A code agent inherits that environment. A plugin launched by the agent reads it. Every request still appears as release-publisher. The authorization layer works exactly as configured while the investigation loses the actor.
Credential identity usually has a long life and a broad purpose. It may be an API token, an SSH private credential, a cloud service account, or a client certificate subject. Process identity should describe a much narrower thing: this executable, from this signer or image, launched in this context, during this run.
The distinction has a practical consequence:
- Revoke a process session when one agent run becomes untrusted.
- Disable or rotate a credential when its secret may have escaped.
- Change account permissions when the authority itself was excessive.
- Investigate the process record when you need to know what actually happened.
If one field has to do all four jobs, it will do none of them well. Calling a credential agent-prod-42 does not solve this. A better label does not turn a bearer token into evidence of the bearer.
Four identities appear in one agent request
A production action normally has at least four identities, and an audit record should preserve all of them instead of flattening them into an account name.
First, there is the human or system owner who initiated the work. That might be a developer at a terminal, a CI job trigger, or a scheduled task. Ownership answers who requested that the agent run and who should receive alerts.
Second, there is the agent process. For a local coding agent, useful evidence can include its executable path, signing authority, process identifier, parent process, launch time, and a random session identifier issued at launch. In a container environment, the equivalent evidence may include an image digest, workload identity document, orchestrator workload name, and pod or task instance. This identity answers which running program asked to perform an action.
Third, there is the credential identity. This is the service account, SSH principal, OAuth client, or API token record that the destination accepts. It answers what the destination will permit.
Fourth, there is the target identity: the hostname, repository, cloud project, database, or API audience affected by the request. Teams often log a generic endpoint and then discover that the action crossed an environment boundary they never meant to grant.
A clean record can read like this:
{
"event": "http.request",
"session_id": "ses_7zQ2...",
"process": {
"pid": 8421,
"signing_authority": "Example Developer ID",
"parent_pid": 8190,
"launch": "interactive-terminal"
},
"credential_ref": "cred_release_publisher",
"credential_subject": "release-publisher",
"target": "api.example.internal",
"operation": "POST /releases",
"decision": "approved",
"result": 201
}
The credential_ref points to a vault record. It is not the secret. The process block provides the evidence that the credential subject cannot. A reviewer can now see that one approved session used release-publisher against one target, and can distinguish that run from another process using the same account later.
Do not overload the human owner field either. A person who asked an agent to update documentation is not automatically the person who approved a production deployment that the agent later attempted. Keep initiation, process, credential, and destination separate. The uncomfortable gaps become visible, which is the point.
Bearer tokens erase the evidence you need most
A bearer token is accepted because the caller has it, so it cannot establish which process is presenting it. This is a property of the mechanism, not a logging defect at your API provider.
RFC 6750 defines bearer token usage directly: any party in possession of the token can use it. That portability made bearer tokens easy to deploy, and it also means an API cannot distinguish the approved agent from a copied process unless you add a separate control. The common response, "we put the token in a secret manager," addresses storage at rest. It does not address what happens after a process receives the value.
The OAuth 2.0 Security Best Current Practice, RFC 9700, pushes in the right direction by recommending sender-constrained access tokens where appropriate, plus short lifetimes and audience restriction. Sender constraint can reduce token replay because the resource server checks proof from the intended client. It does not remove the need to identify the process that controls that client proof. If an agent process can use the private proof material, an attacker controlling that process can still act as the client.
That distinction matters for AI agents because their operating environment is unusually porous. They read repositories, execute commands, call tools, inspect environment variables, and sometimes act on instructions supplied in files or issue comments. A token exposed to the agent does not stay in one clean trust boundary merely because the team intended it for one tool call.
Avoid the popular recommendation to give each agent a dedicated long-lived token and call the problem solved. It is popular because it produces tidy account names and easy dashboards. It fails when the agent can read the token, when a different process can read the same environment, or when the account persists after the agent run ends. Dedicated credentials improve blast-radius accounting, but they do not prove process provenance.
You need two controls: prevent the agent from receiving reusable secret material, and preserve a separate record of the agent process that requested each action. The first limits theft. The second makes approval, revocation, and investigation specific enough to be useful.
Process identity needs evidence that survives a prompt
A process identity should come from facts the operating system or execution environment can report, not from a string the agent supplies in a tool request. An agent declaring name: trusted-release-agent has made a claim, not presented identity evidence.
On a managed Mac, code signing authority gives you a useful starting point. The operating system can tell a supervising app which signed executable launched and which authority signed it. That does not mean every signed program deserves approval. It means an approval screen can show a fact that is harder to forge than a process-provided label.
On a server, look for equivalent evidence. A workload identity issued by the runtime, a verified image digest, a mutually authenticated channel, or a process supervisor's attestation can bind an action to a workload instance. SPIFFE documents this model with the SPIFFE Verifiable Identity Document and X.509 SVIDs: the workload receives an identity from its environment, then presents it to another workload. That model is stronger than a shared environment variable because the identity is scoped to a workload.
Do not mistake a static image digest for a complete process identity. It identifies code content, but a useful action decision still needs the running instance and launch context. The same image can execute in the intended production job, a developer's experimental environment, or an attacker-controlled task. The destination and session remain part of the decision.
For local agent work, capture evidence at session creation, then bind subsequent actions to that session. A minimal session record could include:
session_id: ses_7zQ2...
executable: /Applications/Agent.app/Contents/MacOS/agent
signing_authority: Example Developer ID
parent_process: /Applications/Terminal.app
started_at: 2025-03-08T14:03:19Z
owner: [email protected]
The exact fields vary by operating system. The discipline does not: the component that authorizes an action should collect process facts itself. It should not trust the agent to describe itself accurately after the agent has already received untrusted input.
Process identity also has limits. Code signing does not prove that a signed agent followed safe instructions. An image digest does not prove that its configuration is safe. Identity tells you which actor you approved and gives you a revocation handle. It cannot make a risky requested action safe by itself.
Approval must bind to a run, not an account name
A human approval should authorize a specific process session for a bounded period, not permanently bless whichever process later uses an account. Otherwise approval becomes a disguised grant of standing access.
Approval fatigue usually begins with the wrong unit of approval. Teams either ask a person to approve every harmless request, which trains them to click through, or they approve a service account once and never see a meaningful prompt again. Neither choice identifies the active process.
Use a session approval when an agent begins a run. Show the process evidence that an operator can evaluate: executable or workload name, signing authority or image digest, parent or launcher, intended channels, and a session identifier. Once approved, permit actions through that session until the process exits or the operator revokes it. A new process must request a new session, even if it plans to use the same credential.
Reserve per-action approval for credentials whose impact warrants interruption. A production database administrator credential, an SSH identity that can reach fleet hosts, or an account that can publish public artifacts may need a human decision each time. Ordinary read access does not. The approval mechanism should make that difference explicit rather than bury it in a giant policy file nobody reviews.
This layout gives you containment options that shared access cannot provide. If an agent starts behaving badly, revoke its session. The credential remains available to a separate approved release process. If you suspect secret exposure, disable the credential as well and inspect every session that referenced it.
Sallyport uses this split directly: a new agent process receives a per-session authorization by default, while credentials stay in its encrypted vault and actions run outside the agent process. Its session prompt leads with the process's code-signing authority, which is the evidence an approver needs before allowing a run.
The approval record should include both the process session and the credential reference used later. Do not show the credential value in the prompt or return it in an action result. A system that hides a token in the UI but puts it in an agent tool response has still handed the agent the token.
Credential injection keeps secrets out of the agent's reach
The agent should request an action by naming a credential reference and target, while a trusted executor injects the secret only at the moment it makes the HTTP or SSH call. The agent receives the result, not the reusable credential.
This is a much sharper boundary than putting a token in a shell environment and asking the agent not to print it. Environment variables leak into child processes, debug output, crash reports, command history wrappers, and tool calls. Redaction helps with accidental display after the fact; it cannot retrieve a secret from a process that already read it.
A safe action request has enough detail to authorize and execute the call without containing the credential itself:
{
"session_id": "ses_7zQ2...",
"credential_ref": "cred_release_publisher",
"channel": "http",
"request": {
"method": "POST",
"url": "https://api.example.internal/releases",
"headers": {"Content-Type": "application/json"},
"body": {"version": "1.4.2"}
}
}
The executor checks that the session remains approved, confirms that the vault is available, fetches cred_release_publisher, injects it in the required authorization header, performs the request, and records the decision and result. It should return the response data needed for the agent's task, after applying any ordinary handling required for sensitive response content.
The same principle applies to SSH. The agent may request git fetch or a remote command through an SSH channel, but it should not receive the private credential as a PEM block or an agent socket that any child process can use without supervision. The executor can use the private credential for the connection and bind the event to the agent session.
Sallyport currently supports HTTP credential injection and SSH actions through its bundled helper, so an MCP-capable agent can request the work without holding the API or SSH secret. That design does not make every action safe. It preserves the separation needed to decide whether the process should be allowed to request it.
A shared deployment token hides the failure until it matters
A shared credential turns a straightforward incident into a reconstruction exercise because the same account name appears in every relevant log line. The failure often begins with a sensible shortcut.
Imagine a team that keeps PUBLISH_TOKEN in a CI secret store. Their deployment job reads it, which is expected. A developer also exports it locally to reproduce a release problem. Later, they start a coding agent in that shell because the agent needs to inspect the deployment scripts. The agent can now call the release API through its environment.
An instruction hidden in a repository file tells the agent to run a command that uploads a draft release. The command succeeds. The API audit record says release-publisher created release 1.4.2. The CI log shows no matching job. The developer says they only asked the agent to inspect files. Everyone can agree on those facts, yet none identifies the process that made the call.
A team often responds by rotating PUBLISH_TOKEN. That stops replay if the token leaked, but it also breaks the legitimate CI job and forces rushed repair. The team may then blame the developer, the agent, or the repository instruction without evidence. The account name gives them no way to distinguish a CI invocation from a local agent action.
Now change the design. The release credential stays in a vault controlled by an action executor. The agent launches a session that records its signing authority and parent terminal. It requests the upload action through that session. The executor records an approval decision, the credential reference, target API, request path, and response status.
When the suspicious upload occurs, the incident record answers the first useful questions immediately: it came from a local agent session, that session began from a particular terminal, it received authorization at a specific time, and it used the release credential for one POST request. The operator revokes that session. CI continues because its separately identified process has not been revoked. If the repository instruction might have exposed broader secrets, the team can still rotate the credential, but they do so because evidence supports it rather than because they lack any other control.
The difference is not perfect prevention. An approved agent can still request an action a human later regrets approving. The difference is that the system preserves an actor, an authorization decision, and a targeted stop mechanism. That is enough to shorten an incident rather than turn it into an argument.
Audit records must join identities without storing secrets
An audit trail should let you connect a process session, a credential reference, and an external action while keeping secret material out of the record. If those data live in separate products with no common event identifier, incident response becomes manual correlation under time pressure.
Write one event for the session decision and one event for each action. Give both the same session_id; give each action its own event identifier. Store a credential reference and credential subject if that subject is safe to retain, but never store the bearer token, private credential, or raw authorization header.
A useful action record includes the normalized target, method or remote command, request digest when bodies may contain sensitive data, decision, response status, and timestamps. For SSH, record the host, remote user, requested command, and exit result. For HTTP, record the method, host, path, and status. Capture the raw body only when your retention and data handling rules allow it.
Tamper evidence matters because the process that performs an action may later be accused of hiding it. A hash chain makes removal or rearrangement detectable when an investigator has the full sequence. It does not make an event truthful. If your collector accepts an agent-provided process name, a perfectly chained log preserves that false claim forever. Collect identity evidence at the supervising boundary first, then protect the record.
A simple verification process should work independently of the vault contents. The verifier reads each encrypted event blob, checks that its stored previous hash matches the prior event hash, recomputes the current hash, and reports the first broken position. The output should identify the sequence position without exposing secrets:
$ audit verify events.log
verified: 184 events
chain: valid
first_event: evt_01J...
last_event: evt_01K...
If verification fails, preserve the original files before attempting repair. A missing record can mean corruption, an interrupted write, bad export handling, or deliberate alteration. The chain identifies inconsistency; your surrounding logs and storage controls explain the cause.
Separate identities before you add more automation
Teams can adopt this model without rebuilding every API integration. Start with the credentials that can alter production state, publish artifacts, access customer data, or connect over SSH. Those are the accounts that create the hardest incidents when an agent process inherits them.
Make the first pass concrete:
- List each credential subject, the services it can reach, and every process that currently receives its secret.
- Remove reusable secret values from agent prompts, agent configuration, and agent process environments.
- Define the process evidence you can collect at the point where actions are authorized.
- Issue a session identifier for every agent run and log it beside the credential reference for each action.
- Test containment by revoking one session while another approved workload continues to use the same account.
That last test exposes the common mistake quickly. If you can only stop an agent by disabling the shared account, you have not separated agent identity from credential identity. You have assigned a friendly name to a shared risk.
Do not begin with a sprawling rules engine. Most teams need a few clear decisions: is the vault available, is this process session approved, and does this credential require approval for this action? The more complex part is operational discipline: stop sending secrets into agent processes, collect trustworthy process evidence, and refuse to treat a service account name as a person or program.
When the next questionable action appears, demand an answer to two separate questions: which process requested this, and which authority executed it? If your records cannot answer both, fix that before you grant another agent production access.
FAQ
What is the difference between process identity and credential identity?
A process identity describes the running program that originated a request, such as a signed executable, its launch context, and its session. A credential identity describes the account or service principal authorized to perform the action. One process can use several credentials, and many processes can misuse the same credential.
Can an API token identify the agent that made a request?
No. A credential proves that a caller possessed a secret or token, not which program obtained or presented it. If several jobs, developers, or agents share that credential, the credential record collapses all of them into one indistinguishable actor.
Should every AI agent get its own credential?
Use a distinct credential when two workloads need different permissions, billing ownership, or revocation boundaries. Still record the calling process separately, because separate credentials do not prove which executable ran. A stolen workload-specific token remains usable by another process until you bind it to a verified caller or action gateway.
Is a service account the same as an agent identity?
A service account is an authorization subject. It may be used by a deployment job, a human-operated script, an agent, or several of those if the team permits it. Treating its name as the caller's identity makes incident reviews misleading.
What should an agent action audit log contain?
Record a stable process identifier, signing authority or image digest, parent process, launch method, host or execution environment, session identifier, requested action, target, credential reference, decision, and result. Avoid putting secret material in the log. A usable record lets an investigator answer who launched the process, what it tried, and what authority executed the request.
How do I prevent an AI coding agent from reading API credentials?
Give the process a short-lived session authorization and bind its actions to that session. Keep credentials in a separate store or execution component, then log the association between the process session and the credential reference. Do not pass a long-lived secret into the agent prompt, environment, or tool response.
Why is revoking an agent session different from rotating a credential?
A credential can keep working while the original agent session has ended, changed code, or been replaced by an untrusted process. Revoking the session stops the known caller; rotating or disabling the credential stops all callers that hold it. Those are different containment actions, and teams need both.
Is it safe for multiple agents to use one production credential?
Only when the shared account has narrow permissions, the callers operate under the same owner and review path, and the audit trail identifies each caller independently. Shared production credentials across unrelated agents or teams create a blame-free zone during failures. The convenience rarely survives the first serious investigation.
How do I evaluate an agent credential architecture?
Ask who can obtain the secret, whether the secret enters the agent process or its environment, whether each new process needs approval, and whether logs identify the process separately from the account. Also ask whether you can revoke one running agent without taking down every workload that shares its credential. If the answer depends only on a token name, the design is weak.
Can human approval replace credential isolation?
No. An approval can authorize a process session to request actions without revealing the credential that executes them. The approval should show evidence about the process, such as its signing authority and launch context, then expire when that process exits.