> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getnexor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP tool catalog

> Generated reference for 272 customer-callable Nexor MCP tools, pinned to the public server manifest.

This catalog contains all 272 tools a customer MCP key can call at the pinned public-server revision. The server lists 279 tools in total; 7 internal-administration tools are intentionally excluded here.

<Info>Each canonical purpose below is copied verbatim from the server manifest. Names, scopes, required top-level inputs, operation modes, and contract safeguards are generated from the same snapshot.</Info>

<Warning>Your connected client's `tools/list` response is authoritative for the server it reaches. It includes the complete JSON Schema. If its count differs from this pinned snapshot, review the server revision before automating writes.</Warning>

<Warning>The catalog still lists `create_client_tool`, `update_client_tool`, `assign_tool_to_workflow`, `configure_customer_api_tool`, `create_workflow_tool`, and `update_workflow_tool` because those tools exist in `tools/list`. Creating, editing, or assigning a custom HTTP destination is temporarily not a supported public operation while Nexor hardens destination validation. Do not use these tools to configure a destination until this notice is removed.</Warning>

## How to read the catalog

`Read` means the manifest declares no write scope. `Write` means the call may change state. A safeguard names only what the tool contract exposes; `No contract flag` is not permission to skip operator approval for a consequential action.

<Accordion title="Session metadata (1)">
  | Tool     | Scope             | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                |
  | -------- | ----------------- | ---- | ------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
  | `whoami` | Authenticated key | Read | None                     | No contract flag | Return the authenticated Nexor client identity and the scopes this API key was granted. Call this first to discover which actions are permitted. |
</Accordion>

