Files
wifi-densepose/vendor/ruvector/npm/packages/agentic-synth/docs/DEPLOYMENT.md

17 KiB

🚀 Agentic-Synth Deployment Guide

Version: 0.1.0 Last Updated: 2025-11-22


Table of Contents

  1. Pre-Deployment Checklist
  2. Environment Configuration
  3. Deployment Platforms
  4. Production Best Practices
  5. Monitoring & Logging
  6. Scaling Strategies
  7. Security Considerations
  8. Troubleshooting

1. Pre-Deployment Checklist

Code Readiness

  • All tests passing (run npm test)
  • Build succeeds (run npm run build)
  • No ESLint errors (run npm run lint)
  • TypeScript compiles (run npm run typecheck)
  • Dependencies audited (run npm audit)
  • Environment variables documented
  • Error handling implemented
  • Logging configured
  • Performance benchmarks met

Configuration

  • API keys secured (not in source code)
  • Cache strategy configured
  • Retry logic enabled
  • Rate limiting implemented
  • Timeout values set appropriately
  • Health check endpoint created
  • Metrics collection enabled

Documentation

  • README.md up to date
  • API documentation complete
  • Environment variables listed
  • Deployment instructions written
  • Troubleshooting guide available

2. Environment Configuration

2.1 Environment Variables

Create a .env file (or configure in platform):

# API Configuration
SYNTH_PROVIDER=gemini
SYNTH_API_KEY=your-api-key-here
SYNTH_MODEL=gemini-2.0-flash-exp

# Optional: OpenRouter fallback
OPENROUTER_API_KEY=your-openrouter-key

# Cache Configuration
CACHE_STRATEGY=memory
CACHE_TTL=3600
MAX_CACHE_SIZE=10000

# Performance
MAX_RETRIES=3
REQUEST_TIMEOUT=30000
ENABLE_STREAMING=true

# Optional Integrations
ENABLE_AUTOMATION=false
ENABLE_VECTOR_DB=false
RUVECTOR_URL=http://localhost:3000

# Monitoring
LOG_LEVEL=info
ENABLE_METRICS=true

2.2 Configuration Validation

// config/validate.ts
import { z } from 'zod';

const EnvSchema = z.object({
  SYNTH_PROVIDER: z.enum(['gemini', 'openrouter']),
  SYNTH_API_KEY: z.string().min(10),
  SYNTH_MODEL: z.string().optional(),
  CACHE_TTL: z.string().transform(Number).pipe(z.number().positive()),
  MAX_CACHE_SIZE: z.string().transform(Number).pipe(z.number().positive()),
  MAX_RETRIES: z.string().transform(Number).pipe(z.number().min(0).max(10)),
  REQUEST_TIMEOUT: z.string().transform(Number).pipe(z.number().positive()),
});

export function validateEnv() {
  try {
    return EnvSchema.parse(process.env);
  } catch (error) {
    console.error('❌ Environment validation failed:', error);
    process.exit(1);
  }
}

3. Deployment Platforms

3.1 Node.js Server (Express/Fastify)

Installation:

npm install @ruvector/agentic-synth express dotenv

Server Setup:

// server.ts
import express from 'express';
import { AgenticSynth } from '@ruvector/agentic-synth';
import dotenv from 'dotenv';

dotenv.config();

const app = express();
app.use(express.json());

// Initialize synth
const synth = new AgenticSynth({
  provider: process.env.SYNTH_PROVIDER as 'gemini',
  apiKey: process.env.SYNTH_API_KEY!,
  cacheStrategy: 'memory',
  cacheTTL: parseInt(process.env.CACHE_TTL || '3600'),
  maxCacheSize: parseInt(process.env.MAX_CACHE_SIZE || '10000'),
});

// Health check
app.get('/health', async (req, res) => {
  try {
    const stats = synth.cache.getStats();
    res.json({
      status: 'healthy',
      timestamp: new Date().toISOString(),
      cache: {
        size: stats.size,
        hitRate: (stats.hitRate * 100).toFixed(2) + '%'
      }
    });
  } catch (error) {
    res.status(503).json({ status: 'unhealthy', error: error.message });
  }
});

// Generate endpoint
app.post('/generate/:type', async (req, res) => {
  try {
    const { type } = req.params;
    const options = req.body;

    const result = await synth.generate(type as any, options);
    res.json(result);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`✅ Server running on port ${PORT}`);
});

Start:

npm run build
node dist/server.js

3.2 AWS Lambda (Serverless)

Installation:

npm install @ruvector/agentic-synth aws-lambda

Lambda Handler:

// lambda/handler.ts
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { AgenticSynth } from '@ruvector/agentic-synth';

// Initialize outside handler for reuse (Lambda warm starts)
const synth = new AgenticSynth({
  provider: process.env.SYNTH_PROVIDER as 'gemini',
  apiKey: process.env.SYNTH_API_KEY!,
  cacheStrategy: 'memory',
  cacheTTL: 3600,
});

