An automated company research agent built on Trigger.dev. When you add a lead to your ClickUp list, it scrapes their website, reads Alex Hormozi's books from Google Drive as native PDF context, calls Gemini 2.5 Flash with dynamic reasoning, and posts a structured strategic audit directly as a ClickUp comment — all within 2 minutes. Reply to the comment with any follow-up request (cold email, Grand Slam Offer, competitor analysis, outreach sequence, or strategic Q&A) and the agent responds automatically, always grounded in the original audit and Hormozi frameworks.
Last deployed: February 25, 2026 — fully live and verified working end-to-end.
| Item | Detail |
|---|---|
| GitHub Repo | github.com/miraclechudo1230-png/ThriveForge-AI |
| Hosting | cloud.trigger.dev — Production environment |
| Deploy method | npx trigger.dev@latest deploy (or auto via GitHub Actions on push to main) |
| Status | ✅ Live — polling ClickUp every 2 minutes, audits posting automatically |
- Code deployed via
npx trigger.dev@latest deploy - All environment variables added to
cloud.trigger.dev → Project → Environment Variables → Production(see table below — the.envfile is local only and is not deployed automatically) - GitHub repo created at
github.com/miraclechudo1230-png/ThriveForge-AIand code pushed
- Add a task to the ThriveForge Leads ClickUp list with a company URL in the description
- Within 2 minutes, the AI agent posts a full Hormozi-style strategic audit as a comment
- Reply to the comment → follow-up agent responds within 2 minutes
⚠️ Important for future deployments: After anydeploy, always confirm all environment variables are still present in the Trigger.dev production environment. They are NOT synced from.envautomatically.
src/
├── trigger/lead-strategist/
│ ├── clickup-research-poller.ts Scheduled cron (*/2 * * * *)
│ │ Fetches all unprocessed tasks from ClickUp,
│ │ dispatches one company-researcher-agent per task.
│ │
│ ├── company-researcher-agent.ts Core audit agent.
│ │ 1. Scrapes company website
│ │ 2. Loads Hormozi PDFs via Gemini Files API (RAG)
│ │ 3. Calls Gemini 2.5 Flash with thinking enabled
│ │ 4. Posts formatted strategic audit to ClickUp
│ │ 5. Tags task as `thriveforge-processed`
│ │
│ ├── clickup-followup-poller.ts Scheduled cron (*/2 * * * *)
│ │ Checks all processed tasks for new user replies,
│ │ dispatches one followup-responder-agent per reply.
│ │
│ └── followup-responder-agent.ts Follow-up agent. Auto-detects request type:
│ Q&A / Cold Email / LinkedIn DM /
│ Grand Slam Offer / Competitor Analysis /
│ Outreach Sequence.
│ Always anchors to the original audit context.
│
└── lib/
├── clickup.ts All ClickUp API calls (read tasks, post comments, tag tasks)
├── gemini.ts Gemini 2.5 Flash REST wrapper (supports PDF file refs + thinking)
├── google-drive.ts Google Drive API via raw OAuth2 fetch (no googleapis library)
├── hormozi-rag.ts Uploads Hormozi PDFs to Gemini Files API; reuses active uploads
└── scraper.ts Web scraper — raw fetch by default, Firecrawl if key is present
scripts/
└── auth-google.ts One-time OAuth2 browser flow → writes GOOGLE_REFRESH_TOKEN to .env
State tracking: Tasks are tagged thriveforge-processed in ClickUp after an audit is posted. The research poller ignores tagged tasks; the follow-up poller only watches them. No external database needed.
Copy .env and fill in any missing values. All variables marked required must also be added to cloud.trigger.dev → Project → Environment Variables before deploying.
| Variable | Required | Where to get it |
|---|---|---|
TRIGGER_PROJECT_REF |
✅ | cloud.trigger.dev → Project Settings → Project ref |
TRIGGER_SECRET_KEY |
✅ | cloud.trigger.dev → Project Settings → API Keys → tr_dev_... (local) or tr_prod_... (prod) |
| Variable | Required | Where to get it |
|---|---|---|
CLICKUP_API_TOKEN |
✅ | app.clickup.com → Settings → Apps → API Token |
CLICKUP_LIST_ID |
✅ | Open the ClickUp list → copy the number from the URL |
CLICKUP_WORKSPACE_ID |
✅ | app.clickup.com → Settings → copy from URL |
CLICKUP_DONE_STATUS |
⬜ optional | Exact status name in your workspace (e.g. complete, done). Leave blank to skip. |
| Variable | Required | Where to get it |
|---|---|---|
GOOGLE_CLIENT_ID |
✅ | console.cloud.google.com → APIs & Services → Credentials → OAuth 2.0 Client → credentials.json |
GOOGLE_CLIENT_SECRET |
✅ | Same as above |
GOOGLE_REDIRECT_URI |
✅ | http://localhost (for installed app flow) |
GOOGLE_REFRESH_TOKEN |
✅ | Run npm run auth:google once locally — written automatically |
GOOGLE_DRIVE_FOLDER_ID |
✅ | Open the Drive folder → copy ID from URL after /folders/ |
| Variable | Required | Where to get it |
|---|---|---|
GOOGLE_AI_API_KEY |
✅ | aistudio.google.com → Get API Key |
| Variable | Default | Effect when set |
|---|---|---|
FIRECRAWL_API_KEY |
raw fetch | Upgrades scraper to Firecrawl (handles JS-heavy sites, returns clean markdown). Get from firecrawl.dev. |
SERPAPI_KEY |
disabled | Enables live Google search during research. Get from serpapi.com. |
npm installnpm run auth:googleOpens your browser → approve Google Drive read access → refresh token written to .env automatically.
npm run devThe Trigger.dev CLI connects to the cloud, registers all 4 tasks, and begins executing scheduled runs locally. Logs stream to your terminal in real time.
You should see:
○ Local worker ready [node] → 20260225.1 | Test tasks | View runs
○ [research-poller] Checking list 901711364943 for new tasks...
○ [research-poller] Found 0 unprocessed task(s) ✅
npx trigger.dev@latest deployPush to master. The workflow in .github/workflows/deploy.yml deploys automatically.
Before deploying: Add all environment variables to
cloud.trigger.dev → Project → Environment Variables → Production. The.envfile is only used locally.
- Add a task to your "ThriveForge Leads" ClickUp list
- Put the company URL in the task description, e.g.:
https://example.com — check their B2B positioning - Wait up to 2 minutes
- A strategic audit appears as a comment on the task
After the audit posts, reply to the task comment with any of:
- A strategic question: "Why does their pricing create a ceiling?"
- "Draft a cold email to send them"
- "Write a LinkedIn DM"
- "Build a Grand Slam Offer we could pitch them"
- "How do they compare to [competitor]? https://competitor.com"
- "Give me a 5-step outreach sequence"
Wait up to 2 minutes — the follow-up agent responds with context from the original audit.
From cloud.trigger.dev → Tasks → company-researcher-agent → Test:
{
"taskId": "YOUR_CLICKUP_TASK_ID",
"taskName": "Acme Corp",
"taskDescription": "https://acme.com — review their positioning"
}Edit the SYSTEM_PROMPT and buildUserPrompt() in:
src/trigger/lead-strategist/company-researcher-agent.ts
The current format enforces:
- 4 emoji-headed sections (Business Model, Site Experience, Operational, Next Steps)
- Under 800 words total
- 1 Hormozi citation per section (book title + page number)
- Bold mechanism names
Edit the SYSTEM_PROMPT in:
src/trigger/lead-strategist/followup-responder-agent.ts
Each mode (Q&A, Cold Email, Grand Slam Offer, etc.) has its own format rules inside the system prompt.
In src/lib/gemini.ts, adjust thinkingBudget (default: 8000 tokens):
0— disable thinking (faster, cheaper, less reasoning)8000— current default (strong reasoning, ~60–90s per audit)24576— maximum (deepest reasoning, may hit connection timeouts with 3 PDFs)
In src/lib/scraper.ts, the scrapeUrl() function uses raw fetch by default.
Set FIRECRAWL_API_KEY in .env to automatically switch to Firecrawl for JS-heavy sites.
| Limitation | Impact | Workaround |
|---|---|---|
| Gemini Files API — 48h expiry | Hormozi PDFs are re-uploaded to Gemini every 48 hours | Handled automatically — hormozi-rag.ts checks for active files before uploading |
| Raw fetch scraper | Won't work on JS-rendered sites (SPAs, React apps) | Set FIRECRAWL_API_KEY to upgrade to Firecrawl |
| ClickUp rate limits | 100 req/min on free plan — aggressive polling could hit limits | 2-min polling interval is conservative enough for normal usage |
| Gemini thinking + 3 PDFs | Large context can cause connection resets on very slow networks | thinkingBudget is capped at 8000 (not dynamic) to prevent this |
| Status name sensitivity | CLICKUP_DONE_STATUS must exactly match your workspace status (case-sensitive) |
Leave blank to skip; task state is tracked via the thriveforge-processed tag instead |
| Follow-up detection window | Follow-up poller only detects replies posted within the last 3 minutes | Designed to be robust with a 1-minute buffer over the 2-minute poll interval |
| Google OAuth refresh token | Token is tied to the approving Google account | Re-run npm run auth:google if you get auth errors after a long time |
| No multi-workspace support | One ClickUp list and one Drive folder per deployment | Deploy separate Trigger.dev projects for different workspaces |