Create project
well_create_projectCreate a project in the current workspace. A project is any tracked business object with a name, a kind and a status. Each kind has its own parent, statuses and fields: deal: no parent; status draft, active, paused, won, lost, archived; takes owner_person_id, counterparty_company_id, counterparty_person_id, stage_project_id, probability, position, end_date, amount, currency. pipeline: no parent; status active, archived; takes paid_stage_project_id. pipeline_stage: nests under a pipeline; status active, archived; takes position, probability. cost_center: may nest under a cost_center; status active, archived; takes no other field. property: no parent; status active, archived; takes no other field. project: may nest under a project; status draft, active, paused, completed, archived; takes counterparty_company_id, counterparty_person_id, start_date, end_date, amount, currency, billing_method. campaign: no parent; status draft, active, paused, completed, archived; takes start_date, end_date, channel, objective, included_audience_project_id, excluded_audience_project_id. audience: no parent; status draft, active, paused, completed, archived; takes start_date, end_date. flow: no parent; status draft, active, paused, completed, archived; takes start_date, end_date, trigger_audience_project_id. ad_set: nests under a campaign; status draft, active, paused, completed, archived; takes start_date, end_date, included_audience_project_id, excluded_audience_project_id. ad: may nest under a campaign or ad_set; status draft, active, paused, completed, archived; takes start_date, end_date. experiment: no parent; status draft, active, paused, completed, archived; takes start_date, end_date, experiment_outcome.
Use this tool when the user asks to create, add or start tracking one of these. A deal is a project Well tracks itself, and Well creates its own deal unless a live connected CRM has a deal create in Well (Attio today): create one here when the person names a deal and no such CRM is connected. With a live Attio connection, a deal the person names goes through that connector's create (well_invoke_connector_tool, after its confirmation card in Well); this tool never writes a second deal in Well for it. Another connected CRM, or an Attio connection that needs a reconnect or is in error, keeps the deal in Well.
REQUIRED: name and kind, and status for every kind but a deal. A deal with no status opens as active. The user's own word names the kind, in any language: "Crée le projet Refonte site web" and "Create the project Website redesign" are kind project. When the user creates a project and names no status, send status "active" (in progress): the call fails without a status, and the saved line names that status. Ask the user for the kind when they did not say it, and for the status only when the kind is neither a project nor a deal; never guess either. OPTIONAL: only the fields the kind takes, listed above. Dates are YYYY-MM-DD. A deal needs an amount; a non-null amount needs its currency. probability is a percentage from 0 through 100 with at most two decimals. position is a whole number from 0. billing_method (a project only) is how the work is priced: project_rate, service_rate, person_rate, fixed_fee, non_billable. For a campaign, channel is one of google_ads, linkedin_ads, reddit_ads, chatgpt_ads, meta_ads, tiktok_ads, pinterest_ads and objective is one of awareness, traffic, engagement, leads, sales; included_audience_project_id and excluded_audience_project_id each name a live audience of this workspace. A flow may set trigger_audience_project_id to a live audience of this workspace. parent_project_id, stage_project_id, owner_person_id, counterparty_company_id and counterparty_person_id are ids of this workspace: use one-row well_query_records lookups to resolve them; a deal takes one counterparty, a company or a contact. An experiment may set experiment_outcome to keep, revert, iterate; keep it null when no result is known. An ad set may include or exclude live audiences with included_audience_project_id and excluded_audience_project_id. When the person names the client ("for Client G"), look it up by that name and send its id as counterparty_company_id or counterparty_person_id. When the lookup finds no such company or contact, create nothing: say that Well holds no client of that name and ask whether to add it. Never save the project without the client the person named.
A field the kind does not take, or a status it does not hold, fails and nothing is written. A won or lost deal is closed on the day it is set. On WhatsApp, the person's complete typed order approves the create and writes at once. If a required value is missing, the tool returns missing_fields before any approval or write: ask for only that value, keep the same pending order and resolved ids, then call again with the answer. For a deal, ask for amount first; wait to ask for currency until the person has supplied the amount. A typed order that includes an amount without its currency asks only for the currency. Other surfaces still use their normal approval. Two live pipelines, stages of one pipeline, or cost centers of one parent cannot share a name: the call then fails, and well_list_projects finds the existing one.
Returns { success: true, project } on success, { success: false, error, missing_fields } when it needs one value, or { success: false, error } on another failure.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | What the project is: deal, pipeline, pipeline_stage, cost_center, property, project, campaign, audience, flow, ad_set, ad, experiment. Ask the user when it is not clear. | |
| name | Yes | The project's name, unique per kind among the workspace's live structural projects. | |
| amount | No | The stated amount as a decimal string: a deal's value or a project's budget. Only a deal or a project has one, and it needs a currency. | |
| status | No | Where the project stands: draft, active, paused, won, lost, archived, completed. A kind holds only some of them. Ask the user when it is not clear. | |
| channel | No | The ad platform a campaign runs on: google_ads, linkedin_ads, reddit_ads, chatgpt_ads, meta_ads, tiktok_ads, pinterest_ads. Only a campaign takes it; null clears it. | |
| currency | No | The ISO 4217 currency of amount, e.g. EUR. | |
| end_date | No | The last day, YYYY-MM-DD; not before start_date. | |
| position | No | The slot inside the stage (deal) or pipeline (stage), lowest first; a whole number from 0. | |
| objective | No | The campaign objective: awareness, traffic, engagement, leads, sales. Only a campaign takes it; null clears it. | |
| start_date | No | The first day, YYYY-MM-DD. | |
| probability | No | A deal's win chance as a percentage from 0 through 100 with at most two decimals. | |
| workspace_id | No | Target workspace. Omit when the token authorizes one workspace. Required when it authorizes several — a write lands in exactly one workspace and this call would not say which. | |
| billing_method | No | How the work of a project is priced: project_rate, service_rate, person_rate, fixed_fee, non_billable. Only a project takes it; null clears it. | |
| conversation_id | No | The conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation. | |
| idempotency_key | No | Optional client-supplied key. A retried write with the same key returns the original result instead of re-applying the operation. | |
| owner_person_id | No | A deal's owner: the person_id of a contact of this workspace. | |
| workspace_scope | No | Restrict this call to the family: the token's primary workspace plus the company workspaces under it that you are a member of. Unrelated authorized workspaces drop out of the read; row reads merge across the family, while a per-workspace figure still reports exactly one workspace. | |
| stage_project_id | No | The pipeline stage a deal sits on: the project_id of a live pipeline_stage of this workspace. | |
| parent_project_id | No | The project this one nests under, from the same workspace; the kind decides which parent it takes. | |
| experiment_outcome | No | The experiment result: keep, revert, iterate. Only an experiment takes it; null clears it. | |
| counterparty_person_id | No | The contact a deal or project is with: a person_id of this workspace. Not with counterparty_company_id. | |
| counterparty_company_id | No | The company a deal or project is with: a company_id of this workspace. Not with counterparty_person_id. | |
| trigger_audience_project_id | No | A live audience project_id in this workspace that triggers a flow; null clears it. | |
| excluded_audience_project_id | No | A live audience project_id in this workspace to exclude from a campaign or ad set; null clears it. | |
| included_audience_project_id | No | A live audience project_id in this workspace to include in a campaign or ad set; null clears it. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| code | No | ||
| error | No | ||
| project | No | ||
| success | Yes | ||
| reply_lines | No | ||
| missing_fields | No | ||
| conversation_id | No | The conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation. | |
| near_candidates | No | ||
| newly_connected | No | Tools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. The connected-line rule says when to tell an entry; when it does, one line per entry, in the person's language: "<name> is connected.". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later. | |
| conversation_id_note | No | Present only when the server opened a fresh lane, stating that no choice recorded earlier was read. | |
| conversation_id_source | No | Where the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened. | |
| near_candidates_truncated | No |