NL Protocol Specification v1.0 -- Level 1: Agent Identity
Status: 1.0-draft Version: 1.0.0 Date: 2026-02-08 Level: 1 (Foundation) Conformance: Required for all tiers (Basic, Standard, Advanced)
Note: This document is a SPECIFICATION. It defines required behaviors, data formats, and protocols — not specific products or CLI commands. For implementations of this specification, see IMPLEMENTATIONS.md.
1. Purpose
Every agent that interacts with secrets MUST have a unique, verifiable, governable identity. Without identity, it is impossible to:
- Enforce per-agent access policies (Level 2)
- Attribute actions in audit trails (Level 5)
- Detect anomalous behavior per agent (Level 6)
- Establish trust between agents (Level 7)
- Revoke access to a single compromised agent without disrupting others
Agent identity is the foundation upon which every other level of the NL Protocol is built.
This specification defines:
- The Agent URI format for globally unique identification
- The Agent Identity Document (AID) structure
- Agent type taxonomy and risk profiles
- Agent lifecycle states and transitions
- Platform attestation via signed JWTs
- Trust levels from self-attested to third-party-certified
- Registration and verification flows
2. Requirements Summary
| ID | Requirement | Priority | Description |
|---|---|---|---|
| NL-1.1 | Agent URI | MUST | Every agent MUST have a globally unique URI in the nl:// scheme. |
| NL-1.2 | Agent Identity Document | MUST | Every agent MUST have a structured AID containing identity, capabilities, context, and lifecycle metadata. |
| NL-1.3 | Agent Type | MUST | Every agent MUST declare its type from the standard taxonomy. |
| NL-1.4 | Agent Capabilities | MUST | Every AID MUST declare the set of action types the agent is authorized to perform. |
| NL-1.5 | Agent Lifecycle | MUST | Every agent MUST have a lifecycle state that governs whether it can perform actions. |
| NL-1.6 | Agent Credential | MUST | Every agent MUST authenticate using a credential mechanism supported by the NL-compliant system. |
| NL-1.7 | Platform Attestation | SHOULD (Basic), MUST (Standard+) | Platform Providers SHOULD sign attestation JWTs for agents they provision. Attestation is REQUIRED for Standard and Advanced conformance. |
| NL-1.8 | Trust Level | MUST | Every agent MUST have an assigned trust level (L0-L3) that reflects its identity assurance. |
| NL-1.9 | Session Context | SHOULD | The AID SHOULD include session context (IDE, repository, branch, workspace) when available. |
| NL-1.10 | Expiration | MUST | Every AID MUST have an expires_at timestamp. Expired AIDs MUST be rejected. |
| NL-1.11 | Delegation Chain | SHOULD | The AID SHOULD record the delegation chain: which human or parent agent authorized this agent. |
| NL-1.12 | Organization Binding | MUST | Every agent MUST be bound to an organization identifier. |
3. Agent URI Format
3.1 Syntax
Every agent MUST be identified by a URI in the following format:
nl://VENDOR/AGENT_TYPE/VERSION
Where:
nl://is the scheme identifier for the Never-Leak Protocol.VENDORis the DNS-style domain of the organization that produces or operates the agent. It MUST be a valid domain name (lowercase, no port, no trailing dot).AGENT_TYPEis a kebab-case identifier for the agent software. It MUST consist of lowercase ASCII letters, digits, and hyphens. It MUST NOT begin or end with a hyphen.VERSIONis a semantic version string (MAJOR.MINOR.PATCH). Pre-release and build metadata suffixes (e.g.,-beta.1,+build.42) are OPTIONAL.
3.2 ABNF Grammar
agent-uri = "nl://" vendor "/" agent-type "/" version
vendor = domain-name
agent-type = LCALPHA *(LCALPHA / DIGIT / "-") LCALPHA
/ LCALPHA
version = 1*DIGIT "." 1*DIGIT "." 1*DIGIT [pre-release] [build]
pre-release = "-" 1*(ALPHA / DIGIT / ".")
build = "+" 1*(ALPHA / DIGIT / ".")
domain-name = label *("." label)
label = LCALPHA *(LCALPHA / DIGIT / "-")
LCALPHA = %x61-7A ; a-z
3.3 Examples
| Agent | Agent URI |
|---|---|
| Claude Code v1.5.2 by Anthropic | nl://anthropic.com/claude-code/1.5.2 |
| Cursor AI v0.45.0 | nl://cursor.com/cursor-ai/0.45.0 |
| GitHub Copilot v1.200.0 | nl://github.com/copilot/1.200.0 |
| OpenAI Codex CLI v1.0.0 | nl://openai.com/codex-cli/1.0.0 |
| Windsurf by Codeium v1.2.0 | nl://codeium.com/windsurf/1.2.0 |
| Custom deploy bot by Acme Corp | nl://acme.corp/deploy-bot/2.1.0 |
| CI pipeline runner by Acme Corp | nl://acme.corp/ci-runner/1.0.0 |
| Human user (via CLI) | nl://acme.corp/human/0.0.0 |
3.4 Uniqueness and Instance Distinction
The combination of VENDOR + AGENT_TYPE + VERSION identifies a specific
agent software release. Two different agent products MUST NOT share
the same URI.
However, multiple instances of the same agent software (e.g., two
concurrent Claude Code sessions) share the same Agent URI. Instances are
distinguished by the instance_id field within the AID (see Section 4).
Example: Developer Alice and developer Bob both use Claude Code 1.5.2.
Both agents have the URI nl://anthropic.com/claude-code/1.5.2, but
Alice's instance has instance_id: "a1b2..." and Bob's has
instance_id: "c3d4...".
3.5 Relationship to SPIFFE
The nl:// URI scheme is inspired by SPIFFE's spiffe:// URIs but serves
a different purpose. SPIFFE identifies infrastructure workloads; NL URIs
identify AI agent software. Implementations MAY maintain a mapping between
SPIFFE IDs and NL Agent URIs for organizations that use both systems.
4. Agent Identity Document (AID)
4.1 Overview
The Agent Identity Document (AID) is a JSON structure that fully describes an agent's identity, capabilities, attestation, session context, and lifecycle state. Every agent MUST present a valid AID when submitting action requests to an NL-compliant system.
The AID is NOT a secret. It is an identity document analogous to a passport: it describes who the agent is, not what secrets it can access. Access is governed by Scope Grants (Level 2).
4.2 Complete Schema
{
"$schema": "https://nlprotocol.org/schemas/v1.0/aid.json",
"nl_version": "1.0",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"instance_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": "org_acme_corp_2024",
"agent_type": "coding_assistant",
"trust_level": "L2",
"delegated_by": {
"type": "human",
"identifier": "andres@acme.corp",
"delegation_time": "2026-02-08T10:00:00Z"
},
"capabilities": [
"exec",
"template",
"inject_stdin",
"inject_tempfile"
],
"scope": {
"projects": ["braincol", "xpro"],
"environments": ["development", "staging"],
"categories": ["api", "database"],
"secret_patterns": ["api/*", "database/DB_*"]
},
"public_key": {
"algorithm": "ES256",
"value": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE..."
},
"attestation": {
"type": "jwt",
"token": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImFudGhyb3BpYy1ubC0yMDI2LTAxIn0...",
"issuer": "anthropic.com",
"issued_at": "2026-02-08T10:00:00Z",
"expires_at": "2026-02-08T22:00:00Z"
},
"session_context": {
"ide": "vscode",
"ide_version": "1.96.0",
"repository": "github.com/acme-corp/backend",
"branch": "feature/payments",
"workspace": "/Users/andres/projects/backend",
"os": "darwin",
"hostname": "andres-macbook"
},
"lifecycle": "active",
"created_at": "2026-02-08T10:00:00Z",
"expires_at": "2026-02-08T22:00:00Z",
"last_active_at": "2026-02-08T14:30:00Z"
}
4.3 Field Definitions
4.3.1 Required Fields
Every AID MUST contain the following fields:
| Field | Type | Constraints | Description |
|---|---|---|---|
nl_version |
string | MUST be "1.0" |
The NL Protocol version this AID conforms to. |
agent_uri |
string | MUST match Section 3.2 ABNF | The Agent URI identifying the agent software. |
instance_id |
string | UUID v4 (RFC 4122) | Unique identifier for this agent instance. Generated by the NL-compliant system during registration. |
organization_id |
string | Non-empty, printable ASCII | The identifier of the organization that registered this agent. Format is implementation-defined. |
agent_type |
string | One of the values in Section 5 | The agent's type from the standard taxonomy. |
trust_level |
string | "L0" or "L1" or "L2" or "L3" |
The trust level, reflecting the strength of identity verification. See Section 7. |
capabilities |
string[] | Non-empty array | List of action types this agent is authorized to request. Valid values: "exec", "template", "inject_stdin", "inject_tempfile", "sdk_proxy", "delegate". |
lifecycle |
string | One of the values in Section 6 | Current lifecycle state. |
created_at |
string | ISO 8601, UTC | When this AID was created. |
expires_at |
string | ISO 8601, UTC, after created_at |
When this AID expires. |
4.3.2 Recommended Fields
The following fields are RECOMMENDED. Implementations SHOULD include them.
| Field | Type | Description |
|---|---|---|
public_key |
object | The agent's public key for delegation token signing. Contains algorithm (string, e.g., "ES256", "Ed25519") and value (string, base64url-encoded public key). SHOULD for Basic conformance, MUST for Standard and Advanced conformance. Required for delegation token signing (see Chapter 07). |
delegated_by |
object | Who authorized this agent. See Section 4.3.4. |
scope |
object | Access scope restrictions. See Section 4.3.5. |
attestation |
object | Platform attestation JWT. See Section 8. REQUIRED for Standard+ conformance. |
session_context |
object | Runtime context. See Section 4.3.6. |
last_active_at |
string (ISO 8601) | Timestamp of the agent's most recent action. Updated by the NL-compliant system. |
4.3.3 Optional Fields
| Field | Type | Description |
|---|---|---|
metadata |
object | Arbitrary key-value pairs for implementation-specific data. Keys MUST be strings. Values MUST be strings, numbers, or booleans. |
4.3.4 Delegation Chain (delegated_by)
{
"type": "human | agent",
"identifier": "andres@acme.corp | nl://acme.corp/orchestrator/1.0.0",
"delegation_time": "2026-02-08T10:00:00Z",
"parent_instance_id": "optional-uuid-of-parent-agent"
}
| Field | Type | Description |
|---|---|---|
type |
string | "human" if delegated by a human user, "agent" if delegated by a parent agent. |
identifier |
string | For humans: email address or username. For agents: the parent agent's Agent URI. |
delegation_time |
string (ISO 8601) | When the delegation occurred. |
parent_instance_id |
string (UUID, optional) | If delegated by an agent, the parent's instance_id. Enables audit chain linking. |
4.3.5 Scope Object
The scope object restricts what secrets the agent can reference. If omitted, the agent has no inherent scope and MUST rely entirely on explicit Scope Grants (Level 2).
{
"projects": ["braincol", "xpro"],
"environments": ["development", "staging"],
"categories": ["api", "database"],
"secret_patterns": ["api/*", "database/DB_*"]
}
| Field | Type | Description |
|---|---|---|
projects |
string[] | Allowed projects. ["*"] means all projects. |
environments |
string[] | Allowed environments. ["*"] means all environments. |
categories |
string[] (optional) | Allowed secret categories. If omitted, all categories are allowed within the specified projects/environments. |
secret_patterns |
string[] (optional) | Glob patterns for allowed secret names. * matches any sequence of characters. ? matches exactly one character. |
Scope evaluation rule: A secret reference {{nl:project/environment/category/name}}
is within scope if and only if:
projectmatches at least one entry inprojects(orprojectscontains"*"), ANDenvironmentmatches at least one entry inenvironments(orenvironmentscontains"*"), ANDcategorymatches at least one entry incategories(orcategoriesis omitted), AND- The fully qualified secret path matches at least one pattern in
secret_patterns(orsecret_patternsis omitted).
4.3.6 Session Context
All session context fields are OPTIONAL. Implementations SHOULD populate them when the information is available.
{
"ide": "vscode",
"ide_version": "1.96.0",
"repository": "github.com/acme-corp/backend",
"branch": "feature/payments",
"workspace": "/Users/andres/projects/backend",
"os": "darwin",
"hostname": "andres-macbook"
}
| Field | Type | Description |
|---|---|---|
ide |
string | IDE or development environment: "vscode", "jetbrains", "neovim", "terminal", etc. |
ide_version |
string | Version of the IDE. |
repository |
string | The repository the agent is working in (e.g., "github.com/acme/app"). |
branch |
string | The active Git branch. |
workspace |
string | The local workspace/directory path. |
os |
string | The operating system: "darwin", "linux", "windows". |
hostname |
string | The machine hostname. |
Session context is valuable for:
- Anomaly detection (Level 6): Detecting when an agent's session context changes unexpectedly (e.g., same agent appearing from a different hostname).
- Policy evaluation: Scope Grants MAY be conditional on session context (e.g., "only allow production access from CI/CD, not from developer laptops").
- Audit enrichment (Level 5): Recording what the agent was doing when it accessed a secret.
4.4 Validation Rules
An NL-compliant system MUST validate the following when receiving an AID:
nl_versionMUST be a supported protocol version.agent_uriMUST conform to the ABNF grammar in Section 3.2.instance_idMUST be a valid UUID v4.organization_idMUST be non-empty and MUST match a registered organization in the system.agent_typeMUST be one of the values defined in Section 5.trust_levelMUST be one of"L0","L1","L2","L3".capabilitiesMUST be a non-empty array containing only valid action type strings.lifecycleMUST be"active"for the agent to perform actions. Agents in any other state MUST be rejected with an error indicating the lifecycle state.expires_atMUST be in the future. Expired AIDs MUST be rejected.created_atMUST be in the past (allowing for clock skew tolerance).- If
attestationis present, it MUST be validated according to Section 8. - If the NL-compliant system requires Standard or Advanced conformance,
attestationMUST be present and valid.
When validation fails, the system MUST return an error response specifying which field(s) failed validation and why. The error MUST NOT include any secret values.
5. Agent Type Taxonomy
5.1 Standard Types
Every agent MUST declare its type. The type determines the agent's risk profile and informs policy decisions.
| Type | Risk Level | Typical Context | Typical Secret Access | Examples |
|---|---|---|---|---|
coding_assistant |
MEDIUM | IDE, local terminal | Dev API keys, test tokens, dev DB passwords | Claude Code, Cursor, Copilot, Windsurf, Aider |
autonomous_executor |
HIGH | Headless execution, infrastructure management | Cloud credentials, deploy tokens, production DB passwords | Deploy bots, migration agents, scaling agents |
orchestrator |
VERY HIGH | Multi-agent coordination, workflow management | Cross-service credentials, admin tokens, delegation authority | Workflow coordinators, multi-agent systems |
ci_cd_pipeline |
HIGH | GitHub Actions, Jenkins, GitLab CI, CircleCI | Registry tokens, deploy keys, cloud credentials, signing keys | CI runners, deployment pipelines |
human |
LOW (comparative) | CLI, Web UI, interactive sessions | All (per role assignment) | Developers, DevOps engineers, security admins |
custom |
VARIABLE | Organization-defined | Organization-defined | Internal bots, proprietary agents, security scanners |
5.2 Risk Implications
Implementations SHOULD use agent type to inform default policy decisions:
orchestratoragents SHOULD require human approval for first-time access to production secrets.autonomous_executoragents SHOULD have shorter AID expiration times (RECOMMENDED: 1-4 hours) thancoding_assistantagents (RECOMMENDED: 8-12 hours).ci_cd_pipelineagents SHOULD have AIDs scoped to the specific pipeline run and SHOULD expire when the run completes.humanagents MAY have relaxed session timeouts for interactive use, but the action-based model (Level 2) still applies: even human agents interact with secrets via opaque handles.customagents MUST include arisk_levelfield in their AIDmetadatawith one of:"low","medium","high","very_high".
5.3 Extensibility
Organizations MAY define additional agent types beyond the standard taxonomy. Custom types MUST use a namespaced format to avoid collisions:
custom:ORGANIZATION/TYPE_NAME
Examples:
custom:acme.corp/security-scannercustom:acme.corp/data-migratorcustom:stripe.com/payment-validator
Custom types MUST be registered with the NL-compliant system before use. The registration MUST include a declared risk level.
6. Agent Lifecycle
6.1 States
Every agent has a lifecycle state that determines whether it can perform actions:
register
(none) ───────────────────> PROVISIONED
|
activate
(first auth
or admin)
|
v
reactivate ───────────────> ACTIVE <─────────── (normal operation)
^ / \
| suspend revoke
| / \
| v v
| SUSPENDED REVOKED
| | (terminal)
+───────────────────+
reactivate
(admin only)
| State | Can Perform Actions? | Description |
|---|---|---|
provisioned |
NO | Agent is registered but not yet activated. Credentials have been issued but not yet used. This is the initial state after registration. |
active |
YES | Agent is authorized to perform actions within its scope and capabilities. This is the only state that permits action requests. |
suspended |
NO | Agent is temporarily disabled. Can be reactivated by an administrator. All pending actions MUST be rejected. All outstanding delegation tokens MUST be invalidated. |
revoked |
NO | Agent is permanently disabled. This is a terminal state. The agent MUST NOT be reactivated. A new AID must be issued if the agent software needs to operate again. |
6.2 State Transitions
| Transition | From | To | Triggered By | Description |
|---|---|---|---|---|
register |
(none) | provisioned |
Principal (human admin) | A new agent is registered with the NL-compliant system. |
activate |
provisioned |
active |
First successful authentication, or explicit admin action | The agent demonstrates it has valid credentials. |
suspend |
active |
suspended |
Admin action, automated threat response (Level 6), policy violation, or AID expiration | The agent is temporarily disabled. |
reactivate |
suspended |
active |
Admin action ONLY | A suspended agent is re-enabled. Requires explicit human decision. |
revoke |
active or suspended |
revoked |
Admin action, or automated response to confirmed compromise | The agent is permanently disabled. |
6.3 Rules
An NL-compliant system MUST reject action requests from agents in any state other than
active. The rejection response MUST include the agent's current lifecycle state.When an agent transitions to
suspendedorrevoked, all outstanding delegation tokens issued by that agent MUST be invalidated immediately. Sub-agents that depend on those tokens MUST have their in-flight actions rejected.The
revokedstate is terminal. Implementations MUST NOT allow transition fromrevokedto any other state. If the same agent software needs to operate again, a new AID with a newinstance_idMUST be issued.All lifecycle transitions MUST be recorded in the audit trail (Level 5) with the following metadata:
- Agent URI and instance ID
- Previous state and new state
- Who triggered the transition (admin email, automated system, etc.)
- Timestamp
- Reason (free text)
Implementations SHOULD support automatic suspension when an agent's
expires_attimestamp is reached. The transition reason MUST be recorded as"aid_expired".Implementations SHOULD support configurable auto-suspend after a period of inactivity (RECOMMENDED default: 24 hours of no action requests).
7. Trust Levels
7.1 Overview
Trust levels provide graduated identity assurance. Higher trust levels indicate stronger verification of the agent's claimed identity, enabling NL-compliant systems to make more nuanced policy decisions.
Trust levels are NOT a replacement for Scope Grants (Level 2). An L3 agent with no applicable Scope Grant still cannot access any secrets. Trust levels inform eligibility; Scope Grants provide authorization.
7.2 Level Definitions
| Level | Name | How Achieved | Identity Assurance | Required Evidence |
|---|---|---|---|---|
| L0 | Self-Attested | Agent declares its own identity with no external verification. | LOW -- the agent could be impersonating another. Identity is based solely on the credential issued during registration. | Valid credential only. |
| L1 | Org-Verified | The organization that registered the agent has verified its identity through internal processes (admin approval, API key issuance, internal PKI). | MEDIUM -- the organization vouches for the agent, but no external party has verified. | Valid credential + organization admin has explicitly approved the registration. |
| L2 | Vendor-Attested | The Platform Provider (e.g., Anthropic, OpenAI, Google) has signed a JWT attesting to the agent's identity. The JWT is verifiable using the vendor's published public key. | HIGH -- a trusted external party vouches for the agent's authenticity. | Valid credential + valid attestation JWT signed by the Platform Provider. |
| L3 | Third-Party-Certified | An independent security auditor or certification body has verified the agent's identity, security properties, and NL Protocol compliance. | VERY HIGH -- independent, external verification with formal certification. | Valid credential + L2 attestation + certification document from a recognized certifier. |
7.3 Trust Level Requirements
Every AID MUST include a
trust_levelfield.An NL-compliant system MUST verify that the claimed trust level is supported by the evidence provided:
- L0: No additional evidence beyond a valid credential.
- L1: The
organization_idMUST match a registered organization, the agent credential MUST be valid, and an admin MUST have explicitly approved the agent's registration. - L2: In addition to L1, the
attestationfield MUST contain a valid, unexpired JWT signed by the Platform Provider identified in theagent_uri's vendor component. - L3: In addition to L2, the
attestationfield MUST also contain or reference a certification document from a recognized certification authority.
Scope Grants (Level 2) MAY require a minimum trust level. For example:
{ "permissions": [{ "secrets": ["production/*"], "conditions": { "min_trust_level": "L2" } }] }Implementations SHOULD log trust level mismatches as security events. For example, an L0 agent attempting to use a grant that requires L2 SHOULD be logged with severity
WARNING.
7.4 Trust Level Progression
An agent's trust level MAY be promoted over time as evidence is provided:
L0 ──(admin approval)──> L1 ──(vendor JWT)──> L2 ──(certification)──> L3
- Promotion MUST be recorded in the audit trail.
- Trust level MUST NOT be demoted. If trust in an agent is reduced, the agent SHOULD be revoked and a new AID issued at the appropriate level.
- Promotion does not require a new
instance_id; the existing AID is updated in place.
8. Platform Attestation
8.1 Overview
Platform attestation is a mechanism by which a Platform Provider (e.g., Anthropic, OpenAI, Google, GitHub) cryptographically asserts that an agent is genuine software produced and distributed by that vendor, running in a legitimate runtime context.
Attestation provides strong identity assurance without requiring the NL-compliant system to trust the agent directly. Instead, trust is delegated to the Platform Provider, whose public key is known and verifiable.
Conformance:
- Basic: Attestation is OPTIONAL (MAY).
- Standard: Attestation is REQUIRED (MUST) for all non-human agents.
- Advanced: Attestation is REQUIRED (MUST), including from third-party certifiers.
8.2 Attestation JWT Structure
The attestation is a JSON Web Token (JWT, RFC 7519) signed using JSON Web Signature (JWS, RFC 7515).
Algorithm requirements:
- MUST use an asymmetric algorithm:
ES256,ES384,RS256, orEdDSA. - MUST NOT use symmetric algorithms (
HS256,HS384,HS512). ES256(ECDSA with P-256 and SHA-256) is RECOMMENDED as the default.
8.2.1 JWT Header
{
"alg": "ES256",
"typ": "JWT",
"kid": "anthropic-nl-signing-key-2026-01"
}
| Field | Required | Description |
|---|---|---|
alg |
MUST | Signing algorithm. One of: ES256, ES384, RS256, EdDSA. |
typ |
MUST | Token type. MUST be "JWT". |
kid |
SHOULD | Key identifier for key rotation support. Maps to a key in the vendor's JWK Set. |
8.2.2 JWT Payload
{
"iss": "anthropic.com",
"sub": "nl://anthropic.com/claude-code/1.5.2",
"aud": "nl-protocol",
"iat": 1738922400,
"exp": 1738965600,
"jti": "att_550e8400-e29b-41d4-a716-446655440000",
"nl_claims": {
"agent_type": "coding_assistant",
"agent_version": "1.5.2",
"agent_build": "2026.02.01-stable",
"runtime_environment": "user-device",
"security_properties": [
"sandboxed_execution",
"no_persistent_memory",
"output_filtering",
"tool_approval_required"
],
"nl_protocol_version": "1.0",
"conformance_level": "standard"
}
}
| Field | Required | Description |
|---|---|---|
iss |
MUST | The Platform Provider's domain. MUST match the vendor component of the sub URI. |
sub |
MUST | The Agent URI being attested. MUST match nl:// format. |
aud |
MUST | Audience. MUST be "nl-protocol". |
iat |
MUST | Issued-at timestamp (Unix epoch seconds). |
exp |
MUST | Expiration timestamp (Unix epoch seconds). MUST be after iat. Maximum allowed lifetime: 24 hours. |
jti |
MUST | Unique token identifier. MUST be globally unique. Used for replay prevention. |
nl_claims |
MUST | NL Protocol-specific claims object. See below. |
8.2.3 NL Claims Object
| Claim | Required | Description |
|---|---|---|
agent_type |
MUST | The agent type. MUST match the AID's agent_type. |
agent_version |
MUST | The agent software version. MUST match the version in the Agent URI. |
agent_build |
MAY | Build identifier for additional specificity. |
runtime_environment |
SHOULD | Where the agent executes: "user-device", "cloud-hosted", "ci-cd", "container", "edge". |
security_properties |
SHOULD | List of security features the agent implements. Informational, not enforced by the protocol. |
nl_protocol_version |
MUST | The NL Protocol version the agent claims conformance with. |
conformance_level |
SHOULD | The claimed conformance level: "basic", "standard", "advanced". |
8.3 Attestation Verification
An NL-compliant system MUST verify attestation JWTs using the following procedure:
Step 1: Obtain the vendor's public key.
The system MUST obtain the Platform Provider's public key from a trusted source. Implementations MUST support at least one of the following discovery mechanisms:
Well-known URL (RECOMMENDED):
https://VENDOR/.well-known/nl-protocol/jwks.jsonThe response MUST be a JWK Set (RFC 7517). The system SHOULD cache the JWK Set and refresh it periodically (RECOMMENDED: every 1 hour) or when a
kidis not found in the cached set.Manual configuration: Admin-provided public key or JWK, configured directly in the NL-compliant system. This is acceptable for testing, development, and organizations that do not publish a well-known URL.
Step 2: Verify the JWT signature.
Using the public key identified by the kid header (or the sole key if
no kid is present), verify the JWS signature. If verification fails,
the attestation MUST be rejected.
Step 3: Validate the claims.
issMUST match the vendor domain in theagent_uri.subMUST match theagent_uriin the AID exactly.audMUST be"nl-protocol".expMUST be in the future (allowing for clock skew tolerance).iatMUST be in the past (allowing for clock skew tolerance).jtiMUST NOT have been seen before (replay prevention). The system MUST maintain a set of seenjtivalues. Entries MAY be pruned after the corresponding token'sexptime has passed.nl_claims.agent_typeMUST match the AID'sagent_type.nl_claims.nl_protocol_versionMUST be compatible with the system's supported version(s).
Step 4: Cache the result.
Implementations SHOULD cache successful verification results, keyed by
jti, for the remaining lifetime of the JWT. This avoids repeated
cryptographic operations for the same attestation within a session.
8.4 Key Distribution
Platform Providers that support NL Protocol attestation SHOULD publish their public keys at the well-known URL:
GET https://VENDOR/.well-known/nl-protocol/jwks.json
Example response:
{
"keys": [
{
"kty": "EC",
"crv": "P-256",
"kid": "anthropic-nl-signing-key-2026-01",
"use": "sig",
"alg": "ES256",
"x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
"y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
},
{
"kty": "EC",
"crv": "P-256",
"kid": "anthropic-nl-signing-key-2026-02",
"use": "sig",
"alg": "ES256",
"x": "a1b2c3...",
"y": "d4e5f6..."
}
]
}
Key rotation protocol:
- Vendor publishes a new key with a new
kid. - Vendor begins signing new attestations with the new key.
- Old key remains published until all JWTs signed with it have expired.
- Vendor removes the old key from the JWK Set.
NL-compliant systems SHOULD handle kid misses by refreshing the
JWK Set before rejecting the attestation.
9. Agent Registration
9.1 Registration Flow
Admin (Human) NL-Compliant System Platform Provider
| | |
| 1. Register Agent Request | |
| { agent_uri, type, scope, | |
| capabilities, org_id, | |
| delegated_by } | |
| ---------------------------> | |
| | |
| 2. Validate agent_uri format |
| 3. Verify org_id exists |
| 4. Generate instance_id (UUID v4) |
| 5. Generate credential (API key) |
| 6. Store credential hash (NOT plaintext)|
| 7. Create AID with lifecycle=provisioned|
| 8. Set trust_level = L1 (org-verified) |
| 9. Write audit record |
| | |
| 10. Registration Response | |
| { aid, credential } | |
| (credential shown ONCE) | |
| <--------------------------- | |
| | |
| [OPTIONAL: Request vendor attestation] |
| | |
| | 11. Request attestation |
| | { agent_uri } |
| | -------------------------> |
| | |
| | 12. Attestation JWT |
| | <------------------------- |
| | |
| 13. Verify attestation JWT |
| 14. Update AID: attestation = JWT |
| 15. Promote trust_level: L1 -> L2 |
| 16. Write audit record |
| | |
9.2 Registration Request Format
{
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"organization_id": "org_acme_corp_2024",
"agent_type": "coding_assistant",
"capabilities": ["exec", "template", "inject_stdin", "inject_tempfile"],
"scope": {
"projects": ["braincol"],
"environments": ["development", "staging"],
"categories": ["api", "database"]
},
"delegated_by": {
"type": "human",
"identifier": "andres@acme.corp"
},
"session_context": {
"ide": "vscode",
"repository": "github.com/acme-corp/backend"
},
"requested_ttl_hours": 12
}
9.3 Registration Response Format
{
"aid": {
"nl_version": "1.0",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"instance_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": "org_acme_corp_2024",
"agent_type": "coding_assistant",
"trust_level": "L1",
"capabilities": ["exec", "template", "inject_stdin", "inject_tempfile"],
"scope": {
"projects": ["braincol"],
"environments": ["development", "staging"],
"categories": ["api", "database"]
},
"delegated_by": {
"type": "human",
"identifier": "andres@acme.corp",
"delegation_time": "2026-02-08T10:00:00Z"
},
"lifecycle": "provisioned",
"created_at": "2026-02-08T10:00:00Z",
"expires_at": "2026-02-08T22:00:00Z"
},
"credential": {
"type": "api_key",
"value": "nlk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"note": "This value is shown ONCE. Store it securely. It cannot be retrieved again."
}
}
CRITICAL security requirements for credential issuance:
- The credential value MUST be returned exactly once during registration.
- The NL-compliant system MUST NOT store the plaintext credential. It MUST store only a salted, computationally expensive hash (e.g., Argon2id, bcrypt) for verification.
- The credential MUST have sufficient entropy: minimum 256 bits (RECOMMENDED: 32 bytes, base62-encoded).
- The credential prefix (
nlk_live_in the example) is OPTIONAL but RECOMMENDED for easy identification and secret scanning tools.
9.4 Credential Types
Implementations MUST support at least one of the following credential types:
| Type | Format | Use Case |
|---|---|---|
api_key |
Opaque string (e.g., nlk_live_...) |
Default. Simple, stateless authentication. |
bearer_token |
JWT or opaque token | Short-lived, suitable for CI/CD. |
mtls_certificate |
X.509 certificate | High-security environments with PKI infrastructure. |
Implementations MAY support additional credential types.
10. Example Flows
10.1 Registering a Claude Code Agent
Step 1: Admin registers the agent
An NL-compliant implementation MUST expose a registration endpoint (API, CLI, or admin console). The admin submits a registration request conforming to Section 9.2:
{
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"organization_id": "org_acme_corp_2024",
"agent_type": "coding_assistant",
"capabilities": ["exec", "template", "inject_stdin", "inject_tempfile"],
"scope": {
"projects": ["braincol"],
"environments": ["development", "staging"]
},
"delegated_by": {
"type": "human",
"identifier": "andres@acme.corp"
},
"requested_ttl_hours": 12
}
Step 2: System responds with AID and credential
The NL-compliant system returns a registration response conforming to Section 9.3:
{
"aid": {
"nl_version": "1.0",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"instance_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": "org_acme_corp_2024",
"agent_type": "coding_assistant",
"trust_level": "L1",
"lifecycle": "provisioned",
"created_at": "2026-02-08T10:00:00Z",
"expires_at": "2026-02-08T22:00:00Z"
},
"credential": {
"type": "api_key",
"value": "nlk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"note": "This value is shown ONCE. Store it securely."
}
}
Step 3: Configure the agent
The credential is placed in the agent's environment using whatever mechanism the NL-compliant implementation provides. For example, an implementation that exposes an MCP server might be configured as:
{
"mcpServers": {
"nl-secret-provider": {
"command": "nl-provider",
"args": ["mcp"],
"env": {
"NL_AGENT_USER": "claude-code",
"NL_AGENT_CREDENTIAL": "nlk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
}
}
}
}
The specific environment variable names and configuration format are implementation-defined. The example above is illustrative.
Step 4: First action activates the agent
When the agent submits its first valid action request, the NL-compliant
system transitions the lifecycle from provisioned to active and
records the activation in the audit trail.
10.2 Verifying Agent Identity on Action Request
When an NL-compliant system receives an action request, it performs identity verification before processing the action:
Agent NL-Compliant System
| |
| Action Request |
| { |
| "nl_version": "1.0", |
| "agent": { |
| "agent_uri": "nl://...", |
| "instance_id": "550e...", |
| "attestation": "eyJ..." |
| }, |
| "action": { ... } |
| } |
| ---------------------------------->|
| |
| 1. Extract agent_uri and instance_id
| 2. Look up agent in registry by instance_id
| 3. Verify credential (compare salted hash)
| 4. Check lifecycle == "active"
| 5. Check expires_at > now()
| 6. IF attestation present:
| a. Verify JWT signature against vendor public key
| b. Verify JWT claims (iss, sub, aud, exp, iat, jti)
| c. Check jti for replay
| 7. Verify trust_level is consistent with evidence
| 8. Check capabilities include requested action type
| 9. Evaluate scope against requested secret references
| 10. ALL pass? -> proceed to action processing (Level 2)
| ANY fail? -> return error with specific reason
| |
| Response |
| (action result or identity error) |
| <----------------------------------|
| |
Error response example (identity verification failure):
{
"error": {
"code": "IDENTITY_VERIFICATION_FAILED",
"reason": "Agent lifecycle is 'suspended', expected 'active'",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"instance_id": "550e8400-e29b-41d4-a716-446655440000",
"suggestion": "Contact your administrator to reactivate this agent."
}
}
10.3 Multi-Agent Delegation Identity
When an orchestrator delegates to a sub-agent, identity chains are maintained:
// Orchestrator's AID (abbreviated)
{
"agent_uri": "nl://acme.corp/orchestrator/1.0.0",
"instance_id": "aaaa-bbbb-cccc-dddd",
"agent_type": "orchestrator",
"trust_level": "L2",
"capabilities": ["exec", "delegate"],
"scope": {
"projects": ["braincol"],
"environments": ["development", "staging", "production"]
}
}
// Sub-agent's AID shows the delegation chain
{
"agent_uri": "nl://acme.corp/deploy-bot/2.1.0",
"instance_id": "eeee-ffff-0000-1111",
"agent_type": "autonomous_executor",
"trust_level": "L2",
"delegated_by": {
"type": "agent",
"identifier": "nl://acme.corp/orchestrator/1.0.0",
"parent_instance_id": "aaaa-bbbb-cccc-dddd",
"delegation_time": "2026-02-08T14:00:00Z"
},
"capabilities": ["exec"],
"scope": {
"projects": ["braincol"],
"environments": ["production"],
"categories": ["deploy"]
}
}
Identity invariants in delegation:
- The sub-agent's scope MUST be a strict subset of the orchestrator's scope.
- The sub-agent's capabilities MUST be a subset of the orchestrator's capabilities.
- The delegation chain is recorded and auditable.
- Revoking the orchestrator automatically invalidates the sub-agent's delegation authority.
11. Security Considerations
11.1 AID Confidentiality
The AID is NOT a secret. It is an identity document. However, the
credential issued during registration IS a secret and MUST be
protected accordingly. Implementations SHOULD treat credentials with the
same security posture as passwords.
11.2 Replay Prevention
Attestation JWTs include a jti (JWT ID) claim. NL-compliant systems
MUST maintain a set of seen jti values and reject duplicates. The set
SHOULD be pruned when the corresponding token's exp timestamp passes.
11.3 Instance ID Generation
The instance_id MUST be generated by the NL-compliant system, not by
the agent. This prevents agents from choosing predictable or colliding
instance IDs.
11.4 Clock Skew
Implementations MUST allow a configurable clock skew tolerance when
validating timestamps (iat, exp, expires_at, created_at).
RECOMMENDED default: 30 seconds.
11.5 Credential Rotation
Implementations SHOULD support credential rotation without requiring a
new AID. The agent's instance_id and identity persist; only the
credential value changes. Rotation MUST be recorded in the audit trail.
11.6 Agent URI Spoofing
An agent could claim an agent_uri that does not correspond to its
actual software (e.g., a malicious agent claiming to be Claude Code).
Platform attestation (Section 8) mitigates this: only Anthropic can
sign a valid attestation for nl://anthropic.com/*.
For L0 and L1 trust levels where attestation is not required, the organization takes responsibility for verifying agent identity through its internal registration process.
12. Conformance Checklist
12.1 Basic Conformance
For Basic conformance, an implementation MUST:
- Support the
nl://Agent URI format (Section 3). - Issue and validate AIDs with all required fields (Section 4.3.1).
- Enforce the agent type taxonomy (Section 5).
- Implement all four lifecycle states and valid transitions (Section 6).
- Assign trust levels L0 or L1 (Section 7).
- Support agent registration with credential issuance (Section 9).
- Validate AIDs on every action request (Section 4.4).
- Reject agents with
lifecycle != "active"orexpires_atin the past.
12.2 Standard Conformance
In addition to Basic, Standard conformance MUST:
- Require platform attestation (L2 trust level) for all non-human agents.
- Verify attestation JWTs using the vendor's public key (Section 8.3).
- Support well-known URL key discovery (Section 8.4).
- Enforce attestation expiration (
expclaim). - Implement replay prevention via
jtitracking.
12.3 Advanced Conformance
In addition to Standard, Advanced conformance MUST:
- Support L3 (third-party-certified) trust levels.
- Support delegation chains in AIDs (Section 10.3).
- Validate delegation scope as strict subset of parent scope.
- Cascade revocation through delegation chains.
13. References
- RFC 2119 -- Requirement Levels
- RFC 4122 -- UUID URN Namespace
- RFC 7515 -- JSON Web Signature (JWS)
- RFC 7517 -- JSON Web Key (JWK)
- RFC 7519 -- JSON Web Token (JWT)
- SPIFFE -- Secure Production Identity Framework
- 00-overview.md -- NL Protocol Overview
- 02-action-based-access.md -- Level 2: Action-Based Access
Copyright 2026 Braincol. This specification is licensed under CC BY 4.0.