Agentes de IA com Google Gemini - Documentação Completa

Agentes de IA com Google Gemini

Tutorial Completo e Detalhado - Guia prático de integração com React + Node.js

Começar Tutorial
code React
dns Node.js
auto_awesome Google Gemini
storage API REST
psychology Function Calling
Visão Geral da Arquitetura - Agentes Gemini

Visão Geral da Arquitetura

Compreenda a estrutura completa da solução de agentes de IA com Gemini

layers Componentes Principais

web

Frontend (React)

Context API, Hooks customizados e Componentes de UI para interação com os agentes

dns

Backend (Node.js)

API REST, GeminiService, Sistema de Ferramentas e validação de API Keys

auto_awesome

Google Gemini API

Modelo gemini-2.0-flash-exp com suporte a Function Calling e conversação contextual

timeline Fluxo de Dados

┌─────────────────────┐
│   FRONTEND (React)  │
│  - Context/Hooks    │
│  - Components       │
└──────────┬──────────┘
           │ HTTP/REST
┌──────────▼──────────┐
│  BACKEND (Node.js)  │
│  - Routes           │
│  - GeminiService    │
│  - AgentTools       │
└──────────┬──────────┘
           │ API Call
┌──────────▼──────────┐
│  Google Gemini API  │
│  - AI Processing    │
│  - Function Calling │
└─────────────────────┘
info
Arquitetura em Camadas
Cada camada tem responsabilidades bem definidas, facilitando manutenção e escalabilidade

verified Características Principais

security

Segurança

Criptografia de API Keys e validação em múltiplas camadas

speed

Performance

Cache inteligente e optimistic updates para UX fluida

extension

Extensível

Sistema de ferramentas modulares via Function Calling

psychology

Inteligente

Agentes especializados com contexto e memória persistente

Configuração Inicial - Agentes Gemini

Configuração Inicial

Dependências, variáveis de ambiente e configurações essenciais

dns Backend (Node.js)

Dependências NPM

{
  "dependencies": {
    "@google/generative-ai": "^0.2.1",
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "dotenv": "^16.0.3",
    "crypto": "^1.0.1"
  }
}

Variáveis de Ambiente (.env)

# API Key do Gemini (Sistema)
GEMINI_API_KEY=AIzaSy...

# Configurações da API
PORT=3001
NODE_ENV=development

# Segurança
ENCRYPTION_KEY=sua-chave-32-caracteres

web Frontend (React)

Dependências NPM

{
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "axios": "^1.4.0"
  }
}

Variáveis de Ambiente (.env)

# URL da API Backend
VITE_API_URL=http://localhost:3001/api/v1

# Ambiente
VITE_NODE_ENV=development

settings Arquivo de Configuração do Gemini

Crie o arquivo backend/src/config/gemini.config.ts com as seguintes configurações:

export const geminiConfig = {
  // API Key global do sistema
  systemApiKey: process.env.GEMINI_API_KEY || null,
  
  // Configurações de segurança
  security: {
    encryptUserKeys: true,
    hashAlgorithm: 'sha256',
    keyMasking: true,
    validationCacheTTL: 3600 // 1 hora
  },
  
  // Configurações padrão do modelo
  defaults: {
    model: 'gemini-2.0-flash-exp',
    temperature: 0.7,
    topP: 0.95,
    topK: 40,
    maxOutputTokens: 2048
  },
  
  // Modelos disponíveis
  availableModels: [
    {
      id: 'gemini-2.0-flash-exp',
      name: 'Gemini 2.0 Flash (Experimental)',
      description: 'Modelo rápido e eficiente',
      features: ['function-calling', 'chat', 'streaming']
    },
    {
      id: 'gemini-1.5-pro',
      name: 'Gemini 1.5 Pro',
      description: 'Modelo avançado para tarefas complexas',
      features: ['function-calling', 'chat', 'long-context']
    }
  ]
};
warning
Segurança da API Key
Nunca exponha sua API Key do Gemini no frontend. Sempre faça as chamadas através do backend.
check_circle
Configuração Completa
Com essas configurações, você estará pronto para integrar o Gemini em sua aplicação.
Sistema de Ferramentas - Agentes Gemini

Sistema de Ferramentas

Function Calling - Permitindo que agentes executem ações em tempo real

functions O que é Function Calling?