export const handler = async (
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
  try {
    const { type, ...options } = JSON.parse(event.body || '{}');

    const result = await synth.generate(type, options);

    return {
      statusCode: 200,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(result),
    };
  } catch (error) {
    return {
      statusCode: 500,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ error: error.message }),
    };
  }
};

Deployment (Serverless Framework):

# serverless.yml
service: agentic-synth-api

provider:
  name: aws
  runtime: nodejs20.x
  region: us-east-1
  environment:
    SYNTH_PROVIDER: ${env:SYNTH_PROVIDER}
    SYNTH_API_KEY: ${env:SYNTH_API_KEY}
    CACHE_TTL: 3600

functions:
  generate:
    handler: dist/lambda/handler.handler
    events:
      - http:
          path: generate
          method: post
    timeout: 30
    memorySize: 1024
serverless deploy

3.3 Docker Container

Dockerfile:

FROM node:20-alpine

WORKDIR /app

# Copy package files
COPY package*.json ./
RUN npm ci --production

# Copy source and build
COPY . .
RUN npm run build

# Expose port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"

# Start server
CMD ["node", "dist/server.js"]

Build & Run:

docker build -t agentic-synth .
docker run -p 3000:3000 \
  -e SYNTH_PROVIDER=gemini \
  -e SYNTH_API_KEY=your-key \
  -e CACHE_TTL=3600 \
  agentic-synth

Docker Compose:

version: '3.8'

services:
  agentic-synth:
    build: .
    ports:
      - "3000:3000"
    environment:
      - SYNTH_PROVIDER=gemini
      - SYNTH_API_KEY=${SYNTH_API_KEY}
      - CACHE_TTL=3600
      - MAX_CACHE_SIZE=10000
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 3s
      retries: 3
docker-compose up -d

3.4 Vercel (Edge Functions)

Installation:

npm install @ruvector/agentic-synth

API Route:

// api/generate.ts
import type { VercelRequest, VercelResponse } from '@vercel/node';
import { AgenticSynth } from '@ruvector/agentic-synth';

const synth = new AgenticSynth({
  provider: process.env.SYNTH_PROVIDER as 'gemini',
  apiKey: process.env.SYNTH_API_KEY!,
  cacheStrategy: 'memory',
  cacheTTL: 3600,
});

export default async function handler(
  req: VercelRequest,
  res: VercelResponse
) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  try {
    const { type, ...options } = req.body;
    const result = await synth.generate(type, options);
    res.status(200).json(result);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
}

Deploy:

vercel deploy --prod

4. Production Best Practices

4.1 Error Handling

import { AgenticSynth, APIError, ValidationError } from '@ruvector/agentic-synth';

app.post('/generate', async (req, res) => {
  try {
    const result = await synth.generate(req.body.type, req.body.options);
    res.json(result);
  } catch (error) {
    if (error instanceof ValidationError) {
      return res.status(400).json({
        error: 'Validation failed',
        details: error.validationErrors
      });
    }

    if (error instanceof APIError) {
      console.error('API Error:', {
        provider: error.provider,
        status: error.statusCode,
        message: error.message
      });

      return res.status(502).json({
        error: 'External API error',
        message: error.message
      });
    }

    // Unknown error
    console.error('Unexpected error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

4.2 Request Validation

import { z } from 'zod';

const GenerateRequestSchema = z.object({
  type: z.enum(['time-series', 'events', 'structured']),
  options: z.object({
    count: z.number().positive().max(10000),
    schema: z.record(z.any()),
    constraints: z.array(z.string()).optional(),
  }),
});

app.post('/generate', async (req, res) => {
  try {
    const validated = GenerateRequestSchema.parse(req.body);
    const result = await synth.generate(validated.type, validated.options);
    res.json(result);
  } catch (error) {
    if (error instanceof z.ZodError) {
      return res.status(400).json({
        error: 'Invalid request',
        details: error.errors
      });
    }
    // ... other error handling
  }
});

4.3 Rate Limiting

import rateLimit from 'express-rate-limit';

const limiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 60, // 60 requests per minute
  message: 'Too many requests, please try again later',
  standardHeaders: true,
  legacyHeaders: false,
});

app.use('/generate', limiter);

4.4 Caching Strategy

// Use cache for repeated requests
const synth = new AgenticSynth({
  provider: 'gemini',
  apiKey: process.env.SYNTH_API_KEY!,
  cacheStrategy: 'memory',
  cacheTTL: 3600, // 1 hour
  maxCacheSize: 10000,
});

// Monitor cache performance
setInterval(() => {
  const stats = synth.cache.getStats();
  console.log('Cache Stats:', {
    size: stats.size,
    hitRate: (stats.hitRate * 100).toFixed(2) + '%',
    utilization: ((stats.size / 10000) * 100).toFixed(2) + '%'
  });
}, 60000); // Every minute

5. Monitoring & Logging

5.1 Structured Logging

import winston from 'winston';

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
});

