Pular para conteúdo

API: Agents

Visão Geral

Gerenciamento de agentes IA que processam conversas. Cada agente possui um prompt, mensagens customizáveis e base de conhecimento.

Endpoints

GET /api/agents

Lista todos os agentes do tenant.

Query Parameters:

Parâmetro Tipo Obrigatório Descrição
includeArchived bool Sim Incluir agentes arquivados na listagem

Response (200 OK):

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Suporte TI",
    "description": "Agente para suporte técnico interno",
    "isActive": true,
    "createdAt": "2024-01-15T10:30:00Z",
    "todayConversations": 12,
    "isArchived": false
  }
]


GET /api/agents/{id}

Retorna detalhes de um agente.

Response (200 OK):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Suporte TI",
  "description": "Agente para suporte técnico interno",
  "prompt": "Você é um assistente de TI...",
  "isActive": true,
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-20T14:00:00Z",
  "totalConversations": 150,
  "todayConversations": 12,
  "activeKnowledgeBlocksCount": 5,
  "totalKnowledgeBlocksCount": 8,
  "totalFaqCount": 15,
  "instancesCount": 2
}


POST /api/agents

Cria um novo agente.

Autorização: Admin

Request:

{
  "name": "Suporte TI",
  "description": "Agente para suporte técnico interno",
  "prompt": "Você é um assistente de TI especializado...",
  "isActive": true
}

Response (201 Created):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Suporte TI"
}


PUT /api/agents/{id}

Atualiza um agente.

Autorização: Admin

Request:

{
  "name": "Suporte TI v2",
  "description": "Agente atualizado",
  "prompt": "Você é um assistente de TI...",
  "isActive": true
}

Response (200 OK):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Suporte TI v2",
  "updatedAt": "2024-01-20T14:00:00Z"
}


DELETE /api/agents/{id}

Arquiva um agente (soft delete). O agente fica inativo e não processa mensagens, mas pode ser restaurado.

Autorização: Admin

Response: 204 No Content


POST /api/agents/{id}/restore

Restaura um agente arquivado.

Autorização: Admin

Response: 204 No Content

Comportamento: - Remove flag de arquivamento (IsArchived = false, ArchivedAt = null) - Agente volta ao estado inativo (IsActive = false) — o admin deve ativá-lo manualmente


DELETE /api/agents/{id}/permanent?name={confirmationName}

Exclui permanentemente um agente arquivado e todos os dados associados. Requer confirmação por nome.

Autorização: Admin

Query Parameters:

Parâmetro Tipo Descrição
name string Nome do agente (deve coincidir para confirmar)

Response: 204 No Content

Comportamento: - Somente agentes arquivados podem ser excluídos permanentemente - Remove em cascata: steps, knowledge, FAQs, prompt versions, escalation rules, attachments - Remove arquivos do R2 (storage) em paralelo (Parallel.ForEachAsync, MaxDegreeOfParallelism=10) - Ação irreversível — não pode ser desfeita

Erros:

Status Código Descrição
404 AGENT_NOT_FOUND Agente não encontrado
400 VALIDATION_ERROR Nome de confirmação não confere ou agente não está arquivado

Sub-recursos

Mensagens Customizadas

GET /api/agents/{agentId}/messages

Retorna as mensagens customizadas do agente.

Response (200 OK):

{
  "errorMessage": "Desculpe, estou com dificuldades técnicas.",
  "welcomeMessage": "Olá! Como posso ajudar?",
  "rateLimitMessage": "Você está enviando muitas mensagens.",
  "outOfHoursMessage": "Nosso atendimento funciona das 8h às 18h."
}

PUT /api/agents/{agentId}/messages

Atualiza as mensagens customizadas.

Request:

{
  "errorMessage": "Desculpe, tente novamente.",
  "welcomeMessage": "Bem-vindo!",
  "rateLimitMessage": null,
  "outOfHoursMessage": null
}


Base de Conhecimento

GET /api/agents/{agentId}/knowledge

Lista blocos de conhecimento do agente.

Response (200 OK):

[
  {
    "id": "660e8400-e29b-41d4-a716-446655440000",
    "title": "Impressoras",
    "content": "## Problemas comuns\n\n- Papel atolado...",
    "displayOrder": 0,
    "isActive": true,
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:30:00Z"
  }
]

GET /api/agents/{agentId}/knowledge/{id}

Retorna um bloco específico.

POST /api/agents/{agentId}/knowledge

Cria um bloco de conhecimento.

Request:

{
  "title": "Impressoras",
  "content": "## Problemas comuns\n\n- Papel atolado...",
  "displayOrder": 0,
  "isActive": true
}

PUT /api/agents/{agentId}/knowledge/{id}

Atualiza um bloco.

DELETE /api/agents/{agentId}/knowledge/{id}

Remove um bloco.

POST /api/agents/{agentId}/knowledge/reorder

Reordena os blocos.

Request:

{
  "orderedIds": [
    "660e8400-e29b-41d4-a716-446655440000",
    "770e8400-e29b-41d4-a716-446655440001"
  ]
}


FAQ (Perguntas Frequentes)

FAQs são pares pergunta/resposta que participam da busca semântica junto com a base de conhecimento.

GET /api/agents/{agentId}/faq

Lista FAQs do agente.

Response (200 OK):

[
  {
    "id": "990e8400-e29b-41d4-a716-446655440000",
    "agentId": "550e8400-e29b-41d4-a716-446655440000",
    "question": "Qual o horário de funcionamento?",
    "answer": "Funcionamos de segunda a sexta, das 9h às 18h.",
    "displayOrder": 0,
    "isActive": true,
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:30:00Z"
  }
]

GET /api/agents/{agentId}/faq/{id}

Retorna uma FAQ específica.

POST /api/agents/{agentId}/faq

Cria uma FAQ. O embedding é gerado automaticamente.

Request:

{
  "question": "Qual o horário de funcionamento?",
  "answer": "Funcionamos de segunda a sexta, das 9h às 18h.",
  "isActive": true
}

Response (201 Created):

{
  "id": "990e8400-e29b-41d4-a716-446655440000",
  "agentId": "550e8400-e29b-41d4-a716-446655440000",
  "question": "Qual o horário de funcionamento?",
  "answer": "Funcionamos de segunda a sexta, das 9h às 18h.",
  "displayOrder": 0,
  "isActive": true,
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-15T10:30:00Z"
}

PUT /api/agents/{agentId}/faq/{id}

Atualiza uma FAQ. Se pergunta ou resposta mudarem, o embedding é regenerado.

Request:

{
  "question": "Qual o horário de atendimento?",
  "answer": "Funcionamos de segunda a sexta, das 9h às 18h, e sábados das 9h às 13h.",
  "isActive": true
}

DELETE /api/agents/{agentId}/faq/{id}

Remove uma FAQ.

Response: 204 No Content


Follow-Up

Configuração de follow-up automático para agentes e etapas. O follow-up envia mensagens automáticas ao contato após um período de inatividade na conversa.

Existem dois níveis de follow-up: - Agent-level: configuração global do agente (aplica-se quando não há follow-up específico na etapa) - Step-level: configuração específica por etapa (sobrepõe o follow-up do agente)

GET /api/agents/{agentId}/follow-up

Retorna a configuração de follow-up do agente.

Response (200 OK):

{
  "id": "aa0e8400-e29b-41d4-a716-446655440000",
  "message": "Olá! Ainda precisa de ajuda?",
  "delayMinutes": 30,
  "maxSends": 2,
  "allowedHours": [
    { "dayOfWeek": 1, "startTime": "09:00", "endTime": "18:00" }
  ],
  "isActive": true,
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-15T10:30:00Z"
}

Retorna null se não houver configuração de follow-up.

PUT /api/agents/{agentId}/follow-up

Cria ou atualiza (upsert) a configuração de follow-up do agente.

Autorização: Admin

Request:

{
  "message": "Olá! Ainda precisa de ajuda?",
  "delayMinutes": 30,
  "maxSends": 2,
  "allowedHours": [
    { "dayOfWeek": 1, "startTime": "09:00", "endTime": "18:00" }
  ]
}

Response (200 OK): FollowUpConfigResponse (mesmo schema do GET)

DELETE /api/agents/{agentId}/follow-up

Remove a configuração de follow-up do agente.

Autorização: Admin

Response: 204 No Content

GET /api/agents/{agentId}/steps/{stepId}/follow-up

Retorna a configuração de follow-up de uma etapa específica.

Response (200 OK): FollowUpConfigResponse (mesmo schema do GET agent-level) ou null.

PUT /api/agents/{agentId}/steps/{stepId}/follow-up

Cria ou atualiza (upsert) a configuração de follow-up de uma etapa.

Autorização: Admin

Request:

{
  "message": "Você ainda está aí? Posso ajudar com mais alguma coisa?",
  "delayMinutes": 15,
  "maxSends": 1,
  "allowedHours": null
}

Response (200 OK): FollowUpConfigResponse

DELETE /api/agents/{agentId}/steps/{stepId}/follow-up

Remove a configuração de follow-up de uma etapa.

Autorização: Admin

Response: 204 No Content


Anexos (Attachments)

Arquivos anexados ao agente que podem ser enviados automaticamente pela IA durante conversas.

GET /api/agents/{agentId}/attachments

Lista todos os anexos do agente.

Response (200 OK):

[
  {
    "id": "bb0e8400-e29b-41d4-a716-446655440000",
    "agentId": "550e8400-e29b-41d4-a716-446655440000",
    "fileName": "cardapio.pdf",
    "mimeType": "application/pdf",
    "fileSizeBytes": 204800,
    "storageUrl": "https://r2.example.com/tenants/.../attachments/cardapio.pdf",
    "displayName": "Cardápio Atualizado",
    "description": "Cardápio completo com preços",
    "tags": "cardapio,precos",
    "isActive": true,
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:30:00Z"
  }
]

POST /api/agents/{agentId}/attachments

Faz upload de um novo anexo.

Autorização: Admin

Request:

{
  "fileName": "cardapio.pdf",
  "mimeType": "application/pdf",
  "base64Content": "JVBERi0xLjQK...",
  "displayName": "Cardápio Atualizado",
  "description": "Cardápio completo com preços",
  "tags": "cardapio,precos"
}

Response (201 Created): AttachmentResponse (mesmo schema do GET)

PUT /api/agents/{agentId}/attachments/{id}

Atualiza metadados de um anexo (display name, descrição, tags).

Autorização: Admin

Request:

{
  "displayName": "Cardápio 2024",
  "description": "Cardápio atualizado com novos itens",
  "tags": "cardapio,precos,2024"
}

Response (200 OK): AttachmentResponse

DELETE /api/agents/{agentId}/attachments/{id}

Remove um anexo.

Autorização: Admin

Response: 204 No Content

PUT /api/agents/{agentId}/attachments/{id}/toggle

Ativa/desativa um anexo.

Autorização: Admin

Response (200 OK): AttachmentResponse


Etapas de Atendimento

Etapas guiam a IA por um fluxo estruturado de atendimento. Sem etapas, o agente responde livremente.

GET /api/agents/{agentId}/steps

Lista etapas do agente ordenadas por posição.

Response (200 OK):

[
  {
    "id": "aa0e8400-e29b-41d4-a716-446655440000",
    "name": "Saudação",
    "instructions": "Cumprimente o cliente e pergunte como pode ajudar...",
    "optimizedInstructions": null,
    "order": 1,
    "isActive": true,
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:30:00Z"
  }
]

POST /api/agents/{agentId}/steps

Cria uma nova etapa. Instruções são otimizadas automaticamente.

Request:

{
  "name": "Coleta do Pedido",
  "instructions": "Pergunte ao cliente o que deseja pedir..."
}

Response (201 Created):

{
  "id": "bb0e8400-e29b-41d4-a716-446655440001",
  "name": "Coleta do Pedido",
  "order": 2
}

PUT /api/agents/{agentId}/steps/{id}

Atualiza uma etapa. Re-otimiza se as instruções mudaram.

Request:

{
  "name": "Coleta do Pedido",
  "instructions": "Pergunte ao cliente o que deseja pedir. Confirme cada item."
}

DELETE /api/agents/{agentId}/steps/{id}

Remove uma etapa. Conversas ativas nesta etapa terão CurrentStepId limpo.

Response: 204 No Content

PUT /api/agents/{agentId}/steps/reorder

Reordena as etapas.

Request:

{
  "stepIds": [
    "bb0e8400-e29b-41d4-a716-446655440001",
    "aa0e8400-e29b-41d4-a716-446655440000"
  ]
}

PUT /api/agents/{agentId}/steps/{id}/toggle

Ativa/desativa uma etapa.


Validações de Etapas

Campo Regra
Name Obrigatório, máx 100 caracteres
Instructions Obrigatório, máx 20000 caracteres

AI Assistant

Assistente de IA integrado ao portal para ajudar na criação e refinamento de conteúdo do agente (prompt, base de conhecimento, etapas).

POST /api/agents/{agentId}/ai-assistant/chat

Envia uma mensagem ao assistente de IA contextualizado pela seção do agente sendo editada.

Request:

{
  "sectionKey": "freeform",
  "userMessage": "Melhore este prompt para atendimento de pizzaria",
  "history": [
    { "role": "user", "content": "Mensagem anterior" },
    { "role": "assistant", "content": "Resposta anterior" }
  ],
  "currentContent": "Você é um assistente de atendimento...",
  "contentTitle": "Prompt Principal",
  "stepsContext": "1. Saudação\n2. Coleta do Pedido"
}

Campos:

Campo Tipo Descrição
sectionKey string Seção sendo editada: freeform, knowledge, step, step_planner
userMessage string Mensagem do usuário (máx 4000 chars)
history array Histórico de mensagens da conversa atual
currentContent string? Conteúdo atual da seção (prompt, instrução, etc.)
contentTitle string? Título do conteúdo (ex: nome do bloco de conhecimento)
stepsContext string? Contexto das etapas do agente (apenas para step e step_planner)

Response (200 OK):

{
  "sectionKey": "freeform",
  "suggestedContent": "Você é um assistente virtual especializado em pizzaria...",
  "assistantMessage": "Aqui está uma versão melhorada do seu prompt...",
  "quickReplies": ["Mais formal", "Mais curto", "Adicionar exemplos"]
}

Campo Tipo Descrição
sectionKey string? Seção do conteúdo sugerido
suggestedContent string? Conteúdo sugerido para aplicar na seção
assistantMessage string Resposta textual do assistente
quickReplies array? Sugestões de respostas rápidas

Playground

Endpoints para testar o agente diretamente pelo portal administrativo. Todos os endpoints do playground: - Requerem autorização Admin (RequireAuthorization(AuthConstants.Roles.Admin)) - Estão sob rate limiting LLM (RequireRateLimiting(RateLimitPolicies.Llm)) - Upload de mídia para R2 é feito em paralelo com o processamento via PlaygroundMediaHelper

POST /api/agents/{agentId}/playground/chat

Envia mensagens de teste para o agente. Suporta texto e imagens (Claude Vision).

Request:

{
  "messages": [
    {
      "role": "user",
      "content": "Olá",
      "type": "text"
    },
    {
      "role": "assistant",
      "content": "Olá! Como posso ajudar?",
      "type": "text"
    },
    {
      "role": "user",
      "content": "O que tem nesta imagem?",
      "type": "image",
      "mediaBase64": "iVBORw0KGgo...",
      "mediaMimeType": "image/jpeg"
    }
  ]
}

