Per-Agent Identity in the Mesh
To apply a specific agent's policy to a request, the Mitrity Mesh Authorizer has to know which agent made the request. Inside the mesh, a workload's identity is its Kubernetes namespace + ServiceAccount, presented as a verifiable SPIFFE identity over mutual TLS.
This page shows you how to bind a MITRITY agent to that mesh identity, and how the Authorizer resolves it. It also covers the two rules that keep it safe:
- STRICT mTLS is mandatory;
- unmapped identities are denied by default.
The resolution chain
When a governed request reaches the Authorizer, it resolves the caller from the bottom up:
Workload runs as namespace + ServiceAccount
│ Istio mTLS
▼
SPIFFE source.principal
spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>
│ (namespace + ServiceAccount → bound agent)
▼
MITRITY agent
│
▼
that agent's mission profile + policy → allow / deny / inject credentials
The link in the middle maps the namespace and ServiceAccount to a MITRITY agent. That link is the binding you create in the dashboard. Once it exists, the Authorizer applies exactly that agent's policy to its mesh traffic, the same way Mitrity Gateway and Mitrity MCP Sidecar apply it to that agent's MCP traffic.
The mesh trust domain is a property of your environment, not of the individual agent, so you do not set it per agent. You bind only the namespace and the ServiceAccount.
Binding an agent to a namespace + ServiceAccount
You set an agent's mesh identity when you create the agent, or you edit it later. Both forms have a Mesh Identity section with two fields:
| Field | What to enter | Format |
|---|---|---|
| Namespace | The Kubernetes namespace the agent's workload runs in (for example payments) | DNS-1123 label: lowercase letters, digits and hyphens; must start and end with an alphanumeric; 63 chars max |
| ServiceAccount | The Kubernetes ServiceAccount the workload runs as (for example checkout-bot) | DNS-1123 subdomain: lowercase letters, digits, hyphens and dots; 253 chars max |
Together, namespace + ServiceAccount uniquely identifies one workload identity in the mesh. The granularity is namespace + ServiceAccount on purpose, not the ServiceAccount name alone, so that the same ServiceAccount name in two different namespaces never collides.
Both fields, or neither
Mesh identity is optional. An agent that is not part of a service mesh leaves both fields empty, and it shows as Not mesh-bound on the agent's detail page. But if you set one field, you must set the other. A half-filled binding can never resolve a SPIFFE identity, so the form rejects setting only the namespace or only the ServiceAccount.
To bind an agent
- Go to Agents, then either Register Agent (for a new agent) or open an existing agent and choose Edit.
- In the Mesh Identity section, enter the workload's Namespace and ServiceAccount.
- Save. The agent's detail page now shows its mesh identity as
namespace/ServiceAccount.
The binding is pushed to the Mesh Authorizer with the agent's mission profile. So the Authorizer can resolve namespace + ServiceAccount → agent locally on the request path, with no extra lookup per request.
One mesh identity per agent. Each agent binds to a single
namespace + ServiceAccount, and eachnamespace + ServiceAccountmaps to a single agent within a tenant. If two workloads need different policies, give them different ServiceAccounts and bind each one to its own agent.
STRICT mTLS is required
Envoy only populates the caller's SPIFFE identity (source.principal) when the request arrived over mutual TLS. Without mutual TLS, there is no identity to resolve:
- Under STRICT mTLS, every governed request carries the caller's verified SPIFFE identity. The Authorizer resolves it to the bound agent and applies that agent's policy.
- Under PERMISSIVE mTLS or plaintext, the SPIFFE identity is empty. With no identity, the Authorizer cannot govern the request against any declared mission, so it fails closed (deny).
This is why STRICT mTLS is mandatory for every governed namespace, not a recommendation. The chart pins STRICT on the governed namespace by default. If every request is being denied, the most common cause is an empty identity from missing STRICT mTLS, so confirm that STRICT is in force. Deploy in Istio shows how the chart sets this and how to verify it.
Unmapped identity is denied by default
A request can arrive with a perfectly valid SPIFFE identity that simply does not match any bound agent. An example is a workload in a governed namespace whose ServiceAccount you have not bound to an agent yet. The Authorizer denies these requests by default.
The reasoning is fail-safe. If a request reached the Authorizer at all, it is inside a governed selector, which means you intended to govern it. An identity that the platform cannot map to an agent is an identity it cannot evaluate against a declared mission. So the secure default is to deny, rather than to allow silently.
- Default: deny on unmapped identity. Use this in production. Any workload in a governed namespace must be bound to an agent, or excluded from the governed selector, before its traffic is allowed.
- Permissive rollout (opt-in). During a phased migration, you can switch the Authorizer to allow resolved-but-unmapped identities. You can then bind agents incrementally, without blocking unbound workloads. Treat this as a temporary escape hatch, and return to deny for production.
A missing identity (no mTLS) always fails closed, regardless of this setting. The deny-on-unmapped behavior is specifically about a valid identity that does not resolve to a bound agent.
Agent-to-agent delegation chains
When one bound agent calls another inside the mesh (an agent-to-agent, or A2A, hop), the Authorizer also evaluates the delegation chain. The delegation chain is the path of agents that handed off to one another, and the Authorizer checks it for cycles, excessive depth and privilege escalation. That evaluation depends on the delegation-chain identifier propagating across the hop, in the x-mitrity-delegation-chain-id request header.
If an A2A hop drops that header, the Authorizer can no longer reason about the chain. It treats the drop as a downgrade-bypass attempt and fails closed (deny). Make sure your agents propagate the x-mitrity-delegation-chain-id header on calls to other agents, so that legitimate delegation chains are evaluated and allowed. See Delegation Chains for the chain model.
Related Documentation
- Mesh Enforcement (Istio): the concept and identity model
- Deploy in Istio: install, STRICT mTLS and scoping
- Mesh Egress Allowlist: the opt-in egress allowlist for outbound traffic
- Delegation Chains: agent-to-agent delegation-chain governance
- Core Concepts: agents, mission profiles and policies