Project Tools
create_project
Create a new project. Owner only.
Console-only — not reachable from Slack; use the web console.
Writes to: 02. Projects
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
project_name | ✅ | Unique project name |
project_type | ✅ | "Retainer" | "T&M" | "Fixed Price" | "Pro Bono" | "Agile" | "Internal" — never defaulted |
client_name | Cond. | Client org — created automatically if new. Omit for Internal projects — VERA assigns the implicit "Internal" client automatically |
contract_value | Cond. | Required for Fixed Price |
hours_budget | Cond. | Required for Retainer (annual hours). Optional for others. |
billing_rate | Hourly rate billed to client | |
deadline | YYYY-MM-DD | |
notes | ||
project_category | Defaults to "client" |
Rules:
- Never assume a default project type — always ask
client_nameis not required for Internal projects — the Internal client is implicit- Fixed Price requires a positive
contract_value— the endpoint rejects creation with❌ contract_value is required for Fixed Price projectsif it's missing or ≤ 0. Fixed Price revenue is% complete × contract_value, so without it the project would recognize $0 revenue forever. - For Agile parents: no contract_value or hours_budget on the parent itself
- After Agile parent creation, offer to set up Sprint 1
- "Create a retainer" means
create_projectwithproject_type="Retainer"— this tool creates the parent engagement. The first period child is auto-created bycreate_project. Usecreate_retainer_periodonly when adding a new period to an existing retainer parent (e.g. "create the June period for Acme Retainer"). - On creation, the Project Management task is automatically enabled on the new project so it starts with at least one enabled task — you can allocate hours immediately, and use Edit tasks to add more (Design, Development, etc.). If the tenant has archived or renamed its Project Management task, the project is simply created with no default task (no error).
rename_project
Rename a project and update all references. Owner only.
Console-only — not reachable from Slack; use the web console.
Updates: 02. Projects, 01. Time Entries
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
old_name | ✅ | |
new_name | ✅ |
Protected projects: the internal time-off projects PTO, Sick, and Leave can be neither renamed nor cancelled (cancel_project carries the same guard) — both return a 403 ("…is a protected time-off project and cannot be renamed/cancelled") to keep time-off logging intact. Other internal/overhead projects are unaffected.
update_project
Update one or more fields on an existing project. Owner or Manager.
Console-only — not reachable from Slack; use the web console.
Updates: 02. Projects
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
project_name | ✅ | Current project name |
new_name | Rename the project | |
status | active | completed | cancelled | |
is_billable | Boolean | |
alert_threshold | % at which to flag the budget (default 80) | |
notes | Free-text notes | |
deadline | YYYY-MM-DD | |
contract_value | Owner only. Setting this as a Manager returns ❌ Failed: Only owners can change a project's contract_value… | |
billing_rate | Owner only. Same gate as contract_value. | |
hours_budget | Owner only. Same gate as contract_value. |
Role notes:
- Managers can set
new_name,status,is_billable,alert_threshold,notes, anddeadline. contract_value,billing_rate, andhours_budgetare owner-only on write, mirroring the read-side isolation inget_project_info. A manager attempting to set any of these gets a 403.
Deterministic routing (updated #1090): Field-bearing phrasings now route to update_project in the extractor instead of being hijacked by edit_entry or set_rate. The extractor has an update_project entry with object_nouns: ['contract value', 'billing rate', 'status', 'notes', 'billable', 'is billable'].
Deterministic owner execution (updated #1091): contract_value, billing_rate, and hours_budget now execute via DET confirm→fire gates (no model turn). Both colon form ("update CityCore App Development: contract value 130000") and preposition form ("set the contract value for CityCore App Development to 130000") resolve the project and present a clean confirm. Owner-only denial is also deterministic. Missing-value inputs fall through to the model.
list_projects
List all projects (filtered by role).
Reads from: 02. Projects, 04. Clients, 03. Users
Returns: name, client_name (resolved from client_id; null when the project has no client, including when client_id points at a client that no longer resolves), type, pm_name, status, deadline (Owner/Manager only)
get_project_info
Full project details. Always call this first when checking project status — it tells you the type, which determines whether to follow up with get_project_status or get_retainer_status.
Reads from: 02. Projects, 04. Clients, 03. Users
Returns: name, client, type, budget_hours, status, pm_name, deadline (Owner/Manager), contract_value (Owner), billing_rate (Owner)
get_project_status
Task-level budget status for non-retainer projects.
Reads from: 01. Time Entries, 06. Project_Tasks, 02. Projects
Returns per task: hours_logged, budget_hours, % used, alert status, committed hours (logged + allocated)
Do not use for retainers — use get_retainer_status instead.
get_project_health
Burn rate health for retainer projects, with envelope-aware forecast.
Reads from: 01. Time Entries, 02. Projects, 07. Budgets
Returns: hours_logged, days_elapsed, pace_per_day, projected_eom_hours, allocated_remaining, forecast_with_allocations, variance, utilization%, status
Status values: critical_overpace, warning_overpace, on_track, warning_underpace, critical_underpace
get_my_projects
Projects where the requesting user is the PM (or all projects if Owner).
Parameters: requesting_user_slack_id
delete_project
Permanently hard-delete a project. Owner only. Only allowed when the project is completely empty: no time entries, no allocation envelopes (any status), no vendor liabilities, and no period/sprint children. Use cancel_project for anything with history.
Console-only — not reachable from Slack; use the web console.
Writes to: 02. Projects
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
project_name | Name of the project | |
project_id | ID of the project (alternative to name) |
Returns 400 if the project has time entries, budgets (any status), liabilities, or child periods/sprints — with a message pointing to
cancel_projectas the correct affordance. The protected time-off projects (PTO, Sick, Leave) return 403. This action is irreversible.
Returns: project_id, name, message
close_project
Mark a project (and any active or planned period/sprint children) completed. Owner only. Use this for projects that finished successfully — for projects that won't be completed, use cancel_project instead.
Console-only — not reachable from Slack; use the web console.
Updates: 02. Projects
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
project_name | Name of the project | |
project_id | ID of the project (alternative to name) |
Rejects a period/sprint child directly — close the parent project instead. Also resolves any open retainer/sprint renewal Unresolved Items for the project.
Returns: project_id, project_name, closed_count, message
cancel_project
Mark a project (and any active or planned period/sprint children) cancelled, hiding it from list_projects. Owner only. Use this for projects that will not be completed — for projects that finished successfully, use close_project instead.
Console-only — not reachable from Slack; use the web console.
Updates: 02. Projects
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
project_name | Name of the project | |
project_id | ID of the project (alternative to name) |
Rejects a period/sprint child directly — cancel the parent project instead. Rejects a project already cancelled. The protected time-off projects (PTO, Sick, Leave) return 403 (see
rename_projectabove). Also resolves any open retainer/sprint renewal Unresolved Items for the project.
Returns: project_id, project_name, cancelled_count, message
set_project_budget
Set the project-level hours budget (Tier 1). Owner only.
Console-only — not reachable from Slack; use the web console.
Updates: 02. Projects col D
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
project_name | ✅ | |
budget_hours | ✅ | Total hours cap |
set_project_deadline
Set the project delivery date. Owner or PM of the project (Managers who are not the PM get a deterministic denial).
Console-only — not reachable from Slack; use the web console.
Updates: 02. Projects
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
project_name | ✅ | |
deadline | ✅ | YYYY-MM-DD |
Deterministic routing: natural-language date inputs ("set the deadline for X to next Friday") resolve the date and show a confirm with the concrete ISO date before writing — no model round-trip. A non-PM manager gets a deterministic denial: ❌ Failed: Only owners or <project>'s PM can set its deadline. ISO date inputs ("set the deadline for X to 2027-01-16") fall through to the model.
list_tasks
All task types with billability flag.
Shared with Task Tools — documented there.
create_task
Create a new global task type. Owner only.
Shared with Task Tools — documented there.
rename_task
Rename a task type globally. Owner only.
Shared with Task Tools — documented there.
archive_task
Archive a task type so it no longer appears in menus or as a write target. Owner only.
Shared with Task Tools — documented there.
unarchive_task
Restore an archived task so it appears in menus again. Owner only.
Shared with Task Tools — documented there.
get_project_tasks
All enabled tasks for a project, with budget and hours logged.
Reads from: 06. Project_Tasks, 05. Tasks, 01. Time Entries
Returns per task: task_name, is_billable, budget_hours, alert_threshold, hours_logged, % used, budget_summary
budget_summary includes:
tasks_without_budget: count of enabled tasks with no budget setover_project_budget: whether task totals exceed the project budgetunallocated_hours: project budget minus sum of task budgets
enable_task_for_project
Enable a task on a project with optional budget. Owner or project PM.
Shared with Task Tools — documented there.
disable_task_for_project
Disable a task on a project. Owner or project PM.
Shared with Task Tools — documented there.
get_retainer_status
Monthly burn rate for a retainer project. See Retainers for interpretation guide.
Reads from: 01. Time Entries, 02. Projects, 07. Budgets
Parameters: requesting_user_slack_id, project_name
Returns: budget_hours, hours_logged, hours_remaining, days_elapsed, days_remaining, pace_per_day, projected_eom_hours, allocated_remaining, forecast_with_allocations, variance, utilization_percent, exceed_date, unused_hours, unused_value, status
get_retainer_periods
Full period history for a Retainer parent — past, current, and future periods with hours logged, budget, burn %, and (Owner only) contract value per period. Manager/Owner.
Reads from: 02. Projects, 01. Time Entries
Parameters: requesting_user_slack_id, project_name or project_id
Returns: parent_project, period_count, total_hours_budget, total_hours_logged, total_contract_value (Owner), and periods[] — each with period_id, period_name, period_number, period_status, period_start, period_end, hours_budget, hours_logged, hours_remaining, burn_pct, contract_value (Owner)
get_pm_retainer_summary
All retainer projects assigned to a PM, with burn status for each. Manager/Owner.
create_retainer_period
Add a new billing period to an existing Retainer parent. Owner only.
Console-only — not reachable from Slack; use the web console.
Writes to: 02. Projects
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
parent_project_name | ✅ | The Retainer parent (must already exist — use create_project for the first period) |
period_start | ✅ | First day of the billing month, YYYY-MM-01 |
hours_budget | Overrides the inherited value from the most recent period | |
contract_value | Overrides the inherited value from the most recent period | |
billing_rate | Overrides the inherited value from the most recent period | |
confirmed | Omit (or false) to preview the inherited terms; pass true to actually create the period |
Period number auto-increments; financial terms not explicitly overridden are inherited from the most recent period (or the parent's own defaults, for the very first period).
Retainer and Agile are frozen project types as of the 2026-06-06 pivot — new engagements use T&M, Fixed Price, Pro Bono, or Internal.
create_retainer_periodcurrently returns❌ Failed: new retainer periods / sprints aren't currently supported…for every call, regardless of parameters. Existing retainers continue to report correctly viaget_retainer_statusandget_retainer_periods.
create_sprint
Create a new sprint under an Agile parent. Owner only.
Console-only — not reachable from Slack; use the web console.
Writes to: 02. Projects
Parameters:
| Param | Required | Description |
|---|---|---|
requesting_user_slack_id | ✅ | |
parent_project_name | ✅ | The Agile parent project |
contract_value | ✅ | Must be asked explicitly — never derived |
hours_budget | ✅ | Sprint hours estimate |
Sprint number is auto-incremented — do not specify manually.
Retainer and Agile are frozen project types as of the 2026-06-06 pivot — new engagements use T&M, Fixed Price, Pro Bono, or Internal.
create_sprintcurrently returns❌ Failed: new retainer periods / sprints aren't currently supported…for every call, regardless of parameters. Existing Agile projects continue to report correctly viaget_agile_summary.
get_agile_summary
All sprints under an Agile project with revenue recognition.
Reads from: 02. Projects, 01. Time Entries
Returns per sprint: sprint_name, sprint_number, status, contract_value (Owner), hours_budget, hours_logged, recognised_revenue (Owner)
update_sprint_status
Transition a sprint from planned to active. Owner only. No confirmation prompt needed.
Console-only — not reachable from Slack; use the web console.
Updates: 02. Projects col L
Parameters: requesting_user_slack_id, sprint_id, new_status ("active")