# Planteio API - Arquitetura de Agentes

Este documento detalha o fluxo conversacional do modulo `src/agent`, incluindo responsabilidades, transicoes, estados `pending` e dependencias entre agentes.

## 1. Arquitetura geral

Entradas principais:

- WhatsApp via Evolution: [`src/agent/agent.controller.ts`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.controller.ts)
- Web agent: [`src/agent/agent.controller.ts`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.controller.ts)

Fluxo macro:

1. Recebe mensagem.
2. Normaliza canal, telefone, `messageId` e conteudo.
3. Monta ou recupera `AgentContext`.
4. Executa `handleController`.
5. O controller define a `route`.
6. `executeRoute` chama o subagente.
7. O subagente responde, atualiza `payload`, `transient`, `pending` e `route`.
8. O contexto atualizado e salvo no Redis.

Arquivos centrais:

- [`src/agent/agent.service.ts`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts)
- [`src/agent/types/agent-context.type.ts`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\types\agent-context.type.ts)
- [`src/agent/constants/prompts.ts`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\constants\prompts.ts)
- [`src/agent/assistants/assistant/assistant.agent.ts`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\assistants\assistant\assistant.agent.ts)

## 2. Modelo de estado

O contexto compartilhado do agente fica em [`src/agent/types/agent-context.type.ts`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\types\agent-context.type.ts).

Campos mais importantes:

- `context.route`: subagente atualmente responsavel.
- `context.replyKey`: chave de catalogo para respostas fixas.
- `context.requirements`: flags manuais de forca de rota.
- `context.pending`: estado pendente do fluxo.
- `context.payload`: dados mais persistentes durante a conversa atual.
- `context.transient`: rascunho do que ainda nao foi confirmado/salvo.
- `meta.contextChannel`: `whatsapp` ou `web`.

Leitura pratica:

- `route` diz quem atende.
- `pending` diz em qual pergunta do fluxo o usuario esta.
- `payload` guarda dados ja aceitos.
- `transient` guarda dados em construcao ou resposta anterior do assistant.

## 3. Entradas e preprocessamento

### 3.1 WhatsApp / Evolution

Ponto de entrada: [`handleWebhook`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L514)

Etapas:

1. Aceita payload unico ou array.
2. Descarta eventos sem `data.key`.
3. Ignora mensagens `fromMe`.
4. Resolve `remoteJid`, inclusive fallback de `remoteJidAlt`.
5. Normaliza telefone.
6. Faz deduplicacao no Redis por `instance + phone + messageId`.
7. Extrai conteudo por tipo:
   - texto
   - audio transcrito
   - imagem para texto
   - documento para texto
   - localizacao via reverse geocode
8. Define canal `web` ou `whatsapp`.
9. Carrega contexto.
10. Verifica expiracao de plano.
11. Salva historico do usuario.
12. Executa controller e subagente.
13. Persiste contexto.

### 3.2 Web agent

Ponto de entrada: [`handleWebAgent`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L672)

Etapas:

1. Aceita `message` ou `mediaBase64`.
2. Resolve `mediaType` e `mediaMimeType`.
3. Resolve telefone por `phone` ou `profileId`.
4. Cria uma mensagem sintetica no formato esperado pelo pipeline do agente.
5. Reaproveita a mesma cadeia de tratamento do contexto.

Conclusao: Web e WhatsApp convergem para o mesmo motor conversacional.

## 4. Controller

Ponto principal: [`handleController`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L1213)

Prompt: [`CONTROLLER_AGENT_PROMPT`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\constants\prompts.ts#L1)

Responsabilidades:

- Definir qual subagente assume a mensagem.
- Preservar fluxos em andamento.
- Aplicar atalhos e regras deterministicas antes de chamar IA.
- Encaminhar para fallback de `response` quando necessario.

Ordem de decisao:

1. Hashtags:
   - `#resumo-semanal` -> `resumosemanal`
   - `#relatorio` -> `relatorio`
   - `#agronews` -> `clima`
2. Cancelamento de plano:
   - `response` com `replyKey = cancel_plan`
3. Follow-up explicativo:
   - se houver `assistantLastAnswer`, manda para `assistant`
4. Se existe `route` ativa:
   - mantem a rota
   - excecao importante: escape do onboarding de `plot` quando a mensagem parece evento
5. Menu principal:
   - `1` -> `events`
   - `2` -> `plot`
   - `3` -> `relatorio`
   - `4` -> `response` com `assistant_examples`
6. `requirements`:
   - `plot`, `safra`, `event`
7. Classificacao por IA.

Rotas finais executadas por [`executeRoute`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L1431):

- `profile`
- `events`
- `plot`
- `safra`
- `clima`
- `resumosemanal`
- `relatorio`
- `assistant`
- `response`
- `noop`

## 5. Agente de perfil

Ponto principal: [`handleProfileAgent`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L1458)

Prompt: [`PROFILE_AGENT_PROMPT`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\constants\prompts.ts#L103)

Responsabilidades:

- Fazer onboarding inicial.
- Atualizar cadastro.
- Coletar nome, propriedade, endereco e cidade.
- Tentar geocodificar cidade/endereco para latitude e longitude.
- Pedir confirmacao antes de salvar.
- Persistir `planteio_profiles`.

Fluxo de conversa:

1. Usuario sem perfil cai em `profile`.
2. Pergunta nome.
3. Pergunta nome da propriedade.
4. Pergunta endereco completo ou localizacao.
5. Extrai cidade e, quando possível, coordenadas.
6. Monta resumo final.
7. Marca `transient.profile_confirm_pending = true`.
8. Aguarda confirmacao explicita.
9. Em `upsert_profile`, salva perfil.
10. Faz handover para `plot`.

Estados relevantes:

- `transient.profile_confirm_pending`
- `payload.profile`
- `transient.profile`

Transicoes principais:

- `controller -> profile`
- `profile -> plot`

## 6. Agente de talhao

Ponto principal: [`handlePlotAgent`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L3787)

Prompt: [`PLOT_AGENT_PROMPT`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\constants\prompts.ts#L273)

Responsabilidades:

- Cadastrar um ou varios talhoes.
- Detectar duplicidade por nome.
- Validar area em hectares.
- Confirmar antes de salvar.
- Cancelar fluxo quando pedido.

Fluxo de conversa:

1. Recebe mensagem de cadastro/edicao/listagem.
2. Busca nomes de talhoes existentes.
3. Usa LLM para extrair `plots`, `intent`, `action`.
4. Se faltar dados, entra em coleta.
5. Se houver duplicidade, pede ajuste.
6. Se dados completos, entra em confirmacao.
7. Se confirmado, salva via `upsertPlotFromTransient`.
8. Envia menu principal.

Estados `pending` de plot:

- `plot_collect`
- `plot_confirmation_create`
- `plot_confirmation_update`

Transicoes principais:

- `controller -> plot`
- `profile -> plot`
- `plot -> response`

## 7. Agente de eventos

Ponto principal: [`handleEventsAgent`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L1654)

Prompts:

- [`EVENTS_PENDING_NORMALIZER_PROMPT`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\constants\prompts.ts#L390)
- [`EVENTS_EXTRACTOR_PROMPT`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\constants\prompts.ts#L469)

Responsabilidades:

- Registrar custos, receitas, manejo, plantio, colheita, estoque e operacoes gerais.
- Interpretar mensagens livres, audio, imagem e follow-ups.
- Associar evento a talhao, safra e status.
- Resolver campos faltantes com perguntas guiadas.
- Tratar conflitos de safra.
- Salvar evento no banco.

Fluxo de conversa resumido:

1. Exige perfil antes de tudo.
2. Carrega contexto operacional:
   - talhoes
   - safras abertas
   - status
   - payload/transient atual
3. Se existe `pending`, normaliza a resposta do usuario.
4. Se nao existe `pending`, roda extracao estruturada do evento.
5. Completa lacunas obrigatorias.
6. Entra em estados de escolha ou confirmacao.
7. Persiste evento.
8. Limpa fluxo.

Estados `pending` encontrados no fluxo de eventos:

- `ask_plot_area`
- `ask_plot_name`
- `confirm_create_plot`
- `choose_plot`
- `choose_status`
- `ask_safra_start_date`
- `choose_or_create_safra_for_event`
- `confirm_create_safra`
- `resolve_cost_or_profit`
- `ask_event_title`
- `ask_event_date`
- `confirm_event`
- `confirm_planting_conflict`
- `confirm_switch_safra`

Leitura por grupos:

Estados de talhao dentro de `events`:

- `ask_plot_name`
- `ask_plot_area`
- `confirm_create_plot`

Estados de safra dentro de `events`:

- `ask_safra_start_date`
- `choose_or_create_safra_for_event`
- `confirm_create_safra`
- `confirm_switch_safra`

Estados de evento:

- `choose_plot`
- `choose_status`
- `resolve_cost_or_profit`
- `ask_event_title`
- `ask_event_date`
- `confirm_event`
- `confirm_planting_conflict`

Transicoes principais:

- `controller -> events`
- `events -> safra` em termos de responsabilidade funcional, quando o fluxo precisa de uma safra viavel
- `events -> response` ao concluir

Observacao importante:

O agente de eventos funciona como uma maquina de estados operacional e e o coracao transacional do produto.

## 8. Agente de safra

Ponto principal: [`handleSafraAgent`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L4005)

Prompt: [`SAFRA_AGENT_PROMPT`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\constants\prompts.ts#L618)

Responsabilidades:

- Listar safras abertas.
- Abrir nova safra.
- Encerrar safra existente.
- Guiar escolha de talhao, cultura e data.

Fluxos principais:

Encerramento:

1. Usuario pede encerrar safra.
2. Lista safras abertas.
3. Usuario escolhe por numero ou letra.
4. Sistema pede confirmacao.
5. Se confirmado, encerra a safra.
6. Pergunta se deseja abrir nova safra.

Abertura:

1. Usuario pede abrir safra.
2. Pergunta talhao.
3. Pergunta cultura.
4. Pergunta data de inicio.
5. Pede confirmacao.
6. Cria safra.

Estados `pending` de safra:

- `choose_safra_to_close`
- `confirm_close_safra`
- `ask_create_after_close`
- `ask_create_after_no_open`
- `ask_create_plot`
- `ask_create_culture`
- `ask_create_start_date`
- `confirm_create_safra`

Transicoes principais:

- `controller -> safra`
- `events -> safra` como dependencia operacional
- `safra -> response`

## 9. Agente clima / AgroNews

Ponto principal: [`handleClimaAgent`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L4631)

Prompt: [`AGRONEWS_AGENT_PROMPT`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\constants\prompts.ts#L737)

Responsabilidades:

- Buscar clima atual por coordenada ou cidade.
- Identificar culturas relevantes do produtor.
- Buscar cotacoes mais recentes das culturas.
- Montar mensagem diaria curta para WhatsApp.
- Persistir notificacao local.

Entradas:

- Cron diario
- Hashtag `#agronews`

Regra de plano:

- Antes de executar o fluxo do cron, o sistema reutiliza a mesma validacao de vencimento usada no controller.
- Se o plano estiver expirado:
  - o cron nao executa `handleClimaAgent`
  - nao chama a IA
  - envia diretamente a mesma mensagem padrao de plano expirado
- Se o plano estiver valido:
  - o cron continua normalmente

Fluxo:

1. Busca clima.
2. Busca safras abertas e talhoes.
3. Normaliza culturas.
4. Busca cotacoes em SQL.
5. Chama LLM para resumir.
6. Envia mensagem.
7. Salva `planteio_notifications`.

Cron:

- [`runDailyAgroNewsForAllClients`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L359)

## 10. Agente resumo semanal

Ponto principal: [`handleResumoSemanalAgent`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L4775)

Responsabilidades:

- Calcular indicadores da ultima semana.
- Consolidar saldo por safra.
- Consolidar saldo por hectare.
- Enviar mensagem pronta com link do painel.

Entradas:

- Cron
- Hashtag `#resumo-semanal`

Regra de plano:

- Antes de executar o fluxo do cron, o sistema reutiliza a mesma validacao de vencimento usada no controller.
- Se o plano estiver expirado:
  - o cron nao executa `handleResumoSemanalAgent`
  - nao chama a IA
  - envia diretamente a mesma mensagem padrao de plano expirado
- Se o plano estiver valido:
  - o cron continua normalmente

Fluxo:

1. Busca safras ativas.
2. Conta eventos da semana.
3. Busca eventos das safras ativas.
4. Calcula saldo total e saldo da semana.
5. Monta mensagem textual.
6. Envia mensagem.

Cron:

- [`runWeeklyResumoSemanalForAllClients`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L437)

## 11. Agente de relatorio

Ponto principal: [`handleRelatorioAgent`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L5003)

Responsabilidades:

- Gerar link de acesso ao painel.
- Opcionalmente gerar codigo temporario de login.

Fluxo:

1. Gera link.
2. Responde com CTA para o painel.

Transicoes:

- `controller -> relatorio`
- `relatorio -> response`

## 12. Agente de resposta

Ponto principal: [`handleResponseAgent`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\agent.service.ts#L5084)

Responsabilidades:

- Entregar respostas fixas de menu/catalogo.
- Servir fallback do sistema.
- Responder checkout de plano e mensagens estaticas.

Entradas tipicas:

- saudacao
- ajuda
- menu
- fallback do controller
- checkout/cancelamento de plano

Transicoes:

- `controller -> response`
- `plot -> response`
- `safra -> response`
- `events -> response`

## 13. Assistant

Ponto principal: [`src/agent/assistants/assistant/assistant.agent.ts`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\assistants\assistant\assistant.agent.ts)

Prompts principais:

- [`ASSISTANT_PLANNER_PROMPT`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\assistants\assistant\prompts\assistant.prompts.ts)
- extractors de venda, categoria, colheita e resposta descritiva

Responsabilidades:

- Responder perguntas analiticas sobre os registros do usuario.
- Responder perguntas descritivas sobre eventos, safras e talhoes.
- Explicar a ultima resposta.
- Pedir desambiguacao quando houver varias safras candidatas.

Fluxo principal:

1. Verifica cancelamento.
2. Exige perfil valido.
3. Se houver `assistant_choose_safras`, continua esse pending.
4. Verifica follow-up explicativo com base em `assistantLastAnswer`.
5. Executa planner.
6. Monta dataset filtrado.
7. Se houver ambiguidade de safra, pede selecao por ID.
8. Executa resposta metrica ou descritiva.
9. Guarda a resposta em `transient.assistantLastAnswer`.
10. Limpa `route` e `pending`.

Estado `pending` do assistant:

- `assistant_choose_safras`

Principais capacidades:

- custo total
- custo por hectare
- faturamento total
- lucro liquido
- quantidade vendida
- preco por kg
- margem por kg
- produtividade total
- produtividade por hectare
- custo por categoria
- percentual de custo por categoria
- volume de insumo por hectare
- perguntas descritivas sobre:
  - ultimo evento
  - produto usado
  - dose
  - praga
  - data
  - detalhes
  - talhoes
  - safras
  - safra ativa por talhao
  - safra atual por cultura
  - historico de safra por talhao

Arquivos auxiliares:

- [`src/agent/assistants/assistant/prompts/assistant.prompts.ts`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\assistants\assistant\prompts\assistant.prompts.ts)
- [`src/agent/assistants/assistant/catalog/assistant.catalog.ts`](f:\Developer\SudesteOnline\planteio\planteio-api\src\agent\assistants\assistant\catalog\assistant.catalog.ts)

## 14. Diagrama de responsabilidades

```mermaid
flowchart LR
  A["Entrada Webhook/Web"] --> B["Montar/Recuperar Contexto"]
  B --> C["Controller"]
  C --> D["Profile"]
  C --> E["Plot"]
  C --> F["Events"]
  C --> G["Safra"]
  C --> H["Assistant"]
  C --> I["Clima / AgroNews"]
  C --> J["Resumo Semanal"]
  C --> K["Relatorio"]
  C --> L["Response"]

  D --> E
  E --> L
  F --> G
  F --> L
  G --> L
  H --> H
  H --> L
  I --> L
  J --> L
  K --> L
```

## 15. Diagrama de transicao conversacional

```mermaid
flowchart TD
  U["Mensagem do usuario"] --> C["Controller"]

  C -->|sem perfil| P["Profile"]
  C -->|talhao| T["Plot"]
  C -->|evento operacional| E["Events"]
  C -->|abrir ou encerrar safra| S["Safra"]
  C -->|consulta sobre dados| A["Assistant"]
  C -->|#agronews| N["Clima / AgroNews"]
  C -->|#resumo-semanal| R["Resumo Semanal"]
  C -->|relatorio| O["Relatorio"]
  C -->|menu ou fallback| M["Response"]

  P -->|perfil salvo| T
  T --> M
  E -->|dependencia de safra| S
  E --> M
  S --> M
  A -->|explicacao ou selecao de safra| A
  A --> M
  N --> M
  R --> M
  O --> M
```

## 16. Pendings consolidados

Lista consolidada de `pending.type` encontrada no modulo:

- `plot_collect`
- `plot_confirmation_create`
- `plot_confirmation_update`
- `ask_plot_area`
- `ask_plot_name`
- `confirm_create_plot`
- `choose_plot`
- `choose_status`
- `ask_safra_start_date`
- `choose_or_create_safra_for_event`
- `confirm_create_safra`
- `resolve_cost_or_profit`
- `ask_event_title`
- `ask_event_date`
- `confirm_event`
- `confirm_planting_conflict`
- `confirm_switch_safra`
- `choose_safra_to_close`
- `confirm_close_safra`
- `ask_create_after_close`
- `ask_create_after_no_open`
- `ask_create_plot`
- `ask_create_culture`
- `ask_create_start_date`
- `assistant_choose_safras`

## 17. Leitura executiva

O sistema tem quatro blocos de responsabilidade:

- Orquestracao: `controller`
- Escrita operacional: `profile`, `plot`, `events`, `safra`
- Leitura analitica: `assistant`
- Comunicacao e saida: `clima`, `resumosemanal`, `relatorio`, `response`

Na pratica:

- `events` e o motor transacional.
- `assistant` e o motor analitico.
- `controller` e o despacho central.
- `profile` e `plot` formam o onboarding funcional.
- Os crons de `agronews` e `resumo semanal` tambem respeitam bloqueio por plano expirado antes de qualquer processamento.