if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.simple(),
  }));
}

// Log all requests
app.use((req, res, next) => {
  logger.info('Request', {
    method: req.method,
    path: req.path,
    timestamp: new Date().toISOString()
  });
  next();
});

// Log generation events
app.post('/generate', async (req, res) => {
  const start = Date.now();
  try {
    const result = await synth.generate(req.body.type, req.body.options);

    logger.info('Generation success', {
      type: req.body.type,
      count: req.body.options.count,
      duration: Date.now() - start,
      cached: result.metadata.cached,
      generationTime: result.metadata.generationTime
    });

    res.json(result);
  } catch (error) {
    logger.error('Generation failed', {
      type: req.body.type,
      error: error.message,
      duration: Date.now() - start
    });
    throw error;
  }
});

5.2 Metrics Collection

import { Counter, Histogram, register } from 'prom-client';

// Define metrics
const requestCounter = new Counter({
  name: 'synth_requests_total',
  help: 'Total number of generation requests',
  labelNames: ['type', 'status']
});

const requestDuration = new Histogram({
  name: 'synth_request_duration_seconds',
  help: 'Duration of generation requests',
  labelNames: ['type']
});

const cacheHitRate = new Histogram({
  name: 'synth_cache_hit_rate',
  help: 'Cache hit rate percentage'
});

// Expose metrics endpoint
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', register.contentType);
  res.end(await register.metrics());
});

// Track metrics
app.post('/generate', async (req, res) => {
  const end = requestDuration.startTimer({ type: req.body.type });

  try {
    const result = await synth.generate(req.body.type, req.body.options);

    requestCounter.inc({ type: req.body.type, status: 'success' });
    cacheHitRate.observe(result.metadata.cached ? 100 : 0);

    res.json(result);
  } catch (error) {
    requestCounter.inc({ type: req.body.type, status: 'error' });
    throw error;
  } finally {
    end();
  }
});

6. Scaling Strategies

6.1 Horizontal Scaling

Load Balancer (Nginx):

upstream agentic_synth {
    least_conn;
    server synth1:3000 weight=1;
    server synth2:3000 weight=1;
    server synth3:3000 weight=1;
}

server {
    listen 80;

    location / {
        proxy_pass http://agentic_synth;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /health {
        proxy_pass http://agentic_synth/health;
        proxy_connect_timeout 2s;
        proxy_send_timeout 2s;
        proxy_read_timeout 2s;
    }
}

6.2 Kubernetes Deployment

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: agentic-synth
spec:
  replicas: 3
  selector:
    matchLabels:
      app: agentic-synth
  template:
    metadata:
      labels:
        app: agentic-synth
    spec:
      containers:
      - name: agentic-synth
        image: agentic-synth:latest
        ports:
        - containerPort: 3000
        env:
        - name: SYNTH_PROVIDER
          value: "gemini"
        - name: SYNTH_API_KEY
          valueFrom:
            secretKeyRef:
              name: synth-secrets
              key: api-key
        - name: CACHE_TTL
          value: "3600"
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: agentic-synth-service
spec:
  selector:
    app: agentic-synth
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
  type: LoadBalancer
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: agentic-synth-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: agentic-synth
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

7. Security Considerations

7.1 API Key Management

// ✅ Good: Environment variables
const synth = new AgenticSynth({
  provider: 'gemini',
  apiKey: process.env.SYNTH_API_KEY!
});

// ❌ Bad: Hardcoded
const synth = new AgenticSynth({
  provider: 'gemini',
  apiKey: 'AIza...' // NEVER DO THIS
});

7.2 Input Validation

const MAX_GENERATION_COUNT = 10000;
const MAX_SCHEMA_DEPTH = 5;

function validateOptions(options: any) {
  if (options.count > MAX_GENERATION_COUNT) {
    throw new Error(`Count exceeds maximum (${MAX_GENERATION_COUNT})`);
  }

  if (getSchemaDepth(options.schema) > MAX_SCHEMA_DEPTH) {
    throw new Error(`Schema depth exceeds maximum (${MAX_SCHEMA_DEPTH})`);
  }
}

7.3 HTTPS Only

// Redirect HTTP to HTTPS
app.use((req, res, next) => {
  if (req.header('x-forwarded-proto') !== 'https' && process.env.NODE_ENV === 'production') {
    res.redirect(`https://${req.header('host')}${req.url}`);
  } else {
    next();
  }
});

8. Troubleshooting

Common Issues

Issue: High Memory Usage

  • Solution: Reduce maxCacheSize or enable streaming for large datasets

Issue: Slow Response Times

  • Solution: Enable caching, use faster model, increase cacheTTL

Issue: Rate Limiting (429)

  • Solution: Implement exponential backoff, add rate limiter

Issue: API Connection Failures

  • Solution: Verify API key, check network connectivity, implement retry logic

Last Updated: 2025-11-22 Package Version: 0.1.0 Status: Production Ready