Skip to content

JavaScript Examples

JavaScript and TypeScript examples for AG2Trust API integration.

Setup

Node.js

npm install node-fetch
# or use built-in fetch in Node 18+

Browser

No additional dependencies needed - use native fetch.

Configuration

const API_KEY = process.env.AG2TRUST_API_KEY;
const BASE_URL = 'https://agents.ag2trust.com';

Basic Usage

Send Message to Pool

async function sendMessage(content, threadId = null) {
  const payload = { content };
  if (threadId) {
    payload.thread_id = threadId;
  }

  const response = await fetch(`${BASE_URL}/api/v1/ask/support`, {
    method: 'POST',
    headers: {
      'X-API-Key': API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  });

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }

  return response.json();
}

// Usage
const result = await sendMessage('Hello, I need help');
console.log('Response:', result.content);
console.log('Thread ID:', result.thread_id);

Send Message to Specific Agent

async function sendToAgent(agentId, message) {
  const response = await fetch(
    `${BASE_URL}/api/v1/agents/${agentId}/messages`,
    {
      method: 'POST',
      headers: {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ message })
    }
  );

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }

  const data = await response.json();

  // Extract text content
  const text = data.content
    .filter(block => block.type === 'text')
    .map(block => block.text)
    .join('\n');

  return { text, metadata: data.metadata };
}

// Usage
const { text, metadata } = await sendToAgent('agent-uuid', 'Hello!');
console.log(text);
console.log(`Tokens used: ${metadata.tokens_used}`);

Conversation Management

Multi-Turn Conversation Class

class Conversation {
  constructor(endpoint = 'support') {
    this.endpoint = endpoint;
    this.threadId = null;
    this.history = [];
  }

  async send(content) {
    const payload = { content };
    if (this.threadId) {
      payload.thread_id = this.threadId;
    }

    const response = await fetch(
      `${BASE_URL}/api/v1/ask/${this.endpoint}`,
      {
        method: 'POST',
        headers: {
          'X-API-Key': API_KEY,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    const data = await response.json();
    this.threadId = data.thread_id;

    this.history.push({ role: 'user', content });
    this.history.push({ role: 'assistant', content: data.content });

    return data.content;
  }

  getHistory() {
    return this.history;
  }
}

// Usage
const conv = new Conversation('support');
console.log(await conv.send('I have a billing question'));
console.log(await conv.send('Can you show me my recent invoices?'));
console.log(await conv.send('The one from January looks wrong'));

Error Handling

Custom Error Classes

class AG2TrustError extends Error {
  constructor(message, errorCode = null, details = {}) {
    super(message);
    this.name = 'AG2TrustError';
    this.errorCode = errorCode;
    this.details = details;
  }
}

class RateLimitError extends AG2TrustError {
  constructor(retryAfter) {
    super('Rate limit exceeded', 'RATE_LIMIT_EXCEEDED');
    this.retryAfter = retryAfter;
  }
}

class AgentNotAvailableError extends AG2TrustError {
  constructor() {
    super('No agents available', 'NO_AGENTS_AVAILABLE');
  }
}

async function handleResponse(response) {
  if (response.ok) {
    return response.json();
  }

  if (response.status === 429) {
    const retryAfter = parseInt(response.headers.get('Retry-After') || '5');
    throw new RateLimitError(retryAfter);
  }

  if (response.status === 503) {
    throw new AgentNotAvailableError();
  }

  const error = await response.json();
  throw new AG2TrustError(
    error.error || 'Unknown error',
    error.error_code,
    error.details
  );
}

Retry Logic

async function sendWithRetry(content, maxRetries = 3, threadId = null) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(`${BASE_URL}/api/v1/ask/support`, {
        method: 'POST',
        headers: {
          'X-API-Key': API_KEY,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ content, thread_id: threadId })
      });

      return await handleResponse(response);

    } catch (error) {
      if (error instanceof RateLimitError && attempt < maxRetries - 1) {
        console.log(`Rate limited, waiting ${error.retryAfter}s...`);
        await new Promise(r => setTimeout(r, error.retryAfter * 1000));
        continue;
      }
      throw error;
    }
  }

  throw new Error('Max retries exceeded');
}

Using Axios

Setup

npm install axios

Client with Interceptors

import axios from 'axios';

const client = axios.create({
  baseURL: BASE_URL,
  headers: {
    'X-API-Key': API_KEY,
    'Content-Type': 'application/json'
  },
  timeout: 65000
});

// Response interceptor for error handling
client.interceptors.response.use(
  response => response,
  async error => {
    const { response, config } = error;

    // Handle rate limiting
    if (response?.status === 429) {
      const retryAfter = parseInt(
        response.headers['retry-after'] || '5'
      );

      if (!config._retry) {
        config._retry = true;
        await new Promise(r => setTimeout(r, retryAfter * 1000));
        return client(config);
      }
    }

    return Promise.reject(error);
  }
);

// Usage
async function sendMessage(content, threadId = null) {
  const { data } = await client.post('/api/v1/ask/support', {
    content,
    thread_id: threadId
  });
  return data;
}

