Identities (NHI)
Quick example
- curl
- Python
- Node.js
# Register a new NHI
curl "$TRINITITE_BASE/v1/identities" \
-H "Authorization: Bearer $TRINITITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "billing-assistant",
"tier": "T2",
"workload_origin": "k8s://billing/refund-bot",
"guardian": "stripe-refund-guardian"
}'
import os, requests
requests.post(f"{os.environ['TRINITITE_BASE']}/v1/identities",
headers={"Authorization": f"Bearer {os.environ['TRINITITE_API_KEY']}"},
json={"name": "billing-assistant", "tier": "T2",
"workload_origin": "k8s://billing/refund-bot", "guardian": "stripe-refund-guardian"})
await fetch(`${process.env.TRINITITE_BASE}/v1/identities`, {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.TRINITITE_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'billing-assistant', tier: 'T2',
workload_origin: 'k8s://billing/refund-bot', guardian: 'stripe-refund-guardian',
}),
});
See NHI Governance for the architecture.
Overview
A Non-Human Identity (NHI) is a first-class identity for an autonomous workload — an AI agent, a service principal, a federated cloud identity. NHIs carry a privilege tier and a registered workload origin, and are the unit of identity that the LLM Proxy, MCP Gateway, and CLI Firewall authorize against.
This page covers the three NHI surfaces:
- NHI lifecycle —
/v1/proxy/nhi/*. CRUD, JIT tokens, tier transitions, lifecycle bindings, cascade revocation, economic sessions, IMDS shield, orchestration config. - NHI Federation —
/v1/nhi/federation/*. External identity providers; mirrored identities; sync; events; posture. - NHI ↔ Guardian binding —
/v1/nhi-guardian/*. Which Guardian governs which NHI; which NHIs are ungoverned; concentration; policy impact; tier attestation.
For analytics rollups across these dimensions, see the Analytics API.
Authentication: Authorization: Bearer <session_token | api_key> with the relevant nhi:* permission.
NHI lifecycle (/v1/proxy/nhi)
Identities
| Method | Path | Permission |
|---|---|---|
POST | /v1/proxy/nhi/identities | nhi:update |
GET | /v1/proxy/nhi/identities | nhi:read |
GET | /v1/proxy/nhi/identities/{id} | nhi:read |
DELETE | /v1/proxy/nhi/identities/{id} | nhi:update |
Create
{
"label": "ci-runner-prod",
"principal_user_id": "usr_01JF8RUS1A2B3C4D5E6F7G8H9I",
"privilege_tier": 2,
"workload_id": "k8s://prod/agent-pool/ci-runner",
"workload_attestation_hash": "sha256:e3b0c44...",
"max_spawn_depth": 1,
"parent_nhi_id": null
}
| Field | Type | Required | Description |
|---|---|---|---|
label | string | Yes | 1–255 chars |
principal_user_id | string | No | Human principal responsible for this agent. Auto-provisions a lifecycle binding |
privilege_tier | integer | No | 1–3. Default 1 |
workload_id | string | No | Logical grouping |
workload_attestation_hash | string | No | Hash of the workload definition |
max_spawn_depth | integer | No | 0–3. Limits how deep child NHIs may chain |
parent_nhi_id | string | No | Parent NHI for child agents |
Returns 201 Created with the NHI object.
Privilege tiers
| Tier | Typical access |
|---|---|
1 | Read-only by default (lowest) |
2 | Standard tool access |
3 | Elevated; explicit Guardian-attested tier transition required |
Revoke
DELETE /v1/proxy/nhi/identities/{id} with body { "reason": "..." }. Returns 204 No Content. Active sessions and JIT tokens are invalidated.
JIT tokens
POST /v1/proxy/nhi/tokens issues a Just-In-Time token. Single-use, short-lived. The plaintext token is returned once.
{
"nhi_id": "nhi_01JF8RNHI1A2B3C4D5E6F7G8H9",
"task_correlation_id": "task_2026-05-01-deploy-prod",
"ttl_seconds": 300,
"allowed_network_cidr": "10.0.0.0/16"
}
Response — 201 Created:
{
"token_id": "ntk_01JF8RNTK1A2B3C4D5E6F7G8H9I",
"nhi_id": "nhi_01JF8RNHI1A2B3C4D5E6F7G8H9",
"plaintext_token": "njit_4f8d9e2a1c6b7f3a9e1d2c4b5a6f7e8d",
"expires_at": "2026-05-01T22:19:00Z",
"issued_tier": 2
}
Use the plaintext token as X-Trinitite-Nhi-Token on subsequent proxy or gateway calls.
Tier transitions
POST /v1/proxy/nhi/tier-transitions requests a privilege tier elevation. Requires a guardian_approval_hash proving the assigned Guardian signed off — see tier attestation below.
{
"nhi_id": "nhi_01JF8RNHI1A2B3C4D5E6F7G8H9",
"target_tier": 3,
"guardian_id": "gov_01JF8R3M3X4N5Q6T7V8W9Y0Z1A",
"guardian_approval_hash": "sha256:8f3c...",
"intent_summary": "Elevate to deploy production helm release."
}
Returns 201 Created with the tier transition record.
Lifecycle bindings
Bind an NHI to a human principal. On principal offboarding, bound NHIs cascade-revoke.
| Method | Path | Permission |
|---|---|---|
POST | /v1/proxy/nhi/lifecycle-bindings | nhi:update |
GET | /v1/proxy/nhi/lifecycle-bindings | nhi:read |
{
"nhi_id": "nhi_01JF8RNHI1A2B3C4D5E6F7G8H9",
"principal_user_id": "usr_01JF8RUS1A2B3C4D5E6F7G8H9I",
"hris_employee_id": "EMP-12345"
}
Cascade revocation
POST /v1/proxy/nhi/cascade-revocation revokes all NHIs bound to a departing principal.
{ "principal_user_id": "usr_01JF8RUS1A2B3C4D5E6F7G8H9I" }
Returns a summary of revoked identities.
Economic sessions
A spend-bounded session attached to an NHI. The economic circuit breaker trips when the session exceeds its limit. See also Governance Controls → Credential controls.
| Method | Path | Permission |
|---|---|---|
POST | /v1/proxy/nhi/economic-sessions | nhi:update |
GET | /v1/proxy/nhi/economic-sessions | nhi:read |
PATCH | /v1/proxy/nhi/economic-sessions/{sessionId} | nhi:update |
DELETE | /v1/proxy/nhi/economic-sessions/{sessionId} | nhi:update |
POST | /v1/proxy/nhi/economic-sessions/{sessionId}/trip | nhi:update |
POST | /v1/proxy/nhi/economic-sessions/{sessionId}/reset | nhi:update |
The trip and reset endpoints manually fire / clear the breaker — useful in incident response.
IMDS shield events
GET /v1/proxy/nhi/imds-events — read-only stream of cloud Instance Metadata Service shield events caught at the proxy boundary.
Orchestration config
GET /v1/proxy/nhi/orchestration-config and PATCH ... — retry / backoff configuration per NHI tier.
EX-2.7 tool attempts
| Method | Path | Permission |
|---|---|---|
GET | /v1/proxy/nhi/tool-attempts | nhi:read |
GET | /v1/proxy/nhi/tool-attempts/summary | nhi:read |
Read-only feed of every attempt by an NHI to call a tool — including the verdict, blocker (if any), and policy that fired.
NHI Federation (/v1/nhi/federation)
External NHIs (AWS IAM roles, Azure AD service principals, GCP, Kubernetes service accounts, OIDC subjects, Astrix, Aembit) are mirrored into the platform via the federation registry.
Providers
| Method | Path | Permission |
|---|---|---|
POST | /v1/nhi/federation/providers | nhi:update |
GET | /v1/nhi/federation/providers | nhi:read |
GET | /v1/nhi/federation/providers/{id} | nhi:read |
PATCH | /v1/nhi/federation/providers/{id} | nhi:update |
DELETE | /v1/nhi/federation/providers/{id} | nhi:update |
POST | /v1/nhi/federation/providers/{id}/sync | nhi:update |
{
"provider_type": "aws_iam",
"label": "AWS prod-iam",
"config_json": {
"account_id": "123456789012",
"role_arn_pattern": "arn:aws:iam::123456789012:role/agent-*"
},
"tier_mapping": {
"default": 1,
"by_role_tag": { "tier:2": 2, "tier:3": 3 }
}
}
POST .../sync triggers an out-of-band sync; 200 OK response includes { added, updated, deleted, sync_duration_ms } stats.
Federated identities
| Method | Path | Permission |
|---|---|---|
GET | /v1/nhi/federation/identities | nhi:read |
POST | /v1/nhi/federation/identities/import | nhi:update |
POST | /v1/nhi/federation/identities/{id}/link | nhi:update |
POST | /v1/nhi/federation/identities/{id}/unlink | nhi:update |
Federated identities are linkable to platform-issued NHIs via link / unlink — once linked, governance and analytics aggregate across the pair.
Federation events
| Method | Path | Permission |
|---|---|---|
POST | /v1/nhi/federation/events | nhi:update |
GET | /v1/nhi/federation/events | nhi:read |
Bulk-ingest events from external IdPs (e.g. role assumption logs). POST accepts { events: [...] } and returns 202 Accepted with { ingested }.
Posture summary
GET /v1/nhi/federation/posture — composite federation health (provider connectivity, drift, mirror staleness).
NHI ↔ Guardian binding (/v1/nhi-guardian)
A binding determines whether and how an NHI's traffic is governed. Modes:
| Mode | Behaviour |
|---|---|
input | Guardian evaluates inbound user prompts only |
output | Guardian evaluates outbound model responses only |
bidirectional | Both directions |
Assignments
| Method | Path | Permission |
|---|---|---|
POST | /v1/nhi-guardian/assignments | nhi:update |
GET | /v1/nhi-guardian/assignments | nhi:read |
GET | /v1/nhi-guardian/assignments/{id} | nhi:read |
PATCH | /v1/nhi-guardian/assignments/{id} | nhi:update |
DELETE | /v1/nhi-guardian/assignments/{id} | nhi:update |
{
"nhi_id": "nhi_01JF8RNHI1A2B3C4D5E6F7G8H9",
"guardian_id": "gov_01JF8R3M3X4N5Q6T7V8W9Y0Z1A",
"governance_mode": "bidirectional",
"priority": 100,
"auto_route": true,
"effective_from": "2026-05-01T00:00:00Z",
"effective_until": null
}
Higher priority wins when an NHI has multiple active assignments. auto_route: true means the proxy auto-resolves this assignment when the calling NHI omits an explicit Guardian envelope.
Resolve / ungoverned
GET /v1/nhi-guardian/resolve/{nhiId} — returns the Guardian that would govern this NHI right now (the active resolution chain).
GET /v1/nhi-guardian/ungoverned — every NHI that currently has no active Guardian assignment. Useful for rolling out governance and for posture dashboards.
Metrics
GET /v1/nhi-guardian/metrics — pair-level aggregate metrics (verdict counts, latency, drift signals).
GET /v1/nhi-guardian/metrics/timeseries — bucketed timeseries view.
Training suggestions
The platform mines proxy logs for cases where the assigned Guardian should have corrected or blocked but didn't (or vice versa) and surfaces them as training suggestions.
| Method | Path | Permission |
|---|---|---|
GET | /v1/nhi-guardian/training-suggestions/{guardianId} | nhi:read |
POST | /v1/nhi-guardian/training-suggestions/{id}/accept | nhi:update |
POST | /v1/nhi-guardian/training-suggestions/{id}/reject | nhi:update |
Accepted suggestions feed directly into the next Training job for the Guardian.
Concentration & policy impact
GET /v1/nhi-guardian/concentration — surfaces over-concentration risk (one Guardian governing too many NHIs, or one NHI blocking the fleet on a single binding).
GET /v1/nhi-guardian/policy-impact/{documentId} — for a given Policy document, which NHIs are affected if its assigned Guardians are retrained.
Tier attestation
POST /v1/nhi-guardian/tier-attestation/{nhiId} — the Guardian-signed attestation feeding POST /v1/proxy/nhi/tier-transitions.
{
"target_tier": 3,
"intent_summary": "Elevate to run helm release.",
"evidence": { "training_runs": ["job_01JF..."] }
}
Response — 200 OK:
{
"guardian_approval_hash": "sha256:8f3c...",
"guardian_id": "gov_01JF8R3M3X4N5Q6T7V8W9Y0Z1A",
"expires_at": "2026-05-01T23:00:00Z"
}
The guardian_approval_hash is what POST /v1/proxy/nhi/tier-transitions will validate.
Errors
| HTTP | error.code | Cause |
|---|---|---|
400 | validation_error | Body or query failed schema validation |
401 | unauthenticated | Missing or invalid credential |
401 | nhi_token_invalid | NHI JIT token rejected |
403 | forbidden | Caller lacks nhi:read / nhi:update |
404 | not_found | NHI, federation provider, assignment, or training suggestion not found |
409 | conflict | Concurrent modification, duplicate assignment |
409 | economic_session_limit_exceeded | Economic session breaker tripped |
422 | unprocessable_entity | Tier transition without a valid guardian_approval_hash |
429 | rate_limited | Per-organization rate limit exceeded |
Next steps
- Use an NHI on a proxy call → Proxy
- Use an NHI on the MCP Gateway → MCP Gateway
- Tune org-wide governance for autonomous workloads → Governance Controls
- Aggregate NHI risk and posture → Analytics API