Skip to content

charlenopires/FlaFludeAgentes

Repository files navigation

⚽ FlaFludeAgentes

Sistema multi-agente de debate entre torcedores brasileiros usando Google ADK (Agent Development Kit) + protocolo A2A oficial (a2a-sdk) + LLMs via OpenRouter (LiteLLM). Quatro torcedores (Flamengo, Fluminense, Corinthians, Palmeiras) discutem qual é o maior; um Supervisor sorteia dois deles por rodada e atua como mestre de cerimônia; um Pesquisador com busca web em tempo real fornece fatos; e um Julgador (especialista em retórica, psicologia cognitiva e neuro-persuasão) avalia os argumentos ao final e devolve o veredito ao Supervisor, que anuncia o resultado.

                       ┌──────────────┐
                       │  Streamlit   │  (porta 8501)
                       └──────┬───────┘
                              │  A2A JSON-RPC
        ┌────────────┬────────┼────────┬─────────────┐
        ▼            ▼        ▼        ▼             ▼
  ┌──────────┐ ┌──────────┐  …  ┌──────────┐  ┌──────────┐
  │Supervisor│ │ Torcedor │     │Pesquisad.│  │ Julgador │
  │  (8002)  │ │8003/4/6/7│     │  (8005)  │  │  (8008)  │
  └──────────┘ └──────────┘     └────┬─────┘  └──────────┘
                                     │ web search :online
                                     ▼
                                 🌐 internet

✨ O que tem

  • 7 agentes A2A (google-adk + a2a-sdk oficiais) rodando como servidores ASGI independentes via uvicorn — cada um expõe seu AgentCard em /.well-known/agent-card.json.
  • Sorteio aleatório do par de torcedores que vão debater (12 combinações possíveis); os outros dois clubes ficam visíveis na UI como "🪑 fora da rodada".
  • Pesquisa real na web no Pesquisador: usa openai/gpt-oss-20b:free:online no OpenRouter — o sufixo :online aciona o plugin de Web Search e o agente retorna respostas com URLs reais citadas.
  • Tag [PESQUISA]…[/PESQUISA]: quando um torcedor não tem certeza de um número, ele inclui essa tag e a UI dispara um A2A para o Pesquisador antes do próximo turno. O resultado vira um card destacado no chat.
  • Julgador especialista em retórica, psicologia cognitiva, análise de debate e neuro-persuasão. Avalia os argumentos por 5 critérios (logos/ethos/pathos/neuro/resposta) e devolve veredito JSON ao Supervisor.
  • Supervisor como mestre de cerimônia: sorteia, abre o debate, monitora tempo e anuncia o veredito que recebe do Julgador. Não julga argumentos por conta própria.
  • Streamlit com design system próprio (ui/theme.py + ui/components.py): paleta por clube, cards de agente, bolhas de chat coloridas por time, banner "X VS Y" após sorteio, painel "Bastidores A2A" com o log JSON-RPC.
  • Export JSON da transcrição completa do debate.

🧱 Stack

Camada Tecnologia
Agentes google-adk ≥ 1.8 (LlmAgent, Runner, FunctionTool, LiteLlm)
Protocolo A2A a2a-sdk 1.x — AgentExecutor, DefaultRequestHandler, create_jsonrpc_routes, A2ACardResolver, Client
LLM provider OpenRouter via litellm
Modelo torcedores + supervisor + julgador google/gemini-3.1-flash-lite
Modelo pesquisador openai/gpt-oss-20b:free:online (web search habilitado)
HTTP server uvicorn (ASGI) + Starlette
UI Streamlit
Gerenciador deps uv

🚀 Como rodar em máquina local

