AG-UI Weather Dashboard

April 4, 2026 · View on GitHub

An AI-powered weather dashboard that combines a Google ADK agent backend with a CopilotKit + Next.js frontend, connected via the AG-UI protocol. Ask about weather in any city and get rich, interactive card-based responses rendered inline in the chat sidebar and on a persistent dashboard.

Architecture

graph TB
    subgraph Frontend ["Frontend (Next.js + CopilotKit)"]
        UI[CopilotSidebar Chat UI]
        FT[useFrontendTool Hooks]
        Cards[Weather Card Components]
        API[Open-Meteo API Client]
        Dashboard[Dashboard Grid]
    end

    subgraph Backend ["Backend (Python + Google ADK)"]
        Agent[LlmAgent - GPT-4o-mini]
        AGUI[AGUIToolset Placeholder]
        ADAPTER[ag_ui_adk Adapter]
        FASTAPI[FastAPI Server]
    end

    subgraph External ["External APIs"]
        METEO[Open-Meteo API]
    end

    UI -->|User message| FT
    FT -->|Registers tools| UI
    UI -->|AG-UI Protocol| FASTAPI
    FASTAPI --> ADAPTER
    ADAPTER -->|ClientProxyTool| Agent
    Agent -->|Tool call event| ADAPTER
    ADAPTER -->|SSE stream| UI
    UI -->|Intercepts tool call| FT
    FT -->|Fetches data| API
    API -->|HTTP| METEO
    FT -->|Renders| Cards
    FT -->|Updates state| Dashboard
    Cards -->|Displayed in| UI
    Cards -->|Displayed in| Dashboard

Request Flow

sequenceDiagram
    participant User
    participant CopilotKit as CopilotKit (Frontend)
    participant AGUI as AG-UI Adapter
    participant ADK as ADK Agent (LLM)
    participant OpenMeteo as Open-Meteo API

    User->>CopilotKit: "What's the weather in Tokyo?"
    CopilotKit->>AGUI: RunAgentInput (message + frontend tools)
    AGUI->>AGUI: Replace AGUIToolset with ClientProxyTools
    AGUI->>ADK: Forward message + tools to LLM
    ADK->>AGUI: Tool call: get_current_weather({city: "Tokyo"})
    AGUI->>CopilotKit: TOOL_CALL_START + TOOL_CALL_ARGS + TOOL_CALL_END
    CopilotKit->>CopilotKit: Render loading card
    CopilotKit->>OpenMeteo: Fetch weather data (frontend handler)
    OpenMeteo-->>CopilotKit: Weather JSON
    CopilotKit->>CopilotKit: Render weather card + update dashboard
    CopilotKit->>AGUI: Tool result (JSON)
    AGUI->>ADK: Forward tool result
    ADK->>AGUI: Brief text response
    AGUI->>CopilotKit: TEXT_MESSAGE events
    CopilotKit->>User: Card + "It's sunny in Tokyo!"

Project Structure

agui-weather-dashboard/
├── agent/                          # Python backend
│   ├── weather_dashboard/
│   │   ├── __main__.py             # FastAPI + AG-UI server entry point
│   │   ├── agent.py                # ADK LlmAgent with AGUIToolset
│   │   ├── agent_executor.py       # Agent runner and session management
│   │   ├── prompt_builder.py       # System prompt (no data repetition)
│   │   ├── tools.py                # Backend tool definitions (reference)
│   │   └── weather_client.py       # Python Open-Meteo client (httpx)
│   └── pyproject.toml              # Python dependencies
├── frontend/                       # Next.js frontend
│   ├── src/
│   │   ├── app/
│   │   │   ├── page.tsx            # Main page: WeatherTools + Dashboard
│   │   │   ├── layout.tsx          # Root layout
│   │   │   └── api/copilotkit/
│   │   │       └── route.ts        # CopilotKit runtime + HttpAgent
│   │   ├── components/
│   │   │   └── weather-cards.tsx    # CurrentWeather, Forecast, Historical cards
│   │   └── lib/
│   │       ├── weather-api.ts      # Frontend Open-Meteo client (fetch)
│   │       └── theme.ts            # Theme configuration
│   └── package.json                # Node dependencies
├── tests/                          # Python tests (pytest)
│   ├── test_weather_client.py
│   ├── test_tools.py
│   └── test_prompt_builder.py
├── package.json                    # Workspace root
└── pnpm-workspace.yaml             # pnpm monorepo config

