Skip to content

Output format

Every tool call returns three things:

Part For Content
content[0].text The model A Markdown summary: what was found or done, and what to do next.
structuredContent The client and the card The data, valid against the tool’s outputSchema, with a kind that says what it is.
The card (_meta.ui.resourceUri) The user, in the Claude app The VibeSell card, which renders structuredContent by its kind.

isError is false for a result and true for a refusal; a refusal carries only text. See Errors & refusals.

choose_sending_source · result
{
"content": [
{
"type": "text",
"text": "**Question for the user:** Choose your sending addresses\n_This decides what gets set up for you. Nothing is set up, reserved or billed by this answer._\n\n- `already_warmed` — Start sooner (…)\n- `own_names` — Send under my brand (…)\n- or an answer in their own words\n\nPut this to the user and wait for THEIR answer — never pick for them. Then call choose_sending_source again with the same arguments and answers: [{\"card\":\"ecdbf5a52b3ecea6\",\"answer\":\"<their answer>\"}]…"
}
],
"structuredContent": {
"kind": "choice",
"tool": "choose_sending_source",
"arguments": {},
"card": "ecdbf5a52b3ecea6",
"question": "Choose your sending addresses",
"reason": "This decides what gets set up for you. Nothing is set up, reserved or billed by this answer.",
"choices": [
{
"id": "already_warmed",
"label": "Start sooner",
"description": "Addresses already prepared, without your brand's name. …"
},
{
"id": "own_names",
"label": "Send under my brand",
"description": "Addresses created for you, ready after about 2 business days of preparation, weekends not counted."
}
],
"allowFreeText": true,
"answers": []
},
"isError": false
}

Each tool’s result carries a kind. Clients can switch on it to render results their own way.

kindReturned by
approvalorder_sending_setup, import_leads, launch_campaign, stop_campaign, resume_campaign, upgrade_plan, decide_approval
approvalslist_pending_approvals
campaignget_campaign, stage_campaign
campaign_estimateestimate_campaign_plan
checkoutstart_checkout
choicechoose_sending_source, propose_domains, propose_warmed_domains, propose_email
domain_quotecheck_domains
email_stepchoose_sending_source, propose_domains, propose_warmed_domains, propose_email
first_emailcheck_first_email
lead_countestimate_lead_pool
lead_previewpreview_lead_sample
memoryremember
offersave_offer
plansget_plans_and_billing
playbooksave_playbook
portalopen_billing_portal
replieslist_replies
sending_choicechoose_sending_source, propose_domains, propose_warmed_domains, propose_email
sending_setupget_sending_setup
sequencesave_sequence, approve_sequence
sizingsize_sending_capacity, confirm_sizing
supportcontact_support
targetsave_target, save_target_filters, confirm_target
warmed_shelflist_warmed_domains
warmupstart_warmup
workspaceget_workspace_context

Tools that ask the user something — choose_sending_source, propose_domains, propose_warmed_domains, propose_email — return kind: "choice" with:

  • card — the id of this question;
  • question, reason and choices (each with an id, a label and maybe a description);
  • allowFreeText — whether the user may answer in their own words;
  • arguments — the arguments to call the tool with again;
  • answers — the answers given so far.

The assistant puts the question to the user, then calls the same tool with the same arguments and answers set to the list it got back plus { "card": "<card id>", "answer": "<choice id or the user's words>" }. An answer is only accepted for the very card it was given to: if the question changed in between, the tool asks again. Once settled, the result switches to sending_choice or email_step.

The six approval tools return kind: "approval" with a status — pending, done, not_done or rejected — the card’s action, summary, server-written impact, irreversible flag and expiresAt, plus decideHere and appUrl. See Approval cards.

Results point the user back to VibeSell when something is decided or done there: appUrl (the app), billing links from open_billing_portal, and the Stripe payment page from start_checkout. Only the user opens them.