Proposal Tools
Proposals model prospective work before it exists as a project — staffing lines, vendor commitments, live costing against a target efficiency ratio, and a capacity simulation for whether the team can actually take the work on. A proposal never touches operational reporting: it's excluded from every dashboard, forecast, and reminder VERA sends. It becomes real only when it's converted to a project, which is the first moment it appears anywhere else.
All proposal tools are Owner/Admin only and console-only — not reachable from Slack; use the web console.
create_proposal
Start a new proposal.
Console-only — not reachable from Slack; use the web console.
Writes to: proposals
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
name | ✅ | |
prospect_name | The prospective client's name | |
project_type | "T&M" | "Fixed Price" | "Pro Bono" | "Internal" — defaults to "Fixed Price" | |
contract_value | ||
target_ler | Target labor efficiency ratio for this proposal; falls back to the tenant's standard target when omitted | |
hours_budget | ||
deadline | YYYY-MM-DD | |
notes |
New proposals start as draft. A proposal is created and edited entirely apart from VERA's operational data — nothing here is joined into any project, financial, or capacity report until it's converted.
list_proposals
List proposals.
Reads from: proposals
Parameters:
| Param | Description |
|---|---|
requesting_user_slack_id | |
status | Optional filter: "draft" | "won" | "lost" | "converted" |
update_proposal
Update one or more fields on a proposal.
Console-only — not reachable from Slack; use the web console.
Updates: proposals
Parameters: requesting_user_slack_id, id, and any of name, prospect_name, project_type, contract_value, target_ler, hours_budget, status, notes, deadline
A proposal that is closed — status is "won" or "lost", or it has already been converted to a project — can no longer be edited.
delete_proposal
Permanently delete a proposal. Proposals are speculative, so this is a hard delete, not an archive.
Console-only — not reachable from Slack; use the web console.
Deletes from: proposals
Parameters: requesting_user_slack_id, id
A proposal that has already been converted to a project cannot be deleted — once real work exists downstream of it, the proposal record stays as the paper trail.
create_proposal_role
Add a staffing line to a proposal — a discipline and/or a specific person, with planned hours and (for T&M) a proposed billing rate.
Console-only — not reachable from Slack; use the web console.
Writes to: proposal staffing lines
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
proposal_id | ✅ | |
discipline_id | ||
user_id | A specific person, if the line is pinned to one | |
planned_hours | ||
billing_rate | For T&M proposals | |
task | ||
start_date | Staffing-line window start, YYYY-MM-DD. Both-or-neither with end_date. | |
end_date | Staffing-line window end, YYYY-MM-DD. | |
week_hours | How the line's planned hours land across the weeks of its window — array of { week, hours }. Requires a window; the sum can't exceed planned_hours. |
Costing precedence for an unrated line follows the same order get_proposal_costing uses: the pinned person's own rate, then the discipline's blended rate, then the agency's blended rate.
update_proposal_role
Update a staffing line.
Console-only — not reachable from Slack; use the web console.
Updates: proposal staffing lines
Parameters: requesting_user_slack_id, id, and any of discipline_id, user_id, planned_hours, billing_rate, task
Window and shape (presence-based, same rules as an allocation envelope): start_date/end_date are both-or-neither — omit both to leave the window untouched, send both to set or replace it, send both empty to clear it. week_hours is presence-based too — omitted leaves the shape untouched, an empty array clears it, a non-empty array is validated (every week a Monday inside the window, sum capped at planned_hours) and written. week_hours requires the line to already have a window.
Refused on a closed proposal (status won, lost, or already converted).
delete_proposal_role
Remove a staffing line from a proposal.
Console-only — not reachable from Slack; use the web console.
Deletes from: proposal staffing lines
Parameters: requesting_user_slack_id, id
Refused on a closed proposal.
create_proposal_liability
Add a vendor commitment to a proposal — a fixed-fee line for work the agency plans to outsource rather than staff internally.
Console-only — not reachable from Slack; use the web console.
Writes to: proposal vendor commitments
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
proposal_id | ✅ | |
vendor_user_id | ✅ | Must be an existing user with the vendor employment type |
description | ✅ | |
agreed_amount | ✅ | Positive number |
agreed_hours |
The vendor must already exist as a user before it can be committed on a proposal — a new vendor is onboarded on the Users page first.
Refused on a closed proposal.
update_proposal_liability
Update a vendor commitment on a proposal.
Console-only — not reachable from Slack; use the web console.
Updates: proposal vendor commitments
Parameters: requesting_user_slack_id, id, and any of vendor_user_id, description, agreed_amount, agreed_hours
Refused on a closed proposal.
delete_proposal_liability
Remove a vendor commitment from a proposal.
Console-only — not reachable from Slack; use the web console.
Deletes from: proposal vendor commitments
Parameters: requesting_user_slack_id, id
Refused on a closed proposal.
get_proposal_costing
Live costing snapshot for a proposal — every staffing line and vendor commitment, each cost-rated, plus the resulting P&L.
Reads from: proposals, proposal staffing lines, proposal vendor commitments
Parameters: requesting_user_slack_id, proposal_id
Returns: the proposal; each staffing line annotated with its resolved cost_rate and rate_source ("person" | "discipline" | "agency"); the vendor commitments; and a pnl object with revenue, cost, profit, ler, margin_pct, target_ler, people_budget (revenue ÷ target LER), over_budget, total_hours, committed_envelope, committed_liability, and vendor_hours.
Revenue is the sum of each staffing line's hours × its proposed billing rate for a T&M proposal, or the proposal's contract value otherwise (Pro Bono and Internal naturally price at $0). This is a read-only computation — nothing here writes anything.