Function Calling é uma funcionalidade do Gemini que permite ao modelo de IA identificar quando precisa de dados externos para responder adequadamente a uma pergunta. Em vez de apenas gerar texto, o modelo pode solicitar a execução de funções específicas.

search 1. Identifica necessidade de dados
play_arrow 2. Solicita execução de função
download 3. Recebe resultados da função
auto_awesome 4. Incorpora dados na resposta final

Exemplo Prático

Usuário: "Quantos veículos disponíveis temos?"

Gemini detecta:
{
  functionCall: {
    name: "listar_veiculos",
    args: { status: "disponivel" }
  }
}

Sistema executa:
const veiculos = await buscarVeiculos({ 
  status: "disponivel" 
});

Gemini gera resposta:
"Atualmente temos 2 veículos disponíveis:
- ABC-1234
- XYZ-9876"

build Definição de Ferramentas

As ferramentas são organizadas por tipo de agente. Cada ferramenta possui nome, descrição e parâmetros.

export interface ToolDefinition {
  name: string;
  description: string;
  parameters: {
    type: "object";
    properties: Record<string, {
      type: string;
      description: string;
      enum?: string[];
    }>;
    required: string[];
  };
}

// Ferramentas do Agente de Logística (ALP)
export const AGENT_TOOLS: Record<string, ToolDefinition[]> = {
  ALP: [
    {
      name: "listar_veiculos",
      description: "Lista veículos com filtros opcionais",
      parameters: {
        type: "object",
        properties: {
          status: {
            type: "string",
            description: "Status do veículo",
            enum: ["disponivel", "em_rota", "manutencao"]
          },
          tipo: {
            type: "string",
            description: "Tipo do veículo"
          }
        },
        required: []
      }
    },
    {
      name: "criar_rota",
      description: "Cria nova rota de entrega",
      parameters: {
        type: "object",
        properties: {
          origem: {
            type: "string",
            description: "Endereço de origem"
          },
          destino: {
            type: "string",
            description: "Endereço de destino"
          },
          veiculo_id: {
            type: "string",
            description: "ID do veículo"
          }
        },
        required: ["origem", "destino"]
      }
    }
  ]
};

settings Executor de Ferramentas

A classe AgentToolExecutor é responsável por executar as ferramentas de forma segura e controlada.

export class AgentToolExecutor {
  static async executeTool(
    agentId: string,
    toolName: string,
    args: Record<string, any>
  ): Promise<any> {
    
    // 1. Validar agente
    const agent = await findAgentById(agentId);
    if (!agent) {
      throw new Error('Agente não encontrado');
    }
    
    // 2. Verificar permissões
    const tools = AGENT_TOOLS[agent.type];
    const tool = tools?.find(t => t.name === toolName);
    
    if (!tool) {
      throw new Error(
        `Ferramenta ${toolName} não disponível`
      );
    }
    
    // 3. Executar ação
    switch (toolName) {
      case "listar_veiculos":
        return await this.listarVeiculos(args);
      
      case "criar_rota":
        return await this.criarRota(args);
      
      default:
        throw new Error('Ferramenta não implementada');
    }
  }
  
  private static async listarVeiculos(
    args: { status?: string; tipo?: string }
  ) {
    // Busca no banco de dados
    const veiculos = await database.veiculos.findMany({
      where: {
        ...(args.status && { status: args.status }),
        ...(args.tipo && { tipo: args.tipo })
      }
    });
    
    return {
      total: veiculos.length,
      veiculos: veiculos.map(v => ({
        id: v.id,
        placa: v.placa,
        status: v.status,
        tipo: v.tipo
      }))
    };
  }
}

Segurança e Validação

shield
Validação de Agente

Verifica se o agente existe e tem permissão para usar a ferramenta

verified_user
Validação de Parâmetros

Checa se os argumentos estão de acordo com a definição

lock
Isolamento de Execução

Cada ferramenta roda em contexto controlado e seguro

warning
Importante: Nunca execute código arbitrário. Sempre valide e sanitize os inputs antes de executar ferramentas.
Comunicação API - Agentes Gemini

Comunicação API

Endpoints REST, estrutura de requisições e respostas

cloud Arquitetura da API REST

Base URL

http://localhost:3001/api/v1