<Accordion title="Account readiness (1)">
  | Tool                    | Scope             | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
  | ----------------------- | ----------------- | ---- | ------------------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_account_readiness` | Authenticated key | Read | None                     | No contract flag | MANDATORY FIRST-RUN TOOL. At the start of a new customer conversation, call this before the first substantive reply. Returns account/payment state, granted and missing setup scopes, saved onboarding context, agents/channels/template inventory, a factual readiness checklist, the safest next tools, external human touchpoints, and initial\_dialogue with the exact opening behavior. Each appointment-capable agent carries a booking block (meeting\_type, hosts with schedule/calendar state, activation blockers such as MEETING\_TYPE\_REQUIRED / BOOKING\_AVAILABILITY\_REQUIRED / CALENDLY\_BINDING\_REQUIRED, timezone warnings, and fix\_tools). Follow initial\_dialogue; do not ask for facts in resume\_context, do not mutate while payment/account access is blocked, and do not claim the account is ready merely because dashboard onboarding was marked complete or because an agent is active: an active agent with booking blockers cannot book. |
</Accordion>

<Accordion title="Agents (12)">
  | Tool                          | Scope             | Mode  | Required top-level input           | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | ----------------------------- | ----------------- | ----- | ---------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_workflows`              | `workflows:read`  | Read  | None                               | No contract flag | List the authenticated client's workflows (the funnels leads move through), including each agent's master\_workflow\_id group assignment, enabled channels, and status ids. Archived (soft-deleted) agents are hidden by default; pass include\_archived:true to see them too — each row then carries archived:true and a deleted\_at timestamp so you can find an archived agent to restore with restore\_workflow.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
  | `get_workflow`                | `workflows:read`  | Read  | `workflow_id`                      | No contract flag | Fetch one workflow/agent with prompts/config, ordered status summaries, fields, channels and tool execution settings. Status summaries do not include their full gates/timeouts/transfers; call get\_workflow\_status for each status whose behavior you need to inspect. Use both reads for verification before activation.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | `create_workflow`             | `workflows:write` | Write | `name`, `goal_type`, `statuses`    | No contract flag | Create a new PAUSED workflow/agent. Provide an ordered list of statuses; each needs a key plus a name (or its `label` alias). If no is\_initial/is\_terminal flags are set, the first and last become entry/exit. Statuses accept the full stage config here — entry\_hint, category, color, transition\_rules, requires\_all\_fields/required\_field\_keys, timeout\_config, transfer\_config, pause\_bot, assignment\_config and the is\_\* flags — so a funnel can be fully configured in one call instead of follow-up update\_workflow\_status PATCHes. Unknown status fields are forwarded to the backend as-is. The statuses array is the COMPLETE funnel of YOUR stages: the backend seeds a default pipeline on create, so this tool reads the workflow back, deletes seeded statuses not in your list, and returns the workflow plus a pipeline\_reconciliation report. Three core stages (new, contacted, engaged) and the virtual "discarded" stage ALWAYS exist on every agent and are NOT part of the statuses contract: they are never deleted and are listed under seeded\_statuses\_kept (reason core\_stage/virtual) — do not try to remove them. The result carries a top-level `status`: "created" means the funnel is exactly what you asked; "created\_with\_warnings" means the report has REAL unresolved warnings (duplicate stage labels, non-core seeded stages that could not be removed, missing requested stages) — you MUST resolve those before telling the user the agent is built. Set prune\_unrequested\_statuses:false to keep seeded defaults. Pass timezone (IANA) and region\_style: when omitted the backend anchors them to the ACCOUNT (country/host schedule), never to a Chilean default — read them back in the returned workflow. When the first-contact channel (channels\[0] or the inferred one) has no verified resource on the account, the result carries a channel\_not\_verified warning with the fix tools (connect\_whatsapp\_number, provision\_phone\_number, register\_email\_sender). Idempotent on the backend (a guarded duplicate returns the existing id; stages holding leads are never deleted, only reported). For multi-agent or operational builds, first call describe\_agent\_configuration + review\_agent\_system\_plan, resolve clarifications, and obtain explicit user approval of the final fingerprint. |
  | `set_workflow_prompt`         | `workflows:write` | Write | `workflow_id`, `global_prompt`     | No contract flag | Replace a workflow's base (global) prompt — the business rules and persona the agent follows across channels. Read the current one with get\_workflow first if you want to edit rather than overwrite. Channel-specific overrides are not touched.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
  | `set_workflow_active`         | `workflows:write` | Write | `workflow_id`, `active`            | No contract flag | Turn a workflow on (active) or off (paused). Workflows are created PAUSED — this is how you go live. Activating only starts cadence for enrolled leads not yet contacted; it never re-blasts leads already in progress. Appointment workflows need at least one active meeting type before they can activate.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
  | `update_workflow`             | `workflows:write` | Write | `workflow_id`                      | No contract flag | Update a workflow's identity, metadata, or agent-group assignment: rename it, change its description, set the objective of a 'custom' goal workflow (goal\_statement), move it into an agent group (master\_workflow\_id), remove it from its group (master\_workflow\_id: null), or adjust the agent's identity (language, timezone, region\_style, agent\_name, agent\_role, company\_name, begin\_message). Pass only the fields you want to change. Use list\_agent\_groups to resolve a group name to its tenant-scoped id.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
  | `set_channel_prompt`          | `workflows:write` | Write | `workflow_id`, `channel`, `prompt` | No contract flag | Set the per-channel prompt override for a workflow (e.g. WhatsApp vs email tone/format). Merges with existing channel prompts; doesn't touch the global prompt. Use 'call' for the voice/call channel ('retell' is still accepted as an alias).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | `get_workflow_prompt_history` | `workflows:read`  | Read  | `workflow_id`                      | No contract flag | Read one workflow's prompt version history — snapshots of global + channel prompts, what changed, by whom, and when. workflow\_id must be the exact UUID returned by list\_workflows/get\_workflow; never pass a name, change id, or placeholder text.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
  | `update_workflow_structure`   | `workflows:write` | Write | `workflow_id`                      | No contract flag | Add or edit a workflow's basic funnel statuses and/or data fields. Upsert by key — new keys are added, existing ones updated; nothing is deleted. Status order is deliberately unsupported here: use reorder\_workflow\_statuses. After creating statuses, use update\_workflow\_status for entry/qualification gates, timeouts, transfers, pause behavior and trigger flags. To remove one safely, use get\_pipeline\_impact then delete\_workflow\_status.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | `update_workflow_config`      | `workflows:write` | Write | `workflow_id`, `config`            | No contract flag | Update a workflow's behaviour config (the `config` bag: flags like gate\_outbound\_to\_hours and other non-prompt settings). Merges top-level keys by default — pass only the keys you want to change; existing keys are preserved. Set replace:true only to overwrite the entire config object (rare). Does not touch the prompt, statuses, fields, or channels. Reserved keys are REFUSED here (400 RESERVED\_CONFIG\_KEY) because the runtime reads them by exact key and a misspelled key would merge silently: use set\_payment\_link for payment\_link, set\_host\_assigner for host\_assigner and set\_external\_booking for external\_booking — those validate the shape and the referenced tools.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
  | `set_opening_message`         | `workflows:write` | Write | `workflow_id`, `channel`           | No contract flag | Set the agent's FIRST message for one channel — the fixed opener sent/spoken verbatim before the agent improvises. channel 'call' (voice): `message` is the opening line spoken when the call connects (flat variables \{\{lead\_first\_name}}, \{\{lead\_full\_name}}, \{\{agent\_name}}, \{\{company\_name}}; '' clears it and restores the language-pack default); `agent_speaks_first` (default true) — set false to make the agent wait for the lead to speak, optionally with `silence_ms` (1000–30000, default 3000) before it opens anyway. channel 'email': a fixed first email `subject` + `body` sent verbatim (variables \{\{first\_name}}, \{\{last\_name}}, \{\{email}}, \{\{metadata.key}}); `enabled:false` with empty subject/body removes it so the agent composes the first email itself. channel 'webchat': `message` shown by the widget before the agent speaks. channel 'sms': `message` sent verbatim as the first outbound SMS (same variables as email; a legally required STOP notice is still appended for US numbers). channel 'messenger': `message` sent verbatim as the agent's first reply in a new Messenger conversation. For call/webchat/sms/messenger, '' clears the opener so the agent composes it from the prompt. NOT free text: WhatsApp openers are Meta-approved templates → set\_opening\_templates; Instagram campaign openers are dashboard-only. Returns the persisted opener as read-back; read every channel's opener with get\_workflow → opening\_messages. / Configura el PRIMER mensaje del agente por canal: 'call' (línea de apertura de voz + quién habla primero), 'email' (asunto + cuerpo fijos), 'webchat', 'sms' y 'messenger' (texto fijo del primer mensaje). WhatsApp usa plantillas aprobadas (set\_opening\_templates).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  | `set_payment_link`            | `workflows:write` | Write | `workflow_id`, `source`            | No contract flag | Set (or clear) where a 'Send Payment Link' agent gets the link it sends to leads — the backing for the dashboard's Payment link section. Pick the source: 'fixed' = one static URL for every lead (needs a valid http(s) url; optional label); 'tool' = a tool generates a per-lead link (needs the tool name; optional capture dot-path into the tool's JSON response, e.g. 'data.url'); 'lead' = read the link from a lead metadata field (needs metadata\_key, e.g. 'payment\_url'); 'none' = clear the configured link. Use this instead of writing config.payment\_link through update\_workflow\_config: this validates the shape and reads the saved value back, so a success here means it actually persisted. / Configura de dónde saca el link de pago un agente de 'Enviar link de pago': 'fixed' (URL fija http(s), label opcional), 'tool' (una herramienta genera el link; capture opcional), 'lead' (leer de metadata\_key del lead) o 'none' (borrar). Devuelve el valor guardado como verificación.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
</Accordion>

<Accordion title="Agent tools (6)">
  | Tool                          | Scope             | Mode  | Required top-level input                    | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
  | ----------------------------- | ----------------- | ----- | ------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_workflow_tools`         | `workflows:read`  | Read  | `workflow_id`                               | No contract flag | List a workflow's custom tools (name, method, url, active, stage gate, on-entry, call-once).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | `create_workflow_tool`        | `workflows:write` | Write | `workflow_id`, `name`, `description`, `url` | No contract flag | Create a CUSTOM tool that lives only in THIS workflow (no catalog inheritance). Prefer create\_client\_tool + assign\_tool\_to\_workflow when the tool should be reusable across workflows. name is the snake\_case identifier the agent references (immutable). description tells the agent when to call it. parameters is a JSON Schema for the call arguments. Supports \{\{placeholders}} in url/headers (\{\{lead.metadata.X}}, \{\{lead\_id}}, …). call\_once caches the result per lead; auto\_run\_on\_entry fires it when a lead enters the workflow; available\_in\_statuses gates it to funnel stages. |
  | `update_workflow_tool`        | `workflows:write` | Write | `workflow_id`, `tool_id`                    | No contract flag | Edit a custom tool's config (url, method, description, parameters, headers, timeout, flags). The name cannot change — delete + recreate to rename.                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
  | `set_workflow_tool_execution` | `workflows:write` | Write | `workflow_id`, `tool_id`, `mode`            | No contract flag | Choose exactly how an assigned workflow tool runs. mode="on\_entry" makes it a pre-agent/pre-execution hook: it fires as soon as a lead enters the workflow, before the first agent message, and therefore clears stage gating. mode="agent\_decides" lets the conversational agent call it and optionally gates it to specific status keys. These modes are mutually exclusive. call\_once limits successful execution per workflow run; is\_active is an independent kill switch.                                                                                                                               |
  | `delete_workflow_tool`        | `workflows:write` | Write | `workflow_id`, `tool_id`                    | No contract flag | Remove a custom tool. Soft-disables by default (keeps audit); pass hard=true to delete permanently.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
  | `set_tool_stage_gate`         | `workflows:write` | Write | `workflow_id`, `tool_id`                    | No contract flag | Gate a tool to specific funnel stages: it becomes callable only when the lead is in one of available\_in\_statuses. Pass null to clear the gate (callable anywhere).                                                                                                                                                                                                                                                                                                                                                                                                                                              |
</Accordion>

<Accordion title="Reusable client tools (6)">
  | Tool                          | Scope             | Mode  | Required top-level input                | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | ----------------------------- | ----------------- | ----- | --------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_client_tools`           | `workflows:read`  | Read  | None                                    | No contract flag | List the client's reusable tool catalog. Tools here can be assigned to multiple workflows and stay in sync.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
  | `create_client_tool`          | `workflows:write` | Write | `name`, `description`, `url`            | No contract flag | Create a reusable tool in the client catalog. This is the RECOMMENDED low-level path for an existing customer API operation that should be available across workflows; configure\_customer\_api\_tool is the guided create-and-assign path. name is the immutable snake\_case function identifier. description is loaded into the agent and must say when/how to call the API without containing credentials. parameters is the agent-visible JSON Schema. Use \{\{env.KEY}} in url/headers for secrets configured with set\_function\_environment\_variable; lead/context placeholders are also supported.                                                                                                 |
  | `configure_customer_api_tool` | `workflows:write` | Write | `name`, `purpose`, `when_to_use`, `url` | No contract flag | Turn one operation from an API the customer owns or already uses into a reusable Nexor agent tool, then optionally assign it to workflows. Creates the catalog tool, composes scoped agent instructions from purpose/when-to-use/when-not-to-use/response rules, and configures per-workflow stage gates, call-once behavior, and response-field allowlisting. Model one focused API operation per tool. Store credentials with set\_function\_environment\_variable and reference them as \{\{env.KEY}} in headers; NEVER put credentials in purpose/instructions/parameter descriptions. This creates a new immutable name; use list\_client\_tools + update\_client\_tool when that name already exists. |
  | `update_client_tool`          | `workflows:write` | Write | `tool_id`                               | No contract flag | Edit a catalog tool's config. Changes propagate to every workflow that has assigned (inherited) this tool. The name cannot change — delete + recreate to rename.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  | `delete_client_tool`          | `workflows:write` | Write | `tool_id`                               | No contract flag | Remove a tool from the client catalog.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | `assign_tool_to_workflow`     | `workflows:write` | Write | `client_tool_id`, `workflow_id`         | No contract flag | Assign a catalog tool to a workflow; it inherits and stays in sync with the catalog tool. Idempotent — re-assigning an already-assigned tool returns the existing assignment.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
</Accordion>

<Accordion title="Leads (17)">
  | Tool                            | Scope          | Mode  | Required top-level input  | Safeguard                             | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | ------------------------------- | -------------- | ----- | ------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_leads`                    | `leads:read`   | Read  | None                      | No contract flag                      | Page through the authenticated client's leads with optional search, workflow and human-assignee filters. A workflow\_id includes active and settled/inactive membership by default, matching get\_pipeline\_impact; pass run\_state=active only for current runs. Every lead includes assigned\_to plus assigned\_user when assigned; use list\_team (people:read) for the directory. For recurring polls, pass updated\_since with sort\_by=updated\_at sort\_dir=asc and resume from the max updated\_at seen.                                                                                                                                                                                                                                                       |
  | `get_lead`                      | `leads:read`   | Read  | `lead_id`                 | No contract flag                      | Fetch one lead by id, including its assigned human owner (assigned\_to and assigned\_user id/name, or null), field values, per-channel engagement and active workflow run. Use list\_team (people:read) for the complete user directory.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
  | `get_leads`                     | `leads:read`   | Read  | `lead_ids`                | No contract flag                      | Batch read many leads by id in ONE call (1-500 per call), each with the same field values, per-channel engagement and workflow runs as get\_lead. Always prefer this over calling get\_lead in a loop — N sequential get\_lead calls burn the rate limit. Unknown ids come back in missing\_ids.                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
  | `get_lead_history`              | `leads:read`   | Read  | `lead_id`                 | No contract flag                      | Read what was actually said or sent to ONE lead. The unified timeline returns full WhatsApp and SMS text, email subject/body plus delivery details, and call summary/transcript, with direction and timestamps; it also includes activities, meetings and conversions when unfiltered. Use channel=call,whatsapp,email,sms (one or comma-separated) to isolate communication content. Paging mode uses limit/offset and order\_by; when pagination.has\_more is true, keep paging before claiming the history is complete. Conversation-window mode uses anchor\_ts with before/after (0-20 each) to inspect the messages around one moment. Use list\_transcripts/get\_transcript only for meeting transcripts, not phone calls.                                      |
  | `upsert_leads`                  | `leads:write`  | Write | `leads`                   | No contract flag                      | Create or update one or more leads (idempotent upsert on email/phone). When workflow\_id is provided, enrollment has MOVE semantics: every other active run is deactivated before the target run is created, and the result is verified by reading each successful lead back. Use assign\_lead\_to\_workflow for an already-known lead id. WARNING: first\_message sends a real outbound message immediately (no agent composition) and also requires messages:send; first\_channel only pins the first cadence channel.                                                                                                                                                                                                                                               |
  | `update_lead`                   | `leads:write`  | Write | `lead_id`                 | No contract flag                      | Update one lead. Put identity/contact values in standard fields (first\_name, last\_name, email, phone), and other agent-readable context in metadata. Metadata is shallow-merged and becomes available to the agent on its next execution; it does not change contact destinations or send data externally. Archived leads are rejected.                                                                                                                                                                                                                                                                                                                                                                                                                              |
  | `sync_lead_tags`                | `leads:write`  | Write | `tags`                    | No contract flag                      | Set the exact tag set for a lead (empty clears all tags). Identify the lead by id or email.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  | `assign_lead_to_workflow`       | `leads:write`  | Write | `lead_id`, `workflow_id`  | No contract flag                      | Move a lead into a workflow: deactivates the current run, creates a fresh run and starts its cadence (may trigger outbound contact).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
  | `stop_automation`               | `leads:write`  | Write | `lead_id`                 | No contract flag                      | Human takeover ON for a lead: pause its cadence and cancel pending scheduled tasks. The active workflow is resolved automatically; only pass workflow\_id if the lead is in more than one.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
  | `resume_automation`             | `leads:write`  | Write | `lead_id`                 | No contract flag                      | Human takeover OFF for a lead; optionally reactivate its cadence (may resume outbound contact).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | `set_lead_status`               | `leads:write`  | Write | `lead_id`, `status_key`   | No contract flag                      | Force a lead's funnel status (move it forward or back). The active workflow is resolved automatically; pass workflow\_id only if the lead is in more than one.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
  | `bulk_set_lead_status`          | `leads:write`  | Write | `lead_ids`, `status_key`  | `confirm_transfer_side_effects: true` | Set the funnel status for many leads at once (1-500 per call). Applies the same per-lead status change (with history) as set\_lead\_status; leads that can't be updated come back in `failed` with a reason. When the target status auto-messages (transfer\_config), those leads are withheld with reason `transfer_side_effects_require_confirmation` — confirm with the operator, then re-call with confirm\_transfer\_side\_effects=true to include them.                                                                                                                                                                                                                                                                                                          |
  | `bulk_assign_leads_to_workflow` | `leads:write`  | Write | `lead_ids`, `workflow_id` | No contract flag                      | Move many leads (1-500 per call) into a workflow: each gets its current run deactivated and a fresh run with cadence started (may trigger outbound contact). Failures come back per lead in `failed`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
  | `bulk_archive_leads`            | `leads:write`  | Write | `lead_ids`                | No contract flag                      | SOFT delete (archive) many leads at once (1-500 per call). REVERSIBLE: the leads disappear from active views and their automation stops, but the records are kept and can be restored. This does NOT permanently erase anything — for that, use bulk\_hard\_delete\_leads. When the operator asks to "delete"/"remove"/"borrar"/"eliminar" leads and it is not crystal clear whether they mean archive (reversible) or permanent erase (irreversible), ASK before calling either tool. Confirm before calling. Failures come back per lead in `failed`.                                                                                                                                                                                                                |
  | `delete_lead`                   | `leads:write`  | Write | `lead_id`                 | No contract flag                      | SOFT delete (archive) one lead. REVERSIBLE: the record is kept and can be restored; this does NOT permanently erase it — for that, use hard\_delete\_lead. When the operator asks to "delete"/"remove"/"borrar"/"eliminar" a lead and it is not crystal clear whether they mean archive (reversible) or permanent erase (irreversible), ASK before calling either tool.                                                                                                                                                                                                                                                                                                                                                                                                |
  | `hard_delete_lead`              | `leads:delete` | Write | `lead_id`                 | `confirm: true`                       | PERMANENTLY delete one lead. IRREVERSIBLE AND NOT RECOVERABLE: the lead and ALL of its data — every conversation, message, meeting, call, field value, note, and task — are erased forever. There is no undo and no restore. This is NOT archiving (use delete\_lead for reversible archiving). Preview-then-confirm: call with confirm:false (or omit it) to get a \{ status:'needs\_confirmation' } preview that writes NOTHING; only call again with confirm:true after the operator explicitly confirms permanent erasure of this exact lead. When "delete"/"remove"/"borrar"/"eliminar" is ambiguous between archive and permanent erase, ASK first — never assume hard delete.                                                                                   |
  | `bulk_hard_delete_leads`        | `leads:delete` | Write | `lead_ids`                | `confirm: true`                       | PERMANENTLY delete many leads at once (1-500 per call). IRREVERSIBLE AND NOT RECOVERABLE: each lead and ALL of its data — every conversation, message, meeting, call, field value, note, and task — are erased forever. There is no undo and no restore. This is NOT archiving (use bulk\_archive\_leads for reversible archiving). Preview-then-confirm: call with confirm:false (or omit it) to get a \{ status:'needs\_confirmation' } preview that writes NOTHING; only call again with confirm:true after the operator explicitly confirms permanent erasure of these exact lead ids. When "delete"/"remove"/"borrar"/"eliminar" is ambiguous between archive and permanent erase, ASK first — never assume hard delete. Failures come back per lead in `failed`. |
</Accordion>

<Accordion title="Rules (9)">
  | Tool                        | Scope         | Mode  | Required top-level input         | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | --------------------------- | ------------- | ----- | -------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_reminder_catalog`      | `rules:read`  | Read  | None                             | No contract flag | The reminder contract for THIS account: channels with per-account availability (available\_for\_account + reason, e.g. retell needs an active callable number, sms an SMS-enabled number, whatsapp an active WhatsApp number, email a verified sender), trigger events the runtime actually dispatches (with which ones are reconciled onto existing bookings), delay references and default templates. Call it before set\_reminder\_rule when choosing a channel; pass workflow\_id for the workflow-scoped answer.                                                                                                                                                                                                       |
  | `list_reminder_rules`       | `rules:read`  | Read  | None                             | No contract flag | List lead-facing reminder rules (booking confirmations, pre-meeting reminders).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
  | `set_reminder_rule`         | `rules:write` | Write | `trigger_event`, `template_name` | No contract flag | Create or update a lead reminder rule (idempotent). Channels: whatsapp \| retell \| sms \| email — whether each one can actually send on this account comes from get\_reminder\_catalog (available\_for\_account); a rule on an unavailable channel is stored but the response carries warning 'channel\_not\_available' until the sender is provisioned. trigger\_event 'call\_analyzed' fires post-CALL, not post-meeting; there is no 'reschedule' event (a reschedule re-fires event\_created). delay\_minutes is signed: negative with delay\_reference='event\_start' means before the meeting. Example: \{trigger\_event:'event\_created', channel:'whatsapp', template\_name:'confirm\_booking', delay\_minutes:0}. |
  | `list_host_reminder_rules`  | `rules:read`  | Read  | None                             | No contract flag | List host (sales rep) notification rules. Email-only. Note: cancellation notifications are on by default and may not appear here.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | `set_host_reminder_rule`    | `rules:write` | Write | `trigger_event`, `template_name` | No contract flag | Create or update a host booking-notification rule (notify the rep by email when a meeting is booked; idempotent). Omit workflow\_id for a global rule. Note: host cancellation and reschedule alerts are already sent by default and are not configured here.                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
  | `list_recontact_rules`      | `rules:read`  | Read  | None                             | No contract flag | List re-engage (recontact) rules that drive the AI scanner re-contacting stale leads. Each rule carries cadence\_owned (true when its stage belongs to the initial outreach cadence, so it can never be active).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  | `set_recontact_rule`        | `rules:write` | Write | `name`, `stale_after_hours`      | No contract flag | Create or update a re-engage rule (idempotent). The initial outreach cadence OWNS the stages new, contacted and the workflow's initial stage: an active rule there returns 409 CADENCE\_OWNED\_STAGE (fix: target a later custom stage such as engaged/proposal\_sent, or send is\_active:false). prompt\_hint is a binding instruction to the AI. stale\_reference defaults to 'last\_touchpoint\_at' (recommended; 'last\_response\_at' silently freezes silent leads).                                                                                                                                                                                                                                                   |
  | `list_status_timeout_rules` | `rules:read`  | Read  | None                             | No contract flag | List status auto-timeout configs (auto-transition stagnant leads after a delay).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  | `set_status_timeout_rule`   | `rules:write` | Write | `workflow_id`, `status_key`      | No contract flag | Set or clear the auto-timeout on a workflow status. target\_status\_key must be an existing status key in the SAME workflow. Pass clear:true to disable.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
</Accordion>

<Accordion title="People and invitations (4)">
  | Tool                       | Scope           | Mode  | Required top-level input | Safeguard         | Canonical purpose                                                                                                                                                                                                                                |
  | -------------------------- | --------------- | ----- | ------------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | `list_team`                | `people:read`   | Read  | None                     | No contract flag  | List the authenticated client's active team members (sales reps / hosts) with user id, name, email and CRM external id. Use these user ids with assigned\_to filters; lead and conversation reads expose the matching assigned\_user by default. |
  | `list_pending_invitations` | `people:read`   | Read  | None                     | No contract flag  | List outstanding invitations (not yet accepted, not cancelled, not expired). Consult this before inviting to avoid duplicates.                                                                                                                   |
  | `invite_user`              | `invites:write` | Write | `email`, `role`          | `dry_run` preview | Invite a person to the client's organization by email and role. Idempotent: a still-valid pending invite to the same email is reused, not re-sent. Returns status: created \| reused \| already\_member.                                         |
  | `revoke_invitation`        | `invites:write` | Write | None                     | No contract flag  | Cancel a pending invitation by id or email (preserves audit; does not hard-delete).                                                                                                                                                              |
</Accordion>

<Accordion title="Messaging (6)">
  | Tool                              | Scope            | Mode  | Required top-level input            | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | --------------------------------- | ---------------- | ----- | ----------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_whatsapp_templates`         | `leads:read`     | Read  | None                                | No contract flag | List the client's WhatsApp templates with components, variables, status, internal\_type, language, quality\_score, rejection\_reason, is\_in\_pool and sync timestamps, plus totals \{ total, by\_status }. Defaults to APPROVED; pass status=ALL for a complete terminal-readable approval dashboard, or select PENDING/REJECTED/etc. Filters: internal\_type, language prefix, and q (name/body substring). For fresh Meta state call check\_whatsapp\_template\_approvals.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
  | `get_whatsapp_template`           | `whatsapp:read`  | Read  | None                                | No contract flag | Fetch one WhatsApp template in full detail: status, internal\_type, language, category, components, variables, quality\_score, rejection\_reason (when Meta rejected it), whether it is in a cadence pool, and sync timestamps. Look it up by template\_id (from list\_whatsapp\_templates) or by exact name.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
  | `review_whatsapp_template_drafts` | `whatsapp:read`  | Read  | `templates`                         | No contract flag | Read-only preflight for one or many WhatsApp template drafts. Use it as the conversational back-and-forth loop: generate drafts from the user requirement, call this tool, show errors/warnings and normalized\_templates, revise, and repeat. It verifies the connected WhatsApp account, Meta formatting, examples for every variable, buttons, duplicate names/bodies, and cadence purpose. When all\_valid=true it returns a review\_id; show the exact normalized\_templates to the user and get final sign-off before create\_whatsapp\_templates\_batch.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | `create_whatsapp_templates_batch` | `whatsapp:write` | Write | `templates`, `review_id`, `confirm` | `confirm: true`  | Submit 1-20 reviewed WhatsApp templates to Meta in one confirmed operation. REQUIRED FLOW: review\_whatsapp\_template\_drafts → show normalized drafts and review\_id → obtain explicit user sign-off → call this tool with those exact drafts, review\_id, confirm=true. Never invent confirmation. Meta writes are not atomic, so the result reports every accepted, already-existing, or failed item; then use check\_whatsapp\_template\_approvals to refresh approval states.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
  | `create_whatsapp_template`        | `whatsapp:write` | Write | `name`, `body`                      | No contract flag | Create a new WhatsApp template and submit it to Meta for approval (usually minutes to 48h). Templates are AGENT-SPECIFIC: first resolve the target agent (ask, or list\_workflows) and read it with get\_workflow so the copy matches that agent's persona, goal, product, and language — never write generic copy. After creation, wire the template into THAT agent's cadence with set\_whatsapp\_template\_purpose plus set\_template\_pool / set\_opening\_templates, or it is never auto-used. Body text uses \{\{variable}} placeholders — variables cannot start/end the text nor be consecutive. Name must be lowercase\_with\_underscores. PREFER the canonical variable names Nexor auto-resolves at send time: \{\{nombre}} (lead first name), \{\{agente}} or \{\{ejecutivo}} (agent name), \{\{empresa}} (company), \{\{producto}} (product), and for meeting reminders \{\{fecha}}, \{\{hora}}, \{\{asesor}}, \{\{link\_reunion}}. Other names still work but fall back to LLM resolution. channel\_id is optional when the client has a single WhatsApp business account (use list\_whatsapp\_numbers to disambiguate). |
  | `send_message`                    | `messages:send`  | Write | `lead_id`, `channel`                | No contract flag | Send an outbound message to a lead. WhatsApp/email/sms/imessage accept free text; outside the 24h WhatsApp window you must pass an approved template\_id instead of text. channel="sms" sends via the workflow's SMS-enabled number. channel="imessage" sends a blue-bubble iMessage via the workflow's bound iMessage number (free text, no templates). channel="call" triggers an outbound call. workflow\_id is optional — it is resolved from the lead's active run when omitted.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
</Accordion>

<Accordion title="Account (8)">
  | Tool                    | Scope            | Mode  | Required top-level input          | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                               |
  | ----------------------- | ---------------- | ----- | --------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_lead_meetings`    | `leads:read`     | Read  | `lead_id`                         | No contract flag | List a lead's calendar events with host and meeting type.                                                                                                                                                                                                                                                                                                                                                                                                       |
  | `create_meeting`        | `meetings:write` | Write | `lead_id`, `starts_at`, `ends_at` | No contract flag | Log a booked meeting against an existing lead (no Google Calendar sync). Idempotent via external\_event\_id.                                                                                                                                                                                                                                                                                                                                                    |
  | `ingest_meeting_notes`  | `meetings:write` | Write | `external_meeting_id`, `provider` | No contract flag | Attach an external transcript / summary / action items to an existing meeting. The meeting is resolved via calendar\_event\_id, external\_calendar\_provider + external\_calendar\_event\_id, meeting\_url, or lead\_email (+ optional meeting\_date) — at least one is required. external\_meeting\_id only dedupes the notes (idempotency), it does NOT locate the meeting. Reserved providers (fireflies, diio, gemini, retell) are rejected by the backend. |
  | `list_conversion_types` | `leads:read`     | Read  | None                              | No contract flag | List the client's active conversion types (use these ids with create\_conversion).                                                                                                                                                                                                                                                                                                                                                                              |
  | `set_conversion_type`   | `leads:write`    | Write | `name`                            | No contract flag | Create or update a conversion type by name (idempotent upsert). Conversion types define what counts as a conversion (e.g. "Cuenta abierta", "Primer depósito") and are required before create\_conversion. Never deletes — deactivate with is\_active:false; full removal is dashboard-only.                                                                                                                                                                    |
  | `create_conversion`     | `leads:write`    | Write | `conversion_type_id`, `amount`    | No contract flag | Record a conversion event for a lead (may trigger an async workflow transfer). Needs a conversion\_type\_id (see list\_conversion\_types) and an amount, plus exactly one lead identifier.                                                                                                                                                                                                                                                                      |
  | `list_conversions`      | `leads:read`     | Read  | None                              | No contract flag | List conversion events for the client.                                                                                                                                                                                                                                                                                                                                                                                                                          |
  | `list_campaigns`        | `leads:read`     | Read  | None                              | No contract flag | List the client's campaigns.                                                                                                                                                                                                                                                                                                                                                                                                                                    |
</Accordion>

<Accordion title="Background jobs (10)">
  | Tool                              | Scope             | Mode  | Required top-level input | Safeguard                         | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
  | --------------------------------- | ----------------- | ----- | ------------------------ | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_background_jobs`            | `workflows:read`  | Read  | None                     | No contract flag                  | List the client's background jobs (scheduled or forced lead automations).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | `get_background_job`              | `workflows:read`  | Read  | `job_id`                 | No contract flag                  | Fetch a background job by id with its recent executions.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
  | `create_background_job`           | `workflows:write` | Write | `name`, `steps`          | `dry_run` execution mode          | Create a background job: a scheduled/forced automation that filters leads and runs steps on each. trigger\_type "cron" needs a cron\_expression; "api" runs only when forced (run\_background\_job). A step can evaluate a date/condition — on a metadata key (evaluate\_metadata), a collected funnel field (evaluate\_field), or a tag (evaluate\_tag) — and act, OR run an action directly. Actions include sending a WhatsApp template (send\_message), set\_lead\_status, assign/transfer workflow. lead\_filters/workflow\_filters select candidates; max\_leads\_per\_cycle caps each run (≤500); cooldown\_minutes avoids re-acting on the same lead; dry\_run logs without acting. See the `steps` field for the full vocabulary and `lead_filters` / `workflow_filters` for how candidates are selected. Filters and steps are validated server-side: an unresolvable one is rejected with code invalid\_filters / invalid\_steps and a details\[] naming each problem. Common use: send a survey template once to everyone sitting in a given status. |
  | `update_background_job`           | `workflows:write` | Write | `job_id`                 | `dry_run` execution mode          | Update a background job (any subset of its config). Filters and steps are validated server-side (invalid\_filters / invalid\_steps with details\[]). See `lead_filters` / `workflow_filters` for candidate selection and `steps` for the action vocabulary (send\_message, evaluate\_field, set\_lead\_status, …).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
  | `set_background_job_active`       | `workflows:write` | Write | `job_id`, `active`       | No contract flag                  | Pause or activate a Background Job without changing the rest of its configuration. Keep dry\_run:true until execution logs are verified.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
  | `delete_background_job`           | `workflows:write` | Write | `job_id`                 | No contract flag                  | Delete a background job (cascades its execution history).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | `run_background_job`              | `workflows:write` | Write | `job_id`                 | Operator approval in instructions | Force-run a Background Job now (bypasses schedule/active timing). A non-dry-run job can mutate real leads; inspect config and get explicit operator confirmation first.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
  | `list_background_job_executions`  | `workflows:read`  | Read  | `job_id`                 | No contract flag                  | A background job's recent execution history (counts of candidates/acted/errored per run).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | `get_background_job_execution`    | `workflows:read`  | Read  | `execution_id`           | No contract flag                  | Get one Background Job execution with every per-lead action, tool response, condition result, mutation result, skip, and error.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
  | `analyze_background_job_template` | `workflows:read`  | Read  | `template_name`          | No contract flag                  | Inspect an APPROVED WhatsApp template used by send\_message: shows each \{\{variable}}, whether it resolves automatically or via a workflow tool, and configuration errors.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
</Accordion>

<Accordion title="Reports (8)">
  | Tool                            | Scope          | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
  | ------------------------------- | -------------- | ---- | ------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | `export_leads_report`           | `reports:read` | Read | `workflow_ids`           | No contract flag | Create a complete CSV export of every active, non-test lead in one or more exact workflows, including each lead current stage. Use for requests such as "todos los leads", "exporta", "descarga" or "dame un CSV". First resolve workflow names to their UUIDs with list\_workflows, then pass those UUIDs here. Returns a signed download URL.                                                                                                                                                                                                                                                                                                                                                                    |
  | `get_funnel_report`             | `reports:read` | Read | None                     | No contract flag | Aggregate campaign/funnel report: how many leads sit at each status, and how many were contacted/connected, per workflow (or across all workflows). Use for "how many leads are at each stage" style questions.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
  | `get_field_distribution`        | `reports:read` | Read | `field_key`              | No contract flag | Distribution of a captured lead field (e.g. a disqualification reason) with counts per value and an example evidence quote. Ideal for "top reasons why..." style questions.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | `get_call_stats`                | `reports:read` | Read | None                     | No contract flag | Call statistics (dials, connected, discovery calls, duration) for a date range, totaled or broken down by day.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
  | `get_lead_report`               | `reports:read` | Read | `lead_id`                | No contract flag | Full report bundle for ONE lead: profile, current status, captured field values with evidence, insights, a summary of each call and scheduled tasks — all in one call. Prefer this over get\_lead + get\_lead\_history when the goal is writing a report about a lead.                                                                                                                                                                                                                                                                                                                                                                                                                                             |
  | `get_engagement_metrics`        | `reports:read` | Read | None                     | No contract flag | Engagement snapshot for a date range (default: trailing 7 days): total leads, new leads, meetings booked, and outbound/inbound message counts. Test leads are excluded. Ideal for "how did we do this week" or activity-overview questions; for per-status funnel breakdowns use get\_funnel\_report.                                                                                                                                                                                                                                                                                                                                                                                                              |
  | `get_seller_assignment_metrics` | `reports:read` | Read | None                     | No contract flag | Analyze how the client's leads are distributed across human sellers. Returns assignment coverage (total, assigned, unassigned and assignment rate) plus one row per seller with assigned leads, share of assigned leads, current funnel-stage breakdown, unanswered conversations, meetings booked/completed, conversions, conversion value and conversion rate. Assignment is a CURRENT-OWNER snapshot: historical activity is attributed to the lead's current assigned\_to seller, not necessarily the seller who owned it when the activity happened. Date filters select leads by created\_at and activity by each event's timestamp. Use list\_team (people:read) when you need the complete user directory. |
  | `analyze_lead_fields`           | `reports:read` | Read | None                     | No contract flag | Statistical analysis of captured lead field values: numeric fields get min/max/mean/median/p25/p75/stddev/outlier\_count, boolean/categorical fields get top-15 value frequencies. Filter by workflow, specific field keys, lead statuses, or an explicit lead list (max 50). Ideal for "what is the average budget of qualified leads" or comparing field values across a segment. If your filters match nothing, the response includes available\_field\_keys as a hint. For a simple one-field value distribution with evidence quotes, prefer get\_field\_distribution.                                                                                                                                        |
</Accordion>

<Accordion title="Meetings (8)">
  | Tool                  | Scope            | Mode  | Required top-level input                         | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | --------------------- | ---------------- | ----- | ------------------------------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_meetings`       | `leads:read`     | Read  | None                                             | No contract flag | Page through the client's meetings (booked calls/appointments) with lead, workflow, time and status for each. Ideal for questions like "what meetings are scheduled this week", "which meetings were no-shows", or listing a single lead's meetings. For aggregate counts/rates use get\_meeting\_stats instead.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
  | `get_meeting_stats`   | `reports:read`   | Read  | None                                             | No contract flag | Aggregate meeting statistics for a date range: totals per status (completed, no\_show, cancelled, scheduled, rescheduled) plus show\_rate, completion\_rate and no\_show\_rate (0-1, null when the denominator is 0). Ideal for "what is our show rate" or "how many meetings did we book last month" questions. For individual meetings use list\_meetings.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | `set_meeting_status`  | `meetings:write` | Write | `meeting_id`, `status`                           | No contract flag | Record the outcome of a meeting: 'no\_show' (the lead did not attend) or 'completed'. Runs the same side effects as the dashboard — the no-show re-engagement rule (when configured), the meeting webhook, Cloud Function events and the lead timeline — then reads the meeting back with its provider sync status. Idempotent: re-marking the same outcome is a no-op. meeting\_id is the calendar event id from list\_meetings / list\_lead\_meetings. To cancel a meeting use cancel\_meeting; to move it use reschedule\_meeting.                                                                                                                                                                                                                                                                                                                                                                                                                                  |
  | `cancel_meeting`      | `meetings:write` | Write | `meeting_id`                                     | `confirm: true`  | Cancel a booked meeting. DESTRUCTIVE and lead-facing: deletes the event from the host's calendar (provider-first — if that fails nothing is cancelled), releases the slot, cancels lead and host reminders, emails the lead a cancellation and notifies the host, fires the meeting webhook and any cancellation re-engagement rule. Preview-then-confirm: call with confirm:false (or omit it) to get a \{ status:'needs\_confirmation' } preview that writes NOTHING; only call again with confirm:true after the operator explicitly confirms cancelling this exact meeting. Meetings owned by an external provider (Calendly, GoHighLevel…) come back \{ status:'skipped' }. Reads the meeting back afterwards.                                                                                                                                                                                                                                                    |
  | `get_workflow_slots`  | `workflows:read` | Read  | `workflow_id`, `from`, `to`                      | No contract flag | Free booking slots for a workflow's hosts between two dates, in the workflow's timezone — the same slot engine the dashboard meetings board uses (host calendars, availability schedules, buffers, tier rules). Use it to verify a host produces slots and to pick a starts\_at for book\_meeting / reschedule\_meeting. meeting\_type\_id defaults to the workflow's first active meeting type; host\_id restricts to one host (must be an active agent of the workflow).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
  | `book_meeting`        | `meetings:write` | Write | `workflow_id`, `lead_id`, `host_id`, `starts_at` | `confirm: true`  | Book a meeting for a lead with a host at starts\_at, with the SAME side effects as booking from the dashboard: calendar event on the host's connected calendar (Google/Outlook/Calendly), conferencing link, lead invite + confirmation email (unless invite\_lead:false), host notification and reminders, availability block, and the workflow status transition. Pick starts\_at from get\_workflow\_slots. A slot already taken returns CONFLICT with same-day alternatives. Pass the same idempotency\_key to retry safely — a replay returns the original booking without booking again. Preview-then-confirm: when the lead will be invited, call with confirm:false (or omit it) to get a \{ status:'needs\_confirmation' } preview that writes NOTHING; call again with confirm:true only after the operator explicitly approves. The response includes provider\_sync — check its status; 'sync\_failed' means the row exists but the calendar write failed. |
  | `reschedule_meeting`  | `meetings:write` | Write | `meeting_id`                                     | `confirm: true`  | Move a booked meeting to a new time (starts\_at, or a slot object from get\_workflow\_slots). Provider-aware: the host's calendar event is updated first and the meeting link is kept when the host is unchanged; keep\_host:false with a host\_id rebooks on the new host (new link). The lead receives a reschedule email and the host is notified. Preview-then-confirm: call with confirm:false (or omit it) to get a \{ status:'needs\_confirmation' } preview that writes NOTHING; call again with confirm:true only after the operator explicitly approves. Meetings owned by an external provider come back CONFLICT/MANAGED\_EXTERNALLY. Returns the meeting read-back with provider\_sync.                                                                                                                                                                                                                                                                   |
  | `change_meeting_host` | `meetings:write` | Write | `meeting_id`, `host_id`                          | `confirm: true`  | Reassign a booked meeting to another host (active agent of the same workflow) without changing the time. Provider-aware: the calendar event is moved to the new host's calendar first (new organizer/link where the provider requires it); if that move fails nothing changes. The lead's invite is updated. Preview-then-confirm: call with confirm:false (or omit it) to get a \{ status:'needs\_confirmation' } preview that writes NOTHING; call again with confirm:true only after the operator explicitly approves. Returns the meeting read-back with provider\_sync.                                                                                                                                                                                                                                                                                                                                                                                           |
</Accordion>

<Accordion title="Transcripts (2)">
  | Tool               | Scope        | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                 |
  | ------------------ | ------------ | ---- | ------------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_transcripts` | `leads:read` | Read | None                     | No contract flag | Page through meeting transcripts: per row the lead, meeting date, title, a short summary (\<=500 chars), whether it has action items, and duration. Ideal for "what was discussed in recent meetings" or finding a transcript by keyword before drilling in with get\_transcript. |
  | `get_transcript`   | `leads:read` | Read | `transcript_id`          | No contract flag | Fetch ONE meeting transcript by id: lead, meeting date, title, full summary, action items and duration. Set include\_full\_text/include\_sentences only when you actually need the verbatim conversation — they can be very large. Use list\_transcripts first to find the id.    |
</Accordion>

<Accordion title="Conversations (1)">
  | Tool                   | Scope        | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  | ---------------------- | ------------ | ---- | ------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `search_conversations` | `leads:read` | Read | None                     | No contract flag | Search messages across ALL leads at once (get\_lead\_history covers a single lead). Results include the lead's assigned human owner by default (assigned\_to plus assigned\_user id/name, or null); filter by assigned\_to or unassigned\_only, and use list\_team (people:read) to resolve the full user directory. Two modes: normal mode returns matching messages with lead, channel, direction and a content preview — ideal for "who mentioned pricing this week"; unanswered=true instead returns leads whose LAST message is an unanswered inbound (waiting on a reply) — ideal for "which leads are waiting on us". |
</Accordion>

<Accordion title="Integrations (1)">
  | Tool                     | Scope            | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
  | ------------------------ | ---------------- | ---- | ------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_integration_status` | `workflows:read` | Read | None                     | No contract flag | One-call health summary of the client's integrations: connected CRMs (provider, status, connected\_at, last\_synced\_at, error), counts of WhatsApp numbers, phone numbers and email senders, calendars\[] (one per host calendar connection: user\_id, name, provider google\|outlook\|calendly, status active\|expired\|revoked\|error\|needs\_reauth, role, calendar\_email, last\_error, connected\_at) and booking\_providers\[] (one per appointment-capable agent: provider native\|calendly\|gohighlevel\|external\_booker, binding summary, host\_count, excluded\_hosts = Calendly hosts with no event type bound, which booking silently skips). Ideal for "is our CRM synced", "is the calendar connected" or "why can't the agent book" questions; drill into a channel with its own list tool (list\_whatsapp\_numbers, list\_phone\_numbers, list\_email\_senders). |
</Accordion>

<Accordion title="Phone numbers (7)">
  | Tool                        | Scope           | Mode  | Required top-level input       | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  | --------------------------- | --------------- | ----- | ------------------------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `search_available_numbers`  | `numbers:read`  | Read  | `country`                      | No contract flag | List phone numbers available to buy in a country (ISO code, e.g. "CL", "MX"). Read-only preview — buying one is provision\_phone\_number.                                                                                                                                                                                                                                                                                                                                                    |
  | `list_phone_numbers`        | `numbers:read`  | Read  | None                           | No contract flag | List the client's VOICE/SMS phone numbers with their scope (client vs workflow), the workflow each is bound to, SMS status, and whether each is active. This is the call/SMS inventory only — it does NOT report iMessage state. A Dial iMessage number can appear here as an ordinary voice/SMS-style row (often unassigned); that row says nothing about whether iMessage is provisioned or which agent owns it. For anything iMessage (blue bubble), use list\_imessage\_numbers instead. |
  | `provision_phone_number`    | `numbers:write` | Write | `phone_number`, `country_code` | No contract flag | Buy and provision a phone number for the client (Twilio purchase + Retell import). Billable and capped per client (default 3 active). Pass a workflow\_id to bind the number to that workflow (workflow-scoped); omit it for an account-wide client-scoped number. Fails with NUMBER\_LIMIT\_REACHED at the cap — release or deactivate one first.                                                                                                                                           |
  | `assign_number_to_workflow` | `numbers:write` | Write | `number_id`                    | No contract flag | Reassign one of the client's numbers to a workflow (workflow-scoped) or, with no workflow\_id, make it the account-wide client-scoped number. Only reassigns within the client's own workflows.                                                                                                                                                                                                                                                                                              |
  | `set_number_sms`            | `numbers:write` | Write | `number_id`, `enabled`         | No contract flag | Activate SMS per agent on an existing active Twilio number: enable inbound SMS on the number and set sms\_workflow\_id to bind it to that agent's workflow. SMS is not provisioned separately — it rides on a number the account already has, and requires a Twilio-carrier number (Telnyx numbers cannot carry SMS).                                                                                                                                                                        |
  | `get_number_health`         | `numbers:read`  | Read  | `number_id`                    | No contract flag | Non-destructive health/read-back for one of the client's numbers: reports the number's active state, provider, its call binding and its SMS binding (enabled + owner workflow), and any issues — without placing a call or sending a message.                                                                                                                                                                                                                                                |
  | `deactivate_number`         | `numbers:write` | Write | `number_id`                    | No contract flag | Soft-deactivate one of the client's numbers (stops it being used; does NOT release it from Twilio, so billing continues). Reversible.                                                                                                                                                                                                                                                                                                                                                        |
</Accordion>

<Accordion title="WhatsApp numbers (9)">
  | Tool                            | Scope            | Mode  | Required top-level input     | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
  | ------------------------------- | ---------------- | ----- | ---------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_whatsapp_numbers`         | `whatsapp:read`  | Read  | None                         | No contract flag | List the client's WhatsApp numbers with connection status, quality rating, messaging-limit tier, account restrictions, last health-check time, connection type, and bound workflow.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
  | `connect_whatsapp_number`       | `whatsapp:write` | Write | None                         | No contract flag | Start connecting a WhatsApp number for the client: returns a hosted Kapso setup link the client opens to finish onboarding (choose dedicated/coexistence, Meta login). IMPORTANT — give the returned setup URL to the user DIRECTLY as a clickable link (e.g. "Connect your WhatsApp number here: \<url>") and tell them to open it; the authorization happens entirely on that page and CANNOT be completed in chat, so never withhold the URL or claim you'll connect it for them. Works even when a number is already connected — this adds a NEW one (several allowed per client). Once the user finishes on the hosted page, Nexor records the number and registers its inbound webhook + events automatically (no extra call needed); confirm with list\_whatsapp\_numbers. Capped per client (default 10) — fails with WHATSAPP\_LIMIT\_REACHED at the cap. Then bind it with assign\_whatsapp\_to\_workflow. |
  | `assign_whatsapp_to_workflow`   | `whatsapp:write` | Write | `number_id`                  | No contract flag | Bind one of the client's WhatsApp numbers to a workflow (agent) — this is what makes inbound WhatsApp messages on that number reach the agent. Omit workflow\_id to unbind. Makes the number the default for that workflow.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
  | `deactivate_whatsapp_number`    | `whatsapp:write` | Write | `number_id`                  | No contract flag | Soft-deactivate one of the client's WhatsApp numbers (stops it being used; reversible; does NOT disconnect it from Kapso).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | `rename_whatsapp_number`        | `whatsapp:write` | Write | `number_id`, `internal_name` | No contract flag | Set the operator-facing internal label of one of the client's WhatsApp numbers (does not change the WhatsApp display name shown to leads — for that use set\_whatsapp\_display\_name). Pass an empty internal\_name to clear it.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
  | `reconcile_whatsapp_number`     | `whatsapp:write` | Write | `number_id`                  | No contract flag | Re-check a WhatsApp number against the provider and repair its route status — the fix for a number that shows a broken/invalid connection or after a failed setup return. Returns the refreshed state; run get\_whatsapp\_health afterwards to confirm. If the number needs a fresh Meta authorization, reconnect via connect\_whatsapp\_number (a new hosted setup link).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | `get_whatsapp_business_profile` | `whatsapp:read`  | Read  | `number_id`                  | No contract flag | Read the WhatsApp business profile shown to leads for one number: display name, its Meta review status (APPROVED / PENDING\_REVIEW / etc.), and profile picture. Use before set\_whatsapp\_display\_name to see the current name and whether a review is pending.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
  | `set_whatsapp_display_name`     | `whatsapp:write` | Write | `number_id`, `display_name`  | No contract flag | Submit a new WhatsApp display name (the name leads see) to Meta for review. Must be 3-256 characters. Meta review can take minutes to a couple of days; the response reports displayNameStatus=PENDING\_REVIEW. Re-check with get\_whatsapp\_business\_profile.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | `set_whatsapp_profile_photo`    | `whatsapp:write` | Write | `number_id`, `image_url`     | No contract flag | Replace the WhatsApp profile picture for a number from a public HTTPS image URL (Nexor ingests it into Meta). The image must already be hosted at an https\:// URL — this tool does not upload local files.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
</Accordion>

<Accordion title="WhatsApp health (3)">
  | Tool                           | Scope            | Mode  | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
  | ------------------------------ | ---------------- | ----- | ------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_whatsapp_health`          | `whatsapp:read`  | Read  | `number_id`              | No contract flag | Live health and risk for one WhatsApp number. Returns quality\_rating (GREEN/YELLOW/RED — RED means the account is at risk of Meta restriction), messaging\_health (can\_send\_message AVAILABLE/LIMITED/BLOCKED with per-entity WABA/phone errors and suggested fixes), messaging\_limit tier + daily ceiling, and route\_verification (whether the provider route is valid or needs reconnect/resync). This is the tool for 'is my WhatsApp at risk / why can't it send / what's my sending limit'. One call triggers several Meta calls, so results are briefly cached — don't poll it in a tight loop. |
  | `get_whatsapp_response_timing` | `whatsapp:read`  | Read  | None                     | No contract flag | Read the client's inbound WhatsApp debounce (buffer window): how long Nexor waits to group a lead's rapid consecutive messages into a single AI reply. Returns buffer\_window\_seconds, whether it's the default, and the allowed min/max.                                                                                                                                                                                                                                                                                                                                                                 |
  | `set_whatsapp_response_timing` | `whatsapp:write` | Write | `buffer_window_seconds`  | No contract flag | Set the client's inbound WhatsApp debounce (buffer window) in seconds — larger groups more messages into one reply (more natural, slightly slower); smaller replies faster but may fragment. The change fans out to every active number's webhook; the response reports per-number apply status. Typical range is 5-60 seconds.                                                                                                                                                                                                                                                                            |
</Accordion>

<Accordion title="iMessage numbers (8)">
  | Tool                          | Scope            | Mode  | Required top-level input | Safeguard             | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
  | ----------------------------- | ---------------- | ----- | ------------------------ | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_imessage_offer`          | `imessage:read`  | Read  | None                     | No contract flag      | Read the iMessage number add-on offer for the client BEFORE provisioning: the recurring monthly price (USD), the amount charged today (dueTodayUsd — the full first month, never prorated; 0 in a sandbox/test environment where no charge happens), whether the client can buy (canPurchase) and if not why (reason, e.g. no\_subscription / trial\_not\_allowed / no\_payment\_method / external\_billing / purchase\_disabled), the card on file (brand + last4), how many iMessage numbers they already own, and a state of active \| purchasable \| unavailable. ALWAYS call this first and confirm the recurring charge with the user before calling provision\_imessage\_number. If state is "unavailable" the add-on is not enabled for this client — do not attempt to provision.                                                                                                    |
  | `list_imessage_numbers`       | `imessage:read`  | Read  | None                     | No contract flag      | List the client's iMessage numbers with their E.164 phone number, setupStatus (provisioning \| ready \| failed), setup error if any, the workflow (agent) each is bound to, display identity (displayFirstName, displayLastName, avatarUrl), and active state. imessageWorkflowId is the single OWNER; `owner` adds its name and agent group (masterWorkflowId, masterName) and `sharedWith` lists every sibling agent in that group that already sends and receives through this number without owning one — a number is shared across an agent group exactly like WhatsApp, so an agent listed in sharedWith is connected and needs no assign call. Use this to poll until a freshly provisioned number reaches setupStatus "ready", and to find a number id for get\_imessage\_number, assign\_imessage\_to\_workflow, set\_imessage\_display\_name or set\_imessage\_profile\_photo.      |
  | `provision_imessage_number`   | `imessage:write` | Write | `accept_charge`          | `accept_charge: true` | Buy and provision a NEW iMessage number for the client. THIS CHARGES MONEY: it charges the FULL first month today (never prorated) and adds a recurring monthly line (see get\_imessage\_offer for the exact price) to the client's Stripe subscription. You MUST first call get\_imessage\_offer, show the user the recurring price and the amount charged today, and get their explicit confirmation — only then call this with accept\_charge:true. Fails with imessage\_consent\_required if accept\_charge is not true, and with an eligibility code (e.g. imessage\_no\_subscription, imessage\_no\_payment\_method, imessage\_purchase\_disabled) when the client cannot be charged. The charge is idempotent per call. On success the number provisions asynchronously — poll list\_imessage\_numbers until setupStatus is "ready", then bind it with assign\_imessage\_to\_workflow. |
  | `assign_imessage_to_workflow` | `imessage:write` | Write | `number_id`              | No contract flag      | Bind one of the client's iMessage numbers to a workflow (agent) — this is what makes inbound iMessages on that number reach the agent. The number is then shared by the agent's whole agent group (master\_workflow\_id): every sibling sends and receives through it automatically (new inbound leads land on the owner agent; existing leads follow their active run), so bind ONCE per group and never re-assign it to a sibling that list\_imessage\_numbers already shows in sharedWith. Unless a display identity was set by hand (set\_imessage\_display\_name), the number's display name follows the owner agent's persona. Omit workflow\_id to unbind (the number stays owned/billed, just detached). A group (or a standalone agent) keeps at most one iMessage number, so binding a number to an agent whose group already has one replaces it.                                  |
  | `get_imessage_number`         | `imessage:read`  | Read  | `number_id`              | No contract flag      | Read one iMessage number's live details: E.164 phone number, setupStatus (provisioning \| ready \| failed) and setup error, the workflow (agent) it is bound to plus its agent group (`owner`) and the sibling agents sharing it (`sharedWith`), and the blue-bubble display identity leads see — firstName, lastName, avatarUrl — plus active state. Use before set\_imessage\_display\_name / set\_imessage\_profile\_photo to see the current identity. Fails with imessage\_number\_not\_found for a number outside this client.                                                                                                                                                                                                                                                                                                                                                          |
  | `reconcile_imessage_number`   | `imessage:write` | Write | `number_id`              | No contract flag      | Re-check one iMessage number against Dial (the provider) and repair its local setupStatus — the fix for a number stuck on "provisioning" or "failed" in list\_imessage\_numbers even though it is actually ready. list\_imessage\_numbers reads a locally cached status that is normally advanced only by Dial's setup webhook, so a single missed webhook leaves the number permanently desynced; get\_imessage\_number reads the live truth from Dial but does not persist it. This tool fetches the live Dial status and writes it back, so the list/capabilities path matches reality. Returns the refreshed number; re-run list\_imessage\_numbers or get\_imessage\_number afterwards to confirm. Fails with imessage\_number\_not\_found for a number outside this client.                                                                                                             |
  | `set_imessage_display_name`   | `imessage:write` | Write | `number_id`              | No contract flag      | Set the first and/or last name shown beside an iMessage number's messages in recipients' Messages apps (max 30 characters each; pass an empty string to clear one). Propagates to devices within minutes. Once set by hand the identity is authoritative: it no longer follows the agent persona when the number is (re)assigned. Fails with imessage\_number\_invalid\_fields (+ fieldErrors) when a value is rejected. Read the current identity first with get\_imessage\_number.                                                                                                                                                                                                                                                                                                                                                                                                          |
  | `set_imessage_profile_photo`  | `imessage:write` | Write | `number_id`, `image_url` | No contract flag      | Replace the profile photo shown beside an iMessage number's messages from a public http(s) image URL (jpeg/png/gif/webp, ≤5 MB; the platform mirrors it and returns its stable avatarUrl). Photos can be replaced but NOT removed. This tool does not upload local files — the image must already be hosted. Propagates to devices within minutes.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
</Accordion>

<Accordion title="Email senders (8)">
  | Tool                           | Scope           | Mode  | Required top-level input      | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                           |
  | ------------------------------ | --------------- | ----- | ----------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_email_senders`           | `senders:read`  | Read  | None                          | No contract flag | List the client's registered email senders (domains and individual mailboxes) with their verification status and whether each can send.                                                                                                                                                                                     |
  | `register_email_domain`        | `senders:write` | Write | `sender_email`, `sender_name` | No contract flag | Register a sender under a domain the client owns (e.g. [sales@acme.com](mailto:sales@acme.com)), for sending at scale. Returns the DNS records (SPF/DKIM) the client must add to that domain — adding them is a human step outside this tool. Once added, call verify\_email\_domain, or poll check\_email\_sender\_status. |
  | `register_email_sender`        | `senders:write` | Write | `sender_email`, `sender_name` | No contract flag | Register a personal mailbox (e.g. Gmail/Outlook) as a sender via a magic-link. Nexor emails a verification link to that mailbox — the mailbox owner must open it and click to confirm; that click is a human step outside this tool. Poll check\_email\_sender\_status afterwards to see when it completes.                 |
  | `check_email_sender_status`    | `senders:read`  | Read  | `sender_email`                | No contract flag | Check whether a sender's verification (DNS records or magic-link click) has completed and it can now send. Verification itself happens outside this tool, by a human — use this to poll the result after register\_email\_domain or register\_email\_sender.                                                                |
  | `verify_email_domain`          | `senders:write` | Write | `domain`                      | No contract flag | Trigger a DNS verification check for a domain sender, AFTER the client has already added the DNS records returned by register\_email\_domain. This tool only checks — adding the records is a human step outside this tool.                                                                                                 |
  | `get_email_domain_dns_records` | `senders:read`  | Read  | `domain`                      | No contract flag | Re-fetch the DNS records (SPF/DKIM) for a pending domain sender — e.g. if the client lost the ones returned by register\_email\_domain. Only reads; adding the records to the domain is a human step outside this tool.                                                                                                     |
  | `resend_email_verification`    | `senders:write` | Write | `sender_email`                | No contract flag | Resend the magic-link verification email for a pending sender mailbox.                                                                                                                                                                                                                                                      |
  | `delete_email_sender`          | `senders:write` | Write | `sender_id`                   | No contract flag | Remove a registered sender.                                                                                                                                                                                                                                                                                                 |
</Accordion>

<Accordion title="Template pools (8)">
  | Tool                                    | Scope            | Mode  | Required top-level input       | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
  | --------------------------------------- | ---------------- | ----- | ------------------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_template_pool`                     | `whatsapp:read`  | Read  | `workflow_id`                  | No contract flag | Read a workflow's WhatsApp template pool state in one call: the active rotation pool (name, weight, category), the opening-template config (mode auto\|only\|subset + names), and what's available to add (approved openers and all templates with status + internal\_type). Use it before set\_template\_pool / set\_opening\_templates to see current state.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
  | `set_template_pool`                     | `whatsapp:write` | Write | `workflow_id`, `templates`     | No contract flag | Replace a workflow's WhatsApp cadence template pool with EXACTLY the given list — full-state replace, so a single call covers adding AND removing (retiring) templates atomically: anything omitted is removed from the pool. Each entry: \{ name, weight? (0.01-10, default 1) } and must be an APPROVED template on the client's WhatsApp business account. Read the current pool with get\_template\_pool first, then send the complete desired list.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | `set_opening_templates`                 | `whatsapp:write` | Write | `workflow_id`, `mode`          | No contract flag | Configure which WhatsApp templates a workflow may use as the OPENING (first-contact) message. mode 'auto' lets the cadence pick any eligible opener; 'only' locks it to exactly one template (template\_names must have exactly 1 entry); 'subset' restricts it to the given names (at least 1). Names must be APPROVED templates with internal\_type greeting, opening, legacy\_greeting or outbound. Fails with WOULD\_EMPTY\_OPENING if the change would leave the workflow with no valid opener.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
  | `sync_whatsapp_templates`               | `whatsapp:write` | Write | None                           | No contract flag | Pull the latest template state from Meta for all of the client's WhatsApp business accounts: imports new templates, refreshes statuses (PENDING -> APPROVED/REJECTED) and quality scores. Returns \{ synced, created, updated, channels, warnings }. Run it when a template you expect is missing from list\_whatsapp\_templates or its status looks stale.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
  | `check_whatsapp_template_approvals`     | `whatsapp:write` | Write | None                           | No contract flag | Terminal-friendly approval inspection. By default first syncs every connected WhatsApp business account from Meta, then returns ALL templates in one response with status, quality\_score, rejection\_reason, timestamps, and totals.by\_status. Set refresh=false only when you intentionally want the cached local state. Use after batch submission until each template is APPROVED or REJECTED; rejected drafts can be revised through review\_whatsapp\_template\_drafts under a new name.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
  | `get_whatsapp_template_approval_status` | `whatsapp:read`  | Read  | None                           | No contract flag | THE tool for "have my templates been approved?" / "how long until they're approved?" — in Nexor a bare "template" ALWAYS means a WhatsApp template, so route those questions here. Refreshes from Meta by default, then returns a decision-ready summary — NOT a raw dump: counts \{ total, approved, pending, rejected, ... }, all\_approved / none flags, each PENDING template with how long it has actually been pending (pending\_hours, so you answer with real data instead of a guessed ETA), longest\_pending\_hours, some\_pending\_over\_24h, each REJECTED template with its Meta reason, and review\_window \{ typical, max\_hours }. Also returns numbers\[] — ONLY the verified, fully-connected WhatsApp number(s) (a number still finishing setup is excluded), each with phone\_number and whether it is bound to an agent. Templates only exist for a fully connected WhatsApp number: if none is connected the response is \{ no\_whatsapp: true, numbers: \[] } — then tell the customer to connect a WhatsApp number first (connect\_whatsapp\_number), do NOT say they have zero templates. Otherwise answer with the counts + the canonical window (approval is asynchronous and Meta-owned: usually minutes to \~1 hour, occasionally up to 24-48h) — never invent a precise time. If some\_pending\_over\_24h is true, say it is taking longer than usual. For the full raw list use list\_whatsapp\_templates / check\_whatsapp\_template\_approvals; for one template use get\_whatsapp\_template. Set refresh=false to skip the Meta sync and read cached state. |
  | `set_whatsapp_template_purpose`         | `whatsapp:write` | Write | `template_id`, `internal_type` | No contract flag | Assign the cadence purpose of an existing or Meta-synced WhatsApp template. This is how an already-connected account can make a pre-existing template eligible for opening, follow-up, reminder, or reactivation behavior without recreating it. The template content and Meta approval status are unchanged. Use get\_whatsapp\_template first; only APPROVED greeting templates can subsequently be selected by set\_opening\_templates.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
  | `delete_whatsapp_template`              | `whatsapp:write` | Write | `template_id`, `confirm`       | `confirm: true`  | Soft-delete a WhatsApp template (tenant-scoped; best-effort delete on Meta too). Preview-then-confirm flow: call with confirm=false first — it returns \{ requires\_confirm: true, template: \{ name, status, internal\_type, is\_in\_pool } } and writes NOTHING, so you can show the user what would be removed (especially whether it is still in a cadence pool). Only after reviewing that preview, call again with confirm=true to actually delete; the response reports removed\_from\_pools and meta\_deleted.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
</Accordion>

<Accordion title="Analysis (3)">
  | Tool                     | Scope          | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
  | ------------------------ | -------------- | ---- | ------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_analysis_snapshot`  | `reports:read` | Read | None                     | No contract flag | Precomputed conversation-quality snapshot for the client (or one workflow): eval summary (scored conversations, average score, per-dimension averages, failure buckets), accuracy signals, seeker findings, the worst conversations (with reasons, transcript excerpts for the top 3) and system context. Fast — use it FIRST for "how is the agent doing" questions; only use run\_deep\_analysis when you need a fresh investigation of a specific question.                                 |
  | `list_analysis_findings` | `reports:read` | Read | None                     | No contract flag | List the analysis engine's stored findings/corrections/preferences for the client: title, summary, class, status, client impact, confidence and recommendation. Defaults to status 'open' (actionable backlog); pass status 'all' or a specific status to see history. Findings are produced by prior analysis runs — use run\_deep\_analysis to generate new ones.                                                                                                                            |
  | `run_deep_analysis`      | `reports:read` | Read | `question`               | No contract flag | Run a fresh deep analysis of recent conversations to answer a specific question (e.g. "why are leads ghosting after the price question"). LONG-RUNNING: this call is synchronous and may take 1-3 minutes — tell the user it is in progress and do not retry while waiting. Expensive and rate-limited to 5 runs per day per API key; when capped it returns \{ rate\_limited: true } with the most recent run's findings instead. For a quick health overview prefer get\_analysis\_snapshot. |
</Accordion>

<Accordion title="Lead diagnostics (7)">
  | Tool                 | Scope            | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
  | -------------------- | ---------------- | ---- | ------------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_lead_turns`    | `leads:read`     | Read | `lead_id`                | No contract flag | List a lead's agent turns (one turn = the agent processing one message): trace id, timestamp, channel, model, message/response previews, tools used, errors, latency and token usage. Two modes: (1) paging — use limit + next\_before\_ts to walk back in time; (2) search — pass message\_text, provider\_message\_id, direction or around\_ts to locate WHICH turn handled a specific message (the response includes match.trace\_id with a confidence label). Drill into a turn with get\_lead\_turn. |
  | `get_lead_turn`      | `leads:read`     | Read | `lead_id`, `trace_id`    | No contract flag | Full detail of one agent turn (by trace\_id from list\_lead\_turns): metadata (model, tokens, duration, errors), the lead message + final response + agent reasoning, whether internal content leaked, tools used, the final gate decision, LLM outputs and a step-by-step timeline. Secrets are redacted and URLs reduced to host-only. This is THE tool for "why did the agent say that" questions.                                                                                                     |
  | `get_lead_run_state` | `leads:read`     | Read | `lead_id`                | No contract flag | A lead's current automation state in one call: the active workflow run (status, pause/human-takeover/escalation/dispatch state, next action time), the agent's memory (summary + recent interaction log) and the collected field values with confidence + evidence quotes. Use include to fetch only some sections. This is the first stop for "why isn't the agent messaging this lead" questions.                                                                                                       |
  | `get_lead_verdicts`  | `leads:read`     | Read | `lead_id`                | No contract flag | Quality-judge verdicts and alert events for a lead's conversations: per-turn judge results (pass/fail, score, severity, reason) plus raised alerts (ai / workflow-config / whatsapp categories, redacted previews). Filter by trace\_id or run\_id to inspect one turn/run, or by a time window. Pairs with get\_lead\_turn to see WHAT the agent did vs how it was judged.                                                                                                                               |
  | `get_lead_call`      | `leads:read`     | Read | `lead_id`, `call_id`     | No contract flag | Full detail of one call with a lead (call id from get\_lead\_history, which lists the calls): status, duration, success flag, sentiment, disconnection reason, summary, transcript and the AI call analysis.                                                                                                                                                                                                                                                                                              |
  | `list_offers`        | `workflows:read` | Read | None                     | No contract flag | The client's offer catalog (products/services the agent can pitch): name, description, category, status, source and top items. Pass workflow\_id to see only the offers linked to that workflow (an empty result means the workflow has none linked — there is no fallback to the full catalog). Pass offer\_id for one offer's detail including its items.                                                                                                                                               |
  | `get_client_profile` | `workflows:read` | Read | None                     | No contract flag | The authenticated client's business profile as the agent sees it: name, industry, company size, country (+ secondary countries), timezone, language, website, primary communication channel, lifecycle stage, notes and which settings keys are configured. Useful context before diagnosing agent behavior or drafting client-facing copy.                                                                                                                                                               |
</Accordion>

<Accordion title="Documentation (1)">
  | Tool          | Scope             | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                             |
  | ------------- | ----------------- | ---- | ------------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `search_docs` | Authenticated key | Read | None                     | No contract flag | Search Nexor's product documentation (bundled advanced-feature guides + the live docs site) or read one doc. Pass EXACTLY ONE of: q (search — returns up to 6 results with title, description and path) or path (read — returns the doc content, truncated at \~9000 chars with a marker). Typical flow: search with q, then fetch the best result's path. Public docs only — no tenant data. |
</Accordion>

<Accordion title="Pipeline (2)">
  | Tool                        | Scope             | Mode  | Required top-level input             | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
  | --------------------------- | ----------------- | ----- | ------------------------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `reorder_workflow_statuses` | `workflows:write` | Write | `workflow_id`, `ordered_status_keys` | No contract flag | Replace the order of every mutable status after the protected Lead created, Contacted, and Engaged stages. First call get\_workflow, then pass every remaining persisted status key exactly once in ordered\_status\_keys; omission, duplication, an unknown key, or a changed pipeline fails without mutation. The backend keeps the protected head at sort\_order 0–2 and assigns the submitted tail contiguously from 3. Read back with get\_workflow and compare the exact order before reporting success. Do not include synthetic Discarded stages. |
  | `get_pipeline_impact`       | `reports:read`    | Read  | `workflow_id`                        | No contract flag | Impact preview of a workflow's pipeline BEFORE a destructive change (deleting statuses, moving leads, deactivating the workflow): total board-visible leads bucketed by run state — early, active, settled (terminal/inactive collapsed), ai\_paused and awaiting\_human — plus the top statuses by count. Use it to tell the user "this affects N active leads" and get confirmation. For per-status funnel metrics use get\_funnel\_report instead.                                                                                                     |
</Accordion>

<Accordion title="Knowledge bases (9)">
  | Tool                    | Scope             | Mode  | Required top-level input            | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
  | ----------------------- | ----------------- | ----- | ----------------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_knowledge_bases`  | `workflows:read`  | Read  | None                                | No contract flag | List the client's knowledge bases with status and document/size counts. Pass workflow\_id to see only the KBs attached to that workflow, ordered by retrieval priority (each row then includes its priority). Ideal for "what knowledge bases exist", "which KBs feed this workflow's agent", or finding a KB id before attaching or adding documents.                                                                                                                                                                                                     |
  | `create_knowledge_base` | `workflows:write` | Write | `name`                              | No contract flag | Create a new, empty knowledge base for the client. After creating, add content with add\_kb\_document and make it live for an agent with attach\_knowledge\_base. Ideal for setting up a fresh document collection (e.g. "Pricing FAQ", "Product docs").                                                                                                                                                                                                                                                                                                   |
  | `update_knowledge_base` | `workflows:write` | Write | `knowledge_base_id`                 | No contract flag | Edit a knowledge base's own fields: its name, its description (what it contains / when the agent should use it), and its status ('archived' shelves it so agents stop using it without deleting; 'active' restores it). Provide only the fields you want to change; at least one is required. This is the ONLY way to change a KB's description or rename a KB, there is no dashboard-only field. Returns 404 if the KB does not belong to this client. Ideal for "rename this KB", "set its description to ...", or "archive the old pricing KB".         |
  | `attach_knowledge_base` | `workflows:write` | Write | `workflow_id`, `knowledge_base_id`  | No contract flag | Attach an existing knowledge base to a workflow so that workflow's agent can retrieve from it. priority orders retrieval when several KBs are attached (lower = consulted first); omitted, it appends after the current lowest-priority KB. Returns 409 CONFLICT if already attached, 404 if the KB does not belong to this client. Ideal for "make the pricing KB available to the sales workflow".                                                                                                                                                       |
  | `detach_knowledge_base` | `workflows:write` | Write | `workflow_id`, `knowledge_base_id`  | No contract flag | Detach a knowledge base from a workflow. The KB and its documents are NOT deleted — the workflow's agent just stops retrieving from it. Returns 404 if the KB was not attached to that workflow. Ideal for "stop the sales agent from using the old pricing KB".                                                                                                                                                                                                                                                                                           |
  | `list_kb_documents`     | `workflows:read`  | Read  | `knowledge_base_id`                 | No contract flag | Page through the documents inside one knowledge base: name, source type (file/web/text), processing status, chunk count and timestamps. Ideal for "what's in this KB", checking whether a just-added document finished processing (status ready), or finding a document id to rename/delete.                                                                                                                                                                                                                                                               |
  | `add_kb_document`       | `workflows:write` | Write | `knowledge_base_id`, `name`, `text` | No contract flag | Add a text document to a knowledge base. The text (max 200KB) is chunked and embedded asynchronously — the response is \{ document\_id, status: "pending" }; poll list\_kb\_documents until status is "ready". Ideal for ingesting FAQs, policy text, product descriptions or any copy the agent should be able to cite.                                                                                                                                                                                                                                   |
  | `rename_kb_document`    | `workflows:write` | Write | `knowledge_base_id`, `document_id`  | No contract flag | Rename a document and/or replace its text content. Pass name to rename (embeddings untouched), text to replace the content, or both. Changing content re-indexes the document: it is re-chunked and re-embedded asynchronously, status goes back to 'pending' and returns to 'ready' when done (poll list\_kb\_documents). Only text documents (source type 'text') accept new content: file/web documents return 409. Returns 404 if the document is not in that KB. Ideal for tidying names after bulk ingestion or updating a FAQ/pricing doc in place. |
  | `delete_kb_document`    | `workflows:write` | Write | `knowledge_base_id`, `document_id`  | No contract flag | Permanently delete a document (and its chunks/embeddings) from a knowledge base. The agent stops retrieving it immediately. Returns 404 if the document is not in that KB. Ideal for removing outdated or wrong content the agent keeps citing.                                                                                                                                                                                                                                                                                                            |
</Accordion>

<Accordion title="Webhooks (7)">
  | Tool                       | Scope             | Mode  | Required top-level input                   | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                       |
  | -------------------------- | ----------------- | ----- | ------------------------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_webhooks`            | `workflows:read`  | Read  | None                                       | No contract flag | List the client's outbound webhooks: name, target URL, subscribed events, active flag and delivery health. Secrets are never included. Ideal for "what webhooks are configured", "is anything listening to meeting.completed", or finding a webhook id to update/test/delete.                                                                                                                           |
  | `configure_status_webhook` | `workflows:write` | Write | `workflow_id`, `status_key`, `name`, `url` | No contract flag | Create an outbound webhook that fires only when a lead enters one specific status in one specific workflow/agent. It subscribes to workflow\_run.status\_changed and installs exact workflow\_id + to\_status.key filters, plus any extra filters. The signing\_secret is returned EXACTLY ONCE. Use one webhook per destination/behavior when different statuses need different payloads or receivers. |
  | `get_webhook`              | `workflows:read`  | Read  | `webhook_id`                               | No contract flag | Get one webhook's full configuration: events, filters, auth type, retry setting and payload template. auth\_config is redacted to key names and the signing\_secret is never returned (it is only shown once, at create time). Ideal for auditing exactly what a webhook sends and when.                                                                                                                |
  | `create_webhook`           | `workflows:write` | Write | `name`, `url`                              | No contract flag | Create an outbound webhook. url must be https and publicly reachable (private/metadata IP ranges are rejected server-side). The response includes the signing\_secret EXACTLY ONCE — surface it to the user immediately; it cannot be retrieved later. Ideal for "notify my CRM when a meeting completes" style integrations.                                                                           |
  | `update_webhook`           | `workflows:write` | Write | `webhook_id`                               | No contract flag | Update an existing webhook. Only the fields you pass change; use is\_active to pause (false) or resume (true) deliveries without deleting the webhook. Returns the updated, redacted configuration — the signing\_secret is never re-issued. Ideal for pointing a webhook at a new URL, changing its event list, or toggling it.                                                                        |
  | `delete_webhook`           | `workflows:write` | Write | `webhook_id`                               | No contract flag | Permanently delete a webhook; deliveries stop immediately. Returns 404 if no webhook matched. To pause temporarily instead, use update\_webhook with is\_active:false.                                                                                                                                                                                                                                  |
  | `test_webhook`             | `workflows:write` | Write | `webhook_id`                               | No contract flag | Fire a synthetic test event at a webhook's URL and report the outcome: \{ delivered, response\_status, duration\_ms, error }. The remote response body is never reflected back. Ideal for verifying a newly created or just-edited webhook actually receives events before relying on it.                                                                                                               |
</Accordion>

<Accordion title="Tags (3)">
  | Tool         | Scope         | Mode  | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                     |
  | ------------ | ------------- | ----- | ------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_tags`  | `leads:read`  | Read  | None                     | No contract flag | Page through the client's tag catalog (id, name, slug, description). search matches name, slug and description. Ideal for "what tags exist", finding a tag id before set\_tag/delete\_tag, or checking a slug before creating a similar tag. To tag an individual lead use sync\_lead\_tags instead.                                                                                  |
  | `set_tag`    | `leads:write` | Write | None                     | No contract flag | Create or update a tag in the catalog (upsert). OMIT tag\_id to CREATE: name is required and slug is auto-generated from it unless given. PASS tag\_id to UPDATE that existing tag's name/slug/description (only provided fields change). Returns the tag; 409 CONFLICT if the slug already exists for this client. Leads already carrying an updated tag keep it — renaming is safe. |
  | `delete_tag` | `leads:write` | Write | `tag_id`                 | No contract flag | Permanently delete a tag from the catalog AND remove it from every lead that carries it (cascade). Returns 404 if no tag matched. Ideal for retiring obsolete tags; to merely rename one, use set\_tag with tag\_id instead.                                                                                                                                                          |
</Accordion>

<Accordion title="Processors (6)">
  | Tool                    | Scope             | Mode  | Required top-level input  | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
  | ----------------------- | ----------------- | ----- | ------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_processors`       | `workflows:read`  | Read  | None                      | No contract flag | List the client's pre-workflow processors (lead-routing rule engines): name, default workflow, active flag and rule count. Deactivated processors are hidden unless include\_inactive is true. Ideal for "how are incoming leads routed", or finding a processor id before get\_processor / set\_processor\_rule.                                                                                                                                                 |
  | `get_processor`         | `workflows:read`  | Read  | `processor_id`            | No contract flag | Get one processor with its full rule list: each rule's conditions, target workflow, evaluation position and active flag. Rules are evaluated in position order (1 first); the first match wins. Ideal for auditing routing logic before editing it with set\_processor\_rule.                                                                                                                                                                                     |
  | `set_processor`         | `workflows:write` | Write | None                      | No contract flag | Create or update a pre-workflow processor (upsert). OMIT processor\_id to CREATE: name and default\_workflow\_id are required, and you may seed up to 50 rules atomically (if any rule fails, the whole create rolls back). PASS processor\_id to UPDATE name/description/default\_workflow\_id/is\_active — rules cannot be passed on update; manage them with set\_processor\_rule / delete\_processor\_rule. default\_workflow\_id must belong to this client. |
  | `delete_processor`      | `workflows:write` | Write | `processor_id`            | No contract flag | Soft-deactivate a processor: it stops evaluating rules and routing leads, but the processor and its rules are kept (visible via list\_processors include\_inactive:true) and can be reactivated with set\_processor is\_active:true. Returns \{ deactivated: true }.                                                                                                                                                                                              |
  | `set_processor_rule`    | `workflows:write` | Write | `processor_id`            | No contract flag | Create or update one routing rule on a processor (upsert). OMIT rule\_id to CREATE: name, workflow\_id and conditions (1-20, ALL must match) are required. PASS rule\_id to UPDATE — only provided fields change; passing position (1-based, 1 = evaluated first) also reorders the rule, which is how rules are reordered. workflow\_id must belong to this client. Empty condition lists are rejected: they would match every lead.                             |
  | `delete_processor_rule` | `workflows:write` | Write | `processor_id`, `rule_id` | No contract flag | Permanently delete one routing rule from a processor. Leads that would have matched it fall through to later rules or the default workflow. Returns 404 if the rule is not on that processor.                                                                                                                                                                                                                                                                     |
</Accordion>

<Accordion title="Meeting types (5)">
  | Tool                       | Scope             | Mode  | Required top-level input               | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
  | -------------------------- | ----------------- | ----- | -------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `list_meeting_types`       | `workflows:read`  | Read  | `workflow_id`                          | No contract flag | List a workflow's meeting types exactly as the dashboard form shows them: name, duration, meeting buffer, min notice, max days ahead, calendar title/invite templates, type (video with video\_provider google\_meet/teams, phone, in\_person with location\_details), overbooking + maximum per time slot, color, is\_active, the free-text agent\_selection\_criteria and the enforced agent\_selection\_rules (see set\_meeting\_type\_routing). Ideal for "what appointment kinds can this workflow book" or finding a meeting type id before update\_meeting\_type / delete\_meeting\_type.                                                                                                                                                                                                                                                                                                                                                                                                               |
  | `create_meeting_type`      | `workflows:write` | Write | `workflow_id`, `name`                  | No contract flag | Create the first and only meeting type for an appointment workflow that currently has none. Requires a name; omitted fields receive the dashboard defaults (30 min, 15 min buffer, 2 h notice, 14 days ahead, video). The type is created ACTIVE; it becomes bookable once a host with availability is assigned (add\_executive). If one already exists, returns it explicitly with status="existing" and never creates another. If several exist, fails with MULTIPLE\_MEETING\_TYPES so the operator can consolidate them. Bad values fail with 400 listing the allowed options (e.g. location\_type must be video, phone or in\_person).                                                                                                                                                                                                                                                                                                                                                                    |
  | `update_meeting_type`      | `workflows:write` | Write | `workflow_id`, `meeting_type_id`       | No contract flag | Update one meeting type by id (at least one field required; only provided fields change) — every field of the dashboard meeting form. Pass null for description / event\_description\_template / location\_details / video\_provider / max\_bookings\_per\_slot to clear them. is\_active switches the type on or off: activating while another type is active fails with 409 MT\_EXISTS; deactivating the only active type of a live appointment agent fails with 409 LAST\_ACTIVE\_MEETING\_TYPE. Bad values fail with 400 listing the allowed options. Returns 404 if the meeting type is not in that workflow. Ideal for "make demos 45 minutes", "require 24h notice", "make it in person at the showroom", "use Teams instead of Meet".                                                                                                                                                                                                                                                                  |
  | `set_meeting_type_routing` | `workflows:write` | Write | `workflow_id`, `agent_selection_rules` | No contract flag | Write the enforced host routing rules (agent\_selection\_rules) of a meeting type and read them back. Unlike agent\_selection\_criteria (free text the AI interprets), these rules are applied server-side when slots are offered and booked. Every host reference is validated against the hosts assigned to the meeting type (list\_executives; pass user ids, names are resolved to the assigned host and stored by name). Examples: two hosts strictly alternating → \{routing:"cycle", tiers:\[\{agents:\[A,B], mode:"cycle", pattern:\[0,1]}]}; leads with renta >= 50000 to Ana, the rest split 2:1 between Bruno and Carla, below 0 disqualified → \{field:"renta", tiers:\[\{min:50000, agents:\[ana]}, \{min:0, agents:\[bruno, carla], weights:\[2,1]}, \{min:-1e9, action:"disqualify"}]}. Pass agent\_selection\_rules: null to clear. meeting\_type\_id may be omitted when the workflow has exactly one meeting type. 400 lists what is wrong (unassigned host, unordered tiers, unknown mode). |
  | `delete_meeting_type`      | `workflows:write` | Write | `workflow_id`, `meeting_type_id`       | No contract flag | Delete a meeting type from a workflow. The response reports impact: agent\_assignments\_removed and future\_events\_orphaned (already-booked meetings keep their calendar events but lose the type link). Returns 409 LAST\_APPOINTMENT\_TYPE when the workflow's goal is 'appointment' and this is its only remaining type — an appointment workflow must keep at least one. 404 if the id is not in that workflow.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
</Accordion>

<Accordion title="Agent configuration (12)">
  | Tool                         | Scope             | Mode  | Required top-level input      | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
  | ---------------------------- | ----------------- | ----- | ----------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_workflow_status`        | `workflows:read`  | Read  | `workflow_id`, `status_key`   | No contract flag | Read one workflow status's complete configuration without changing it: label/category/flags, entry\_hint, required-field and transition gates, timeout, transfer, pause and assignment behavior. Use this before update\_workflow\_status and preserve exact labels/casing unless the user explicitly asks to rename them.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  | `update_workflow_status`     | `workflows:write` | Write | `workflow_id`, `status_key`   | No contract flag | Configure one existing funnel status exactly like the dashboard stage editor. entry\_hint is the natural-language qualification/entry gate for that status; requires\_all\_fields or required\_field\_keys adds a deterministic variable gate; transition\_rules adds structured qualification rules; timeout\_config auto-moves stale leads; terminal transfer\_config moves the lead to another specialized agent/workflow and can copy collected fields; pause\_bot stops the current agent; assignment\_config (\{mode, agent\_ids, restrict\_booking\_to\_assignee}) assigns a human team member on entry — only ONE status per workflow may carry it (409 ASSIGNMENT\_CONFIG\_EXISTS with holder\_status\_key; clear it there with assignment\_config:null first). category must be active/won/lost/paused/deferred. System stages other than the escalation stage and the virtual Discarded stage refuse writes with 409 PROTECTED\_STATUS. Read get\_workflow\_status first and change only intended fields; preserve the exact label unless renaming was explicitly requested.                                                                               |
  | `list_workflow_voices`       | `workflows:read`  | Read  | `workflow_id`                 | No contract flag | List the voice catalog usable by a workflow's call agent: public voices plus the client's private voices, each with id, voice\_id, name, provider, language, gender and a preview\_url (a playable .mp3 sample link you can hand the user to hear the voice). Use this to pick a voice\_id for set\_workflow\_voice, or to show the user samples before switching.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
  | `set_workflow_voice`         | `workflows:write` | Write | `workflow_id`                 | No contract flag | Switch and/or tune the workflow's call voice. To CHANGE which voice the lead hears, pass ONE of: gender ('male'/'female' — the server picks a matching voice in the workflow's language, e.g. a male voice for 'voz de hombre'), voice\_id (an exact id from list\_workflow\_voices), or voice\_name (a name to match). The server writes the effective voice where the call runtime actually reads it and returns resolved\_voice with a preview\_url (.mp3) you should share with the user so they can hear it. To TUNE the current voice, pass a voice object with knobs (voiceSpeed, voiceTemperature, volume); these are key-level merged and preserved. Provide at least one of gender/voice\_id/voice\_name/voice. Unknown voice\_id or no gender match returns INVALID\_VOICE with available\_voices. Version-snapshotted.                                                                                                                                                                                                                                                                                                                                    |
  | `get_workflow_cadence`       | `workflows:read`  | Read  | `workflow_id`                 | No contract flag | Read a workflow's outreach cadence (block-config): the sequenced contact blocks (channel, delay, templates), timing/business-hours config and retry behaviour.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | `set_workflow_cadence`       | `workflows:write` | Write | `workflow_id`, `block_config` | No contract flag | Replace a workflow's outreach cadence (block-config). Read the current one with get\_workflow\_cadence first and send the full edited object — this is a whole-document PUT, not a merge. It does NOT set the WhatsApp opening template: dayConfig.config.opening\_template is ignored when unchanged and REJECTED when changed (use set\_opening\_templates, which validates the opener). WhatsApp template names referenced by blocks must exist and be APPROVED on the client's WABAs; business hours are re-derived server-side.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
  | `get_workflow_qualification` | `workflows:read`  | Read  | `workflow_id`                 | No contract flag | Read a workflow's lead-qualification model (futurology): the scoring categories and the conditions that classify a lead into them.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
  | `set_workflow_qualification` | `workflows:write` | Write | `workflow_id`                 | No contract flag | Write a workflow's lead-qualification model (futurology). categories and conditions address the SAME rows under two vocabularies (category\_key/category\_name/description = condition\_key/condition\_name/condition\_description), so a key may appear once per call. Every row needs its key AND its human name (condition\_name / category\_name — never invented by the server); threshold\_type, timing\_type and scope are closed enums and wrong types are refused with 400 naming the index and field. Default is a merge (upsert by key, unsent columns keep their stored value); pass replace:true to clear the whole model and write what you send. get\_workflow\_qualification returns rows under the same field names, so a read-modify-write needs no translation. Provide at least one of categories/conditions.                                                                                                                                                                                                                                                                                                                                     |
  | `delete_workflow_status`     | `workflows:write` | Write | `workflow_id`, `status_key`   | No contract flag | DESTRUCTIVE: permanently delete a funnel status from a workflow. Call get\_pipeline\_impact FIRST to see how many leads sit on each status. If any leads are on the status you must pass migration\_target (the status key those leads are moved to) or the call fails with STATUS\_HAS\_LEADS and the lead count. The only initial status and the last terminal status can never be deleted.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
  | `delete_workflow_field`      | `workflows:write` | Write | `workflow_id`, `field_key`    | No contract flag | DESTRUCTIVE: permanently delete a data field (variable) from a workflow. Leads' previously collected answers are preserved (detached from the field but kept in history); the field is removed from the funnel and the agent stops collecting it. Refuses with FIELD\_IN\_USE (409) when the field still gates a status (required fields / transition rules) or a qualification rule — remove those references first, then delete. There is no undo — prefer editing the field with update\_workflow\_structure over deleting it.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
  | `delete_workflow`            | `workflows:write` | Write | `workflow_id`                 | `confirm: true`  | DESTRUCTIVE / IRREVERSIBLE: delete an entire agent (workflow) — its funnel, fields, cadence and configuration. It is a soft-delete (archive), not a hard purge, but there is no in-chat undo, so treat it as permanent and get explicit user sign-off first. Preview-then-confirm: call with confirm:false (or omit it) to get a \{ status:'needs\_confirmation' } preview that writes NOTHING; only call again with confirm:true to actually delete. The backend REFUSES the delete when the agent still has active leads in its pipeline: that returns \{ status:'blocked', reason:'agent\_has\_leads', lead\_count } (no exception) so you can tell the user how many leads must be moved or closed first (use get\_pipeline\_impact to inspect them). / DESTRUCTIVO E IRREVERSIBLE: elimina un agente (workflow) completo. Es un archivado (borrado suave) sin deshacer en el chat; pide confirmación explícita. Primero confirm:false para previsualizar sin escribir, luego confirm:true para eliminar. Si el agente aún tiene leads activos, el backend lo rechaza y devuelve \{ status:'blocked', reason:'agent\_has\_leads', lead\_count } sin lanzar error. |
  | `restore_workflow`           | `workflows:write` | Write | `workflow_id`                 | No contract flag | Un-archive (restore) an agent that was previously deleted with delete\_workflow. Archive is a soft-delete, and this is its inverse: it clears the archive so the agent is listable and editable again. The agent comes back PAUSED and inactive — the channels it had (WhatsApp / phone / Instagram / Meta) were released when it was archived and are NOT re-attached, and its old leads/runs stay paused; reconnect channels and activate explicitly afterwards. Find the archived agent's id first with list\_workflows include\_archived:true. Idempotent: restoring an agent that isn't archived returns \{ status:'already\_live' } without error. / Restaura (desarchiva) un agente eliminado con delete\_workflow. El borrado es suave y esto es su inverso: el agente vuelve a aparecer y a ser editable, pero PAUSADO e inactivo; sus canales fueron liberados al archivar y NO se reconectan solos. Usa list\_workflows include\_archived:true para encontrar su id.                                                                                                                                                                                       |
</Accordion>

<Accordion title="Executives (4)">
  | Tool               | Scope             | Mode  | Required top-level input      | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | ------------------ | ----------------- | ----- | ----------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | `list_executives`  | `workflows:read`  | Read  | `workflow_id`                 | No contract flag | List a workflow's executives — the human hosts who take its meetings — with their user, active flag and assigned meeting types.                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | `add_executive`    | `workflows:write` | Write | `workflow_id`, `user_id`      | No contract flag | Add a team member as an executive (meeting host) of a workflow, optionally restricted to specific meeting types. The user must belong to the client's team (see get\_team); adding someone who is already a host fails with a conflict. Assigning the host to a meeting type that was created inactive (seeded in the dashboard before any host existed) activates it, unless another type is already active; the response lists meeting\_types\_activated. Pass meeting\_type\_ids explicitly for that to happen — omitting it links no meeting type. |
  | `update_executive` | `workflows:write` | Write | `workflow_id`, `executive_id` | No contract flag | Update a workflow executive: toggle is\_active and/or replace their full meeting-type set (meeting\_type\_ids overwrites the current assignments — pass the complete list). Provide at least one field. Linking the host (or switching them back on) activates a meeting type that was created inactive, unless another type is already active; the response lists meeting\_types\_activated.                                                                                                                                                          |
  | `remove_executive` | `workflows:write` | Write | `workflow_id`, `executive_id` | No contract flag | Remove an executive (meeting host) from a workflow. Their existing meetings are untouched; they just stop receiving new ones.                                                                                                                                                                                                                                                                                                                                                                                                                          |
</Accordion>

<Accordion title="Advanced (1)">
  | Tool                         | Scope            | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                              |
  | ---------------------------- | ---------------- | ---- | ------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | `describe_advanced_features` | `workflows:read` | Read | None                     | No contract flag | Map every surface in the dashboard Advanced hub to its purpose, execution model, MCP tools, and safety considerations. Use this as the entry point for Advanced configuration. |
</Accordion>

<Accordion title="Agent system (2)">
  | Tool                           | Scope            | Mode | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
  | ------------------------------ | ---------------- | ---- | ------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `describe_agent_configuration` | `workflows:read` | Read | None                     | No contract flag | Complete reference for designing and configuring one or many Nexor agents through MCP: prompts, statuses and qualification gates, variables, cadence, tools, pre-execution hooks, stage gates, webhooks, transfers, Cloud/Scheduled Functions, and the required clarification/sign-off workflow. Call this before proposing a non-trivial or multi-agent build.                                                                                                                                                                                                                                                                                                                                               |
  | `review_agent_system_plan`     | `workflows:read` | Read | `plan`                   | No contract flag | Preflight a complete single- or multi-agent configuration before any mutations. Finds missing identities, goals, status gates, transfer targets, channels/language/timezone (every agent needs an IANA timezone — it anchors booking slots), planned channels with no verified resource on the account, webhook destinations, booking prerequisites for appointment agents (meeting type, host, calendar plan or external provider), and operational risks; returns a stable plan fingerprint and the exact final sign-off prompt. Do not create/update agents, tools, hooks, webhooks, functions, schedules, jobs, or transfers until this review is clean and the user explicitly approves the fingerprint. |
</Accordion>

<Accordion title="Agent groups (4)">
  | Tool                 | Scope             | Mode  | Required top-level input | Safeguard                         | Canonical purpose                                                                                                                                                                                            |
  | -------------------- | ----------------- | ----- | ------------------------ | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | `list_agent_groups`  | `workflows:read`  | Read  | None                     | No contract flag                  | List active agent groups with their ids, names, and descriptions. Use this before assigning an agent by group name; list\_workflows returns each agent's current master\_workflow\_id membership.            |
  | `create_agent_group` | `workflows:write` | Write | `name`                   | No contract flag                  | Create an agent group. To create and assign in one conversation, create the group first, then call update\_workflow with the returned group id as master\_workflow\_id, and read back both lists.            |
  | `update_agent_group` | `workflows:write` | Write | `agent_group_id`         | No contract flag                  | Rename an agent group or change its description. Pass only the fields to update. This does not change agent membership; use update\_workflow\.master\_workflow\_id for that.                                 |
  | `delete_agent_group` | `workflows:write` | Write | `agent_group_id`         | Operator approval in instructions | Delete (deactivate) an agent group after explicit confirmation. The backend unassigns its member agents; it does not delete those agents. Read back list\_agent\_groups and list\_workflows after the write. |
</Accordion>

<Accordion title="Calendars (3)">
  | Tool                       | Scope             | Mode  | Required top-level input   | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
  | -------------------------- | ----------------- | ----- | -------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `connect_calendar`         | `calendars:write` | Write | `user_id`, `provider`      | `confirm: true`  | Start connecting a team member's Google or Outlook calendar (the host's busy time and conferencing link for bookings). Returns connect\_url, expires\_at (10 min) and connection\_request\_id. IMPORTANT — hand connect\_url to the user DIRECTLY as a clickable link and say who must open it (the host signs in and grants calendar access there; it cannot be completed in chat). When the target user is NOT the operator you are talking to, you MUST first tell the operator whose calendar will be linked and get an explicit yes, then call again with confirm=true — the backend refuses with CONFLICT/CONFIRMATION\_REQUIRED otherwise. Other refusals: USER\_NOT\_ACCEPTED (fix: invite\_user and wait for acceptance), PROVIDER\_UNAVAILABLE (Outlook not enabled here), OTHER\_PROVIDER\_ACTIVE (disconnect the other provider first). Afterwards poll get\_calendar\_connections until status=active and scopes\_ok=true. |
  | `get_calendar_connections` | `calendars:read`  | Read  | None                       | No contract flag | List calendar connections (Google, Outlook, Calendly) for the account or one team member: provider, status (active / needs\_reauth / revoked / error), role, calendar\_email, scopes\_ok (false = reconnect with connect\_calendar), last\_error, connected\_at. Poll this after connect\_calendar; the host is bookable with busy-time awareness once a row is active with scopes\_ok=true.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  | `disconnect_calendar`      | `calendars:write` | Write | `connection_id`, `confirm` | `confirm: true`  | Revoke a host's calendar connection (the agent stops reading their busy time and creating events there; Outlook accounts are also removed from the provider). Preview-then-confirm: call with confirm=false first — returns \{ requires\_confirm: true, connection } and changes NOTHING; show the operator whose calendar it is, then call again with confirm=true. Reads the connection back after revoking.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
</Accordion>

<Accordion title="Availability (5)">
  | Tool                    | Scope             | Mode  | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
  | ----------------------- | ----------------- | ----- | ------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_host_availability` | `people:read`     | Read  | `user_id`                | No contract flag | Read a team member's booking availability: timezone (host's own or seeded from the account), schedule flags, weekly slots grouped by weekday (0=Sunday), blocked dates, and slot\_count. A host with slot\_count 0 and no Calendly cannot be booked (BOOKING\_AVAILABILITY\_REQUIRED).                                                                                                                                                                                                                                                                           |
  | `set_host_schedule`     | `calendars:write` | Write | `user_id`, `slots`       | No contract flag | Replace a team member's whole weekly schedule in one call (atomic: the previous slots are removed). slots = \[\{ weekday 0-6, start 'HH:MM', end 'HH:MM' }] — e.g. Monday-Friday 09:00-17:00 is five entries with weekday 1..5. Overlapping slots on one weekday, end before start, or an unknown IANA timezone are refused with the offending field. timezone defaults to the host's current one, else the account timezone (seeded). Returns the persisted availability; readiness recomputes and BOOKING\_AVAILABILITY\_REQUIRED clears once slot\_count > 0. |
  | `set_host_timezone`     | `calendars:write` | Write | `user_id`, `timezone`    | No contract flag | Set (or clear with null) a team member's availability timezone without touching their slots. Unknown IANA zones are refused. Setting a zone also turns respect\_own\_timezone on unless you pass it explicitly. Returns the persisted availability.                                                                                                                                                                                                                                                                                                              |
  | `set_host_blocks`       | `calendars:write` | Write | `user_id`                | No contract flag | Add and/or remove a team member's blocked dates (time off). add = \[\{ date 'YYYY-MM-DD', start?, end?, all\_day?, reason? }] (omit times for all-day); remove = block ids from get\_host\_availability. Applied in order (removes first, then adds); returns the persisted availability with the final block list.                                                                                                                                                                                                                                              |
  | `auto_assign_solo_host` | `workflows:write` | Write | `workflow_id`            | No contract flag | Make a team member the meeting host of an appointment workflow and cover all its meeting types — the one-call setup for a single-host account. Omit user\_id when the account has exactly one eligible member (owner/admin/human\_agent); with several, the backend answers MULTIPLE\_HOSTS with candidates and you pass user\_id. Idempotent. Returns the assignment plus that host's availability; follow with set\_host\_schedule and connect\_calendar if slot\_count is 0 or no calendar is active.                                                         |
</Accordion>

<Accordion title="Calendly (9)">
  | Tool                        | Scope             | Mode  | Required top-level input                                           | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | --------------------------- | ----------------- | ----- | ------------------------------------------------------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `connect_calendly`          | `workflows:write` | Write | None                                                               | No contract flag | Start connecting the client's Calendly account: returns a hosted Composio authorization URL (connect\_url, expires in \~10 min) the operator opens to grant access. IMPORTANT — give connect\_url to the user DIRECTLY as a clickable link and tell them to open it; the authorization happens entirely on that page and CANNOT be completed in chat. After they finish, Nexor registers the webhook subscription and starts provisioning automatically. Poll get\_calendly\_status until state=connected (plan\_required means the Calendly plan has no webhook support). Fails with already\_connected when an active connection exists — pass reconnect=true to re-authorize. Next: list\_calendly\_event\_types, then set\_calendly\_binding per host per meeting type. |
  | `get_calendly_status`       | `workflows:read`  | Read  | None                                                               | No contract flag | Read the client's Calendly connection: state (not\_connected / connected / plan\_required / disconnected), webhook health\_status, plan\_tier, host\_mode, last provisioning report (per-host outcomes: wired / needs\_mapping / no\_event\_type / primary\_conflict) and the Composio account status. The poll target after connect\_calendly and the place to read provisioning results.                                                                                                                                                                                                                                                                                                                                                                                  |
  | `list_calendly_event_types` | `workflows:read`  | Read  | None                                                               | No contract flag | List the connected Calendly account's event types: uri (the API uri set\_calendly\_binding needs), name, duration\_minutes, active, scheduling\_url, kind and owner. Defaults to the connecting user's event types; pass owner\_uri (a Calendly user uri from the provisioning report hosts\[].uri) to list another host's. Only an ACTIVE event type whose duration equals the meeting type's duration can be bound.                                                                                                                                                                                                                                                                                                                                                       |
  | `set_calendly_binding`      | `workflows:write` | Write | `workflow_id`, `meeting_type_id`, `host_user_id`, `event_type_uri` | No contract flag | Bind a Calendly event type to ONE host for ONE meeting type of a workflow (the per-host model; there is no per-workflow link to manage). The backend validates the event type is active and its duration equals the meeting type's duration\_minutes (400 duration\_mismatch otherwise), assigns the host to the workflow/meeting type if needed, writes the binding and reads it back. The first binding on a workflow switches that workflow to Calendly mode: native booking tools are gated and get\_available\_slots reads Calendly. Pass event\_type\_uri=null to clear a host's binding (the host then appears under excluded\_hosts). Repeat per host per meeting type; verify with list\_calendly\_bindings.                                                       |
  | `list_calendly_bindings`    | `workflows:read`  | Read  | `workflow_id`                                                      | No contract flag | Read a workflow's Calendly wiring: workflow\_mode (calendly / native), the per-host bindings (host, meeting type, event\_type\_uri) and excluded\_hosts — hosts assigned to a meeting type WITHOUT an event type (reason no\_event\_type\_binding) who are silently missing from availability until set\_calendly\_binding fixes them. Optionally filter by meeting\_type\_id.                                                                                                                                                                                                                                                                                                                                                                                              |
  | `set_calendly_host_mode`    | `workflows:write` | Write | `mode`                                                             | No contract flag | Set the Calendly host mode. 'teams' is the only value: hosts are the Calendly organization members, each mapped to a Nexor user and wired per meeting type by provisioning. Enqueues a provisioning pass; read the outcome with get\_calendly\_status or run provision\_calendly for an immediate report.                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
  | `map_calendly_hosts`        | `workflows:write` | Write | `calendly_user_uri`, `host_user_id`                                | No contract flag | Map a Calendly host (calendly\_user\_uri from the provisioning report hosts\[] with outcome needs\_mapping) to a Nexor user, or pass host\_user\_id=null to unassign. The uri must come from the last provisioning report — run provision\_calendly first. Fails with primary\_conflict when the user already books through another calendar (e.g. Google) and cross\_client\_primary when they are a host in another client. Enqueues a provisioning pass afterwards.                                                                                                                                                                                                                                                                                                      |
  | `provision_calendly`        | `workflows:write` | Write | None                                                               | No contract flag | Run Calendly provisioning now and return the report: discovers the organization's hosts, maps them to Nexor users (explicit mapping > email match > needs\_mapping), resolves each host's event type and wires workflow\_agent\_meeting\_types for every workflow in Calendly mode. Report hosts\[] outcomes: wired / needs\_mapping (→ map\_calendly\_hosts) / no\_event\_type (→ set\_calendly\_binding) / primary\_conflict / cross\_client\_primary. Requires host mode set and at least one workflow bound. Pass wait=false to enqueue instead and poll get\_calendly\_status.                                                                                                                                                                                         |
  | `disconnect_calendly`       | `workflows:write` | Write | None                                                               | `confirm: true`  | Disconnect Calendly for the client: deletes the webhook subscription, deactivates the integration and revokes the Composio account. Workflows bound to Calendly stop receiving Calendly bookings; per-host bindings are kept for a later reconnect. Preview-then-confirm: call with confirm:false (or omit it) to get a \{ status:'needs\_confirmation' } preview that writes NOTHING; only call again with confirm:true after the operator explicitly confirms.                                                                                                                                                                                                                                                                                                            |
</Accordion>

<Accordion title="Booking settings (8)">
  | Tool                                 | Scope             | Mode  | Required top-level input                         | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
  | ------------------------------------ | ----------------- | ----- | ------------------------------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_workflow_booking_settings`      | `workflows:read`  | Read  | `workflow_id`                                    | No contract flag | Read a workflow's booking settings in one call: default\_attendees (people invited to every booked meeting), host\_assigner (CRM seller-assigner config) and external\_booking (client-owned booker config). Use it before set\_default\_attendees / set\_host\_assigner / set\_external\_booking to see the current state.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | `set_default_attendees`              | `workflows:write` | Write | `workflow_id`, `attendees`                       | No contract flag | Replace the people invited to EVERY meeting booked on this workflow (e.g. a sales manager who sits in on all calls). Full-state: the list sent IS the list afterwards; send \[] to clear. Entries are \{email, name?}; emails are validated and deduped. They appear on the next booked event's calendar invite alongside the host and the lead.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | `get_meeting_confirmation_email`     | `workflows:read`  | Read  | `workflow_id`, `meeting_type_id`                 | No contract flag | Read a meeting type's lead confirmation email settings (email\_config) and the list of allowed keys. Use before set\_meeting\_confirmation\_email; the write replaces the whole object.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
  | `set_meeting_confirmation_email`     | `workflows:write` | Write | `workflow_id`, `meeting_type_id`, `email_config` | No contract flag | Configure the confirmation email the lead receives when a meeting of this type is booked — subject, title, greeting, CTA label, calendar note, extra sections, disclaimer, sender name, or send\_to\_lead:false to suppress it. Same keys as the dashboard's email panel; unknown keys are rejected (400) because the renderer never reads them. Replaces the whole email\_config (read it first to keep other fields); null clears it. Use preview\_meeting\_confirmation\_email to see the result before/after saving.                                                                                                                                                                                                                                                                                                                                                                                                              |
  | `preview_meeting_confirmation_email` | `workflows:read`  | Read  | `workflow_id`, `meeting_type_id`                 | No contract flag | Render the lead confirmation email (subject + HTML) for a meeting type with sample data, using a draft email\_config if given or the persisted one otherwise. Sends nothing. Use it to show the operator what the lead will receive before calling set\_meeting\_confirmation\_email.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
  | `set_host_assigner`                  | `workflows:write` | Write | `workflow_id`                                    | No contract flag | Declare the workflow's CRM seller assigner: an existing ACTIVE workflow tool whose response names the seller, so bookings go to that seller's calendar and the lead's owner mirrors the CRM. tool = the workflow\_tools name; id\_field = the response field carrying the seller id; external\_key = the client\_users.external\_ids key that maps it to a Nexor user (e.g. hubspot\_owner\_id), or identity:true when the tool already returns a Nexor user\_id. Validates keys and that the tool exists and is active (400 otherwise), writes config.host\_assigner, then RUNS the test connection (real call to the client's endpoint) and returns its report — the config is persisted even when the test fails (ok:false with the failing step) so you can iterate; test:false skips it. clear:true removes the assigner. Never write host\_assigner through update\_workflow\_config.                                           |
  | `test_host_assigner`                 | `workflows:write` | Write | `workflow_id`                                    | No contract flag | Dry-run the configured host assigner without touching any lead: calls the assigner tool for real, extracts the seller id (id\_field), maps it to a Nexor team member and checks their calendar connection. Returns ok plus per-step checks, the fields the response actually carries (to pick id\_field), and the resolved user. Pass tool/id\_field/external\_key/identity to test a variant before saving with set\_host\_assigner.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
  | `set_external_booking`               | `workflows:write` | Write | `workflow_id`, `external_booking`                | No contract flag | Declare that the client's OWN booker (their HTTP tools) owns the calendar for this workflow, so Nexor mirrors every booking into a meeting with reminders and confirmation emails. All three verbs are REQUIRED — tool (create), reschedule\_tool and cancel\_tool — because an omitted verb is silently never mirrored (phantom meetings); reschedule\_tool must differ from tool. fields maps dot-paths in the RAW tool response (data.slots.0.start style, never brackets): starts\_at is required, ends\_at/meeting\_url/external\_id/title/timezone optional. Every referenced tool (incl. slots\_tool/slots\_tools) must exist and be active on the workflow (400 TOOL\_NOT\_FOUND otherwise). provider defaults to external\_booker (auto-gates native booking tools); gohighlevel needs no fields. Replaces the whole section and reads it back; null clears. Never write external\_booking through update\_workflow\_config. |
</Accordion>

<Accordion title="CRM connections (3)">
  | Tool                        | Scope             | Mode  | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | --------------------------- | ----------------- | ----- | ------------------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `connect_crm`               | `workflows:write` | Write | `provider`               | No contract flag | Start connecting the client's CRM (hubspot, zoho, kommo or gohighlevel). Returns connect\_url + connection\_request\_id. IMPORTANT — give connect\_url to the user DIRECTLY as a clickable link and tell them to open it: HubSpot/Zoho authorize on the vendor's consent page; Kommo/GoHighLevel paste their token into a Nexor-hosted form. The credentials are entered on that page only — never ask the user to paste a token in chat, and never claim you connected it for them. Then poll get\_crm\_connection\_status with the connection\_request\_id until status=completed (last\_error explains a rejected attempt; the same link stays valid until expires\_at). Reconnecting an already-connected CRM issues a fresh link. |
  | `get_crm_connection_status` | `workflows:read`  | Read  | `provider`               | No contract flag | Connection state of one CRM provider for the client (connected, status, account/org/location identity, last sync + error — never tokens). Pass connection\_request\_id (from connect\_crm) to also see that issuance: pending \| completed \| expired \| failed with last\_error. Use after connect\_crm and for "is HubSpot connected" questions; get\_integration\_status gives the cross-provider summary.                                                                                                                                                                                                                                                                                                                          |
  | `disconnect_crm`            | `workflows:write` | Write | `provider`               | `confirm: true`  | Disconnect the client's CRM (stops its sync immediately; configuration is kept so a reconnect restores it). Destructive for the live sync: ask the user first and call with confirm=true only after they explicitly agree. Without confirm=true nothing changes and the response explains what would be disconnected.                                                                                                                                                                                                                                                                                                                                                                                                                  |
