Basic Usage

This chapter covers fundamental JACS operations in Node.js, including agent initialization, document creation, signing, and verification.

Initializing an Agent

Create and Load Agent

import { JacsAgent } from 'jacsnpm';

// Create a new agent instance
const agent = new JacsAgent();

// Load configuration from file
agent.load('./jacs.config.json');

Configuration File

Create jacs.config.json:

{
  "$schema": "https://hai.ai/schemas/jacs.config.schema.json",
  "jacs_data_directory": "./jacs_data",
  "jacs_key_directory": "./jacs_keys",
  "jacs_default_storage": "fs",
  "jacs_agent_key_algorithm": "ring-Ed25519",
  "jacs_agent_id_and_version": "agent-uuid:version-uuid"
}

Creating Documents

Basic Document Creation

import { JacsAgent } from 'jacsnpm';

const agent = new JacsAgent();
agent.load('./jacs.config.json');

// Create a document from JSON
const documentData = {
  title: "Project Proposal",
  content: "Quarterly development plan",
  budget: 50000
};

const signedDocument = agent.createDocument(JSON.stringify(documentData));
console.log('Signed document:', signedDocument);

With Custom Schema

Validate against a custom JSON Schema:

const signedDocument = agent.createDocument(
  JSON.stringify(documentData),
  './schemas/proposal.schema.json'  // custom schema path
);

With Output File

const signedDocument = agent.createDocument(
  JSON.stringify(documentData),
  null,                    // no custom schema
  './output/proposal.json' // output filename
);

Without Saving

const signedDocument = agent.createDocument(
  JSON.stringify(documentData),
  null,   // no custom schema
  null,   // no output filename
  true    // noSave = true
);

With Attachments

const signedDocument = agent.createDocument(
  JSON.stringify(documentData),
  null,                      // no custom schema
  null,                      // no output filename
  false,                     // save the document
  './attachments/report.pdf', // attachment path
  true                       // embed files
);

Verifying Documents

Verify Document Signature

// Verify a document's signature and hash
const isValid = agent.verifyDocument(signedDocumentJson);
console.log('Document valid:', isValid);

Verify Specific Signature Field

// Verify with a custom signature field
const isValid = agent.verifySignature(
  signedDocumentJson,
  'jacsSignature'  // signature field name
);

Updating Documents

Update Existing Document

// Original document key format: "id:version"
const documentKey = 'doc-uuid:version-uuid';

// Modified document content
const updatedData = {
  jacsId: 'doc-uuid',
  jacsVersion: 'version-uuid',
  title: "Updated Proposal",
  content: "Revised quarterly plan",
  budget: 75000
};

const updatedDocument = agent.updateDocument(
  documentKey,
  JSON.stringify(updatedData)
);

console.log('Updated document:', updatedDocument);

Update with New Attachments

const updatedDocument = agent.updateDocument(
  documentKey,
  JSON.stringify(updatedData),
  ['./new-report.pdf'],  // new attachments
  true                   // embed files
);

Signing and Verification

Sign Arbitrary Data

// Sign any string data
const signature = agent.signString('Important message to sign');
console.log('Signature:', signature);

Verify Arbitrary Data

// Verify a signature on string data
const isValid = agent.verifyString(
  'Important message to sign',  // original data
  signatureBase64,              // base64 signature
  publicKeyBuffer,              // public key as Buffer
  'ring-Ed25519'                // algorithm
);

Working with Agreements

Create an Agreement

// Add agreement requiring multiple agent signatures
const documentWithAgreement = agent.createAgreement(
  signedDocumentJson,
  ['agent1-uuid', 'agent2-uuid'],           // required signers
  'Do you agree to these terms?',            // question
  'Q1 2024 service contract',                // context
  'jacsAgreement'                            // field name
);

Sign an Agreement

// Sign the agreement as the current agent
const signedAgreement = agent.signAgreement(
  documentWithAgreementJson,
  'jacsAgreement'  // agreement field name
);

Check Agreement Status

// Check which agents have signed
const status = agent.checkAgreement(
  documentWithAgreementJson,
  'jacsAgreement'
);

console.log('Agreement status:', JSON.parse(status));

Agent Operations

Verify Agent

// Verify the loaded agent's signature
const isValid = agent.verifyAgent();
console.log('Agent valid:', isValid);

// Verify a specific agent file
const isValidOther = agent.verifyAgent('./other-agent.json');

Update Agent

// Update agent document
const updatedAgentJson = agent.updateAgent(JSON.stringify({
  jacsId: 'agent-uuid',
  jacsVersion: 'version-uuid',
  name: 'Updated Agent Name',
  description: 'Updated description'
}));

Sign External Agent

// Sign another agent's document with registration signature
const signedAgentJson = agent.signAgent(
  externalAgentJson,
  publicKeyBuffer,
  'ring-Ed25519'
);

Request/Response Signing

Sign a Request

// Sign request parameters as a JACS document
const signedRequest = agent.signRequest({
  method: 'GET',
  path: '/api/resource',
  timestamp: new Date().toISOString(),
  body: { query: 'data' }
});

Verify a Response

// Verify a signed response
const result = agent.verifyResponse(signedResponseJson);
console.log('Response valid:', result);

// Verify and get signer's agent ID
const resultWithId = agent.verifyResponseWithAgentId(signedResponseJson);
console.log('Signer ID:', resultWithId);

Utility Functions

Hash String

import { hashString } from 'jacsnpm';

// SHA-256 hash of a string
const hash = hashString('data to hash');
console.log('Hash:', hash);

Create Configuration

import { createConfig } from 'jacsnpm';

// Programmatically create a config JSON string
const configJson = createConfig(
  undefined,            // jacs_use_security
  './jacs_data',        // jacs_data_directory
  './jacs_keys',        // jacs_key_directory
  undefined,            // private key filename
  undefined,            // public key filename
  'ring-Ed25519',       // key algorithm
  undefined,            // private key password
  undefined,            // agent id and version
  'fs'                  // default storage
);

console.log('Config:', configJson);

Error Handling

import { JacsAgent } from 'jacsnpm';

const agent = new JacsAgent();

try {
  agent.load('./jacs.config.json');
} catch (error) {
  console.error('Failed to load agent:', error.message);
}

try {
  const doc = agent.createDocument(JSON.stringify({ data: 'test' }));
  console.log('Document created');
} catch (error) {
  console.error('Failed to create document:', error.message);
}

try {
  const isValid = agent.verifyDocument(invalidJson);
} catch (error) {
  console.error('Verification failed:', error.message);
}

Complete Example

import { JacsAgent, hashString } from 'jacsnpm';

async function main() {
  // Initialize agent
  const agent = new JacsAgent();
  agent.load('./jacs.config.json');

  // Create a task document
  const task = {
    title: 'Code Review',
    description: 'Review pull request #123',
    assignee: 'developer-uuid',
    deadline: '2024-02-01'
  };

  const signedTask = agent.createDocument(JSON.stringify(task));
  console.log('Task created');

  // Verify the task
  if (agent.verifyDocument(signedTask)) {
    console.log('Task signature valid');
  }

  // Create agreement for task acceptance
  const taskWithAgreement = agent.createAgreement(
    signedTask,
    ['manager-uuid', 'developer-uuid'],
    'Do you accept this task assignment?'
  );

  // Sign the agreement
  const signedAgreement = agent.signAgreement(taskWithAgreement);
  console.log('Agreement signed');

  // Check agreement status
  const status = agent.checkAgreement(signedAgreement);
  console.log('Status:', status);

  // Hash some data for reference
  const taskHash = hashString(signedTask);
  console.log('Task hash:', taskHash);
}

main().catch(console.error);

Next Steps