Address
NFTAuth AgentGuard / Developer Documentation
Connected
Welcome to NFTAuth AgentGuard
DEV PREVIEWNFTAuth Project presents

NFTAuth AgentGuard

A device-bound authorization SDK for OpenAI agents. Developers wrap sensitive agent tools so the agent can research and prepare actions, but cannot execute the exact sensitive action until it is cryptographically approved by the intended user on an enrolled device.

Install SDKOpen Sandbox

System Information

Product:
NFTAuth AgentGuard
SDK:
@nftauth/agentguard
Version:
0.1.0
Runtime:
Node.js
Status:
Developer Preview
The control gap

Credentials authorize an agent. They do not prove user intent.

The problem

Valid access can still produce the wrong action.

An agent can spend too much, message the wrong person, delete the wrong data, deploy to the wrong environment, share confidential files, or follow malicious and misunderstood instructionsβ€”even while holding legitimate account credentials. The threat also includes deliberate interference: a bad actor, compromised service, injected instruction, or unauthorized person may try to make your agent act without your knowledge. Possession of credentials alone must never let someone else silently direct a protected action.

The solution

Bind approval to the complete prepared action.

AgentGuard separates reasoning, action preparation, user authorization, and final execution. Research remains free. A sensitive function pauses until the enrolled device approves its exact material payload.

Product components

One protection path, four focused pieces.

01

AgentGuard SDK

Framework-independent Node wrapper at the sensitive execution boundary.

02

Authorization API

Creates, binds, expires, verifies, and transitions exact-action requests.

03

NFTAuth mobile app

Private-beta iOS app for device-bound review, unlock, approve, and deny.

04

Sandbox

Publicly testable simulation of policy, tampering, replay, expiry, and isolation.

Architecture

The agent proposes. The device decides. The server verifies.

Ten-minute quickstart

Protect one sensitive function.

Developer Preview credentials are currently issued manually by NFTAuth Project. There is no self-service developer dashboard yet.

  1. Install the local SDK package.

    Repository installation β€” available now
    npm install ./packages/agentguard-sdk
    Packed archive installation β€” available now
    npm pack ./packages/agentguard-sdk
    npm install ./nftauth-agentguard-0.1.0.tgz
    Planned public npm release β€” not currently published
    npm install @nftauth/agentguard
  2. Configure credentials.

    Environment β€” trusted server only
    NFTA_API_BASE=https://api-staging.nftauthproject.com
    NFTA_AGENT_ID=your-issued-agent-id
    NFTA_AGENT_CREDENTIAL=your-issued-server-credential

    Never expose the credential in Webflow, browser JavaScript, an iOS bundle, or model context.

  3. Initialize AgentGuard on your Node server.

    Continue with the complete server-side example below.

  4. Protect a sensitive tool.

    Wrap one sensitive tool execution.

  5. Enroll or select the user.

    Register or select the enrolled NFTAuth user.

  6. Run the agent.

    Run the OpenAI agent.

  7. Approve from the device.

    Review and approve the exact action on the enrolled device.

  8. Execute exactly once.

    Confirm the original function executes once.

OpenAI integrations

Wrap the function you control.

AgentGuard is framework-independent. It protects developer-hosted function execution; it does not modify OpenAI-hosted tools without a local execution boundary.

OpenAI Agents SDK

Complete server-side example
import { Agent, run, tool } from '@openai/agents';
import { z } from 'zod';
import { AgentGuard, AuthorizationDeniedError,
  AuthorizationExpiredError } from '@nftauth/agentguard';

const guard = new AgentGuard({
  apiBase: process.env.NFTA_API_BASE,
  agentId: process.env.NFTA_AGENT_ID,
  agentCredential: process.env.NFTA_AGENT_CREDENTIAL
});

const protectedSend = guard.protect({
  action: 'send_email',
  getUserId: (_args, runContext) => runContext.context.userId,
  buildApprovalPayload: (args) => ({
    recipient: args.to, subject: args.subject, message_preview: args.body
  }),
  execute: (args, runContext) => runContext.context.emailService.send(args)
});

const sendEmail = tool({
  name: 'send_email',
  description: 'Send an email after exact-action approval.',
  parameters: z.object({
    to: z.string().email(), subject: z.string().min(1), body: z.string().min(1)
  }),
  execute: protectedSend
});

const agent = new Agent({ name: 'Personal operations agent', model: 'gpt-5.6',
  instructions: 'Prepare useful actions. Sensitive execution needs approval.',
  tools: [sendEmail] });

const userId = 'enrolled-user@example.com';
const emailService = { send: async (message) => ({ accepted: true, message }) };

