Subchapter 8.4
references/workflow.mdMarkdown11 KBView on GitHub
File: /tmp/company_discovery_batch_{N}.json
browse cloud search --output writes a JSON object (NOT a flat array):
{
"requestId": "abc123",
"query": "AI data extraction startups",
"results": [
{ "url": "https://example.com", "title": "Example Corp", "author": null, "publishedDate": null },
...
]
}The list_urls.mjs script handles both formats (flat array and { results: [...] }).
File: {OUTPUT_DIR}/{company-slug}.md
Where {OUTPUT_DIR} is the per-run directory on the user’s Desktop (e.g., ~/Desktop/acme_research_2026-04-23/). The main agent sets this up in Step 0 and passes the full literal path to every subagent.
Each research subagent writes one markdown file per company. See references/example-research.md for the full template.
YAML frontmatter fields (used for report + CSV compilation):
company_name (required)website (required)product_descriptionindustrytarget_audiencekey_features (pipe-separated: feature1 | feature2 | feature3)icp_fit_score (integer 1-10, required)icp_fit_reasoningemployee_estimatefunding_infoheadquartersBody sections:
## Product — what they do## Research Findings — evidence with confidence levels and sourcesCRITICAL: Use consistent field names across all files. The compile_report.mjs script reads these fields.
Use extract_page.mjs for all homepage/product-page content extraction. It fetches via browse cloud fetch --output, parses title + meta + visible body text, and falls back to browse get markdown automatically when fetch fails or returns thin JS-rendered content:
node {SKILL_DIR}/scripts/extract_page.mjs "https://example.com" --max-chars 3000Output is a structured block:
URL: https://example.com
FETCH_OK: true|false
FALLBACK_TO_BROWSE: true|false
TITLE: ...
META_DESCRIPTION: ...
OG_TITLE: ...
OG_DESCRIPTION: ...
HEADINGS: h1/h2/h3 joined by " | "
BODY_CHARS: N
BODY:
<cleaned visible text, max N chars>Why not a raw browse cloud fetch | sed pipeline? Without --output, browse cloud fetch returns a JSON envelope with the HTML embedded as an escaped string. A naive sed pipeline strips <> from the wrapper and content, and it removes <meta> tags, which on Framer/Next.js SPAs are often the only readable content. extract_page.mjs uses --output to parse raw HTML directly.
When to use raw browse cloud fetch: Only for small structured files where you want the JSON envelope intact — e.g. sitemap.xml, robots.txt, llms.txt. For any HTML page you’d feed to a model, use extract_page.mjs.
Before writing product_description, industry, or target_audience into a company file, confirm the claim is grounded in extract_page.mjs output. Quote or closely paraphrase from TITLE, META_DESCRIPTION, OG_DESCRIPTION, HEADINGS, or BODY.
If extract_page.mjs returns FETCH_OK: false AND FALLBACK_TO_BROWSE: false (or BODY_CHARS < 50), the homepage is inaccessible. Do not fabricate. Write:
product_description: Unknown — homepage content not accessibleicp_fit_score: 3 (or lower)icp_fit_reasoning: Insufficient evidence — homepage returned no readable contentA classic failure mode this prevents: a Framer/Next.js landing page with no server-rendered copy, where the subagent pattern-matches visual cues (“design-forward”, “Geist Mono”, “Framer-built”) onto the user’s own ICP. Typography is not a product.
You are a company discovery subagent. Run search queries and save results.
TOOL RULES — CRITICAL, FOLLOW EXACTLY:
1. You may ONLY use the Bash tool. No exceptions.
2. Run ALL searches in a SINGLE Bash call using && chaining.
3. BANNED TOOLS: WebFetch, WebSearch, Write, Read, Glob, Grep — ALL BANNED.
If you use ANY banned tool, the entire run fails. Use ONLY Bash.
4. NEVER use ~ or $HOME in paths — use full literal paths.
TASK:
Run ALL of the following searches in ONE Bash command:
browse cloud search "{query1}" --num-results 25 --output /tmp/company_discovery_batch_{N1}.json && \
browse cloud search "{query2}" --num-results 25 --output /tmp/company_discovery_batch_{N2}.json && \
browse cloud search "{query3}" --num-results 25 --output /tmp/company_discovery_batch_{N3}.json && \
echo "Discovery complete"
After the command completes, report back ONLY the count of results found per batch.
Do NOT analyze, summarize, or return the actual results.You are a company research subagent. For each company URL, research the company and score ICP fit.
CONTEXT:
- User's company: {user_company}
- User's product: {user_product}
- ICP description: {icp_description}
- Depth mode: {depth_mode}
- Output directory: {OUTPUT_DIR} ← write research files HERE, as a full literal path
URLS TO PROCESS:
{url_list}
TOOL RULES — CRITICAL, FOLLOW EXACTLY:
1. You may ONLY use the Bash tool. No exceptions.
2. All searches: Bash → browse cloud search "..." --num-results 10
3. All homepage/product-page content extraction:
Bash → node {SKILL_DIR}/scripts/extract_page.mjs "URL" --max-chars 3000
This returns structured TITLE / META_DESCRIPTION / OG_DESCRIPTION / HEADINGS / BODY and auto-falls back to browse get markdown when fetch fails or returns thin JS-rendered content.
DO NOT hand-roll a `browse cloud fetch | sed` pipeline — it strips meta tags and doesn't parse the stdout JSON envelope. Use `browse cloud fetch` raw only for sitemap.xml, robots.txt, llms.txt.
4. BATCH all file writes: Write ALL markdown files in a SINGLE Bash call using chained heredocs (one permission prompt, not one per file).
5. BANNED TOOLS: WebFetch, WebSearch, Write, Read, Glob, Grep — ALL BANNED.
If you use ANY banned tool, the entire run fails. Use ONLY Bash.
6. NEVER use ~ or $HOME in paths — use full literal paths.
ANTI-HALLUCINATION RULES — CRITICAL:
- NEVER infer product_description, industry, or target_audience from fonts, framework (Framer/Next.js/React), design system, or visual style. Typography is not a product.
Launch as many subagents as possible in a single message (up to ~6 Agent tool calls per message). Each subagent MUST batch all its Bash operations to minimize permission prompts.
&& chainingnode {SKILL_DIR}/scripts/list_urls.mjs /tmpquick: ~10 companies per subagentdeep: ~5 companies per subagentdeeper: ~2-3 companies per subagent{OUTPUT_DIR}search_queries = ceil(requested_companies / 35)
discovery_subagents = search_queries
expected_urls = search_queries * 20
quick: research_subagents = ceil(expected_urls / 10)
deep: research_subagents = ceil(expected_urls / 5)
deeper: research_subagents = ceil(expected_urls / 3)extract_page.mjs already handles the browse cloud fetch → browse get markdown fallback internally. If it still returns FETCH_OK: false with empty BODY, skip the company and mark product_description as Unknown (do not guess).After all research subagents complete, compile the HTML report and CSV in one command:
node {SKILL_DIR}/scripts/compile_report.mjs {OUTPUT_DIR} --openThe script:
.md files in {OUTPUT_DIR}{OUTPUT_DIR}/index.html — scored overview page{OUTPUT_DIR}/companies/{slug}.html — one page per company{OUTPUT_DIR}/results.csv — spreadsheet for sheets/CRMindex.html in the default browser (--open flag)