Estrutura de Endpoints

  • /agents - Gerenciamento de agentes
  • /conversations - Conversas e histórico
  • /messages - Envio de mensagens
  • /tools - Execução de ferramentas

Headers Padrão

{
  "Content-Type": "application/json",
  "Accept": "application/json",
  "X-API-Version": "1.0",
  "X-Client-Id": "react-app"
}

api Principais Endpoints

GET /agents

Lista todos os agentes disponíveis

Resposta:

{
  "success": true,
  "data": [
    {
      "id": "agent-1",
      "name": "Agente de Logística",
      "type": "ALP",
      "modelName": "gemini-2.0-flash-exp",
      "status": "active"
    }
  ]
}
POST /conversations

Inicia uma nova conversa com um agente

Requisição:

{
  "agentId": "agent-1",
  "title": "Nova conversa",
  "metadata": {
    "source": "web-app"
  }
}

Resposta:

{
  "success": true,
  "data": {
    "id": "conv-123",
    "agentId": "agent-1",
    "title": "Nova conversa",
    "messages": [],
    "createdAt": "2025-10-14T10:00:00Z"
  }
}
POST /conversations/:id/messages

Envia mensagem para um agente

Requisição:

{
  "content": "Quantos veículos disponíveis?",
  "role": "user",
  "userApiKey": "AIzaSy..." // opcional
}

Resposta:

{
  "success": true,
  "data": {
    "id": "msg-456",
    "conversationId": "conv-123",
    "role": "assistant",
    "content": "Temos 2 veículos disponíveis...",
    "confidence": 0.95,
    "toolCalls": [],
    "timestamp": "2025-10-14T10:01:00Z"
  }
}
POST /tools/execute

Executa uma ferramenta específica

Requisição:

{
  "agentId": "agent-1",
  "toolName": "listar_veiculos",
  "args": {
    "status": "disponivel"
  }
}

Resposta:

{
  "success": true,
  "data": {
    "total": 2,
    "veiculos": [
      { "id": "v1", "placa": "ABC-1234" },
      { "id": "v2", "placa": "XYZ-9876" }
    ]
  }
}

error Tratamento de Erros

400 Bad Request

Dados de entrada inválidos

{
  "success": false,
  "error": {
    "code": "INVALID_INPUT",
    "message": "Campo obrigatório"
  }
}

401 Unauthorized

API Key inválida ou ausente

{
  "success": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "API Key inválida"
  }
}

500 Server Error

Erro interno do servidor

{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Erro inesperado"
  }
}
info
Padrão de Resposta: Todas as respostas seguem o formato { success: boolean, data?: any, error?: Error } para facilitar o tratamento no frontend.
Fluxo Completo de Conversação - Agentes Gemini

Fluxo Completo de Conversação

Entenda o ciclo completo desde a mensagem do usuário até a resposta da IA

account_tree Diagrama de Fluxo

┌─────────────────────────────────────────────────────────┐
  1. FRONTEND - Usuário Envia Mensagem              
└────────────────────────┬────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────┐
  2. CONTEXT - Optimistic Update                    
     • Adiciona mensagem do usuário imediatamente       
     • UI atualiza instantaneamente                      
└────────────────────────┬────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────┐
  3. API CALL - POST /conversations/:id/messages   
     • Envia payload com mensagem e histórico           
└────────────────────────┬────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────┐
  4. BACKEND - GeminiService.sendMessage()         
     • Valida API Key                                    
     • Gera prompt do sistema                            
     • Constrói histórico da conversa                     
└────────────────────────┬────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────┐
  5. GEMINI API - Processamento de IA               
     • Analisa mensagem e contexto                        
     • Decide se precisa executar ferramentas             
└────────────────────────┬────────────────────────────────┘
                         │
                    ┌────┴────┐
                    │         │
              ┌─────▼─────┐   ▼ (Sem ferramentas)
              │ 6. TOOLS  │
              │ EXECUTION │
              └─────┬─────┘
                    │
                    ▼
┌─────────────────────────────────────────────────────────┐
  7. GEMINI - Gera Resposta Final                  
     • Incorpora resultados das ferramentas               
     • Formata resposta natural                           
└────────────────────────┬────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────┐
  8. BACKEND - Processa Resposta                   
     • Calcula confiança                                  
     • Salva mensagem no banco                            
     • Retorna JSON para frontend                         
