AI & Software Solution
AI

AI Agents: From Demo to Production Integration

GE

Guvantic Engineering

Guvantic Technical Publication

16 min
AI Agents: From Demo to Production Integration
Executive Architectural Overview (AEO Direct Answer)

Learn how to integrate AI agents with web applications using tool calling, RAG, and MCP. Practical patterns for building production-ready agentic systems with code examples.

AI agents are moving from demos to production. This guide covers integration patterns — tool calling, RAG, and MCP — that connect agents to existing web applications.

The Problem: AI in Production is Hard

You've built a cool AI demo. But production is different:

Hallucinations: AI makes up facts
Latency: LLMs are slow (2-10 seconds)
Security: Exposing AI to users creates risks
Integration: Connecting to your existing systems is complex
Cost: API calls are expensive
Architectural Topology Specification
AI Demo vs Production Gap — Shows the gap between demos (simple, single query) and production (complex, integrated, secure, monitored).

Agent Architecture Overview

Architectural Topology Specification
Production AI Agent Architecture — Shows:
User → Web App (Frontend) → API Gateway → Agent Orchestrator
Agent Orchestrator: LLM → Tool Router → Knowledge Base (RAG) → Database
Agent → Web App APIs (REST/WebSocket) → Service Layer
Monitoring: Logs, Metrics, Traces
Guardrails: Input validation, output filtering, rate limiting

Tool Calling (Function Calling) Implementation

Tool Definition (OpenAI Format)

typescriptProduction snippet
// tools/index.ts
export const tools = [
  {
    type: "function",
    function: {
      name: "searchProducts",
      description: "Search for products in the catalog",
      parameters: {
        type: "object",
        properties: {
          query: {
            type: "string",
            description: "Search term for products",
          },
          category: {
            type: "string",
            enum: ["electronics", "clothing", "books", "home"],
            description: "Product category filter",
          },
          limit: {
            type: "integer",
            minimum: 1,
            maximum: 50,
            default: 10,
          },
        },
        required: ["query"],
      },
    },
  },
  {
    type: "function",
    function: {
      name: "createSupportTicket",
      description: "Create a customer support ticket",
      parameters: {
        type: "object",
        properties: {
          userId: { type: "string", description: "User ID" },
          subject: { type: "string", description: "Ticket subject" },
          description: { type: "string", description: "Detailed description" },
          priority: { type: "string", enum: ["low", "medium", "high", "urgent"] },
        },
        required: ["userId", "subject", "description"],
      },
    },
  },
];

Tool Implementation

typescriptProduction snippet
// tools/handlers.ts
import { prisma } from "@/lib/db";

export async function handleToolCall(tool: any) {
  const { name, arguments: args } = tool.function;

  switch (name) {
    case "searchProducts":
      return await searchProducts(args);
    case "createSupportTicket":
      return await createSupportTicket(args);
    default:
      throw new Error(`Unknown tool: ${name}`);
  }
}

async function searchProducts({ query, category, limit = 10 }: any) {
  const products = await prisma.product.findMany({
    where: {
      AND: [
        { name: { contains: query, mode: "insensitive" } },
        category ? { category } : {},
      ],
    },
    take: limit,
    select: { id: true, name: true, price: true, description: true, image: true },
  });

  return {
    results: products,
    count: products.length,
    query,
  };
}

async function createSupportTicket({ userId, subject, description, priority = "medium" }: any) {
  const ticket = await prisma.supportTicket.create({
    data: {
      userId,
      subject,
      description,
      priority,
      status: "open",
      createdAt: new Date(),
    },
  });

  return {
    ticketId: ticket.id,
    message: "Support ticket created successfully",
  };
}

Agent Orchestrator

typescriptProduction snippet
// orchestrator.ts
import OpenAI from "openai";
import { tools, handleToolCall } from "./tools";

export class AgentOrchestrator {
  private openai: OpenAI;
  private maxIterations = 5;

  constructor() {
    this.openai = new OpenAI({
      apiKey: process.env.OPENAI_API_KEY,
    });
  }

  async processQuery(userInput: string, userId: string) {
    const messages: any[] = [
      {
        role: "system",
        content: "You are a helpful customer support assistant. Use the available tools to help users with product searches and support tickets.",
      },
      { role: "user", content: userInput },
    ];

    let iterations = 0;
    let finalResponse = "";

    while (iterations < this.maxIterations) {
      const response = await this.openai.chat.completions.create({
        model: "gpt-4-turbo-preview",
        messages,
        tools,
        tool_choice: "auto",
      });

      const message = response.choices[0].message;
      messages.push(message);

      if (message.tool_calls) {
        const toolResults = await Promise.all(
          message.tool_calls.map(async (toolCall: any) => {
            try {
              const result = await handleToolCall(toolCall);
              return {
                tool_call_id: toolCall.id,
                role: "tool",
                content: JSON.stringify(result),
              };
            } catch (error) {
              return {
                tool_call_id: toolCall.id,
                role: "tool",
                content: JSON.stringify({ error: (error as Error).message }),
              };
            }
          })
        );

        messages.push(...toolResults);
        iterations++;
        continue;
      }

      // No more tool calls, we have the final response
      finalResponse = message.content;
      break;
    }

    return { response: finalResponse, iterations };
  }
}