try {
  const result = await run(agent, 'Tell my manager I am 15 minutes late.', {
    context: { userId, emailService }
  });
  console.log(result.finalOutput);
} catch (error) {
  if (error instanceof AuthorizationDeniedError ||
      error instanceof AuthorizationExpiredError) {
    console.log('The sensitive tool did not execute.');
  } else throw error;
}

Responses API function loop

Protect the custom tool dispatcher
import OpenAI from 'openai';
import { AgentGuard } from '@nftauth/agentguard';

const openai = new OpenAI();
const guard = new AgentGuard({ apiBase: process.env.NFTA_API_BASE,
  agentId: process.env.NFTA_AGENT_ID,
  agentCredential: process.env.NFTA_AGENT_CREDENTIAL });

const transfer = guard.protect({
  action: 'transfer_money',
  getUserId: (_args, ctx) => ctx.userId,
  buildApprovalPayload: ({ recipient, amount, memo }) =>
    ({ recipient, amount, memo }),
  execute: (args, ctx) => ctx.payments.transfer(args)
});
const context = { userId: 'enrolled-user@example.com',
  payments: { transfer: async (input) => ({ completed: true, input }) } };

const tools = [{ type: 'function', name: 'transfer_money', strict: true,
  description: 'Transfer money after NFTAuth approval.',
  parameters: { type: 'object', properties: {
    recipient: { type: 'string' }, amount: { type: 'string' },
    memo: { type: 'string' }
  }, required: ['recipient', 'amount', 'memo'], additionalProperties: false }
}];
let response = await openai.responses.create({
  model: 'gpt-5.6', input: 'Transfer $250 to Alex.', tools
});
const outputs = [];
for (const item of response.output) {
  if (item.type !== 'function_call') continue;
  const result = await transfer(JSON.parse(item.arguments), context,
    { toolCall: { callId: item.call_id } });
  outputs.push({ type: 'function_call_output', call_id: item.call_id,
    output: JSON.stringify(result) });
}
if (outputs.length) response = await openai.responses.create({
  model: 'gpt-5.6', previous_response_id: response.id, input: outputs, tools
});
console.log(response.output_text);
Policy ownership

The developer decides what must stop.

The phone does not decide developer policy, and the SDK protects only explicitly wrapped functions. Read-only research normally does not require approval. Spend, transfer, send, delete, deploy, disclose, publish, permission, and external-modification functions normally do.

Reusable sample policy
const { SENSITIVE_ACTION_POLICY, requiresAgentGuard } =
  require('@nftauth/agentguard/policy');

// Included policy groups: purchases, transfers, emailAndMessaging,
// deletion, productionDeployment, sensitiveFileSharing,
// permissionChanges, publicPosting, calendarModifications.
if (requiresAgentGuard(actionName, SENSITIVE_ACTION_POLICY)) {
  execute = guard.protect(protectedToolConfiguration);
}

The Sandbox policy controls demonstrate this same developer choice visually.

Connecting the mobile application

Route an exact action to its enrolled user.

Current Build Week implementation

The private-beta iOS app registers an email identity, verifies an email code, creates the wallet and non-transferable NFT identity, creates a Secure Enclave P-256 device signing key, stores the registration PIN hash, and uploads its current FCM token through the signed device flow. The server maps the SDK's configured user_id to that enrollment. An authorization push contains only the request ID; the app signs nftauth.agent-action.v1|mobile-fetch|request_id|user_id|timestamp, downloads the complete protected action, validates request ID, owner, status, expiry, and canonical payload hash, then displays the material purchase details. PIN or hardware-card unlock enables approval; denial is available. Its decision signs nftauth.agent-action.v1|mobile-decision|request_id|nonce|decision|payload_hash|timestamp. The server verifies identity, key, NFT/device binding, hash, nonce, timestamp, ownership, expiry, and state before transitioning the request. Developer Preview access can rely on manually configured, pre-enrolled test accounts.

Intended production onboarding β€” planned

Self-service developer and user linking, credential issuance, account selection, lifecycle management, and broader mobile distribution are planned architecture. QR linking, deep links, connection codes, a developer dashboard, and App Store availability are not part of the current implementation.

Mobile application walkthrough

Registration and credential setup
NFTAuth AgentGuard registration screen on iPhone
Email confirmation, wallet/NFT setup, Secure Enclave device key, registration PIN, push enrollment.
Incoming action review
Locked purchase authorization review in NFTAuth AgentGuard
Agent, requested time, product, merchant, quantity, item price, shipping, tax, and total.
Unlock and decision
Unlocked NFTAuth AgentGuard purchase approval screen
Existing PIN sheet or hardware-card option; approve after unlock or deny.
Recovery and security settings
NFTAuth AgentGuard security and device settings screen
Existing recovery and settings surfaces in the private-beta app.
API reference

The exact endpoints used by the SDK.

