Back to samples
Vantage logo
Media

Vantage

Personalized news headlines delivered over RCS

3 min read

Note: the visuals in this demo recording have since been refreshed with sharper brand assets. The conversation flow is identical to what you'll get from a fresh clone.

What's inside

  • Top headlines across general, world, business, tech, sports, and more
  • Search news by free-form keyword
  • Per-user dedup so users never see the same headline twice
  • Gemini Flash with Google Search tool for fresh, grounded results
  • Direct deep-links to Google News search for each story

A personalized news chatbot that delivers fresh headlines over RCS. Users browse top stories by category, search by keyword, and never see the same headline twice — all powered by Gemini Flash with Google Search grounding.

This guide walks you from a fresh clone to live news in your messages app in under 10 minutes.

What you'll build

  • A Pinnacle RCS agent that returns rich news cards on demand
  • A Gemini-grounded fetcher that pulls today's headlines in real time
  • Per-user dedup so the same article never shows up twice
  • A clean separation between transport, news fetching, and presentation

Prerequisites

1. Clone and install

Bash
git clone https://github.com/pinnacle-samples/Vantage
cd Vantage
npm install

2. Configure environment

Bash
cp .env.example .env
env
PINNACLE_API_KEY=your_pinnacle_api_key_here
PINNACLE_AGENT_ID=your_agent_id_here
PINNACLE_SIGNING_SECRET=your_signing_secret_here
GEMINI_API_KEY=your_gemini_api_key_here
TEST_MODE=false
PORT=3000

The Gemini key is required — without it the news fetcher returns an empty array and the agent will tell users no articles were found.

3. Expose your webhook

Bash
ngrok http 3000

4. Connect the webhook

In the Webhooks dashboard:

  1. Add https://<your-tunnel-domain>/webhook
  2. Attach it to your RCS agent
  3. Copy the signing secret into PINNACLE_SIGNING_SECRET

5. Run it

Bash
npm run dev

Send MENU or START to your agent. You'll see the Vantage main menu — tap a category or type a topic and the agent fetches today's top stories live.

How the pieces fit together

Vantage/
├── server.ts                # Express bootstrap
├── router.ts                # /webhook POST — verifies + dispatches
├── lib/
│   ├── rcsClient.ts         # PinnacleClient instance
│   ├── baseAgent.ts         # Shared send + typing helpers
│   ├── typing.ts            # Fire-and-forget typing indicator
│   ├── agent.ts             # Agent — formats articles into cards
│   ├── cache.ts             # Optional disk cache for repeat queries
│   └── news/
│       ├── fetch.ts         # Gemini + Google Search article fetcher
│       └── type.ts          # Article, NewsPayload types

Action handlers

ActionWhat it does
showMainMenuLanding card + category quick replies
sendExplorePageTop headlines / category browse view
sendArticlesFetches and renders articles for a category or query
sendHelpHelp text and search hints

The router also handles free-form text — typing a topic like "climate change" triggers sendArticles with that as the query.

How freshness works

lib/news/fetch.ts uses Gemini Flash with the google_search tool plus a strict prompt:

  • Hard cutoff: only articles from today or yesterday
  • Adds after:<yesterday> to the search query
  • Rejects week-old roundups and evergreen explainers
  • Trims headlines and summaries to RCS card field limits

Headlines a user has already seen are tracked in an in-memory Map keyed by phone number. For production, swap this for Redis — the function signatures are async so you can drop in a real client without touching call sites.

Customize categories

Categories are defined in lib/agent.ts. Add or remove entries to match your audience — the explore page rebuilds automatically.

Going to production

  • Replace the in-memory dedup Map in lib/news/fetch.ts with Redis
  • Set TEST_MODE=false and submit your agent for carrier approval
  • Add scheduled push notifications by wiring a cron to agent.sendMessage for each subscriber

Resources

© 2026 Pinnacle Software Development, Inc.