Campos da mensagem (PlaygroundMessageDto):

Campo Tipo Descrição
role string "user" ou "assistant"
content string Texto da mensagem (ou legenda da imagem)
type string "text" (padrão) ou "image"
mediaBase64 string? Dados da imagem em base64 (apenas type="image")
mediaMimeType string? MIME type da mídia (ex: "image/jpeg")

Response (200 OK):

{
  "content": "Na imagem posso ver...",
  "inputTokens": 1500,
  "outputTokens": 200
}

Comportamento: - Mensagens de texto são enviadas normalmente ao LLM - Mensagens de imagem são convertidas para ChatMessage.WithImage() (Claude Vision multimodal) - Limitado às últimas 20 mensagens do histórico


POST /api/agents/{agentId}/playground/transcribe

Transcreve áudio em texto usando Whisper (OpenAI).

Request:

{
  "audioBase64": "UklGRiQA...",
  "mimeType": "audio/webm"
}

Campo Tipo Descrição
audioBase64 string Áudio gravado em base64
mimeType string MIME type do áudio (ex: "audio/webm", "audio/ogg")

Response (200 OK):

{
  "text": "Como configuro uma impressora?"
}

Comportamento: - Converte base64 para bytes e envia ao Whisper API - Retorna texto transcrito que o frontend usa como mensagem de texto - Validação: audioBase64 e mimeType são obrigatórios


POST /api/agents/{agentId}/playground/describe-image

Realiza OCR/descrição de imagem via Claude Vision. O frontend usa o texto retornado como contexto antes de enviar ao LLM no chat.

Request:

{
  "imageBase64": "iVBORw0KGgo...",
  "mimeType": "image/jpeg",
  "caption": "O que é isso?"
}

Campo Tipo Descrição
imageBase64 string Dados da imagem em base64
mimeType string MIME type da imagem (ex: "image/jpeg", "image/png")
caption string? Legenda opcional da imagem

Response (200 OK):

{
  "description": "Uma foto de uma pizza margherita em uma caixa de papelão branca...",
  "mediaUrl": "https://r2.example.com/tenants/.../playground/image.jpeg"
}

Campo Tipo Descrição
description string Texto descritivo gerado pelo Claude Vision
mediaUrl string? URL da imagem salva no R2 (pode ser null se upload falhar)

Comportamento: - OCR via Claude Vision e upload para R2 executam em paralelo (Task.WhenAll) - Se o upload falhar, o processamento continua e mediaUrl retorna null - Se a descrição falhar, retorna erro 400 com mensagem de validação - Handler: PlaygroundDescribeImageHandler


Rate Limiting

Endpoints de escrita (POST, PUT, DELETE) de agentes e sub-recursos (KB, steps, FAQ, attachments, prompt versions, agent CRUD) usam a política AgentConfig: 30 requisições por 60 segundos por usuário.

Endpoints de leitura (GET) continuam na política Admin: 30 requisições por minuto.

Veja rate-limiting.md para detalhes.


Validações

CreateAgentRequest / UpdateAgentRequest

Campo Regra
Name Obrigatório, máx 255 caracteres
Description Máx 1000 caracteres
Prompt Máx 20000 caracteres

AgentAiAssistantRequest

Campo Regra
AgentId Obrigatório
SectionKey Obrigatório (freeform, knowledge, step, step_planner)
UserMessage Obrigatório, máx 4000 caracteres

CreateKnowledgeBlockRequest

Campo Regra
Title Obrigatório, máx 200 caracteres
Content Obrigatório

CreateFaqItemRequest / UpdateFaqItemRequest

Campo Regra
Question Obrigatório, máx 500 caracteres
Answer Obrigatório

Erros Comuns

Status Código Descrição
404 AGENT_NOT_FOUND Agente não encontrado
409 AGENT_NAME_EXISTS Já existe agente com este nome
400 VALIDATION_ERROR Campos inválidos