└────────────────────────┬────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────┐
  9. FRONTEND - Atualiza UI                         
     • Substitui mensagem temporária                      
     • Exibe resposta do agente                           
└─────────────────────────────────────────────────────────┘

play_circle Exemplo Prático: Passo a Passo

Passo 1: Usuário Pergunta

"Quantos veículos disponíveis temos?"

Passo 2: Optimistic Update

setMessages(prev => [...prev, {
  id: 'temp-123',
  role: 'user',
  content: 'Quantos veículos...',
  timestamp: new Date()
}]);

Passo 3: Requisição HTTP

POST /api/v1/conversations/conv-123/messages
{
  "content": "Quantos veículos...",
  "role": "user"
}

Passo 4: Backend Processa

const response = await geminiService.sendMessage(
  agentConfig,
  message.content,
  conversationHistory,
  userApiKey
);

Passo 5: Gemini Analisa

// Gemini detecta necessidade de ferramenta
{
  functionCall: {
    name: "listar_veiculos",
    args: { status: "disponivel" }
  }
}

Passo 6: Executa Ferramenta

const result = await AgentToolExecutor.executeTool(
  agentId,
  'listar_veiculos',
  { status: 'disponivel' }
);

// Retorna:
{
  total: 2,
  veiculos: [
    { id: 'v1', placa: 'ABC-1234' },
    { id: 'v2', placa: 'XYZ-9876' }
  ]
}

Passo 7: Gemini Gera Resposta

// Com os dados da ferramenta, Gemini gera:
"Atualmente temos 2 veículos disponíveis:
- ABC-1234
- XYZ-9876"

Passo 8: Backend Retorna

{
  "success": true,
  "data": {
    "id": "msg-456",
    "role": "assistant",
    "content": "Atualmente temos 2...",
    "confidence": 0.95,
    "toolCalls": [{
      "name": "listar_veiculos",
      "result": { ... }
    }],
    "timestamp": "2025-10-14T10:01:30Z"
  }
}

Passo 9: UI Atualiza

// Remove temporária, adiciona real
setMessages(prev => [
  ...prev.filter(m => !m.id.startsWith('temp-')),
  aiMessage
]);

settings Cenários Especiais

error

Erro na Requisição

Remove mensagem optimistic, exibe erro ao usuário e mantém histórico anterior intacto

repeat

Múltiplas Ferramentas

Gemini pode solicitar execução de várias ferramentas em sequência para responder adequadamente

schedule

Timeout

Se resposta demorar mais de 30s, retorna erro e permite que usuário tente novamente

Gestão de Estado e Performance - Agentes Gemini

Gestão de Estado e Performance

Otimizações, cache e estratégias para uma experiência fluida

storage Estratégias de Cache

vpn_key

Cache de Validação de API Keys

Valida API Keys apenas uma vez por hora, armazenando resultado em memória

interface ApiKeyValidationCache {
  [keyHash: string]: {
    isValid: boolean;
    timestamp: number;
    expiresAt: number;
  };
}

private validationCache: ApiKeyValidationCache = {};

async validateApiKeyWithCache(apiKey: string) {
  const keyHash = ApiKeySecurity.hash(apiKey);
  const cached = this.validationCache[keyHash];
  
  // Verifica se cache ainda é válido
  if (cached && Date.now() < cached.expiresAt) {
    return cached.isValid;
  }
  
  // Valida novamente
  const isValid = await this.testConnection(apiKey);
  
  // Atualiza cache (TTL: 1 hora)
  this.validationCache[keyHash] = {
    isValid,
    timestamp: Date.now(),
    expiresAt: Date.now() + 3600000
  };
  
  return isValid;
}
trending_up Reduz 99% das chamadas de validação
chat

Cache de Conversas (Frontend)

Armazena conversas ativas no Context para evitar requisições desnecessárias

// No AIChatContext
const [conversationsCache, setConversationsCache] = 
  useState<Map<string, Conversation>>(new Map());

const getConversation = useCallback(
  async (id: string) => {
    // Verifica cache primeiro
    if (conversationsCache.has(id)) {
      return conversationsCache.get(id);
    }
    
    // Busca do servidor
    const response = await api.get(`/conversations/${id}`);
    const conversation = response.data;
    
    // Atualiza cache
    setConversationsCache(prev => 
      new Map(prev).set(id, conversation)
    );
    
    return conversation;
  },
  [conversationsCache]
);
flash_on Navegação instantânea entre conversas

flash_on Optimistic Updates - Detalhado

Conceito

Atualiza a UI imediatamente assumindo que a operação será bem-sucedida, sem esperar resposta do servidor. Se falhar, reverte a mudança.

Benefícios

  • UI instantaneamente responsiva
  • Melhor percepção de performance
  • Reduz latência percebida em 90%
  • Experiência similar a apps nativos
psychology
Psicologia da UX: Usuários toleram melhor uma pequena espera quando veem feedback imediato da sua ação.
const sendMessage = async (content: string) => {
  if (!activeConversation) return;
  
  // 1. Mensagem temporária
  const tempId = `temp-${Date.now()}`;
  const userMessage = {
    id: tempId,
    role: 'user',
    content,
    timestamp: new Date(),
    sending: true // flag visual
  };
  
  // 2. Atualiza UI imediatamente
  setActiveConv(prev => ({
    ...prev!,
    messages: [...prev!.messages, userMessage]
  }));
  
  try {
    // 3. Envia para servidor
    const response = await api.post(
      `/conversations/${activeConversation.id}/messages`,
      { content, role: 'user' }
    );
    
    // 4. Substitui mensagem temporária
    setActiveConv(prev => ({
      ...prev!,
      messages: prev!.messages.map(m => 
        m.id === tempId 
          ? { ...response.data, sending: false }
          : m
      )
    }));
    
    // 5. Adiciona resposta do agente
    const aiMessage = response.data.aiResponse;
    setActiveConv(prev => ({
      ...prev!,
      messages: [...prev!.messages, aiMessage]
    }));
    
  } catch (error) {
    // 6. Rollback em caso de erro
    setActiveConv(prev => ({
      ...prev!,
      messages: prev!.messages.filter(
        m => m.id !== tempId
      )
    }));
    
    // 7. Notifica usuário
    showError('Falha ao enviar mensagem');
  }
};

tune Otimizações de Renderização (React)

React.memo

Evita re-renderizações desnecessárias de componentes

const ChatMessage = React.memo(
  ({ message }) => (
    <div className="message">
      {message.content}
    </div>
  ),
  (prev, next) => 
    prev.message.id === next.message.id
);

useCallback

Memoiza funções para evitar recriação

const handleSend = useCallback(
  (message: string) => {
    sendChatMessage(message);
  },
  [sendChatMessage]
);

Virtualização

Renderiza apenas mensagens visíveis

import { FixedSizeList } from 
  'react-window';

<FixedSizeList
  height={600}
  itemCount={messages.length}
  itemSize={80}
>
  {MessageRow}
</FixedSizeList>

speed Métricas de Performance Alvo

Métrica Alvo Medição Otimização
Time to First Message < 100ms Optimistic update ✅ Implementado
API Response Time < 2s Gemini + Backend ✅ Cache de API Keys
UI Update Time < 50ms React re-render ✅ React.memo + Virtual List
Conversation Load < 300ms Navegação entre conversas ✅ Cache de conversas
Memory Usage < 100MB Limite de mensagens em cache ⚠️ Limpar conversas antigas
check_circle
Performance Excelente: Com estas otimizações, a aplicação pode lidar com 50+ mensagens simultâneas sem lag perceptível.
warning
Monitoramento: Use ferramentas como React DevTools Profiler e Chrome Performance para identificar gargalos.
Segurança e Boas Práticas - Agentes Gemini

Segurança e Boas Práticas

Proteja sua aplicação e dados dos usuários

vpn_key Segurança de API Keys

Princípios Fundamentais

block
❌ NUNCA exponha API Keys no frontend

Chaves no código cliente podem ser extraídas e abusadas

check_circle
✅ Sempre use backend como proxy

Backend valida, protege e intermedia todas as chamadas

lock
🔐 Criptografe keys de usuários

Se armazenar keys de usuários, sempre criptografe

Implementação de Segurança

// ApiKeySecurity.ts
import crypto from 'crypto';

export class ApiKeySecurity {
  private static ALGORITHM = 'aes-256-gcm';
  private static KEY = process.env.ENCRYPTION_KEY!;
  
  // Criptografa API Key
  static encrypt(apiKey: string): string {
    const iv = crypto.randomBytes(16);
    const cipher = crypto.createCipheriv(
      this.ALGORITHM,
      Buffer.from(this.KEY, 'hex'),
      iv
    );
    
    let encrypted = cipher.update(apiKey, 'utf8', 'hex');
    encrypted += cipher.final('hex');
    const authTag = cipher.getAuthTag();
    
    return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
  }
  
  // Descriptografa API Key
  static decrypt(encryptedKey: string): string {
    const [ivHex, authTagHex, encrypted] = encryptedKey.split(':');
    
    const decipher = crypto.createDecipheriv(
      this.ALGORITHM,
      Buffer.from(this.KEY, 'hex'),
      Buffer.from(ivHex, 'hex')
    );
    
    decipher.setAuthTag(Buffer.from(authTagHex, 'hex'));
    
    let decrypted = decipher.update(encrypted, 'hex', 'utf8');
    decrypted += decipher.final('utf8');
    
    return decrypted;
  }
  
  // Hash para cache (one-way)
  static hash(apiKey: string): string {
    return crypto
      .createHash('sha256')
      .update(apiKey)
      .digest('hex');
  }
  
  // Valida formato de API Key
  static validateFormat(apiKey: string): boolean {
    return /^AIza[0-9A-Za-z\-_]{35}$/.test(apiKey);
  }
  
  // Mascara key para logs
  static mask(apiKey: string): string {
    if (apiKey.length < 8) return '***';
    return `${apiKey.substring(0, 4)}...${apiKey.substring(apiKey.length - 4)}`;
  }
}

verified_user Validação de Entrada

Backend Validation

// Middleware de validação
const validateMessageInput = (req, res, next) => {
  const { content, role } = req.body;
  
  // Valida presença
  if (!content || typeof content !== 'string') {
    return res.status(400).json({
      success: false,
      error: {
        code: 'INVALID_CONTENT',
        message: 'Content é obrigatório'
      }
    });
  }
  
  // Limita tamanho
  if (content.length > 10000) {
    return res.status(400).json({
      success: false,
      error: {
        code: 'CONTENT_TOO_LONG',
        message: 'Máximo 10.000 caracteres'
      }
    });
  }
  
  // Sanitiza HTML/Scripts
  req.body.content = sanitizeHtml(content, {
    allowedTags: [],
    allowedAttributes: {}
  });
  
  // Valida role
  if (!['user', 'assistant'].includes(role)) {
    return res.status(400).json({
      success: false,
      error: {
        code: 'INVALID_ROLE',
        message: 'Role deve ser user ou assistant'
      }
    });
  }
  
  next();
};

Rate Limiting

import rateLimit from 'express-rate-limit';

// Limita requisições por IP
const messageLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 minuto
  max: 20, // 20 mensagens por minuto
  message: {
    success: false,
    error: {
      code: 'RATE_LIMIT_EXCEEDED',
      message: 'Muitas requisições. Aguarde 1 minuto.'
    }
  },
  standardHeaders: true,
  legacyHeaders: false
});

// Aplica no endpoint
app.post(
  '/api/v1/conversations/:id/messages',
  messageLimiter,
  validateMessageInput,
  sendMessageHandler
);
warning
Ataques Comuns: SQL Injection, XSS, CSRF, DDoS. Sempre valide e sanitize inputs, use HTTPS, implemente rate limiting e monitore logs.

code Boas Práticas de Código

error_outline

Tratamento de Erros

  • Use try-catch em async functions
  • Nunca exponha stack traces ao usuário
  • Log detalhado no servidor
  • Mensagens amigáveis no frontend
description

Logging

  • Use níveis (info, warn, error)
  • Nunca logue API Keys completas
  • Inclua timestamps e IDs de rastreamento
  • Centralize logs (Winston, Bunyan)
integration_instructions

TypeScript

  • Sempre defina tipos explícitos
  • Use interfaces para contratos
  • Evite 'any', prefira 'unknown'
  • Configure strict mode

Exemplo: Logging Seguro

import winston from 'winston';

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

// ✅ Correto - API Key mascarada
logger.info('API Key validada', {
  keyHash: ApiKeySecurity.hash(apiKey),
  keyMask: ApiKeySecurity.mask(apiKey),
  userId: user.id
});

// ❌ ERRADO - Expõe API Key
logger.info('API Key validada', { 
  apiKey: apiKey // NUNCA FAÇA ISSO!
});

Checklist de Segurança

  • API Keys nunca no frontend
  • HTTPS em produção
  • Validação de entrada (backend)
  • Rate limiting implementado
  • Sanitização de HTML/SQL
  • CORS configurado corretamente
  • Logs sem dados sensíveis
  • Dependências atualizadas
  • Variáveis de ambiente seguras
  • Testes de segurança automatizados
Exemplos Práticos - Agentes Gemini

Exemplos Práticos

Casos de uso reais e implementações completas

support_agent Exemplo 1: Agente de Atendimento ao Cliente

Configuração do Agente

{
  "id": "agent-suporte",
  "name": "Agente de Suporte",
  "type": "CUSTOMER_SUPPORT",
  "modelName": "gemini-2.0-flash-exp",
  "systemPrompt": `
    Você é um assistente de atendimento ao cliente.
    
    Regras:
    - Seja educado e empático
    - Pergunte informações necessárias
    - Use ferramentas para consultar dados
    - Resolva problemas de forma proativa
    - Escale para humano quando necessário
  `,
  "temperature": 0.7,
  "tools": [
    "buscar_pedido",
    "consultar_estoque",
    "abrir_ticket",
    "verificar_garantia"
  ]
}

Ferramentas Disponíveis

export const SUPPORT_TOOLS = [
  {
    name: "buscar_pedido",
    description: "Busca informações de um pedido",
    parameters: {
      type: "object",
      properties: {
        pedido_id: {
          type: "string",
          description: "ID do pedido"
        }
      },
      required: ["pedido_id"]
    }
  },
  {
    name: "abrir_ticket",
    description: "Abre ticket de suporte",
    parameters: {
      type: "object",
      properties: {
        titulo: { type: "string" },
        descricao: { type: "string" },
        prioridade: { 
          type: "string",
          enum: ["baixa", "media", "alta"]
        }
      },
      required: ["titulo", "descricao"]
    }
  }
];

Conversa de Exemplo

👤 Usuário:

Olá, meu pedido #12345 não chegou ainda

🤖 Agente:

[Executa: buscar_pedido({ pedido_id: "12345" })]

Olá! Verifiquei seu pedido #12345. Ele foi despachado ontem e está em trânsito. Previsão de entrega: 14/10/2025. Você pode acompanhar em tempo real pelo código de rastreio: BR123456789.

👤 Usuário:

Mas eu preciso urgente. Dá para adiantar?

🤖 Agente:

[Executa: abrir_ticket({ titulo: "Entrega urgente", prioridade: "alta" })]