Tech Stack

LayerTechnologyPurpose
LLMGPT-4o-mini (via LiteLLM)Agent reasoning and tool selection
Agent FrameworkGoogle ADKAgent lifecycle, session management
Agent-UI ProtocolAG-UI + ag_ui_adkStandardized event streaming between agent and frontend
Frontend FrameworkNext.js 16 (Turbopack)React SSR, API routes
Chat UICopilotKit 1.54.1Sidebar chat, tool call rendering, frontend tool execution
StylingTailwind CSS 4Utility-first CSS for weather cards
Weather DataOpen-Meteo APIFree, no-auth geocoding + weather + forecast + historical
Backend ServerFastAPI + UvicornAsync Python HTTP server for AG-UI endpoint
Package Managementpnpm (JS) + uv (Python)Dependency management

Prerequisites

  • Python 3.13+ with uv
  • Node.js 20+ with pnpm
  • OpenAI API key

Setup

  1. Clone and install dependencies:

    git clone <repo-url>
    cd agui-weather-dashboard
    pnpm install
    cd agent && uv sync && cd ..
    
  2. Configure environment:

    # agent/.env
    OPENAI_API_KEY=sk-your-key-here
    LITELLM_MODEL=openai/gpt-4o-mini
    AGENT_PORT=10002
    
  3. Start both servers:

    pnpm dev
    

    This runs concurrently:

    • Agent: http://localhost:10002 (AG-UI protocol endpoint)
    • Frontend: http://localhost:3000 (Next.js app)
  4. Open http://localhost:3000 and start chatting.

How It Works

Frontend Tools (useFrontendTool)

The key pattern that makes card rendering work is useFrontendTool from CopilotKit. Each weather tool is registered on the frontend with:

  • handler - Executes when the agent calls the tool. Fetches data from Open-Meteo directly in the browser.
  • render - Returns a React component displayed inline in the chat. Shows a loading state while fetching, then the full weather card.
stateDiagram-v2
    [*] --> Registered: useFrontendTool()
    Registered --> InProgress: Agent calls tool
    InProgress --> Executing: Handler starts
    Executing --> Complete: Data fetched
    Complete --> CardRendered: render() called
    CardRendered --> DashboardUpdated: onResult callback
    DashboardUpdated --> [*]

    InProgress --> InProgress: Loading card shown

AGUIToolset Placeholder

The ADK agent is created with tools=[AGUIToolset()]. This empty placeholder is critical -- at runtime, ag_ui_adk replaces it with ClientProxyToolset, which wraps each frontend tool as an ADK-compatible ClientProxyTool. Without this placeholder, the agent never sees the frontend tools.

Dashboard State

When a tool handler completes, it calls onResult() which adds the weather data to the dashboard grid. The dashboard:

  • Accumulates cards from multiple queries
  • Updates in place if you ask about the same city + type again
  • Displays in a responsive 1-2 column grid

Weather Cards

Three card types with distinct visual styles:

CardGradientData
Current WeatherBlueTemperature, feels like, humidity, wind, pressure, sunrise/sunset
ForecastIndigo-PurpleDaily high/low, conditions, precipitation probability (1-7 days)
HistoricalEmerald-TealPast daily data table + summary (avg high, total rain, trend)

API Endpoints

Agent (AG-UI Protocol)

  • POST http://localhost:10002/ - AG-UI run endpoint (SSE stream)

Frontend (Next.js)

  • POST /api/copilotkit - CopilotKit runtime proxy to AG-UI agent

External (Open-Meteo, no auth required)

  • GET https://geocoding-api.open-meteo.com/v1/search - City geocoding
  • GET https://api.open-meteo.com/v1/forecast - Current weather + forecast
  • GET https://archive-api.open-meteo.com/v1/archive - Historical weather

Testing

cd agent && uv run pytest ../tests/ -v

Tests cover:

  • Weather client API calls (mocked with respx)
  • Tool functions
  • Prompt builder output

Example Queries

  • "What's the weather in Tokyo?"
  • "Show me a 5-day forecast for London"
  • "Compare weather in New York, Paris, and Sydney"
  • "What was the weather like in Berlin last week?"

License

MIT