Docs/Node.js SDK

Node.js / TypeScript Integration

Native fetch-based integration for Node.js 18+ and all modern JavaScript environments. Fully typed.

Basic Fetch (No Dependencies)

typescript
const GUARDRAIL_API_KEY = process.env.GUARDRAIL_API_KEY!;

interface GuardrailResult {
  risk_score: number;
  status: 'approved' | 'flagged' | 'rejected';
  flags: string[];
  redacted_text: string;
}

async function checkAgentOutput(agentId: string, proposedText: string): Promise<GuardrailResult> {
  const response = await fetch('https://api.guardrail.ai/v1/guardrail/check', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${GUARDRAIL_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ agent_id: agentId, proposed_text: proposedText }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Guardrail error ${response.status}: ${error.detail}`);
  }

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

// Usage
const result = await checkAgentOutput('support-bot', 'Your card number 4111... was processed.');

if (result.status === 'approved') {
  console.log('Safe:', result.redacted_text);
} else {
  console.warn('Blocked:', result.flags);
}

Express.js Middleware

Add Guardrail as Express middleware to automatically screen all AI output routes.

typescript (express)
import express, { Request, Response, NextFunction } from 'express';

const GUARDRAIL_KEY = process.env.GUARDRAIL_API_KEY!;

// Middleware factory
function guardrailMiddleware(agentId: string) {
  return async (req: Request, res: Response, next: NextFunction) => {
    const textToCheck = req.body?.ai_response;
    if (!textToCheck) return next();

    try {
      const result = await fetch('https://api.guardrail.ai/v1/guardrail/check', {
        method: 'POST',
        headers: { 'Authorization': `Bearer ${GUARDRAIL_KEY}`, 'Content-Type': 'application/json' },
        body: JSON.stringify({ agent_id: agentId, proposed_text: textToCheck }),
      }).then(r => r.json());

      if (result.status === 'rejected') {
        return res.status(400).json({ error: 'AI response blocked by safety policy', flags: result.flags });
      }
      
      // Replace with safe redacted version
      req.body.ai_response = result.redacted_text;
      req.body.guardrail_risk_score = result.risk_score;
      next();
    } catch (err) {
      console.error('Guardrail check failed:', err);
      next(); // Fail-open: proceed without blocking on guardrail errors
    }
  };
}

// Apply to your routes
const app = express();
app.post('/api/chat', guardrailMiddleware('chat-agent'), async (req, res) => {
  // By the time we're here, req.body.ai_response is already sanitized
  res.json({ message: req.body.ai_response });
});

Vercel AI SDK Integration

typescript (vercel ai)
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

export async function POST(req: Request) {
  const { messages } = await req.json();

  // 1. Generate LLM response
  const result = streamText({ model: openai('gpt-4o'), messages });
  const fullText = await result.text;

  // 2. Run through Guardrail before returning
  const guardrail = await fetch('https://api.guardrail.ai/v1/guardrail/check', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.GUARDRAIL_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ agent_id: 'vercel-ai-chat', proposed_text: fullText }),
  }).then(r => r.json());

  if (guardrail.status === 'rejected') {
    return Response.json({ role: 'assistant', content: 'I cannot provide that information.' });
  }

  return Response.json({ role: 'assistant', content: guardrail.redacted_text });
}