Technology Aug 23, 2026 · 3 min read

Trusted AI Agent Transactions, Part 3: SPIRE Workload Identity

Binding a logical agent to a real workload with SPIRE Part 2 used a SPIRE JWT-SVID as the actor token in PingFederate token exchange. That proves more than a caller-supplied agent name, but it helps to understand exactly what it proves. A logical agent describes an approved application r...

DE
DEV Community
by DarkEdges
Trusted AI Agent Transactions, Part 3: SPIRE Workload Identity

Binding a logical agent to a real workload with SPIRE

Part 2 used a SPIRE JWT-SVID as the actor token in PingFederate token exchange. That proves more than a caller-supplied agent name, but it helps to understand exactly what it proves.

A logical agent describes an approved application role. A SPIFFE ID identifies an attested running workload. They are related, but they are not interchangeable.

AgentID:  urn:agent:customer-support
SPIFFEID: spiffe://example.org/agent/customer-support

The first is a policy identity. The second is a cryptographically attested runtime identity.

Two SVID formats, two jobs

The implementation uses both SPIRE credential formats:

  • JWT-SVID authenticates the agent to PingFederate during RFC 8693 token exchange
  • X.509-SVID authenticates workload-to-workload connections with mTLS

The JWT-SVID uses an audience dedicated to the PingFederate Transaction Token Service integration. The Txn-Token audience identifies the trust domain in which the call chain is valid. The protected target and tool belong in transaction context and authorization policy. Reusing the actor-token audience for the Txn-Token would blur two distinct trust boundaries.

Immediate caller identity changes at every hop

The transaction token remains unchanged through the request path, but the immediate caller changes:

Agent -> Gateway:     caller is the agent SPIFFE ID
Gateway -> MCP:       caller is the gateway SPIFFE ID
MCP -> Protected API: caller is the MCP server SPIFFE ID

This lets the protected API reject a direct agent call even if the agent possesses a valid transaction token. The API can require the verified transaction context and the expected MCP server identity on the current mTLS connection.

Local development without making lab shortcuts production policy

The Docker lab runs a SPIRE Server and Agent and uses Docker workload attestation. Each workload has a distinct label and registration entry:

wai.workload=demo-agent
wai.workload=mcp-gateway
wai.workload=demo-mcp-server
wai.workload=demo-api

Those selectors produce separate SPIFFE IDs. Mounting the Workload API socket does not let a container choose an identity. SPIRE observes the calling workload and matches its external selectors to a registered entry.

The lab uses a join token to bootstrap the SPIRE Agent. That is explicitly a development choice. A production deployment should use a node attestor appropriate to its environment, such as cloud instance identity, Kubernetes PSAT, X.509 proof of possession, or hardware-backed attestation.

Rotation and ambiguity

SPIRE signing keys can overlap during normal rotation. The integration accepts multiple JWT authorities only when every entry is explicitly a JWT-SVID authority, uses a unique non-empty key ID, and satisfies the configured key and algorithm constraints.

Unknown key IDs, duplicate IDs, unexpected algorithms, ambiguous identities, missing audiences, and conflicting claims fail closed. The token header is never allowed to choose a newly trusted algorithm dynamically.

The binding rule remains the same throughout: a workload cannot become another logical agent by changing request data.

Previous: Using PingFederate token exchange as the delegation boundary

Next: Making policy decisions with PingAuthorize

GitHub Repository: https://github.com/darkedges/pf-tts

DE
Source

This article was originally published by DEV Community and written by DarkEdges.

Read original article on DEV Community
Back to Discover

Reading List