Skip to content
xooo123Public

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

NewsPilot

A voice-first autonomous news agent. You ask for the news you care about; NewsPilot researches the live web, evaluates and ranks the results, synthesizes a concise source-backed briefing, and reads it aloud then researches again to answer follow-up questions.

Built for the All Things Agentic Hackathon 2026 (Taskmaster track).

License: MIT Python 3.10+ Google ADK Deployed on Cloud Run

Live demo: https://newspilot-284521543847.us-central1.run.app


Overview

Staying informed usually means scrolling several feeds, opening many tabs, and mentally de-duplicating the same story reported by different outlets — or reading a generic AI summary that hides its sources and can't answer a follow-up.

NewsPilot is different in two ways. First, it's a genuine agent: it decides what to research, gathers real sources, filters and ranks them, and follows up with more research when a question needs it — rather than answering from a model's training data. Second, it's voice-first: it greets you, listens, and reads the briefing aloud in a natural voice.

It is not user → LLM → response. A single orchestrating agent plans a multi-step task and calls specialized tools to complete it.

Demo

[ADD DEMO VIDEO]

[ADD SCREENSHOT]

You can try the deployed app at the live URL above. (Prototype: expect a cold start on the first request, and see Limitations.)

How It Works

flowchart TD
    A[User request - voice or text] --> B[Orchestrator interprets intent<br/>and reads saved preferences]
    B --> C{Request scope}
    C -->|too ambiguous| Q[Ask one clarifying question]
    C -->|specific or broad| D[Search sub-agent:<br/>google_search grounding]
    D --> E[deduplicate_stories]
    E --> F[rank_stories]
    F --> G[Synthesize briefing<br/>with source links]
    G --> H[Read aloud - Cloud TTS]
    H --> I{Follow-up question?}
    I -->|needs more detail| D
    I -->|answered| J[Done]
Loading

The orchestrator decides the scope (a specific topic, a broad sweep, or a clarifying question), gathers stories, then runs them through deterministic de-duplication and ranking before writing the spoken briefing. Follow-up questions re-enter the same loop and trigger fresh research when needed.

Agent Architecture

flowchart LR
    subgraph Browser
      UI["Voice UI<br/>Web Speech STT · audio-reactive orb"]
    end
    subgraph GCP["Google Cloud"]
      subgraph CR["Cloud Run — FastAPI (server.py)"]
        ORCH["Orchestrator agent<br/>Google ADK · Gemini"]
        SUB["Search sub-agent<br/>google_search"]
        DD["deduplicate_stories"]
        RK["rank_stories"]
        PREF["get / save_user_preferences"]
      end
      VTX["Vertex AI · Gemini"]
      FS["Firestore · preferences"]
      TTS["Cloud Text-to-Speech · Chirp 3 HD"]
    end
    UI -->|POST /api/chat| ORCH
    ORCH --> SUB --> VTX
    ORCH --> DD
    ORCH --> RK
    ORCH --> PREF --> FS
    ORCH --> VTX
    UI -->|POST /api/tts| TTS
Loading
Component Implementation
Main agent A single ADK LlmAgent orchestrator that plans, synthesizes, and handles follow-ups
Tools news_search_agent (as an AgentTool), deduplicate_stories, rank_stories, get_user_preferences, save_user_preferences
Search A dedicated sub-agent holding only the built-in google_search tool
Model Gemini via Vertex AI
Memory / state Firestore for long-term preferences; ADK in-memory sessions for conversation context
Backend FastAPI (server.py) exposing /api/chat and /api/tts
Frontend Vanilla HTML/CSS/JS voice UI (no build step)
Cloud Cloud Run (hosting), Vertex AI, Firestore, Cloud Text-to-Speech

Why the search sub-agent is separate: ADK/Gemini does not allow the built-in google_search tool to coexist with custom function tools in one agent. The supported workaround is the Agent-as-Tool pattern google_search lives alone in a sub-agent that the orchestrator calls as a tool. Sources are returned as structured JSON so they survive the tool boundary.

Key Features

  • Voice-first interaction: browser speech-to-text in, natural Chirp 3 HD voice out
  • Live web research via Google Search grounding
  • Duplicate/overlap detection across outlets (deterministic)
  • Story ranking by recency, source reputation, and breadth of coverage (deterministic)
  • Source-aware briefings every briefing keeps real source links
  • Follow-up research using conversation context
  • Personalized preferences (topics, avoid-list, length, style) persisted across sessions
  • Graceful failure handling (e.g. preference store falls back to local JSON if Firestore is unreachable)

Technology Stack

