Skip to main content
Navigation

guides

Writing Proposal Prompts

How Prompt Templates Work

Prospector generates proposal drafts by sending a prompt to an AI model. That prompt is assembled from a template you write plus context data from the lead (job description, client history, your profile, score breakdown). Your template defines the structure, tone, and strategy of the proposal. The AI fills in the specifics.

Templates are stored as files in ~/.ghoststack/prospector/templates/. Each template is a Markdown file with YAML frontmatter for metadata and a body that contains the prompt text with variable placeholders.

Template Structure

---
name: 'default'
match_skills: []
match_job_type: ['fixed', 'hourly']
priority: 0
---

Write a proposal for the following freelance job posting.

**Job title**: {{job.title}}
**Job description**: {{job.description}}
**Required skills**: {{job.skills | join(", ")}}
**Budget**: {{job.budget.amount}} {{job.budget.currency}} ({{job.budget.type}})
**Client history**: {{client.total_spend}} spent, {{client.rating}} avg rating, {{client.hires}} past hires

**My relevant skills**: {{profile.skills | intersect(job.skills) | join(", ")}}
**My experience summary**: {{profile.experience}}

Write a concise, professional proposal (150-250 words) that:

1. Opens with a specific observation about the project, not a generic greeting
2. Connects my skills directly to their requirements
3. Mentions a relevant past project if one exists in my portfolio
4. Proposes a clear next step
5. Ends naturally without a formulaic closing

Tone: direct and confident, not salesy. Do not use phrases like "I am excited to apply" or "I believe I am the perfect fit."

Variable Reference

Templates use double-brace syntax for variable interpolation. Available variables:

VariableTypeDescription
job.titlestringJob posting title
job.descriptionstringFull job description text
job.skillsstring[]Required skills listed on the job
job.budget.amountnumberBudget amount
job.budget.typestring”fixed” or “hourly”
job.budget.currencystringCurrency code (e.g., “USD”)
job.durationstringExpected project duration
client.total_spendnumberClient’s total platform spend
client.ratingnumberClient’s average rating
client.hiresnumberNumber of past hires
client.previous_contractsnumberYour past contracts with this client
profile.skillsstring[]Your configured skills
profile.experiencestringYour experience summary
profile.portfolioobject[]Your portfolio items
score.compositenumberLead’s overall score
score.signals.*numberIndividual signal scores

Filters

Variables support filters using the pipe (|) syntax:

  • join(separator) - joins arrays into a string
  • intersect(other_array) - returns common elements between two arrays
  • truncate(length) - truncates text to a maximum character count
  • lowercase / uppercase - case conversion
  • default(value) - fallback if the variable is null or empty

Multiple Templates

You can create specialized templates for different job types. Prospector selects the best-matching template based on match_skills and match_job_type in the frontmatter. Templates with higher priority values are preferred when multiple templates match.

~/.ghoststack/prospector/templates/
  default.md          # priority: 0, matches everything
  react-project.md    # priority: 10, match_skills: ["react", "next.js"]
  api-backend.md      # priority: 10, match_skills: ["node.js", "postgresql"]
  quick-fix.md        # priority: 5, match_job_type: ["fixed"], budget < $500

When a lead’s required skills overlap with a template’s match_skills, that template wins over the default. If multiple specialized templates match, the one with the highest priority is selected.

Writing Better Prompts

The quality of your proposals depends heavily on how well you write your prompt templates. A few guidelines based on what produces good results:

Be specific about structure. Tell the AI exactly how many words you want, what sections to include, and what order. Vague instructions like “write a good proposal” produce generic output.

Specify what to avoid. AI models default to enthusiastic, salesy language unless you tell them not to. Explicitly list phrases and patterns you do not want.

Use score data strategically. Your template has access to the lead’s score breakdown. You can instruct the AI to emphasize your strongest match areas: “If skill_match is above 80, lead with technical expertise. If client_history shows repeat client, reference our previous work.”

Test with real leads. After writing a template, generate drafts for 5-10 recent leads and review them. Look for patterns: if every draft opens the same way, your template is too rigid. If drafts miss important project details, your context assembly might need adjustment.

# Generate a draft without submitting it
ghoststack prospector proposals draft <lead-id> --template react-project --dry-run

Template Versioning

Prospector tracks which template version generated each proposal. When you edit a template, the previous version is preserved so you can compare proposal quality before and after changes. Use the proposals history command to review how template changes affected your win rate over time.