outreach.draft
Generate a platform-specific outreach draft for a lead by analyzing their post and selecting the right engagement action—comment, reply, or DM—to produce a tailored message ready to paste.
Instructions
Generate a platform-tuned outreach message for a specific lead the user wants to engage. Behavior: hits the draft-outreach edge function which uses an LLM with platform-specific tone profiles (Reddit paragraph, X 280-char reply, YouTube comment, TikTok DM, Instagram caption). Persists nothing. Consumes one credit per draft. Each call is independent; the drafter does not remember previous drafts. Usage: call this once per lead the user picked from a leads.find result. Pick the right outreach_action for the situation: 'comment_post' for a top-level reply on a thread, 'reply_comment' to respond to a specific comment (provide reply_to_author + reply_to_text), 'dm' or 'dm_post_author' for a DM, 'channel_about' for a YouTube About-tab cold intro, 'profile_check' for stale posts where you want a follow-up rather than a direct reply. Do NOT call outreach.draft for COMPETITOR-flagged leads (their matched_signals contains 'category:COMPETITOR') as outreach to a competitor's content is bad form. Do NOT use it to write generic copy unrelated to a specific post. Returns: { draft } as a single string ready to paste, no surrounding chrome.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| idea | Yes | The refined product idea (used as the writer's voice) | |
| source | Yes | Which platform the lead is on | |
| outreach_action | Yes | How to engage. dm/dm_post_author for DMs, comment_post for top-level comments, reply_comment to respond to a specific thread comment, channel_about for YouTube About-tab contact, profile_check for stale posts. | |
| post_title | Yes | Title of the lead post | |
| post_body | Yes | Body / snippet of the lead post | |
| post_handle | No | OP handle (e.g. 'u/founder', '@user'). Optional but improves drafts. | |
| language | No | Output language. Defaults to 'en'. | |
| reply_to_author | No | For reply_comment: the author of the comment being replied to. | |
| reply_to_text | No | For reply_comment: the comment text being replied to. |
Implementation Reference
- src/index.ts:632-671 (schema)Zod schema defining the input parameters for outreach.draft: idea, source (platform enum), outreach_action, post_title, post_body, post_handle, language, reply_to_author, reply_to_text.
{ idea: z .string() .describe("The refined product idea (used as the writer's voice)"), source: z .enum(["reddit", "x", "twitter", "youtube", "tiktok", "instagram"]) .describe("Which platform the lead is on"), outreach_action: z .enum([ "reply_comment", "comment_post", "reply", "comment", "dm", "dm_post_author", "channel_about", "profile_check", ]) .describe( "How to engage. dm/dm_post_author for DMs, comment_post for top-level comments, reply_comment to respond to a specific thread comment, channel_about for YouTube About-tab contact, profile_check for stale posts.", ), post_title: z.string().describe("Title of the lead post"), post_body: z.string().describe("Body / snippet of the lead post"), post_handle: z .string() .optional() .describe("OP handle (e.g. 'u/founder', '@user'). Optional but improves drafts."), language: z .enum(["en", "pt"]) .optional() .describe("Output language. Defaults to 'en'."), reply_to_author: z .string() .optional() .describe("For reply_comment: the author of the comment being replied to."), reply_to_text: z .string() .optional() .describe("For reply_comment: the comment text being replied to."), }, - src/index.ts:629-725 (registration)Registration of the 'outreach.draft' tool via server.tool(...) with its description, schema, and metadata hints.
server.tool( "outreach.draft", "Generate a platform-tuned outreach message for a specific lead the user wants to engage. Behavior: hits the draft-outreach edge function which uses an LLM with platform-specific tone profiles (Reddit paragraph, X 280-char reply, YouTube comment, TikTok DM, Instagram caption). Persists nothing. Consumes one credit per draft. Each call is independent; the drafter does not remember previous drafts. Usage: call this once per lead the user picked from a leads.find result. Pick the right outreach_action for the situation: 'comment_post' for a top-level reply on a thread, 'reply_comment' to respond to a specific comment (provide reply_to_author + reply_to_text), 'dm' or 'dm_post_author' for a DM, 'channel_about' for a YouTube About-tab cold intro, 'profile_check' for stale posts where you want a follow-up rather than a direct reply. Do NOT call outreach.draft for COMPETITOR-flagged leads (their matched_signals contains 'category:COMPETITOR') as outreach to a competitor's content is bad form. Do NOT use it to write generic copy unrelated to a specific post. Returns: { draft } as a single string ready to paste, no surrounding chrome.", { idea: z .string() .describe("The refined product idea (used as the writer's voice)"), source: z .enum(["reddit", "x", "twitter", "youtube", "tiktok", "instagram"]) .describe("Which platform the lead is on"), outreach_action: z .enum([ "reply_comment", "comment_post", "reply", "comment", "dm", "dm_post_author", "channel_about", "profile_check", ]) .describe( "How to engage. dm/dm_post_author for DMs, comment_post for top-level comments, reply_comment to respond to a specific thread comment, channel_about for YouTube About-tab contact, profile_check for stale posts.", ), post_title: z.string().describe("Title of the lead post"), post_body: z.string().describe("Body / snippet of the lead post"), post_handle: z .string() .optional() .describe("OP handle (e.g. 'u/founder', '@user'). Optional but improves drafts."), language: z .enum(["en", "pt"]) .optional() .describe("Output language. Defaults to 'en'."), reply_to_author: z .string() .optional() .describe("For reply_comment: the author of the comment being replied to."), reply_to_text: z .string() .optional() .describe("For reply_comment: the comment text being replied to."), }, { title: "Draft outreach", readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: true, }, async ({ idea, source, outreach_action, post_title, post_body, post_handle, language, reply_to_author, reply_to_text, }) => { const err = requireKey(); if (err) return err; const fallbackLanguage = GORILLA_DEFAULT_LANGUAGE === "pt" ? "pt" : "en"; const body: Record<string, unknown> = { idea, language: language ?? fallbackLanguage, source, outreach_action, post: { title: post_title, body: post_body, ...(post_handle ? { handle: post_handle } : {}), }, }; if (reply_to_author && reply_to_text) { body.reply_to_comment = { author: reply_to_author, text: reply_to_text }; } const { draft } = await call<{ draft: string }>( "POST", "draft-outreach", body, ); return { content: [ { type: "text" as const, text: draft, }, ], }; }, ); - src/index.ts:679-724 (handler)Async handler function for outreach.draft: constructs the request body, calls the 'draft-outreach' API endpoint via the call() helper, and returns the draft text.
async ({ idea, source, outreach_action, post_title, post_body, post_handle, language, reply_to_author, reply_to_text, }) => { const err = requireKey(); if (err) return err; const fallbackLanguage = GORILLA_DEFAULT_LANGUAGE === "pt" ? "pt" : "en"; const body: Record<string, unknown> = { idea, language: language ?? fallbackLanguage, source, outreach_action, post: { title: post_title, body: post_body, ...(post_handle ? { handle: post_handle } : {}), }, }; if (reply_to_author && reply_to_text) { body.reply_to_comment = { author: reply_to_author, text: reply_to_text }; } const { draft } = await call<{ draft: string }>( "POST", "draft-outreach", body, ); return { content: [ { type: "text" as const, text: draft, }, ], }; }, - src/index.ts:91-113 (helper)Generic HTTP call helper used by the handler to POST to the 'draft-outreach' endpoint with auth headers.
async function call<T>( method: "GET" | "POST" | "DELETE", endpoint: string, body?: unknown ): Promise<T> { const cfg = await getConfig(); const res = await fetch(`${cfg.api_base}/${endpoint}`, { method, headers: { "Content-Type": "application/json", "x-api-key": GORILLA_API_KEY, apikey: cfg.gateway_key, }, ...(body !== undefined ? { body: JSON.stringify(body) } : {}), }); if (!res.ok) { const text = await res.text().catch(() => ""); throw new Error(`${method} /${endpoint} failed (${res.status}): ${text}`); } return res.json() as Promise<T>; } - src/index.ts:27-29 (helper)Configuration of GORILLA_DEFAULT_LANGUAGE used as fallback language in outreach.draft when not provided.
// Optional: default language used as fallback in idea.refine and outreach.draft // when the caller doesn't pass `language`. Accepts "en", "pt", or "all". const GORILLA_DEFAULT_LANGUAGE = process.env.GORILLA_DEFAULT_LANGUAGE ?? "";