One identity per agent isn't enough
Three signals — who delegated, what's acting, where it's running — should sign together. A practical sketch of composite identity for agent systems.
The default model for agent auth is "give the agent a credential." It works until the second time you ask the question "okay, but who actually did this."
The honest answer involves three different things. Most production deployments only stamp one of them on each request, which is why their audit logs read like riddles.
The three signals
User. Whose intent is this? The user logged into your IdP and asked the agent to do a thing. Their session — their consent — is what gives the agent the right to act at all. Without this, any action the agent takes is the agent's own.
Agent. What software is acting? Not "release-bot" as a label, but a specific, registered, versioned build with a declared capability surface. The build that shipped yesterday and the build that shipped today are different agents.
Workload. Where is it running? The Kubernetes pod, the Lambda invocation, the local dev machine. Provided by the runtime, attested by it. When the runtime dies, this signal dies.
Each signal alone is insufficient. A user session is just consent — it doesn't tell you what's holding it. An agent registration is a category — many copies of the same build are running right now. A workload attestation is a host — many different agents might run on the same one.
Signed together, they're an actor specific enough to authorize, narrow enough to bound, and short-lived enough that revocation is implicit.
Workload identity is the underrated leg of the tripod
The user signal is the one most teams already have — your IdP handles it. The agent signal is something you build — a registry, a version, a manifest. The workload signal is the one people don't think about until they need it.
The good news is the prior art exists. SPIFFE (Secure Production Identity Framework For Everyone) is a CNCF graduated project that defines exactly this: cryptographically-attested workload identity, issued by a local agent that knows what's running because it's running it.
A SPIFFE ID looks like:
spiffe://trust.example/ns/prod/sa/release-bot
The trust domain, then a path that names the workload. The local SPIRE agent attests the workload (it sees the process, checks selectors like UID, container image hash, or Kubernetes service account) and hands it an X.509 certificate or JWT bound to that ID.
If you're building agent infrastructure, the workload-identity question is mostly solved. The tricky part is composing it with user and agent identity into a single principal that policy can evaluate.
What "signed together" actually means
Conceptually, the composite identity is a signed assertion saying "user U, through agent A, on workload W, at time T, for task K." Each leg has its own provenance:
- User comes from the IdP token (the OIDC ID token or its successor in a token-exchange chain).
- Agent comes from your registry, signed at agent build/deploy time.
- Workload comes from the runtime, attested at process start.
A binding service composes them. The result is a short-lived credential (minutes, not hours) that downstream policy treats as one principal. The act claim from RFC 8693 is a useful place to encode the agent leg if you want existing OAuth-aware services to keep working — the chain becomes visible to them, even if they don't understand the full composite.
A small example
The shape, simplified:
const principal = await bind({
user: req.identity, // OIDC ID token from your IdP
agent: {
id: "release-bot",
version: "1.2.0",
digest: "sha256:9c8...",
},
workload: await attest(), // SPIFFE JWT-SVID from local SPIRE
});
// principal carries all three signals. Policy can read any of them.
// downstream tokens issued from `principal` inherit the chain.
bind is the operation that makes the composite real. Once you have a principal, downstream calls — including token exchanges to third-party services — can include the full chain. When something goes wrong, who did this becomes a query against the principal, not a forensics exercise across three log sources.
What you give up
Composite identity is harder to model in your head than a service account. You have to keep three things straight, and you have to instrument three things (IdP, registry, attestation) before you get the benefit. Teams that try to retrofit it onto a fleet of "service-account-shaped" agents have a bad time.
But teams shipping new agents — and most agent fleets in 2026 are still new — have an opportunity here that the service-account era didn't offer. You can describe what an agent is supposed to do, bind it to a real user, and have every tool call answer to a policy that knows all three. The blast radius shrinks. The audit trail gets a lot easier to read.
The bet is straightforward: three signals signed together cost less than one signal everyone has to interpret.
Want to talk to us? Request access or email the team.