Beltic logo
Getting Started

Quickstart - Agent Identity Verification with FACT

Get started with FACT credentials for AI agent identity verification. Learn KYA (Know Your Agent) workflows, self-signing credentials, and agent authentication in under 30 minutes.

This guide provides the fastest path to issuing and validating your first Beltic credential for agentic identity and agent identity verification. You'll learn KYA (Know Your Agent) workflows, pick a template, customize it, validate the structure, sign it (including self-signing), and verify the signature.

What You'll Learn

  • How to select and customize a credential template
  • How to validate credentials against JSON schemas
  • How to sign credentials with the CLI or SDK
  • How to verify credential signatures

Prerequisites

Before starting, ensure you have the following installed:

Required

  • Node.js 18+ - Install Node.js
  • Git - For cloning the beltic-spec repository

Choose Your Path

CLI Prerequisites

Install the Beltic CLI:

# Homebrew (macOS/Linux)
brew tap belticlabs/tap
brew install beltic

# Or shell script
curl -fsSL https://raw.githubusercontent.com/belticlabs/beltic-cli/master/install.sh | sh

Verify installation:

beltic --version
# Output: beltic 0.1.0

SDK Prerequisites

Install the TypeScript SDK:

npm install @belticlabs/kya

Validator (Both Paths)

Choose one JSON Schema validator:

Option 1: AJV CLI

npm install -g ajv-cli ajv-formats

Option 2: Python jsonschema

pip install jsonschema

Step 1: Get the Spec Repository

Clone the beltic-spec repository for schemas and templates:

git clone https://github.com/belticlabs/beltic-spec.git
cd beltic-spec

Step 2: Pick a Template

Choose a template based on your use case:

DeveloperCredential Templates

Located in examples/developer/v1/tests/:

  • valid-individual-minimal.json - Solo developer, basic verification
  • valid-individual-complete.json - Individual with full KYB
  • valid-organization-tier1.json - Startup, basic organization info
  • valid-organization-tier2-complete.json - Established company with enhanced KYB

AgentCredential Templates

Located in examples/agent/v1/tests/:

  • valid-simple-agent.json - Basic agent with minimal fields
  • valid-complex-agent.json - Full-featured agent with all optional fields

Step 3: Copy and Customize

Copy your chosen template and edit the key fields:

cp examples/developer/v1/tests/valid-individual-minimal.json my-dev-cred.json

Edit my-dev-cred.json and update:

  • credentialId - Generate a new UUID
  • legalName - Your legal name or business name
  • entityType - "individual" or "organization"
  • subjectDid - Your DID (e.g., did:web:example.com or did:key:...)
  • issuerDid - Issuer's DID
  • issuanceDate - Current date in ISO 8601 format
  • expirationDate - Expiration date (typically 6-12 months from issuance)

Example (showing required fields for individual):

{
  "credentialId": "550e8400-e29b-41d4-a716-446655440000",
  "legalName": "Jane Developer",
  "entityType": "individual",
  "incorporationJurisdiction": { "country": "US" },
  "businessRegistrationStatus": "not_applicable",
  "taxIdExists": false,
  "kybTier": "tier_0_unverified",
  "sanctionsScreeningStatus": "not_screened",
  "overallRiskRating": "not_assessed",
  "issuanceDate": "2025-01-15T10:00:00Z",
  "expirationDate": "2026-01-15T10:00:00Z",
  "issuerDid": "did:web:issuer.beltic.dev",
  "subjectDid": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
  "credentialStatus": "active"
}

Use the CLI for developer credentials. The beltic dev-init command generates a valid self-attested developer credential with prompts:

beltic dev-init

Step 4: Validate the Credential

Validate your credential against the JSON schema before signing:

Using AJV CLI

ajv validate \
  -s schemas/developer/v1/developer-credential-v1.schema.json \
  -d my-dev-cred.json

Expected output (success):

my-dev-cred.json valid

Expected output (error):

my-dev-cred.json invalid
[
  {
    "instancePath": "/legalName",
    "message": "must be string"
  }
]

Using Python

python3 scripts/validate_all.py

Using npm Scripts

# Validate all developer credentials in examples/
npm run validate:developer

# Validate all agent credentials
npm run validate:agent

# Run conditional rule tests
npm run test:conditional-rules

CLI Path

Step 5: Generate Keys

Generate a keypair for signing:

beltic keygen --alg EdDSA --out private.pem --pub public.pem

Expected output:

Generated EdDSA keypair
Private key: private.pem
Public key: public.pem

Step 6: Sign the Credential

Sign your credential to create a JWS token:

beltic sign \
  --payload my-dev-cred.json \
  --key private.pem \
  --out credential.jwt

Expected output:

Credential signed successfully
Token written to: credential.jwt
Token size: 2847 bytes

The CLI performs schema validation before signing. To skip validation (not recommended):

beltic sign --payload my-dev-cred.json --key private.pem --skip-schema

Step 7: Verify the Credential

Verify the signature and schema:

beltic verify \
  --token credential.jwt \
  --key public.pem

Expected output:

✓ Signature valid
✓ Claims valid
✓ Schema valid
Credential ID: 550e8400-e29b-41d4-a716-446655440000
Subject: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
Issuer: did:web:issuer.beltic.dev
Issued: 2025-01-15T10:00:00Z
Expires: 2026-01-15T10:00:00Z

SDK Path

Step 5: Validate with SDK

import { validateDeveloperCredential } from '@belticlabs/kya';
import { readFileSync } from 'fs';

// Load credential from file
const credential = JSON.parse(readFileSync('my-dev-cred.json', 'utf-8'));

// Validate the credential
const result = validateDeveloperCredential(credential);

if (!result.valid) {
  console.error('Validation errors:', result.errors);
  process.exit(1);
}

console.log('Credential is valid!');
console.log('Legal name:', result.data.legalName);

Step 6: Sign with External Library

The @belticlabs/kya SDK focuses on validation and HTTP signatures. For signing credentials, use the CLI or a JWT library like jose:

import * as jose from 'jose';
import { validateDeveloperCredential } from '@belticlabs/kya';
import { readFileSync } from 'fs';

// Load and validate credential
const credential = JSON.parse(readFileSync('my-dev-cred.json', 'utf-8'));
const validation = validateDeveloperCredential(credential);
if (!validation.valid) throw new Error('Invalid credential');

// Generate key pair
const { privateKey, publicKey } = await jose.generateKeyPair('EdDSA');

// Sign the credential
const jwt = await new jose.SignJWT({ vc: credential })
  .setProtectedHeader({ 
    alg: 'EdDSA', 
    typ: 'application/beltic-developer+jwt' 
  })
  .setIssuer(credential.issuerDid)
  .setSubject(credential.subjectDid)
  .setIssuedAt()
  .setExpirationTime('1y')
  .sign(privateKey);

console.log('Signed JWT:', jwt);

Step 7: Verify with SDK

import { decodeToken, validateDeveloperCredential } from '@belticlabs/kya';

// Decode the token (without cryptographic verification)
const decoded = decodeToken(jwt);

console.log('Token type:', decoded.header.typ);
console.log('Payload:', decoded.payload);

// Validate the embedded credential
if (decoded.payload.vc) {
  const result = validateDeveloperCredential(decoded.payload.vc);
  console.log('Credential valid:', result.valid);
}

Troubleshooting

Issue: "command not found: beltic"

Cause: The CLI binary is not in your PATH.

Solution:

# If installed via shell script, add to PATH
export PATH="$PATH:$HOME/.beltic/bin"

# Or reinstall via Homebrew
brew tap belticlabs/tap
brew install beltic

Issue: "Schema validation failed: data must have required property 'legalName'"

Cause: Required field is missing from your credential.

Solution: Check that all required fields are present. For DeveloperCredential, required fields include:

  • credentialId, legalName, entityType, incorporationJurisdiction, businessRegistrationStatus, taxIdExists, kybTier, sanctionsScreeningStatus, overallRiskRating, issuanceDate, expirationDate, issuerDid, subjectDid, credentialStatus

Refer to the template you copied to ensure all required fields are included.

Issue: "Invalid signature"

Cause: The public key doesn't match the private key used for signing, or the credential was modified after signing.

Solution:

  • Ensure you're using the matching public key file (.pub.pem for the private key)
  • Don't modify the token after signing
  • Regenerate the token if you've changed the credential

Issue: "Module '@belticlabs/kya' not found"

Cause: The SDK is not installed.

Solution:

npm install @belticlabs/kya

Issue: "Date ordering violation: issuanceDate must be before expirationDate"

Cause: The credential dates are in the wrong order or in an invalid format.

Solution:

  • Ensure dates are in ISO 8601 format: YYYY-MM-DDTHH:mm:ssZ
  • Verify issuanceDate < expirationDate
  • Ensure expirationDate is in the future

Help us build better tools - If you're building with FACT or have ideas to improve the CLI and SDK, we want to hear from you. Your feedback helps us understand real-world needs and build better developer tools. Contact pranav at beltic dot com or share your thoughts on our Feedback page.

Next Steps

Congratulations! You've issued and verified your first Beltic credential. Here's what to explore next:

Additional Resources