Component Technology Purpose
Agent framework Google ADK (Python, 2.x) Orchestrator + tool calling
LLM Gemini via Vertex AI Planning, synthesis, tool selection
Web research Google Search grounding (ADK built-in tool) Current, real sources
Voice output Google Cloud Text-to-Speech (Chirp 3 HD) Natural spoken briefings
Voice input Browser Web Speech API Speech-to-text
Database Firestore Long-term user preferences
Backend FastAPI + Uvicorn /api/chat, /api/tts, static UI
Frontend HTML / CSS / JavaScript Voice UI (no build step)
Cloud / hosting Cloud Run (via Cloud Build) Deployment

Project Structure

newspilot/
├── server.py                 # FastAPI: /api/chat (agent) + /api/tts (voice) + serves the UI
├── main.py                   # Optional ADK dev-UI entry point (adk web / get_fast_api_app)
├── Dockerfile                # Cloud Run container image
├── .gcloudignore             # Keeps .venv/.env out of the Cloud Build upload
├── .env.example              # Template for newspilot/.env (no secrets)
├── requirements.txt
├── start_newspilot.bat       # Windows one-click local launcher
├── static/                   # Voice UI
│   ├── index.html
│   ├── css/style.css
│   └── js/app.js             # STT, cloud-TTS playback, audio-reactive orb
├── docs/                     # architecture.svg, demo script, Devpost writeup
└── newspilot/                # The agent package
    ├── agent.py              # root_agent (orchestrator) + tool wiring
    ├── prompts.py            # All agent instructions
    ├── config.py             # Model + auth configuration (from env)
    ├── memory.py             # Firestore preference store (+ JSON fallback)
    ├── sub_agents/
    │   └── search_agent.py   # google_search specialist
    └── tools/
        ├── dedup.py          # deduplicate_stories
        ├── rank.py           # rank_stories
        └── preferences.py    # get/save_user_preferences

Getting Started

Prerequisites

  • Python 3.10+
  • A Google Cloud project with billing enabled
  • The gcloud CLI
  • A modern Chromium-based browser (Chrome/Edge) for voice input

Installation

python -m venv .venv
source .venv/bin/activate            # Windows: .venv\Scripts\activate
pip install -r requirements.txt

Authenticate and enable services

NewsPilot authenticates to Google Cloud with Application Default Credentials (no hardcoded keys).

gcloud auth application-default login
gcloud config set project YOUR_PROJECT_ID
gcloud services enable aiplatform.googleapis.com firestore.googleapis.com texttospeech.googleapis.com
gcloud firestore databases create --location=nam5       # one-time

Environment variables

Copy the template and edit it:

cp .env.example newspilot/.env
Variable Description Required
GOOGLE_GENAI_USE_VERTEXAI TRUE to route Gemini through Vertex AI Yes
GOOGLE_CLOUD_PROJECT Your GCP project ID Yes (Vertex)
GOOGLE_CLOUD_LOCATION Gemini location; use global for the newest models Yes (Vertex)
NEWSPILOT_MODEL / NEWSPILOT_SEARCH_MODEL Gemini model IDs No (has a default)
NEWSPILOT_TTS_VOICE Chirp 3 HD voice name No (defaults to en-US-Chirp3-HD-Aoede)
GOOGLE_API_KEY AI Studio key — only if GOOGLE_GENAI_USE_VERTEXAI=FALSE Conditional
HTTPS_PROXY / HTTP_PROXY Local-only proxy (e.g. to reach Google behind a VPN). Never set in the cloud. No

Model note: the code default is gemini-3.7-flash. The live deployment runs gemini-3.6-flash on the global endpoint, because newer Gemini models are exposed there and may return 404 on regional endpoints for new projects. Any "Gemini 3.5 or newer" model can be selected via NEWSPILOT_MODEL.

Running locally

python server.py            # -> http://localhost:9000  (open in Chrome/Edge)

Windows users can instead double-click start_newspilot.bat, which activates the venv, starts the server, and opens the browser.

Usage

User:      "Give me today's AI news, especially new models and research."
NewsPilot: "Here's your briefing on new AI models:
            1. ...
            2. ...
            3. ...
            Sources: ..."   (read aloud)

User:      "Tell me more about the second story."
NewsPilot: (resolves "second story" from context, researches again, answers)

Google Cloud Deployment

NewsPilot is deployed to Cloud Run, built from source by Cloud Build. It uses Vertex AI (Gemini), Firestore (preferences), Google Search grounding (research), and Cloud Text-to-Speech (voice).

gcloud run deploy newspilot --source . --region us-central1 --allow-unauthenticated \
  --memory 1Gi --cpu 1 --timeout 300 \
  --set-env-vars="GOOGLE_GENAI_USE_VERTEXAI=TRUE,GOOGLE_CLOUD_PROJECT=YOUR_PROJECT_ID,GOOGLE_CLOUD_LOCATION=global,NEWSPILOT_MODEL=gemini-3.6-flash,NEWSPILOT_SEARCH_MODEL=gemini-3.6-flash,NEWSPILOT_TTS_VOICE=en-US-Chirp3-HD-Aoede"

Required IAM (granted once):

  • Runtime service account: roles/aiplatform.user, roles/datastore.user
  • Cloud Build service account: roles/cloudbuild.builds.builder

The .gcloudignore keeps .venv and .env out of the build, so local-only proxy settings never reach the container; runtime config is passed via --set-env-vars.

Agentic Design

NewsPilot qualifies as an agent because the orchestrator makes decisions and drives a multi-step workflow, rather than returning a single model completion.

The LLM-driven decisions include:

  • Goal interpretation turning a request into a scope (specific topic, broad sweep, or a clarifying question), informed by saved preferences.
  • Tool selection choosing when to research, when to de-duplicate, when to rank, and when to read or write preferences.
  • Multi-step workflow search → de-duplicate → rank → synthesize.
  • Follow-up investigation deciding a follow-up needs more detail and calling the search tool again instead of answering from memory.
  • Context/state resolving references like "the second story" from the conversation.

Deterministic (non-LLM) logic is deliberately separated:

  • deduplicate_stories merges stories by normalized URL and title similarity.
  • rank_stories scores by recency, a source-reputation weighting, and breadth of coverage.
  • memory.py reads/writes preferences and falls back to local JSON on failure.

Hallucination and stale-news risk is reduced by grounding every briefing in Google Search results and returning real source URLs; the agent is instructed not to invent news, quotes, dates, or links, and to state plainly when a search returns nothing.

Design Decisions

  • Google ADK, single orchestrator + tools rather than a multi-agent swarm: simpler to reason about and debug, with the LLM deciding when to use each tool.
  • Agent-as-Tool for search: required because ADK won't mix the built-in google_search tool with custom function tools in one agent; it also yields clean separation of concerns.
  • Deterministic de-dup and ranking: fast, free, and explainable, instead of making every step an LLM call.
  • Firestore for preferences, ADK sessions for conversation: separates long-term memory from short-term context; a local JSON fallback keeps the app working if the database is unreachable during development.
  • Custom FastAPI server: one clean, same-origin JSON contract (/api/chat, /api/tts) for the browser, with full control over errors.
  • Config via environment variables: the same code runs on Vertex AI or the AI Studio API by flipping one flag, with no code changes.

Limitations

  • Prototype deployment. Cloud Run scales to zero, so the first request incurs a cold start; briefings also take time because they involve multiple model and search calls.
  • Voice input depends on the browser. Speech-to-text uses the Web Speech API (best in Chrome/Edge; unavailable in some browsers). Typing is always available.
  • Session memory is in-memory. Conversation context is per server instance and not shared across Cloud Run instances or restarts; only preferences persist (in Firestore).
  • Single-user preferences. There is no authentication; preferences are stored under one demo user.
  • Rate limits / availability. Model and API quotas can throttle requests; the agent reports failures rather than crashing.
  • Source ranking is heuristic, based on a small curated source-weight list and recency, not a full credibility model.

Future Improvements

Planned (not yet implemented):

  • Streaming voice for lower latency
  • Scheduled/automatic morning briefings
  • Multi-user accounts so preferences follow the user
  • Richer source cards (outlet names, logos) and a fuller credibility model
  • Multilingual briefings
  • Improved interruption/barge-in handling

Hackathon

All Things Agentic Hackathon 2026 Taskmaster track.

The Taskmaster track focuses on agents that automate a real multi-step task rather than simply chat. NewsPilot automates the full news-research loop gather, filter, de-duplicate, rank, synthesize, and speak and performs additional research to answer follow-up questions, using Google ADK, Gemini on Vertex AI, Google Search grounding, Firestore, Cloud Text-to-Speech, and Cloud Run.

Contributing

This is a hackathon project. Issues and pull requests are welcome; please keep changes focused and include a clear description.

License

MIT — see LICENSE.

Acknowledgements

  • Google Agent Development Kit (ADK)
  • Gemini and Vertex AI
  • Google Search grounding
  • Google Cloud Text-to-Speech (Chirp 3 HD), Firestore, and Cloud Run

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages