Skip to main content
This page documents the Python MCP surface (mcp.heybtw.com). It reflects mcp-server/tools/activate_list.py as of this page’s publication — see Schema stability.
This tool writes. action="confirm" sends real invites to real people.It is the only non-read-only tool on this surface. It is registered with readOnlyHint=false and idempotentHint=false, and those annotations are accurate — do not treat this tool like the read tools, and do not retry a confirm freely. The one safe retry is narrowly defined below under When a retry is safe.

Purpose

activate_list sends a saved heyBTW List to the Luma event it is linked to, behind a mandatory human confirmation round trip. It wraps the same server-side send service as the Activate panel in the product, so eligibility rules, Luma dedupe, quota warnings, and the resulting funnel all agree with what the UI would do. This is the one action path for sending a List to Luma. For discovering who to invite in the first place, use get_invite_recommendations.

The confirmation protocol

This sequence is not a convention an agent may optimise away. Every invariant in it is re-enforced server-side, and a confirm that skips a step is refused.
  1. Call action="preview" with the list_id. Nothing is sent. The response carries the eligible count, the excluded counts and their reasons, the named target event with its dates, and the workspace’s trailing-7-day invite usage.
  2. Present that payload to the human and obtain their explicit go-ahead. The preview response carries a coverage_note saying exactly this. Do not summarise the preview into a yes/no question that hides the target event or the count.
  3. Call action="confirm" with the same list_id and a fresh UUID client_request_id.
Two additional gates can apply, both surfaced on the preview:
  • Sends over 2,500 require typed_count — the eligible count typed back by the human. preview.requires_typed_count tells you when this applies.
  • A preview that exceeds the workspace’s weekly reference requires weekly_warning_acknowledged=true. preview.exceeds_weekly_reference tells you when this applies.
Never call action="confirm" as the first call in a session, and never call it to “check whether it would work.” There is no dry-run mode on confirm; preview is the dry run.

Parameters

Omitting a required argument for the chosen action is rejected as a structured invalid_parameter error before any network call, so a malformed confirm cannot reach the send service.

Access requirements

  • A workspace-scoped credential. Admin and global keys are refused, on every action rather than only on confirm — a preview that a later confirm would refuse is a confirmation payload that can only mislead the human reading it.
  • A plan including the agent-connections-outbound capability. Without it the tool raises a structured entitlement_required error.

Sample request

Sample response (action="preview")

Response field reference

Envelope

A result whose status is not "ok" (invalid, unavailable, not_found, forbidden) passes through as the service returned it, rather than being reworded here.

resultaction="preview"

resultaction="confirm"

resultaction="status"

resultaction="funnel"

When a retry is safe

confirm is not idempotent in general. The tool is registered idempotentHint=false on purpose: a dynamic List that has grown since the last activation re-sends the delta on a second confirm. Re-issuing a confirm with a new client_request_id is a new send, not a retry.
There is exactly one safe retry, and it is bounded:
  • A confirm that fails with send_outcome_unknown. The transport failed and the send’s true state is unknown. Retry with the same client_request_id. The server dedupes on that key, so the retry cannot double-send, and the response’s idempotent field tells you whether the original had in fact landed. This is the only outcome the tool refuses to guess about, which is why it has a dedicated error rather than a generic one.
Everything else — a fresh client_request_id, a re-run “just to be sure”, a retry after a timeout you did not confirm was send_outcome_unknown — risks sending again. destructiveHint is false because an invite is additive and Luma dedupes repeats server-side. That is a statement about damage, not about repetition being free: a duplicate confirm still consumes the workspace’s invite volume and can still put a second heyBTW-originated invite in front of a recipient.

Errors

  • invalid_parameter. An unrecognised action, a missing per-action required argument, or a global/admin credential. Raised before any network call.
  • entitlement_required. The workspace’s plan does not include agent-connections-outbound.
  • send_outcome_unknown. confirm only. See When a retry is safe.
  • Generic sanitized error. Every other failure, as on the read tools — see get_workspace_overview — Errors.

Pagination and limits

One call per invocation. No limit parameter, no cursor pagination. Rate limited per workspace at 30 requests/5s, 60/minute, and 1,000/day; counters are held per server instance rather than shared, so the effective ceiling scales with instance count. A 429 carries a Retry-After header naming the window you tripped — honor it rather than guessing a backoff.
  • get_invite_recommendations — find candidates before building the List you activate here.
  • get_event_details — check who is already registered for the target event.
  • Lists — how static and dynamic Lists resolve membership, which is what determines the delta a second confirm would send.