@opendirectory.dev/skills 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/claude-md-generator/.env.example +7 -0
- package/.claude/skills/claude-md-generator/README.md +78 -0
- package/.claude/skills/claude-md-generator/SKILL.md +248 -0
- package/.claude/skills/claude-md-generator/evals/evals.json +35 -0
- package/.claude/skills/claude-md-generator/references/section-guide.md +175 -0
- package/dist/e2e.test.d.ts +1 -0
- package/dist/e2e.test.js +62 -0
- package/dist/fs-adapters.d.ts +4 -0
- package/dist/fs-adapters.js +101 -0
- package/dist/fs-adapters.test.d.ts +1 -0
- package/dist/fs-adapters.test.js +108 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +211 -0
- package/dist/transformers.d.ts +6 -0
- package/dist/transformers.js +2 -0
- package/package.json +25 -0
- package/registry.json +226 -0
- package/skills/blog-cover-image-cli/.github/workflows/publish.yml +19 -0
- package/skills/blog-cover-image-cli/LICENSE +15 -0
- package/skills/blog-cover-image-cli/README.md +126 -0
- package/skills/blog-cover-image-cli/SKILL.md +7 -0
- package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/README.md +30 -0
- package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/SKILL.md +72 -0
- package/skills/blog-cover-image-cli/bin/cli.js +226 -0
- package/skills/blog-cover-image-cli/examples/100x_UX_Research_AI_Agent.png +0 -0
- package/skills/blog-cover-image-cli/examples/Firecrawl-supabase-bolt.png +0 -0
- package/skills/blog-cover-image-cli/examples/Git-City_Case_study_Cover_Image.jpg +0 -0
- package/skills/blog-cover-image-cli/examples/THE DISTRIBUTION LAYER (2).png +0 -0
- package/skills/blog-cover-image-cli/examples/canva-perplexity-duolingo-cover-image.png +0 -0
- package/skills/blog-cover-image-cli/examples/gamma-mistral-veed.png +0 -0
- package/skills/blog-cover-image-cli/examples/server-survival-case-study-cover-image(1).png +0 -0
- package/skills/blog-cover-image-cli/examples/viral-meme-automation.png +0 -0
- package/skills/blog-cover-image-cli/index.js +2 -0
- package/skills/blog-cover-image-cli/package-lock.json +2238 -0
- package/skills/blog-cover-image-cli/package.json +37 -0
- package/skills/blog-cover-image-cli/src/geminiGenerator.js +126 -0
- package/skills/blog-cover-image-cli/src/imageValidator.js +54 -0
- package/skills/blog-cover-image-cli/src/logoFetcher.js +86 -0
- package/skills/claude-md-generator/.env.example +7 -0
- package/skills/claude-md-generator/README.md +78 -0
- package/skills/claude-md-generator/SKILL.md +254 -0
- package/skills/claude-md-generator/evals/evals.json +35 -0
- package/skills/claude-md-generator/references/section-guide.md +175 -0
- package/skills/cook-the-blog/README.md +86 -0
- package/skills/cook-the-blog/SKILL.md +130 -0
- package/skills/dependency-update-bot/.env.example +13 -0
- package/skills/dependency-update-bot/README.md +101 -0
- package/skills/dependency-update-bot/SKILL.md +376 -0
- package/skills/dependency-update-bot/evals/evals.json +45 -0
- package/skills/dependency-update-bot/references/changelog-patterns.md +201 -0
- package/skills/docs-from-code/.env.example +13 -0
- package/skills/docs-from-code/README.md +97 -0
- package/skills/docs-from-code/SKILL.md +160 -0
- package/skills/docs-from-code/evals/evals.json +29 -0
- package/skills/docs-from-code/references/extraction-guide.md +174 -0
- package/skills/docs-from-code/references/output-template.md +135 -0
- package/skills/docs-from-code/scripts/extract_py.py +238 -0
- package/skills/docs-from-code/scripts/extract_ts.ts +284 -0
- package/skills/docs-from-code/scripts/package.json +18 -0
- package/skills/explain-this-pr/README.md +74 -0
- package/skills/explain-this-pr/SKILL.md +130 -0
- package/skills/explain-this-pr/evals/evals.json +35 -0
- package/skills/google-trends-api-skills/README.md +78 -0
- package/skills/google-trends-api-skills/SKILL.md +7 -0
- package/skills/google-trends-api-skills/google-trends-api/SKILL.md +163 -0
- package/skills/google-trends-api-skills/google-trends-api/references/api-responses.md +188 -0
- package/skills/google-trends-api-skills/google-trends-api/scripts/discover_keywords.py +344 -0
- package/skills/google-trends-api-skills/seo-keyword-research/SKILL.md +205 -0
- package/skills/google-trends-api-skills/seo-keyword-research/references/keyword-placement-guide.md +89 -0
- package/skills/google-trends-api-skills/seo-keyword-research/references/tech-blog-examples.md +207 -0
- package/skills/google-trends-api-skills/seo-keyword-research/scripts/blog_seo_research.py +373 -0
- package/skills/hackernews-intel/.env.example +33 -0
- package/skills/hackernews-intel/README.md +161 -0
- package/skills/hackernews-intel/SKILL.md +156 -0
- package/skills/hackernews-intel/evals/evals.json +35 -0
- package/skills/hackernews-intel/package.json +15 -0
- package/skills/hackernews-intel/scripts/monitor-hn.js +258 -0
- package/skills/kill-the-standup/.env.example +22 -0
- package/skills/kill-the-standup/README.md +84 -0
- package/skills/kill-the-standup/SKILL.md +169 -0
- package/skills/kill-the-standup/evals/evals.json +35 -0
- package/skills/kill-the-standup/references/standup-format.md +102 -0
- package/skills/linkedin-post-generator/.env.example +14 -0
- package/skills/linkedin-post-generator/README.md +107 -0
- package/skills/linkedin-post-generator/SKILL.md +228 -0
- package/skills/linkedin-post-generator/evals/evals.json +35 -0
- package/skills/linkedin-post-generator/references/linkedin-format.md +216 -0
- package/skills/linkedin-post-generator/references/output-template.md +154 -0
- package/skills/llms-txt-generator/.env.example +18 -0
- package/skills/llms-txt-generator/README.md +142 -0
- package/skills/llms-txt-generator/SKILL.md +176 -0
- package/skills/llms-txt-generator/evals/evals.json +35 -0
- package/skills/llms-txt-generator/references/llms-txt-spec.md +88 -0
- package/skills/llms-txt-generator/references/output-template.md +76 -0
- package/skills/llms-txt-generator/test-output/genzcareer.in/llms.txt +31 -0
- package/skills/luma-attendees-scraper/README.md +170 -0
- package/skills/luma-attendees-scraper/SKILL.md +7 -0
- package/skills/luma-attendees-scraper/luma_attendees_export.js +223 -0
- package/skills/meeting-brief-generator/.env.example +21 -0
- package/skills/meeting-brief-generator/README.md +90 -0
- package/skills/meeting-brief-generator/SKILL.md +275 -0
- package/skills/meeting-brief-generator/evals/evals.json +35 -0
- package/skills/meeting-brief-generator/references/brief-format.md +114 -0
- package/skills/meeting-brief-generator/references/output-template.md +150 -0
- package/skills/meta-ads-skill/README.md +100 -0
- package/skills/meta-ads-skill/SKILL.md +7 -0
- package/skills/meta-ads-skill/meta-ads-skill/SKILL.md +41 -0
- package/skills/meta-ads-skill/meta-ads-skill/references/report_templates.md +47 -0
- package/skills/meta-ads-skill/meta-ads-skill/references/workflows.md +51 -0
- package/skills/meta-ads-skill/meta-ads-skill/scripts/auth_check.py +22 -0
- package/skills/meta-ads-skill/meta-ads-skill/scripts/formatters.py +46 -0
- package/skills/newsletter-digest/.env.example +20 -0
- package/skills/newsletter-digest/README.md +147 -0
- package/skills/newsletter-digest/SKILL.md +221 -0
- package/skills/newsletter-digest/evals/evals.json +35 -0
- package/skills/newsletter-digest/feeds.json +7 -0
- package/skills/newsletter-digest/package.json +15 -0
- package/skills/newsletter-digest/references/digest-format.md +123 -0
- package/skills/newsletter-digest/references/output-template.md +136 -0
- package/skills/newsletter-digest/scripts/fetch-feeds.js +141 -0
- package/skills/newsletter-digest/scripts/ghost-publish.js +147 -0
- package/skills/noise2blog/.env.example +16 -0
- package/skills/noise2blog/README.md +107 -0
- package/skills/noise2blog/SKILL.md +229 -0
- package/skills/noise2blog/evals/evals.json +35 -0
- package/skills/noise2blog/references/blog-format.md +188 -0
- package/skills/noise2blog/references/output-template.md +184 -0
- package/skills/outreach-sequence-builder/.env.example +12 -0
- package/skills/outreach-sequence-builder/README.md +108 -0
- package/skills/outreach-sequence-builder/SKILL.md +248 -0
- package/skills/outreach-sequence-builder/evals/evals.json +36 -0
- package/skills/outreach-sequence-builder/references/output-template.md +171 -0
- package/skills/outreach-sequence-builder/references/sequence-format.md +167 -0
- package/skills/outreach-sequence-builder/references/signal-playbook.md +117 -0
- package/skills/position-me/README.md +71 -0
- package/skills/position-me/SKILL.md +7 -0
- package/skills/position-me/position-me/SKILL.md +50 -0
- package/skills/position-me/position-me/references/EVALUATION_SOP.md +40 -0
- package/skills/position-me/position-me/references/REPORT_TEMPLATE.md +58 -0
- package/skills/position-me/position-me/scripts/extract_links.py +49 -0
- package/skills/pr-description-writer/README.md +81 -0
- package/skills/pr-description-writer/SKILL.md +141 -0
- package/skills/pr-description-writer/evals/evals.json +35 -0
- package/skills/pr-description-writer/references/pr-format-guide.md +145 -0
- package/skills/producthunt-launch-kit/.env.example +7 -0
- package/skills/producthunt-launch-kit/README.md +95 -0
- package/skills/producthunt-launch-kit/SKILL.md +380 -0
- package/skills/producthunt-launch-kit/evals/evals.json +35 -0
- package/skills/producthunt-launch-kit/references/copy-rules.md +124 -0
- package/skills/reddit-icp-monitor/.env.example +16 -0
- package/skills/reddit-icp-monitor/README.md +117 -0
- package/skills/reddit-icp-monitor/SKILL.md +271 -0
- package/skills/reddit-icp-monitor/evals/evals.json +40 -0
- package/skills/reddit-icp-monitor/references/icp-format.md +131 -0
- package/skills/reddit-icp-monitor/references/reply-rules.md +110 -0
- package/skills/reddit-post-engine/.env.example +13 -0
- package/skills/reddit-post-engine/README.md +103 -0
- package/skills/reddit-post-engine/SKILL.md +303 -0
- package/skills/reddit-post-engine/evals/evals.json +35 -0
- package/skills/reddit-post-engine/references/subreddit-playbook.md +156 -0
- package/skills/schema-markup-generator/.env.example +19 -0
- package/skills/schema-markup-generator/README.md +114 -0
- package/skills/schema-markup-generator/SKILL.md +192 -0
- package/skills/schema-markup-generator/evals/evals.json +35 -0
- package/skills/schema-markup-generator/references/json-ld-spec.md +263 -0
- package/skills/schema-markup-generator/references/output-template.md +556 -0
- package/skills/show-hn-writer/.env.example +14 -0
- package/skills/show-hn-writer/README.md +88 -0
- package/skills/show-hn-writer/SKILL.md +303 -0
- package/skills/show-hn-writer/evals/evals.json +35 -0
- package/skills/show-hn-writer/references/hn-rules.md +74 -0
- package/skills/show-hn-writer/references/title-formulas.md +93 -0
- package/skills/stargazer/README.md +79 -0
- package/skills/stargazer/SKILL.md +7 -0
- package/skills/stargazer/stargazer-skill/SKILL.md +58 -0
- package/skills/stargazer/stargazer-skill/assets/.env.example +18 -0
- package/skills/stargazer/stargazer-skill/scripts/convert_to_csv.py +63 -0
- package/skills/stargazer/stargazer-skill/scripts/count_emails.py +52 -0
- package/skills/stargazer/stargazer-skill/scripts/stargazer_deep_extractor.py +450 -0
- package/skills/tweet-thread-from-blog/.env.example +14 -0
- package/skills/tweet-thread-from-blog/README.md +109 -0
- package/skills/tweet-thread-from-blog/SKILL.md +177 -0
- package/skills/tweet-thread-from-blog/evals/evals.json +35 -0
- package/skills/tweet-thread-from-blog/references/output-template.md +193 -0
- package/skills/tweet-thread-from-blog/references/thread-format.md +107 -0
- package/skills/twitter-GTM-find-skill/README.md +43 -0
- package/skills/twitter-GTM-find-skill/SKILL.md +7 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/SKILL.md +37 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/references/icp-checklist.md +35 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/package.json +23 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/run_pipeline.sh +8 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/debug.ts +23 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/extractor.ts +79 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/icp-filter.ts +87 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/index.ts +94 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/scraper.ts +41 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/tsconfig.json +13 -0
- package/skills/yc-intent-radar-skill/README.md +39 -0
- package/skills/yc-intent-radar-skill/SKILL.md +7 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/SKILL.md +59 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/auth.js +29 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/db.js +62 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/export_radar_candidates.js +40 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package-lock.json +1525 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package.json +12 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/scraper.js +217 -0
- package/src/e2e.test.ts +35 -0
- package/src/fs-adapters.test.ts +91 -0
- package/src/fs-adapters.ts +65 -0
- package/src/index.ts +182 -0
- package/src/transformers.ts +6 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: meeting-brief-generator
|
|
3
|
+
description: Takes a company name and optional contact, runs targeted research via Tavily, synthesizes a 1-page pre-call brief with Gemini, and optionally saves it to Notion. Use when asked to prepare for a meeting, research a prospect before a call, generate a company brief, create a pre-call summary, or write a meeting prep doc. Trigger when a user says "prepare me for a meeting with", "research this company before my call", "generate a meeting brief for", "I have a call with X tomorrow", or "create a prospect brief for".
|
|
4
|
+
compatibility: [claude-code, gemini-cli, github-copilot]
|
|
5
|
+
author: OpenDirectory
|
|
6
|
+
version: 1.0.0
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Meeting Brief Generator
|
|
10
|
+
|
|
11
|
+
Take a company name and optional contact. Research the company via Tavily. Synthesize a 1-page pre-call brief with Gemini. Optionally save to Notion.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
**Critical rule:** DO NOT INVENT SPECIFICS. Every fact, number, and claim in the brief must come from a Tavily search result. Mark any section with no search data as "Limited public information found." Never fabricate funding amounts, employee counts, or product details.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Step 1: Setup Check
|
|
20
|
+
|
|
21
|
+
Confirm required env vars:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
echo "TAVILY_API_KEY: ${TAVILY_API_KEY:+set}"
|
|
25
|
+
echo "GEMINI_API_KEY: ${GEMINI_API_KEY:+set}"
|
|
26
|
+
echo "NOTION_TOKEN: ${NOTION_TOKEN:-not set}"
|
|
27
|
+
echo "NOTION_DATABASE_ID: ${NOTION_DATABASE_ID:-not set}"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**If TAVILY_API_KEY is missing:**
|
|
31
|
+
Stop. Tell the user: "TAVILY_API_KEY is required. Get it at app.tavily.com. Add it to your .env file."
|
|
32
|
+
|
|
33
|
+
**If GEMINI_API_KEY is missing:**
|
|
34
|
+
Stop. Tell the user: "GEMINI_API_KEY is required. Get it at aistudio.google.com. Add it to your .env file."
|
|
35
|
+
|
|
36
|
+
**If NOTION_TOKEN or NOTION_DATABASE_ID is missing:**
|
|
37
|
+
Continue. The brief will be output as text only. Notion saving is skipped.
|
|
38
|
+
|
|
39
|
+
**Confirm input is present.**
|
|
40
|
+
The user must provide at minimum a company name. If not provided, ask: "Which company are you meeting with?"
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Step 2: Gather Context
|
|
45
|
+
|
|
46
|
+
Collect the following. Ask only for what is missing.
|
|
47
|
+
|
|
48
|
+
Required:
|
|
49
|
+
- Company name (or domain/URL if provided)
|
|
50
|
+
- Meeting date
|
|
51
|
+
|
|
52
|
+
Optional (do not block if missing):
|
|
53
|
+
- Contact name and title
|
|
54
|
+
- Meeting type (discovery, demo, follow-up, QBR)
|
|
55
|
+
- Any specific topics or goals the user wants to cover
|
|
56
|
+
|
|
57
|
+
If the user provides a company URL or domain, use it to make Tavily queries more precise (e.g. `site:example.com` or include the domain in search terms).
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Step 3: Research with Tavily
|
|
62
|
+
|
|
63
|
+
Run these searches in sequence. Each targets one section of the brief. Save the top results from each (title, url, content snippet, score).
|
|
64
|
+
|
|
65
|
+
Keep results with score >= 0.5. If a search returns 0 qualifying results, mark that section as "Limited public information found."
|
|
66
|
+
|
|
67
|
+
**Search 1: Company overview**
|
|
68
|
+
```bash
|
|
69
|
+
curl -s -X POST "https://api.tavily.com/search" \
|
|
70
|
+
-H "Content-Type: application/json" \
|
|
71
|
+
-d '{
|
|
72
|
+
"api_key": "'"$TAVILY_API_KEY"'",
|
|
73
|
+
"query": "\"COMPANY\" overview founded employees headquarters",
|
|
74
|
+
"search_depth": "advanced",
|
|
75
|
+
"max_results": 5,
|
|
76
|
+
"include_answer": true
|
|
77
|
+
}'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Search 2: Recent news (last 30 days)**
|
|
81
|
+
```bash
|
|
82
|
+
curl -s -X POST "https://api.tavily.com/search" \
|
|
83
|
+
-H "Content-Type: application/json" \
|
|
84
|
+
-d '{
|
|
85
|
+
"api_key": "'"$TAVILY_API_KEY"'",
|
|
86
|
+
"query": "\"COMPANY\" news announcement",
|
|
87
|
+
"search_depth": "advanced",
|
|
88
|
+
"max_results": 5,
|
|
89
|
+
"include_answer": true,
|
|
90
|
+
"topic": "news",
|
|
91
|
+
"time_range": "month"
|
|
92
|
+
}'
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Search 3: Tech stack**
|
|
96
|
+
```bash
|
|
97
|
+
curl -s -X POST "https://api.tavily.com/search" \
|
|
98
|
+
-H "Content-Type: application/json" \
|
|
99
|
+
-d '{
|
|
100
|
+
"api_key": "'"$TAVILY_API_KEY"'",
|
|
101
|
+
"query": "\"COMPANY\" technology stack engineering infrastructure tools",
|
|
102
|
+
"search_depth": "advanced",
|
|
103
|
+
"max_results": 5,
|
|
104
|
+
"include_answer": true
|
|
105
|
+
}'
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Search 4: Product and pricing**
|
|
109
|
+
```bash
|
|
110
|
+
curl -s -X POST "https://api.tavily.com/search" \
|
|
111
|
+
-H "Content-Type: application/json" \
|
|
112
|
+
-d '{
|
|
113
|
+
"api_key": "'"$TAVILY_API_KEY"'",
|
|
114
|
+
"query": "\"COMPANY\" product features pricing use case",
|
|
115
|
+
"search_depth": "advanced",
|
|
116
|
+
"max_results": 5,
|
|
117
|
+
"include_answer": true
|
|
118
|
+
}'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Search 5: Competitors**
|
|
122
|
+
```bash
|
|
123
|
+
curl -s -X POST "https://api.tavily.com/search" \
|
|
124
|
+
-H "Content-Type: application/json" \
|
|
125
|
+
-d '{
|
|
126
|
+
"api_key": "'"$TAVILY_API_KEY"'",
|
|
127
|
+
"query": "\"COMPANY\" competitors alternatives vs",
|
|
128
|
+
"search_depth": "advanced",
|
|
129
|
+
"max_results": 5,
|
|
130
|
+
"include_answer": true
|
|
131
|
+
}'
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Search 6: Funding and growth**
|
|
135
|
+
```bash
|
|
136
|
+
curl -s -X POST "https://api.tavily.com/search" \
|
|
137
|
+
-H "Content-Type: application/json" \
|
|
138
|
+
-d '{
|
|
139
|
+
"api_key": "'"$TAVILY_API_KEY"'",
|
|
140
|
+
"query": "\"COMPANY\" funding raised valuation growth",
|
|
141
|
+
"search_depth": "advanced",
|
|
142
|
+
"max_results": 5,
|
|
143
|
+
"include_answer": true
|
|
144
|
+
}'
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**If contact name is provided, run two more searches:**
|
|
148
|
+
|
|
149
|
+
**Search 7: Contact profile**
|
|
150
|
+
```bash
|
|
151
|
+
curl -s -X POST "https://api.tavily.com/search" \
|
|
152
|
+
-H "Content-Type: application/json" \
|
|
153
|
+
-d '{
|
|
154
|
+
"api_key": "'"$TAVILY_API_KEY"'",
|
|
155
|
+
"query": "\"CONTACT_NAME\" \"COMPANY\" role title",
|
|
156
|
+
"search_depth": "advanced",
|
|
157
|
+
"max_results": 5,
|
|
158
|
+
"include_answer": true
|
|
159
|
+
}'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Search 8: Contact background**
|
|
163
|
+
```bash
|
|
164
|
+
curl -s -X POST "https://api.tavily.com/search" \
|
|
165
|
+
-H "Content-Type: application/json" \
|
|
166
|
+
-d '{
|
|
167
|
+
"api_key": "'"$TAVILY_API_KEY"'",
|
|
168
|
+
"query": "\"CONTACT_NAME\" background career LinkedIn",
|
|
169
|
+
"search_depth": "advanced",
|
|
170
|
+
"max_results": 5,
|
|
171
|
+
"include_answer": true
|
|
172
|
+
}'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Step 4: Synthesize with Gemini
|
|
178
|
+
|
|
179
|
+
Read `references/brief-format.md` in full. Read `references/output-template.md` and use the template.
|
|
180
|
+
|
|
181
|
+
Write the Gemini request to a temp file:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
cat > /tmp/meeting-brief-request.json << 'ENDJSON'
|
|
185
|
+
{
|
|
186
|
+
"system_instruction": {
|
|
187
|
+
"parts": [{
|
|
188
|
+
"text": "You are a GTM research analyst preparing a 1-page pre-call brief for a sales or business development meeting. Rules: Every claim must cite a source URL from the provided research. Use the format 'Because [finding from research], mention [point] to [goal]' for talking points. No invented data. If a section has no research data, write 'Limited public information found.' No em dashes. No banned words. Under 400 words total. The brief must be scannable in 3 minutes."
|
|
189
|
+
}]
|
|
190
|
+
},
|
|
191
|
+
"contents": [{
|
|
192
|
+
"parts": [{
|
|
193
|
+
"text": "RESEARCH_RESULTS_AND_INSTRUCTIONS_HERE"
|
|
194
|
+
}]
|
|
195
|
+
}],
|
|
196
|
+
"generationConfig": {
|
|
197
|
+
"temperature": 0.3,
|
|
198
|
+
"maxOutputTokens": 2500
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
ENDJSON
|
|
202
|
+
curl -s -X POST \
|
|
203
|
+
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
|
|
204
|
+
-H "Content-Type: application/json" \
|
|
205
|
+
-d @/tmp/meeting-brief-request.json \
|
|
206
|
+
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Replace `RESEARCH_RESULTS_AND_INSTRUCTIONS_HERE` with:
|
|
210
|
+
- All Tavily search results (title, url, content snippet per result)
|
|
211
|
+
- The brief template structure from output-template.md
|
|
212
|
+
- The company name, contact name (if provided), meeting date, meeting type (if provided)
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Step 5: Self-QA
|
|
217
|
+
|
|
218
|
+
Check before presenting:
|
|
219
|
+
|
|
220
|
+
- [ ] No invented data. Every fact has a source URL from Tavily results.
|
|
221
|
+
- [ ] Talking points use "Because [finding], mention [point] to [goal]" format
|
|
222
|
+
- [ ] No em dashes in any line
|
|
223
|
+
- [ ] No banned words
|
|
224
|
+
- [ ] Brief is under 400 words
|
|
225
|
+
- [ ] Decision Maker section says "Not specified" if no contact was provided
|
|
226
|
+
- [ ] Sections with no data say "Limited public information found" rather than guessing
|
|
227
|
+
- [ ] Open questions are specific to this company, not generic
|
|
228
|
+
|
|
229
|
+
Fix any violation before presenting.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Step 6: Output or Save to Notion
|
|
234
|
+
|
|
235
|
+
Present the full brief in a code block.
|
|
236
|
+
|
|
237
|
+
If NOTION_TOKEN and NOTION_DATABASE_ID are both set, ask: "Save this brief to Notion?"
|
|
238
|
+
|
|
239
|
+
On confirmation:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
cat > /tmp/notion-brief-payload.json << 'ENDJSON'
|
|
243
|
+
{
|
|
244
|
+
"parent": { "database_id": "NOTION_DATABASE_ID_HERE" },
|
|
245
|
+
"properties": {
|
|
246
|
+
"Name": {
|
|
247
|
+
"title": [{ "text": { "content": "Meeting Brief: COMPANY, DATE" } }]
|
|
248
|
+
},
|
|
249
|
+
"Date": {
|
|
250
|
+
"date": { "start": "YYYY-MM-DD" }
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
"children": [
|
|
254
|
+
{
|
|
255
|
+
"object": "block",
|
|
256
|
+
"type": "paragraph",
|
|
257
|
+
"paragraph": {
|
|
258
|
+
"rich_text": [{ "type": "text", "text": { "content": "BRIEF_CONTENT_HERE" } }]
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
ENDJSON
|
|
264
|
+
curl -s -X POST "https://api.notion.com/v1/pages" \
|
|
265
|
+
-H "Authorization: Bearer $NOTION_TOKEN" \
|
|
266
|
+
-H "Content-Type: application/json" \
|
|
267
|
+
-H "Notion-Version: 2022-06-28" \
|
|
268
|
+
-d @/tmp/notion-brief-payload.json
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
After posting: "Brief saved to Notion. Check your database."
|
|
272
|
+
|
|
273
|
+
If Notion is not configured: present the brief only. Do not mention Notion.
|
|
274
|
+
|
|
275
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "meeting-brief-generator",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Prepare me for a meeting with Acme Corp on April 15. I'm meeting Jordan Lee, their VP Engineering. It's a discovery call.",
|
|
7
|
+
"expected_output": "Agent checks TAVILY_API_KEY and GEMINI_API_KEY — both set. Confirms company name, contact, date, and meeting type from the prompt. Runs 8 Tavily searches (overview, news, tech stack, product, competitors, funding, contact profile, contact background). Filters results with score >= 0.5. Synthesizes 1-page brief with Gemini using brief-format.md rules. Brief includes all 7 sections: Company Snapshot, Recent News, Decision Maker (Jordan Lee details), Tech Stack Signals, Competitive Context, Talking Points (3-5 bullets using Because/mention/to formula), Open Questions (2-3 company-specific). Every fact has a source URL. Under 400 words. Asks if user wants to save to Notion.",
|
|
8
|
+
"files": []
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": 2,
|
|
12
|
+
"prompt": "Generate a meeting brief for Stripe. Meeting is tomorrow.",
|
|
13
|
+
"expected_output": "Agent detects no contact name and no meeting type in the prompt. Runs 6 Tavily searches (skips contact-specific searches). Produces complete brief with all sections. Decision Maker section reads 'Not specified.' Talking points are based on company-level research (not contact-specific). Open questions are relevant to Stripe's public situation. Agent does not ask for more info before proceeding — proceeds with available data. Brief is under 400 words.",
|
|
14
|
+
"files": []
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": 3,
|
|
18
|
+
"prompt": "Create a meeting brief for my call with Linear next week",
|
|
19
|
+
"expected_output": "Agent checks TAVILY_API_KEY — it is missing from environment. Agent stops immediately at Step 1. Tells the user: 'TAVILY_API_KEY is required. Get it at app.tavily.com. Add it to your .env file.' Does not run any searches or generate any content.",
|
|
20
|
+
"files": []
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": 4,
|
|
24
|
+
"prompt": "Prepare a brief for Vercel and save it to Notion. Meeting is April 20.",
|
|
25
|
+
"expected_output": "Agent runs full research workflow. Produces brief. Asks: 'Save this brief to Notion?' On user confirmation, writes payload to /tmp/notion-brief-payload.json and POSTs to https://api.notion.com/v1/pages with Authorization header, Notion-Version header, parent database_id, title property 'Meeting Brief: Vercel — 2026-04-20', and brief content as paragraph blocks. Reports 'Brief saved to Notion.' If NOTION_TOKEN or NOTION_DATABASE_ID are not set, agent skips the Notion prompt and outputs text only.",
|
|
26
|
+
"files": []
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": 5,
|
|
30
|
+
"prompt": "Prepare a brief for a company called NicheStartupXYZ123. Meeting is April 22.",
|
|
31
|
+
"expected_output": "Agent runs all 6 Tavily searches. Most return 0 or very low-score results. Agent does not invent content for empty sections. Company Snapshot reads what was found or 'Limited public information found.' Recent News reads 'No news found in the last 30 days.' Tech Stack Signals reads 'No public tech stack data found.' Talking points are based only on what search results returned. Brief is still presented (not aborted). Agent does not apologize or over-explain the lack of data.",
|
|
32
|
+
"files": []
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Brief Format Guide
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
A meeting brief gives you the 3 minutes of research that makes a 30-minute call feel like you have been following this company for months. It is a reference document, not a report. Every section answers one question a prepared seller asks before a call.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Structure (fixed, one template)
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
# Meeting Brief: {Company} — {Date}
|
|
13
|
+
|
|
14
|
+
## Company Snapshot
|
|
15
|
+
## Recent News
|
|
16
|
+
## Decision Maker
|
|
17
|
+
## Tech Stack Signals
|
|
18
|
+
## Competitive Context
|
|
19
|
+
## Talking Points
|
|
20
|
+
## Open Questions
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Section Rules
|
|
26
|
+
|
|
27
|
+
### Company Snapshot
|
|
28
|
+
One or two sentences maximum. Cover: what the company does, when it was founded, where it is based, approximate size (employees or revenue range), and funding stage if known. Cite the source URL inline.
|
|
29
|
+
|
|
30
|
+
Do not write a paragraph. One sentence per data point is enough.
|
|
31
|
+
|
|
32
|
+
Example:
|
|
33
|
+
- Acme Corp builds developer tooling for Kubernetes observability, founded 2019, 120 employees, Series B ($28M, Bessemer, 2024). [Source](https://example.com)
|
|
34
|
+
|
|
35
|
+
### Recent News
|
|
36
|
+
Last 30 days only. Three bullets maximum. Each bullet states the event and why it matters for the call.
|
|
37
|
+
|
|
38
|
+
Format: `[Event]. Source: [URL]`
|
|
39
|
+
|
|
40
|
+
Skip this section entirely if no news was found in the last 30 days. Write "No news found in the last 30 days."
|
|
41
|
+
|
|
42
|
+
Do not include news older than 30 days unless it is a major funding round within the last 90 days.
|
|
43
|
+
|
|
44
|
+
### Decision Maker
|
|
45
|
+
Name, title, tenure at the company, and one notable background fact (prior company, published work, area of focus). Cite sources.
|
|
46
|
+
|
|
47
|
+
If no contact was provided: write "Not specified."
|
|
48
|
+
|
|
49
|
+
Do not speculate about seniority or buying authority. Only state what research confirms.
|
|
50
|
+
|
|
51
|
+
### Tech Stack Signals
|
|
52
|
+
Bullet list of tools, platforms, or infrastructure visible from public sources (job postings, engineering blog, GitHub, BuiltWith-style data). Each bullet names the tool and where it was spotted.
|
|
53
|
+
|
|
54
|
+
Format: `{Tool} — spotted in {job posting / engineering blog / GitHub}`
|
|
55
|
+
|
|
56
|
+
If nothing was found: "No public tech stack data found."
|
|
57
|
+
|
|
58
|
+
### Competitive Context
|
|
59
|
+
Two to four bullets. Name the competitors and state one observable differentiator or weakness per competitor. Use research data, not assumptions.
|
|
60
|
+
|
|
61
|
+
Format: `vs. {Competitor}: {one observable difference}`
|
|
62
|
+
|
|
63
|
+
### Talking Points
|
|
64
|
+
Three to five bullets. Each follows this exact formula from the GTM playbook:
|
|
65
|
+
|
|
66
|
+
`Because [specific finding from research], mention [your point] to [goal for the conversation].`
|
|
67
|
+
|
|
68
|
+
Every talking point must trace to a specific Tavily result. Do not write a talking point without a "Because" clause grounded in research.
|
|
69
|
+
|
|
70
|
+
Examples:
|
|
71
|
+
- Because Acme raised a Series B in January and posted 12 backend engineering roles, mention your enterprise onboarding package to understand their scaling timeline.
|
|
72
|
+
- Because their engineering blog mentions a migration from monolith to microservices, mention your observability tooling to open a conversation about their infra complexity.
|
|
73
|
+
|
|
74
|
+
### Open Questions
|
|
75
|
+
Two to three questions specific to this company's situation. They should open discovery, not pitch. Generic questions ("What are your goals?") are not acceptable here.
|
|
76
|
+
|
|
77
|
+
Format: `{Question} (based on {finding})`
|
|
78
|
+
|
|
79
|
+
Examples:
|
|
80
|
+
- With the recent Series B, what is the 12-month engineering headcount plan? (based on 12 open backend roles)
|
|
81
|
+
- The engineering blog mentions moving to microservices last year. How is observability handled across services currently? (based on engineering blog post)
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Length and Format Rules
|
|
86
|
+
|
|
87
|
+
- Under 400 words total
|
|
88
|
+
- No paragraphs in the brief body (bullets and one-liners only)
|
|
89
|
+
- No em dashes anywhere
|
|
90
|
+
- No banned words: incredible, amazing, leveraging, game-changing, groundbreaking, pivotal, utilize, disruptive, transformative, unlock, seamless, robust
|
|
91
|
+
- Every claim has a source URL
|
|
92
|
+
- Sections with no data say "Limited public information found" or "Not specified" (never leave blank)
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Citation Rule
|
|
97
|
+
|
|
98
|
+
Every data point must be followed by a source URL in parentheses or as a markdown link. This is non-negotiable. If you cannot cite it, do not include it.
|
|
99
|
+
|
|
100
|
+
Acceptable: `120 employees ([LinkedIn](https://linkedin.com/company/acme))`
|
|
101
|
+
Not acceptable: `approximately 100-150 employees`
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Validation Checklist
|
|
106
|
+
|
|
107
|
+
- [ ] Under 400 words
|
|
108
|
+
- [ ] Every section present (or explicitly marked as "Not found")
|
|
109
|
+
- [ ] No em dashes
|
|
110
|
+
- [ ] No banned words
|
|
111
|
+
- [ ] Every claim has a source URL
|
|
112
|
+
- [ ] Talking points use "Because/mention/to" formula
|
|
113
|
+
- [ ] Open questions are company-specific, not generic
|
|
114
|
+
- [ ] Decision Maker section says "Not specified" if no contact provided
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Output Template
|
|
2
|
+
|
|
3
|
+
One template. The brief format is fixed. Replace every [BRACKETED SLOT] with content from Tavily results. Never leave bracket text in the output. Skip a slot with "Limited public information found" if no data exists for it.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Template
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
# Meeting Brief: [COMPANY NAME] — [MEETING DATE]
|
|
11
|
+
|
|
12
|
+
Meeting type: [MEETING TYPE or "Not specified"]
|
|
13
|
+
Contact: [CONTACT NAME, TITLE or "Not specified"]
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Company Snapshot
|
|
18
|
+
|
|
19
|
+
[One sentence: what the company does, founded year, HQ, size, funding stage. Source URL in parentheses.]
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Recent News
|
|
24
|
+
|
|
25
|
+
[Bullet 1: Event + why it matters for the call. Source URL.]
|
|
26
|
+
[Bullet 2: Event + why it matters. Source URL.]
|
|
27
|
+
[Bullet 3: Event + why it matters. Source URL.]
|
|
28
|
+
|
|
29
|
+
(If no news found in the last 30 days, write: "No news found in the last 30 days.")
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Decision Maker
|
|
34
|
+
|
|
35
|
+
[NAME]: [Title], [tenure at company]. [One background fact: prior company, area of focus, or notable work]. ([Source URL])
|
|
36
|
+
|
|
37
|
+
(If no contact provided, write: "Not specified.")
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Tech Stack Signals
|
|
42
|
+
|
|
43
|
+
- [Tool or platform] — spotted in [source: job posting / engineering blog / GitHub / BuiltWith] ([URL])
|
|
44
|
+
- [Tool or platform] — spotted in [source] ([URL])
|
|
45
|
+
|
|
46
|
+
(If nothing found, write: "No public tech stack data found.")
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Competitive Context
|
|
51
|
+
|
|
52
|
+
- vs. [Competitor 1]: [One observable difference or weakness] ([URL])
|
|
53
|
+
- vs. [Competitor 2]: [One observable difference] ([URL])
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Talking Points
|
|
58
|
+
|
|
59
|
+
- Because [specific finding from research], mention [your point] to [goal for the conversation].
|
|
60
|
+
- Because [specific finding], mention [point] to [goal].
|
|
61
|
+
- Because [specific finding], mention [point] to [goal].
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Open Questions
|
|
66
|
+
|
|
67
|
+
- [Question specific to this company]? (based on [finding and source])
|
|
68
|
+
- [Question specific to this company]? (based on [finding and source])
|
|
69
|
+
- [Question specific to this company]? (based on [finding and source])
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Worked Example
|
|
75
|
+
|
|
76
|
+
Company: Acme Corp (acmecorp.io)
|
|
77
|
+
Contact: Jordan Lee, VP Engineering
|
|
78
|
+
Meeting date: 2026-04-15
|
|
79
|
+
Meeting type: Discovery
|
|
80
|
+
|
|
81
|
+
```markdown
|
|
82
|
+
# Meeting Brief: Acme Corp — 2026-04-15
|
|
83
|
+
|
|
84
|
+
Meeting type: Discovery
|
|
85
|
+
Contact: Jordan Lee, VP Engineering
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Company Snapshot
|
|
90
|
+
|
|
91
|
+
Acme Corp builds Kubernetes observability tooling for platform engineering teams, founded 2019, headquartered in San Francisco, 120 employees, Series B ($28M led by Bessemer Venture Partners, January 2026). ([TechCrunch](https://techcrunch.com/acme-series-b))
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Recent News
|
|
96
|
+
|
|
97
|
+
- Raised $28M Series B in January 2026 to expand enterprise sales and double engineering headcount. ([TechCrunch](https://techcrunch.com/acme-series-b))
|
|
98
|
+
- Posted 12 backend engineering roles focused on Go and distributed systems in March 2026. ([Acme Careers](https://acmecorp.io/careers))
|
|
99
|
+
- Published an engineering blog post on migrating their internal monolith to microservices. ([Acme Blog](https://acmecorp.io/blog/microservices))
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Decision Maker
|
|
104
|
+
|
|
105
|
+
Jordan Lee: VP Engineering, joined Acme Corp in 2023. Previously Staff Engineer at Datadog for 4 years, focused on metrics ingestion pipelines. Active on LinkedIn writing about platform engineering and internal developer platforms. ([LinkedIn](https://linkedin.com/in/jordan-lee))
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Tech Stack Signals
|
|
110
|
+
|
|
111
|
+
- Kubernetes — core product is built on top of it; mentioned in all job postings ([Acme Careers](https://acmecorp.io/careers))
|
|
112
|
+
- Go — primary backend language, referenced in 12 open engineering roles ([Acme Careers](https://acmecorp.io/careers))
|
|
113
|
+
- Prometheus — mentioned in engineering blog as current metrics stack ([Acme Blog](https://acmecorp.io/blog/microservices))
|
|
114
|
+
- AWS — referenced in infrastructure job descriptions ([Acme Careers](https://acmecorp.io/careers))
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Competitive Context
|
|
119
|
+
|
|
120
|
+
- vs. Datadog: Acme focuses specifically on Kubernetes-native observability vs Datadog's broader APM suite; Acme markets on lower cost and fewer agents to deploy. ([G2 Comparison](https://g2.com/compare/acme-vs-datadog))
|
|
121
|
+
- vs. Grafana: Grafana requires more manual setup; Acme's value prop is opinionated defaults for platform teams. ([Acme Blog](https://acmecorp.io/blog/vs-grafana))
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Talking Points
|
|
126
|
+
|
|
127
|
+
- Because Acme raised a Series B in January and posted 12 backend engineering roles, mention your enterprise onboarding package to understand their scaling timeline and whether they are building infrastructure ahead of the hire or after.
|
|
128
|
+
- Because their engineering blog describes a recent monolith-to-microservices migration, mention your service mesh observability features to open a conversation about how they are currently tracking latency across services.
|
|
129
|
+
- Because Jordan Lee previously worked at Datadog, mention your pricing model comparison to acknowledge they have deep familiarity with enterprise observability tooling and will ask sharp questions about cost.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Open Questions
|
|
134
|
+
|
|
135
|
+
- With 12 open backend roles and a Series B closed in January, what does the engineering headcount look like 12 months from now? (based on Acme Careers page and TechCrunch funding report)
|
|
136
|
+
- The engineering blog mentions the microservices migration is ongoing. How are service-to-service latency and error rates currently tracked? (based on Acme Blog post on microservices)
|
|
137
|
+
- Jordan came from Datadog. What gaps in the current observability setup prompted the search for a new tool? (based on LinkedIn profile and Acme's founding story)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Fill-In Rules
|
|
143
|
+
|
|
144
|
+
1. Replace every [BRACKETED SLOT] with content from Tavily results
|
|
145
|
+
2. Never leave bracket text in the output
|
|
146
|
+
3. Source every claim with a URL in parentheses
|
|
147
|
+
4. Skip sections with no data using "Limited public information found" or "Not specified"
|
|
148
|
+
5. Talking points must follow the "Because/mention/to" formula exactly
|
|
149
|
+
6. Open questions must reference a specific finding in parentheses
|
|
150
|
+
7. Word count must stay under 400 words
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Meta Ads Agentic Skill
|
|
2
|
+
|
|
3
|
+
<img width="1376" height="768" alt="meta-ads-skill" src="https://github.com/user-attachments/assets/baf2509b-0ee0-41ca-9555-3ad350a6824c" />
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The **Meta Ads Skill** is a comprehensive, production-ready OpenCode skill designed to give LLMs and AI agents expert-level capabilities to orchestrate the [Varnan-Tech Meta Ads MCP Server](https://github.com/Varnan-Tech/Meta-Ads-MCP).
|
|
8
|
+
|
|
9
|
+
By using this skill, an agent transforms into an **Expert Media Buyer**. It will know exactly how to safely authenticate, explore ad structures, troubleshoot campaign performance (like CPA spikes), discover new audiences, and format massive Meta APIs JSON payloads into beautiful, readable markdown reports.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## For Agents: How to Use This Skill Efficiently
|
|
14
|
+
|
|
15
|
+
This skill is designed using a **Progressive Disclosure (Hub-and-Spoke)** architecture to maximize context window efficiency:
|
|
16
|
+
|
|
17
|
+
1. **The Hub (`SKILL.md`)**: The primary entry point. It provides strict guardrails, safety protocols, and the authentication troubleshooting workflow.
|
|
18
|
+
2. **The Spokes (`references/` & `scripts/`)**:
|
|
19
|
+
- When you need to perform a specific task (e.g., investigating a CPA spike), read `references/workflows.md` for the exact step-by-step orchestration strategy.
|
|
20
|
+
- When presenting data to the user, read `references/report_templates.md` to strictly follow the required Markdown layout.
|
|
21
|
+
- **Data Parsing**: Meta Ads JSON responses are massive. *Always* use the provided `scripts/formatters.py` to condense raw JSON from `get_campaigns`, `get_adsets`, or `get_insights` into clean markdown tables before reasoning over them.
|
|
22
|
+
|
|
23
|
+
### Strict Agent Guardrails
|
|
24
|
+
* **Context Protection**: ALWAYS default to `time_range="last_7d"` for insights. ALWAYS use `limit=10` for listing campaigns/adsets initially.
|
|
25
|
+
* **Safety First**: NEVER execute state-changing tools (`create_campaign`, `update_campaign`, `clear_database`, `reset_database`) without explicitly showing the parameters to the user and waiting for their affirmative confirmation.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Installation & Setup of the Meta Ads MCP
|
|
30
|
+
|
|
31
|
+
To use this skill, the host machine must have the Varnan-Tech Meta Ads MCP Server installed and running.
|
|
32
|
+
|
|
33
|
+
### 1. Prerequisites
|
|
34
|
+
- **Python 3.10+**
|
|
35
|
+
- A **Meta Developer Account** with a configured App.
|
|
36
|
+
|
|
37
|
+
### 2. Configure the Meta App
|
|
38
|
+
1. Go to the [Facebook Developers Portal](https://developers.facebook.com/).
|
|
39
|
+
2. Create an App and add the **Marketing API** product.
|
|
40
|
+
3. Under the Facebook Login settings, add `http://localhost:8000/auth/facebook/callback` to the **Valid OAuth Redirect URIs**.
|
|
41
|
+
4. Retrieve your **App ID** and **App Secret**.
|
|
42
|
+
|
|
43
|
+
### 3. Server Setup
|
|
44
|
+
Clone the MCP repository:
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/Varnan-Tech/Meta-Ads-MCP.git
|
|
47
|
+
cd Meta-Ads-MCP
|
|
48
|
+
pip install -r requirements.txt
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Create a `.env` file in the root of the MCP server:
|
|
52
|
+
```env
|
|
53
|
+
FB_APP_ID="your_facebook_app_id"
|
|
54
|
+
FB_APP_SECRET="your_facebook_app_secret"
|
|
55
|
+
FB_OAUTH_ENABLED="true"
|
|
56
|
+
FB_REDIRECT_URI="http://localhost:8000/auth/facebook/callback"
|
|
57
|
+
DATABASE_URL="sqlite:///.meta-ads-mcp/oauth.db"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Authentication Workflow
|
|
63
|
+
|
|
64
|
+
The server uses OAuth backed by a local SQLite database to seamlessly pass tokens to the MCP context.
|
|
65
|
+
|
|
66
|
+
1. **Start the local Auth Server**:
|
|
67
|
+
```bash
|
|
68
|
+
python src/auth/run_web_server.py
|
|
69
|
+
```
|
|
70
|
+
2. **Authenticate**: Open `http://localhost:8000/auth/facebook` in your web browser.
|
|
71
|
+
3. **Grant Permissions**: Click "Connect Facebook" and approve the `ads_management`, `ads_read`, and `read_insights` permissions.
|
|
72
|
+
4. **Completion**: The OAuth token is saved securely to the SQLite DB. The agent can now use the MCP tools automatically without needing the token pasted into the prompt.
|
|
73
|
+
|
|
74
|
+
*If an agent encounters an Auth Error during operation, it is instructed by this skill to guide the user back through this exact login flow.*
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Skill Repository Structure
|
|
79
|
+
|
|
80
|
+
When you deploy this skill, the structure will look like this:
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
meta-ads-skill/
|
|
84
|
+
SKILL.md # The core router & guardrails
|
|
85
|
+
references/
|
|
86
|
+
report_templates.md # Standardized markdown report structures
|
|
87
|
+
workflows.md # Orchestration strategies (e.g., CPA troubleshooting)
|
|
88
|
+
scripts/
|
|
89
|
+
auth_check.py # Diagnostic script for token status
|
|
90
|
+
formatters.py # JSON -> Markdown table utilities
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Supported Tools (via MCP)
|
|
94
|
+
|
|
95
|
+
Through the underlying MCP, this skill orchestrates:
|
|
96
|
+
* **Account Management**: `get_ad_accounts()`, `get_account_info()`
|
|
97
|
+
* **Campaigns & Ads**: `get_campaigns()`, `get_adsets()`, `get_ads()`, `create_campaign()`, `update_campaign()`
|
|
98
|
+
* **Analytics**: `get_insights()`, `analyze_campaigns()`
|
|
99
|
+
* **Targeting**: `search_interests()`, `search_demographics()`, `estimate_audience_size()`
|
|
100
|
+
* **Database**: `token_status()`, `clear_database()`, `reset_database()`
|