Entendo a urgência! Abri um ticket prioritário (#T-789) para nossa equipe logística verificar possibilidades de entrega expressa. Você receberá retorno em até 2 horas. Posso ajudar com mais alguma coisa?

psychology Problema resolvido proativamente

analytics Exemplo 2: Agente de Análise de Dados

Configuração

{
  "id": "agent-analytics",
  "name": "Analista de Dados IA",
  "type": "DATA_ANALYST",
  "modelName": "gemini-1.5-pro",
  "systemPrompt": `
    Você é um analista de dados especializado.
    
    Capacidades:
    - Interpretar queries SQL
    - Gerar visualizações
    - Identificar tendências
    - Fazer previsões baseadas em dados
    - Explicar insights de forma clara
  `,
  "temperature": 0.3,
  "tools": [
    "executar_query",
    "gerar_grafico",
    "calcular_metricas"
  ]
}

Executor de Query

async executarQuery(args: { query: string }) {
  // Valida query (previne SQL injection)
  const sanitizedQuery = this.sanitizeSQL(args.query);
  
  // Limita queries a SELECT apenas
  if (!sanitizedQuery.toLowerCase().startsWith('select')) {
    throw new Error('Apenas queries SELECT permitidas');
  }
  
  // Executa com timeout
  const result = await database.query(
    sanitizedQuery,
    { timeout: 5000 }
  );
  
  return {
    rows: result.rows.slice(0, 100), // Limita resultados
    totalCount: result.rowCount,
    executionTime: result.duration
  };
}

Conversa de Exemplo

👤 Usuário:

Quais foram as vendas totais do último trimestre?

🤖 Agente:

[Executa: executar_query({ query: "SELECT SUM(valor) as total FROM vendas WHERE data >= '2024-07-01' AND data <= '2024-09-30'" })]

Análise do Q3 2024 (Jul-Set):

  • Vendas Totais: R$ 2.450.000,00
  • Número de Transações: 1.234
  • Ticket Médio: R$ 1.985,50

Comparado ao Q2, houve crescimento de 15%. Posso gerar um gráfico?

👤 Usuário:

Sim, por favor! E me mostre os top 5 produtos

🤖 Agente:

[Executa: gerar_grafico({ tipo: "linha", dados: [...] })]
[Executa: executar_query({ query: "SELECT produto, SUM(valor) as total FROM vendas GROUP BY produto ORDER BY total DESC LIMIT 5" })]

📊 Gráfico gerado! Top 5 produtos:

  1. Produto A - R$ 450.000
  2. Produto B - R$ 380.000
  3. Produto C - R$ 320.000
  4. Produto D - R$ 280.000
  5. Produto E - R$ 240.000

code Exemplo 3: Componente React Completo

import React, { useState, useEffect } from 'react';
import { useAIChat } from '../contexts/AIChatContext';

export const ChatPanel: React.FC = () => {
  const { 
    activeConversation, 
    sendChatMessage, 
    loading 
  } = useAIChat();
  
  const [message, setMessage] = useState('');
  const [messages, setMessages] = useState<ChatMessage[]>([]);
  
  // Atualiza mensagens quando conversa muda
  useEffect(() => {
    if (activeConversation) {
      setMessages(activeConversation.messages);
    }
  }, [activeConversation]);
  
  const handleSend = async (e: React.FormEvent) => {
    e.preventDefault();
    
    if (!message.trim() || loading) return;
    
    const currentMessage = message;
    setMessage(''); // Limpa input imediatamente
    
    try {
      await sendChatMessage(currentMessage);
    } catch (error) {
      console.error('Erro ao enviar mensagem:', error);
      setMessage(currentMessage); // Restaura em caso de erro
    }
  };
  
  return (
    <div className="chat-panel">
      {/* Header */}
      <div className="chat-header">
        <h2>{activeConversation?.agent.name || 'Selecione um agente'}</h2>
        {activeConversation && (
          <span className="badge">
            {activeConversation.agent.type}
          </span>
        )}
      </div>
      
      {/* Mensagens */}
      <div className="messages-container">
        {messages.map((msg) => (
          <div 
            key={msg.id} 
            className={`message ${msg.role}`}
          >
            <div className="message-avatar">
              {msg.role === 'user' ? '👤' : '🤖'}
            </div>
            <div className="message-content">
              <div className="message-text">{msg.content}</div>
              <div className="message-meta">
                <span>{formatTime(msg.timestamp)}</span>
                {msg.confidence && (
                  <span>Confiança: {(msg.confidence * 100).toFixed(0)}%</span>
                )}
                {msg.sending && <span>Enviando...</span>}
              </div>
            </div>
          </div>
        ))}
        
        {loading && (
          <div className="typing-indicator">
            <span></span><span></span><span></span>
          </div>
        )}
      </div>
      
      {/* Input */}
      <form onSubmit={handleSend} className="chat-input">
        <input
          type="text"
          value={message}
          onChange={(e) => setMessage(e.target.value)}
          placeholder="Digite sua mensagem..."
          disabled={!activeConversation || loading}
        />
        <button 
          type="submit" 
          disabled={!message.trim() || loading}
        >
          Enviar
        </button>
      </form>
    </div>
  );
};

// Utilitário de formatação
function formatTime(date: Date): string {
  return new Intl.DateTimeFormat('pt-BR', {
    hour: '2-digit',
    minute: '2-digit'
  }).format(new Date(date));
}

school Próximos Passos

🛠️ Ferramentas

  • React DevTools
  • Postman (API Testing)
  • VS Code Extensions

🚀 Deploy

  • Vercel (Frontend)
  • Railway (Backend)
  • Supabase (Database)
celebration
Parabéns! Você concluiu o tutorial completo de implementação de Agentes de IA com Google Gemini. Agora é hora de colocar em prática e criar soluções incríveis! 🎉

Assistente Virtual

Online

Olá! 👋

Para começar, por favor nos informe: