O CloudOps CLI é um console de operações self-service em linha de comando projetado para rodar localmente no terminal do desenvolvedor. Ele permite gerenciar, monitorar, provisionar e destruir recursos de infraestrutura na AWS (especialmente adequado para as limitações do AWS Academy Learner Labs) por meio de uma interface interativa baseada em texto e de um Assistente de IA Autônomo.
Este projeto foca na arquitetura de um CLI Local Híbrido, que combina comandos automatizados determinísticos de infraestrutura sob demanda com tomadas de decisão cognitivas via Agente de IA (orquestrado pela @strands-agents/sdk integrada ao modelo Groq).
┌───────────────────────────────────────┐
│ TERMINAL DO USUÁRIO │
│ $ bun run src/cli.ts (cloudops) │
└──────────────────┬────────────────────┘
│
┌──────────────────────────┴──────────────────────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ FLUXO IA │ │ FLUXO DIRETO │
│ Agent SDK │ │ Menu CLI │
└──────┬───────┘ └──────┬───────┘
│ │
├───────────────┬──────────────── │
▼ ▼ ▼ │
[Ferramentas] [Segurança] [Aprovações] │
use_aws Monkey Patches BeforeToolCall │
get_logs Tokens Tokenizer Confirm Hook │
│ │ │ │
▼ ▼ ▼ ▼
┌────────────────────────────────────────────────────────────┐
│ AWS SDK v3 CLIENTS │
│ EC2 │ RDS │ ELB │ Secrets │ DynamoDB │
└──────────────────────────────┬─────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────┐
│ RECURSOS AWS │
│ │
│ ✦ Infraestrutura Dinâmica (EC2, RDS, ALB) │
│ ✦ CloudWatch Logs (logs de sistema e inicialização) │
│ ✦ DynamoDB (Log Centralizado e Histórico de Ações) │
│ ✦ Secrets Manager (Configurações e Chaves do Usuário) │
└────────────────────────────────────────────────────────────┘
A arquitetura do CLI divide-se em duas camadas lógicas principais:
- Camada de Orquestração Local e IA: O CLI roda localmente no runtime Bun.js, provendo respostas rápidas e sem necessidade de infraestrutura de servidor ativa para o gerenciamento. A inteligência é orquestrada localmente no processo do CLI, conectando-se a APIs de inferência remota (Groq).
- Camada de Infraestrutura AWS Dinâmica: Diferente de plataformas IaC declarativas fixas, o CLI utiliza comandos imperativos diretamente via AWS SDK v3 para criar, consultar e excluir recursos na conta AWS do usuário com base no perfil de tags unificado (
userIdeplatform: cloudops-console).
- Runtime: Bun.js - Execução ultrarrápida de TypeScript nativo, gerenciamento de pacotes integrado e compatibilidade de chamadas locais.
- Framework CLI: @clack/prompts - Utilizado para construir menus interativos, spinners de carregamento, prompts de senha e modais de confirmação modernos diretamente no terminal.
- Orquestração de Agente de IA: @strands-agents/sdk - SDK para controle de estado do agente, tratamento de histórico e injeção dinâmica de ferramentas (Tools) com hooks de ciclo de vida.
- Modelo Cognitivo: Groq API (
openai/gpt-oss-20bou similar) - Processamento de linguagem natural configurado comtemperature: 0para garantir a geração precisa de chamadas estruturadas de ferramentas. - Provedor Cloud e Persistência: AWS SDK v3 - Comunicação direta com os serviços
EC2,RDS,Elastic Load Balancing V2,CloudWatch Logs,Secrets ManagereDynamoDB. - Renderização Visual: Renderizador Markdown Customizado baseando-se em cores ANSI e tabelas estruturadas desenhadas em caracteres unicode para exibição rica de saídas no terminal.
O repositório é 100% focado no CLI local, contendo a seguinte organização:
poc-fund-cloud/
├── package.json # Metadados, scripts e dependências do Bun
├── tsconfig.json # Configurações do compilador TypeScript
├── requirements.md # Documento de requisitos conceituais da plataforma
├── README.md # Este relatório arquitetural
├── last_commands.sh # Últimos códigos executáveis extraídos da IA
├── scripts/ # Utilitários adicionais de infraestrutura local
└── src/ # Código-fonte principal
├── cli.ts # Entrypoint do CLI, menus e loop de eventos
├── agent.ts # Definição do Agente de IA, ferramentas e patches
├── db.ts # Logs de auditoria e persistência via DynamoDB
└── lib/ # Bibliotecas de suporte
├── catalog.ts # Catálogo de Stacks (web-simple, web-alb, etc.)
├── limits.ts # Validadores de limites físicos do Learner Lab
├── renderer.ts # Renderizador ANSI de Markdown para o terminal
├── tags.ts # Tags padrão para governança de recursos
└── aws/ # Wrappers da AWS SDK v3
├── credentials.ts # Acesso a credenciais de usuários e webhooks
├── ec2.ts # Criação de instâncias e injeção do CW Agent
├── rds.ts # Criação e regras de acesso do PostgreSQL/MySQL
├── elb.ts # Integração com Application Load Balancer
├── logs.ts # Consulta a logs do CloudWatch Logs
├── resources.ts # Coleta centralizada de recursos por tag
└── errors.ts # Parser e tradutor de exceções da AWS
O assistente cognitivo centraliza o suporte de operações simplificado em português técnico.
O agente tem acesso a uma coleção de ferramentas locais de sistema:
get_instance_logs: Lê os logs de sistema (/var/log/messagesecloud-init) do CloudWatch de uma EC2 específica.get_provisioning_history: Obtém auditoria e log de ações executadas pelo usuário.check_lab_limits: Avalia em tempo real o consumo de instâncias e vCPUs vs os limites do Learner Lab.provision_stack: Instancia uma stack completa (EC2 + RDS + ALB) parametrizada.destroy_resource: Remove instâncias do EC2 ou RDS após validação de propriedade.use_aws: Permite rodar comandos arbitrários da AWS CLI. Para garantir a segurança, implementa uma validação robusta:- Blacklist: Bloqueia termos que alteram estado como
create-,delete-,terminate-,run-instances,put-, etc. - Whitelist: Apenas permite verbos seguros de leitura (
describe,list,get,help,download).
- Blacklist: Bloqueia termos que alteram estado como
web_search: Efetua buscas na web para capturar documentações atualizadas da AWS (utiliza parser autônomo baseado em HTML do DuckDuckGo, sem necessidade de chaves de API adicionais).get_public_ip: Captura o IP de internet do terminal do usuário para criação inteligente de regras de inbound.test_connection: Executa ping TCP diretamente do terminal local até o host para verificar se portas como80(HTTP) ou5432(RDS) estão abertas e acessíveis.save_executable_code: Salva scripts gerados localmente e aplica permissões de execução (chmod 755).cleanup_sg_rules: Limpa regras de Security Group temporárias criadas pelo CLI que ficaram órfãs (identificadas pela descrição contendocli-auto-sg).
Por meio do hook BeforeToolCallEvent do SDK, ações sensíveis e destrutivas (provision_stack, destroy_resource, save_executable_code) são interceptadas antes de serem disparadas. O CLI pausa temporariamente o processador do agente, exibe uma ficha técnica no terminal usando o Clack Note e solicita a aprovação explícita do usuário:
const decision = await clack.confirm({
message: "⚠️ ATENÇÃO: Verifique o conteúdo acima cuidadosamente. Deseja aprovar a gravação e o CONTEÚDO deste arquivo no seu workspace?",
active: "Sim, aprovar",
inactive: "Não, rejeitar"
});Se recusado, a chamada da ferramenta é abortada com segurança no ciclo de vida local.
Modelos de linguagem menores rodando em ambientes otimizados (como Groq) podem apresentar problemas de vazamento de tokens de delimitadores internos (tokenizer leak), como <|channel|>commentary ao final das chamadas de ferramentas ou argumentos. Para mitigar isso sem depender de tratamentos fracos de prompt:
- Validação do Nome de Ferramentas: Modificamos a regex
TOOL_NAME_PATTERNno core do SDK para aceitar os caracteres especiais de token. - Duplicação de Registro com Alias: Criamos um patch no
ToolRegistry.prototype.adddo SDK. Toda vez que uma ferramenta é registrada (ex:use_aws), o patch automaticamente clona o objeto usandoObject.create(tool)e registra uma variação com o sufixo (ex:use_aws<|channel|>commentary), garantindo que tanto a propriedadenamequanto os metadadostoolSpec.namefiquem idênticos. Dessa forma, caso o modelo vaze o token, a API de inferência reconhece a ferramenta normalmente. - Estabilidade de Temperatura: Forçamos a configuração do
OpenAIModelcomtemperature: 0nas definições de inferência para aumentar a previsibilidade lógica do JSON gerado.
A criação dinâmica de recursos é rastreada na AWS por meio de tags estruturadas. Isso garante que múltiplos desenvolvedores possam compartilhar a mesma conta do AWS Academy sem interferirem nos recursos dos outros:
platform: Identifica que o recurso foi criado pelo console (cloudops-console).userId: Identifica a conta/matrícula do desenvolvedor dono do recurso.stackId: Vincula o recurso à stack correspondente (web-simple,web-alboudb-only).
Quando o usuário solicita a listagem ou exclusão de recursos, as SDKs de consulta filtram as instâncias localmente e na API da AWS usando a tag userId correspondente.
Toda EC2 criada dinamicamente passa por injeção de script de inicialização (UserData) codificado em Base64. Esse script realiza os seguintes passos de bootstrap:
- Instala o agente unificado da AWS CloudWatch (
amazon-cloudwatch-agent). - Escreve o arquivo de configuração para coletar o syslog do sistema (
/var/log/messages) e logs de inicialização (/var/log/cloud-init-output.log). - Define dinamicamente o grupo de log mapeado na estrutura
/cloudops/{userId}/{instanceId}. - Inicializa o serviço do agente.
Isso permite que o desenvolvedor use a ferramenta get_instance_logs do assistente ou consulte logs diretamente pelo terminal local de forma instantânea.
- EC2: No ato do provisionamento, as portas de tráfego web padrão (
80e443) são automaticamente liberadas no Security Group da instância com regras de Ingress para tráfego público (0.0.0.0/0). - RDS PostgreSQL/MySQL: Se a stack for criada com banco público (
dbPublic: true), a porta padrão de comunicação5432ou3306é automaticamente liberada no Security Group padrão (default) para receber acessos externos, permitindo testes diretos de conexão local via CLI.
Para evitar a necessidade de gerenciar bancos de dados SQL locais e complexos (como PostgreSQL/MySQL autohospedados) apenas para auditar ações, o CLI adota um modelo totalmente serverless e leve usando o Amazon DynamoDB:
- Ao provisionar ou destruir uma stack, os detalhes (IDs dos recursos, data, status de sucesso e detalhes estruturados) são gravados em uma tabela do DynamoDB.
- O histórico é armazenado em uma tabela única compartilhada chamada
cloudops-history. - A tabela utiliza
userIdcomo chave de partição (HASH) etimestampcomo chave de ordenação (RANGE). Isto evita a proliferação desnecessária de tabelas na conta do Learner Lab, mantendo a governança adequada para buscas ordenadas cronologicamente. - O CLI cria a tabela sob demanda de forma transparente via
CreateTableCommandcaso ela ainda não exista na conta. - Regras de Security Group: As regras de Ingress criadas dinamicamente são registradas com a descrição
cli-auto-sg|{userId}|{timestamp}, permitindo a auditoria e a remoção posterior por meio da ferramentacleanup_sg_rules.
- Bun.js instalado na máquina.
- AWS CLI configurado localmente ou variáveis de ambiente da AWS exportadas (Access Key, Secret Key, Session Token) provenientes do seu AWS Academy Learner Lab.
Clone o projeto e instale as dependências:
bun installVocê pode preencher um arquivo .env na raiz do projeto com sua chave da Groq API:
GROQ_API_KEY=gsk_your_groq_api_key_hereDica: Caso a chave da API do Groq não seja fornecida no arquivo
.envou nas variáveis de ambiente, o CLI fará uma busca automática no Secrets Manager da AWS pelo segredolab-groq/default. Caso ainda não esteja configurado lá, o CLI solicitará interativamente pelo terminal e salvará no.envpara você.
Execute o script de inicialização padrão via Bun:
bun startO CLI carregará suas credenciais locais da AWS, efetuará a validação da sessão (via STS) de forma imediata e abrirá o painel de controle. Se suas credenciais do Learner Lab estiverem expiradas, o CLI exibirá um aviso explicativo e encerrará a execução com segurança.
Você pode rodar todo o CLI de forma simulada passando a flag --dry-run:
bun start -- --dry-runNeste modo:
- Nenhuma operação real será enviada para a AWS (as chamadas de SDK de provisionamento, exclusão e CLI serão simuladas com sucesso).
- As gravações de arquivos e execuções locais serão simuladas.
- Caso você não tenha credenciais AWS exportadas, o CLI usará credenciais fictícias e um ID de conta mockado (
123456789012), permitindo que você demonstre o funcionamento completo do chat e do fluxo de aprovações sem internet ou chaves ativas!