The Problem: Too Many Tabs, Not Enough Time
If you've ever worked in outside sales, you know the drill. You're sitting in your truck between appointments, trying to check your calendar, fire off a follow-up email, log a note in the CRM, and figure out which prospect is closest to your current location. That's four apps minimum, and none of them talk to each other.
I spent years bouncing between Google Calendar, Gmail, a spreadsheet-based pipeline tracker, Google Maps, and a notes app. Every day I'd forget to log something, miss a follow-up, or waste 20 minutes planning a route that a computer could figure out in seconds.
So I decided to build something better: a single chat interface where I could just tell my assistant what I needed, and it would handle the rest.
The Solution: One Chat to Rule Them All
The idea was simple. I wanted to open Telegram on my phone and type things like:
"What do I have today?"
"Schedule a meeting with Dave Torres Thursday at 2pm at his office"
"Did Johnson Electric ever reply to my quote?"
"Add Acme Corp as a new lead, talked to Mike the facilities manager"
And have an AI that actually understands context do the right thing -- create calendar events, search my email, update my pipeline, whatever the request calls for. No menus, no forms, no switching apps. Just a conversation.
After a few weeks of building, that's exactly what I got.
Architecture Overview
Here's how the pieces fit together:
Telegram / Web Chat
|
Node.js + Express Server
|
Claude AI (Anthropic) -- tool-use layer
|
+-----------+-----------+-----------+
| | | |
Google Google Google OpenRoute
Calendar Gmail Sheets Service
|
Contacts
Node.js + Express handles incoming messages from Telegram's Bot API and a simple web chat fallback. It manages conversation history and orchestrates everything.
Claude (Anthropic's Sonnet model) is the brain. It receives the user's message along with a set of defined tools, and decides which ones to call. This is the key architectural insight -- I don't write routing logic or intent parsing. I define capabilities, and the model figures out when to use them.
Google APIs provide the actual data layer. Calendar for scheduling, Gmail for email search and drafting, Sheets for the CRM pipeline, and Contacts for looking up people.
Telegram Bot API gives me a mobile-first interface that's always in my pocket. Fast, reliable, supports rich formatting.
Scheduled jobs handle proactive features -- morning briefings, appointment reminders, and weekly recaps that the assistant sends without being asked.
Interesting Technical Decisions
Google Sheets as a CRM
I didn't want to build and maintain a database for pipeline tracking. Google Sheets turned out to be a surprisingly good lightweight CRM. It's visual, easy to share with a manager, and the Sheets API is straightforward. Each row is a lead with columns for company, contact name, status, value, next action, and notes. Claude reads and writes to it directly.
Gmail Drafts as Persistent Memory
This one is my favorite hack. The assistant needs to remember things between conversations -- user preferences, key contacts, recurring patterns. Instead of spinning up a database, I store memory as a JSON object inside a Gmail draft with a specific label. On startup, the assistant loads the draft. When memory updates, it overwrites it. It's free, backed up, and I can even read or edit it manually from Gmail. Zero infrastructure.
Commitment Scanning
One of the most useful features. The assistant periodically scans my sent emails for commitments I've made -- phrases that suggest I promised to send something, follow up, or schedule a call. It extracts these and adds them to a tracked list so nothing slips through the cracks.
Route Optimization
When I have a day full of appointments across the city, the assistant can pull addresses from my calendar events and calculate an optimized route using OpenRouteService's API. It returns a sensible driving order with estimated travel times.
The Tool-Use Pattern
Claude's tool-use feature is what makes this whole thing work. You define tools as JSON schemas, and the model decides when to invoke them based on the conversation. Here's a simplified example of how one tool is defined:
{
name: "search_email",
description: "Search the user's Gmail for emails matching a query.",
input_schema: {
type: "object",
properties: {
query: {
type: "string",
description: "Gmail search query"
},
max_results: {
type: "number",
description: "Maximum number of results to return",
default: 5
}
},
required: ["query"]
}
}
You send this tool definition along with the conversation to Claude's API. When the user says something like "Did Johnson Electric reply to my quote?", Claude decides to call search_email with an appropriate query, gets the results, and formulates a natural response. I never write a single if statement to detect intent. The model handles it.
Example Interactions
Here's what a typical morning looks like:
7:00 AM -- Automatic morning briefing lands in Telegram:
"Good morning! You have 3 appointments today: 9am with Northwest Mechanical (site visit), 11:30am with Torres Plumbing (quote review), and 2pm with Valley HVAC (intro meeting). You also have 2 pending follow-ups due today. Want me to plan your route?"
Me: "Yeah plan my route"
Assistant: "Based on your appointment locations, I'd suggest: Northwest Mechanical first (already at 9am), then Valley HVAC at 2pm since it's on the way back from the east side, with Torres Plumbing last if you can shift it to 3:30. Want me to reschedule Torres?"
Me: "Did Northwest Mechanical reply to that proposal I sent last week?"
Assistant: "Yes -- Sarah Chen replied on March 19th. She had questions about the warranty terms on the commercial units and asked if you could bring spec sheets to tomorrow's meeting."
Me: "Add a note to their pipeline entry: warranty discussion pending, bring spec sheets"
Assistant: "Done. Updated Northwest Mechanical's notes in your pipeline."
That entire exchange took about 90 seconds. Doing it the old way -- checking email, opening the spreadsheet, updating the note -- would have taken five minutes of app-switching while sitting in a parking lot.
Proactive Features
The assistant doesn't just respond -- it reaches out:
- Morning briefings with your schedule, pending follow-ups, and any emails that came in overnight from prospects
- Appointment reminders 30 minutes before each meeting with the contact's info and recent correspondence
- Weekly pipeline recaps summarizing new leads, moved stages, and closed deals
- Commitment reminders when you promised to do something and the deadline is approaching
These scheduled notifications turn the assistant from a reactive tool into something that genuinely has your back.
Tech Stack and Cost
| Component | Service | Monthly Cost |
|---|---|---|
| AI Model | Claude Sonnet (Anthropic API) | $5-20 (usage-based) |
| Server | Any Node.js host (Railway, Render, VPS) | $0-5 |
| Calendar, Email, CRM | Google Workspace APIs | Free tier |
| Route Planning | OpenRouteService | Free tier |
| Chat Interface | Telegram Bot API | Free |
| Total | $5-25/month |
Compare that to a proper CRM subscription plus all the integration tools you'd need to wire things together. This approach costs less than a Salesforce seat and does exactly what I need.
Try It Yourself
After running this for my own workflow and refining it over several months, I packaged the whole thing as a template. It's a complete Node.js project with all the integrations wired up, documentation for getting your API keys set up, and instructions for deploying to your own server.
You'll need to bring your own API keys (Anthropic, Google, Telegram), but the entire codebase is yours to customize. Add tools, change the prompts, connect new services -- it's designed to be extended.
If you're an outside sales rep who's comfortable with Node.js (or knows someone who is), this might save you hours every week. And if you're a developer looking for a real-world example of Claude's tool-use pattern with practical integrations, the codebase is a solid reference.
Happy to answer questions in the comments.
Top comments (0)