1. Pré-requisitos

  • Python 3.12+
  • uv instalado (brew install uv ou curl -LsSf https://astral.sh/uv/install.sh | sh)
  • Conta no OpenRouter e uma API key (sk-or-v1-…)

2. Clone e instale

git clone https://github.com/seu-usuario/FlaFludeAgentes.git
cd FlaFludeAgentes
uv sync

3. Configure variáveis de ambiente

cp .env.example .env
# edite .env e cole sua OPENROUTER_API_KEY

Conteúdo mínimo do .env:

OPENROUTER_API_KEY=sk-or-v1-...
FAN_MODEL=google/gemini-3.1-flash-lite
RESEARCHER_MODEL=openai/gpt-oss-20b:free:online
OR_APP_NAME=FlaFludeAgentes
OR_SITE_URL=http://localhost:8501

4. Suba os 7 servidores A2A (Terminal 1)

uv run python start_a2a_servers.py

Saída esperada:

🤖 FlaFludeAgentes — 7 servidores A2A (Google ADK + a2a-sdk)
⚖️ Subindo Supervisor (porta 8002)…
🔴⚫ Subindo Flamengo (porta 8003)…
🟢🔴 Subindo Fluminense (porta 8004)…
🔎 Subindo Pesquisador (porta 8005)…
⚫⚪ Subindo Corinthians (porta 8006)…
🟢⚪ Subindo Palmeiras (porta 8007)…
🧠 Subindo Julgador (porta 8008)…

🔍 Health check via /.well-known/agent-card.json
  ⚖️ Supervisor    :8002  🟢 OK
  🔴⚫ Flamengo     :8003  🟢 OK
  🟢🔴 Fluminense   :8004  🟢 OK
  🔎 Pesquisador   :8005  🟢 OK
  ⚫⚪ Corinthians   :8006  🟢 OK
  🟢⚪ Palmeiras     :8007  🟢 OK
  🧠 Julgador      :8008  🟢 OK

5. Suba o Streamlit (Terminal 2)

uv run streamlit run app.py

Abra http://localhost:8501.

6. Use a app

  1. Defina a duração do debate (2–15 minutos) na barra lateral.
  2. Clique Atualizar status A2A para conferir que os 7 cards estão verdes.
  3. Clique 🎬 Iniciar debate — o Supervisor sorteia dois clubes (banner VS aparece no centro).
  4. Clique ➡️ Turno do para gerar o próximo argumento. Se o torcedor incluir [PESQUISA]…[/PESQUISA], a UI consulta o Pesquisador automaticamente e mostra o card com fontes (URLs) antes de avançar.
  5. Quando o timer zerar (ou ao clicar ⏹ Encerrar e analisar agora), o Julgador analisa o debate por logos/ethos/pathos/neuro/resposta, devolve o veredito ao Supervisor, e este faz o anúncio público com pontuação por critério. O botão para exportar a transcrição em JSON aparece em seguida.

🧪 Testes & smoke

# unit tests (LiteLlm wrapper, sorteio, parsing de fontes, fan specs)
uv run pytest -q

# smoke A2A end-to-end (requer servidores no ar e OpenRouter válido)
uv run python scripts/smoke_a2a.py

Para validar manualmente um agent card individual:

curl http://localhost:8002/.well-known/agent-card.json | jq

📁 Estrutura

FlaFludeAgentes/
├── a2a_runtime.py            # LiteLlm helper + ADKAgentExecutor + builder Starlette
├── a2a_client.py             # A2AClientRegistry + A2ASyncRegistry (consumido pelo Streamlit)
├── fan_agent.py              # FanSpec + build_fan_app(...) compartilhado pelos 4 torcedores
├── supervisor_agent/agent.py # Mestre de cerimônia (sorteia, abre, anuncia veredito)
├── researcher_agent/agent.py # Web search via plugin :online do OpenRouter
├── judge_agent/agent.py      # Julgador: retórica, psicologia, neuro-persuasão
├── flamengo_agent/agent.py
├── fluminense_agent/agent.py
├── corinthians_agent/agent.py
├── palmeiras_agent/agent.py
├── ui/
│   ├── theme.py              # Design tokens + inject_css()
│   └── components.py         # debate_header, agent_card, chat_bubble, research_card, …
├── app.py                    # Streamlit (não instancia agentes localmente)
├── start_a2a_servers.py      # Spawna os 7 uvicorns em processos paralelos
├── scripts/smoke_a2a.py      # Descobre os 7 e dispara 1 debate
├── tests/test_runtime.py     # Pytest cobrindo a fiação
├── utils/                    # Logging estruturado (mantido)
├── pyproject.toml
├── .env.example
├── CLAUDE.md                 # Instruções específicas para Claude Code
└── README.md                 # (este arquivo)

🤖 Os 7 agentes

Agente Porta Modelo Tools principais
Supervisor 8002 google/gemini-3.1-flash-lite pick_starting_pair, start_debate, announce_winner, get_time_status
Flamengo 8003 google/gemini-3.1-flash-lite initial_argument, counter_argument, request_research
Fluminense 8004 google/gemini-3.1-flash-lite idem
Pesquisador 8005 openai/gpt-oss-20b:free:online (sem tool — usa Web Search direto)
Corinthians 8006 google/gemini-3.1-flash-lite idem torcedores
Palmeiras 8007 google/gemini-3.1-flash-lite idem torcedores
Julgador 8008 google/gemini-3.1-flash-lite judge_debate (logos/ethos/pathos/neuro/resp)

Cada agente expõe:

  • GET /.well-known/agent-card.json → metadados (nome, descrição, skills, capabilities, URL).
  • POST / → JSON-RPC do protocolo A2A (message/send, message/stream, etc.).

Rodar um agente isolado

uv run python -m supervisor_agent.agent     # 8002 — mestre de cerimônia
uv run python -m flamengo_agent.agent       # 8003
uv run python -m fluminense_agent.agent     # 8004
uv run python -m researcher_agent.agent     # 8005
uv run python -m corinthians_agent.agent    # 8006
uv run python -m palmeiras_agent.agent      # 8007
uv run python -m judge_agent.agent          # 8008 — julgador técnico

🔄 Fluxo de uma rodada

  1. UI → Supervisor (A2A): "Inicie um debate de N minutos chamando _start_debate_tool."
  2. Supervisor roda a tool, sorteia 2 clubes entre os 4, devolve JSON com starting_team, opponent_team, benched, etc.
  3. UI desenha o team_picker_panel (banner VS) e ativa o card do torcedor sorteado.
  4. UI → Torcedor sorteado (A2A): "Argumento inicial contra , 200–350 palavras, use [PESQUISA] para dado incerto."
  5. Se a resposta tem [PESQUISA]q[/PESQUISA]:
    • UI → Pesquisador (A2A): consulta q.
    • Pesquisador chama o LLM :online → OpenRouter busca na web → resposta com URLs.
    • UI renderiza research_card com a query e as fontes.
  6. UI → Oponente (A2A): "Contra-argumente o último argumento."
  7. Turnos alternam até o cronômetro zerar (ou usuário encerrar).
  8. UI → Julgador (A2A): judge_debate(history) → veredito técnico pontuando cada torcedor por logos/ethos/pathos/neuro/resposta e declarando o vencedor.
  9. UI → Supervisor (A2A): announce_winner(verdict_json) → o Supervisor recebe o veredito e formata o anúncio público de encerramento.

O Supervisor não julga argumentos por conta própria — ele apenas modera o fluxo e anuncia o veredito que o Julgador entrega.

Todo o tráfego A2A é registrado em A2AClientRegistry.message_log() e exibido no expander 🎛️ Bastidores A2A da UI.


🔑 Variáveis de ambiente

Variável Obrigatória Default Função
OPENROUTER_API_KEY Autenticação no OpenRouter
FAN_MODEL google/gemini-3.1-flash-lite Modelo dos torcedores, supervisor e julgador
RESEARCHER_MODEL openai/gpt-oss-20b:free:online Modelo do pesquisador (sufixo :online ativa Web Search)
OR_APP_NAME Aparece no leaderboard do OpenRouter
OR_SITE_URL Referer enviado ao OpenRouter
SUPERVISOR_PORT, RESEARCHER_PORT, FLAMENGO_PORT, JUDGE_PORT, … 8002–8008 Sobrescrever portas individuais

🛠️ Solução de problemas

"OPENROUTER_API_KEY não encontrado" — confira que .env existe na raiz e que está no formato KEY=valor sem aspas.

address already in use ao subir o launcher — uma instância anterior ficou de pé. Limpe com:

lsof -ti :8002,8003,8004,8005,8006,8007,8008 | xargs kill -9

Pesquisador retorna respostas sem fontes — o plugin :online pode estar desativado no provedor; confirme o slug em https://openrouter.ai/models e que RESEARCHER_MODEL termina com :online.

Streamlit não acha agentes (todos vermelhos) — clique Atualizar status A2A na sidebar. Se continuar, valide manualmente com curl http://localhost:8002/.well-known/agent-card.json.

InvalidAgentResponseError: Agent should enqueue Task before … — versão incompatível do a2a-sdk. O projeto foi testado com a2a-sdk==1.0.2; rode uv sync para garantir.


⚖️ Notas de segurança

  • Nunca comite .env. O .gitignore já cobre.
  • Se você expor uma OPENROUTER_API_KEY por engano (chat, screenshot, log), rotacione-a no painel do OpenRouter — chaves vazadas devem ser consideradas comprometidas.
  • O Pesquisador faz fetch real à internet via OpenRouter; cada turno com [PESQUISA] consome créditos do plugin de Web Search.

📜 Licença

MIT — veja LICENSE.


⚽ FlaFludeAgentes — Fla, Flu, Timão e Verdão debatem; Claude (via OpenRouter) faz o agenciamento.

About

Demo para o uso do protocolo A2A por meio de 4 agentes criados com Google ADK: Supervisor, Torcedor do Flu e do Fla e um Pesquisador, onde o Supervisor recebe uma ordem do Usuário com tempo determinado, e ordena aos Agentes Torcedores que iniciem o Debate, que poderão usar o Agente Pesquisador para aprimorar seu argumento

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages