POC de estudo explorando o uso combinado de A2UI (design system Angular Material) e AG-UI Protocol para construção de uma interface Angular verdadeiramente agêntica, onde componentes de UI são renderizados dinamicamente a partir de um catálogo JSON dirigido por um LLM via streaming.
O fluxo central é: usuário interage via chat → LLM escolhe tools (WeatherAPI, CRUD, etc.) → backend emite eventos AG-UI → frontend renderiza componentes A2UI reativamente via Angular Signals.
| Camada | Tecnologia |
|---|---|
| Frontend | Angular 21 (standalone + Signals) + Angular Material |
| Backend | Python 3.11 / FastAPI |
| Protocolo agêntico | AG-UI (client + server) |
| LLM | Configurável via .env (OpenAI / Anthropic) |
| API externa | OpenWeatherMap (via tool call) |
| MCP | Tools expostas via MCP server no backend |
Por que Angular 21? O projeto começou na v17, mas os SDKs oficiais necessários para as próximas partes do tutorial exigem versões mais novas:
@copilotkit/angularexige Angular^20 || ^21 || ^22, e@a2ui/angular(SDK do protocolo A2UI da Google) exige^21.2.5— nenhuma versão publicada de nenhum dos dois suporta Angular 17. A migração foi feita de forma sequencial (17 → 18 → 19 → 20 → 21, viang updatea cada major, já que os schematics de migração automática só se aplicam passo a passo) na issue #59, validando build e testes a cada etapa. Angular 21 foi o alvo escolhido por ser a versão mínima que satisfaz os peer ranges dos dois SDKs simultaneamente, sem precisar ir até a 22.
a2ui/
├── apps/
│ ├── frontend/ # Angular 21 + Angular Material (Design System)
│ └── backend/ # Python + FastAPI (estrutura base)
├── package.json # workspace raiz + scripts de conveniência
├── .editorconfig
└── .gitignore
- Node.js 18+ e npm
- Python 3.11+
./dev.shSobe os dois serviços em paralelo e encerra ambos com Ctrl+C.
Pré-requisitos: venv criado em apps/backend/.venv e .env preenchido (veja abaixo).
| Serviço | URL |
|---|---|
| Frontend | http://localhost:4200 |
| Backend (Swagger) | http://localhost:8000/docs |
| MCP Server | http://localhost:8000/mcp |
npm install # instala deps do workspace frontend
npm run fe:start # ng serve -> http://localhost:4200
npm run fe:build # build de produção
npm run fe:test # testes unitários (Karma/Jasmine)cd apps/backend
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements-dev.txt
cp .env.example .env
uvicorn app.main:app --reload --port 8000 # http://localhost:8000/docsOu pela raiz:
npm run be:start
npm run be:testA mesma app FastAPI expõe as tools do backend via MCP (Streamable HTTP) em
http://127.0.0.1:8000/mcp. Para apontar o Cursor para ele, em .cursor/mcp.json:
{
"mcpServers": {
"a2ui-backend": {
"url": "http://127.0.0.1:8000/mcp"
}
}
}Configuração do Claude Desktop, teste rápido com um cliente Python e detalhes de
implementação estão em docs/mcp.md.
Documentação completa do backend (endpoints, variáveis de ambiente, banco de dados, estrutura):
apps/backend/README.md
Cada issue tem uma branch e uma worktree dedicada, criadas via /doljak-create-issue.
Convenções:
| Item | Formato | Exemplo |
|---|---|---|
| Branch | <prefixo>/<tema>-<numero>-<titulo> |
chore/llm-config-1-setup-provider |
| Worktree | wts/<numero>-worktree-<tema> |
wts/1-worktree-llm-config |
| Doc de spec | docs/issues-plans/issue-<numero>-<tema>.md |
docs/issues-plans/issue-1-llm-config.md |
Prefixos: feat/ · chore/ · fix/ · refactor/ · docs/
As worktrees ficam em wts/ dentro do repo (ignorado pelo .gitignore). Para acessar uma worktree ativa:
# listar worktrees ativas
git worktree list
# entrar em uma worktree
cd wts/1-worktree-llm-configTodo merge em main passa por PR com ao menos 1 aprovação — push direto está bloqueado.
Cada item será rastreado como uma issue no repositório. O objetivo é cobrir todas as camadas da stack de ponta a ponta.
- Configurar provedor LLM (modelo, API key, parâmetros de tool use e streaming) via
.envepydantic-settings(#1) - Implementar invocação de tools pelo LLM (tool calling / function calling) (#2)
- Tratar streaming de eventos LLM no backend (#3)
- Registrar e configurar chave da WeatherAPI.com (#4, #14)
- Criar tool
get_weather(city)no backend consumindo a API (#5)
- Estruturar camada de tools chamáveis pelo LLM (roteamento, schemas, execução) (#6)
- Expor tools via MCP Server (Model Context Protocol) no FastAPI (#7)
- Implementar BE CRUD (entidade de exemplo end-to-end: model → schema → service → route) (#8)
-
ChatService— consumirPOST /api/chatvia SSE com Fetch streaming (#24) -
ChatComponent— layout, estado com Signals e renderização de tokens em tempo real (#25) - Rota
/chate link de navegação na toolbar (#26)
- Configurar AG-UI Server no backend (emissão de eventos de UI via streaming)
- Configurar AG-UI Client no frontend (consumo do stream e despacho de eventos para Signals)
Tutorial A2UI Parte 1 (docs/tutorial_A2UI/01-ag-ui-sdk-typescript.md, baseado em AG-UI in Practice: The SDK for TypeScript) — concluída:
-
[Back]Esqueleto de agente (AbstractAgent) emitindoRUN_STARTED/TEXT_MESSAGE_*/RUN_FINISHED(#32) — como funciona (diagrama) -
[Front]Consumir eventos do agente viaHttpAgent+AgentSubscriber(#34) — como funciona (diagrama)
A estudar — Tutorial A2UI Parte 2 (docs/tutorial_A2UI/02-ag-ui-copilotkit-angular.md, baseado em Agentic UI with Angular, CopilotKit, and AG-UI):
-
[Back]Endpoint AG-UI comPOSTreal, resolvendo o ciclo de tool call client-side (#45) -
[Front]Instalar e configurar o CopilotKit (provideCopilotKit) (#46) -
[Front]Agent store:AppHttpAgent+initAgentStore+injectAgentStore(#47)
- Definir o contrato do catálogo JSON (schema que mapeia nomes de componentes para props A2UI)
- Implementar o catálogo de componentes A2UI (registro de componentes renderizáveis por nome)
- Construir o renderer A2UI (lê eventos AG-UI via Signal e renderiza componentes do catálogo dinamicamente)
Tutorial A2UI Parte 1 (docs/tutorial_A2UI/01-ag-ui-sdk-typescript.md) — concluída:
-
[Back]Ligar a toolget_weatherexistente como server-side tool call do AG-UI (#33) — como funciona (diagrama) -
[Front]Definir schema client-side (Tool+ zod) de clima para renderização no chat (#35) -
[Front]Ciclo de duas runs para resultado de tool call client-side (#36)
A estudar — Tutorial A2UI Parte 2 (docs/tutorial_A2UI/02-ag-ui-copilotkit-angular.md):
-
[Front]Tool de clima viacreateFrontendTool, sem o ciclo manual de duas runs (#48) -
[Front]Widget de clima renderizado viacopilot-render-tool-calls(#49) -
[Front]UI de chat sidecar ligada ao agent store do CopilotKit (#50)
A estudar — Tutorial A2UI Parte 3 (docs/tutorial_A2UI/03-google-a2ui-dynamic-ui.md, protocolo A2UI da Google — nome coincide com o do projeto, mas são coisas diferentes; issues marcadas -GOOGLE-A2UI-):
-
[Front]Instalar e configurar o SDK A2UI (@a2ui/angular,@a2ui/web_core) (#52) -
[Front]Renderizar card estático viacreateSurface/updateComponents/updateDataModel(#53) -
[Front]Modelar o card de clima com oWeatherToolResultexistente (#54) -
[Front]Ação do cliente pra atualizar o card no lugar (onAction) (#55)
Tutorial A2UI Parte 4 (docs/tutorial_A2UI/04-integrating-a2ui-with-ag-ui.md, baseado em Integrating A2UI with AG-UI and CopilotKit in Angular) — concluída:
-
[Back]Emitir operações A2UI dentro de umACTIVITY_SNAPSHOTdo agente de clima (#72) -
[Front]A2uiActivityRenderervia a interfaceActivityRendererdo CopilotKit (#73) -
[Front]Renderizar o card de clima dentro do chat real via o activity renderer (#74)
Tutorial A2UI Parte 5 (docs/tutorial_A2UI/05-custom-catalogs-in-a2ui.md, baseado em Custom Catalogs in A2UI) — concluída:
-
[Front]Componente customizado de clima (HumidityGauge) com schema Zod +binding()(#75) -
[Front]Registrar catálogo customizado viaBasicCatalogBase+A2UI_RENDERER_CONFIG(#76) -
[Front]Usar o widget customizado no card de clima (#77)
Tutorial A2UI Parte 6 (docs/tutorial_A2UI/06-a2ui-dashboard-performance.md, baseado em How I Made My A2UI Dashboard 300 Times Faster) — concluída:
-
[Back]DSL compacta pra um mini-dashboard de clima, no lugar de markup A2UI completo (#78) -
[Back]Conversão determinística DSL → A2UI no backend (#79) -
[Back]Cache da estrutura gerada por hash da requisição (#80)
Tutorial A2UI Parte 7 (docs/tutorial_A2UI/07-mcp-apps-fundamentals.md, baseado em Agentic UI with MCP Apps, protocolo MCP Apps — issues marcadas -MCP-APPS-) — concluída:
-
[Back]Investigar suporte a MCP Apps no SDK Pythonmcpe registrar o recurso de app da tool de clima (#81) -
[Front]Host mínimo: iframe +AppBridgesobrepostMessage(#82) -
[Front]App mínimo: renderizar o widget a partir do input/resultado da tool (#83)
Tutorial A2UI Parte 8 (docs/tutorial_A2UI/08-mcp-apps-angular-copilotkit.md, baseado em MCP Apps in Angular with CopilotKit) — concluída:
-
[Back]EmitirACTIVITY_SNAPSHOT(mcp-apps) com o resultado da tool de clima (#84) -
[Back]Middleware de proxy no backend pras requisições de recurso/tool do widget (#85) -
[Front]provideMCPApps()emapp.config.ts(#86) -
[Front]Renderizar a atividade de MCP Apps no chat real (#87)
As 8 partes do tutorial A2UI (docs/tutorial_A2UI/) estão concluídas — AG-UI, A2UI (protocolo Google), catálogo customizado, DSL de dashboard com cache e MCP Apps já estão todos integrados no chat real.
- Backend: camada de tools (ToolRegistry), tool calling + streaming com LLM, tool
get_weather(WeatherAPI.com), MCP Server em/mcp, CRUD deConversationcom SQLAlchemy + Alembic, agente AG-UI emitindoACTIVITY_SNAPSHOT(A2UI e MCP Apps) para o card de clima, DSL compacta → A2UI com cache por hash, middleware de proxy MCP Apps. ✅ - Frontend: app shell com toolbar Material, tema
azure-blue; rota/chatunificada em torno do<copilot-chat>do@copilotkit/angular(chat antigo baseado emChatService/SSE removido — PR #94), comA2uiActivityRenderer, catálogo A2UI customizado (HumidityGauge) e widget MCP Apps todos operando lado a lado no mesmo chat. ✅ - Em andamento (working tree, ainda sem issue/PR): ajustes no agente e no card de clima A2UI — novo módulo
weather_intent.pyno backend e componentetemperature-herono frontend, além de refino visual doHumidityGaugee doA2uiActivityRenderer. Ainda não commitado.