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:
| Variable | Type | Description |
|---|---|---|
job.title | string | Job posting title |
job.description | string | Full job description text |
job.skills | string[] | Required skills listed on the job |
job.budget.amount | number | Budget amount |
job.budget.type | string | ”fixed” or “hourly” |
job.budget.currency | string | Currency code (e.g., “USD”) |
job.duration | string | Expected project duration |
client.total_spend | number | Client’s total platform spend |
client.rating | number | Client’s average rating |
client.hires | number | Number of past hires |
client.previous_contracts | number | Your past contracts with this client |
profile.skills | string[] | Your configured skills |
profile.experience | string | Your experience summary |
profile.portfolio | object[] | Your portfolio items |
score.composite | number | Lead’s overall score |
score.signals.* | number | Individual signal scores |
Filters
Variables support filters using the pipe (|) syntax:
join(separator)- joins arrays into a stringintersect(other_array)- returns common elements between two arraystruncate(length)- truncates text to a maximum character countlowercase/uppercase- case conversiondefault(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.