POST /v1/agent-authorizations

Creates or idempotently replays one pending authorization. Requires Authorization: Bearer <agent credential> and Idempotency-Key.

Strict request body
{
  "schema": "nftauth.agent-action.v1",
  "agent_id": "agent_example",
  "user_id": "enrolled-user@example.com",
  "run_id": "run_123",
  "tool_call": { "id": "call_123", "name": "purchase", "version": "1",
    "arguments": { "product": "Example", "merchant": "Example Shop", "total": "99.00" } }
}
HTTP 202 response
{
  "success": true, "message": "Awaiting NFTAuth approval.",
  "request_id": "aar_…", "status": "pending", "payload_hash": "sha256:…",
  "agent_id": "agent_example", "user_id": "enrolled-user@example.com",
  "run_id": "run_123", "tool_call_id": "call_123", "tool_name": "purchase",
  "created_at": "2026-07-21T12:00:00.000Z",
  "expires_at": "2026-07-21T12:02:00.000Z", "delivery_status": "sent",
  "resume_handle": "returned only to the trusted agent server",
  "idempotent_replay": false
}
GET /v1/agent-authorizations/:request_id

Returns sanitized agent-visible status. Requires the same bearer credential. The SDK verifies request ID, agent ID, user ID, run ID, tool-call identity, and payload hash on every response.

Status response
{
  "success": true, "request_id": "aar_…",
  "status": "pending | approved | denied | expired", "payload_hash": "sha256:…",
  "agent_id": "agent_example", "user_id": "enrolled-user@example.com",
  "run_id": "run_123", "tool_call_id": "call_123", "tool_name": "purchase",
  "created_at": "2026-07-21T12:00:00.000Z",
  "expires_at": "2026-07-21T12:02:00.000Z", "delivery_status": "sent"
}

Common failures include 401 invalid agent credential, 400 malformed strict action (including a payload over the module's 64 KiB limit), 403 agent identity mismatch, 404 unknown or inaccessible request, 409 enrollment/idempotency conflict, 410 expiry, 429 rate limiting, and fail-closed 503 dependency errors. Denial is terminal status denied.

SDK reference

Small surface, explicit outcomes.

APIPurpose
new AgentGuard(options)Configure API base, agent ID, credential, polling, authorization/request timeouts, fetch, and optional atomic execution store.
requestAuthorization(options)Validate and create a strict pending exact-action request.
waitForDecision(request, options?)Poll and verify until approved, denied, expired, or timed out.
authorize(options)Create and wait without executing.
authorizeAndExecute(options)Authorize, atomically claim, call execute once, and return its result.
protect(config)Wrap a sensitive function using user lookup and material-payload mapping callbacks.
MemoryExecutionStoreSingle-process replay claim. Supply shared atomic storage for multi-process deployments.

Typed errors

All extend AgentGuardError: AgentGuardConfigurationError, AuthorizationDeniedError, AuthorizationExpiredError, AuthorizationUnavailableError, PayloadMismatchError, AuthorizationReplayError, InvalidApiResponseError, AuthorizationTimeoutError, and AgentGuardRateLimitError. Safe properties include code, and when applicable status, requestId, and retryAfter.

Security guarantees

Approval is verified, not inferred.

Device-bound signing

The enrolled device key signs the decision; the backend verifies it server-side with NFT/device enrollment.

Exact payload binding

Canonical hashing binds identity, run, tool, version, and every material argument.

Freshness

Expiration, timestamp, a 256-bit nonce, and atomic state transitions reject stale or replayed decisions.

Fail closed

Denial, expiry, mismatch, malformed data, network failure, or unverified status prevents execution.

Execution is claimed once before the callback. The existing Redis-backed agent-run path provides distributed execution locking; SDK users running multiple Node processes must provide an atomic shared executionStore. Isolated sandbox state never grants production approval.

Threat demonstrations

Open the Sandbox to attempt payload tampering, consumed-approval replay, forced expiration, denial, policy bypass for intentionally non-sensitive actions, and cross-session access.

Availability

What is available today.

  • SDK: Developer Preview, included in the project repository.
  • Authorization API: live demonstration environment.
  • Sandbox: publicly testable simulation.
  • iOS app: private beta, not currently publicly listed in the App Store.
  • Production self-service onboarding: planned.
  • Real external actions: limited to the integrations specifically implemented by the developer.
OpenAI Build Week

From working authorization platform to reusable agent protection.

Build Week produced the GPT-5.6 agent orchestration, agent authorization bridge, strict agent action schema, device-bound action approval integration, agent-run lifecycle, exactly-once execution controls, sandbox, reusable AgentGuard SDK, and this developer documentation. The underlying NFTAuth platform, deployed contract, identity work, mobile foundations, and patent predate Build Week.