feat: Update architecture proposal with enhanced automation details and SQL optimization insights

This commit is contained in:
william.dias 2026-01-21 14:54:48 -03:00
parent 7e9149ca72
commit d6adaa204c
6 changed files with 88 additions and 31 deletions

View file

@ -2,7 +2,7 @@
## 1) Resumo executivo
Esta proposta apresenta uma arquitetura moderna baseada em Agno para construção de agentes especializados em performance e refatoração de queries SQL Server e Oracle, com governança, observabilidade e segurança de dados. O objetivo é acelerar a melhoria de desempenho, reduzir custos operacionais e habilitar automações confiáveis em múltiplos setores. O desenho prioriza previsibilidade de custos, rastreabilidade e integração com processos corporativos já existentes.
Esta proposta posiciona a Icatu na vanguarda da automação inteligente com uma arquitetura Agno-first para otimização de SQL Oracle e SQL Server. O resultado esperado é **ganho acelerado de performance**, **redução direta de custos** e **escala de produtividade** sem aumento proporcional de equipes. A solução traz governança, observabilidade e segurança desde o primeiro dia, com integração total aos fluxos corporativos e potencial de automação transversal em toda a empresa.
## 2) Objetivo do projeto
@ -12,6 +12,8 @@ Esta proposta apresenta uma arquitetura moderna baseada em Agno para construçã
- Viabilizar RAG corporativo para respostas alinhadas ao conhecimento interno.
- Preparar integração com canais corporativos (ex.: Microsoft Teams) para entrada de solicitações.
Resultado esperado: **padronização técnica corporativa**, **velocidade de entrega** e **governança executiva** para decisões de performance.
## 3) Escopo funcional
- Otimização de queries SQL para Oracle e SQL Server.
@ -20,6 +22,8 @@ Esta proposta apresenta uma arquitetura moderna baseada em Agno para construçã
- Execução assistida (manual ou semi-automática) com trilha de auditoria.
- Produção de relatórios executivos e técnicos por área/solicitante.
Escopo desenhado para impacto rápido: **as consultas mais críticas recebem atenção imediata**, e o conhecimento se acumula para ganhos contínuos.
## 4) Benefícios para a diretoria
- **Eficiência operacional**: redução de tempo gasto por equipes na análise manual de queries.
@ -28,7 +32,7 @@ Esta proposta apresenta uma arquitetura moderna baseada em Agno para construçã
- **Governança e compliance**: rastreabilidade, métricas, custos e decisões auditáveis.
- **Redução de risco**: revisão automática e análise conservadora antes de mudanças.
Detalhamento das vantagens:
Detalhamento das vantagens (foco executivo):
- **ROI acelerado**: melhora contínua de performance reduz custos de infraestrutura e tempo de execução de cargas críticas.
- **Padronização técnica**: boas práticas de SQL e refatoração aplicadas de forma consistente em toda a empresa.
@ -36,6 +40,7 @@ Detalhamento das vantagens:
- **Observabilidade e previsibilidade**: visibilidade clara de custos, latência e impacto das mudanças por área.
- **Escala por demanda**: agentes acionados sob demanda, com priorização por SLA e criticidade.
- **Qualidade contínua**: revisão e validação reduzem regressões em ambientes críticos.
- **Imagem institucional**: adoção de IA aplicada com governança fortalece a percepção de inovação e maturidade tecnológica.
## 5) Novas possibilidades de automação
@ -45,6 +50,7 @@ Detalhamento das vantagens:
- **Assistente de engenharia** para padrões corporativos de SQL.
- **RAG corporativo** para políticas internas, padrões de modelagem e convenções.
- **Apoio a squads** com respostas contextualizadas e justificativas técnicas.
- **Automação orientada a metas**: backlog de otimizações priorizado por impacto financeiro.
## 5.1) Cenários de automação por setor
@ -98,6 +104,8 @@ Detalhamento das vantagens:
- **Integrações corporativas**: bancos, repositórios de conhecimento, logs e custos.
- **Camada de governança**: políticas de acesso, limites de uso e auditoria.
Arquitetura pensada para expansão: novos agentes, novos bancos e novos fluxos entram sem reescrita do core.
## 6.1) Integração com Microsoft Teams
- **Canal dedicado**: solicitações feitas diretamente no Teams por usuários autorizados.
@ -106,6 +114,7 @@ Detalhamento das vantagens:
- **Notificações automáticas**: alertas de performance e relatórios em tempo real.
- **Trilha de auditoria**: registro de solicitações e respostas por usuário/time.
- **Rotas por squad**: distribuição automática de tarefas por área responsável.
- **Experiência fluida**: usuários solicitam melhorias sem sair do canal que já utilizam diariamente.
## 7) Observabilidade (obrigatório)
@ -122,6 +131,7 @@ Métricas mínimas:
- Latência média e p95.
- Taxa de retrabalho/recusa.
- Taxa de aprovação e impacto percebido.
- Ganhos mensais estimados por área (tempo e custo).
## 8) Segurança da informação
@ -130,6 +140,7 @@ Métricas mínimas:
- **Mascaramento de dados sensíveis** antes do envio ao LLM.
- **Políticas de retenção** e segregação de dados por área.
- **Auditoria completa** de entradas/saídas para rastreabilidade.
- **Conformidade reforçada**: trilhas claras para auditoria interna e externa.
## 9) RAG corporativo
@ -137,6 +148,7 @@ Métricas mínimas:
- Ingestão de documentação técnica, padrões e decisões arquiteturais.
- Recuperação com filtros por área e confidencialidade.
- Curadoria contínua com feedback dos times para melhorar a relevância.
- **Aumento de precisão**: respostas consistentes com políticas internas e padrões técnicos.
## 10) Frameworks considerados
@ -145,6 +157,7 @@ Métricas mínimas:
- **Pontos fortes**: orquestração de agentes, memória, tools, execução local, integração rápida.
- **Ideal para**: time de agentes especializados e integração customizada.
- **Governança**: fácil acoplamento com módulos de observabilidade e segurança.
- **Escala corporativa**: mais aderente a integrações enterprise e customizações profundas.
### B) Langflow
@ -164,6 +177,7 @@ Métricas mínimas:
- **Langflow** para protótipos e desenho de fluxos.
- **Dify** para distribuição ampla (se desejarem um portal corporativo pronto).
- **Observabilidade** acoplada desde o início (OpenTelemetry + Langfuse/Phoenix).
- **Escala com controle**: custos e resultados visíveis para a diretoria em dashboards executivos.
## 12) Roadmap proposto
@ -171,6 +185,7 @@ Métricas mínimas:
2. **Fase 2**: observabilidade + segurança + governança.
3. **Fase 3**: escala para áreas e processos internos.
4. **Fase 4**: integração com Teams e automações cross-area.
5. **Fase 5**: expansão para todo o ciclo de vida de performance (detecção, otimização, validação, monitoramento).
## 13) Riscos e mitigação
@ -179,12 +194,15 @@ Métricas mínimas:
- **Vazamento de dados**: mitigado com RAG isolado e mascaramento.
- **Mudanças não controladas**: mitigado com workflow de aprovação.
O modelo foi desenhado para que **os ganhos superem consistentemente qualquer esforço de implantação**, com governança e controle pleno.
## 14) Próximos passos
- Alinhamento técnico com @Rodrigo Bittencourt De Macedo.
- Definição do escopo mínimo viável (Oracle + SQL Server).
- Aprovação do framework prioritário e das ferramentas de observabilidade.
- Definição de critérios de sucesso (KPIs técnicos e executivos).
- Plano de comunicação executiva e cronograma de entregas visíveis para a diretoria.
---

File diff suppressed because one or more lines are too long

View file

@ -30,7 +30,8 @@ sql_quality_agent = Agent(
"- Compare a explicação natural com a SQL otimizada e destaque riscos de divergência.",
"- Use checklist: tabelas, colunas, CASE, subqueries, filtros, joins, aliases, cálculos.",
"- Gere o diff linha a linha usando diff_sql(original_sql, optimized_sql).",
"- Apresente o diff em formato visual (lado a lado) e depois comente cada trecho alterado.",
"- Inclua um diff lado a lado (tabela) imediatamente após a SQL otimizada.",
"- Depois do diff, comente cada trecho alterado.",
"- Para cada trecho alterado: descreva o que mudou, por que mudou, vantagens, desvantagens e riscos.",
"- Se houver risco, solicite correção ao SQL Optimizer com detalhes objetivos.",
"- Não reescreva a SQL diretamente.",

View file

@ -29,7 +29,7 @@ class AgnoLLMAdapter(BaseLLMAdapter):
self._log_request(prompt, temperature=temperature, max_tokens=max_tokens)
try:
# Best-effort: set common parameters if supported by model
if hasattr(self._model, "temperature"):
if self._supports_temperature() and hasattr(self._model, "temperature"):
setattr(self._model, "temperature", temperature)
if hasattr(self._model, "max_tokens"):
setattr(self._model, "max_tokens", max_tokens)
@ -50,6 +50,11 @@ class AgnoLLMAdapter(BaseLLMAdapter):
def provider_name(self) -> str:
return self._model.get_provider()
def _supports_temperature(self) -> bool:
model_id = getattr(self._model, "id", "")
normalized = str(model_id).strip().lower()
return not normalized.startswith("gpt-5")
@staticmethod
def _extract_text(response: Any) -> Optional[str]:
"""Extract response text from Agno ModelResponse."""

View file

@ -2,7 +2,7 @@
from agno.models.anthropic import Claude
from agno.models.google import Gemini
from agno.models.openai import OpenAIChat
from agno.models.openai import OpenAIChat, OpenAIResponses
from agno.models.groq import Groq
from agno.models.mistral.mistral import MistralChat
from agno.models.ollama import Ollama
@ -75,9 +75,15 @@ class LLMAdapterFactory:
provider = settings.llm.provider
api_key = settings.llm.api_key
def _openai_model_class(model_id: str):
normalized = model_id.strip().lower()
if normalized.startswith("gpt-5") or normalized.startswith("o3") or normalized.startswith("o4-mini"):
return OpenAIResponses
return OpenAIChat
providers = {
"gemini": (Gemini, "GOOGLE_API_KEY"),
"openai": (OpenAIChat, "OPENAI_API_KEY"),
"openai": (_openai_model_class(model), "OPENAI_API_KEY"),
"claude": (Claude, "ANTHROPIC_API_KEY"),
"groq": (Groq, "GROQ_API_KEY"),
"mistral": (MistralChat, "MISTRAL_API_KEY"),

View file

@ -177,6 +177,40 @@ def _escape_html(text: str) -> str:
)
def _append_row(rows: list[str], left: str, right: str) -> None:
rows.append(
f"<tr><td><pre>{_escape_html(left)}</pre></td><td><pre>{_escape_html(right)}</pre></td></tr>"
)
def _iter_pairs(left_lines: list[str], right_lines: list[str]) -> Iterable[tuple[str, str]]:
max_len = max(len(left_lines), len(right_lines))
for idx in range(max_len):
left = left_lines[idx] if idx < len(left_lines) else ""
right = right_lines[idx] if idx < len(right_lines) else ""
yield left, right
def _handle_equal(rows: list[str], left: list[str], right: list[str]) -> None:
for lval, rval in zip(left, right):
_append_row(rows, lval, rval)
def _handle_replace(rows: list[str], left: list[str], right: list[str]) -> None:
for lval, rval in _iter_pairs(left, right):
_append_row(rows, lval, rval)
def _handle_delete(rows: list[str], left: list[str], _right: list[str]) -> None:
for lval in left:
_append_row(rows, lval, "")
def _handle_insert(rows: list[str], _left: list[str], right: list[str]) -> None:
for rval in right:
_append_row(rows, "", rval)
def diff_sql(original_sql: str, optimized_sql: str) -> str:
"""Generate a side-by-side diff between original and optimized SQL.
@ -193,32 +227,17 @@ def diff_sql(original_sql: str, optimized_sql: str) -> str:
matcher = difflib.SequenceMatcher(a=original_lines, b=optimized_lines)
rows: list[str] = []
handlers = {
"equal": _handle_equal,
"replace": _handle_replace,
"delete": _handle_delete,
"insert": _handle_insert,
}
for tag, i1, i2, j1, j2 in matcher.get_opcodes():
if tag == "equal":
for left, right in zip(original_lines[i1:i2], optimized_lines[j1:j2]):
rows.append(
f"<tr><td><pre>{_escape_html(left)}</pre></td><td><pre>{_escape_html(right)}</pre></td></tr>"
)
elif tag == "replace":
left_chunk = original_lines[i1:i2]
right_chunk = optimized_lines[j1:j2]
max_len = max(len(left_chunk), len(right_chunk))
for idx in range(max_len):
left = left_chunk[idx] if idx < len(left_chunk) else ""
right = right_chunk[idx] if idx < len(right_chunk) else ""
rows.append(
f"<tr><td><pre>{_escape_html(left)}</pre></td><td><pre>{_escape_html(right)}</pre></td></tr>"
)
elif tag == "delete":
for left in original_lines[i1:i2]:
rows.append(
f"<tr><td><pre>{_escape_html(left)}</pre></td><td><pre></pre></td></tr>"
)
elif tag == "insert":
for right in optimized_lines[j1:j2]:
rows.append(
f"<tr><td><pre></pre></td><td><pre>{_escape_html(right)}</pre></td></tr>"
)
handler = handlers.get(tag)
if handler:
handler(rows, original_lines[i1:i2], optimized_lines[j1:j2])
if not rows:
return "<table><tr><th>Original</th><th>Otimizada</th></tr></table>"