RAG (Retrieval-Augmented Generation)

Architectural Topology Specification
RAG Architecture — Shows:
User Query → Embedding Model → Vector Database → Retrieved Chunks
Retrieved Chunks + Query → LLM → Generated Answer
Knowledge Base → Chunking → Embeddings → Vector DB

RAG Implementation

typescriptProduction snippet
// rag.ts
import { Pinecone } from "@pinecone-database/pinecone";
import { OpenAI } from "openai";

export class RAGEngine {
  private openai: OpenAI;
  private pinecone: Pinecone;
  private index: any;

  constructor() {
    this.openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
    this.pinecone = new Pinecone({ apiKey: process.env.PINECONE_API_KEY });
    this.index = this.pinecone.index("knowledge-base");
  }

  async retrieve(query: string, topK = 5) {
    // Get embedding for query
    const embedding = await this.openai.embeddings.create({
      model: "text-embedding-3-small",
      input: query,
    });

    // Search vector database
    const results = await this.index.query({
      vector: embedding.data[0].embedding,
      topK,
      includeMetadata: true,
    });

    return results.matches.map((match: any) => match.metadata.text);
  }

  async answer(query: string) {
    const chunks = await this.retrieve(query);
    const context = chunks.join("

");

    const response = await this.openai.chat.completions.create({
      model: "gpt-4-turbo-preview",
      messages: [
        {
          role: "system",
          content: "Answer the user's question based on the provided context. If the context doesn't contain the answer, say so.",
        },
        {
          role: "user",
          content: `Context: ${context}\n\nQuestion: ${query}`,
        },
      ],
    });

    return {
      answer: response.choices[0].message.content,
      sources: chunks.slice(0, 3),
    };
  }
}

Model Context Protocol (MCP)

Architectural Topology Specification
MCP Architecture — Shows:
AI Agent → MCP Client → MCP Server
MCP Server → Tools/Resources/Context → External Systems
Standard protocol enables plug-and-play integrations

MCP Server Example

typescriptProduction snippet
// mcp-server.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { stdioTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server({
  name: "product-catalog-mcp",
  version: "1.0.0",
});

server.setRequestHandler("tools/list", async () => {
  return {
    tools: [
      {
        name: "searchProducts",
        description: "Search products in catalog",
        inputSchema: {
          type: "object",
          properties: {
            query: { type: "string" },
            category: { type: "string" },
          },
          required: ["query"],
        },
      },
    ],
  };
});

server.setRequestHandler("tools/call", async (request: any) => {
  const { name, arguments: args } = request;
  if (name === "searchProducts") {
    return await searchProducts(args);
  }
  throw new Error(`Unknown tool: ${name}`);
});

// Connect to stdio for MCP communication
const transport = new stdioTransport();
await server.connect(transport);

Guardrails and Security

Input Validation

typescriptProduction snippet
import { z } from "zod";

const UserInputSchema = z.object({
  query: z.string().min(1).max(500).refine(
    (text) => !text.includes("<script>"),
    "Potential XSS detected"
  ),
  userId: z.string().uuid(),
});

async function processUserInput(input: unknown) {
  const validated = UserInputSchema.parse(input);
  // ... process safely
}

Output Filtering

typescriptProduction snippet
import DOMPurify from "dompurify";

function sanitizeAIOutput(content: string) {
  // Remove URLs that might be harmful
  const urlRegex = /(https?://[^s]+)/g;
  const cleanContent = content.replace(urlRegex, (url) => {
    const allowedDomains = ["example.com", "docs.example.com"];
    try {
      const parsedUrl = new URL(url);
      if (allowedDomains.includes(parsedUrl.hostname)) {
        return url;
      }
      return "[URL removed for security]";
    } catch {
      return "[Invalid URL]";
    }
  });

  // Sanitize HTML
  return DOMPurify.sanitize(cleanContent);
}

Rate Limiting

typescriptProduction snippet
// Rate limit per user per minute
const rateLimiter = new SlidingWindowRateLimiter(redis, 10, 60); // 10 requests/minute

app.post("/api/agent/query", async (req, res) => {
  const userId = req.user.id;
  if (!await rateLimiter.allow(userId)) {
    return res.status(429).json({ error: "Rate limit exceeded" });
  }
  // ... process query
});
Keywords:#AI agents#RAG#tool calling#MCP#web application integration#production AI
GE

Guvantic Engineering

Engineering & System Architecture Division

Engineering teams at Guvantic deliver mission-critical software, high-concurrency microservices, and international organic positioning strategies for fast-growing companies in USA, UK, and India.

Related Engineering Insights