Webhook Handling

Express.js Server

const express = require('express');
const crypto = require('crypto');

const app = express();

// Use raw body for signature verification
app.use('/webhooks', express.raw({ type: '*/*' }));

function verifySignature(body, signature) {
  const expected = crypto
    .createHmac('sha256', API_KEY)
    .update(body)
    .digest('hex');

  const provided = signature.replace('sha256=', '');

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(provided)
  );
}

app.post('/webhooks/ag2trust', (req, res) => {
  const signature = req.headers['x-webhook-signature'] || '';

  if (!verifySignature(req.body, signature)) {
    return res.status(401).send('Invalid signature');
  }

  const payload = JSON.parse(req.body);
  const { callback_id, status, content } = payload;

  if (status === 'completed') {
    processResponse(callback_id, content);
  } else {
    handleFailure(callback_id, payload);
  }

  res.status(200).send('OK');
});

function processResponse(callbackId, content) {
  content.forEach(block => {
    if (block.type === 'text') {
      console.log(`[${callbackId}] ${block.text}`);
    }
  });
}

function handleFailure(callbackId, payload) {
  console.error(`[${callbackId}] Failed: ${payload.error}`);
}

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});

Send Async Request

async function sendAsyncMessage(agentId, message, webhookUrl) {
  const response = await fetch(
    `${BASE_URL}/api/v1/agents/${agentId}/messages`,
    {
      method: 'POST',
      headers: {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        message,
        webhook_url: webhookUrl
      })
    }
  );

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }

  return response.json();
}

// Usage
const result = await sendAsyncMessage(
  'agent-uuid',
  'Analyze this large dataset...',
  'https://your-server.com/webhooks/ag2trust'
);
console.log(`Processing started: ${result.callback_id}`);

TypeScript

Type Definitions

interface Message {
  content: string;
  thread_id?: string;
}

interface PoolResponse {
  thread_id: string;
  agent_id: string;
  content: string;
  timestamp: string;
}

interface ContentBlock {
  type: 'text' | 'error';
  text?: string;
  error?: string;
}

interface AgentResponse {
  message_id: string;
  content: ContentBlock[];
  metadata: {
    tokens_used: number;
    model: string;
    duration_ms: number;
  };
}

interface Agent {
  agent_id: string;
  name: string;
  status: 'running' | 'stopped' | 'error';
  capabilities: string[];
}

Typed Client

class AG2TrustClient {
  private apiKey: string;
  private baseUrl: string;

  constructor(apiKey: string, baseUrl = 'https://agents.ag2trust.com') {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
  }

  async ask(endpoint: string, content: string, threadId?: string): Promise<PoolResponse> {
    const payload: Message = { content };
    if (threadId) {
      payload.thread_id = threadId;
    }

    const response = await fetch(`${this.baseUrl}/api/v1/ask/${endpoint}`, {
      method: 'POST',
      headers: {
        'X-API-Key': this.apiKey,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(payload)
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    return response.json() as Promise<PoolResponse>;
  }

  async sendToAgent(agentId: string, message: string): Promise<AgentResponse> {
    const response = await fetch(
      `${this.baseUrl}/api/v1/agents/${agentId}/messages`,
      {
        method: 'POST',
        headers: {
          'X-API-Key': this.apiKey,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ message })
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    return response.json() as Promise<AgentResponse>;
  }

  async listAgents(): Promise<Agent[]> {
    const response = await fetch(`${this.baseUrl}/api/v1/agents`, {
      headers: {
        'X-API-Key': this.apiKey
      }
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    const data = await response.json();
    return data.agents;
  }
}

// Usage
const client = new AG2TrustClient(process.env.AG2TRUST_API_KEY!);

const response = await client.ask('support', 'Hello!');
console.log(response.content);

Browser Usage

With CORS

<!DOCTYPE html>
<html>
<head>
  <title>AG2Trust Chat</title>
</head>
<body>
  <div id="chat"></div>
  <input type="text" id="input" placeholder="Type a message...">
  <button onclick="send()">Send</button>

  <script>
    // NOTE: Never expose API keys in client-side code in production!
    // Use a backend proxy instead.

    const API_KEY = 'cust_your_api_key';  // Use backend proxy in production
    const BASE_URL = 'https://agents.ag2trust.com';

    let threadId = null;

    async function send() {
      const input = document.getElementById('input');
      const content = input.value;
      input.value = '';

      addMessage('You', content);

      const payload = { content };
      if (threadId) {
        payload.thread_id = threadId;
      }

      const response = await fetch(`${BASE_URL}/api/v1/ask/support`, {
        method: 'POST',
        headers: {
          'X-API-Key': API_KEY,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
      });

      const data = await response.json();
      threadId = data.thread_id;

      addMessage('Agent', data.content);
    }

    function addMessage(sender, text) {
      const chat = document.getElementById('chat');
      chat.innerHTML += `<p><strong>${sender}:</strong> ${text}</p>`;
    }
  </script>
</body>
</html>

API Key Security

Never expose API keys in client-side code for production applications. Use a backend proxy to keep your API key secure.