Agent Authentication
ZewstID provides first-class support for AI agent identities. Agents are registered with unique credentials, assigned trust levels, and tracked through audit logs.
Overview
Unlike regular service accounts, agents have additional properties:
- Trust levels that control what they can access
- Capabilities that declare what they can do
- Audit trails for every action they take
- Delegation support for acting on behalf of users
┌──────────────────────────────────────────────────┐ │ Agent Lifecycle │ │ │ │ Register ──► Sandboxed ──► Registered ──► Verified │ │ │ Trust Level: untrusted basic elevated │ │ Capabilities: limited standard full │ │ Audit: all logged all logged all logged│ └──────────────────────────────────────────────────┘
Registering an Agent
Via the Developer Portal
- Navigate to Agents in the left sidebar
- Click Register Agent
- Fill in the agent details:
- Name — A descriptive name (e.g., "Customer Support Bot")
- Type — ,
autonomous, oruser-delegatedservice - Description — What the agent does
- Capabilities — What the agent can do (e.g., ,
read_users)send_notifications
- Click Register — you'll receive credentials
Via the API
curl -X POST https://api.zewstid.com/api/v1/agents \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Customer Support Bot", "type": "autonomous", "description": "Handles tier-1 support tickets", "capabilities": ["read_users", "read_tickets", "send_notifications"] }'
Response:
{ "id": "agent_xyz789", "clientId": "agent-customer-support-bot", "clientSecret": "zs_agent_secret_xxxxx", "name": "Customer Support Bot", "type": "autonomous", "trustLevel": "sandboxed", "capabilities": ["read_users", "read_tickets", "send_notifications"], "status": "active", "createdAt": "2026-02-20T10:00:00Z" }
Agent Types
| Type | Description | Use Case |
|---|---|---|
autonomous | Acts independently without user interaction | Background processing, monitoring |
user-delegated | Acts on behalf of a user with delegated permissions | AI assistants, user-facing bots |
service | Internal service-to-service communication | Microservice backends |
Trust Levels
Agents start at
sandboxed| Level | Access | Promotion Rule |
|---|---|---|
sandboxed | Read-only, rate-limited, no delegation | Default for new agents |
registered | Standard API access, basic delegation | Manual promotion by admin |
verified | Full API access, delegation, A2A exchange | After review and audit |
privileged | Admin-level access, cross-tenant operations | Requires explicit approval |
Updating Trust Level
Via the portal: Use the trust level dropdown on each agent card.
Via the API:
curl -X POST https://api.zewstid.com/api/v1/agents/agent_xyz789/trust \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "trustLevel": "registered", "reason": "Completed sandbox testing successfully" }'
Capabilities
Capabilities declare what an agent can do. They are checked at runtime when the agent makes API calls.
Built-in Capabilities
| Capability | Description |
|---|---|
read_users | Read user profiles |
write_users | Create and update users |
read_tickets | Access support tickets |
send_notifications | Send emails/push notifications |
manage_sessions | List and revoke sessions |
read_analytics | Access analytics data |
delegate | Request delegation from users |
a2a_exchange | Exchange tokens with other agents |
Managing Capabilities
# Get current capabilities curl https://api.zewstid.com/api/v1/agents/agent_xyz789/capabilities \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" # Update capabilities curl -X PUT https://api.zewstid.com/api/v1/agents/agent_xyz789/capabilities \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "capabilities": ["read_users", "send_notifications", "delegate"] }'
Getting Agent Tokens
Agents authenticate the same way as service accounts — using
client_credentialscurl -X POST https://api.zewstid.com/api/v1/oauth/token \ -H "Content-Type: application/json" \ -d '{ "grant_type": "client_credentials", "client_id": "agent-customer-support-bot", "client_secret": "zs_agent_secret_xxxxx" }'
The returned token includes agent metadata:
{ "access_token": "eyJhbGciOiJSUzI1NiIs...", "token_type": "Bearer", "expires_in": 3600, "agent_id": "agent_xyz789", "trust_level": "registered" }
Audit Log
Every agent action is recorded in the audit log. View it via the API:
curl https://api.zewstid.com/api/v1/agents/agent_xyz789/audit \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response:
{ "entries": [ { "timestamp": "2026-02-20T10:05:00Z", "action": "token_issued", "ip": "10.0.0.5", "details": { "scopes": ["users:read"] } }, { "timestamp": "2026-02-20T10:05:01Z", "action": "api_call", "endpoint": "GET /api/v1/m2m/users", "status": 200 } ] }
Node SDK Usage
The
@zewstid/nodeZewstIDAgentimport { ZewstIDAgent } from '@zewstid/node'; const agent = new ZewstIDAgent({ domain: 'auth.zewstid.com', clientId: process.env.AGENT_CLIENT_ID!, clientSecret: process.env.AGENT_CLIENT_SECRET!, agentId: 'agent_xyz789', }); // Get a token (cached and refreshed automatically) const token = await agent.getToken(); // Request delegation from a user const delegation = await agent.requestDelegation({ userId: 'user_123', scopes: ['profile:read', 'orders:read'], reason: 'Access your order history for support', expiresIn: 3600, }); // List delegations const delegations = await agent.listDelegations();
Security Considerations
- Credential storage — Store agent secrets in environment variables or a secrets manager
- Least privilege — Only request capabilities the agent actually needs
- Trust escalation — Start agents at and promote gradually
sandboxed - Audit review — Regularly review agent audit logs for anomalies
- Credential rotation — Rotate agent credentials every 90 days
- Revocation — Disable agents immediately if compromised
Kill Switch
The kill switch provides instant, defense-in-depth agent termination. When activated, the agent is simultaneously blacklisted in the real-time cache (for immediate token rejection) and disabled at the identity provider level (for persistent disablement).
Activating the Kill Switch
curl -X POST https://api.zewstid.com/api/v1/agents/agent_xyz789/kill \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "reason": "Agent exhibiting unauthorized data access patterns" }'
Response:
{ "success": true, "agentId": "agent_xyz789", "status": "killed", "killedAt": "2026-02-20T15:30:00Z", "reason": "Agent exhibiting unauthorized data access patterns" }
Once killed, all existing tokens are immediately rejected and new token requests fail. The agent receives an
AgentKilledErrorRecovering an Agent
curl -X POST https://api.zewstid.com/api/v1/agents/agent_xyz789/recover \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN"
Recovery re-enables the agent at the identity provider level and removes the real-time blacklist entry. A new client secret is issued — the old secret is permanently invalidated.
Viewing Kill Events
curl https://api.zewstid.com/api/v1/agents/agent_xyz789/kill-events \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN"
Returns the full kill/recover history for audit purposes.
SDK Usage
import { ZewstIDAgent, AgentKilledError } from '@zewstid/node'; const agent = new ZewstIDAgent({ /* config */ }); try { const token = await agent.getToken(); } catch (err) { if (err instanceof AgentKilledError) { console.error('Agent has been killed:', err.message); process.exit(1); } }
Human-in-the-Loop (HITL)
HITL policies require human approval before agents can execute sensitive actions. Policies match requests using glob patterns on action and resource fields, with configurable approval modes and timeouts.
Creating a Policy
curl -X POST https://api.zewstid.com/api/v1/agents/hitl/policies \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Require approval for user deletion", "actionPattern": "delete_*", "resourcePattern": "users/*", "approvalMode": "async", "timeoutSeconds": 300, "approverType": "user", "approverId": "user_admin_123", "autoDenyOnTimeout": true, "priority": 10 }'
Policy fields:
| Field | Description |
|---|---|
actionPattern | Glob pattern matched against the action (e.g., delete_*transfer_funds |
resourcePattern | Glob pattern matched against the resource (e.g., users/*accounts/prod/* |
approvalMode | syncasync |
timeoutSeconds | How long before the request expires (1-3600) |
approverType | userrole |
approverId | User ID or role name of the approver |
autoDenyOnTimeout | If true |
priority | Higher priority policies are evaluated first |
Managing Policies
# List all policies curl https://api.zewstid.com/api/v1/agents/hitl/policies \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" # Update a policy curl -X PATCH https://api.zewstid.com/api/v1/agents/hitl/policies/policy_123 \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "timeoutSeconds": 600, "autoDenyOnTimeout": false }' # Delete a policy curl -X DELETE https://api.zewstid.com/api/v1/agents/hitl/policies/policy_123 \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN"
Requesting Approval (Agent Side)
curl -X POST https://api.zewstid.com/api/v1/agents/hitl/request \ -H "Authorization: Bearer AGENT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "action": "delete_user", "resource": "users/user_456", "context": { "reason": "Account cleanup", "requestedBy": "support_agent" } }'
Response:
{ "requestId": "hitl_req_abc123", "status": "pending_approval", "expiresAt": "2026-02-20T15:35:00Z" }
Polling for Approval
curl https://api.zewstid.com/api/v1/agents/hitl/request/hitl_req_abc123 \ -H "Authorization: Bearer AGENT_TOKEN"
Returns
pending_approvalapproveddeniedexpiredApproving / Denying (Human Side)
# Approve curl -X POST https://api.zewstid.com/api/v1/agents/hitl/request/hitl_req_abc123/approve \ -H "Authorization: Bearer APPROVER_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "reason": "Verified account cleanup is appropriate" }' # Deny curl -X POST https://api.zewstid.com/api/v1/agents/hitl/request/hitl_req_abc123/deny \ -H "Authorization: Bearer APPROVER_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "reason": "User still has active subscriptions" }'
SDK Usage
const approval = await agent.requestApproval({ action: 'delete_user', resource: 'users/user_456', context: { reason: 'Account cleanup' }, }); // Poll until resolved let status = await agent.getApprovalStatus(approval.requestId); while (status.status === 'pending_approval') { await new Promise(r => setTimeout(r, 2000)); status = await agent.getApprovalStatus(approval.requestId); } if (status.status === 'approved') { // Proceed with action }
JIT (Just-In-Time) Privileges
JIT allows agents to request short-lived elevated privileges for specific actions. Grants can be auto-approved based on policy or require HITL approval.
Requesting a JIT Grant
curl -X POST https://api.zewstid.com/api/v1/jit/request \ -H "Authorization: Bearer AGENT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "action": "read_pii", "resource": "users/user_789/profile", "scopes": ["users:read:pii"], "duration": 300, "context": { "ticketId": "SUPPORT-1234" } }'
Response:
{ "grantId": "jit_grant_xyz", "status": "active", "expiresAt": "2026-02-20T15:35:00Z", "scopes": ["users:read:pii"] }
If HITL approval is required,
statuspending_approvalGrant Lifecycle
Request ──► pending_approval ──► active ──► expired │ │ ▼ ▼ denied revoked
Checking Grant Status
curl https://api.zewstid.com/api/v1/jit/grants/jit_grant_xyz/status \ -H "Authorization: Bearer AGENT_TOKEN"
Revoking a Grant (Admin)
curl -X POST https://api.zewstid.com/api/v1/jit/grants/jit_grant_xyz/revoke \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "reason": "Security incident" }'
SDK Usage
const grant = await agent.requestJIT({ action: 'read_pii', resource: 'users/user_789/profile', duration: 300, }); if (grant.status === 'active') { // Use elevated privileges within the TTL } const status = await agent.getJITStatus(grant.grantId);
RAR (Rich Authorization Requests)
RAR implements RFC 9396 to provide fine-grained authorization. Instead of broad scopes, agents request specific
authorization_detailsRegistering an Authorization Type
curl -X POST https://api.zewstid.com/api/v1/rar/types \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "payment_transfer", "displayName": "Payment Transfer", "description": "Authorization for fund transfers", "allowedActions": ["initiate", "approve", "cancel"], "allowedLocations": ["us", "eu"], "schema": { "type": "object", "properties": { "amount": { "type": "number", "maximum": 10000 }, "currency": { "type": "string", "enum": ["USD", "EUR", "GBP"] }, "recipient": { "type": "string" } }, "required": ["amount", "currency", "recipient"] } }'
Listing and Retrieving Types
# List all types curl https://api.zewstid.com/api/v1/rar/types \ -H "Authorization: Bearer YOUR_TOKEN" # Get a specific type (includes JSON Schema) curl https://api.zewstid.com/api/v1/rar/types/payment_transfer \ -H "Authorization: Bearer YOUR_TOKEN"
Requesting a Token with RAR
Include
authorization_detailscurl -X POST https://api.zewstid.com/api/v1/oauth/token \ -H "Content-Type: application/json" \ -d '{ "grant_type": "client_credentials", "client_id": "agent-payment-bot", "client_secret": "zs_agent_secret_xxxxx", "authorization_details": [ { "type": "payment_transfer", "actions": ["initiate"], "locations": ["us"], "amount": 500, "currency": "USD", "recipient": "merchant_abc" } ] }'
The server validates the request against the registered JSON Schema and the agent's capability ceiling. If valid, the authorization details are bound to the token.
Validating Authorization Details
curl -X POST https://api.zewstid.com/api/v1/rar/validate \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "authorization_details": [ { "type": "payment_transfer", "actions": ["initiate"], "amount": 500, "currency": "USD", "recipient": "merchant_abc" } ] }'
SDK Usage
const token = await agent.getTokenWithRAR([ { type: 'payment_transfer', actions: ['initiate'], locations: ['us'], amount: 500, currency: 'USD', recipient: 'merchant_abc', }, ]);
Workload Identity Federation (WIF)
WIF enables secretless authentication for agents running on cloud platforms (Kubernetes, AWS, GCP, Azure). Instead of storing client secrets, agents exchange their platform-issued identity tokens for ZewstID tokens.
How It Works
┌─────────────────┐ platform token ┌──────────────┐ ZewstID token ┌─────────────┐ │ Cloud Platform │ ──────────────────► │ ZewstID API │ ──────────────► │ Agent uses │ │ (k8s, AWS, GCP) │ │ /oauth/token │ │ ZewstID API │ └─────────────────┘ └──────────────┘ └─────────────┘
Registering a Trusted Issuer
curl -X POST https://api.zewstid.com/api/v1/workload-identity/issuers \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Production K8s Cluster", "issuerUrl": "https://oidc.eks.us-east-1.amazonaws.com/id/ABCDEF1234567890", "jwksUri": "https://oidc.eks.us-east-1.amazonaws.com/id/ABCDEF1234567890/keys", "platform": "kubernetes", "allowedAudiences": ["sts.amazonaws.com"], "allowedSubjects": ["system:serviceaccount:agents:*"], "maxTokenAgeSeconds": 3600 }'
Creating Identity Mappings
Map platform identities to ZewstID agent identities:
curl -X POST https://api.zewstid.com/api/v1/workload-identity/mappings \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "issuerId": "issuer_abc123", "agentClientId": "agent-payment-bot", "subjectPattern": "system:serviceaccount:agents:payment-bot", "subjectMatchType": "exact", "scopes": ["payments:read", "payments:write"] }'
Token Exchange
Agents exchange their platform token for a ZewstID token:
curl -X POST https://api.zewstid.com/api/v1/oauth/token \ -H "Content-Type: application/json" \ -d '{ "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", "subject_token": "eyJhbGciOiJSUzI1NiIs...", "subject_token_type": "urn:ietf:params:oauth:token-type:jwt" }'
Platform Examples
Kubernetes:
apiVersion: v1 kind: ServiceAccount metadata: name: payment-bot namespace: agents annotations: zewstid.com/agent-client-id: "agent-payment-bot"
import { ZewstIDAgent } from '@zewstid/node'; const agent = new ZewstIDAgent({ clientId: 'agent-payment-bot', agentId: 'agent_payment_bot', workloadIdentity: { platform: 'kubernetes', tokenPath: '/var/run/secrets/tokens/zewstid-token', }, }); // No client secret needed — uses service account token const token = await agent.getToken();
AWS (IAM Roles):
const agent = new ZewstIDAgent({ clientId: 'agent-payment-bot', agentId: 'agent_payment_bot', workloadIdentity: { platform: 'aws', roleArn: 'arn:aws:iam::123456789:role/agent-role', }, });
GCP (Service Accounts):
const agent = new ZewstIDAgent({ clientId: 'agent-payment-bot', agentId: 'agent_payment_bot', workloadIdentity: { platform: 'gcp', serviceAccountEmail: '[email protected]', }, });
Intent Metadata
Intent metadata provides structured context for every agent action, enabling end-to-end traceability across multi-agent chains. Agents attach intent headers to their API calls, which are recorded in the audit log.
Standard Headers
| Header | Description | Example |
|---|---|---|
X-ZewstID-Task-ID | Unique task identifier | task_abc123 |
X-ZewstID-Chain-ID | Chain identifier for multi-hop requests | chain_xyz789 |
X-ZewstID-Intent-Action | What the agent intends to do | process_refund |
X-ZewstID-Intent-Reason | Why the action is being taken | Customer requested refund |
X-ZewstID-Intent-Initiator | Who/what initiated the action | support_agent |
X-ZewstID-Intent-Depth | Hop level in the chain | 012 |
X-ZewstID-Parent-Task-ID | Previous task in the chain | task_parent_456 |
Querying by Task
curl "https://api.zewstid.com/api/v1/audit/intent/tasks/task_abc123?limit=50" \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN"
Querying by Chain
# All entries in a chain curl "https://api.zewstid.com/api/v1/audit/intent/chains/chain_xyz789" \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN" # Ordered trace (hop-by-hop execution path) curl "https://api.zewstid.com/api/v1/audit/intent/chains/chain_xyz789/trace" \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN"
Searching Audit Entries
curl "https://api.zewstid.com/api/v1/audit/intent/search?intentAction=process_refund&from=2026-02-01&to=2026-02-28" \ -H "Authorization: Bearer YOUR_ADMIN_TOKEN"
Query parameters:
agentClientIdintentActionintentInitiatorfromtolimitoffsetSDK Usage
// Set intent for subsequent API calls agent.setIntent({ action: 'process_refund', reason: 'Customer requested refund for order #1234', initiator: 'support_agent', taskId: 'task_abc123', chainId: 'chain_xyz789', }); // All subsequent API calls include intent headers const result = await agent.processRefund(orderId); // Get current intent const intent = agent.getIntent(); // Clear intent when done agent.clearIntent();
Next Steps
- M2M Authentication — Service account basics
- Delegation & A2A — Agent delegation and token exchange
- Node.js SDK Reference — class docs
ZewstIDAgent
Was this page helpful?
Let us know how we can improve our documentation