</Accordion>

<Accordion title="HubSpot (10)">
  | Tool                            | Scope             | Mode  | Required top-level input | Safeguard        | Canonical purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | ------------------------------- | ----------------- | ----- | ------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `get_hubspot_config`            | `workflows:read`  | Read  | None                     | No contract flag | Read the client's whole HubSpot post-connect configuration in one call: connection (hub, auth mode, scopes, sync health), default\_workflow\_id, per-field outbound mappings (field\_mappings), the stage → lifecyclestage mapping (lifecycle\_mapping), list routing rules (HubSpot list → workflow), deal\_sync settings, sync\_back, and owner\_mappings (team members with the HubSpot owner id stored on them under external\_key). Fails with not\_connected until connect\_crm(provider=hubspot) completes. Start here before any set\_hubspot\_\* call so you never overwrite what the dashboard configured.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
  | `set_hubspot_field_mappings`    | `workflows:write` | Write | `mappings`               | No contract flag | Write outbound field mappings (Nexor field → HubSpot contact property), one row per nexor\_field; rows not listed are left untouched. hubspot\_property=null removes that field's mapping. Optional per row: nexor\_field\_type (text/number/date/boolean…), write\_once (never overwrite a value already in HubSpot), value\_mapping (\{ nexor\_value: hubspot\_option }), is\_active, hubspot\_property\_label, hubspot\_property\_type. Use get\_hubspot\_config first; the stage → lifecycle mapping is set\_hubspot\_lifecycle\_mapping, not this. Returns applied rows and the full read-back.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
  | `set_hubspot_lifecycle_mapping` | `workflows:write` | Write | `value_mapping`          | No contract flag | Set how Nexor stages map onto a HubSpot contact property (default lifecyclestage): value\_mapping = \{ nexor\_status\_key: hubspot\_option\_internal\_value }, e.g. \{ qualified: 'salesqualifiedlead', booked: 'opportunity' }. Pass value\_mapping=null to clear. Stage keys come from get\_workflow; option values are the HubSpot property's internal option values. Returns the stored row.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
  | `set_hubspot_list_routing`      | `workflows:write` | Write | `rules`                  | No contract flag | Replace the HubSpot list → workflow routing with the given rules (FULL replace: a list omitted here stops being routed; pass rules=\[] to clear). Each rule: list\_id (numeric HubSpot list id, or v3:\<id>), workflow\_id (the agent that receives contacts entering the list), optional name, recurring (keep pulling new members), pause\_on\_exit (pause the lead when it leaves the list), sync\_interval\_minutes (supported intervals only). Read the current rules with get\_hubspot\_config and send them back with your change — this is not a merge. Then run\_hubspot\_import(list\_id) to pull the current members.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
  | `set_hubspot_deal_sync`         | `workflows:write` | Write | `enabled`                | No contract flag | Configure deal sync (HubSpot deal stage changes → Nexor conversions/lost). enabled=true requires pipeline\_id (a HubSpot DEAL pipeline id); active\_stages are the stage ids that count as won (creates a conversion of conversion\_type\_id when the deal reaches them), lost\_stages the ones that mark the lead lost. Optional workflow\_id pins which agent's leads are swept (default: the connection's default workflow). Ids are validated against HubSpot (404 pipeline\_not\_found / stage\_not\_found with the available ones). Runtime keys (cursor, last\_swept\_at) are preserved. Returns the stored deal\_sync.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
  | `map_hubspot_owners_to_hosts`   | `workflows:write` | Write | `mappings`               | No contract flag | Map HubSpot owners (sales reps) to Nexor team members so a lead assigned to a rep routes to that host's calendar and outbound sync writes the right hubspot\_owner\_id. Each mapping names the owner (owner\_email or owner\_id, matched against the portal's owners) and the member (user\_id from list\_team, or user\_email). Writes the owner id on the member (client\_users.external\_ids\[external\_key], the same field the dashboard member form edits, so both resolve the same host). Returns applied, unmatched (owner\_not\_found / user\_not\_found) and advisory warnings: no\_calendar\_connected, calendar\_email\_mismatch (the member's connected calendar email differs from the owner's) — warnings never block. Verify with get\_hubspot\_config.owner\_mappings or list\_team.                                                                                                                                                                                                                                                                                                                                                                  |
  | `install_hubspot_agent_tools`   | `workflows:write` | Write | `workflow_id`, `tools`   | No contract flag | Install platform HubSpot tools on an agent with their fixed parameters — the same rows the dashboard HubSpot agent-tools panel creates, so list\_workflow\_tools / list\_hubspot\_agent\_tools show them. tools: create\_contact (no params), create\_communication (no params; optional summary\_instructions), assign\_owner (optional owner = HubSpot owner id for a fixed owner; omitted = the lead's Nexor assignee), create\_deal (REQUIRES pipeline + stage: deal pipeline/stage ids), update\_deal (REQUIRES stage; only if the catalog carries it), sync\_lead\_stage (REQUIRES lead\_pipeline + status\_map), sync\_deal\_stage (REQUIRES pipeline + status\_map). Ids are validated against HubSpot and status\_map keys against the workflow's stages (400 missing\_fixed\_parameter lists what is missing per tool; 404 pipeline\_not\_found / stage\_not\_found / lead\_pipeline\_not\_found / owner\_not\_found return the available ids; 409 tool\_unavailable = the connection lacks the scope). Idempotent: re-installing updates the fixed params. A booking agent that must log to HubSpot needs at least create\_contact + create\_communication. |
  | `list_hubspot_agent_tools`      | `workflows:read`  | Read  | `workflow_id`            | No contract flag | List the platform HubSpot tools installed on a workflow with their fixed config read back in install vocabulary (create\_deal → pipeline/stage; sync\_\*\_stage → pipeline or lead\_pipeline + status\_map; assign\_owner → owner\_source; create\_communication → summary\_instructions), plus is\_active, inherited, auto\_run\_on\_entry, tool\_available\_for\_agent and available\_in\_statuses. Also returns installable (the tool names) and fixed\_parameters (required/optional per tool). Same rows list\_workflow\_tools shows, filtered to HubSpot.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | `run_hubspot_import`            | `workflows:write` | Write | None                     | `confirm: true`  | Import HubSpot contacts into Nexor as leads. Exactly one selector: list\_id (a routed or any HubSpot list; queued in the background, returns job\_id), contact\_ids (specific contact ids; runs inline and returns stats), or all=true (every contact in the portal; queued, 409 import\_in\_progress if one is running). Optional workflow\_id pins the agent the new leads enter (default: the list's routing rule, else the connection's default workflow; null = no auto-assignment). This creates leads and may start outreach — it is an operational run: call with confirm:false (or omit it) to get a needs\_confirmation preview that does nothing; only pass confirm:true after the operator explicitly approves. Track with get\_hubspot\_sync\_status.                                                                                                                                                                                                                                                                                                                                                                                                     |
  | `get_hubspot_sync_status`       | `workflows:read`  | Read  | None                     | No contract flag | Read HubSpot sync health: connection (sync\_status, last\_sync\_at, last\_sync\_error, token\_expired), inbound\_enabled, import\_all progress, per-list import stats for routed lists, deal\_sync sweep state (last\_swept\_at, rate\_limited\_until), last\_7\_days counts per direction/status and recent\_failures (event, error, contact). The poll target after run\_hubspot\_import and the first read when a client says HubSpot is not syncing.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
</Accordion>

<Accordion title="Cloud Functions (13)">
  | Tool                                   | Scope             | Mode  | Required top-level input        | Safeguard                         | Canonical purpose                                                                                                                                                                                                                                             |
  | -------------------------------------- | ----------------- | ----- | ------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `describe_cloud_functions`             | `workflows:read`  | Read  | None                            | No contract flag                  | Explain Cloud Functions: supported triggers, runtime globals, buffered effects, environment variables, deployment, and manual-run safety. Call before authoring code.                                                                                         |
  | `list_cloud_functions`                 | `workflows:read`  | Read  | None                            | No contract flag                  | List Cloud Functions with trigger, active/deployment health summary, and last-run metadata.                                                                                                                                                                   |
  | `get_cloud_function`                   | `workflows:read`  | Read  | `function_id`                   | No contract flag                  | Get one Cloud Function, including its currently saved source code.                                                                                                                                                                                            |
  | `create_cloud_function`                | `workflows:write` | Write | `name`, `trigger_event`, `code` | No contract flag                  | Create and deploy an event-driven Cloud Function. Read the triggering lead from ctx.lead/lead and use native effects instead of refetching it through the public leads API. Start inactive while validating code, then activate with update\_cloud\_function. |
  | `update_cloud_function`                | `workflows:write` | Write | `function_id`                   | No contract flag                  | Update and, when executable state changes, redeploy a Cloud Function. Source changes replace the entire saved code string.                                                                                                                                    |
  | `delete_cloud_function`                | `workflows:write` | Write | `function_id`                   | Operator approval in instructions | Permanently delete a Cloud Function, its run history, and its deployed Worker. Destructive: confirm with the operator first.                                                                                                                                  |
  | `run_cloud_function`                   | `workflows:write` | Write | `function_id`                   | No contract flag                  | Test the saved/deployed Cloud Function with a ctx payload. Always dry-run: proposed effects are recorded but no Nexor lead mutations are applied.                                                                                                             |
  | `list_cloud_function_runs`             | `workflows:read`  | Read  | None                            | No contract flag                  | List compact Cloud Function run summaries; filter by function, lead, trigger source, or status.                                                                                                                                                               |
  | `get_cloud_function_run`               | `workflows:read`  | Read  | `run_id`                        | No contract flag                  | Get full Cloud Function trace detail: ctx, logs, result/error, network requests, proposed/applied effects, and lead snapshots.                                                                                                                                |
  | `clear_cloud_function_runs`            | `workflows:write` | Write | None                            | Operator approval in instructions | Permanently clear Cloud Function run history, optionally for one function. Destructive: confirm with the operator first.                                                                                                                                      |
  | `list_function_environment_variables`  | `workflows:read`  | Read  | None                            | No contract flag                  | List names and timestamps of client-wide, write-only environment variables shared by Cloud and Scheduled Functions. Values are never returned.                                                                                                                |
  | `set_function_environment_variable`    | `workflows:write` | Write | `key`, `value`                  | No contract flag                  | Create or replace a shared secret. Key must match ^\[A-Z]\[A-Z0-9\_]\{0,63}\$. The value is encrypted, never echoed, and triggers redeployment of active Cloud/Scheduled Functions.                                                                           |
  | `delete_function_environment_variable` | `workflows:write` | Write | `key`                           | Operator approval in instructions | Delete a shared environment variable and redeploy active functions without it. Destructive and may break code that reads env.KEY; confirm first.                                                                                                              |
</Accordion>

<Accordion title="Scheduled Functions (12)">
  | Tool                                  | Scope             | Mode  | Required top-level input                      | Safeguard                         | Canonical purpose                                                                                                                                                                                                                                 |
  | ------------------------------------- | ----------------- | ----- | --------------------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `describe_scheduled_functions`        | `workflows:read`  | Read  | None                                          | No contract flag                  | Explain Scheduled Functions, cohort lookup syntax, runtime/effects, scheduling, and the important manual-run mutation behavior.                                                                                                                   |
  | `list_scheduled_functions`            | `workflows:read`  | Read  | None                                          | No contract flag                  | List Scheduled Functions with cron, timezone, next/last run, active state, and cohort cap.                                                                                                                                                        |
  | `get_scheduled_function`              | `workflows:read`  | Read  | `function_id`                                 | No contract flag                  | Get one Scheduled Function including saved source code and lookup configuration.                                                                                                                                                                  |
  | `create_scheduled_function`           | `workflows:write` | Write | `name`, `cron_expression`, `timezone`, `code` | No contract flag                  | Create and deploy a cron function. Put lead filtering/order/limit in lookup\_config, preview the schedule and cohort, then make code consume ctx.leads; never refetch that cohort through the public leads API. Start inactive for risky effects. |
  | `update_scheduled_function`           | `workflows:write` | Write | `function_id`                                 | No contract flag                  | Update schedule, cohort, code, metadata, or active state. Code/reactivation deploys; cron/timezone changes recompute next\_run\_at.                                                                                                               |
  | `delete_scheduled_function`           | `workflows:write` | Write | `function_id`                                 | Operator approval in instructions | Permanently delete a Scheduled Function, run history, and Worker. Destructive: confirm first.                                                                                                                                                     |
  | `preview_scheduled_function_schedule` | `workflows:read`  | Read  | `cron_expression`, `timezone`                 | No contract flag                  | Validate a five-field cron in an IANA timezone and return its next 1-10 UTC occurrences.                                                                                                                                                          |
  | `preview_scheduled_function_cohort`   | `workflows:read`  | Read  | `lookup_config`                               | No contract flag                  | Resolve a lookup\_config without running code. Returns matching count and bounded sample so you can verify who would enter ctx.leads.                                                                                                             |
  | `run_scheduled_function`              | `workflows:write` | Write | `function_id`, `confirm`                      | `confirm: true`                   | Run a Scheduled Function immediately. WARNING: unlike Cloud Function tests, this applies buffered effects to real tenant data. Only call after the operator explicitly confirms; pass confirm:true.                                               |
  | `list_scheduled_function_runs`        | `workflows:read`  | Read  | None                                          | No contract flag                  | List Scheduled Function execution summaries by function/status with pagination.                                                                                                                                                                   |
  | `get_scheduled_function_run`          | `workflows:read`  | Read  | `run_id`                                      | No contract flag                  | Get a full Scheduled Function trace: resolved cohort context, logs, network, result/error, and applied/failed effects.                                                                                                                            |
  | `clear_scheduled_function_runs`       | `workflows:write` | Write | None                                          | Operator approval in instructions | Permanently clear Scheduled Function run history, optionally for one function. Destructive: confirm first.                                                                                                                                        |
</Accordion>

## Pinned source and regeneration

Generated from `getnexor-ai/nexor-public-mcp` at `422ca3501bc7e73d00150211c2ef0e6b84cb4c27`, using `docs/tool-manifest.json` (SHA-256 `0bcd54c517788ca7e74fb6e6e193f70d5b0f8b9791b8154bf1f2a114d2801125`).

After checking out that exact commit locally:

```bash theme={null}
npm run mcp:snapshot -- /absolute/path/to/nexor-public-mcp
npm run mcp:check -- /absolute/path/to/nexor-public-mcp
```
