Skip to main content
Most Kubernetes identity systems give you one identity per pod. Hexr goes further: every agent process gets its own unique SPIFFE ID. If you’re running a multi-agent framework like CrewAI or LangChain with multiple sub-agents in one container, each role — researcher, writer, editor — gets its own cryptographic identity. This distinction is what makes per-role access control, per-agent cost tracking, and precise audit logs possible.

Why per-process identity matters

Standard Kubernetes identity

One identity per pod.
Pod: content-crew
└── spiffe://…/pod/content-crew
    └── Who called GPT-4? 🤷
No visibility into which sub-agent made which call. Cost attribution is impossible. Access control is all-or-nothing at the pod level.

Hexr per-process identity

One identity per agent process.
Pod: content-crew
├── spiffe://…/researcher  → 1,200 tokens
├── spiffe://…/writer      → 3,400 tokens
└── spiffe://…/editor      →   800 tokens
Per-role access control, cost tracking, and audit logs — all from a single pod.

SPIFFE ID format

Every agent process receives a SPIFFE ID following this pattern:
spiffe://{trust-domain}/agent/{tenant}/{agent-name}/{process-role}
ComponentDescriptionExample
trust-domainYour SPIRE trust domainhexr.cloud
tenantYour tenant namespaceacme-corp
agent-nameFrom @hexr_agent(name=...)content-crew
process-roleSub-agent role within the agentresearcher
Examples for a multi-role agent:
spiffe://hexr.cloud/agent/acme-corp/research-analyst/main
spiffe://hexr.cloud/agent/acme-corp/content-crew/researcher
spiffe://hexr.cloud/agent/acme-corp/content-crew/writer
spiffe://hexr.cloud/agent/acme-corp/content-crew/editor

How it works

The identity lifecycle runs in four stages — most of which happen automatically.

Stage 1: Build-time discovery

hexr build performs AST analysis on your Python source to discover every agent role before any code runs:
$ hexr build content_crew.py --tenant acme-corp
Discovered agents:
  content-crew (CrewAI framework)
    ├── researcher (Agent role)
    ├── writer (Agent role)
    └── editor (Agent role)

Generated:
  .hexr/process-contexts/
    ├── researcher.json
    ├── writer.json
    └── editor.json
Each process context file contains the template for SPIRE registration:
{
  "agent_name": "content-crew",
  "tenant": "acme-corp",
  "process_role": "researcher",
  "framework": "crewai",
  "trust_domain": "hexr.cloud"
}

Stage 2: Pod startup and registration

When the pod starts, the Auto-Registrar creates a SPIRE entry for each role:

Kubernetes fires pod event

The Kubernetes API notifies the Auto-Registrar that a pod with hexr.io/managed=true was created.

Auto-Registrar reads contexts

Reads the process context ConfigMaps mounted in the pod. Each file describes one agent role (researcher, writer, editor).

SPIRE entries created per role

For each process role, the Auto-Registrar calls SPIRE.CreateEntry:
RoleSPIFFE IDSelectors
researcherspiffe://hexr.cloud/agent/acme-corp/content-crew/researcherk8s:pod-uid:{uid}, hexr:process-role:researcher
writerspiffe://hexr.cloud/agent/acme-corp/content-crew/writerk8s:pod-uid:{uid}, hexr:process-role:writer
editorspiffe://hexr.cloud/agent/acme-corp/content-crew/editork8s:pod-uid:{uid}, hexr:process-role:editor

Stage 3: Runtime marker files

When each agent process starts, the SDK automatically writes a marker file that identifies the process:
# Inside @hexr_agent decorator — happens automatically
HexrContext.set_agent_context(
    agent_name="content-crew",
    tenant="acme-corp",
    framework="crewai",
    resources=["aws_s3", "gcp_bigquery"]
)
# Writes: /tmp/hexr-context/content-crew-researcher.json
The PID Mapper reads this marker, maps the container PID to the host PID using /proc, and writes the enriched context:
{
  "agent_name": "content-crew",
  "process_role": "researcher",
  "container_pid": 42,
  "host_pid": 83721,
  "tenant": "acme-corp"
}

Stage 4: SVID issuance

The agent process fetches its SVID from the SPIRE Workload API. The SDK handles this automatically:
# Automatic — SDK handles this
svid = spire_workload_api.FetchX509SVID()
# Returns: X.509 certificate with:
#   Subject: spiffe://hexr.cloud/agent/acme-corp/content-crew/researcher
#   Valid: 1 hour (auto-rotated)
This SVID is used for:
  • mTLS — Envoy loads it via SDS for all encrypted communication
  • JWT exchange — the Credential Injector verifies it before issuing cloud credentials
  • Audit — every action is attributed to this specific process identity

What per-process identity gives you

Scoped cloud access per role

You can restrict each role to exactly the cloud services it needs:
@hexr_agent(
    name="data-pipeline",
    tenant="acme-corp",
    resources=["aws_s3:read", "gcp_bigquery:query"]  # Only S3 read + BQ query
)
def pipeline(query: str):
    s3 = hexr_tool("aws_s3")          # ✅ Allowed (read-only S3)
    bq = hexr_tool("gcp_bigquery")    # ✅ Allowed (query-only BQ)
    ec2 = hexr_tool("aws_ec2")        # ❌ Denied by OPA policy

Per-agent cost attribution

With hexr_llm(), every LLM call is tagged with the calling process’s SPIFFE ID — giving you accurate cost breakdowns per role:
Trace: content-crew run #47
├── spiffe://…/content-crew/researcher
│   └── GPT-4o: 1,200 input + 800 output tokens ($0.028)
├── spiffe://…/content-crew/writer
│   └── GPT-4o: 3,400 input + 2,100 output tokens ($0.089)
└── spiffe://…/content-crew/editor
    └── GPT-4o: 800 input + 400 output tokens ($0.019)

Total: $0.136 for this run

Authenticated agent-to-agent communication

When agents communicate across pods, mTLS verifies both parties with their SPIFFE IDs — no API keys or tokens required:
Agent A: spiffe://hexr.cloud/agent/acme-corp/orchestrator/main
    → mTLS →
Agent B: spiffe://hexr.cloud/agent/acme-corp/data-analyst/main

Both sides verified. No API keys. No tokens. Pure cryptographic identity.

Security properties

PropertyBenefit
No shared credentialsEach process has its own short-lived X.509 certificate
Auto-rotationSVIDs rotate every hour automatically — no manual rotation
Instant revocationDelete the SPIRE entry and the identity is immediately invalid
Precise audit trailEvery operation is traced to a specific process, not just a pod
Lateral movement preventionProcess A cannot impersonate Process B — they have different SPIFFE IDs
Blast radius containmentA compromised process can only access its own scoped resources