diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18ccd11c62f..4b6fca3beda 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -657,6 +657,7 @@ jobs: permissions: contents: read actions: read + checks: read steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6 @@ -666,27 +667,31 @@ jobs: with: bun-version: 1.4.4 - # Diff from the head of the last earlier run whose submission succeeded, not the previous + # Diff from the last earlier main commit whose `indexnow` check succeeded, not the previous # push: a push that never deployed, or whose submission failed, would otherwise drop its - # changed URLs for good. Falls back to the previous push when no such run is in view. The - # diff needs only the two trees, so that one commit is fetched alone; an all-zero `before` - # (the branch's first push) has no base, which the script skips. + # changed URLs for good. The check-runs lookup asks for this one check per commit, so it + # stays small and counts every attempt of a re-run; a lookup that errors counts as no + # success. With no success in view, the base is the oldest run in view, so URLs that no + # submission ever covered are sent now. The diff needs only the two trees, so that one + # commit is fetched alone; an all-zero `before` (the branch's first push) has no base, + # which the script skips. - name: Submit changed URLs to IndexNow env: GH_TOKEN: ${{ github.token }} PUSH_BEFORE: ${{ github.event.before }} run: | BASE_SHA="" - while read -r run_id head_sha; do - conclusion="$(gh api --paginate "repos/$GITHUB_REPOSITORY/actions/runs/$run_id/jobs?per_page=100" \ - --jq '.jobs[] | select(.name == "indexnow") | .conclusion')" - if [[ "$conclusion" == "success" ]]; then + OLDEST_SHA="" + while read -r head_sha; do + OLDEST_SHA="$head_sha" + if succeeded="$(gh api "repos/$GITHUB_REPOSITORY/commits/$head_sha/check-runs?check_name=indexnow&filter=all" \ + --jq '[.check_runs[] | select(.conclusion == "success")] | length')" && [[ "$succeeded" -gt 0 ]]; then BASE_SHA="$head_sha" break fi done < <(gh api "repos/$GITHUB_REPOSITORY/actions/workflows/ci.yml/runs?branch=main&event=push&per_page=30" \ - --jq ".workflow_runs[] | select(.id < $GITHUB_RUN_ID) | \"\\(.id) \\(.head_sha)\"") - BASE_SHA="${BASE_SHA:-$PUSH_BEFORE}" + --jq ".workflow_runs[] | select(.id < $GITHUB_RUN_ID) | .head_sha") + BASE_SHA="${BASE_SHA:-${OLDEST_SHA:-$PUSH_BEFORE}}" echo "Submitting URLs changed in $BASE_SHA..$GITHUB_SHA" if [[ ! "$BASE_SHA" =~ ^0+$ ]]; then git fetch --no-tags --depth=1 origin "$BASE_SHA" diff --git a/.github/workflows/migrate.yml b/.github/workflows/migrate.yml index f0b04f4619d..4975ca60334 100644 --- a/.github/workflows/migrate.yml +++ b/.github/workflows/migrate.yml @@ -38,8 +38,41 @@ jobs: runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-4vcpu-ubuntu-2404' || 'ubuntu-latest' }} # Bulk projection loads and concurrent index builds can outlast ordinary schema changes. timeout-minutes: 300 + # One migrate job per environment at a time, so a manual dispatch queues + # behind a CI run instead of racing it for migrate.ts's advisory lock, which + # gives up after 30 minutes. Job-level because a called workflow evaluates + # workflow-level concurrency with the caller's github context; the group + # must also never equal ci.yml's ci- group or the two deadlock. + concurrency: + group: migrate-${{ inputs.environment }} + cancel-in-progress: false steps: + # An environment only migrates from its own branch, so a manual dispatch + # from a feature branch cannot apply that branch's migrations to a shared + # database. Under workflow_call github.ref is the caller's ref (ci.yml's + # push to main/staging/dev). This fails rather than skips: ci.yml's + # promote gates on migrate succeeding, and a skipped run must never read + # as a migration that happened. It runs before any secret is read. + - name: Require the environment's own branch + env: + ENVIRONMENT: ${{ inputs.environment }} + REF: ${{ github.ref }} + run: | + case "${ENVIRONMENT}" in + production) expected=refs/heads/main ;; + staging) expected=refs/heads/staging ;; + dev) expected=refs/heads/dev ;; + *) + echo "::error::Unknown migrate environment '${ENVIRONMENT}'" + exit 1 + ;; + esac + if [ "${REF}" != "${expected}" ]; then + echo "::error::Refusing to migrate ${ENVIRONMENT} from ${REF}; ${ENVIRONMENT} migrates only from ${expected}" + exit 1 + fi + - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6 with: diff --git a/apps/docs/content/docs/integrations/tailscale.mdx b/apps/docs/content/docs/integrations/tailscale.mdx index 1ab5da682a4..9a804a57d89 100644 --- a/apps/docs/content/docs/integrations/tailscale.mdx +++ b/apps/docs/content/docs/integrations/tailscale.mdx @@ -10,33 +10,44 @@ import { ReferenceDetails } from "@/components/ui/reference-details" {/* MANUAL-CONTENT-START:intro */} -Use [Tailscale](https://tailscale.com) to manage devices, DNS, ACLs, auth keys, users, and routes in a tailnet. +Use [Tailscale](https://tailscale.com) to manage devices, users, device posture, DNS, policy files, keys, and tailnet settings. ## Authentication -The Tailscale block uses API key authentication. To get an API key: +Enter a Tailscale **API access token** in **API Access Token**. The block sends it using Bearer authentication. Create a personal token in the [Keys page of the admin console](https://login.tailscale.com/admin/settings/keys); personal tokens expire after 1–90 days and inherit the user's permissions. -1. Go to the [Tailscale admin console](https://login.tailscale.com/admin/settings/keys) -2. Navigate to **Settings > Keys** -3. Click **Generate API key** -4. Set an expiry (1-90 days) and copy the key (starts with `tskey-api-`) +An access token generated by a Tailscale OAuth client or federated identity also works. Generate that token using Tailscale's documented [trust credential flow](https://tailscale.com/docs/reference/trust-credentials), then supply the access token to the block. The block does not exchange client secrets or refresh expired tokens. For scheduled workflows, supply a fresh access token from your credential management workflow before it expires. -You must have an **Owner**, **Admin**, **IT admin**, or **Network admin** role to generate API keys. +Device enrollment keys (`tskey-auth-`) and OAuth client secrets (`tskey-client-`) cannot authenticate these API requests. When using scoped OAuth access tokens, grant the scopes required by the selected endpoint in the [API reference](https://tailscale.com/api). Creating a tailnet-owned auth key with OAuth also requires device tags owned by that credential. ## Tailnet identifier [#tailnet-identifier] -Every operation requires a **tailnet** parameter. This is typically your organization's domain name (e.g., `example.com`). You can also use `"-"` to refer to your default tailnet. +Tailnet-scoped operations require a **Tailnet**: use `-` for the access token's default tailnet, the tailnet ID from General Settings, or a supported legacy tailnet name. Device- and user-scoped operations use their resource IDs directly. + +## Device fields, filters, and keys + +In advanced mode, select **All** device fields to include route, connectivity, SSH, and posture details. **Device Filters** accepts URL query syntax such as `isEphemeral=true&tags=tag:server`. Repeating a tag filter requires all specified tags. User lists can be filtered by relationship type and role. + +**List Keys** returns active enrollment keys, API access tokens, and trust credentials. Use `keyType` and `userId` to identify the intended credentials before revoking them. **Include All Tailnet Keys** defaults to enabled; disable it to use the API's token-owner visibility rules. + +## Policy and network changes + +Use **Validate ACL** to validate JSON or HuJSON policy files, or run a JSON array of ACL tests, without changing the policy. Inspect `valid`, `message`, and `results`, since validation errors can be returned with HTTP 200. Pass the ETag from **Get ACL** to **Set ACL** to protect against concurrent edits. + +List inputs accept comma-separated values or a JSON array of strings. Use `[]` to clear tags, enabled routes, nameservers, or search paths. **Set Split DNS** replaces every split DNS entry; **Update Split DNS** changes only specified entries and accepts `null` to remove a domain. **Set DNS Configuration** replaces the complete DNS configuration, including resolver options and preferences. **Update Tailnet Settings** updates only supplied settings; do not specify both `routeSelection` and `regionalRoutingOn`. + +List endpoints return a single API response and do not support pagination. Sim applies its shared response byte limit before transforming the result. {/* MANUAL-CONTENT-END */} ## Use the block [#usage-instructions] -Interact with the Tailscale API to manage devices, DNS, ACLs, auth keys, users, and routes across your tailnet. +Manage Tailscale devices, user access, posture attributes, DNS configuration, policy files, keys, subnet routes, and tailnet settings. ## Actions ### Tailscale List Devices -List all devices in the tailnet +List devices in the tailnet @@ -44,36 +55,72 @@ List all devices in the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `fields` | string | No | Device fields to return: default or all | +| `filters` | string | No | URL query filters for top-level device fields, e.g. isEphemeral=true&tags=tag:server | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `devices` | array | List of devices in the tailnet | -| ↳ `id` | string | Legacy device ID | +| `devices` | array | Devices in the tailnet | +| ↳ `addresses` | array | Tailscale IP addresses | +| ↳ `id` | string | Resource ID | | ↳ `nodeId` | string | Preferred device ID | -| ↳ `name` | string | Device name | -| ↳ `hostname` | string | Device hostname | -| ↳ `user` | string | Associated user | -| ↳ `os` | string | Operating system | +| ↳ `user` | string | User who registered the device | +| ↳ `name` | string | Device MagicDNS name | +| ↳ `hostname` | string | Device machine name | | ↳ `clientVersion` | string | Tailscale client version | -| ↳ `addresses` | array | Tailscale IP addresses | -| ↳ `tags` | array | Device tags | -| ↳ `authorized` | boolean | Whether the device is authorized | -| ↳ `blocksIncomingConnections` | boolean | Whether the device blocks incoming connections | -| ↳ `keyExpiryDisabled` | boolean | Whether the device key is exempt from expiring | -| ↳ `expires` | string | The device's auth key expiration timestamp | -| ↳ `lastSeen` | string | Last seen timestamp | +| ↳ `updateAvailable` | boolean | Whether a client update is available | +| ↳ `os` | string | Operating system | | ↳ `created` | string | Creation timestamp | -| `count` | number | Total number of devices | +| ↳ `connectedToControl` | boolean | Whether the device is connected to the control server | +| ↳ `lastSeen` | string | Last seen timestamp; a connected device may omit it | +| ↳ `keyExpiryDisabled` | boolean | Whether device key expiry is disabled | +| ↳ `expires` | string | Key expiration timestamp | +| ↳ `authorized` | boolean | Whether the device is authorized | +| ↳ `isExternal` | boolean | Whether the device is shared from another tailnet | +| ↳ `multipleConnections` | boolean | Whether multiple devices are using the same node key | +| ↳ `machineKey` | string | Machine public key | +| ↳ `nodeKey` | string | Node public key | +| ↳ `blocksIncomingConnections` | boolean | Whether incoming connections are blocked | +| ↳ `enabledRoutes` | array | Approved subnet routes | +| ↳ `advertisedRoutes` | array | Advertised subnet routes | +| ↳ `clientConnectivity` | json | Connectivity report | +| ↳ `endpoints` | array | Client's magicsock UDP IP:port endpoints \(IPv4 or IPv6\) | +| ↳ `mappingVariesByDestIP` | boolean | 'true' if the host's NAT mappings vary based on the destination IP | +| ↳ `latency` | json | Map of DERP server locations and their current latency | +| ↳ `clientSupports` | json | Identifies features supported by the client | +| ↳ `hairPinning` | boolean | This information is no longer tracked and will always be null | +| ↳ `ipv6` | boolean | 'true' if the device OS supports IPv6, regardless of whether IPv6 internet connectivity is available | +| ↳ `pcp` | boolean | 'true' if PCP port-mapping service exists on your router | +| ↳ `pmp` | boolean | 'true' if NAT-PMP port-mapping service exists on your router | +| ↳ `udp` | boolean | 'true' if UDP traffic is enabled on the current network; if 'false', Tailscale may be unable to make direct connections, and will rely on our DERP servers | +| ↳ `upnp` | boolean | 'true' if UPnP port-mapping service exists on your router | +| ↳ `tags` | array | Assigned tags | +| ↳ `tailnetLockError` | string | Tailnet lock signature error | +| ↳ `tailnetLockKey` | string | Tailnet lock public key | +| ↳ `sshEnabled` | boolean | Whether Tailscale SSH is enabled | +| ↳ `postureIdentity` | json | Device posture identity | +| ↳ `serialNumbers` | array | Serial numbers | +| ↳ `disabled` | boolean | Disabled | +| ↳ `postureStatus` | json | Device posture status | +| ↳ `passing` | boolean | Reports whether the device is passing this posture | +| ↳ `impacting` | boolean | Whether the status of this posture affects the connectivity of the device | +| ↳ `failingAssertions` | array | List of posture assertions the device is failing | +| ↳ `isEphemeral` | boolean | Whether the device is ephemeral | +| ↳ `distro` | json | Operating system distribution | +| ↳ `name` | string | Operating system distribution name | +| ↳ `version` | string | The operating system distribution version that the device is running | +| ↳ `codeName` | string | The operating system distribution code name that the device is running | +| `count` | number | Number of returned items | ### Tailscale Get Device -Get details of a specific device by ID +Get details of a specific device @@ -81,33 +128,87 @@ Get details of a specific device by ID | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `deviceId` | string | Yes | Device ID | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | +| `fields` | string | No | Device fields to return: default or all | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `id` | string | Legacy device ID | +| `addresses` | array | Tailscale IP addresses | +| `id` | string | Resource ID | | `nodeId` | string | Preferred device ID | -| `name` | string | Device name | -| `hostname` | string | Device hostname | -| `user` | string | Associated user | -| `os` | string | Operating system | +| `user` | string | User who registered the device | +| `name` | string | Device MagicDNS name | +| `hostname` | string | Device machine name | | `clientVersion` | string | Tailscale client version | -| `addresses` | array | Tailscale IP addresses | -| `tags` | array | Device tags | -| `authorized` | boolean | Whether the device is authorized | -| `blocksIncomingConnections` | boolean | Whether the device blocks incoming connections | -| `keyExpiryDisabled` | boolean | Whether the device key is exempt from expiring | -| `expires` | string | The device's auth key expiration timestamp | -| `lastSeen` | string | Last seen timestamp | +| `updateAvailable` | boolean | Whether a client update is available | +| `os` | string | Operating system | | `created` | string | Creation timestamp | -| `isExternal` | boolean | Whether the device is external | -| `updateAvailable` | boolean | Whether an update is available | -| `machineKey` | string | Machine key | -| `nodeKey` | string | Node key | +| `connectedToControl` | boolean | Whether the device is connected to the control server | +| `lastSeen` | string | Last seen timestamp; a connected device may omit it | +| `keyExpiryDisabled` | boolean | Whether device key expiry is disabled | +| `expires` | string | Key expiration timestamp | +| `authorized` | boolean | Whether the device is authorized | +| `isExternal` | boolean | Whether the device is shared from another tailnet | +| `multipleConnections` | boolean | Whether multiple devices are using the same node key | +| `machineKey` | string | Machine public key | +| `nodeKey` | string | Node public key | +| `blocksIncomingConnections` | boolean | Whether incoming connections are blocked | +| `enabledRoutes` | array | Approved subnet routes | +| `advertisedRoutes` | array | Advertised subnet routes | +| `clientConnectivity` | json | Connectivity report | +| ↳ `endpoints` | array | Client's magicsock UDP IP:port endpoints \(IPv4 or IPv6\) | +| ↳ `mappingVariesByDestIP` | boolean | 'true' if the host's NAT mappings vary based on the destination IP | +| ↳ `latency` | json | Map of DERP server locations and their current latency | +| ↳ `clientSupports` | json | Identifies features supported by the client | +| ↳ `hairPinning` | boolean | This information is no longer tracked and will always be null | +| ↳ `ipv6` | boolean | 'true' if the device OS supports IPv6, regardless of whether IPv6 internet connectivity is available | +| ↳ `pcp` | boolean | 'true' if PCP port-mapping service exists on your router | +| ↳ `pmp` | boolean | 'true' if NAT-PMP port-mapping service exists on your router | +| ↳ `udp` | boolean | 'true' if UDP traffic is enabled on the current network; if 'false', Tailscale may be unable to make direct connections, and will rely on our DERP servers | +| ↳ `upnp` | boolean | 'true' if UPnP port-mapping service exists on your router | +| `tags` | array | Assigned tags | +| `tailnetLockError` | string | Tailnet lock signature error | +| `tailnetLockKey` | string | Tailnet lock public key | +| `sshEnabled` | boolean | Whether Tailscale SSH is enabled | +| `postureIdentity` | json | Device posture identity | +| ↳ `serialNumbers` | array | Serial numbers | +| ↳ `disabled` | boolean | Disabled | +| `postureStatus` | json | Device posture status | +| ↳ `passing` | boolean | Reports whether the device is passing this posture | +| ↳ `impacting` | boolean | Whether the status of this posture affects the connectivity of the device | +| ↳ `failingAssertions` | array | List of posture assertions the device is failing | +| `isEphemeral` | boolean | Whether the device is ephemeral | +| `distro` | json | Operating system distribution | +| ↳ `name` | string | Operating system distribution name | +| ↳ `version` | string | The operating system distribution version that the device is running | +| ↳ `codeName` | string | The operating system distribution code name that the device is running | + + + +### Tailscale Set Device Name + +Rename a device or reset its name to the OS hostname + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | +| `name` | string | No | New device name or FQDN; empty resets it to the OS hostname | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the operation succeeded | +| `deviceId` | string | ID of the affected device | +| `name` | string | Submitted device name; empty resets the name | @@ -121,16 +222,15 @@ Remove a device from the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `deviceId` | string | Yes | Device ID to delete | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `success` | boolean | Whether the device was successfully deleted | -| `deviceId` | string | ID of the deleted device | +| `success` | boolean | Whether the operation succeeded | +| `deviceId` | string | ID of the affected device | @@ -144,24 +244,23 @@ Authorize or deauthorize a device on the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `deviceId` | string | Yes | Device ID to authorize | -| `authorized` | boolean | Yes | Whether to authorize \(true\) or deauthorize \(false\) the device | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | +| `authorized` | boolean | Yes | Whether to authorize or deauthorize the device | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | | `success` | boolean | Whether the operation succeeded | -| `deviceId` | string | Device ID | -| `authorized` | boolean | Authorization status after the operation | +| `deviceId` | string | ID of the affected device | +| `authorized` | boolean | Requested device authorization state | ### Tailscale Set Device Tags -Set tags on a device in the tailnet +Replace the tags assigned to a device @@ -169,24 +268,23 @@ Set tags on a device in the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `deviceId` | string | Yes | Device ID | -| `tags` | string | Yes | Comma-separated list of tags \(e.g., "tag:server,tag:production"\) | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | +| `tags` | string | Yes | Comma-separated device tags; use \[\] to clear tags | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `success` | boolean | Whether the tags were successfully set | -| `deviceId` | string | Device ID | -| `tags` | array | Tags set on the device | +| `success` | boolean | Whether the operation succeeded | +| `deviceId` | string | ID of the affected device | +| `tags` | array | Tags submitted for the device | ### Tailscale Get Device Routes -Get the subnet routes for a device +Get the advertised and approved subnet routes for a device @@ -194,22 +292,21 @@ Get the subnet routes for a device | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `deviceId` | string | Yes | Device ID | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `advertisedRoutes` | array | Subnet routes the device is advertising | -| `enabledRoutes` | array | Subnet routes that are approved/enabled | +| `advertisedRoutes` | array | Subnet CIDR routes advertised by the device | +| `enabledRoutes` | array | Approved subnet CIDR routes | ### Tailscale Set Device Routes -Set the enabled subnet routes for a device +Replace the enabled subnet routes for a device @@ -217,23 +314,22 @@ Set the enabled subnet routes for a device | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `deviceId` | string | Yes | Device ID | -| `routes` | string | Yes | Comma-separated list of subnet routes to enable \(e.g., "10.0.0.0/24,192.168.1.0/24"\) | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | +| `routes` | string | Yes | Comma-separated enabled CIDR routes; use \[\] to disable all routes | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `advertisedRoutes` | array | Subnet routes the device is advertising | -| `enabledRoutes` | array | Subnet routes that are now enabled | +| `advertisedRoutes` | array | Subnet CIDR routes advertised by the device | +| `enabledRoutes` | array | Approved subnet CIDR routes | ### Tailscale Update Device Key -Enable or disable key expiry on a device +Enable or disable device key expiry @@ -241,24 +337,93 @@ Enable or disable key expiry on a device | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `deviceId` | string | Yes | Device ID | -| `keyExpiryDisabled` | boolean | Yes | Whether to disable key expiry \(true\) or enable it \(false\) | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | +| `keyExpiryDisabled` | boolean | Yes | Whether to disable device key expiry | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | | `success` | boolean | Whether the operation succeeded | -| `deviceId` | string | Device ID | -| `keyExpiryDisabled` | boolean | Whether key expiry is now disabled | +| `deviceId` | string | ID of the affected device | +| `keyExpiryDisabled` | boolean | Requested device key expiry setting | ### Tailscale Expire Device Key -Immediately expire a device's node key, requiring it to re-authenticate before it can reconnect to the tailnet +Immediately expire a device node key so the device must reauthenticate + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the operation succeeded | +| `deviceId` | string | ID of the affected device | + + + +### Tailscale Get Device Attributes + +Get device posture attributes and their expiry times + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `attributes` | json | Map of posture attribute names to string, number, or boolean values | +| `expiries` | json | Map of posture attribute names to RFC 3339 expiry timestamps | + + + +### Tailscale Set Device Attribute + +Create or update a custom device posture attribute with an optional expiry + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | +| `attributeKey` | string | Yes | Custom posture attribute name, prefixed with custom: | +| `attributeValue` | string | Yes | JSON scalar attribute value: a quoted string, integer, or boolean | +| `expiry` | string | No | Attribute expiry as an RFC 3339 timestamp | +| `comment` | string | No | Reason for setting the posture attribute, up to 200 characters | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `attributes` | json | Map of posture attribute names to string, number, or boolean values | +| `expiries` | json | Map of posture attribute names to RFC 3339 expiry timestamps | + + + +### Tailscale Delete Device Attribute + +Remove a custom posture attribute from a device @@ -266,22 +431,23 @@ Immediately expire a device's node key, requiring it to re-authenticate before i | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `deviceId` | string | Yes | Device ID to expire the key for | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `deviceId` | string | Yes | Device nodeId \(preferred\) or legacy device ID | +| `attributeKey` | string | Yes | Custom posture attribute name, prefixed with custom: | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `success` | boolean | Whether the device's key was successfully expired | -| `deviceId` | string | Device ID | +| `success` | boolean | Whether the operation succeeded | +| `deviceId` | string | ID of the affected device | +| `attributeKey` | string | Deleted custom posture attribute key | ### Tailscale List DNS Nameservers -Get the DNS nameservers configured for the tailnet +Get the global DNS nameservers configured for the tailnet @@ -289,20 +455,20 @@ Get the DNS nameservers configured for the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `dns` | array | List of DNS nameserver addresses | +| `dns` | array | DNS nameserver IP addresses | ### Tailscale Set DNS Nameservers -Set the DNS nameservers for the tailnet +Replace the global DNS nameservers for the tailnet @@ -310,22 +476,22 @@ Set the DNS nameservers for the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `dns` | string | Yes | Comma-separated list of DNS nameserver IP addresses \(e.g., "8.8.8.8,8.8.4.4"\) | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `dns` | string | Yes | Comma-separated DNS nameserver IP addresses; \[\] clears the nameservers | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `dns` | array | Updated list of DNS nameserver addresses | +| `dns` | array | DNS nameserver IP addresses | | `magicDNS` | boolean | Whether MagicDNS is enabled | ### Tailscale Get DNS Preferences -Get the DNS preferences for the tailnet including MagicDNS status +Get the MagicDNS preference for the tailnet @@ -333,8 +499,8 @@ Get the DNS preferences for the tailnet including MagicDNS status | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | #### Output @@ -346,7 +512,7 @@ Get the DNS preferences for the tailnet including MagicDNS status ### Tailscale Set DNS Preferences -Set DNS preferences for the tailnet (enable/disable MagicDNS) +Enable or disable MagicDNS for the tailnet @@ -354,21 +520,21 @@ Set DNS preferences for the tailnet (enable/disable MagicDNS) | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `magicDNS` | boolean | Yes | Whether to enable \(true\) or disable \(false\) MagicDNS | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `magicDNS` | boolean | Yes | Whether MagicDNS is enabled | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `magicDNS` | boolean | Updated MagicDNS status | +| `magicDNS` | boolean | Whether MagicDNS is enabled | ### Tailscale Get DNS Search Paths -Get the DNS search paths configured for the tailnet +Get the DNS search domains configured for the tailnet @@ -376,20 +542,63 @@ Get the DNS search paths configured for the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `searchPaths` | array | List of DNS search path domains | +| `searchPaths` | array | DNS search domain names | ### Tailscale Set DNS Search Paths -Set the DNS search paths for the tailnet +Replace the DNS search domains for the tailnet + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `searchPaths` | string | Yes | Comma-separated DNS search domains; \[\] clears the search paths | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `searchPaths` | array | DNS search domain names | + + + +### Tailscale Get Split DNS + +Get split DNS resolvers + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `splitDns` | json | Map of domain names to DNS resolver arrays or null | + + + +### Tailscale Update Split DNS + +Update selected split DNS resolvers @@ -397,21 +606,102 @@ Set the DNS search paths for the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `searchPaths` | string | Yes | Comma-separated list of DNS search path domains \(e.g., "corp.example.com,internal.example.com"\) | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `splitDns` | string | Yes | JSON map of domains to nameserver arrays; null deletes a domain when updating | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `searchPaths` | array | Updated list of DNS search path domains | +| `splitDns` | json | Map of domain names to DNS resolver arrays or null | + + + +### Tailscale Set Split DNS + +Replace all split DNS resolvers + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `splitDns` | string | Yes | JSON map of domains to nameserver arrays; null deletes a domain when updating | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `splitDns` | json | Map of domain names to DNS resolver arrays or null | + + + +### Tailscale Get DNS Configuration + +Get tailnet DNS configuration + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `dnsConfiguration` | json | Dns configuration | +| ↳ `nameservers` | array | Global DNS resolvers to use | +| ↳ `address` | string | IPv4 or IPv6 address of the DNS resolver | +| ↳ `useWithExitNode` | boolean | If true, this resolver should still be used when a device is configured to use a Tailscale exit node | +| ↳ `splitDNS` | json | Map of DNS name suffixes \(domains\) to lists of resolvers for Split DNS and advanced routing overlays | +| ↳ `searchPaths` | array | Search domain paths to apply | +| ↳ `preferences` | json | Preferences | +| ↳ `overrideLocalDNS` | boolean | If true, resolvers in `nameservers` override the local OS DNS configuration; if false, local resolvers are used | +| ↳ `magicDNS` | boolean | Whether MagicDNS is enabled for this tailnet | + + + +### Tailscale Set DNS Configuration + +Replace the full tailnet DNS configuration + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `dnsConfiguration` | string | Yes | Complete DNS configuration JSON: nameservers, splitDNS, searchPaths, preferences | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `dnsConfiguration` | json | Dns configuration | +| ↳ `nameservers` | array | Global DNS resolvers to use | +| ↳ `address` | string | IPv4 or IPv6 address of the DNS resolver | +| ↳ `useWithExitNode` | boolean | If true, this resolver should still be used when a device is configured to use a Tailscale exit node | +| ↳ `splitDNS` | json | Map of DNS name suffixes \(domains\) to lists of resolvers for Split DNS and advanced routing overlays | +| ↳ `searchPaths` | array | Search domain paths to apply | +| ↳ `preferences` | json | Preferences | +| ↳ `overrideLocalDNS` | boolean | If true, resolvers in `nameservers` override the local OS DNS configuration; if false, local resolvers are used | +| ↳ `magicDNS` | boolean | Whether MagicDNS is enabled for this tailnet | ### Tailscale List Users -List all users in the tailnet +List users in the tailnet @@ -419,31 +709,113 @@ List all users in the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `userType` | string | No | User relationship: member \(default\), shared, or all | +| `role` | string | No | User role: owner, member, admin, it-admin, network-admin, billing-admin, or auditor | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `users` | array | List of users in the tailnet | -| ↳ `id` | string | User ID | -| ↳ `displayName` | string | Display name | -| ↳ `loginName` | string | Login name / email | -| ↳ `profilePicURL` | string | Profile picture URL | -| ↳ `role` | string | User role \(owner, admin, member, etc.\) | -| ↳ `status` | string | User status \(active, suspended, etc.\) | -| ↳ `type` | string | User type \(member, shared, tagged\) | +| `users` | array | Users in the tailnet | +| ↳ `id` | string | Resource ID | +| ↳ `displayName` | string | User display name | +| ↳ `loginName` | string | User login name | +| ↳ `tailnetId` | string | Owning tailnet ID | | ↳ `created` | string | Creation timestamp | -| ↳ `lastSeen` | string | Last seen timestamp | -| ↳ `deviceCount` | number | Number of devices owned by user | -| `count` | number | Total number of users | +| ↳ `type` | string | User relationship: member or shared | +| ↳ `role` | string | User role | +| ↳ `status` | string | User status | +| ↳ `deviceCount` | number | Number of devices owned by the user | +| ↳ `lastSeen` | string | Last time a user device connected or the user authenticated | +| ↳ `currentlyConnected` | boolean | Whether the user has a device connected to the control server | +| ↳ `profilePicURL` | string | User profile picture URL | +| `count` | number | Number of returned items | + + + +### Tailscale Get User + +Get details of a specific user + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `userId` | string | Yes | Tailscale user ID | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Resource ID | +| `displayName` | string | User display name | +| `loginName` | string | User login name | +| `tailnetId` | string | Owning tailnet ID | +| `created` | string | Creation timestamp | +| `type` | string | User relationship: member or shared | +| `role` | string | User role | +| `status` | string | User status | +| `deviceCount` | number | Number of devices owned by the user | +| `lastSeen` | string | Last time a user device connected or the user authenticated | +| `currentlyConnected` | boolean | Whether the user has a device connected to the control server | +| `profilePicURL` | string | User profile picture URL | + + + +### Tailscale Set User Role + +Change a tailnet user’s role + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `userId` | string | Yes | Tailscale user ID | +| `role` | string | Yes | User role: owner, member, admin, it-admin, network-admin, billing-admin, or auditor | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the operation succeeded | +| `userId` | string | ID of the affected user | +| `role` | string | Requested user role | + + + +### Tailscale Approve User + +Approve a pending user to join the tailnet + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `userId` | string | Yes | Tailscale user ID | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the operation succeeded | +| `userId` | string | ID of the affected user | ### Tailscale Suspend User -Suspend a user's access to the tailnet +Suspend a user’s access to the tailnet @@ -451,16 +823,37 @@ Suspend a user's access to the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `userId` | string | Yes | User ID to suspend | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `userId` | string | Yes | Tailscale user ID | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `success` | boolean | Whether the user was successfully suspended | -| `userId` | string | ID of the suspended user | +| `success` | boolean | Whether the operation succeeded | +| `userId` | string | ID of the affected user | + + + +### Tailscale Restore User + +Restore a suspended user’s access to the tailnet + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `userId` | string | Yes | Tailscale user ID | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `success` | boolean | Whether the operation succeeded | +| `userId` | string | ID of the affected user | @@ -474,22 +867,21 @@ Delete a user from the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `userId` | string | Yes | User ID to delete | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `userId` | string | Yes | Tailscale user ID | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `success` | boolean | Whether the user was successfully deleted | -| `userId` | string | ID of the deleted user | +| `success` | boolean | Whether the operation succeeded | +| `userId` | string | ID of the affected user | ### Tailscale Create Auth Key -Create a new auth key for the tailnet to pre-authorize devices +Create a device enrollment auth key @@ -497,36 +889,47 @@ Create a new auth key for the tailnet to pre-authorize devices | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `reusable` | boolean | No | Whether the key can be used more than once | -| `ephemeral` | boolean | No | Whether devices authenticated with this key are ephemeral | -| `preauthorized` | boolean | No | Whether devices are pre-authorized \(skip manual approval\) | -| `tags` | string | No | Comma-separated list of tags for devices using this key \(e.g., "tag:server,tag:prod"\) | -| `description` | string | No | Description for the auth key | -| `expirySeconds` | number | No | Key expiry time in seconds \(default: 90 days\) | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `reusable` | boolean | No | Whether the auth key can register multiple devices \(default false\) | +| `ephemeral` | boolean | No | Whether devices registered with the key are ephemeral \(default false\) | +| `preauthorized` | boolean | No | Whether devices skip manual approval \(default true\) | +| `tags` | string | No | Comma-separated tags; required when creating a tailnet-owned key using OAuth | +| `description` | string | No | Auth key description, up to 50 alphanumeric characters, spaces, or hyphens | +| `expirySeconds` | number | No | Auth key lifetime in seconds \(default 7776000, 90 days\) | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `id` | string | Auth key ID | -| `key` | string | The auth key value \(only shown once at creation\) | -| `description` | string | Key description | +| `id` | string | Resource ID | +| `keyType` | string | Credential type: auth, api, client, or federated | +| `expirySeconds` | number | Auth key lifetime in seconds | | `created` | string | Creation timestamp | -| `expires` | string | Expiration timestamp | -| `revoked` | string | Revocation timestamp \(empty if not revoked\) | -| `capabilities` | object | Key capabilities | -| ↳ `reusable` | boolean | Whether the key is reusable | -| ↳ `ephemeral` | boolean | Whether devices are ephemeral | -| ↳ `preauthorized` | boolean | Whether devices are pre-authorized | -| ↳ `tags` | array | Tags applied to devices using this key | +| `updated` | string | Last update timestamp | +| `expires` | string | Key expiration timestamp | +| `revoked` | string | Revocation timestamp | +| `capabilities` | json | Device enrollment capabilities | +| ↳ `reusable` | boolean | reusable for auth keys only; reusable auth keys can be used multiple times to register different devices | +| ↳ `ephemeral` | boolean | ephemeral for auth keys only; ephemeral keys are used to connect and then clean up short-lived devices | +| ↳ `preauthorized` | boolean | preauthorized for auth keys only; these are also referred to as "pre-approved" keys | +| ↳ `tags` | array | Assigned tags | +| `scopes` | array | Granted API scopes | +| `tags` | array | Assigned tags | +| `description` | string | Key description | +| `invalid` | boolean | Whether the key is expired or revoked | +| `userId` | string | Creating user ID; empty for a tailnet-owned key | +| `audience` | string | Federated identity audience | +| `issuer` | string | Federated identity issuer | +| `subject` | string | Federated identity subject pattern | +| `customClaimRules` | json | Map of custom OIDC claims to matching patterns | +| `key` | string | Auth key secret, returned only at creation | -### Tailscale List Auth Keys +### Tailscale List Keys -List all auth keys in the tailnet +List active auth keys, API access tokens, and trust credentials in the tailnet @@ -534,31 +937,43 @@ List all auth keys in the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `all` | boolean | No | Include all tailnet keys \(default true\); false restricts keys according to the access token owner | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `keys` | array | List of auth keys | -| ↳ `id` | string | Auth key ID | -| ↳ `description` | string | Key description | +| `keys` | array | Keys in the tailnet | +| ↳ `id` | string | Resource ID | +| ↳ `keyType` | string | Credential type: auth, api, client, or federated | +| ↳ `expirySeconds` | number | Auth key lifetime in seconds | | ↳ `created` | string | Creation timestamp | -| ↳ `expires` | string | Expiration timestamp | +| ↳ `updated` | string | Last update timestamp | +| ↳ `expires` | string | Key expiration timestamp | | ↳ `revoked` | string | Revocation timestamp | -| ↳ `capabilities` | object | Key capabilities | -| ↳ `reusable` | boolean | Whether the key is reusable | -| ↳ `ephemeral` | boolean | Whether devices are ephemeral | -| ↳ `preauthorized` | boolean | Whether devices are pre-authorized | -| ↳ `tags` | array | Tags applied to devices | -| `count` | number | Total number of auth keys | +| ↳ `capabilities` | json | Device enrollment capabilities | +| ↳ `reusable` | boolean | reusable for auth keys only; reusable auth keys can be used multiple times to register different devices | +| ↳ `ephemeral` | boolean | ephemeral for auth keys only; ephemeral keys are used to connect and then clean up short-lived devices | +| ↳ `preauthorized` | boolean | preauthorized for auth keys only; these are also referred to as "pre-approved" keys | +| ↳ `tags` | array | Assigned tags | +| ↳ `scopes` | array | Granted API scopes | +| ↳ `tags` | array | Assigned tags | +| ↳ `description` | string | Key description | +| ↳ `invalid` | boolean | Whether the key is expired or revoked | +| ↳ `userId` | string | Creating user ID; empty for a tailnet-owned key | +| ↳ `audience` | string | Federated identity audience | +| ↳ `issuer` | string | Federated identity issuer | +| ↳ `subject` | string | Federated identity subject pattern | +| ↳ `customClaimRules` | json | Map of custom OIDC claims to matching patterns | +| `count` | number | Number of returned items | ### Tailscale Get Auth Key -Get details of a specific auth key +Get a key’s type, owner, scopes, expiry, and device enrollment capabilities @@ -566,30 +981,41 @@ Get details of a specific auth key | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `keyId` | string | Yes | Auth key ID | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `keyId` | string | Yes | Tailscale key ID | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `id` | string | Auth key ID | -| `description` | string | Key description | +| `id` | string | Resource ID | +| `keyType` | string | Credential type: auth, api, client, or federated | +| `expirySeconds` | number | Auth key lifetime in seconds | | `created` | string | Creation timestamp | -| `expires` | string | Expiration timestamp | +| `updated` | string | Last update timestamp | +| `expires` | string | Key expiration timestamp | | `revoked` | string | Revocation timestamp | -| `capabilities` | object | Key capabilities | -| ↳ `reusable` | boolean | Whether the key is reusable | -| ↳ `ephemeral` | boolean | Whether devices are ephemeral | -| ↳ `preauthorized` | boolean | Whether devices are pre-authorized | -| ↳ `tags` | array | Tags applied to devices using this key | +| `capabilities` | json | Device enrollment capabilities | +| ↳ `reusable` | boolean | reusable for auth keys only; reusable auth keys can be used multiple times to register different devices | +| ↳ `ephemeral` | boolean | ephemeral for auth keys only; ephemeral keys are used to connect and then clean up short-lived devices | +| ↳ `preauthorized` | boolean | preauthorized for auth keys only; these are also referred to as "pre-approved" keys | +| ↳ `tags` | array | Assigned tags | +| `scopes` | array | Granted API scopes | +| `tags` | array | Assigned tags | +| `description` | string | Key description | +| `invalid` | boolean | Whether the key is expired or revoked | +| `userId` | string | Creating user ID; empty for a tailnet-owned key | +| `audience` | string | Federated identity audience | +| `issuer` | string | Federated identity issuer | +| `subject` | string | Federated identity subject pattern | +| `customClaimRules` | json | Map of custom OIDC claims to matching patterns | ### Tailscale Delete Auth Key -Revoke and delete an auth key +Revoke an auth key, API access token, or trust credential @@ -597,22 +1023,22 @@ Revoke and delete an auth key | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `keyId` | string | Yes | Auth key ID to delete | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `keyId` | string | Yes | Tailscale key ID | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `success` | boolean | Whether the auth key was successfully deleted | -| `keyId` | string | ID of the deleted auth key | +| `success` | boolean | Whether the operation succeeded | +| `keyId` | string | ID of the revoked key | ### Tailscale Get ACL -Get the current ACL policy for the tailnet +Get the tailnet policy file @@ -620,21 +1046,109 @@ Get the current ACL policy for the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | +| `details` | boolean | No | Include the original HuJSON policy and its warnings and parsing errors | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `acl` | string | ACL policy as JSON string | -| `etag` | string | ETag for the current ACL version \(use with If-Match header for updates\) | +| `warnings` | array | Policy warnings | +| `errors` | array | Policy parsing errors | +| `acl` | string | Tailnet policy as JSON, or the original HuJSON when diagnostics are enabled | +| `etag` | string | Policy ETag for conditional updates | + + + +### Tailscale Validate ACL + +Validate a policy file or run ACL tests without changing the tailnet policy + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `acl` | string | Yes | Policy file in JSON or HuJSON, or a JSON array of ACL tests for validation | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `valid` | boolean | Whether validation and tests passed without warnings | +| `message` | string | Validation summary | +| `results` | array | Validation and test diagnostics | +| ↳ `user` | string | Test identity | +| ↳ `errors` | array | Test failures | +| ↳ `warnings` | array | Policy warnings | ### Tailscale Set ACL -Replace the ACL policy file for the tailnet +Replace the tailnet policy file + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `acl` | string | Yes | Complete tailnet policy file in JSON or HuJSON | +| `ifMatch` | string | No | ETag from Get ACL, or ts-default to replace only an untouched default policy | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `acl` | string | Tailnet policy file as a JSON string | +| `etag` | string | Policy ETag for conditional updates | + + + +### Tailscale Get Tailnet Settings + +Get tailnet settings + + + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `settings` | json | Settings for a tailnet | +| ↳ `aclsExternallyManagedOn` | boolean | Prevents users from editing policies in the admin console to avoid conflicts with external management workflows like GitOps or Terraform | +| ↳ `aclsExternalLink` | string | Link to the external tailnet policy definition or management solution for this tailnet | +| ↳ `adminConsoleSessionTimeoutMinutes` | number | The \[admin console session timeout\]\(/docs/account/admin-console-session-timeout\) for members of this tailnet | +| ↳ `devicesApprovalOn` | boolean | Whether \[device approval\]\(/docs/features/access-control/device-management/device-approval\) is enabled for the tailnet | +| ↳ `devicesAutoUpdatesOn` | boolean | Whether \[auto updates\]\(/docs/features/client/update#auto-updates\) are enabled for devices that belong to this tailnet | +| ↳ `devicesKeyDurationDays` | number | The \[key expiry\]\(/docs/features/access-control/key-expiry\) duration for devices on this tailnet | +| ↳ `usersApprovalOn` | boolean | Whether \[user approval\]\(/docs/features/access-control/user-approval\) is enabled for this tailnet | +| ↳ `usersRoleAllowedToJoinExternalTailnets` | string | Which user roles are allowed to \[join external tailnets\]\(/docs/features/sharing/how-to/invite-any-user\) | +| ↳ `networkFlowLoggingOn` | boolean | Whether \[network flog logs\]\(/docs/features/logging/network-flow-logs\) are enabled for the tailnet | +| ↳ `regionalRoutingOn` | boolean | Whether \[regional routing\]\(/docs/features/route-selection#regional-routing\) is enabled for the tailnet | +| ↳ `routeSelection` | string | The \[route selection\]\(/docs/features/route-selection\) algorithm used by the tailnet: * `active-passive-failover` - Active-passive failover \(formerly known as "Failover"\) * `regional-routing` - Regional routing * `regional-routing-failover` - Regional routing with in-region failover * `magicroute` - MagicRoute A PATCH request must not specify both the `regionalRoutingOn` and `routeSelection` fields | +| ↳ `postureIdentityCollectionOn` | boolean | Whether \[identity collection\]\(/docs/features/access-control/device-management/how-to/manage-identity\) is enabled for \[device posture\]\(/docs/features/device-posture\) integrations for the tailnet | +| ↳ `httpsEnabled` | boolean | Whether provisioning of \[HTTPS certificates\]\(/docs/how-to/set-up-https-certificates\) is enabled for this tailnet | + + + +### Tailscale Update Tailnet Settings + +Update selected tailnet settings @@ -642,17 +1156,28 @@ Replace the ACL policy file for the tailnet | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `apiKey` | string | Yes | Tailscale API key | -| `tailnet` | string | Yes | Tailnet name \(e.g., example.com\) or "-" for default | -| `acl` | string | Yes | The new ACL policy file, as a JSON string | -| `ifMatch` | string | No | ETag from a prior Get ACL call to avoid overwriting concurrent updates. Use "ts-default" to only replace an untouched default policy file. | +| `apiKey` | string | Yes | Tailscale API access token or OAuth access token \(not an auth key or OAuth client secret\) | +| `tailnet` | string | Yes | Tailnet ID, legacy name, or "-" for the token’s default tailnet | +| `settings` | string | Yes | JSON object of settings to update; omitted settings remain unchanged | #### Output | Parameter | Type | Description | | --------- | ---- | ----------- | -| `acl` | string | Updated ACL policy as JSON string | -| `etag` | string | ETag for the new ACL version \(use with If-Match header for future updates\) | +| `settings` | json | Settings for a tailnet | +| ↳ `aclsExternallyManagedOn` | boolean | Prevents users from editing policies in the admin console to avoid conflicts with external management workflows like GitOps or Terraform | +| ↳ `aclsExternalLink` | string | Link to the external tailnet policy definition or management solution for this tailnet | +| ↳ `adminConsoleSessionTimeoutMinutes` | number | The \[admin console session timeout\]\(/docs/account/admin-console-session-timeout\) for members of this tailnet | +| ↳ `devicesApprovalOn` | boolean | Whether \[device approval\]\(/docs/features/access-control/device-management/device-approval\) is enabled for the tailnet | +| ↳ `devicesAutoUpdatesOn` | boolean | Whether \[auto updates\]\(/docs/features/client/update#auto-updates\) are enabled for devices that belong to this tailnet | +| ↳ `devicesKeyDurationDays` | number | The \[key expiry\]\(/docs/features/access-control/key-expiry\) duration for devices on this tailnet | +| ↳ `usersApprovalOn` | boolean | Whether \[user approval\]\(/docs/features/access-control/user-approval\) is enabled for this tailnet | +| ↳ `usersRoleAllowedToJoinExternalTailnets` | string | Which user roles are allowed to \[join external tailnets\]\(/docs/features/sharing/how-to/invite-any-user\) | +| ↳ `networkFlowLoggingOn` | boolean | Whether \[network flog logs\]\(/docs/features/logging/network-flow-logs\) are enabled for the tailnet | +| ↳ `regionalRoutingOn` | boolean | Whether \[regional routing\]\(/docs/features/route-selection#regional-routing\) is enabled for the tailnet | +| ↳ `routeSelection` | string | The \[route selection\]\(/docs/features/route-selection\) algorithm used by the tailnet: * `active-passive-failover` - Active-passive failover \(formerly known as "Failover"\) * `regional-routing` - Regional routing * `regional-routing-failover` - Regional routing with in-region failover * `magicroute` - MagicRoute A PATCH request must not specify both the `regionalRoutingOn` and `routeSelection` fields | +| ↳ `postureIdentityCollectionOn` | boolean | Whether \[identity collection\]\(/docs/features/access-control/device-management/how-to/manage-identity\) is enabled for \[device posture\]\(/docs/features/device-posture\) integrations for the tailnet | +| ↳ `httpsEnabled` | boolean | Whether provisioning of \[HTTPS certificates\]\(/docs/how-to/set-up-https-certificates\) is enabled for this tailnet | diff --git a/apps/docs/content/docs/integrations/vanta.mdx b/apps/docs/content/docs/integrations/vanta.mdx index 01ef621d6bb..3e4f999b04c 100644 --- a/apps/docs/content/docs/integrations/vanta.mdx +++ b/apps/docs/content/docs/integrations/vanta.mdx @@ -56,7 +56,21 @@ List the compliance frameworks (e.g., SOC 2, ISO 27001) available in a Vanta acc | Parameter | Type | Description | | --------- | ---- | ----------- | | `frameworks` | array | Frameworks in the Vanta account | +| ↳ `id` | string | The framework's unique ID | +| ↳ `displayName` | string | The framework's display name | +| ↳ `shorthandName` | string | The short version of the framework's name | +| ↳ `description` | string | The framework's description | +| ↳ `numControlsCompleted` | number | Number of completed controls in the framework | +| ↳ `numControlsTotal` | number | Total number of controls in the framework | +| ↳ `numDocumentsPassing` | number | Number of passing documents in the framework | +| ↳ `numDocumentsTotal` | number | Total number of documents in the framework | +| ↳ `numTestsPassing` | number | Number of passing tests in the framework | +| ↳ `numTestsTotal` | number | Total number of tests in the framework | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -77,6 +91,30 @@ Get a Vanta compliance framework by ID, including its requirement categories and | Parameter | Type | Description | | --------- | ---- | ----------- | | `framework` | json | The requested framework with requirement categories | +| ↳ `id` | string | The framework's unique ID | +| ↳ `displayName` | string | The framework's display name | +| ↳ `shorthandName` | string | The short version of the framework's name | +| ↳ `description` | string | The framework's description | +| ↳ `numControlsCompleted` | number | Number of completed controls in the framework | +| ↳ `numControlsTotal` | number | Total number of controls in the framework | +| ↳ `numDocumentsPassing` | number | Number of passing documents in the framework | +| ↳ `numDocumentsTotal` | number | Total number of documents in the framework | +| ↳ `numTestsPassing` | number | Number of passing tests in the framework | +| ↳ `numTestsTotal` | number | Total number of tests in the framework | +| ↳ `requirementCategories` | array | The framework's requirement categories, each with requirements and mapped controls | +| ↳ `id` | string | Requirement category ID | +| ↳ `name` | string | Requirement category name | +| ↳ `shorthand` | string | Requirement category short name | +| ↳ `requirements` | array | Requirements in this category, each listing its mapped controls | +| ↳ `id` | string | Requirement ID | +| ↳ `name` | string | Requirement name | +| ↳ `shorthand` | string | Requirement shorthand | +| ↳ `description` | string | Requirement description | +| ↳ `controls` | array | Controls mapped to the requirement | +| ↳ `id` | string | Control ID | +| ↳ `externalId` | string | External control ID | +| ↳ `name` | string | Control name | +| ↳ `description` | string | Control description | @@ -99,7 +137,27 @@ List the controls that belong to a specific Vanta compliance framework | Parameter | Type | Description | | --------- | ---- | ----------- | | `controls` | array | Controls belonging to the framework | +| ↳ `id` | string | The control's unique ID | +| ↳ `externalId` | string | The control's external ID | +| ↳ `name` | string | The control's name | +| ↳ `description` | string | The control's description | +| ↳ `source` | string | The control source, either "Vanta" or "Custom" | +| ↳ `domains` | array | Security domains the control belongs to | +| ↳ `owner` | json | The control's owner | +| ↳ `id` | string | Unique ID of the owner | +| ↳ `displayName` | string | Display name of the owner | +| ↳ `emailAddress` | string | Email address of the owner | +| ↳ `role` | string | The control's GDPR role, if applicable | +| ↳ `customFields` | array | Custom field values configured in the Vanta instance | +| ↳ `label` | string | Custom field label | +| ↳ `value` | json | Custom field value \(string or list of strings\) | +| ↳ `creationDate` | string | When the control was created \(null for Vanta library controls\) | +| ↳ `modificationDate` | string | When the control was last modified \(null for Vanta library controls\) | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -122,7 +180,27 @@ List the security controls in a Vanta account, optionally filtered by framework | Parameter | Type | Description | | --------- | ---- | ----------- | | `controls` | array | Controls matching the filters | +| ↳ `id` | string | The control's unique ID | +| ↳ `externalId` | string | The control's external ID | +| ↳ `name` | string | The control's name | +| ↳ `description` | string | The control's description | +| ↳ `source` | string | The control source, either "Vanta" or "Custom" | +| ↳ `domains` | array | Security domains the control belongs to | +| ↳ `owner` | json | The control's owner | +| ↳ `id` | string | Unique ID of the owner | +| ↳ `displayName` | string | Display name of the owner | +| ↳ `emailAddress` | string | Email address of the owner | +| ↳ `role` | string | The control's GDPR role, if applicable | +| ↳ `customFields` | array | Custom field values configured in the Vanta instance | +| ↳ `label` | string | Custom field label | +| ↳ `value` | json | Custom field value \(string or list of strings\) | +| ↳ `creationDate` | string | When the control was created \(null for Vanta library controls\) | +| ↳ `modificationDate` | string | When the control was last modified \(null for Vanta library controls\) | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -143,6 +221,28 @@ Get a Vanta security control by ID, including its status and evidence pass/fail | Parameter | Type | Description | | --------- | ---- | ----------- | | `control` | json | The requested control with status and evidence counts | +| ↳ `id` | string | The control's unique ID | +| ↳ `externalId` | string | The control's external ID | +| ↳ `name` | string | The control's name | +| ↳ `description` | string | The control's description | +| ↳ `source` | string | The control source, either "Vanta" or "Custom" | +| ↳ `domains` | array | Security domains the control belongs to | +| ↳ `owner` | json | The control's owner | +| ↳ `id` | string | Unique ID of the owner | +| ↳ `displayName` | string | Display name of the owner | +| ↳ `emailAddress` | string | Email address of the owner | +| ↳ `role` | string | The control's GDPR role, if applicable | +| ↳ `customFields` | array | Custom field values configured in the Vanta instance | +| ↳ `label` | string | Custom field label | +| ↳ `value` | json | Custom field value \(string or list of strings\) | +| ↳ `creationDate` | string | When the control was created \(null for Vanta library controls\) | +| ↳ `modificationDate` | string | When the control was last modified \(null for Vanta library controls\) | +| ↳ `note` | string | A user-created note for the control | +| ↳ `status` | string | Control status \(NO_EVIDENCE_MAPPED, NOT_STARTED, IN_PROGRESS, or COMPLETED\) | +| ↳ `numDocumentsPassing` | number | Number of passing documents linked to the control | +| ↳ `numDocumentsTotal` | number | Total number of documents linked to the control | +| ↳ `numTestsPassing` | number | Number of passing tests linked to the control | +| ↳ `numTestsTotal` | number | Total number of tests linked to the control | @@ -165,7 +265,36 @@ List the automated tests mapped to a specific Vanta control | Parameter | Type | Description | | --------- | ---- | ----------- | | `tests` | array | Tests mapped to the control | +| ↳ `id` | string | The test's unique ID | +| ↳ `name` | string | The test's name | +| ↳ `description` | string | The test's description | +| ↳ `failureDescription` | string | The test's failure description | +| ↳ `remediationDescription` | string | The test's remediation description | +| ↳ `category` | string | The test's category | +| ↳ `status` | string | Test run status \(OK, DEACTIVATED, NEEDS_ATTENTION, IN_PROGRESS, INVALID, or NOT_APPLICABLE\) | +| ↳ `integrations` | array | The test's third-party integration dependencies | +| ↳ `lastTestRunDate` | string | Timestamp of the last test run | +| ↳ `latestFlipDate` | string | Most recent date the test flipped status | +| ↳ `version` | json | The test's version | +| ↳ `major` | number | Major version number | +| ↳ `minor` | number | Minor version number | +| ↳ `deactivatedStatusInfo` | json | The test's deactivation status | +| ↳ `isDeactivated` | boolean | Whether the test is deactivated | +| ↳ `deactivatedReason` | string | Reason for deactivation | +| ↳ `lastUpdatedDate` | string | Date of the last deactivation status update | +| ↳ `remediationStatusInfo` | json | The test's remediation status | +| ↳ `status` | string | Remediation status | +| ↳ `soonestRemediateByDate` | string | Soonest remediate-by date | +| ↳ `itemCount` | number | Number of items needing remediation | +| ↳ `owner` | json | The test's owner | +| ↳ `id` | string | Unique ID of the owner | +| ↳ `displayName` | string | Display name of the owner | +| ↳ `emailAddress` | string | Email address of the owner | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -188,7 +317,20 @@ List the evidence documents mapped to a specific Vanta control | Parameter | Type | Description | | --------- | ---- | ----------- | | `documents` | array | Documents mapped to the control | +| ↳ `id` | string | The document's unique ID | +| ↳ `title` | string | The document's title | +| ↳ `description` | string | The document's description | +| ↳ `category` | string | The document's category | +| ↳ `ownerId` | string | User ID of the document's owner | +| ↳ `isSensitive` | boolean | Whether the document is sensitive | +| ↳ `uploadStatus` | string | Document status \("Needs document", "Needs update", "Not relevant", or "OK"\) | +| ↳ `uploadStatusDate` | string | Date the upload status last changed | +| ↳ `url` | string | URL to view the document within Vanta | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -217,7 +359,36 @@ List the automated compliance tests in a Vanta account, with filters for status, | Parameter | Type | Description | | --------- | ---- | ----------- | | `tests` | array | Tests matching the filters | +| ↳ `id` | string | The test's unique ID | +| ↳ `name` | string | The test's name | +| ↳ `description` | string | The test's description | +| ↳ `failureDescription` | string | The test's failure description | +| ↳ `remediationDescription` | string | The test's remediation description | +| ↳ `category` | string | The test's category | +| ↳ `status` | string | Test run status \(OK, DEACTIVATED, NEEDS_ATTENTION, IN_PROGRESS, INVALID, or NOT_APPLICABLE\) | +| ↳ `integrations` | array | The test's third-party integration dependencies | +| ↳ `lastTestRunDate` | string | Timestamp of the last test run | +| ↳ `latestFlipDate` | string | Most recent date the test flipped status | +| ↳ `version` | json | The test's version | +| ↳ `major` | number | Major version number | +| ↳ `minor` | number | Minor version number | +| ↳ `deactivatedStatusInfo` | json | The test's deactivation status | +| ↳ `isDeactivated` | boolean | Whether the test is deactivated | +| ↳ `deactivatedReason` | string | Reason for deactivation | +| ↳ `lastUpdatedDate` | string | Date of the last deactivation status update | +| ↳ `remediationStatusInfo` | json | The test's remediation status | +| ↳ `status` | string | Remediation status | +| ↳ `soonestRemediateByDate` | string | Soonest remediate-by date | +| ↳ `itemCount` | number | Number of items needing remediation | +| ↳ `owner` | json | The test's owner | +| ↳ `id` | string | Unique ID of the owner | +| ↳ `displayName` | string | Display name of the owner | +| ↳ `emailAddress` | string | Email address of the owner | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -238,6 +409,31 @@ Get a Vanta automated compliance test by ID, including its status and remediatio | Parameter | Type | Description | | --------- | ---- | ----------- | | `test` | json | The requested test | +| ↳ `id` | string | The test's unique ID | +| ↳ `name` | string | The test's name | +| ↳ `description` | string | The test's description | +| ↳ `failureDescription` | string | The test's failure description | +| ↳ `remediationDescription` | string | The test's remediation description | +| ↳ `category` | string | The test's category | +| ↳ `status` | string | Test run status \(OK, DEACTIVATED, NEEDS_ATTENTION, IN_PROGRESS, INVALID, or NOT_APPLICABLE\) | +| ↳ `integrations` | array | The test's third-party integration dependencies | +| ↳ `lastTestRunDate` | string | Timestamp of the last test run | +| ↳ `latestFlipDate` | string | Most recent date the test flipped status | +| ↳ `version` | json | The test's version | +| ↳ `major` | number | Major version number | +| ↳ `minor` | number | Minor version number | +| ↳ `deactivatedStatusInfo` | json | The test's deactivation status | +| ↳ `isDeactivated` | boolean | Whether the test is deactivated | +| ↳ `deactivatedReason` | string | Reason for deactivation | +| ↳ `lastUpdatedDate` | string | Date of the last deactivation status update | +| ↳ `remediationStatusInfo` | json | The test's remediation status | +| ↳ `status` | string | Remediation status | +| ↳ `soonestRemediateByDate` | string | Soonest remediate-by date | +| ↳ `itemCount` | number | Number of items needing remediation | +| ↳ `owner` | json | The test's owner | +| ↳ `id` | string | Unique ID of the owner | +| ↳ `displayName` | string | Display name of the owner | +| ↳ `emailAddress` | string | Email address of the owner | @@ -261,7 +457,18 @@ List the failing or deactivated resource entities for a specific Vanta test, use | Parameter | Type | Description | | --------- | ---- | ----------- | | `entities` | array | Resource entities for the test | +| ↳ `id` | string | Identifier of the entity | +| ↳ `entityStatus` | string | Entity status \(FAILING or DEACTIVATED\) | +| ↳ `displayName` | string | Display name of the entity | +| ↳ `responseType` | string | Response type of the entity | +| ↳ `deactivatedReason` | string | Reason for deactivation | +| ↳ `createdDate` | string | Date the entity was first detected | +| ↳ `lastUpdatedDate` | string | Date of the last update to the entity | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -285,7 +492,20 @@ List the evidence documents in a Vanta account, optionally filtered by framework | Parameter | Type | Description | | --------- | ---- | ----------- | | `documents` | array | Documents matching the filters | +| ↳ `id` | string | The document's unique ID | +| ↳ `title` | string | The document's title | +| ↳ `description` | string | The document's description | +| ↳ `category` | string | The document's category | +| ↳ `ownerId` | string | User ID of the document's owner | +| ↳ `isSensitive` | boolean | Whether the document is sensitive | +| ↳ `uploadStatus` | string | Document status \("Needs document", "Needs update", "Not relevant", or "OK"\) | +| ↳ `uploadStatusDate` | string | Date the upload status last changed | +| ↳ `url` | string | URL to view the document within Vanta | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -306,6 +526,25 @@ Get a Vanta evidence document by ID, including its renewal schedule and deactiva | Parameter | Type | Description | | --------- | ---- | ----------- | | `document` | json | The requested document | +| ↳ `id` | string | The document's unique ID | +| ↳ `title` | string | The document's title | +| ↳ `description` | string | The document's description | +| ↳ `category` | string | The document's category | +| ↳ `ownerId` | string | User ID of the document's owner | +| ↳ `isSensitive` | boolean | Whether the document is sensitive | +| ↳ `uploadStatus` | string | Document status \("Needs document", "Needs update", "Not relevant", or "OK"\) | +| ↳ `uploadStatusDate` | string | Date the upload status last changed | +| ↳ `url` | string | URL to view the document within Vanta | +| ↳ `note` | string | A user note for the document | +| ↳ `nextRenewalDate` | string | When the document needs to be renewed | +| ↳ `renewalCadence` | string | How often the document must be renewed | +| ↳ `reminderWindow` | string | Reminder window ahead of the renewal date \(P0D, P1D, P1W, P1M, or P3M\) | +| ↳ `subscribers` | array | Emails subscribed to the document | +| ↳ `deactivatedStatus` | json | The document's deactivation status | +| ↳ `isDeactivated` | boolean | Whether the document is deactivated | +| ↳ `reason` | string | Reason the document was deactivated | +| ↳ `creationDate` | string | Date the document was deactivated | +| ↳ `expiration` | string | Date the deactivation expires | @@ -328,7 +567,24 @@ List the files uploaded to a specific Vanta evidence document | Parameter | Type | Description | | --------- | ---- | ----------- | | `uploads` | array | Files uploaded to the document | +| ↳ `id` | string | Unique ID of the uploaded file | +| ↳ `fileName` | string | File name of the upload | +| ↳ `title` | string | Title of the upload | +| ↳ `description` | string | Description of the upload | +| ↳ `mimeType` | string | MIME type of the uploaded file | +| ↳ `uploadedBy` | json | Actor who uploaded the file \(a user or an application\) | +| ↳ `id` | string | Actor ID | +| ↳ `type` | string | Actor type \(USER or APPLICATION\) | +| ↳ `creationDate` | string | Date the file was uploaded | +| ↳ `updatedDate` | string | Date the file was last updated | +| ↳ `deletionDate` | string | Date the file was deleted \(null if not deleted\) | +| ↳ `effectiveDate` | string | The file's effective date | +| ↳ `url` | string | The file's URL | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -354,6 +610,19 @@ Upload an evidence file to a Vanta document. Requires credentials with the vanta | Parameter | Type | Description | | --------- | ---- | ----------- | | `upload` | json | Metadata of the uploaded file | +| ↳ `id` | string | Unique ID of the uploaded file | +| ↳ `fileName` | string | File name of the upload | +| ↳ `title` | string | Title of the upload | +| ↳ `description` | string | Description of the upload | +| ↳ `mimeType` | string | MIME type of the uploaded file | +| ↳ `uploadedBy` | json | Actor who uploaded the file \(a user or an application\) | +| ↳ `id` | string | Actor ID | +| ↳ `type` | string | Actor type \(USER or APPLICATION\) | +| ↳ `creationDate` | string | Date the file was uploaded | +| ↳ `updatedDate` | string | Date the file was last updated | +| ↳ `deletionDate` | string | Date the file was deleted \(null if not deleted\) | +| ↳ `effectiveDate` | string | The file's effective date | +| ↳ `url` | string | The file's URL | @@ -426,7 +695,32 @@ List the people tracked in a Vanta account with employment status, group members | Parameter | Type | Description | | --------- | ---- | ----------- | | `people` | array | People matching the filters | +| ↳ `id` | string | The person's unique ID | +| ↳ `userId` | string | ID of the associated Vanta user account, if one exists | +| ↳ `emailAddress` | string | The person's email address | +| ↳ `name` | json | The person's name | +| ↳ `first` | string | First \(given\) name | +| ↳ `last` | string | Last \(family\) name | +| ↳ `display` | string | Display name used in Vanta | +| ↳ `employment` | json | The person's employment information | +| ↳ `status` | string | Employment status \(UPCOMING, CURRENT, ON_LEAVE, INACTIVE, or FORMER\) | +| ↳ `startDate` | string | Employment start date | +| ↳ `endDate` | string | Employment end date, if present | +| ↳ `jobTitle` | string | Job title | +| ↳ `leaveInfo` | json | The person's active or upcoming leave, if any | +| ↳ `status` | string | Leave status \(ACTIVE or UPCOMING\) | +| ↳ `startDate` | string | Start of the leave | +| ↳ `endDate` | string | End of the leave \(null implies indefinite leave\) | +| ↳ `groupIds` | array | IDs of the groups the person belongs to | +| ↳ `tasksSummary` | json | Aggregated status of the person's tasks | +| ↳ `status` | string | Overall task status \(e.g., NONE, DUE_SOON, OVERDUE, COMPLETE, PAUSED, or an OFFBOARDING_* variant\) | +| ↳ `dueDate` | string | Due date of the person's earliest-due task | +| ↳ `completionDate` | string | Date the person's tasks were completed | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -447,6 +741,27 @@ Get a person tracked in Vanta by ID, including employment, leave, and security t | Parameter | Type | Description | | --------- | ---- | ----------- | | `person` | json | The requested person | +| ↳ `id` | string | The person's unique ID | +| ↳ `userId` | string | ID of the associated Vanta user account, if one exists | +| ↳ `emailAddress` | string | The person's email address | +| ↳ `name` | json | The person's name | +| ↳ `first` | string | First \(given\) name | +| ↳ `last` | string | Last \(family\) name | +| ↳ `display` | string | Display name used in Vanta | +| ↳ `employment` | json | The person's employment information | +| ↳ `status` | string | Employment status \(UPCOMING, CURRENT, ON_LEAVE, INACTIVE, or FORMER\) | +| ↳ `startDate` | string | Employment start date | +| ↳ `endDate` | string | Employment end date, if present | +| ↳ `jobTitle` | string | Job title | +| ↳ `leaveInfo` | json | The person's active or upcoming leave, if any | +| ↳ `status` | string | Leave status \(ACTIVE or UPCOMING\) | +| ↳ `startDate` | string | Start of the leave | +| ↳ `endDate` | string | End of the leave \(null implies indefinite leave\) | +| ↳ `groupIds` | array | IDs of the groups the person belongs to | +| ↳ `tasksSummary` | json | Aggregated status of the person's tasks | +| ↳ `status` | string | Overall task status \(e.g., NONE, DUE_SOON, OVERDUE, COMPLETE, PAUSED, or an OFFBOARDING_* variant\) | +| ↳ `dueDate` | string | Due date of the person's earliest-due task | +| ↳ `completionDate` | string | Date the person's tasks were completed | @@ -468,7 +783,23 @@ List the security policies in a Vanta account with approval status and version i | Parameter | Type | Description | | --------- | ---- | ----------- | | `policies` | array | Policies in the Vanta account | +| ↳ `id` | string | The policy's unique ID | +| ↳ `name` | string | The policy's name | +| ↳ `description` | string | The policy's description | +| ↳ `status` | string | Policy status \(OK or NEEDS_REMEDIATION\) | +| ↳ `approvedAtDate` | string | The policy's most recent approval date, if applicable | +| ↳ `latestVersionStatus` | string | Status of the policy's latest version \(NOT_STARTED, DRAFT, PENDING_APPROVAL, APPROVED, RENEW_SOON, or EXPIRED\) | +| ↳ `latestApprovedVersion` | json | The latest approved version of the policy, if available | +| ↳ `versionId` | string | ID of the latest approved version | +| ↳ `documents` | array | Available policy document versions, organized by language | +| ↳ `language` | string | Document language | +| ↳ `slugId` | string | Document slug ID | +| ↳ `url` | string | Document URL | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -489,6 +820,18 @@ Get a Vanta security policy by ID, including its approval status and latest appr | Parameter | Type | Description | | --------- | ---- | ----------- | | `policy` | json | The requested policy | +| ↳ `id` | string | The policy's unique ID | +| ↳ `name` | string | The policy's name | +| ↳ `description` | string | The policy's description | +| ↳ `status` | string | Policy status \(OK or NEEDS_REMEDIATION\) | +| ↳ `approvedAtDate` | string | The policy's most recent approval date, if applicable | +| ↳ `latestVersionStatus` | string | Status of the policy's latest version \(NOT_STARTED, DRAFT, PENDING_APPROVAL, APPROVED, RENEW_SOON, or EXPIRED\) | +| ↳ `latestApprovedVersion` | json | The latest approved version of the policy, if available | +| ↳ `versionId` | string | ID of the latest approved version | +| ↳ `documents` | array | Available policy document versions, organized by language | +| ↳ `language` | string | Document language | +| ↳ `slugId` | string | Document slug ID | +| ↳ `url` | string | Document URL | @@ -512,7 +855,51 @@ List the vendors tracked in a Vanta account with risk levels, contract dates, an | Parameter | Type | Description | | --------- | ---- | ----------- | | `vendors` | array | Vendors matching the filters | +| ↳ `id` | string | The vendor's unique ID | +| ↳ `name` | string | The vendor's display name | +| ↳ `status` | string | Vendor status \(MANAGED, ARCHIVED, or IN_PROCUREMENT\) | +| ↳ `websiteUrl` | string | The vendor's website URL | +| ↳ `category` | string | Display name of the vendor's category | +| ↳ `servicesProvided` | string | Services provided by the vendor | +| ↳ `additionalNotes` | string | Additional notes about the vendor | +| ↳ `accountManagerName` | string | The vendor's external account manager name | +| ↳ `accountManagerEmail` | string | The vendor's external account manager email | +| ↳ `securityOwnerUserId` | string | Vanta user ID of the vendor's security owner | +| ↳ `businessOwnerUserId` | string | Vanta user ID of the vendor's business owner | +| ↳ `inherentRiskLevel` | string | Inherent risk level \(CRITICAL, HIGH, MEDIUM, LOW, or UNSCORED\) | +| ↳ `residualRiskLevel` | string | Residual risk level \(CRITICAL, HIGH, MEDIUM, LOW, or UNSCORED\) | +| ↳ `isRiskAutoScored` | boolean | Whether the vendor's risk is automatically scored | +| ↳ `isVisibleToAuditors` | boolean | Whether auditors can view this vendor | +| ↳ `riskAttributeIds` | array | Risk attribute IDs assigned to the vendor | +| ↳ `vendorHeadquarters` | string | Country code of the vendor's headquarters | +| ↳ `contractStartDate` | string | Date the vendor contract began | +| ↳ `contractRenewalDate` | string | Date the vendor contract is up for renewal | +| ↳ `contractTerminationDate` | string | Date the vendor contract was terminated | +| ↳ `contractAmount` | json | Contract amount for the vendor | +| ↳ `amount` | number | Amount of the contract | +| ↳ `currency` | string | Currency of the contract | +| ↳ `nextSecurityReviewDueDate` | string | Next due date for a security review | +| ↳ `lastSecurityReviewCompletionDate` | string | Most recent date a security review was completed | +| ↳ `authDetails` | json | The vendor's authentication details | +| ↳ `method` | string | Authentication method \(e.g., SSO, OKTA, USERNAME_PASSWORD\) | +| ↳ `passwordMFA` | boolean | Whether passwords require multi-factor authentication | +| ↳ `passwordMinimumLength` | number | Minimum password length | +| ↳ `passwordRequiresNumber` | boolean | Whether passwords require a number | +| ↳ `passwordRequiresSymbol` | boolean | Whether passwords require a symbol | +| ↳ `customFields` | array | Custom field values configured in the Vanta instance | +| ↳ `label` | string | Custom field label | +| ↳ `value` | json | Custom field value \(string or list of strings\) | +| ↳ `latestDecision` | json | The vendor's latest decision \(null when no decision has been made\) | +| ↳ `status` | string | Decision status \(APPROVED, CONDITIONALLY_APPROVED, or NOT_APPROVED\) | +| ↳ `lastUpdatedAt` | string | When the decision was last updated | +| ↳ `linkedTaskTrackerTaskProcurementRequest` | json | Linked task tracker procurement request, if any | +| ↳ `url` | string | URL of the procurement request | +| ↳ `service` | string | Task tracker service | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -533,6 +920,46 @@ Get a Vanta vendor by ID, including risk levels, contract details, and authentic | Parameter | Type | Description | | --------- | ---- | ----------- | | `vendor` | json | The requested vendor | +| ↳ `id` | string | The vendor's unique ID | +| ↳ `name` | string | The vendor's display name | +| ↳ `status` | string | Vendor status \(MANAGED, ARCHIVED, or IN_PROCUREMENT\) | +| ↳ `websiteUrl` | string | The vendor's website URL | +| ↳ `category` | string | Display name of the vendor's category | +| ↳ `servicesProvided` | string | Services provided by the vendor | +| ↳ `additionalNotes` | string | Additional notes about the vendor | +| ↳ `accountManagerName` | string | The vendor's external account manager name | +| ↳ `accountManagerEmail` | string | The vendor's external account manager email | +| ↳ `securityOwnerUserId` | string | Vanta user ID of the vendor's security owner | +| ↳ `businessOwnerUserId` | string | Vanta user ID of the vendor's business owner | +| ↳ `inherentRiskLevel` | string | Inherent risk level \(CRITICAL, HIGH, MEDIUM, LOW, or UNSCORED\) | +| ↳ `residualRiskLevel` | string | Residual risk level \(CRITICAL, HIGH, MEDIUM, LOW, or UNSCORED\) | +| ↳ `isRiskAutoScored` | boolean | Whether the vendor's risk is automatically scored | +| ↳ `isVisibleToAuditors` | boolean | Whether auditors can view this vendor | +| ↳ `riskAttributeIds` | array | Risk attribute IDs assigned to the vendor | +| ↳ `vendorHeadquarters` | string | Country code of the vendor's headquarters | +| ↳ `contractStartDate` | string | Date the vendor contract began | +| ↳ `contractRenewalDate` | string | Date the vendor contract is up for renewal | +| ↳ `contractTerminationDate` | string | Date the vendor contract was terminated | +| ↳ `contractAmount` | json | Contract amount for the vendor | +| ↳ `amount` | number | Amount of the contract | +| ↳ `currency` | string | Currency of the contract | +| ↳ `nextSecurityReviewDueDate` | string | Next due date for a security review | +| ↳ `lastSecurityReviewCompletionDate` | string | Most recent date a security review was completed | +| ↳ `authDetails` | json | The vendor's authentication details | +| ↳ `method` | string | Authentication method \(e.g., SSO, OKTA, USERNAME_PASSWORD\) | +| ↳ `passwordMFA` | boolean | Whether passwords require multi-factor authentication | +| ↳ `passwordMinimumLength` | number | Minimum password length | +| ↳ `passwordRequiresNumber` | boolean | Whether passwords require a number | +| ↳ `passwordRequiresSymbol` | boolean | Whether passwords require a symbol | +| ↳ `customFields` | array | Custom field values configured in the Vanta instance | +| ↳ `label` | string | Custom field label | +| ↳ `value` | json | Custom field value \(string or list of strings\) | +| ↳ `latestDecision` | json | The vendor's latest decision \(null when no decision has been made\) | +| ↳ `status` | string | Decision status \(APPROVED, CONDITIONALLY_APPROVED, or NOT_APPROVED\) | +| ↳ `lastUpdatedAt` | string | When the decision was last updated | +| ↳ `linkedTaskTrackerTaskProcurementRequest` | json | Linked task tracker procurement request, if any | +| ↳ `url` | string | URL of the procurement request | +| ↳ `service` | string | Task tracker service | @@ -555,7 +982,27 @@ List the monitored computers in a Vanta account with screenlock, disk encryption | Parameter | Type | Description | | --------- | ---- | ----------- | | `computers` | array | Monitored computers matching the filters | +| ↳ `id` | string | Unique identifier of the monitored computer | +| ↳ `integrationId` | string | Integration that reports this computer | +| ↳ `lastCheckDate` | string | Date of the computer's most recent report | +| ↳ `screenlock` | string | Screenlock check outcome \(PASS, FAIL, IN_PROGRESS, or NA\) | +| ↳ `diskEncryption` | string | Disk encryption check outcome \(PASS, FAIL, IN_PROGRESS, or NA\) | +| ↳ `passwordManager` | string | Password manager check outcome \(PASS, FAIL, IN_PROGRESS, or NA\) | +| ↳ `antivirusInstallation` | string | Antivirus check outcome \(PASS, FAIL, IN_PROGRESS, or NA\) | +| ↳ `operatingSystem` | json | The computer's operating system | +| ↳ `type` | string | Operating system type \(macOS, linux, or windows\) | +| ↳ `version` | string | Operating system version | +| ↳ `owner` | json | The computer's owner | +| ↳ `id` | string | Unique ID of the owner | +| ↳ `displayName` | string | Display name of the owner | +| ↳ `emailAddress` | string | Email address of the owner | +| ↳ `serialNumber` | string | Serial number of the computer | +| ↳ `udid` | string | Universal device ID of the computer | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -588,7 +1035,37 @@ List the vulnerabilities detected across a Vanta account with filters for severi | Parameter | Type | Description | | --------- | ---- | ----------- | | `vulnerabilities` | array | Vulnerabilities matching the filters | +| ↳ `id` | string | Unique identifier of the vulnerability | +| ↳ `name` | string | Display name of the vulnerability | +| ↳ `description` | string | Description of the vulnerability | +| ↳ `severity` | string | Severity \(LOW, MEDIUM, HIGH, or CRITICAL\) | +| ↳ `vulnerabilityType` | string | Vulnerability type \(CONFIGURATION, COMMON, or GROUPED\) | +| ↳ `integrationId` | string | Integration that scans this vulnerability | +| ↳ `targetId` | string | ID of the resource the vulnerability was found on | +| ↳ `packageIdentifier` | string | Identifier of the affected package \(COMMON and GROUPED vulnerabilities only\) | +| ↳ `cvssSeverityScore` | number | CVSS severity score | +| ↳ `scannerScore` | number | Scanner score | +| ↳ `isFixable` | boolean | Whether the vulnerability is fixable | +| ↳ `fixedVersion` | string | Package version that remediates the vulnerability | +| ↳ `remediateByDate` | string | SLA date by which the vulnerability should be remediated | +| ↳ `firstDetectedDate` | string | Date first detected by Vanta | +| ↳ `sourceDetectedDate` | string | Date first detected by the source | +| ↳ `lastDetectedDate` | string | Date last detected | +| ↳ `scanSource` | string | Scanning tool that detected the vulnerability | +| ↳ `externalURL` | string | External URL for the vulnerability | +| ↳ `relatedVulns` | array | Related vulnerabilities \(GROUPED vulnerabilities only\) | +| ↳ `relatedUrls` | array | Related URLs | +| ↳ `deactivateMetadata` | json | Deactivation metadata, if the vulnerability was deactivated | +| ↳ `isVulnDeactivatedIndefinitely` | boolean | Whether deactivated indefinitely | +| ↳ `deactivatedUntilDate` | string | Date the vulnerability will be reactivated | +| ↳ `deactivationReason` | string | Reason for deactivation | +| ↳ `deactivatedOnDate` | string | Date the vulnerability was deactivated | +| ↳ `deactivatedBy` | string | User who deactivated the vulnerability | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -615,7 +1092,18 @@ List remediated vulnerabilities in a Vanta account with detection, SLA deadline, | Parameter | Type | Description | | --------- | ---- | ----------- | | `remediations` | array | Vulnerability remediations matching the filters | +| ↳ `id` | string | Unique identifier of the remediation | +| ↳ `vulnerabilityId` | string | ID of the remediated vulnerability | +| ↳ `vulnerableAssetId` | string | ID of the vulnerable asset | +| ↳ `severity` | string | Severity of the vulnerability | +| ↳ `detectedDate` | string | Date the vulnerability was first detected | +| ↳ `slaDeadlineDate` | string | SLA deadline for remediation | +| ↳ `remediationDate` | string | Date the vulnerability was remediated | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -641,7 +1129,34 @@ List the assets associated with vulnerabilities in a Vanta account (servers, rep | Parameter | Type | Description | | --------- | ---- | ----------- | | `assets` | array | Vulnerable assets matching the filters | +| ↳ `id` | string | Unique identifier of the vulnerable asset | +| ↳ `name` | string | Display name of the vulnerable asset | +| ↳ `assetType` | string | Asset type \(e.g., SERVER, SERVERLESS_FUNCTION, CONTAINER_REPOSITORY, CODE_REPOSITORY, WORKSTATION\) | +| ↳ `hasBeenScanned` | boolean | Whether the asset has been scanned | +| ↳ `imageScanTag` | string | Container image tag that vulnerabilities are retrieved for \(container repositories only\) | +| ↳ `scanners` | array | Integrations scanning this asset, with per-scanner asset details \(resource ID, hostnames, IPs, image metadata\) | +| ↳ `resourceId` | string | Vanta resource ID | +| ↳ `integrationId` | string | Scanning integration ID | +| ↳ `targetId` | string | Asset identifier in the scanning source | +| ↳ `imageDigest` | string | Container image digest | +| ↳ `imagePushedAtDate` | string | Container image push date | +| ↳ `parentAccountOrOrganization` | string | Parent account or organization | +| ↳ `biosUuid` | string | BIOS UUID | +| ↳ `imageTags` | array | Container image tags | +| ↳ `ipv4s` | array | IPv4 addresses | +| ↳ `ipv6s` | array | IPv6 addresses | +| ↳ `macAddresses` | array | MAC addresses | +| ↳ `hostnames` | array | Host names | +| ↳ `fqdns` | array | Fully qualified domain names | +| ↳ `operatingSystems` | array | Operating systems | +| ↳ `assetTags` | array | Tags from the scanning source | +| ↳ `key` | string | Tag key | +| ↳ `value` | string | Tag value | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -662,6 +1177,29 @@ Get a vulnerable asset in Vanta by ID, including the scanners reporting it and p | Parameter | Type | Description | | --------- | ---- | ----------- | | `asset` | json | The requested vulnerable asset | +| ↳ `id` | string | Unique identifier of the vulnerable asset | +| ↳ `name` | string | Display name of the vulnerable asset | +| ↳ `assetType` | string | Asset type \(e.g., SERVER, SERVERLESS_FUNCTION, CONTAINER_REPOSITORY, CODE_REPOSITORY, WORKSTATION\) | +| ↳ `hasBeenScanned` | boolean | Whether the asset has been scanned | +| ↳ `imageScanTag` | string | Container image tag that vulnerabilities are retrieved for \(container repositories only\) | +| ↳ `scanners` | array | Integrations scanning this asset, with per-scanner asset details \(resource ID, hostnames, IPs, image metadata\) | +| ↳ `resourceId` | string | Vanta resource ID | +| ↳ `integrationId` | string | Scanning integration ID | +| ↳ `targetId` | string | Asset identifier in the scanning source | +| ↳ `imageDigest` | string | Container image digest | +| ↳ `imagePushedAtDate` | string | Container image push date | +| ↳ `parentAccountOrOrganization` | string | Parent account or organization | +| ↳ `biosUuid` | string | BIOS UUID | +| ↳ `imageTags` | array | Container image tags | +| ↳ `ipv4s` | array | IPv4 addresses | +| ↳ `ipv6s` | array | IPv6 addresses | +| ↳ `macAddresses` | array | MAC addresses | +| ↳ `hostnames` | array | Host names | +| ↳ `fqdns` | array | Fully qualified domain names | +| ↳ `operatingSystems` | array | Operating systems | +| ↳ `assetTags` | array | Tags from the scanning source | +| ↳ `key` | string | Tag key | +| ↳ `value` | string | Tag value | @@ -694,7 +1232,31 @@ List the risk scenarios in a Vanta risk register with likelihood/impact scores, | Parameter | Type | Description | | --------- | ---- | ----------- | | `riskScenarios` | array | Risk scenarios matching the filters | +| ↳ `riskId` | string | Unique user-specified ID of the risk scenario | +| ↳ `description` | string | Description of the risk scenario | +| ↳ `likelihood` | number | Likelihood score \(defaults to a 1-5 range; null when unscored\) | +| ↳ `impact` | number | Impact score \(defaults to a 1-5 range; null when unscored\) | +| ↳ `residualLikelihood` | number | Residual likelihood score after treatments | +| ↳ `residualImpact` | number | Residual impact score after treatments | +| ↳ `categories` | array | Categories this risk scenario belongs to | +| ↳ `ciaCategories` | array | CIA categories \(Confidentiality, Integrity, Availability\) | +| ↳ `treatment` | string | Risk treatment decision \(Mitigate, Transfer, Avoid, or Accept\) | +| ↳ `owner` | string | Email of the person responsible for this risk | +| ↳ `note` | string | Additional context about the risk scenario | +| ↳ `riskRegister` | string | Name of the associated risk register | +| ↳ `customFields` | array | Custom field values configured in the Vanta instance | +| ↳ `label` | string | Custom field label | +| ↳ `value` | json | Custom field value \(string or list of strings\) | +| ↳ `isArchived` | boolean | Whether the scenario is archived | +| ↳ `reviewStatus` | string | Review status \(APPROVED, DRAFT, NOT_REVIEWED, AWAITING_SUBMISSION, PENDING_APPROVAL, or REQUESTED_CHANGES\) | +| ↳ `requiredApprovers` | array | Required approvers for this risk scenario | +| ↳ `type` | string | Scenario type \("Risk Scenario" or "Enterprise Risk"\) | +| ↳ `identificationDate` | string | Date this risk was identified | | `pageInfo` | json | Cursor pagination info for the returned page; pass endCursor as pageCursor to fetch the next page | +| ↳ `startCursor` | string | Cursor pointing to the start of the current page | +| ↳ `endCursor` | string | Cursor pointing to the end of the current page; pass as pageCursor to fetch the next page | +| ↳ `hasNextPage` | boolean | Whether another page exists after this one | +| ↳ `hasPreviousPage` | boolean | Whether a page exists before this one | @@ -715,6 +1277,26 @@ Get a Vanta risk scenario by ID, including its scores, treatment decision, and r | Parameter | Type | Description | | --------- | ---- | ----------- | | `riskScenario` | json | The requested risk scenario | +| ↳ `riskId` | string | Unique user-specified ID of the risk scenario | +| ↳ `description` | string | Description of the risk scenario | +| ↳ `likelihood` | number | Likelihood score \(defaults to a 1-5 range; null when unscored\) | +| ↳ `impact` | number | Impact score \(defaults to a 1-5 range; null when unscored\) | +| ↳ `residualLikelihood` | number | Residual likelihood score after treatments | +| ↳ `residualImpact` | number | Residual impact score after treatments | +| ↳ `categories` | array | Categories this risk scenario belongs to | +| ↳ `ciaCategories` | array | CIA categories \(Confidentiality, Integrity, Availability\) | +| ↳ `treatment` | string | Risk treatment decision \(Mitigate, Transfer, Avoid, or Accept\) | +| ↳ `owner` | string | Email of the person responsible for this risk | +| ↳ `note` | string | Additional context about the risk scenario | +| ↳ `riskRegister` | string | Name of the associated risk register | +| ↳ `customFields` | array | Custom field values configured in the Vanta instance | +| ↳ `label` | string | Custom field label | +| ↳ `value` | json | Custom field value \(string or list of strings\) | +| ↳ `isArchived` | boolean | Whether the scenario is archived | +| ↳ `reviewStatus` | string | Review status \(APPROVED, DRAFT, NOT_REVIEWED, AWAITING_SUBMISSION, PENDING_APPROVAL, or REQUESTED_CHANGES\) | +| ↳ `requiredApprovers` | array | Required approvers for this risk scenario | +| ↳ `type` | string | Scenario type \("Risk Scenario" or "Enterprise Risk"\) | +| ↳ `identificationDate` | string | Date this risk was identified | diff --git a/apps/docs/content/docs/integrations/zoho_desk.mdx b/apps/docs/content/docs/integrations/zoho_desk.mdx index 0767b8c16a8..d4a7721bacd 100644 --- a/apps/docs/content/docs/integrations/zoho_desk.mdx +++ b/apps/docs/content/docs/integrations/zoho_desk.mdx @@ -1069,6 +1069,40 @@ List Accounts in Zoho Desk. | Parameter | Type | Description | | --------- | ---- | ----------- | | `accounts` | array | Accounts records, including explicitly requested portal fields | +| ↳ `photoURL` | string | Account photo URL | +| ↳ `owner` | object | Owner | +| ↳ `firstName` | string | First name | +| ↳ `lastName` | string | Last name | +| ↳ `id` | string | Id | +| ↳ `website` | string | Website of the account | +| ↳ `accountName` | string | Name of the account | +| ↳ `phone` | string | Phone number of the account | +| ↳ `email` | string | Email ID of the account | +| ↳ `country` | string | Country | +| ↳ `code` | string | Code | +| ↳ `cf` | json | Cf values defined by the provider or portal configuration | +| ↳ `city` | string | City | +| ↳ `street` | string | Street | +| ↳ `annualrevenue` | string | Annualrevenue | +| ↳ `description` | string | Description | +| ↳ `industry` | string | Industry | +| ↳ `state` | string | State | +| ↳ `ownerId` | string | Owner ID | +| ↳ `fax` | string | Fax | +| ↳ `modifiedTime` | string | Modified time | +| ↳ `isFollowing` | boolean | Is following | +| ↳ `isDeleted` | boolean | Is deleted | +| ↳ `isTrashed` | boolean | Is trashed | +| ↳ `associatedSLAIds` | array | Associated slaids | +| ↳ `webUrl` | string | Web url | +| ↳ `createdTime` | string | Created time | +| ↳ `zohoCRMAccount` | object | Zoho crmaccount | +| ↳ `id` | string | Id | +| ↳ `id` | string | Id | +| ↳ `layoutId` | string | Layout ID | +| ↳ `layoutDetails` | object | Layout details | +| ↳ `id` | string | Id | +| ↳ `layoutName` | string | Layout name | | `count` | number | Number of results in this page | | `nextFrom` | number | Next index to request; null when this page is empty. The next request may return an empty page. | @@ -1107,6 +1141,40 @@ Create Account in Zoho Desk. | Parameter | Type | Description | | --------- | ---- | ----------- | | `account` | object | The account | +| ↳ `photoURL` | string | Account photo URL | +| ↳ `owner` | object | Owner | +| ↳ `firstName` | string | First name | +| ↳ `lastName` | string | Last name | +| ↳ `id` | string | Id | +| ↳ `website` | string | Website of the account | +| ↳ `accountName` | string | Name of the account | +| ↳ `phone` | string | Phone number of the account | +| ↳ `email` | string | Email ID of the account | +| ↳ `country` | string | Country | +| ↳ `code` | string | Code | +| ↳ `cf` | json | Cf values defined by the provider or portal configuration | +| ↳ `city` | string | City | +| ↳ `street` | string | Street | +| ↳ `annualrevenue` | string | Annualrevenue | +| ↳ `description` | string | Description | +| ↳ `industry` | string | Industry | +| ↳ `state` | string | State | +| ↳ `ownerId` | string | Owner ID | +| ↳ `fax` | string | Fax | +| ↳ `modifiedTime` | string | Modified time | +| ↳ `isFollowing` | boolean | Is following | +| ↳ `isDeleted` | boolean | Is deleted | +| ↳ `isTrashed` | boolean | Is trashed | +| ↳ `associatedSLAIds` | array | Associated slaids | +| ↳ `webUrl` | string | Web url | +| ↳ `createdTime` | string | Created time | +| ↳ `zohoCRMAccount` | object | Zoho crmaccount | +| ↳ `id` | string | Id | +| ↳ `id` | string | Id | +| ↳ `layoutId` | string | Layout ID | +| ↳ `layoutDetails` | object | Layout details | +| ↳ `id` | string | Id | +| ↳ `layoutName` | string | Layout name | @@ -1144,6 +1212,40 @@ Update Account in Zoho Desk. | Parameter | Type | Description | | --------- | ---- | ----------- | | `account` | object | The account | +| ↳ `photoURL` | string | Account photo URL | +| ↳ `owner` | object | Owner | +| ↳ `firstName` | string | First name | +| ↳ `lastName` | string | Last name | +| ↳ `id` | string | Id | +| ↳ `website` | string | Website of the account | +| ↳ `accountName` | string | Name of the account | +| ↳ `phone` | string | Phone number of the account | +| ↳ `email` | string | Email ID of the account | +| ↳ `country` | string | Country | +| ↳ `code` | string | Code | +| ↳ `cf` | json | Cf values defined by the provider or portal configuration | +| ↳ `city` | string | City | +| ↳ `street` | string | Street | +| ↳ `annualrevenue` | string | Annualrevenue | +| ↳ `description` | string | Description | +| ↳ `industry` | string | Industry | +| ↳ `state` | string | State | +| ↳ `ownerId` | string | Owner ID | +| ↳ `fax` | string | Fax | +| ↳ `modifiedTime` | string | Modified time | +| ↳ `isFollowing` | boolean | Is following | +| ↳ `isDeleted` | boolean | Is deleted | +| ↳ `isTrashed` | boolean | Is trashed | +| ↳ `associatedSLAIds` | array | Associated slaids | +| ↳ `webUrl` | string | Web url | +| ↳ `createdTime` | string | Created time | +| ↳ `zohoCRMAccount` | object | Zoho crmaccount | +| ↳ `id` | string | Id | +| ↳ `id` | string | Id | +| ↳ `layoutId` | string | Layout ID | +| ↳ `layoutDetails` | object | Layout details | +| ↳ `id` | string | Id | +| ↳ `layoutName` | string | Layout name | @@ -1182,6 +1284,40 @@ Search Accounts in Zoho Desk. | Parameter | Type | Description | | --------- | ---- | ----------- | | `accounts` | array | Search Accounts results | +| ↳ `photoURL` | string | Account photo URL | +| ↳ `owner` | object | Owner | +| ↳ `firstName` | string | First name | +| ↳ `lastName` | string | Last name | +| ↳ `id` | string | Id | +| ↳ `website` | string | Website of the account | +| ↳ `accountName` | string | Name of the account | +| ↳ `phone` | string | Phone number of the account | +| ↳ `email` | string | Email ID of the account | +| ↳ `country` | string | Country | +| ↳ `code` | string | Code | +| ↳ `cf` | json | Cf values defined by the provider or portal configuration | +| ↳ `city` | string | City | +| ↳ `street` | string | Street | +| ↳ `annualrevenue` | string | Annualrevenue | +| ↳ `description` | string | Description | +| ↳ `industry` | string | Industry | +| ↳ `state` | string | State | +| ↳ `ownerId` | string | Owner ID | +| ↳ `fax` | string | Fax | +| ↳ `modifiedTime` | string | Modified time | +| ↳ `isFollowing` | boolean | Is following | +| ↳ `isDeleted` | boolean | Is deleted | +| ↳ `isTrashed` | boolean | Is trashed | +| ↳ `associatedSLAIds` | array | Associated slaids | +| ↳ `webUrl` | string | Web url | +| ↳ `createdTime` | string | Created time | +| ↳ `zohoCRMAccount` | object | Zoho crmaccount | +| ↳ `id` | string | Id | +| ↳ `id` | string | Id | +| ↳ `layoutId` | string | Layout ID | +| ↳ `layoutDetails` | object | Layout details | +| ↳ `id` | string | Id | +| ↳ `layoutName` | string | Layout name | | `count` | number | Number of results in this page | | `nextFrom` | number | Next search index; null for an empty page, a reached total, or the 1000-result search window. Narrow the filters to find further matches. | | `totalCount` | number | Total search matches reported by Zoho, when provided | @@ -1207,6 +1343,40 @@ Get Account in Zoho Desk. | Parameter | Type | Description | | --------- | ---- | ----------- | | `account` | object | The account | +| ↳ `photoURL` | string | Account photo URL | +| ↳ `owner` | object | Owner | +| ↳ `firstName` | string | First name | +| ↳ `lastName` | string | Last name | +| ↳ `id` | string | Id | +| ↳ `website` | string | Website of the account | +| ↳ `accountName` | string | Name of the account | +| ↳ `phone` | string | Phone number of the account | +| ↳ `email` | string | Email ID of the account | +| ↳ `country` | string | Country | +| ↳ `code` | string | Code | +| ↳ `cf` | json | Cf values defined by the provider or portal configuration | +| ↳ `city` | string | City | +| ↳ `street` | string | Street | +| ↳ `annualrevenue` | string | Annualrevenue | +| ↳ `description` | string | Description | +| ↳ `industry` | string | Industry | +| ↳ `state` | string | State | +| ↳ `ownerId` | string | Owner ID | +| ↳ `fax` | string | Fax | +| ↳ `modifiedTime` | string | Modified time | +| ↳ `isFollowing` | boolean | Is following | +| ↳ `isDeleted` | boolean | Is deleted | +| ↳ `isTrashed` | boolean | Is trashed | +| ↳ `associatedSLAIds` | array | Associated slaids | +| ↳ `webUrl` | string | Web url | +| ↳ `createdTime` | string | Created time | +| ↳ `zohoCRMAccount` | object | Zoho crmaccount | +| ↳ `id` | string | Id | +| ↳ `id` | string | Id | +| ↳ `layoutId` | string | Layout ID | +| ↳ `layoutDetails` | object | Layout details | +| ↳ `id` | string | Id | +| ↳ `layoutName` | string | Layout name | @@ -1232,6 +1402,20 @@ List Departments in Zoho Desk. | Parameter | Type | Description | | --------- | ---- | ----------- | | `departments` | array | List Departments results | +| ↳ `isAssignToTeamEnabled` | boolean | Whether assignment to teams is enabled | +| ↳ `chatStatus` | string | Chat status of the department Allowed values: AVAILABLE, DISABLED, NOT_CREATED | +| ↳ `hasLogo` | boolean | Whether the department has a logo | +| ↳ `sanitizedName` | string | Sanitized Name of the department | +| ↳ `isVisibleInCustomerPortal` | boolean | Whether the department is visible in the help center | +| ↳ `creatorId` | string | Unique ID of the user who created the department | +| ↳ `description` | string | Short description of the department | +| ↳ `isDefault` | boolean | Whether this is the default department in the help desk portal | +| ↳ `isEnabled` | boolean | Whether the department is enabled | +| ↳ `name` | string | Name of the department | +| ↳ `createdTime` | string | Time at which the department was created | +| ↳ `id` | string | Unique ID of the department | +| ↳ `nameInCustomerPortal` | string | Display name of the department in the help center | +| ↳ `associatedAgentIds` | array | ID\(s\) of the agents associated with the department | | `count` | number | Number of results in this page | | `nextFrom` | number | Next index to request; null when this page is empty. The next request may return an empty page. | @@ -1255,6 +1439,20 @@ Get Department in Zoho Desk. | Parameter | Type | Description | | --------- | ---- | ----------- | | `department` | object | The department | +| ↳ `isAssignToTeamEnabled` | boolean | Whether assignment to teams is enabled | +| ↳ `chatStatus` | string | Chat status of the department Allowed values: AVAILABLE, DISABLED, NOT_CREATED | +| ↳ `hasLogo` | boolean | Whether the department has a logo | +| ↳ `sanitizedName` | string | Sanitized Name of the department | +| ↳ `isVisibleInCustomerPortal` | boolean | Whether the department is visible in the help center | +| ↳ `creatorId` | string | Unique ID of the user who created the department | +| ↳ `description` | string | Short description of the department | +| ↳ `isDefault` | boolean | Whether this is the default department in the help desk portal | +| ↳ `isEnabled` | boolean | Whether the department is enabled | +| ↳ `name` | string | Name of the department | +| ↳ `createdTime` | string | Time at which the department was created | +| ↳ `id` | string | Unique ID of the department | +| ↳ `nameInCustomerPortal` | string | Display name of the department in the help center | +| ↳ `associatedAgentIds` | array | ID\(s\) of the agents associated with the department | @@ -1290,6 +1488,87 @@ List Agents in Zoho Desk. | Parameter | Type | Description | | --------- | ---- | ----------- | | `agents` | array | List Agents results | +| ↳ `lastName` | string | Last name of the agent | +| ↳ `extn` | string | Extension number of the agent | +| ↳ `roleId` | string | Role ID of the agent | +| ↳ `langCode` | string | Language code of the agent | +| ↳ `mobile` | string | Mobile number of the agent | +| ↳ `emailId` | string | Email ID of the agent | +| ↳ `associatedChatDepartmentIds` | array | Associated chat department IDs | +| ↳ `associatedDepartmentIds` | array | Associated department IDs | +| ↳ `firstName` | string | First name of the agent | +| ↳ `phone` | string | Phone number of the agent | +| ↳ `countryCode` | string | Country code of the agent | +| ↳ `profileId` | string | Profile ID of the agent | +| ↳ `rolePermissionType` | string | Role permission type of the agent. Allowed values: AgentPublic, AgentPersonal, AgentTeamPersonal, Admin, Light, Custom | +| ↳ `aboutInfo` | string | About information of the agent | +| ↳ `status` | string | Activation status of the agent. Allowed values: ACTIVE, DISABLED | +| ↳ `channelExpert` | array | Channel expert | +| ↳ `timeZone` | string | Time zone of the agent | +| ↳ `cf` | json | Cf values defined by the provider or portal configuration | +| ↳ `photoURL` | string | URL of the image file displaying the agent's photo | +| ↳ `name` | string | Full name of the agent | +| ↳ `isConfirmed` | boolean | Indicates whether the agent is a confirmed user in the portal. Allowed values: true = confirmed, false = unconfirmed | +| ↳ `id` | string | Unique ID of the agent | +| ↳ `zuid` | string | Zoho User ID of the agent | +| ↳ `isZiaAgent` | boolean | Indicates whether the agent is a Zia agent or a human agent | +| ↳ `associatedChatDepartments` | array | Associated chat departments | +| ↳ `sanitizedName` | string | Sanitized name of the chat department | +| ↳ `name` | string | Full name of the department | +| ↳ `id` | string | Unique ID of the department | +| ↳ `role` | object | Role | +| ↳ `isDefault` | boolean | Whether this is the default role | +| ↳ `shareDataWithPeers` | boolean | Whether share data with peers | +| ↳ `immediateSubRoles` | array | Immediate sub roles | +| ↳ `encId` | string | Encrypted ID | +| ↳ `name` | string | Name of the role | +| ↳ `description` | string | Description | +| ↳ `adminRole` | boolean | Whether admin role | +| ↳ `reportsTo` | string | ID of the role this role reports to | +| ↳ `id` | string | Unique ID of the role | +| ↳ `isVisible` | boolean | Whether visible | +| ↳ `verifiedEmails` | array | Verified emails | +| ↳ `profile` | object | Profile | +| ↳ `modifiedTime` | string | Timestamp when this record was last modified \(epoch milliseconds\) | +| ↳ `visible` | boolean | Whether visible | +| ↳ `allowedTabs` | array | Allowed tabs | +| ↳ `defaultProfile` | boolean | Whether default profile | +| ↳ `allowedPermissionNames` | array | Allowed permission names | +| ↳ `type` | string | Accepted values: ADMIN, STANDARD, LIGHT, CUSTOM, PORTAL | +| ↳ `invisibleTabs` | array | Invisible tabs | +| ↳ `portalProfile` | boolean | Whether portal profile | +| ↳ `prohibitedPermissionNames` | array | Prohibited permission names | +| ↳ `allowedPermissions` | array | Allowed permissions | +| ↳ `profileDesc` | string | Description of the profile | +| ↳ `createdBy` | string | ID of the user who created this record | +| ↳ `lightAgentProfile` | boolean | Whether light agent profile | +| ↳ `name` | string | Full name of the profile | +| ↳ `visibleTabs` | array | Visible tabs | +| ↳ `createdTime` | string | Timestamp when this record was created \(epoch milliseconds\) | +| ↳ `modifiedBy` | string | ID of the user who last modified this record | +| ↳ `id` | string | Unique ID of the profile | +| ↳ `category` | boolean | Category | +| ↳ `prohibitedPermisisons` | array | Prohibited permisisons | +| ↳ `adminProfile` | boolean | Whether admin profile | +| ↳ `associatedDepartments` | array | Associated departments | +| ↳ `chatStatusId` | string | ID of the chat status | +| ↳ `chatStatus` | string | Status of chat department. Accepted values: AVAILABLE, DISABLED, NOT_CREATED | +| ↳ `isAssignToTeamEnabled` | boolean | Whether is assign to team enabled | +| ↳ `modifiedTime` | string | Timestamp when this record was last modified \(epoch milliseconds\) | +| ↳ `hasLogo` | boolean | Whether has logo | +| ↳ `sanitizedName` | string | Sanitized name of the chat department | +| ↳ `sanitizedDeptHash` | string | Sanitized dept hash | +| ↳ `isVisibleInCustomerPortal` | boolean | Whether visible in the customer portal | +| ↳ `creatorId` | string | ID of the creator | +| ↳ `description` | string | Description | +| ↳ `associatedAgentIds` | array | Associated agent IDs | +| ↳ `isDefault` | boolean | Whether this is the default | +| ↳ `isEnabled` | boolean | Whether enabled | +| ↳ `name` | string | Full name of the agent | +| ↳ `createdTime` | string | Timestamp when this record was created \(epoch milliseconds\) | +| ↳ `id` | string | Unique ID of the department | +| ↳ `nameInCustomerPortal` | string | Name shown in the customer portal | +| ↳ `status` | string | Accepted values: 0, 1, 2 | | `count` | number | Number of results in this page | | `nextFrom` | number | Next index to request; null when this page is empty. The next request may return an empty page. | @@ -1314,6 +1593,87 @@ Get Agent in Zoho Desk. | Parameter | Type | Description | | --------- | ---- | ----------- | | `agent` | object | The agent | +| ↳ `lastName` | string | Last name of the agent | +| ↳ `extn` | string | Extension number of the agent | +| ↳ `roleId` | string | Role ID of the agent | +| ↳ `langCode` | string | Language code of the agent | +| ↳ `mobile` | string | Mobile number of the agent | +| ↳ `emailId` | string | Email ID of the agent | +| ↳ `associatedChatDepartmentIds` | array | Associated chat department IDs | +| ↳ `associatedDepartmentIds` | array | Associated department IDs | +| ↳ `firstName` | string | First name of the agent | +| ↳ `phone` | string | Phone number of the agent | +| ↳ `countryCode` | string | Country code of the agent | +| ↳ `profileId` | string | Profile ID of the agent | +| ↳ `rolePermissionType` | string | Role permission type of the agent. Allowed values: AgentPublic, AgentPersonal, AgentTeamPersonal, Admin, Light, Custom | +| ↳ `aboutInfo` | string | About information of the agent | +| ↳ `status` | string | Activation status of the agent. Allowed values: ACTIVE, DISABLED | +| ↳ `channelExpert` | array | Channel expert | +| ↳ `timeZone` | string | Time zone of the agent | +| ↳ `cf` | json | Cf values defined by the provider or portal configuration | +| ↳ `photoURL` | string | URL of the image file displaying the agent's photo | +| ↳ `name` | string | Full name of the agent | +| ↳ `isConfirmed` | boolean | Indicates whether the agent is a confirmed user in the portal. Allowed values: true = confirmed, false = unconfirmed | +| ↳ `id` | string | Unique ID of the agent | +| ↳ `zuid` | string | Zoho User ID of the agent | +| ↳ `isZiaAgent` | boolean | Indicates whether the agent is a Zia agent or a human agent | +| ↳ `associatedChatDepartments` | array | Associated chat departments | +| ↳ `sanitizedName` | string | Sanitized name of the chat department | +| ↳ `name` | string | Full name of the department | +| ↳ `id` | string | Unique ID of the department | +| ↳ `role` | object | Role | +| ↳ `isDefault` | boolean | Whether this is the default role | +| ↳ `shareDataWithPeers` | boolean | Whether share data with peers | +| ↳ `immediateSubRoles` | array | Immediate sub roles | +| ↳ `encId` | string | Encrypted ID | +| ↳ `name` | string | Name of the role | +| ↳ `description` | string | Description | +| ↳ `adminRole` | boolean | Whether admin role | +| ↳ `reportsTo` | string | ID of the role this role reports to | +| ↳ `id` | string | Unique ID of the role | +| ↳ `isVisible` | boolean | Whether visible | +| ↳ `verifiedEmails` | array | Verified emails | +| ↳ `profile` | object | Profile | +| ↳ `modifiedTime` | string | Timestamp when this record was last modified \(epoch milliseconds\) | +| ↳ `visible` | boolean | Whether visible | +| ↳ `allowedTabs` | array | Allowed tabs | +| ↳ `defaultProfile` | boolean | Whether default profile | +| ↳ `allowedPermissionNames` | array | Allowed permission names | +| ↳ `type` | string | Accepted values: ADMIN, STANDARD, LIGHT, CUSTOM, PORTAL | +| ↳ `invisibleTabs` | array | Invisible tabs | +| ↳ `portalProfile` | boolean | Whether portal profile | +| ↳ `prohibitedPermissionNames` | array | Prohibited permission names | +| ↳ `allowedPermissions` | array | Allowed permissions | +| ↳ `profileDesc` | string | Description of the profile | +| ↳ `createdBy` | string | ID of the user who created this record | +| ↳ `lightAgentProfile` | boolean | Whether light agent profile | +| ↳ `name` | string | Full name of the profile | +| ↳ `visibleTabs` | array | Visible tabs | +| ↳ `createdTime` | string | Timestamp when this record was created \(epoch milliseconds\) | +| ↳ `modifiedBy` | string | ID of the user who last modified this record | +| ↳ `id` | string | Unique ID of the profile | +| ↳ `category` | boolean | Category | +| ↳ `prohibitedPermisisons` | array | Prohibited permisisons | +| ↳ `adminProfile` | boolean | Whether admin profile | +| ↳ `associatedDepartments` | array | Associated departments | +| ↳ `chatStatusId` | string | ID of the chat status | +| ↳ `chatStatus` | string | Status of chat department. Accepted values: AVAILABLE, DISABLED, NOT_CREATED | +| ↳ `isAssignToTeamEnabled` | boolean | Whether is assign to team enabled | +| ↳ `modifiedTime` | string | Timestamp when this record was last modified \(epoch milliseconds\) | +| ↳ `hasLogo` | boolean | Whether has logo | +| ↳ `sanitizedName` | string | Sanitized name of the chat department | +| ↳ `sanitizedDeptHash` | string | Sanitized dept hash | +| ↳ `isVisibleInCustomerPortal` | boolean | Whether visible in the customer portal | +| ↳ `creatorId` | string | ID of the creator | +| ↳ `description` | string | Description | +| ↳ `associatedAgentIds` | array | Associated agent IDs | +| ↳ `isDefault` | boolean | Whether this is the default | +| ↳ `isEnabled` | boolean | Whether enabled | +| ↳ `name` | string | Full name of the agent | +| ↳ `createdTime` | string | Timestamp when this record was created \(epoch milliseconds\) | +| ↳ `id` | string | Unique ID of the department | +| ↳ `nameInCustomerPortal` | string | Name shown in the customer portal | +| ↳ `status` | string | Accepted values: 0, 1, 2 | diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content.tsx index 3932cc438e5..f1fdb49e952 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content.tsx @@ -91,7 +91,7 @@ const PROSE_CLASSES = cn( 'prose prose-base dark:prose-invert max-w-none', 'antialiased break-words tracking-[0]', 'prose-headings:font-semibold prose-headings:tracking-[0] prose-headings:text-[var(--text-primary)]', - 'prose-headings:mb-3 prose-headings:mt-6 first:prose-headings:mt-0', + 'prose-headings:mb-3 prose-headings:mt-6 prose-headings:first:mt-0', 'prose-p:text-base prose-p:leading-[25px] prose-p:text-[var(--text-primary)]', 'prose-li:text-base prose-li:leading-[25px] prose-li:text-[var(--text-primary)]', 'prose-li:my-1', @@ -783,13 +783,10 @@ function ChatContentInner({ {groups.map((group, i) => { if (group.kind === 'inline') { return ( -
:first-child]:mt-0 [&>:last-child]:mb-0')} - > +
(blockId, subBlockId) + const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId) const value = isPreview ? previewValue : (storeValue ?? propValue) @@ -34,7 +34,7 @@ export function Switch({
diff --git a/apps/sim/background/seal-account-tokens.test.ts b/apps/sim/background/seal-account-tokens.test.ts new file mode 100644 index 00000000000..bc48e14cce7 --- /dev/null +++ b/apps/sim/background/seal-account-tokens.test.ts @@ -0,0 +1,67 @@ +/** + * @vitest-environment node + */ + +import { sealingKeyId } from '@sim/security/encryption' +import { databaseMockFns } from '@sim/testing/mocks/database.mock' +import { beforeEach, describe, expect, it, vi } from 'vitest' + +const { mockPostgres } = vi.hoisted(() => ({ mockPostgres: vi.fn() })) + +vi.mock('postgres', () => ({ default: mockPostgres })) +/** The pass derives each column's sealing context from the real column definitions. */ +vi.unmock('@sim/db/schema') + +import { + runSealAccountTokens, + type SealAccountTokensPayload, +} from '@/background/seal-account-tokens' + +const ENCRYPTION_KEY = 'ab'.repeat(32) +const WORKER_KEY_ID = sealingKeyId(Buffer.from(ENCRYPTION_KEY, 'hex')) + +/** A postgres.js client over an empty `account` table. */ +function emptyAccountTable() { + return Object.assign(async () => [], { end: vi.fn(async () => {}) }) +} + +describe('runSealAccountTokens', () => { + beforeEach(() => { + vi.stubEnv('ENCRYPTION_KEY', ENCRYPTION_KEY) + vi.stubEnv('ENCRYPT_ACCOUNT_TOKENS', 'true') + databaseMockFns.mockResolveDbUrl.mockReturnValue('postgresql://fixture/sim') + mockPostgres.mockReset() + mockPostgres.mockImplementation(emptyAccountTable) + }) + + it('refuses a real seal under a key id other than the worker’s, before connecting', async () => { + await expect( + runSealAccountTokens({ mode: 'seal', dryRun: false, expectedKeyId: 'deadbeef' }) + ).rejects.toThrow(`ENCRYPTION_KEY has key id ${WORKER_KEY_ID}, not the expected deadbeef`) + expect(mockPostgres).not.toHaveBeenCalled() + }) + + it('refuses a payload without dryRun instead of treating it as a real run', async () => { + const payload = { mode: 'seal', expectedKeyId: WORKER_KEY_ID } as SealAccountTokensPayload + + await expect(runSealAccountTokens(payload)).rejects.toThrow('dryRun must be a boolean') + expect(mockPostgres).not.toHaveBeenCalled() + }) + + it('refuses to seal while this worker writes plaintext tokens, before connecting', async () => { + vi.stubEnv('ENCRYPT_ACCOUNT_TOKENS', 'false') + + await expect( + runSealAccountTokens({ mode: 'seal', dryRun: false, expectedKeyId: WORKER_KEY_ID }) + ).rejects.toThrow('ENCRYPT_ACCOUNT_TOKENS is not enabled') + expect(mockPostgres).not.toHaveBeenCalled() + }) + + it('still allows unsealing while writers store plaintext, which is the rollback', async () => { + vi.stubEnv('ENCRYPT_ACCOUNT_TOKENS', 'false') + + await expect( + runSealAccountTokens({ mode: 'unseal', dryRun: false, expectedKeyId: WORKER_KEY_ID }) + ).resolves.toEqual({ keyId: WORKER_KEY_ID, scanned: 0, pending: 0, updated: 0, foreignKey: 0 }) + }) +}) diff --git a/apps/sim/background/seal-account-tokens.ts b/apps/sim/background/seal-account-tokens.ts new file mode 100644 index 00000000000..0f0ae8a8dd3 --- /dev/null +++ b/apps/sim/background/seal-account-tokens.ts @@ -0,0 +1,98 @@ +import { resolveDbUrl } from '@sim/db' +import { sealAccountTokens } from '@sim/db/script-migrations/0037_seal_account_tokens' +import { isAccountTokenWriteSealingEnabled, readEncryptionKey } from '@sim/db/sealed-text' +import { createLogger } from '@sim/logger' +import { sealingKeyId } from '@sim/security/encryption' +import { task } from '@trigger.dev/sdk' +import postgres from 'postgres' + +const logger = createLogger('SealAccountTokensTask') + +const MAX_BATCH_SIZE = 1000 +const MAX_PAUSE_MS = 10_000 + +export interface SealAccountTokensPayload { + mode: 'seal' | 'unseal' + dryRun: boolean + /** The key id the fleet logs at startup (`Account token sealing`); must match this worker's. */ + expectedKeyId: string + batchSize?: number + pauseMs?: number +} + +function assertIntegerInRange(name: string, value: number | undefined, min: number, max: number) { + if (value === undefined) return + if (!Number.isInteger(value) || value < min || value > max) { + throw new Error(`${name} must be an integer between ${min} and ${max}`) + } +} + +/** + * Runs the account-token sealing backfill (`0037_seal_account_tokens`) from a worker, which already + * holds the database and the fleet's `ENCRYPTION_KEY`. Refuses before connecting when the payload + * names a key id other than this worker's, so a pass can never seal rows under a key the fleet + * cannot open, and refuses `seal` while this worker's writers still store plaintext. + * + * Opens its own single connection rather than reusing the `@sim/db` pool: the pass binds JS arrays + * through the postgres.js tag, which needs the array type map the shared pool skips + * (`fetch_types: false`). It resolves the same URL as the worker's `db` client and sets no startup + * `search_path`, which PgBouncer rejects. + */ +export async function runSealAccountTokens(payload: SealAccountTokensPayload) { + const { mode, dryRun, expectedKeyId, batchSize, pauseMs } = payload + if (mode !== 'seal' && mode !== 'unseal') throw new Error(`Unknown mode ${String(mode)}`) + if (typeof dryRun !== 'boolean') throw new Error('dryRun must be a boolean') + if (typeof expectedKeyId !== 'string') throw new Error('expectedKeyId must be a string') + assertIntegerInRange('batchSize', batchSize, 1, MAX_BATCH_SIZE) + assertIntegerInRange('pauseMs', pauseMs, 0, MAX_PAUSE_MS) + + const keyId = sealingKeyId(readEncryptionKey()) + if (expectedKeyId !== keyId) { + throw new Error(`ENCRYPTION_KEY has key id ${keyId}, not the expected ${expectedKeyId}`) + } + if (mode === 'seal' && !isAccountTokenWriteSealingEnabled()) { + throw new Error( + 'Refusing to seal: ENCRYPT_ACCOUNT_TOKENS is not enabled on this worker, so writers still store plaintext' + ) + } + + const role = process.env.SIM_DB_ROLE?.trim() || 'web' + const url = resolveDbUrl('DATABASE_URL', role) + if (!url) throw new Error('Missing DATABASE_URL environment variable') + + logger.info('Account token sealing started', { mode, dryRun, keyId, batchSize, pauseMs }) + const sql = postgres(url, { + max: 1, + prepare: false, + connect_timeout: 30, + idle_timeout: 20, + onnotice: () => {}, + connection: { application_name: 'sim-account-token-sealing' }, + }) + try { + const result = await sealAccountTokens(sql, { + mode, + expectedKeyId, + dryRun, + batchSize, + pauseMs, + }) + logger.info('Account token sealing finished', { mode, dryRun, ...result }) + return result + } finally { + await sql.end({ timeout: 5 }) + } +} + +/** Manual-only: never scheduled or dispatched by app code; trigger it from the dashboard or API. */ +export const sealAccountTokensTask = task({ + id: 'seal-account-tokens', + machine: 'small-1x', + maxDuration: 10_800, + retry: { maxAttempts: 1 }, + queue: { + name: 'seal-account-tokens', + concurrencyLimit: 1, + }, + run: (payload: SealAccountTokensPayload) => runSealAccountTokens(payload), +}) diff --git a/apps/sim/blocks/blocks/tailscale.ts b/apps/sim/blocks/blocks/tailscale.ts index f72509a1acf..1fd7ec7025c 100644 --- a/apps/sim/blocks/blocks/tailscale.ts +++ b/apps/sim/blocks/blocks/tailscale.ts @@ -2,12 +2,21 @@ import { TailscaleIcon } from '@/components/icons' import type { BlockConfig, BlockMeta } from '@/blocks/types' import { AuthMode, IntegrationType } from '@/blocks/types' +const SWITCH_DEFAULTS = { + authorize_device: { authorized: true }, + update_device_key: { keyExpiryDisabled: true }, + set_dns_preferences: { magicDNS: true }, + create_auth_key: { reusable: false, ephemeral: false, preauthorized: true }, + list_auth_keys: { all: true }, + get_acl: { details: false }, +} as const + export const TailscaleBlock: BlockConfig = { type: 'tailscale', name: 'Tailscale', description: 'Manage devices and network settings in your Tailscale tailnet', longDescription: - 'Interact with the Tailscale API to manage devices, DNS, ACLs, auth keys, users, and routes across your tailnet.', + 'Manage Tailscale devices, user access, posture attributes, DNS configuration, policy files, keys, subnet routes, and tailnet settings.', docsLink: 'https://docs.sim.ai/integrations/tailscale', category: 'tools', integrationType: IntegrationType.Security, @@ -23,8 +32,6 @@ export const TailscaleBlock: BlockConfig = { delete_device: [ { text: 'Remove device', field: 'deviceId', core: true, after: 'from the tailnet' }, ], - /* `authorized`'s options are labelled "Authorize"/"Deauthorize", so the - chip cannot carry the verb — the sentence states the change instead. */ authorize_device: [ { text: 'Set device', field: 'deviceId', core: true }, { text: 'to', field: 'authorized' }, @@ -74,9 +81,40 @@ export const TailscaleBlock: BlockConfig = { { text: 'tagged', field: 'tags' }, { text: ', expiring in', field: 'expirySeconds', after: 'seconds' }, ], - list_auth_keys: ['List the tailnet auth keys'], + list_auth_keys: ['List active tailnet keys and trust credentials'], get_auth_key: [{ text: 'Fetch auth key', field: 'keyId', core: true }], delete_auth_key: [{ text: 'Revoke auth key', field: 'keyId', core: true }], + set_device_name: [ + { text: 'Rename device', field: 'deviceId', core: true }, + { text: 'to', field: 'name' }, + ], + get_device_attributes: [ + { text: 'Read posture attributes for device', field: 'deviceId', core: true }, + ], + set_device_attribute: [ + { text: 'Set posture attribute', field: 'attributeKey', core: true }, + { text: 'on device', field: 'deviceId', core: true }, + { text: 'to', field: 'attributeValue' }, + ], + delete_device_attribute: [ + { text: 'Delete posture attribute', field: 'attributeKey', core: true }, + { text: 'from device', field: 'deviceId', core: true }, + ], + get_user: [{ text: 'Read tailnet user', field: 'userId', core: true }], + approve_user: [{ text: 'Approve tailnet access for user', field: 'userId', core: true }], + restore_user: [{ text: 'Restore tailnet access for user', field: 'userId', core: true }], + set_user_role: [ + { text: 'Set role for user', field: 'userId', core: true }, + { text: 'to', field: 'role', core: true }, + ], + get_split_dns: ['Read split DNS resolvers'], + set_split_dns: ['Replace all split DNS resolvers'], + update_split_dns: ['Update selected split DNS resolvers'], + get_dns_configuration: ['Read the full tailnet DNS configuration'], + set_dns_configuration: ['Replace the full tailnet DNS configuration'], + get_tailnet_settings: ['Read tailnet settings'], + update_tailnet_settings: ['Update selected tailnet settings'], + validate_acl: ['Validate a policy file or run ACL tests'], get_acl: ['Read the tailnet ACL policy'], set_acl: [ 'Replace the tailnet ACL policy', @@ -94,6 +132,7 @@ export const TailscaleBlock: BlockConfig = { options: [ { label: 'List Devices', id: 'list_devices' }, { label: 'Get Device', id: 'get_device' }, + { label: 'Set Device Name', id: 'set_device_name' }, { label: 'Delete Device', id: 'delete_device' }, { label: 'Authorize Device', id: 'authorize_device' }, { label: 'Set Device Tags', id: 'set_device_tags' }, @@ -101,37 +140,80 @@ export const TailscaleBlock: BlockConfig = { { label: 'Set Device Routes', id: 'set_device_routes' }, { label: 'Update Device Key', id: 'update_device_key' }, { label: 'Expire Device Key', id: 'expire_device_key' }, + { label: 'Get Device Attributes', id: 'get_device_attributes' }, + { label: 'Set Device Attribute', id: 'set_device_attribute' }, + { label: 'Delete Device Attribute', id: 'delete_device_attribute' }, { label: 'List DNS Nameservers', id: 'list_dns_nameservers' }, { label: 'Set DNS Nameservers', id: 'set_dns_nameservers' }, { label: 'Get DNS Preferences', id: 'get_dns_preferences' }, { label: 'Set DNS Preferences', id: 'set_dns_preferences' }, { label: 'Get DNS Search Paths', id: 'get_dns_searchpaths' }, { label: 'Set DNS Search Paths', id: 'set_dns_searchpaths' }, + { label: 'Get Split DNS', id: 'get_split_dns' }, + { label: 'Update Split DNS', id: 'update_split_dns' }, + { label: 'Set Split DNS', id: 'set_split_dns' }, + { label: 'Get DNS Configuration', id: 'get_dns_configuration' }, + { label: 'Set DNS Configuration', id: 'set_dns_configuration' }, { label: 'List Users', id: 'list_users' }, + { label: 'Get User', id: 'get_user' }, + { label: 'Set User Role', id: 'set_user_role' }, + { label: 'Approve User', id: 'approve_user' }, { label: 'Suspend User', id: 'suspend_user' }, + { label: 'Restore User', id: 'restore_user' }, { label: 'Delete User', id: 'delete_user' }, { label: 'Create Auth Key', id: 'create_auth_key' }, - { label: 'List Auth Keys', id: 'list_auth_keys' }, + { label: 'List Keys', id: 'list_auth_keys' }, { label: 'Get Auth Key', id: 'get_auth_key' }, { label: 'Delete Auth Key', id: 'delete_auth_key' }, { label: 'Get ACL', id: 'get_acl' }, + { label: 'Validate ACL', id: 'validate_acl' }, { label: 'Set ACL', id: 'set_acl' }, + { label: 'Get Tailnet Settings', id: 'get_tailnet_settings' }, + { label: 'Update Tailnet Settings', id: 'update_tailnet_settings' }, ], value: () => 'list_devices', }, { id: 'apiKey', - title: 'API Key', + title: 'API Access Token', type: 'short-input', password: true, - placeholder: 'tskey-api-...', + placeholder: 'Enter a Tailscale API or OAuth access token', required: true, }, { id: 'tailnet', title: 'Tailnet', type: 'short-input', - placeholder: 'example.com or "-" for default', + placeholder: 'Tailnet ID or - for the token’s default tailnet', + value: () => '-', + condition: { + field: 'operation', + value: [ + 'create_auth_key', + 'delete_auth_key', + 'get_acl', + 'get_auth_key', + 'get_dns_configuration', + 'get_dns_preferences', + 'get_dns_searchpaths', + 'get_split_dns', + 'get_tailnet_settings', + 'list_auth_keys', + 'list_devices', + 'list_dns_nameservers', + 'list_users', + 'set_acl', + 'set_dns_configuration', + 'set_dns_nameservers', + 'set_dns_preferences', + 'set_dns_searchpaths', + 'set_split_dns', + 'update_split_dns', + 'update_tailnet_settings', + 'validate_acl', + ], + }, required: true, }, { @@ -143,6 +225,10 @@ export const TailscaleBlock: BlockConfig = { field: 'operation', value: [ 'get_device', + 'delete_device_attribute', + 'set_device_attribute', + 'get_device_attributes', + 'set_device_name', 'delete_device', 'authorize_device', 'set_device_tags', @@ -156,6 +242,10 @@ export const TailscaleBlock: BlockConfig = { field: 'operation', value: [ 'get_device', + 'delete_device_attribute', + 'set_device_attribute', + 'get_device_attributes', + 'set_device_name', 'delete_device', 'authorize_device', 'set_device_tags', @@ -168,87 +258,82 @@ export const TailscaleBlock: BlockConfig = { }, { id: 'authorized', + required: true, title: 'Authorized', - type: 'dropdown', - options: [ - { label: 'Authorize', id: 'true' }, - { label: 'Deauthorize', id: 'false' }, - ], - value: () => 'true', + type: 'switch', + value: () => String(SWITCH_DEFAULTS.authorize_device.authorized), condition: { field: 'operation', value: 'authorize_device' }, }, { id: 'keyExpiryDisabled', + required: true, title: 'Key Expiry Disabled', - type: 'dropdown', - options: [ - { label: 'Disable Expiry', id: 'true' }, - { label: 'Enable Expiry', id: 'false' }, - ], - value: () => 'true', + type: 'switch', + value: () => String(SWITCH_DEFAULTS.update_device_key.keyExpiryDisabled), condition: { field: 'operation', value: 'update_device_key' }, }, { id: 'tags', title: 'Tags', type: 'short-input', - placeholder: 'tag:server,tag:production', + placeholder: 'tag:server,tag:production or [] to clear', condition: { field: 'operation', value: ['set_device_tags', 'create_auth_key'] }, required: { field: 'operation', value: 'set_device_tags' }, wandConfig: { enabled: true, prompt: - 'Generate a comma-separated list of Tailscale ACL tags. Each tag must start with "tag:" (e.g., tag:server,tag:production). Return ONLY the comma-separated tags - no explanations, no extra text.', + 'Generate a comma-separated list of Tailscale ACL tags. Each tag must start with "tag:" (e.g., tag:server,tag:production). Return ONLY the comma-separated tags.', + placeholder: 'Describe the tags you need', }, }, { id: 'routes', title: 'Routes', type: 'short-input', - placeholder: '10.0.0.0/24,192.168.1.0/24', + placeholder: '10.0.0.0/24,192.168.1.0/24 or [] to clear', condition: { field: 'operation', value: 'set_device_routes' }, required: { field: 'operation', value: 'set_device_routes' }, wandConfig: { enabled: true, prompt: - 'Generate a comma-separated list of subnet routes in CIDR notation (e.g., 10.0.0.0/24,192.168.1.0/24). Return ONLY the comma-separated routes - no explanations, no extra text.', + 'Generate a comma-separated list of subnet routes in CIDR notation (e.g., 10.0.0.0/24,192.168.1.0/24). Return ONLY the comma-separated routes.', + placeholder: 'Describe the routes you need', }, }, { id: 'dnsServers', title: 'DNS Nameservers', type: 'short-input', - placeholder: '8.8.8.8,8.8.4.4', + placeholder: '8.8.8.8,8.8.4.4 or [] to clear', condition: { field: 'operation', value: 'set_dns_nameservers' }, required: { field: 'operation', value: 'set_dns_nameservers' }, wandConfig: { enabled: true, prompt: - 'Generate a comma-separated list of DNS nameserver IP addresses (e.g., 8.8.8.8,8.8.4.4). Return ONLY the comma-separated IP addresses - no explanations, no extra text.', + 'Generate a comma-separated list of DNS nameserver IP addresses (e.g., 8.8.8.8,8.8.4.4). Return ONLY the comma-separated IP addresses.', + placeholder: 'Describe the IP addresses you need', }, }, { id: 'magicDNS', + required: true, title: 'MagicDNS', - type: 'dropdown', - options: [ - { label: 'Enable', id: 'true' }, - { label: 'Disable', id: 'false' }, - ], - value: () => 'true', + type: 'switch', + value: () => String(SWITCH_DEFAULTS.set_dns_preferences.magicDNS), condition: { field: 'operation', value: 'set_dns_preferences' }, }, { id: 'searchPaths', title: 'Search Paths', type: 'short-input', - placeholder: 'corp.example.com,internal.example.com', + placeholder: 'corp.example.com,internal.example.com or [] to clear', condition: { field: 'operation', value: 'set_dns_searchpaths' }, required: { field: 'operation', value: 'set_dns_searchpaths' }, wandConfig: { enabled: true, prompt: - 'Generate a comma-separated list of DNS search path domains (e.g., corp.example.com,internal.example.com). Return ONLY the comma-separated domains - no explanations, no extra text.', + 'Generate a comma-separated list of DNS search path domains (e.g., corp.example.com,internal.example.com). Return ONLY the comma-separated domains.', + placeholder: 'Describe the domains you need', }, }, { @@ -262,36 +347,24 @@ export const TailscaleBlock: BlockConfig = { { id: 'reusable', title: 'Reusable', - type: 'dropdown', - options: [ - { label: 'No', id: 'false' }, - { label: 'Yes', id: 'true' }, - ], - value: () => 'false', + type: 'switch', + value: () => String(SWITCH_DEFAULTS.create_auth_key.reusable), condition: { field: 'operation', value: 'create_auth_key' }, mode: 'advanced', }, { id: 'ephemeral', title: 'Ephemeral', - type: 'dropdown', - options: [ - { label: 'No', id: 'false' }, - { label: 'Yes', id: 'true' }, - ], - value: () => 'false', + type: 'switch', + value: () => String(SWITCH_DEFAULTS.create_auth_key.ephemeral), condition: { field: 'operation', value: 'create_auth_key' }, mode: 'advanced', }, { id: 'preauthorized', title: 'Preauthorized', - type: 'dropdown', - options: [ - { label: 'Yes', id: 'true' }, - { label: 'No', id: 'false' }, - ], - value: () => 'true', + type: 'switch', + value: () => String(SWITCH_DEFAULTS.create_auth_key.preauthorized), condition: { field: 'operation', value: 'create_auth_key' }, mode: 'advanced', }, @@ -316,16 +389,37 @@ export const TailscaleBlock: BlockConfig = { title: 'User ID', type: 'short-input', placeholder: 'Enter user ID', - condition: { field: 'operation', value: ['suspend_user', 'delete_user'] }, - required: { field: 'operation', value: ['suspend_user', 'delete_user'] }, + condition: { + field: 'operation', + value: [ + 'get_user', + 'approve_user', + 'suspend_user', + 'restore_user', + 'delete_user', + 'set_user_role', + ], + }, + required: { + field: 'operation', + value: [ + 'get_user', + 'approve_user', + 'suspend_user', + 'restore_user', + 'delete_user', + 'set_user_role', + ], + }, }, { id: 'acl', title: 'ACL Policy', type: 'long-input', - placeholder: '{"acls": [{"action": "accept", "users": ["*"], "ports": ["*:*"]}]}', - condition: { field: 'operation', value: 'set_acl' }, - required: { field: 'operation', value: 'set_acl' }, + placeholder: + '{"acls": [{"action": "accept", "src": ["tag:server"], "dst": ["tag:database:5432"]}]}', + condition: { field: 'operation', value: ['set_acl', 'validate_acl'] }, + required: { field: 'operation', value: ['set_acl', 'validate_acl'] }, }, { id: 'ifMatch', @@ -335,12 +429,284 @@ export const TailscaleBlock: BlockConfig = { condition: { field: 'operation', value: 'set_acl' }, mode: 'advanced', }, + { + id: 'details', + title: 'Policy Diagnostics', + type: 'switch', + value: () => String(SWITCH_DEFAULTS.get_acl.details), + condition: { field: 'operation', value: 'get_acl' }, + mode: 'advanced', + }, + { + id: 'roleFilter', + title: 'Filter by Role', + type: 'dropdown', + options: [ + { + label: 'Any Role', + id: '', + }, + { + label: 'Owner', + id: 'owner', + }, + { + label: 'Member', + id: 'member', + }, + { + label: 'Admin', + id: 'admin', + }, + { + label: 'It Admin', + id: 'it-admin', + }, + { + label: 'Network Admin', + id: 'network-admin', + }, + { + label: 'Billing Admin', + id: 'billing-admin', + }, + { + label: 'Auditor', + id: 'auditor', + }, + ], + condition: { + field: 'operation', + value: 'list_users', + }, + mode: 'advanced', + }, + { + id: 'fields', + title: 'Device Fields', + type: 'dropdown', + options: [ + { + label: 'Default', + id: 'default', + }, + { + label: 'All', + id: 'all', + }, + ], + condition: { + field: 'operation', + value: ['list_devices', 'get_device'], + }, + mode: 'advanced', + value: () => 'default', + }, + { + id: 'filters', + title: 'Device Filters', + type: 'long-input', + placeholder: 'isEphemeral=true&tags=tag:server', + condition: { + field: 'operation', + value: 'list_devices', + }, + mode: 'advanced', + wandConfig: { + enabled: true, + placeholder: 'Describe the devices to include', + prompt: + 'Generate URL query filters for top-level Tailscale device properties, for example isEphemeral=true&tags=tag:server. Repeat a parameter to require multiple tag values. Return ONLY the URL query string.', + }, + }, + { + id: 'all', + title: 'Include All Tailnet Keys', + type: 'switch', + condition: { + field: 'operation', + value: 'list_auth_keys', + }, + mode: 'advanced', + value: () => String(SWITCH_DEFAULTS.list_auth_keys.all), + }, + { + id: 'userType', + title: 'User Type', + type: 'dropdown', + options: [ + { + label: 'Member', + id: 'member', + }, + { + label: 'Shared', + id: 'shared', + }, + { + label: 'All', + id: 'all', + }, + ], + condition: { + field: 'operation', + value: 'list_users', + }, + mode: 'advanced', + value: () => 'member', + }, + { + id: 'role', + title: 'User Role', + type: 'dropdown', + options: [ + { + label: 'Owner', + id: 'owner', + }, + { + label: 'Member', + id: 'member', + }, + { + label: 'Admin', + id: 'admin', + }, + { + label: 'It Admin', + id: 'it-admin', + }, + { + label: 'Network Admin', + id: 'network-admin', + }, + { + label: 'Billing Admin', + id: 'billing-admin', + }, + { + label: 'Auditor', + id: 'auditor', + }, + ], + condition: { + field: 'operation', + value: 'set_user_role', + }, + required: { + field: 'operation', + value: 'set_user_role', + }, + }, + { + id: 'name', + title: 'Device Name', + type: 'short-input', + placeholder: 'New name; leave empty to reset to the OS hostname', + condition: { + field: 'operation', + value: 'set_device_name', + }, + }, + { + id: 'attributeKey', + title: 'Attribute Key', + type: 'short-input', + placeholder: 'custom:diskEncryption', + condition: { + field: 'operation', + value: ['set_device_attribute', 'delete_device_attribute'], + }, + required: true, + }, + { + id: 'attributeValue', + title: 'Attribute Value (JSON)', + type: 'short-input', + placeholder: 'true, 100, or "encrypted"', + condition: { + field: 'operation', + value: 'set_device_attribute', + }, + required: true, + }, + { + id: 'expiry', + title: 'Attribute Expiry', + type: 'short-input', + placeholder: '2026-12-01T00:00:00Z; no expiry by default', + condition: { + field: 'operation', + value: 'set_device_attribute', + }, + mode: 'advanced', + wandConfig: { + enabled: true, + generationType: 'timestamp', + placeholder: 'When should the attribute expire?', + prompt: + 'Generate the expiry time for a Tailscale posture attribute. Return ONLY the RFC 3339 timestamp.', + }, + }, + { + id: 'comment', + title: 'Audit Comment', + type: 'short-input', + placeholder: 'Reason for setting this attribute (optional)', + condition: { + field: 'operation', + value: 'set_device_attribute', + }, + mode: 'advanced', + }, + { + id: 'splitDns', + title: 'Split DNS (JSON)', + type: 'long-input', + placeholder: '{"corp.example.com": ["10.0.0.53"]}', + condition: { + field: 'operation', + value: ['set_split_dns', 'update_split_dns'], + }, + required: true, + wandConfig: { + enabled: true, + generationType: 'json-object', + placeholder: 'Describe the domains and DNS resolvers', + prompt: + 'Generate a Tailscale split DNS map of domain names to arrays of nameserver IP addresses. Use null to delete a domain in an update. Return ONLY the JSON object.', + }, + }, + { + id: 'dnsConfiguration', + title: 'DNS Configuration (JSON)', + type: 'long-input', + placeholder: + '{"nameservers": [{"address": "1.1.1.1", "useWithExitNode": true}], "splitDNS": {}, "searchPaths": [], "preferences": {"magicDNS": true, "overrideLocalDNS": true}}', + condition: { + field: 'operation', + value: 'set_dns_configuration', + }, + required: true, + }, + { + id: 'settings', + title: 'Tailnet Settings (JSON)', + type: 'long-input', + placeholder: '{"devicesApprovalOn": true, "devicesKeyDurationDays": 90}', + condition: { + field: 'operation', + value: 'update_tailnet_settings', + }, + required: true, + }, ], tools: { access: [ 'tailscale_list_devices', 'tailscale_get_device', + 'tailscale_set_device_name', 'tailscale_delete_device', 'tailscale_authorize_device', 'tailscale_set_device_tags', @@ -348,56 +714,95 @@ export const TailscaleBlock: BlockConfig = { 'tailscale_set_device_routes', 'tailscale_update_device_key', 'tailscale_expire_device_key', + 'tailscale_get_device_attributes', + 'tailscale_set_device_attribute', + 'tailscale_delete_device_attribute', 'tailscale_list_dns_nameservers', 'tailscale_set_dns_nameservers', 'tailscale_get_dns_preferences', 'tailscale_set_dns_preferences', 'tailscale_get_dns_searchpaths', 'tailscale_set_dns_searchpaths', + 'tailscale_get_split_dns', + 'tailscale_update_split_dns', + 'tailscale_set_split_dns', + 'tailscale_get_dns_configuration', + 'tailscale_set_dns_configuration', 'tailscale_list_users', + 'tailscale_get_user', + 'tailscale_set_user_role', + 'tailscale_approve_user', 'tailscale_suspend_user', + 'tailscale_restore_user', 'tailscale_delete_user', 'tailscale_create_auth_key', 'tailscale_list_auth_keys', 'tailscale_get_auth_key', 'tailscale_delete_auth_key', 'tailscale_get_acl', + 'tailscale_validate_acl', 'tailscale_set_acl', + 'tailscale_get_tailnet_settings', + 'tailscale_update_tailnet_settings', ], config: { tool: (params) => `tailscale_${params.operation}`, params: (params) => { const mapped: Record = { - apiKey: params.apiKey, - tailnet: params.tailnet, + ...params, + dns: params.dnsServers, + description: params.authKeyDescription, + name: params.name ?? '', + role: params.operation === 'list_users' ? params.roleFilter || undefined : params.role, + } + const defaults = + Object.entries(SWITCH_DEFAULTS).find( + ([operation]) => operation === params.operation + )?.[1] ?? {} + for (const [field, defaultValue] of Object.entries(defaults)) { + const value = params[field] + if (value == null || value === '') { + mapped[field] = defaultValue + } else if (typeof value === 'boolean') { + mapped[field] = value + } else if (value === 'true' || value === 'false') { + mapped[field] = value === 'true' + } else { + throw new Error(`${field} must be true or false`) + } + } + if ( + params.operation === 'create_auth_key' && + params.expirySeconds != null && + params.expirySeconds !== '' + ) { + const expirySeconds = Number(params.expirySeconds) + if (!Number.isFinite(expirySeconds)) throw new Error('Expiry must be a finite number') + mapped.expirySeconds = expirySeconds } - if (params.deviceId) mapped.deviceId = params.deviceId - if (params.keyId) mapped.keyId = params.keyId - if (params.userId) mapped.userId = params.userId - if (params.tags) mapped.tags = params.tags - if (params.routes) mapped.routes = params.routes - if (params.dnsServers) mapped.dns = params.dnsServers - if (params.searchPaths) mapped.searchPaths = params.searchPaths - if (params.acl) mapped.acl = params.acl - if (params.ifMatch) mapped.ifMatch = params.ifMatch - if (params.authorized !== undefined) mapped.authorized = params.authorized === 'true' - if (params.keyExpiryDisabled !== undefined) - mapped.keyExpiryDisabled = params.keyExpiryDisabled === 'true' - if (params.magicDNS !== undefined) mapped.magicDNS = params.magicDNS === 'true' - if (params.authKeyDescription) mapped.description = params.authKeyDescription - if (params.reusable !== undefined) mapped.reusable = params.reusable === 'true' - if (params.ephemeral !== undefined) mapped.ephemeral = params.ephemeral === 'true' - if (params.preauthorized !== undefined) - mapped.preauthorized = params.preauthorized === 'true' - if (params.expirySeconds) mapped.expirySeconds = Number(params.expirySeconds) return mapped }, }, }, inputs: { - apiKey: { type: 'string', description: 'Tailscale API key' }, - tailnet: { type: 'string', description: 'Tailnet name' }, + roleFilter: { type: 'string', description: 'Filter the user list by role' }, + details: { type: 'boolean', description: 'Include HuJSON policy warnings and errors' }, + settings: { type: 'string', description: 'Tailnet Settings (JSON)' }, + dnsConfiguration: { type: 'string', description: 'DNS Configuration (JSON)' }, + splitDns: { type: 'string', description: 'Split DNS (JSON)' }, + comment: { type: 'string', description: 'Audit Comment' }, + expiry: { type: 'string', description: 'Attribute Expiry' }, + attributeValue: { type: 'string', description: 'Attribute Value (JSON)' }, + attributeKey: { type: 'string', description: 'Attribute Key' }, + name: { type: 'string', description: 'Device Name' }, + role: { type: 'string', description: 'User Role' }, + userType: { type: 'string', description: 'User Type' }, + all: { type: 'boolean', description: 'Include All Tailnet Keys' }, + filters: { type: 'string', description: 'Device Filters' }, + fields: { type: 'string', description: 'Device Fields' }, + apiKey: { type: 'string', description: 'Tailscale API access token or OAuth access token' }, + tailnet: { type: 'string', description: 'Tailnet ID, legacy name, or - for default' }, deviceId: { type: 'string', description: 'Device ID' }, keyId: { type: 'string', description: 'Auth key ID' }, userId: { type: 'string', description: 'User ID' }, @@ -418,7 +823,74 @@ export const TailscaleBlock: BlockConfig = { }, outputs: { - devices: { type: 'json', description: 'List of devices in the tailnet' }, + warnings: { type: 'json', description: 'Policy warning strings from detailed Get ACL' }, + errors: { type: 'json', description: 'Policy parsing error strings from detailed Get ACL' }, + connectedToControl: { type: 'boolean', description: 'connectedToControl' }, + multipleConnections: { type: 'boolean', description: 'multipleConnections' }, + clientConnectivity: { + type: 'json', + description: + 'Device connectivity (endpoints, mappingVariesByDestIP, latency, clientSupports)', + }, + tailnetLockError: { type: 'string', description: 'tailnetLockError' }, + tailnetLockKey: { type: 'string', description: 'tailnetLockKey' }, + sshEnabled: { type: 'boolean', description: 'sshEnabled' }, + postureIdentity: { type: 'json', description: 'Posture identity (serialNumbers, disabled)' }, + postureStatus: { + type: 'json', + description: 'Posture status (passing, impacting, failingAssertions)', + }, + isEphemeral: { type: 'boolean', description: 'isEphemeral' }, + distro: { type: 'json', description: 'OS distribution (name, version, codeName)' }, + keyType: { type: 'string', description: 'keyType' }, + expirySeconds: { type: 'number', description: 'expirySeconds' }, + updated: { type: 'string', description: 'updated' }, + scopes: { type: 'json', description: 'scopes' }, + invalid: { type: 'boolean', description: 'invalid' }, + audience: { type: 'string', description: 'audience' }, + issuer: { type: 'string', description: 'issuer' }, + subject: { type: 'string', description: 'subject' }, + customClaimRules: { type: 'json', description: 'customClaimRules' }, + tailnetId: { type: 'string', description: 'Tailnet ID for a user' }, + displayName: { type: 'string', description: 'User display name' }, + loginName: { type: 'string', description: 'User login name' }, + profilePicURL: { type: 'string', description: 'User profile picture URL' }, + role: { type: 'string', description: 'User role' }, + status: { type: 'string', description: 'User status' }, + type: { type: 'string', description: 'User relationship to the tailnet' }, + deviceCount: { type: 'number', description: 'Number of devices owned by a user' }, + currentlyConnected: { + type: 'boolean', + description: 'Whether a user has a device connected to the control server', + }, + attributeKey: { type: 'string', description: 'Deleted custom posture attribute key' }, + attributes: { + type: 'json', + description: 'Map of posture attribute names to string, number, or boolean values', + }, + expiries: { type: 'json', description: 'Map of posture attribute names to expiry timestamps' }, + splitDns: { type: 'json', description: 'Map of domain names to DNS resolver arrays or null' }, + valid: { + type: 'boolean', + description: 'Whether ACL validation and tests passed without warnings', + }, + message: { type: 'string', description: 'ACL validation summary' }, + results: { type: 'json', description: 'ACL test diagnostics [{user, errors, warnings}]' }, + settings: { + type: 'json', + description: + 'Tailnet settings (device and user approval, key expiry, updates, policy management, logging, routing, HTTPS)', + }, + dnsConfiguration: { + type: 'json', + description: 'Full DNS configuration (nameservers, splitDNS, searchPaths, preferences)', + }, + + devices: { + type: 'json', + description: + 'Devices [{id, nodeId, hostname, user, os, tags, authorized, lastSeen, connectedToControl, updateAvailable}]', + }, count: { type: 'number', description: 'Total count of items returned' }, id: { type: 'string', description: 'Device or auth key ID' }, nodeId: { type: 'string', description: 'Preferred device ID' }, @@ -448,15 +920,26 @@ export const TailscaleBlock: BlockConfig = { dns: { type: 'json', description: 'DNS nameserver addresses' }, magicDNS: { type: 'boolean', description: 'Whether MagicDNS is enabled' }, searchPaths: { type: 'json', description: 'DNS search paths' }, - users: { type: 'json', description: 'List of users in the tailnet' }, - keys: { type: 'json', description: 'List of auth keys' }, + users: { + type: 'json', + description: + 'Users [{id, displayName, loginName, role, status, type, tailnetId, deviceCount, currentlyConnected}]', + }, + keys: { + type: 'json', + description: + 'Active keys [{id, keyType, userId, description, created, expires, scopes, tags, capabilities}]', + }, key: { type: 'string', description: 'Auth key value (only at creation)' }, keyId: { type: 'string', description: 'Auth key ID' }, description: { type: 'string', description: 'Auth key description' }, expires: { type: 'string', description: 'Device key or auth key expiration timestamp' }, revoked: { type: 'string', description: 'Revocation timestamp' }, - capabilities: { type: 'json', description: 'Auth key capabilities' }, - acl: { type: 'string', description: 'ACL policy as JSON string' }, + capabilities: { + type: 'json', + description: 'Device enrollment capabilities (reusable, ephemeral, preauthorized, tags)', + }, + acl: { type: 'string', description: 'Policy as JSON or original HuJSON for detailed Get ACL' }, etag: { type: 'string', description: 'ACL ETag for conditional updates' }, userId: { type: 'string', description: 'User ID' }, }, @@ -479,7 +962,7 @@ export const TailscaleBlockMeta = { icon: TailscaleIcon, title: 'Tailscale ACL drift detector', prompt: - 'Create a scheduled workflow that diffs Tailscale ACLs against the source of truth, alerts on drift to Slack, and, on approval, pushes the corrected policy back with Set ACL.', + 'Create a scheduled workflow that diffs Tailscale ACLs against the source of truth, validates the proposed policy with Validate ACL, alerts on drift to Slack, and, on approval, pushes the corrected policy back with Set ACL.', modules: ['scheduled', 'agent', 'workflows'], category: 'engineering', tags: ['devops', 'monitoring'], @@ -536,6 +1019,20 @@ export const TailscaleBlockMeta = { }, ], skills: [ + { + name: 'synchronize-device-posture', + description: + 'Publish custom device posture signals with an expiry so access rules can use current compliance data.', + content: + '# Synchronize Device Posture\n\n1. Find the device nodeId with List Devices.\n2. Use Get Device Attributes to inspect the current signals.\n3. Use Set Device Attribute with a custom: key and a JSON scalar value from your compliance source. Set Attribute Expiry so stale signals disappear automatically, and add an audit comment.\n4. Read the attributes again to verify the value and expiry; use Delete Device Attribute to remove a signal.\n\nReturn the device ID, attribute value, and expiry.', + }, + { + name: 'manage-private-dns-routes', + description: + 'Maintain split DNS resolvers for private domains without replacing unrelated DNS routes.', + content: + '# Manage Private DNS Routes\n\n1. Use Get Split DNS to read the current domain-to-resolver map.\n2. Use Update Split DNS with only the domains being changed. Supply null for a domain to remove it.\n3. Use Get DNS Configuration when resolver behavior with exit nodes or overrideLocalDNS matters.\n4. Read the configuration again and report the affected domains and resolvers.\n\nUse Set Split DNS or Set DNS Configuration only when replacing the full corresponding configuration is intended.', + }, { name: 'audit-tailnet-devices', description: @@ -555,14 +1052,14 @@ export const TailscaleBlockMeta = { description: "Deauthorize or remove a departing user's devices and auth keys, then suspend or delete their tailnet account.", content: - '# Offboard a Tailscale Device\n\nRemove a device from the tailnet during offboarding so access is cut cleanly.\n\n## Steps\n1. Use List Devices to find the deviceId tied to the departing user.\n2. To immediately cut access use Authorize Device set to Deauthorize, or Delete Device to remove it entirely.\n3. Use List Auth Keys to find any keys the user created, then Delete Auth Key for each.\n4. Use List Users to find the userId, then Suspend User to freeze access reversibly, or Delete User to remove the account entirely.\n5. Capture the device detail with Get Device before deletion if you need an audit record.\n\n## Output\nConfirm the device was deauthorized or deleted, the auth keys were revoked, and the user account was suspended or deleted for the offboarding audit log.', + '# Offboard a Tailscale Device\n\nRemove a device from the tailnet during offboarding so access is cut cleanly.\n\n## Steps\n1. Use List Devices to find the deviceId tied to the departing user.\n2. To immediately cut access use Authorize Device set to Deauthorize, or Delete Device to remove it entirely.\n3. Use List Keys and filter for keyType auth and the departing userId before revoking any enrollment keys with Delete Auth Key.\n4. Use List Users to find the userId, then Suspend User to freeze access reversibly, or Delete User to remove the account entirely.\n5. Capture the device detail with Get Device before deletion if you need an audit record.\n\n## Output\nConfirm the device was deauthorized or deleted, the auth keys were revoked, and the user account was suspended or deleted for the offboarding audit log.', }, { name: 'update-tailnet-acl', description: 'Push an updated ACL policy file to the tailnet using ETag-guarded writes to avoid clobbering concurrent edits.', content: - '# Update the Tailnet ACL as Policy-as-Code\n\nApply a reviewed ACL change programmatically instead of editing it by hand in the admin console.\n\n## Steps\n1. Use Get ACL to fetch the current policy file and its etag.\n2. Compute or generate the new policy JSON from your source of truth (git, agent-authored rules, etc.).\n3. Use Set ACL with the new ACL Policy JSON, passing the etag from step 1 in If-Match to guard against concurrent updates (use "ts-default" instead if you only want to replace an untouched default policy).\n4. If the write fails with a precondition error, re-fetch the ACL and retry.\n\n## Output\nReturn the updated ACL JSON and its new etag, plus a summary of what changed for the change-management record.', + '# Update the Tailnet ACL as Policy-as-Code\n\nApply a reviewed ACL change programmatically instead of editing it by hand in the admin console.\n\n## Steps\n1. Use Get ACL to fetch the current policy file and its etag.\n2. Compute or generate the new policy JSON from your source of truth (git, agent-authored rules, etc.).\n3. Run Validate ACL with the proposed policy, then use Set ACL with the new ACL Policy JSON, passing the etag from step 1 in If-Match to guard against concurrent updates (use "ts-default" instead if you only want to replace an untouched default policy).\n4. If the write fails with a precondition error, re-fetch the ACL and retry.\n\n## Output\nReturn the updated ACL JSON and its new etag, plus a summary of what changed for the change-management record.', }, { name: 'lock-down-compromised-device', diff --git a/apps/sim/content/changelog/editorial-standard.md b/apps/sim/content/changelog/editorial-standard.md index 45fd4084f5b..2714010b592 100644 --- a/apps/sim/content/changelog/editorial-standard.md +++ b/apps/sim/content/changelog/editorial-standard.md @@ -8,6 +8,8 @@ A standalone update needs a meaningful capability, a substantial improvement to Choose by product impact, not commit type, integration count, or ease of screenshotting. Consider Chat, Search, Files, Tables, collaboration, building and running agents, and account controls alongside integrations and models. Ask what a team can do differently, what recurring friction was removed, or what action it must take. Compare credible alternatives before choosing the lead; do not turn an implementation mechanism into a launch to create variety. Integrations can lead when their benefit is the strongest story, but operation counts alone are not a headline. +A new integration does not outrank an improvement to an existing capability merely because it is new. Completing a useful end-to-end task, such as moving prepared knowledge between workspaces, can matter more than adding another service. Explain the practical difference before listing controls or setup requirements. Give smaller changes proportionately less space. If no candidate meets the substantive-change bar, skip the edition; a schedule is a review opportunity, not a publishing quota. + A substantial product fix can join a related edition's short Improvements or Fixes section. Keep routine input validation, retry handling, cancellation cleanup, internal race fixes, refactors, and small polish in the technical release history; a clearer error alone is not an action-required notice. A batch of commits is not a story. Defer a batch with only supporting notes instead of padding it into a launch. An urgent breaking change needs a timely notice and a verified explanatory image when there is no useful product screen. Keep existing article URLs, original dates, and RSS identities when refining historical copy. Do not merge existing entries just to make a larger announcement. Preserve material version, permission, and rollout restrictions. diff --git a/apps/sim/content/changelog/knowledge-base-imports/index.mdx b/apps/sim/content/changelog/knowledge-base-imports/index.mdx new file mode 100644 index 00000000000..d4f101c76d4 --- /dev/null +++ b/apps/sim/content/changelog/knowledge-base-imports/index.mdx @@ -0,0 +1,33 @@ +--- +slug: knowledge-base-imports +title: 'Move knowledge bases between workspaces' +description: 'Move prepared knowledge between Sim workspaces or deployments, keeping documents, tags, and settings. Also: Amazon EC2 actions for agents and workflows.' +date: '2026-10-26T16:00:00Z' +authors: [waleed] +tags: [Knowledge Base, Workspace] +ogImage: /changelog/knowledge-open-rooms-v1.jpg +ogAlt: 'Monochrome illustration of an open stone walkway overlooking the coast' +technical: false +draft: false +release: + versions: [v0.9.32] +--- + + + +Move a knowledge base between Sim workspaces or deployments without rebuilding it document by document. Export a `.simkb.zip` archive, then import it through the Sim CLI or API to create a new base with its documents, tags, and settings. + +When the archive includes a search index compatible with the destination's embedding model and dimensions, Sim reuses it without embedding charges. Otherwise, Sim processes the documents again, with normal usage charges. + +The original base stays unchanged. Exports include only active, included documents readable by the whole workspace. Imported connector content is a snapshot; live connections and access permissions do not transfer. Your permissions must allow export in the source and knowledge-base creation and uploads in the destination. [Export and import guide](https://docs.sim.ai/knowledgebase/export-import). + +### Also in v0.9.32 + +- **[Amazon EC2](/integrations/amazon-ec2):** Agents and workflows can inspect and control instances, create disk snapshots, and manage resource tags using an AWS access key with the required permissions. [EC2 setup](https://docs.sim.ai/integrations/ec2). + +Read the full [v0.9.32 technical release notes](https://github.com/simstudioai/sim/releases/tag/v0.9.32). diff --git a/apps/sim/content/changelog/knowledge-base-imports/production.md b/apps/sim/content/changelog/knowledge-base-imports/production.md new file mode 100644 index 00000000000..bee9ed01be8 --- /dev/null +++ b/apps/sim/content/changelog/knowledge-base-imports/production.md @@ -0,0 +1,54 @@ +# Move knowledge bases between workspaces + +Edition: 2026-10-26. Canonical: https://www.sim.ai/changelog/knowledge-base-imports. + +## Editorial selection + +Lead with knowledge portability: a team can copy prepared knowledge to another workspace or deployment without rebuilding it document by document. Completing that task matters more than the novelty or operation count of another integration. Amazon EC2 is a concise supporting note from the same release. + +Reviewed the published v0.9.32 and v0.9.33 changes across knowledge, Chat, execution, account security, infrastructure, and integrations. Scheduled agent jobs have no creation API, command, or UI yet, so their runtime is not announced. Parser, log, retry, token-storage, and deployment internals stay in the technical history. Minor Chat conveniences do not carry a standalone announcement. + +Copy leads with the reader's outcome, gives the minimum useful behavior and constraints, and keeps a smaller change in a short note. No publication quota, operation inventory, speculative benefit, or filler. + +## Source and release evidence + +| Claim | Source | Release | +| --- | --- | --- | +| Import an archive as a new base, preserving documents, tags, configuration and enabled flags | [#9327](https://github.com/simstudioai/sim/pull/9327) | [v0.9.32](https://github.com/simstudioai/sim/releases/tag/v0.9.32) | +| Compatible included vectors avoid re-embedding; other documents follow normal processing and billing | #9327 | v0.9.32 | +| Connector connections, credentials and access grants are not transferred | #9327 and the export/import guide | v0.9.32 | +| Inspect/control EC2 instances, create snapshots and manage tags with AWS credentials and IAM permissions | [#9304](https://github.com/simstudioai/sim/pull/9304) | v0.9.32 | + +Release membership is explicit in the published release body. Both source commits are included in the successfully deployed production release. The new editorial entry uses its canonical URL as the feed identity. + +## Availability and boundaries + +- Verified the deployed [export/import guide](https://docs.sim.ai/knowledgebase/export-import), CLI command contract, and hosted authenticated import-status route. Import is available through the API and current CLI; no browser import control is claimed. +- Export includes eligible workspace-readable content. Creation/uploads permission is needed in the destination; permission grants and live connector configuration are not portable. +- Index reuse requires both the embedding model and dimensions to match. Otherwise normal processing and usage charges apply. Partial document failures are reported; the guide explains archive limits and cancellation. +- Verified the deployed EC2 catalog and [setup guide](https://docs.sim.ai/integrations/ec2). AWS permissions still govern operations. No AWS mutation or successful new cloud-account execution is claimed by this article. +- Source CI includes an export/import round trip against real storage and a database. This editorial task does not claim a new production import or run local test suites. + +## Media production + +Format: original generated editorial illustration. A curved stone walkway connects open rooms overlooking a coast, suggesting portability between workspaces. It is conceptual art, not a product screenshot or evidence of an import. + +Generation art direction: “Create one original wide 16:9 editorial illustration. Restrained grayscale matte painting, fine graphite and dry-brush paper texture, soft overcast light. A spacious modern stone colonnade on a coastal hillside: repeated simple rectangular doorways receding into the distance, one broad curved stone walkway returning around an open courtyard, distant pale hills and clouds through the openings. Human-scale understated architecture, negative space, readable at mobile width. No people, text, logos, icons, diagrams, UI, devices, borders or floating objects.” + +The original unused illustration was generated during earlier editorial exploration and is used here for its connecting-spaces concept. Final asset: `/changelog/knowledge-open-rooms-v1.jpg`, 1672 × 941, optimized from the original PNG. Generation provenance is retained privately. Existing shared image styling and viewer remain unchanged. + +## Publication review + +- [x] Source claims, release membership, access requirements and editorial selection reviewed. +- [x] Final media and copy reviewed in the actual desktop/mobile article. +- [x] Canonical/schema, discovery, previous feed identities and links verified. +- [ ] Repository checks and both current-head reviews complete. +- [ ] Normal staging deployment and hosted article verified. + +## Announcement drafts + +**Social:** Move prepared knowledge between Sim workspaces or deployments, keeping documents, tags, and settings. Import an exported archive through the CLI or API to create a new knowledge base. https://www.sim.ai/changelog/knowledge-base-imports + +**Email:** Your prepared knowledge can move with your team. Export a Sim knowledge base and import it into another workspace or deployment, preserving its documents, tags, and settings. Connections and permissions stay separate. This update also adds Amazon EC2 actions for agents and workflows. https://www.sim.ai/changelog/knowledge-base-imports + +Do not distribute before the production article is verified. Private operational evidence is kept outside this public brief. diff --git a/apps/sim/content/library/agentic-ai-coding-tools-what-they-are-and-how-the-top-options-compare/index.mdx b/apps/sim/content/library/agentic-ai-coding-tools-what-they-are-and-how-the-top-options-compare/index.mdx index b540558cf63..de34bc14dec 100644 --- a/apps/sim/content/library/agentic-ai-coding-tools-what-they-are-and-how-the-top-options-compare/index.mdx +++ b/apps/sim/content/library/agentic-ai-coding-tools-what-they-are-and-how-the-top-options-compare/index.mdx @@ -3,42 +3,42 @@ slug: agentic-ai-coding-tools-what-they-are-and-how-the-top-options-compare title: 'Best Agentic Coding Tools: IDEs & Platforms Compared' description: 'Compare the best agentic coding tools, IDEs, and platforms for planning, writing, debugging, and shipping code with autonomous AI agents.' date: 2026-08-01 -updated: 2026-10-25 +updated: 2026-10-26 authors: - andrew -readingTime: 39 +readingTime: 38 tags: [AI Agents, Coding Tools, Developer Tools, Sim] ogImage: /library/agentic-ai-coding-tools-what-they-are-and-how-the-top-options-compare/cover.jpg draft: false faq: - q: "What's the difference between agentic AI coding tools and regular AI code completion?" - a: "Regular AI code completion predicts code as a developer types, while an agentic coding tool plans and executes a sequence of actions. Sim complements agentic coding tools by coordinating code-related actions with external tools and data, so developers can use each category for the work it handles best without expecting a workflow platform to replace an IDE." + a: "Regular AI code completion predicts code as a developer types, while an agentic coding tool plans and executes a sequence of actions such as inspecting files, editing code, and running checks." - q: "Is Cursor an agentic AI coding tool?" - a: "Cursor is an agentic AI coding tool because its agent mode can work across a project instead of only suggesting inline completions. Sim can connect workflows and data to compatible coding agents while Cursor handles repository work, keeping code changes in the editor and surrounding processes separate." + a: "Yes. Cursor's agent mode can work across a project, editing files and running terminal commands, instead of only suggesting inline completions." - q: "Is GitHub Copilot agentic?" - a: "GitHub Copilot is agentic when its agent mode plans and carries out multi-step work in a supported IDE. Sim serves a different role by coordinating workflows across tools and data sources, which separates repository changes from the automation around them." + a: "GitHub Copilot is agentic when its agent mode plans and carries out multi-step work in a supported IDE, and GitHub also offers a cloud agent for delegated tasks." - q: "What is the cheapest agentic AI coding tool?" - a: "Several agentic tools offer free tiers, so no single product has the lowest entry price. Sim, Cursor, and GitHub Copilot provide free access with product-specific limits, so compare included usage, paid-plan prices, and overage charges against the expected workload." + a: "Several agentic tools offer free tiers, including Cursor, GitHub Copilot, and Amazon Q Developer, so no single product has the lowest entry price. Compare included usage, paid-plan prices, and overage charges against the expected workload." - q: "Can an agentic coding tool work inside a larger business workflow, not just an IDE?" - a: "An agentic coding tool can participate in a larger workflow when another system connects its output to external applications. Sim can coordinate those surrounding steps while the coding agent handles repository changes, keeping code editing in the development environment." + a: "Yes, when a workflow layer connects the coding agent's output to external applications, checks, and approvals. Sim can coordinate those surrounding steps while the coding agent handles repository changes." - q: "Does Sim replace Cursor or GitHub Copilot?" - a: "Sim is the open-source AI workspace, while Cursor and GitHub Copilot are coding tools built for repository work. Sim coordinates automated processes that can include code execution, external tools, and data without treating the products as interchangeable." + a: "No. Cursor and GitHub Copilot are coding tools built for repository work, while Sim is the open-source AI workspace that coordinates the processes around them, such as code execution steps, external tools, data, and approvals." - q: "What is the best agentic AI tool for automated code review?" a: "CodeRabbit is the best dedicated agentic AI tool for automated pull-request review, while GitHub Copilot is the strongest default for GitHub-native coding-agent workflows and Qodo Merge is a strong option for test-aware PR feedback." - q: "Which agentic AI tools generate unit tests?" a: "GitHub Copilot, Claude Code, OpenAI Codex, Cursor, Devin, and other repository-capable coding agents can generate unit tests, but teams should prefer tools that can execute the tests and show reproducible results." - q: "Which agentic coding platform should a dev team choose for production?" - a: "A production development team should choose GitHub Copilot for GitHub-native delegated coding, CodeRabbit for dedicated PR review, Claude Code for programmable terminal work, and Sim for governed orchestration across agents, CI, scanners, and approvals." + a: "Choose the tool that passes every mandatory security and operational gate and performs well on your own repositories. As starting points, GitHub Copilot fits GitHub-native delegated coding, CodeRabbit dedicated PR review, Claude Code programmable terminal work, and Sim governed orchestration across agents, CI, scanners, and approvals." - q: "What is agentic code review?" a: "Agentic code review is repository-aware analysis in which an AI coding agent examines a change, reasons across files, proposes or applies fixes, runs available tools, and revises its work from the results." - q: "How is agentic code review different from static analysis?" a: "Agentic code review uses probabilistic reasoning and repository context to investigate broad issues, while static analysis applies deterministic rules that are usually faster, repeatable, and easier to enforce." - q: "Can an AI coding agent replace human code review?" - a: "An AI coding agent cannot safely replace human code review for production changes because people must still validate intent, architecture, security implications, and residual risk." + a: "No. Generated changes can be plausible while still containing regressions, vulnerabilities, or incorrect assumptions, so people must still validate intent, architecture, security implications, and residual risk for production changes." - q: "Can AI coding agents run tests?" a: "Repository-capable AI coding agents can run tests when their execution environment and permissions expose the required commands, dependencies, services, and test data." - - q: "How do you evaluate an AI coding agent?" - a: "A development team should evaluate an AI coding agent on private repository tasks using correctness, review precision, test quality, diff size, reproducibility, security, and required human intervention." + - q: "How should engineering teams evaluate agentic coding tools for production use?" + a: "Apply mandatory security and operational gates first, then run every candidate on private repository tasks under identical conditions. Compare correctness, accepted changes, review effort, test quality, diff size, reproducibility, security findings, recovery, and total cost." - q: "What makes an AI-generated unit test reliable?" a: "An AI-generated unit test is most reliable when it fails against the original defect, passes after the fix, asserts observable behavior, covers meaningful edge cases, and remains understandable to a human reviewer." - q: "What are the main risks of AI code review?" @@ -58,21 +58,15 @@ faq: - q: "Can n8n automate AI code review?" a: "n8n can automate parts of an AI code-review process by connecting repository events, model calls, checks, and notifications, although teams must design their own permission and approval boundaries." - q: "What is the difference between an AI coding agent and an AI workflow agent?" - a: "An AI coding agent works directly on software-development tasks, while an AI workflow agent coordinates actions across applications, APIs, data, and approval steps." - - q: "What security permissions should an AI coding agent have?" - a: "An AI coding agent should receive the minimum repository, command, network, and secret access required for one task, with separate identity, short-lived credentials, protected branches, and auditable activity." + a: "An AI coding agent works directly on software repositories, while an AI workflow agent coordinates actions across models, APIs, data, approval steps, and business systems. A production team may connect the two without treating them as interchangeable." + - q: "What security controls should an agentic coding tool have?" + a: "An agentic coding tool should have the minimum repository, command, network, and secret access one task requires, with a separate identity, short-lived credentials, protected branches, administrative revocation, and auditable actions. The exact controls must match the sensitivity of the code and systems the tool can reach." - q: "Should AI-generated tests be trusted if they pass?" a: "AI-generated tests should not be trusted merely because they pass because a weak test can validate the implementation without proving the intended behavior or reproducing the original defect." - q: "What is the best way to automate code review and testing with multiple AI tools?" - a: "Sim fits teams that need to orchestrate multiple coding agents, CI systems, scanners, notifications, and human decisions in one governed workflow." - - q: "How should engineering teams evaluate agentic coding tools for production use?" - a: "Agentic coding tools should be evaluated with mandatory security and operational gates followed by repository-specific tests. Teams should compare accepted changes, correctness, review effort, security findings, recovery, and total cost under identical conditions." - - q: "What is the best agentic coding tool for production teams?" - a: "The best agentic coding tool for a production team is the tool that passes every mandatory gate and performs well on that team’s repositories and tasks. No universal ranking can replace evidence about code quality, access controls, review effort, recovery, and cost in the intended environment." + a: "Use a workflow layer that coordinates coding agents, CI systems, scanners, notifications, and human decisions in one governed process; Sim fits teams that need that orchestration." - q: "What makes an agentic coding tool production-ready?" a: "An agentic coding tool is production-ready when it consistently produces correct, reviewable changes within defined security, permission, audit, and rollback boundaries. Production readiness also requires stable evidence that the tool improves accepted output without creating excessive defects or reviewer burden." - - q: "What security controls should an agentic coding tool have?" - a: "An agentic coding tool should support least-privilege repository access, bounded command execution, protected secret handling, data controls, administrative revocation, auditable actions, and compatibility with required review policies. The exact controls must match the sensitivity of the code and systems the tool can reach." - q: "Should coding agents be allowed to run commands?" a: "Coding agents should be allowed to run commands only inside a constrained environment with limited credentials, network access, filesystem scope, and execution time. Consequential or destructive commands should require explicit approval or be blocked entirely." - q: "How do you benchmark agentic coding tools?" @@ -87,8 +81,6 @@ faq: a: "An agentic coding tool should be tested with malicious instructions placed in repository files, issues, documentation, logs, and dependency content. The test should confirm that untrusted text cannot cause unauthorized secret access, network calls, command execution, policy bypass, or out-of-scope changes." - q: "Are cloud coding agents safe for private source code?" a: "Cloud coding agents are appropriate for private source code only when their current first-party data terms, retention, model-training treatment, subprocessors, access controls, and deployment boundaries satisfy the organization’s requirements. Teams should not infer those protections from marketing language or from a different plan." - - q: "Do agentic coding tools replace code review?" - a: "Agentic coding tools do not replace code review because generated changes can be plausible while still containing regressions, vulnerabilities, or incorrect assumptions. Human review and independent automated checks remain necessary for consequential code changes." - q: "Do agentic coding tools replace continuous integration?" a: "Agentic coding tools do not replace continuous integration because their own claims about tests or correctness are not independent evidence. CI should run deterministic tests, security checks, and policy enforcement outside the agent’s control." - q: "Should engineering teams use one coding agent or multiple coding agents?" @@ -101,10 +93,6 @@ faq: a: "An agentic coding tool pilot should run long enough to cover representative task categories, repeated trials, different reviewers, and realistic failure cases. Calendar duration matters less than collecting enough comparable evidence to distinguish reliable performance from isolated success." - q: "How do you roll back changes made by a coding agent?" a: "Coding agent changes should be isolated in branches or pull requests so teams can inspect, reject, or revert them with standard version-control procedures. Any external side effects created during execution need separate logs and recovery steps because reverting a commit will not undo them." - - q: "Is an agentic coding tool the same as an AI workflow agent?" - a: "An agentic coding tool is not the same as an AI workflow agent because coding tools primarily work with software repositories, while workflow agents coordinate actions across models, APIs, data, and business systems. A production team may connect the two categories without treating them as interchangeable." - - q: "Can Sim replace an agentic coding tool?" - a: "Sim does not directly replace an agentic coding tool because Sim is designed for building, deploying, and managing AI agents that automate real work across connected systems rather than serving as a dedicated coding environment. Teams can use Sim alongside coding agents when a software task needs to participate in a broader operational workflow." - q: "What evidence should a vendor provide before an agentic coding tool is approved?" a: "An agentic coding tool vendor should provide current first-party documentation for data handling, retention, model training, subprocessors, security controls, deployment, authentication, administration, auditability, pricing, support, and licensing. The engineering team should combine that documentation with results from its own controlled pilot." - q: "What is the best agentic coding tool?" @@ -143,6 +131,18 @@ faq: a: "Best AI Coding Agents for Refactoring and Debugging: 5 Tools Compared compares tools specifically for maintaining, repairing, and restructuring existing code." - q: "Which guide explains how to benchmark AI coding agents reproducibly?" a: "AI coding-agent benchmark: a reproducible test of debugging, test generation, and refactoring explains a controlled evaluation method for task-level results." + - q: "How do you evaluate whether an AI coding agent is accurate?" + a: "AI coding-agent accuracy should be evaluated with executable acceptance tests, regression checks, static analysis, and human review rather than the agent’s own completion claim." + - q: "Should AI-generated code require human review?" + a: "AI-generated code should require human review whenever it can affect production behavior, security, customer data, infrastructure, financial transactions, or compliance obligations." + - q: "Is Claude Code an agentic AI coding tool?" + a: "Claude Code is an agentic AI coding tool designed for terminal-based repository work using local development commands under user-defined permissions." + - q: "Is Devin an agentic AI coding tool?" + a: "Devin is an agentic AI coding tool designed to perform bounded software-engineering tasks in a hosted environment and return work for review." + - q: "Is OpenAI Codex an agentic AI coding tool?" + a: "OpenAI Codex is an agentic AI coding tool for performing bounded software-development tasks through OpenAI’s cloud and command-line experiences." + - q: "What is the most important production metric for an AI coding agent?" + a: "Cost per accepted task is the most useful top-level production metric because it combines successful outcomes with retries, usage, supervision, review, and rework." --- ## TL;DR @@ -158,13 +158,24 @@ Agentic AI tools in this guide fall into two distinct groups. Choose the category based on where the work happens. If you are shipping a SaaS product, you will usually want an in-IDE agent. If you are automating a process across several applications, you will usually want a workflow platform. This guide compares both categories and explains where their capabilities overlap. +Teams focused on codebase maintenance can read [Best AI Coding Agents for Refactoring and Debugging: 5 Tools Compared](https://www.sim.ai/library/best-ai-coding-agents-refactoring-debugging). Teams deciding how much autonomy they need can read [AI Coding Agents vs Code Completion Tools: Which Should Engineering Teams Choose?](https://www.sim.ai/library/ai-coding-agents-vs-code-completion-tools). + ## What are agentic coding tools? -Agentic coding tools are software development assistants that can plan and execute multistep coding tasks instead of only suggesting the next line of code. +Agentic coding tools are software development assistants that can plan and execute multistep coding tasks instead of only suggesting the next line of code. Traditional autocomplete predicts the next few tokens as you type, and a standard chat response does not independently act on a codebase. A coding agent typically receives a goal, examines relevant files, proposes or makes edits, invokes development tools, checks the result, and reports what changed. Autonomy varies: some agents work interactively inside an editor or terminal, while others handle delegated tasks in a hosted environment. -The defining capability is the ability to take actions across a software project while preserving enough context for a developer to review the result, not simply the presence of a chat interface. +Three capabilities make a tool agentic: + +- **Multi-step planning.** + The tool breaks a goal into file edits, terminal commands, and checks rather than completing one line. +- **Tool use.** + The agent can run terminal commands, execute tests, browse documentation, or call APIs instead of only generating text. +- **Self-correction.** + When a test fails or a command errors, the agent can read the output and revise its approach instead of waiting for a human to diagnose it. + +The defining capability is the ability to take actions across a software project while preserving enough context for a developer to review the result, not simply the presence of a chat interface. Sim's guide to [AI agents](https://www.sim.ai/library/what-is-an-ai-agent-definition-how-it-works-and-examples) explains how the concept applies beyond coding. ## Which agentic coding tool is best in 2026? @@ -220,28 +231,17 @@ Devin fits teams evaluating a hosted agent for bounded software engineering task Amazon Q Developer fits teams whose development, operations, and cloud administration center on AWS. AWS publishes its Free and Pro tiers, interfaces, and request allowances on the [Amazon Q Developer pricing page](https://aws.amazon.com/q/developer/pricing/) as of October 2026. -## What makes an AI coding tool agentic? - -An AI coding tool is agentic when it can plan a multi-step task, take actions across a codebase, and correct mistakes without a human approving every line. Traditional autocomplete instead predicts the next few tokens as you type, while a standard chat response does not independently act on a codebase. - -- **Multi-step planning.** - The tool breaks a goal into file edits, terminal commands, and checks rather than completing one line. -- **Tool use.** - The agent can run terminal commands, execute tests, browse documentation, or call APIs instead of only generating text. -- **Self-correction.** - When a test fails or a command errors, the agent can read the output and revise its approach instead of waiting for a human to diagnose it. - -Sim's guide to [AI agents](https://www.sim.ai/library/what-is-an-ai-agent-definition-how-it-works-and-examples) explains how the concept applies beyond coding. - ## What's the difference between an AI coding agent and an agent-workflow platform? -An AI coding agent writes and modifies code in a specific project. An agent-workflow platform builds agents that can use code as one action in a larger automated process spanning apps and data sources. +An AI coding agent writes and modifies code in a specific project. An agent-workflow platform builds agents that can use code as one action in a larger automated process spanning apps and data sources. The two categories solve different primary jobs and should be evaluated against category-specific criteria. -[Cursor](https://cursor.com/), [Claude Code](https://claude.com/product/claude-code), and [GitHub Copilot](https://github.com/features/copilot) are coding agents built around repository work. [Gumloop](https://www.gumloop.com/) and [n8n](https://n8n.io/) are workflow platforms that can connect code execution to applications such as Slack, a CRM, or a database. Sim is the open-source AI workspace and can coordinate code execution with those surrounding systems. +[Cursor](https://cursor.com/), [Claude Code](https://claude.com/product/claude-code), and [GitHub Copilot](https://github.com/features/copilot) are coding agents built around repository work, Git workflows, and terminal access. [Gumloop](https://www.gumloop.com/) and [n8n](https://n8n.io/) are workflow platforms that can connect code execution to applications such as Slack, a CRM, or a database. Sim is the open-source AI workspace and can coordinate code execution with those surrounding systems. The categories overlap when a workflow executes custom code or exposes tools to a coding agent. Sim includes a [Function block for custom JavaScript](https://docs.sim.ai/workflows/blocks/function), while [Chat](https://docs.sim.ai/chat/workflows) lets you describe workflows in natural language. -Sim does not replace an in-IDE coding agent for writing and shipping a codebase. It supports workflows in which code execution is one step in an automated process involving external tools or data. Sim's guide to [AI agents and RPA](https://www.sim.ai/library/ai-agents-vs-rpa) explains how agent-based automation differs from rule-based automation. +An agent-workflow platform does not replace an in-IDE coding agent for writing and shipping a codebase. A workflow platform can connect a coding agent's output to a broader process: the coding agent still modifies the codebase in its development environment, while Sim coordinates supported actions involving other tools and data. + +For a direct category comparison, see [AI Coding Agents vs. AI Workflow Agents: What's the Difference?](https://www.sim.ai/library/ai-coding-agents-vs-ai-workflow-agents). Sim's guide to [AI agents and RPA](https://www.sim.ai/library/ai-agents-vs-rpa) explains how agent-based automation differs from rule-based automation, and its comparison of an [AI agent and a chatbot](https://www.sim.ai/library/ai-agent-vs-chatbot) helps when deciding between an agent and a conversational interface. ## Which agentic AI coding tools fit each use case? @@ -352,55 +352,44 @@ The table describes product positioning rather than a guarantee that every repos ## What are the key facts about each AI coding agent? -GitHub Copilot, CodeRabbit, Qodo Merge, Claude Code, OpenAI Codex, Cursor, Devin, n8n, and Sim differ most in where they run, how they are governed, and whether they are coding agents or orchestration systems. +GitHub Copilot, CodeRabbit, Qodo Merge, Claude Code, OpenAI Codex, Cursor, Devin, n8n, and Sim differ most in where they run, how they are governed, and whether they are coding agents or orchestration systems. As of October 2026, the facts below summarize only controls and billing units documented on each vendor's current first-party pages. -As of October 2026: - -- **GitHub Copilot** is a commercial GitHub product with cloud-agent and code-review access on applicable [Copilot plans](https://github.com/features/copilot/plans). -- **CodeRabbit** is a commercial product centered on agentic pull-request review, with current deployment and billing options on the [CodeRabbit pricing page](https://www.coderabbit.ai/pricing). -- **Qodo Merge** is a commercial pull-request review product with agentic review and rules, with current packaging on the [Qodo pricing page](https://www.qodo.ai/pricing/). -- **Claude Code** is Anthropic's coding agent for repository work through terminal, IDE, Slack, and web surfaces, as described on the [Claude Code product page](https://claude.com/product/claude-code). -- **OpenAI Codex** can read, edit, and run code, while [Codex cloud](https://developers.openai.com/codex/cloud) can execute background tasks in parallel cloud environments. -- **Cursor** is a commercial AI code editor with agent workflows, and its current allowances and billing are maintained on the [Cursor pricing page](https://cursor.com/pricing). -- **Devin** is a commercial coding-agent product available through desktop, CLI, and cloud-agent experiences, with current access and billing on the [Devin pricing page](https://devin.ai/pricing). -- **n8n** is a self-hostable workflow automation product under the source-available Sustainable Use License, not an OSI-approved open-source license; its hosted service uses the vendor's current [n8n pricing](https://n8n.io/pricing/). -- **Sim** is the open-source AI workspace for building, deploying, and managing AI agents. Sim's core is Apache 2.0, while `apps/sim/ee` is governed by the separate [Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE), and current cloud plans are listed on the [Sim pricing page](https://www.sim.ai/pricing). - -### Production facts at a glance - -As of October 2026, the production facts below summarize only controls and billing units documented on each vendor's current first-party pages. - -- **Cursor:** Cursor runs as a local editor with cloud AI services and cloud agents; Privacy Mode prevents Cursor and model providers from using code for training, Teams admins can enforce that mode and manage retention and SSO, and Teams billing is [per seat with plan-specific usage](https://cursor.com/docs/account/teams/pricing), as detailed in Cursor's [privacy documentation](https://cursor.com/docs/enterprise/privacy-and-data-governance). -- **GitHub Copilot:** GitHub Copilot spans supported IDEs and GitHub's cloud agent; GitHub says an indexed repository is [not used for model training](https://docs.github.com/copilot/concepts/indexing-repositories-for-copilot-chat), organization and enterprise owners can manage feature and model [policies](https://docs.github.com/copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-policies-for-copilot-in-your-organization), and business plans bill per user with included and overage [premium requests](https://docs.github.com/copilot/concepts/copilot-billing/about-billing-for-github-copilot-in-your-enterprise). -- **Claude Code:** Claude Code runs in the terminal, IDE, web, and other [documented surfaces](https://claude.com/product/claude-code); Anthropic says commercial-product inputs and outputs are [not used for training by default](https://privacy.anthropic.com/en/articles/7996868-is-my-data-used-for-model-training), Claude for Work [owners manage accounts and organizational data](https://privacy.anthropic.com/en/articles/9265372-who-owns-and-manages-the-data-of-my-team), and access is billed through [Claude plan seats](https://claude.com/pricing) or API usage. +- **Cursor:** Cursor is a commercial AI code editor that runs locally with cloud AI services and cloud agents; Privacy Mode prevents Cursor and model providers from using code for training, Teams admins can enforce that mode and manage retention and SSO, and Teams billing is [per seat with plan-specific usage](https://cursor.com/docs/account/teams/pricing), as detailed in Cursor's [privacy documentation](https://cursor.com/docs/enterprise/privacy-and-data-governance). Current allowances are on the [Cursor pricing page](https://cursor.com/pricing). +- **GitHub Copilot:** GitHub Copilot spans supported IDEs and GitHub's cloud agent, with cloud-agent and code-review access on applicable [Copilot plans](https://github.com/features/copilot/plans); GitHub says an indexed repository is [not used for model training](https://docs.github.com/copilot/concepts/indexing-repositories-for-copilot-chat), organization and enterprise owners can manage feature and model [policies](https://docs.github.com/copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-policies-for-copilot-in-your-organization), and business plans bill per user with included and overage [premium requests](https://docs.github.com/copilot/concepts/copilot-billing/about-billing-for-github-copilot-in-your-enterprise). +- **Claude Code:** Claude Code is Anthropic's coding agent for repository work in the terminal, IDE, Slack, web, and other [documented surfaces](https://claude.com/product/claude-code); Anthropic says commercial-product inputs and outputs are [not used for training by default](https://privacy.anthropic.com/en/articles/7996868-is-my-data-used-for-model-training), Claude for Work [owners manage accounts and organizational data](https://privacy.anthropic.com/en/articles/9265372-who-owns-and-manages-the-data-of-my-team), and access is billed through [Claude plan seats](https://claude.com/pricing) or API usage. - **Windsurf:** Windsurf runs as an editor and through supported IDE plugins; Teams and Enterprise add centralized billing, admin dashboards, SSO, and role-based access control, while paid-plan consumption follows the vendor's [usage-based plan model](https://docs.windsurf.com/windsurf/accounts/usage). - **Replit Agent:** Replit Agent runs in Replit's hosted development environment; Replit says Enterprise customer content is [not used to train its models](https://docs.replit.com/legal-and-security-info/model-improvement), Enterprise adds SSO, SCIM, governance, and administrative roles, and Pro uses pooled credits without per-seat fees according to [Replit's plan documentation](https://docs.replit.com/category/teams). -- **CodeRabbit:** CodeRabbit runs on supported Git providers, IDEs, and CLI, with an Enterprise [self-hosted deployment](https://docs.coderabbit.ai/self-hosted/overview); [cached code](https://docs.coderabbit.ai/reference/caching) is encrypted, never used for training, and expires within seven days, administrators can manage seats, roles, permissions, and audit logs, and paid plans use per-developer review limits plus separately billed on-demand products under its [plan documentation](https://docs.coderabbit.ai/management/plans). -- **Qodo Merge:** Qodo supports multi-tenant, single-tenant, and on-premises [deployment models](https://docs.qodo.ai/deployment-models); Team and Enterprise users are [opted out of model training by default](https://docs.qodo.ai/qodo-ide/data-sharing), [account roles](https://docs.qodo.ai/account-management/roles-and-permissions) govern administrative scope, and current Qodo billing uses a shared [workspace credit pool](https://docs.qodo.ai/pricing-and-usage). -- **OpenAI Codex:** Codex runs locally through desktop, CLI, and IDE surfaces or in Codex cloud; ChatGPT Business and Enterprise inputs and outputs are [not used for model training by default](https://openai.com/enterprise-privacy/), managed-workspace roles and retention settings apply to Codex, and access is billed through eligible ChatGPT plans or API usage as described in the [Codex authentication documentation](https://developers.openai.com/codex/auth). -- **Devin:** Devin provides [cloud and customer-dedicated enterprise deployments](https://docs.devin.ai/enterprise/deployment/overview), although its brain remains in Cognition's cloud; Cognition documents [encryption in transit and at rest](https://docs.devin.ai/enterprise/overview), Enterprise supports [SSO and SCIM administration](https://docs.devin.ai/enterprise/security-access/sso/guide), and usage is billed in [Agent Compute Units](https://docs.devin.ai/admin/billing/enterprise). -- **Sim:** Sim is available on Sim Cloud or as a self-hosted deployment; cloud retention defaults and configurable [data-retention controls](https://docs.sim.ai/platform/enterprise/data-retention) are documented by plan, Enterprise adds organization access and audit controls, and Sim Cloud meters usage in [credits](https://docs.sim.ai/platform/costs), while billing-disabled self-hosted deployments do not apply plan-based usage billing. +- **CodeRabbit:** CodeRabbit is a commercial product centered on agentic pull-request review that runs on supported Git providers, IDEs, and CLI, with an Enterprise [self-hosted deployment](https://docs.coderabbit.ai/self-hosted/overview); [cached code](https://docs.coderabbit.ai/reference/caching) is encrypted, never used for training, and expires within seven days, administrators can manage seats, roles, permissions, and audit logs, and paid plans use per-developer review limits plus separately billed on-demand products under its [plan documentation](https://docs.coderabbit.ai/management/plans). Current options are on the [CodeRabbit pricing page](https://www.coderabbit.ai/pricing). +- **Qodo Merge:** Qodo Merge is a commercial pull-request review product with agentic review and rules; Qodo supports multi-tenant, single-tenant, and on-premises [deployment models](https://docs.qodo.ai/deployment-models), Team and Enterprise users are [opted out of model training by default](https://docs.qodo.ai/qodo-ide/data-sharing), [account roles](https://docs.qodo.ai/account-management/roles-and-permissions) govern administrative scope, and current Qodo billing uses a shared [workspace credit pool](https://docs.qodo.ai/pricing-and-usage) described on the [Qodo pricing page](https://www.qodo.ai/pricing/). +- **OpenAI Codex:** Codex can read, edit, and run code locally through desktop, CLI, and IDE surfaces, while [Codex cloud](https://developers.openai.com/codex/cloud) can execute background tasks in parallel cloud environments; ChatGPT Business and Enterprise inputs and outputs are [not used for model training by default](https://openai.com/enterprise-privacy/), managed-workspace roles and retention settings apply to Codex, and access is billed through eligible ChatGPT plans or API usage as described in the [Codex authentication documentation](https://developers.openai.com/codex/auth). +- **Devin:** Devin is a commercial coding-agent product available through desktop, CLI, and cloud-agent experiences, with [cloud and customer-dedicated enterprise deployments](https://docs.devin.ai/enterprise/deployment/overview), although its brain remains in Cognition's cloud; Cognition documents [encryption in transit and at rest](https://docs.devin.ai/enterprise/overview), Enterprise supports [SSO and SCIM administration](https://docs.devin.ai/enterprise/security-access/sso/guide), and usage is billed in [Agent Compute Units](https://docs.devin.ai/admin/billing/enterprise), with current access on the [Devin pricing page](https://devin.ai/pricing). +- **Sim:** Sim is the open-source AI workspace for building, deploying, and managing AI agents, available on Sim Cloud or as a self-hosted deployment. Sim's core is Apache 2.0, while `apps/sim/ee` is governed by the separate [Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE); cloud retention defaults and configurable [data-retention controls](https://docs.sim.ai/platform/enterprise/data-retention) are documented by plan, Enterprise adds organization access and audit controls, and Sim Cloud meters usage in [credits](https://docs.sim.ai/platform/costs), while billing-disabled self-hosted deployments do not apply plan-based usage billing. Current cloud plans are listed on the [Sim pricing page](https://www.sim.ai/pricing). - **Gumloop:** Gumloop is a hosted workflow platform; organization administrators can enforce [connector policies](https://docs.gumloop.com/enterprise-features/app-policies/overview), inspect [audit logs](https://docs.gumloop.com/enterprise-features/audit_logging), and [export organization usage and credit data](https://docs.gumloop.com/enterprise-features/organization_data_export), while [subscription administration](https://docs.gumloop.com/core-concepts/subscription_management) is restricted to the Admin role. -- **n8n:** n8n is available as a managed cloud service or self-hosted software; n8n states in its [privacy documentation](https://docs.n8n.io/privacy-and-security) that it does not manage customer data in self-hosted deployments, instance owners and admins can configure [SSO and other security controls](https://docs.n8n.io/deploy/host-n8n/configure-n8n/security), and cloud plans meter workflow executions under the vendor's [pricing](https://n8n.io/pricing). +- **n8n:** n8n is a self-hostable workflow automation product under the source-available Sustainable Use License, not an OSI-approved open-source license, and is also available as a managed cloud service; n8n states in its [privacy documentation](https://docs.n8n.io/privacy-and-security) that it does not manage customer data in self-hosted deployments, instance owners and admins can configure [SSO and other security controls](https://docs.n8n.io/deploy/host-n8n/configure-n8n/security), and cloud plans meter workflow executions under the vendor's [pricing](https://n8n.io/pricing). - **Zapier:** Zapier is a hosted automation service; its [Enterprise controls](https://help.zapier.com/hc/en-us/articles/8496213575053-Get-started-with-Zapier-s-Enterprise-plan) include SAML SSO, SCIM, app restrictions, audit capabilities, and custom data retention, while Zap workflows are [metered in tasks](https://help.zapier.com/hc/en-us/articles/16051471305357-How-to-select-your-Zapier-plan). ## Which agentic AI tools generate unit tests? GitHub Copilot, Claude Code, OpenAI Codex, Cursor, Devin, and other repository-capable coding agents can generate unit tests, but the best tool is the one that can run those tests, inspect failures, and revise the implementation inside the team's actual environment. -Test generation should be evaluated as an execution loop rather than as text generation. A useful coding agent must be able to: +Test generation should be evaluated as an execution loop rather than as text generation. A useful coding agent should identify the behavior the change is supposed to preserve or introduce, find the project's existing test framework and conventions, add tests at the correct layer, and interpret failures without weakening valid assertions. + +The strongest evidence is a red-green sequence: -1. Identify the behavior the change is supposed to preserve or introduce. -2. Find the project's existing test framework and conventions. -3. Add tests at the correct layer. -4. Run the relevant test command. -5. Interpret failures without weakening valid assertions. -6. Show the final diff and execution evidence to a reviewer. +1. Demonstrate the failure against the original code. +2. Add a focused regression test. +3. Confirm that the test fails for the expected reason. +4. Apply the implementation change. +5. Confirm that the new test and the relevant existing suite pass. +6. Review whether the test asserts behavior rather than implementation details. +7. Show the final diff and execution evidence, and require a human to approve it. -A generated test is not automatically a good test. Teams should check whether the test would fail against the original bug, whether it covers meaningful edge cases, and whether it asserts observable behavior instead of reproducing implementation details. +A generated test is not automatically a good test. Teams should check whether the test would fail against the original bug, whether it covers meaningful edge cases, and whether it asserts observable behavior instead of reproducing implementation details. If an agent writes the test only after seeing its own implementation, reviewers should scrutinize the result for confirmation bias and missing negative cases. ## Which agentic coding platform should a dev team choose for production? +**Verdict:** GitHub Copilot is the default production candidate for organizations already standardized on GitHub because it works across GitHub, supported IDEs, and the command line, with [organization plan and administration options](https://github.com/features/copilot/plans). This verdict is a starting point rather than a universal ranking: repository results, access controls, review effort, and total cost should determine the final choice. + A production development team should choose GitHub Copilot for GitHub-native delegated coding, CodeRabbit for dedicated pull-request review, Qodo Merge for test-aware PR feedback, Claude Code for programmable terminal workflows, and Sim when the team needs to coordinate multiple agents, CI systems, scanners, and human approvals. The decision should follow the control boundary: @@ -467,19 +456,7 @@ The production decision should compare observed results against predefined accep ## What production tasks should teams include in an agentic coding tool benchmark? -A production benchmark should test agentic coding tools on representative maintenance tasks with objective acceptance checks. One successful task does not establish dependable performance across the software lifecycle, so teams should use the consolidated task set and measurement method below. - -## How should teams test code quality and correctness? - -Agentic coding tools should be judged by externally checked outcomes rather than by whether their explanations sound convincing. Define acceptance tests before each run whenever possible, then use existing and hidden tests, type checks, static analysis, security scans, and review by an engineer who did not supervise the run. - -A correct patch should solve the stated problem, preserve unrelated behavior, follow repository conventions, and avoid unnecessary changes. Track first-pass success separately from eventual success because repeated intervention changes the operating cost and risk profile. - -Diff quality also matters. Large, unrelated, or unexplained edits increase review cost even when the test suite passes, so production teams should prefer the smallest change that fully satisfies the acceptance criteria. - -## How should teams evaluate AI coding agents for code review and testing? - -A development team should evaluate AI coding agents with a private benchmark drawn from real defects, review comments, and test gaps in its own repositories. Use tasks that represent production work rather than isolated algorithm exercises: +A development team should evaluate AI coding agents for code review and testing with a private benchmark drawn from real defects, review comments, and test gaps in its own repositories. One successful task does not establish dependable performance across the software lifecycle, so use tasks that represent production work rather than isolated algorithm exercises: 1. Fix a reproducible defect with a known regression test without changing unrelated behavior. 2. Add tests for an existing module, including meaningful edge cases, a security-sensitive input-validation defect, and a flaky test that requires diagnosis rather than deletion. @@ -496,9 +473,21 @@ A development team should evaluate AI coding agents with a private benchmark dra 13. Recover from a misleading hypothesis or failed command. 14. Summarize every change, remaining risk, and test result for a reviewer. -Begin each task from the same repository snapshot in an isolated environment, keep the instructions, permissions, and pass criteria consistent, and run each task multiple times. Evaluate correctness, review precision, test quality, unnecessary diff size, reproducibility, human intervention, and time to a reviewable result. +## How should teams test code quality and correctness? + +Agentic coding tools should be judged by externally checked outcomes rather than by whether their explanations sound convincing. Define acceptance tests before each run whenever possible, then use existing and hidden tests, type checks, static analysis, security scans, and review by an engineer who did not supervise the run. + +A correct patch should solve the stated problem, preserve unrelated behavior, follow repository conventions, and avoid unnecessary changes. Track first-pass success separately from eventual success because repeated intervention changes the operating cost and risk profile. + +Diff quality also matters. Large, unrelated, or unexplained edits increase review cost even when the test suite passes, so production teams should prefer the smallest change that fully satisfies the acceptance criteria. + +## How do you run a fair pilot of agentic AI coding tools? + +A fair pilot gives every candidate the same task definitions, starting repository revisions, acceptance tests, permission boundaries, run limits, and reviewer criteria. Begin each task from the same repository snapshot in an isolated environment, draw debugging, refactoring, test-generation, and bounded feature tasks from the repositories where the selected tool will operate, and run important tasks multiple times. -Record task completion, hidden-test results, regressions, security findings, changed files, commands and failures, wall-clock time, reviewer time and corrections, unnecessary churn, model or tool consumption, total cost, and whether the final change was accepted. The [reproducible AI coding-agent benchmark](https://www.sim.ai/library/reproducible-ai-coding-agent-benchmark) provides a framework for testing debugging, test generation, and refactoring without relying on vendor demonstrations. +Randomize review order where practical, and capture the task, repository revision, tool and model configuration, command log, changed files, tests, hidden-test results, regressions, security findings, retries, wall-clock time, reviewer time and corrections, unnecessary churn, model or tool consumption, total cost, and final decision. Evaluate correctness, review precision, test quality, unnecessary diff size, reproducibility, human intervention, and time to a reviewable result. + +Reviewers should accept patches based on correctness and maintainability rather than explanation length or confident completion claims. The [reproducible AI coding-agent benchmark](https://www.sim.ai/library/reproducible-ai-coding-agent-benchmark) provides a framework for testing debugging, test generation, and refactoring without relying on vendor demonstrations. ## Which metrics show whether an agentic coding tool is production-ready? @@ -539,9 +528,9 @@ A safe workflow constrains the agent's permissions, records the commands it ran, ## When do AI coding agents need human approval? -AI coding agents need human approval before merging code, changing security-sensitive behavior, modifying infrastructure, accessing production data, altering dependencies, or bypassing a failed deterministic check. +AI coding agents need human approval before merging code, changing security-sensitive behavior, modifying infrastructure, accessing production data, altering dependencies, running privileged commands, or bypassing a failed deterministic check. -Human reviewers should retain responsibility for intent and risk. An agent can provide evidence, but a reviewer must decide whether the change matches the requirement and whether the remaining risk is acceptable. +Human reviewers should retain responsibility for intent and risk. An agent can provide evidence, but a reviewer must decide whether the change matches the requirement and whether the remaining risk is acceptable. Reviewers need a normal code diff, evidence that required checks ran, a record of consequential commands, and a clear statement of assumptions or remaining failures rather than only a chat transcript. Approval is especially important for: @@ -553,13 +542,7 @@ Approval is especially important for: - Test modifications made in response to a failure. - Large diffs or changes outside the requested scope. -Branch protection and required status checks should remain authoritative even when an agent submits the pull request. - -## How should teams evaluate human review and change control? - -Agentic coding tools should make plans, edits, commands, test evidence, and unresolved uncertainty visible before a change reaches production. Reviewers need a normal code diff, evidence that required checks ran, a record of consequential commands, and a clear statement of assumptions or remaining failures rather than only a chat transcript. - -High-risk changes should require approval before privileged commands, dependency changes, database migrations, infrastructure edits, or deployment actions. Branch protections, ownership rules, required checks, and separation of duties should remain in force, and teams should confirm that agent-authored changes can be reverted through the same version-control and deployment processes used for human-authored changes. +Branch protection, ownership rules, required status checks, and separation of duties should remain authoritative even when an agent submits the pull request, and teams should confirm that agent-authored changes can be reverted through the same version-control and deployment processes used for human-authored changes. ## How should teams measure the ROI of agentic coding tools? @@ -615,15 +598,15 @@ Sim is not a substitute for a coding agent, source-control permissions, or CI. S Sim is not a dedicated AI coding agent; Sim is the open-source AI workspace teams can use to orchestrate coding agents, repository events, tests, scanners, notifications, and approval steps. -A coding agent edits or reviews code. Sim coordinates the surrounding workflow, including context collection, model or agent calls, deterministic validation, policy decisions, and human review. +A coding agent edits or reviews code. Sim coordinates the surrounding workflow, including context collection, model or agent calls, deterministic validation, policy decisions, and human review. Sim fits engineering teams that need coding work to connect to broader tools, approval steps, and operational processes rather than remain inside an IDE or repository agent. -This distinction matters when a development team already uses tools such as GitHub Copilot, CodeRabbit, Claude Code, or another repository agent but lacks a consistent process for deciding which changes may proceed automatically. +This distinction matters when a development team already uses tools such as GitHub Copilot, CodeRabbit, Claude Code, or another repository agent but lacks a consistent process for deciding which changes may proceed automatically. [Sim's core](https://github.com/simstudioai/sim/blob/main/LICENSE) is Apache 2.0, while code in [`apps/sim/ee`](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) uses the separate Sim Enterprise License and requires an active Sim Enterprise subscription for production use. ## Can n8n automate AI code review workflows? n8n can orchestrate repository, AI, and notification steps, making n8n a relevant incumbent for teams that already use general-purpose workflow automation. n8n and Sim coordinate work around dedicated coding agents rather than replacing repository-aware tools such as Cursor or Claude Code. -As of October 2026, n8n is source-available under the [Sustainable Use License](https://github.com/n8n-io/n8n/blob/master/LICENSE.md) rather than OSI-approved open source. Sim is the open-source AI workspace where teams build, deploy, and manage AI agents, and Sim fits surrounding processes that need tool coordination, routing, and human decisions. Sim's core is Apache 2.0, while code in `apps/sim/ee` uses the separate [Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE). Teams comparing the two should consider licensing alongside agent controls, deployment requirements, and the workflow-building experience. +As of October 2026, n8n is source-available under the [Sustainable Use License](https://github.com/n8n-io/n8n/blob/master/LICENSE.md) rather than OSI-approved open source. Sim fits surrounding processes that need tool coordination, routing, and human decisions. Teams comparing the two should consider licensing alongside agent controls, deployment requirements, and the workflow-building experience. For a broader comparison, see [Sim vs n8n vs OpenAI AgentKit: AI Agent Builder Comparison (2026)](https://www.sim.ai/library/openai-vs-n8n-vs-sim). @@ -666,31 +649,21 @@ Production testing should cover: Use least privilege by default: separate read access from write access, separate code modification from command execution, and require human approval before consequential actions. Run untrusted tasks in disposable environments and keep production credentials out of the agent's execution context whenever possible. -## What is the best workflow for AI-generated unit tests? - -The best workflow for AI-generated unit tests requires the agent to reproduce the defect, add a test that fails before the fix, implement or review the fix, and show that the same test passes afterward. - -The strongest evidence is a red-green sequence: +## What are the best AI coding agents for refactoring and debugging? -1. Demonstrate the failure against the original code. -2. Add a focused regression test. -3. Confirm that the test fails for the expected reason. -4. Apply the implementation change. -5. Confirm that the new test and the relevant existing suite pass. -6. Review whether the test asserts behavior rather than implementation details. -7. Require a human to approve the final diff. +The best AI coding agent for refactoring and debugging is the candidate that produces the highest rate of correct, reviewable changes on the team's own repositories after passing its production gates. For a task-specific comparison focused on those jobs, see [Best AI Coding Agents for Refactoring and Debugging: 5 Tools Compared](https://www.sim.ai/library/best-ai-coding-agents-refactoring-debugging). -If an agent writes the test only after seeing its own implementation, reviewers should scrutinize the result for confirmation bias and missing negative cases. +## Are there open-source agentic AI coding tools? -## How do AI coding agents differ from AI workflow agents? +Agentic AI coding tools use different license models, including proprietary, source-available, and open-source licenses. Many prominent in-IDE coding agents, including Cursor, Windsurf, and Claude Code, are proprietary applications. -AI coding agents primarily inspect, generate, test, and modify software, while AI workflow agents coordinate work across models, APIs, data, and business systems. Engineering teams may use both, but the two categories solve different primary jobs and should be evaluated against category-specific criteria. +Licensing varies more among workflow platforms that can run code. n8n uses its [Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license/), which is source-available and includes commercial restrictions. Sim's core uses the permissive [Apache License 2.0](https://github.com/simstudioai/sim), and our documentation provides [self-hosting guidance](https://docs.sim.ai/self-hosting). Features in `apps/sim/ee`, such as SSO, SCIM, access control, audit logs, and white-labeling, use a [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE), which is free for development, testing, and internal non-production use, requires an Enterprise subscription for production use, and does not permit modification or redistribution. Sim's comparison of [open-source AI agent platforms](https://www.sim.ai/library/open-source-ai-agent-platforms) covers additional licensing and deployment models. -For a direct category comparison, see [AI Coding Agents vs. AI Workflow Agents: What's the Difference?](https://www.sim.ai/library/ai-coding-agents-vs-ai-workflow-agents). Sim is not a direct substitute for a coding agent: Sim is the open-source AI workspace where teams build, deploy, and manage AI agents that automate real work across connected systems. +## Do agentic coding tools support MCP? -## What are the best AI coding agents for refactoring and debugging? +The [Model Context Protocol](https://modelcontextprotocol.io/) gives AI clients a standard way to connect to external tools and context. [Claude Code's MCP documentation](https://docs.anthropic.com/en/docs/claude-code/mcp) and [Cursor's MCP documentation](https://cursor.com/docs/mcp) explain how each product connects to external MCP servers. -The best AI coding agent for refactoring and debugging is the candidate that produces the highest rate of correct, reviewable changes on the team's own repositories after passing its production gates. For a task-specific comparison focused on those jobs, see [Best AI Coding Agents for Refactoring and Debugging: 5 Tools Compared](https://www.sim.ai/library/best-ai-coding-agents-refactoring-debugging). +Sim can [connect external MCP servers](https://docs.sim.ai/agents/mcp) to a workflow and [publish deployed workflows as MCP tools](https://docs.sim.ai/workflows/deployment/mcp) for compatible clients. Sim's guide to [MCP servers](https://www.sim.ai/library/what-is-an-mcp-server) explains the protocol and its role in tool connections. ## Related comparisons @@ -698,26 +671,9 @@ Sim's library separates coding-agent selection from broader platform, workflow, - [AI Coding Agents vs. AI Workflow Agents: What's the Difference?](https://www.sim.ai/library/ai-coding-agents-vs-ai-workflow-agents) - [Best AI Coding Agents for Refactoring and Debugging: 5 Tools Compared](https://www.sim.ai/library/best-ai-coding-agents-refactoring-debugging) +- [AI Coding Agents vs Code Completion Tools: Which Should Engineering Teams Choose?](https://www.sim.ai/library/ai-coding-agents-vs-code-completion-tools) - [AI coding-agent benchmark: a reproducible test of debugging, test generation, and refactoring](https://www.sim.ai/library/reproducible-ai-coding-agent-benchmark) - [Best AI Agent Platforms and Builders in 2026](https://www.sim.ai/library/best-ai-agent-platforms-2026) - [Best AI Agent Builders for Human Approval Workflows](https://www.sim.ai/library/best-ai-agent-builders-for-human-approval-workflows) - [What Is Human-in-the-Loop in AI Agents?](https://www.sim.ai/library/what-is-human-in-the-loop-in-ai-agents) - [6 Best AI Observability Tools for Production Agents in 2026](https://www.sim.ai/library/6-best-ai-observability-tools-for-production-agents-in-2026) - -## Can an agent-workflow platform replace an in-IDE coding agent? - -An agent-workflow platform does not replace an in-IDE agent for writing and shipping a codebase. In-IDE agents work with codebase context, Git workflows, and terminal access. General workflow platforms instead coordinate actions across applications and data sources. - -A workflow platform can connect a coding agent's output to a broader process. The coding agent still modifies the codebase in its development environment, while Sim coordinates supported actions involving other tools and data. If you are deciding between an agent and a conversational interface, read Sim's comparison of an [AI agent and a chatbot](https://www.sim.ai/library/ai-agent-vs-chatbot). - -## Are there open-source agentic AI coding tools? - -Agentic AI coding tools use different license models, including proprietary, source-available, and open-source licenses. Many prominent in-IDE coding agents, including Cursor, Windsurf, and Claude Code, are proprietary applications. - -Licensing varies more among workflow platforms that can run code. n8n uses its [Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license/), which is source-available and includes commercial restrictions. Sim's core uses the permissive [Apache License 2.0](https://github.com/simstudioai/sim), and our documentation provides [self-hosting guidance](https://docs.sim.ai/self-hosting). Features in `apps/sim/ee`, such as SSO, SCIM, access control, audit logs, and white-labeling, use a [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE), which is free for development, testing, and internal non-production use, requires an Enterprise subscription for production use, and does not permit modification or redistribution. Sim's comparison of [open-source AI agent platforms](https://www.sim.ai/library/open-source-ai-agent-platforms) covers additional licensing and deployment models. - -## Do agentic coding tools support MCP? - -The [Model Context Protocol](https://modelcontextprotocol.io/) gives AI clients a standard way to connect to external tools and context. [Claude Code's MCP documentation](https://docs.anthropic.com/en/docs/claude-code/mcp) and [Cursor's MCP documentation](https://cursor.com/docs/mcp) explain how each product connects to external MCP servers. - -Sim can [connect external MCP servers](https://docs.sim.ai/agents/mcp) to a workflow and [publish deployed workflows as MCP tools](https://docs.sim.ai/workflows/deployment/mcp) for compatible clients. Sim's guide to [MCP servers](https://www.sim.ai/library/what-is-an-mcp-server) explains the protocol and its role in tool connections. diff --git a/apps/sim/content/library/ai-agent-examples-by-department-and-industry/index.mdx b/apps/sim/content/library/ai-agent-examples-by-department-and-industry/index.mdx index a1cdbcb1439..173862acecf 100644 --- a/apps/sim/content/library/ai-agent-examples-by-department-and-industry/index.mdx +++ b/apps/sim/content/library/ai-agent-examples-by-department-and-industry/index.mdx @@ -4,7 +4,7 @@ title: 'AI Agent Examples by Department and Industry: A Practical Roundup' description: 'A practical roundup of AI agent examples across sales, support, operations, engineering, marketing, HR, and seven industries, with build patterns for Sim.' seoTitle: 'AI Agent Examples by Department and Industry' date: 2026-09-17 -updated: 2026-10-25 +updated: 2026-10-26 authors: - andrew readingTime: 43 @@ -19,69 +19,49 @@ faq: - q: "Do these AI agent examples require coding?" a: "Many examples can use visual blocks, integrations, and prompts without custom code. Sim supports visual, conversational, and code-based building, while custom APIs or unusual business rules may require a function block or developer support." - q: "How do you enforce human oversight?" - a: "A Human in the Loop block pauses a run for submitted form fields before refunds, candidate decisions, account changes, or other consequential actions. A downstream Condition checks the approval field. Guardrails reports whether checks passed or failed, and a downstream Condition routes on that result. Run logs record the actions taken for later review." + a: "Place a Human in the Loop step before refunds, candidate decisions, account changes, or other consequential actions, and let a downstream Condition check the submitted approval field. Guardrails results are routed the same way, and run logs record the actions taken for later review." - q: "What are examples of AI agents in business?" - a: "AI agents in business include lead-research agents, support-ticket triage agents, invoice-exception agents, campaign-production agents, vendor-onboarding agents, and incident-investigation agents." + a: "Common business AI agents include support triage, lead and account research, content drafting and campaign production, document intake, invoice-exception investigation, vendor onboarding, incident investigation, meeting preparation, and evidence-based routing." - q: "What are examples of AI agents in sales?" - a: "Sales AI agents can research accounts, enrich leads, score qualification evidence, summarize calls, identify missing next steps, draft follow-ups, and update CRM records with human review before external commitments." + a: "Sales AI agents can research accounts, prepare source-linked account briefs, enrich leads, score qualification evidence, summarize calls, identify missing next steps, propose meeting questions, draft follow-ups, and update CRM records with human review before external commitments." - q: "What are examples of AI agents in customer service?" - a: "Customer-service AI agents can classify tickets, retrieve account context, search approved documentation, draft grounded responses, route urgent cases, and escalate requests that require judgment." + a: "Customer-service AI agents can classify tickets, retrieve account context, search approved documentation, draft responses with source references, route urgent cases, and escalate sensitive, uncertain, or judgment-heavy requests to a human reviewer." - q: "What are examples of AI agents in operations?" a: "Operations AI agents can process document intake, investigate invoice mismatches, coordinate vendor onboarding, monitor service-level exceptions, and prepare cases for an authorized reviewer." - q: "What are examples of AI agents in marketing?" - a: "Marketing AI agents can research defined audiences, create campaign drafts, repurpose approved content, check required claims, coordinate reviews, and summarize performance data." + a: "Marketing AI agents can research defined audiences, convert an approved campaign brief into channel-specific drafts, repurpose approved content, flag unsupported claims, coordinate reviews, and summarize performance data, with approval required before distribution." - q: "What are examples of AI agents for technical teams?" a: "Technical AI agents can investigate incidents, correlate logs with deployments, triage engineering requests, search runbooks, draft issue details, and prepare remediation options for an engineer." - q: "What is a real-world example of an AI agent?" - a: "A real-world AI agent can receive a support ticket, identify the customer and issue, retrieve relevant documentation, draft a grounded response, and route uncertain or sensitive cases to a support specialist." + a: "A support intake agent is a simple real-world example: it reads a request, identifies the customer and issue, retrieves approved documentation, asks for missing details, drafts a grounded response, and routes uncertain or sensitive cases to the correct queue or specialist." - q: "What is the difference between an AI agent and an automation?" a: "An AI agent uses model-based interpretation or decision-making within a bounded process, while conventional automation primarily executes predefined rules and branches." - q: "Do AI agents replace employees?" a: "AI agents are best used to handle bounded tasks and prepare decisions while employees retain accountability for judgment, exceptions, relationships, and consequential actions." - q: "When should an AI agent require human approval?" - a: "An AI agent should require human approval before consequential, difficult-to-reverse, legally sensitive, security-sensitive, or low-confidence actions." + a: "An AI agent should require human approval immediately before consequential, difficult-to-reverse, legally sensitive, or security-sensitive actions, and whenever evidence is incomplete or conflicting or confidence and policy conditions require escalation." - q: "How do you choose the first AI agent use case?" a: "A team should choose a first AI agent use case with frequent work, clear inputs, a measurable outcome, reversible actions, accessible data, and an accountable process owner." - q: "How do you measure AI agent performance?" a: "AI agent performance should be measured with task completion, accuracy, correction rate, escalation rate, latency, cost, human review time, reliability, safety events, and the workflow's business outcome." - q: "Can an AI agent use multiple business applications?" a: "An AI agent can use multiple business applications when it has authenticated tools, narrowly scoped permissions, reliable identifiers, and rules for handling failed or conflicting actions." - - q: "Can I build these AI agent examples with n8n?" - a: "n8n can build many integration-heavy examples, while Sim is designed as an open-source AI workspace for teams building, deploying, and managing AI agents." - q: "Is Sim open source?" a: "Sim's core is Apache 2.0 open source, while code in apps/sim/ee is covered by the separate Sim Enterprise License and requires an Enterprise subscription for production use." - q: "Can Sim use local AI models?" a: "Self-hosted Sim can use local or privately hosted models through Ollama, vLLM, LM Studio, or LiteLLM without requiring Sim Enterprise." - q: "How do you prevent an AI agent from taking the wrong action?" a: "AI agent risk is reduced through narrow permissions, deterministic policy checks, human approval, grounded context, input validation, complete run records, adversarial testing, and safe failure behavior." - - q: "What are the most common AI agent examples?" - a: "The most common AI agent examples include support triage, account research, content drafting, document intake, exception investigation, meeting preparation, and evidence-based routing." - - q: "What is an example of an AI agent in customer service?" - a: "A customer service AI agent can classify a ticket, retrieve approved knowledge, draft a response with source references, and send sensitive or uncertain cases to a human reviewer." - - q: "What is an example of an AI agent in sales?" - a: "A sales AI agent can prepare a source-linked account brief, identify missing qualification information, and propose meeting questions for a sales representative to review." - - q: "What is an example of an AI agent in marketing?" - a: "A marketing AI agent can convert an approved campaign brief into channel-specific drafts while flagging unsupported claims and requiring approval before distribution." - - q: "What is an example of an AI agent in human resources?" - a: "A human resources AI agent can organize application evidence against a predefined job rubric while leaving interview and employment decisions to accountable people." - - q: "What is an example of an AI agent in finance?" - a: "A finance AI agent can compare an invoice with its purchase order and receiving record, summarize mismatches, and route the evidence packet to an authorized reviewer." - q: "What is an example of an AI agent in legal operations?" a: "A legal operations AI agent can classify contract intake, identify missing information, and flag deviations from an approved clause library without replacing legal judgment." - q: "What is an example of an AI agent in procurement?" a: "A procurement AI agent can normalize supplier submissions into a source-linked requirements matrix while leaving shortlisting and award decisions to the evaluation team." - - q: "What is an example of an AI agent in IT?" - a: "An IT AI agent can summarize an incident timeline, retrieve the relevant runbook, and propose the next diagnostic check while requiring approval for disruptive actions." - q: "What is an example of an AI agent in software engineering?" a: "A software engineering AI agent can summarize a pull request, identify possible test gaps, and prepare review questions without bypassing repository protections or human review." - - q: "What is an example of an AI agent in healthcare?" - a: "A healthcare AI agent can prepare an authorized document-review or routing packet, but diagnosis, treatment, and other clinical decisions must remain with qualified professionals." - q: "What is an example of an AI agent in financial services?" a: "A financial services AI agent can assemble an investigation packet from authorized records while leaving account restrictions, filings, and customer-impacting actions to authorized reviewers." - q: "What tasks should AI agents not perform autonomously?" a: "AI agents should not autonomously make high-impact legal, medical, employment, financial, security, or safety decisions when errors could materially affect a person or organization." - - q: "Where should a human review an AI agent workflow?" - a: "A human should review an AI agent workflow immediately before a consequential action, whenever evidence is incomplete or conflicting, and whenever confidence or policy conditions require escalation." - q: "How do you prevent an AI agent from inventing facts?" a: "An AI agent should be constrained to approved sources, required to return source identifiers, tested for missing-data behavior, and routed to a reviewer when evidence does not support an answer." - q: "Can AI agents work across multiple departments?" @@ -89,13 +69,13 @@ faq: - q: "Are these AI agent examples guaranteed to save time or money?" a: "AI agent examples do not guarantee time or cost savings because results depend on task design, data quality, model behavior, integrations, review requirements, and operating conditions." - q: "What are practical AI agent examples for finance?" - a: "Finance AI agent examples include invoice matching, reconciliation investigation, expense-policy review, collections prioritization, close support, and variance explanation." + a: "Finance AI agent examples include invoice matching against purchase orders and receiving records, reconciliation investigation, expense-policy review, collections prioritization, close support, and variance explanation, with evidence routed to an authorized reviewer." - q: "What are practical AI agent examples for HR?" - a: "HR AI agent examples include onboarding coordination, policy-question routing, training reminders, document collection, and interview scheduling with appropriate human oversight." + a: "HR AI agent examples include onboarding coordination, policy-question routing, training reminders, document collection, interview scheduling, and organizing application evidence against a predefined rubric, while interview and employment decisions stay with accountable people." - q: "What are practical AI agent examples for IT teams?" - a: "IT AI agent examples include helpdesk triage, runbook retrieval, incident coordination, access-request preparation, asset investigation, and approved low-risk remediation." + a: "IT AI agent examples include helpdesk triage, runbook retrieval, incident timelines and coordination, proposed diagnostic checks, access-request preparation, asset investigation, and approved low-risk remediation, with approval required for disruptive actions." - q: "What are examples of AI agents in healthcare?" - a: "Healthcare AI agent examples include referral intake, appointment coordination, authorized document organization, administrative coding support, and staff handoffs without autonomous clinical decisions." + a: "Healthcare AI agent examples include referral intake, appointment coordination, authorized document review and routing packets, administrative coding support, and staff handoffs, while diagnosis, treatment, and other clinical decisions remain with qualified professionals." - q: "What are examples of AI agents in ecommerce?" a: "Ecommerce AI agent examples include return handling, order-issue investigation, catalog enrichment, review analysis, inventory exception routing, and customer-support triage." - q: "What are examples of AI agents in manufacturing?" @@ -103,13 +83,11 @@ faq: - q: "How do you measure AI agent ROI?" a: "AI agent ROI compares implementation and operating costs with verified gains in staff time, cycle time, quality, conversion, recovery, or throughput while accounting for review and failure costs." - q: "Can Sim build multistep AI agent workflows?" - a: "Sim can build multistep AI agent workflows that combine model reasoning, tools, conditions, and human review in a visual builder." + a: "Yes. Sim's visual builder combines approved context, model reasoning, tool actions, deterministic conditions, failure paths, and human review, so teams can build multistep agents for a specific department or process." - q: "Where can I find more multi-step AI agent examples?" a: "The Sim guide titled 25 Multi-Step AI Agent Examples Beyond Chatbots provides a broader catalog of multistep workflow patterns." - q: "Where can I find AI agent ideas for my business?" a: "The Sim guide titled 10 AI Agent Ideas for Real Impact: Get Started With Sim helps teams identify and prioritize an initial use case." - - q: "What is a simple AI agent example?" - a: "A simple AI agent example is a support intake agent that reads a request, retrieves approved documentation, asks for missing details, and routes the case to the correct queue." - q: "Can AI agents work with Slack?" a: "AI agents can work with Slack to receive requests, request human input, deliver summaries, and notify owners when a workflow needs attention." - q: "Can AI agents connect to a CRM?" @@ -125,9 +103,13 @@ faq: - q: "Is Sim an AI agent builder?" a: "Sim is the open-source AI workspace where teams build, deploy, and manage AI agents through a visual workflow builder." - q: "What is the best AI agent platform for business workflows?" - a: "Sim fits teams that want an open-source AI workspace with a visual workflow builder for building, deploying, and managing AI agents, while the right fit depends on deployment, governance, integration, and team requirements." + a: "The right platform depends on deployment, governance, integration, and team requirements; Sim fits teams that want an open-source AI workspace with a visual workflow builder for building, deploying, and managing AI agents." - q: "What is the difference between AI agent ideas and AI agent examples?" a: "AI agent ideas identify promising problems to solve, while AI agent examples specify the trigger, context, decisions, actions, approvals, outputs, and measurements of a workable process." + - q: "What is an example of an AI agent in recruiting?" + a: "A recruiting AI agent can coordinate interview availability, prepare candidate communications, summarize approved application information, and update scheduling records without making the hiring decision." + - q: "Can n8n, Zapier, or Make build AI agent workflows?" + a: "n8n, Zapier, and Make can build many integration-heavy examples, but teams should compare how each option handles model judgment, deterministic routing, permissions, evaluation, human review, and deployment requirements for the specific use case." --- ## TL;DR @@ -152,11 +134,13 @@ Invoice processing provides another useful distinction. OCR software extracts ve The examples in this roundup follow a recurring pattern. A trigger starts the job, the agent gathers context, and tool calls perform an action. A human-in-the-loop checkpoint controls sensitive or irreversible decisions. In [Sim](https://www.sim.ai), an Agent block handles reasoning, a knowledge base supplies trusted context, and workflows connect triggers, tools, actions, and review steps. The guide to [what an AI agent is](https://www.sim.ai/library/what-is-an-ai-agent-definition-how-it-works-and-examples) explains these components in more detail. -A useful example should make five details explicit: what starts the agent, what information it needs, which tools it may use, which decisions require human approval, and what business outcome the team will measure. An agent differs from simple trigger-and-action automation because it can interpret context before choosing a permitted action. Deterministic controls still belong around high-impact actions such as sending a contract, changing a payment, or updating production. [AI Agents vs RPA: When to Use Each for Enterprise Automation](https://www.sim.ai/library/ai-agents-vs-rpa) explains when contextual interpretation is useful and when fixed automation is the better fit. +Deterministic controls still belong around high-impact actions such as sending a contract, changing a payment, or updating production. [AI Agents vs RPA: When to Use Each for Enterprise Automation](https://www.sim.ai/library/ai-agents-vs-rpa) explains when contextual interpretation is useful and when fixed automation is the better fit. ## What every AI agent workflow should define before implementation -Every AI agent workflow should define its trigger, inputs, decisions, actions, controls, handoff rules, and success metric before implementation begins. +Every AI agent workflow should define its trigger, inputs, decisions, actions, controls, handoff rules, and success metric before implementation begins, including which decisions require human approval and what business outcome the team will measure. + +A production workflow should route ambiguous or incomplete cases to a person instead of forcing an answer, and its evaluation should cover business outcomes, quality, latency, cost, escalation, and errors. - **Trigger:** The event that starts the workflow, such as a form submission, new ticket, scheduled run, or database change. - **Inputs:** The records, documents, messages, and system data the agent may use. @@ -176,7 +160,7 @@ Practical department agents include support triage, sales research, campaign pre | Sales | Pipeline follow-up agent | Opportunity stage changes or becomes inactive | CRM, email, calendar, team chat | History summary, missing next steps, draft follow-up, and tasks | Account owner approves external messages | Opportunities without next steps, follow-up latency, stage conversion | | Support / Customer support | Ticket triage and routing agent | New support request | Help desk, knowledge base, CRM, incident system | Category, urgency, routing recommendation, sources, and draft | Specialist reviews sensitive or low-confidence cases | First-response time, routing accuracy, reassignment rate | | Support | Resolution-drafting agent | Ticket is assigned | Help desk, documentation, status page, customer database | Cited troubleshooting steps and response draft | Support representative approves customer-facing answers or flagged drafts | Handle time, draft acceptance rate, reopen rate | -| Operations | Invoice exception agent | Invoice fails validation | Email, document storage, ERP, procurement system | Mismatched fields, source records, and exception summary | Finance or procurement approves payment changes | Exception cycle time, manual touches, duplicate payments avoided | +| Operations / Finance | Invoice exception agent | Invoice fails a deterministic validation check | Email, document storage, ERP, procurement system, purchase order, receiving record, vendor record | Mismatched fields, source records, exception category, and evidence packet | Authorized finance or procurement reviewer decides payment, rejection, or account changes | Exception cycle time, manual touches, exception correctness, escalation rate, duplicate payments avoided | | Operations | Vendor onboarding agent | Vendor request is submitted | Forms, document storage, procurement, identity and risk tools | Completeness record, open questions, risk flags, and owner | Procurement, legal, or security approves flagged cases | Onboarding time, incomplete submissions, review backlog | | Marketing | Campaign production agent | Campaign brief is approved | Project management, CMS, CRM, analytics, ad platforms | Channel drafts, source notes, claim flags, and review tasks | Brand, legal, or campaign owner approves deployment | Production time, revision count, on-time launches | | Marketing | Content repurposing agent | Webinar, interview, or report is completed | Video transcript, document storage, CMS, social tools | Derivative drafts, source mapping, and distribution proposal | Editor approves facts, voice, and deployment | Assets per source, editing time, engagement by format | @@ -184,7 +168,6 @@ Practical department agents include support triage, sales research, campaign pre | Technical / Engineering | Engineering intake agent | Bug report or feature request arrives | Issue tracker, source control, documentation, product analytics | Ownership classification, related issues, and draft acceptance criteria | Engineer or product owner approves prioritization | Triage time, duplicate rate, issues ready for development | | HR / Human resources | Resume intake agent | Application or resume is submitted | Forms, email, document storage, applicant tracking system | Evidence-based rubric packet and missing information | Recruiter decides whether the candidate advances | Intake time, incomplete applications, extraction corrections | | HR | Employee onboarding agent | Signed offer is received | HR system, e-signature, identity management, ticketing | Required documents, assigned tasks, and prerequisite status | HR reviews exceptions, failed checks, and role or location changes | Onboarding time, missing tasks, delayed starts | -| Finance | Invoice exception review agent | Invoice fails a deterministic check | ERP, purchase order, receiving record, vendor record | Exception category and evidence packet | Authorized reviewer decides payment, rejection, or account changes | Exception correctness, review time, and escalation rate | | Legal | Contract-intake routing agent | New contract request | Intake form, clause library, policy documents | Contract type, missing fields, risk flags, and owner | Legal reviewer decides advice, clause acceptance, and signature | Classification correctness, missing-field rate, and escalation rate | | Procurement | Supplier comparison agent | Completed supplier submissions | Requirements, supplier responses, policy documents | Source-linked comparison matrix and missing evidence | Evaluation team decides shortlisting or award | Evidence coverage, correction rate, and reviewer overrides | @@ -194,18 +177,16 @@ These patterns do not guarantee results. Establish a baseline, name an owner, an A sales AI agent can prepare a source-linked account brief, identify missing qualification information, and draft outreach for a representative to review. +A production-shaped sales workflow starts with a form submission, CRM event, completed meeting, or upcoming calendar event. It uses approved account history, enrichment, transcripts, and interaction records as context; decides fit, intent, missing information, and the next permitted action; then enriches records, routes leads, prepares briefs, or drafts follow-up. Explicit territory and qualification rules control routing, representatives approve relationship-sensitive communication and commitments, and suggested metrics include routing accuracy, representative acceptance, time to first action, follow-up time, and correction rate. + Outbound prospecting agents turn a target account profile into a researched outreach sequence. The agent finds matching companies, enriches each contact with CRM and external data, and researches recent signals such as hiring activity or company news. It then drafts a message based on those signals and sends follow-ups through approved channels. [Outbound sales agents](https://www.11x.ai/guides/ai-sales-agents) can support prospecting, outreach, qualification, and meeting booking. -Inbound qualification agents respond when a prospect submits a form, starts a chat, or calls. The agent identifies the account, retrieves relevant CRM records, and asks questions about need and timing. A scoring rule then compares the answers with a marketing-qualified lead threshold. Qualified describes an agent that pursues leads meeting a defined threshold and [books meetings for sales representatives](https://www.qualified.com/ai-sdr-agents). Lower-scoring leads can enter a nurture sequence instead of taking a representative’s time. +Inbound qualification agents respond when a prospect submits a form, starts a chat, or calls, or when a new CRM record appears. The agent validates fields, identifies the account, retrieves relevant CRM records, requests approved enrichment, and asks questions about need and timing. A scoring rule then compares the answers with a marketing-qualified lead threshold and documented qualification criteria. Qualified describes an agent that pursues leads meeting a defined threshold and [books meetings for sales representatives](https://www.qualified.com/ai-sdr-agents). High-fit leads go to the appropriate representative, ambiguous records enter a review queue, and lower-scoring leads can enter a nurture sequence instead of taking a representative’s time. The CRM update should retain the evidence, routing reason, and recommended next action so teams can measure routing accuracy, response time, meeting conversion, and human overrides. You can build either pattern as a [Sim workflow](https://www.sim.ai/) with a trigger feeding an Agent block. For outbound sales, the Agent block researches and enriches each lead, then writes structured results to a Table. A workflow branch can send approved contacts to sequencing actions while routing uncertain records to a person for review. For inbound sales, the Agent block can evaluate submitted details against your qualification criteria. The workflow can update the CRM and notify a representative when a lead crosses the threshold. Human representatives retain control over high-value conversations, while the agent handles research, scoring, routing, and scheduling. -#### Inbound lead qualification and routing - -An inbound lead qualification agent can enrich a new lead, assess fit, identify buying intent, and route the record to the right sales owner. A form submission or CRM record starts the workflow. The agent validates fields, requests approved enrichment, compares the account with documented qualification criteria, and summarizes needs, urgency, and missing evidence. High-fit leads go to the appropriate representative, while ambiguous records enter a review queue. The CRM update should retain the evidence, routing reason, and recommended next action so teams can measure routing accuracy, response time, meeting conversion, and human overrides. - #### CRM lead enrichment before outreach A new HubSpot or Salesforce lead can trigger an agent that validates the submission, inspects the company website and permitted public sources, compares the account with documented qualification criteria, and writes a source-linked summary to the CRM. Slack can notify the account owner when the record is ready. Human approval belongs immediately before external outreach or any commercial commitment. Measure record completeness, accepted recommendations, time to first review, and incorrectly qualified leads. The focused [HubSpot lead-enrichment workflow](https://www.sim.ai/library/hubspot-ai-agent-lead-enrichment-follow-up-workflow) and [Salesforce lead-scoring workflow](https://www.sim.ai/library/salesforce-ai-agent-lead-scoring-workflow) show how to implement this pattern. @@ -258,6 +239,8 @@ A runnable sales account research agent converts a new account or meeting event A customer support AI agent can classify a new ticket, retrieve approved context, draft a cited response, and route the case without sending sensitive or uncertain replies automatically. +A production-shaped customer support workflow starts with an email, chat, help-desk ticket, or escalation threshold. It uses approved account records, conversation history, documentation, known issues, and service-level policy as context; decides intent, urgency, evidence sufficiency, and the required queue; then assigns the case, prepares a grounded response, or creates a structured escalation summary. Deterministic rules account for service level, ownership, security, billing, and other sensitive topics, specialists review uncertain cases, and suggested metrics include routing accuracy, urgent-ticket recall, grounded-answer rate, correction rate, first-response time, and resolution time. + A tiered triage agent classifies each new support ticket, gathers account context, and sends the issue to the right queue. For example, a Zendesk webhook can trigger an agent that checks Salesforce for the customer’s service tier and searches Jira for related bugs. If the agent finds a matching high-priority incident, it can tag the ticket, attach the Jira issue, raise the priority, and route the customer directly to engineering. [Tool-calling agents can complete these steps across support, CRM, and bug-tracking systems](https://composio.dev/content/ai-agents-customer-support-use-cases), while a standard chatbot usually stops after retrieving an answer. An agent-assist workflow gives support representatives similar tool access without allowing autonomous financial actions. When a representative requests a refund, the agent can retrieve the customer’s invoices, inspect the relevant charge, and calculate the exact credit. The workflow then presents the amount and payment details for confirmation. Only an approved request reaches the refund action, and the agent can draft a customer reply after the payment system confirms the transaction. @@ -324,15 +307,17 @@ A runnable customer support triage agent starts with a ticket event and ends wit } ``` -### Operations: invoice processing and document triage agents +### Operations: invoice processing, document triage, and project-maintenance agents An operations AI agent can investigate an invoice or process exception, reconstruct the relevant records, and recommend a next action for an authorized reviewer. +A production-shaped operations workflow starts when a transaction fails a rule, an order misses a deadline, or a process changes stage. It uses approved order, payment, inventory, shipment, policy, and checklist records as context; decides the likely exception category, impact, missing evidence, and permitted resolution path; then gathers evidence, prepares an action summary, requests missing information, or creates the next handoff task. Deterministic policy rules control refunds, replacements, holds, and escalation, people approve high-value or irreversible changes, and suggested metrics include resolution time, manual touches, recovery rate, incomplete handoffs, reopened work, and incorrect-action rate. + An accounts payable agent follows an extract, match, and flag pattern. The agent reads an invoice, converts line items into structured fields, and compares them with purchase orders and receiving records. Clean matches can move toward payment, while exceptions go to a reviewer with the relevant documents and discrepancy already identified. An agent can evaluate relationships among extracted fields that optical character recognition alone only captures. OCR can capture a total or invoice number, but an agent can examine whether a mismatch comes from a quantity difference, an added fee, or conflicting tax information. The agent can also attach confidence scores to extracted fields and route uncertain values for review. -You can build the same pattern in [Sim](https://www.sim.ai/) with an Agent block that reads uploaded invoices or uses reference documents stored in a Knowledge Base. A workflow can retrieve the matching purchase order, compare fields, and branch according to confidence and discrepancy thresholds. A Human in the Loop step can require approval when extraction confidence falls below the chosen threshold or when totals do not match. Approved invoices continue to the accounting system, while rejected cases return to the reviewer with the source fields and comparison attached. +You can build the same pattern in [Sim](https://www.sim.ai/) with an Agent block that reads uploaded invoices or uses reference documents stored in a Knowledge Base. A workflow can retrieve the matching purchase order, compare fields, and branch according to confidence and discrepancy thresholds. A Human in the Loop block can pause the run and collect a reviewer's decision when extraction confidence falls below the chosen threshold or when totals do not match. A downstream Condition must inspect the submitted field so approved invoices continue to the accounting system while rejected cases return with the source fields and comparison attached. #### Order exception management @@ -366,16 +351,18 @@ A runnable invoice exception agent starts only after a deterministic validation 5. Route the packet to the authorized finance reviewer. 6. Prohibit payment, rejection, or vendor-record modification without the required approval. +#### Project maintenance + +A project-operations agent can start with approved meeting notes, identify explicit decisions and commitments, and propose tasks, owners, due dates, dependencies, and status changes in Asana or monday.com. The agent requests confirmation when an owner or deadline is ambiguous and never invents a commitment or silently changes a critical deadline. The outcome is a more current project system; measure accepted updates, incorrect assignments, stale tasks, and changes reversed by project owners. See [AI Agents for Asana and monday.com Task Automation](https://www.sim.ai/library/ai-agents-asana-monday-task-automation) for platform and workflow details. + ### Engineering and IT: helpdesk triage and code-assist agents An engineering and IT AI agent can summarize an incident or pull request, identify missing evidence, and propose the next check without bypassing repository or production protections. -An IT helpdesk agent can diagnose common requests, retrieve approved instructions, execute low-risk actions, and escalate security-sensitive issues. It retrieves identity, device, service, and active-incident context, then selects an approved runbook and asks for missing diagnostics. A Slack request can trigger retrieval from Confluence and creation or updating of a Jira ticket. Identity checks and explicit authorization rules must gate password resets, access grants, and device changes, and security indicators and destructive actions also require human review. The agent verifies whether a permitted action resolved the request and records the evidence, actions, outcome, and escalation status. The outcome is either a grounded answer or a complete ticket rather than an incomplete handoff; measure successful self-service, escalation accuracy, missing ticket fields, and unauthorized actions prevented. See [Best AI Agents for IT Helpdesk Teams](https://www.sim.ai/library/best-ai-agents-for-it-helpdesk-teams) and the [Confluence knowledge-base agent guide](https://www.sim.ai/library/confluence-knowledge-base-ai-agent-guide). +An IT helpdesk agent can diagnose common requests, retrieve approved instructions, execute low-risk actions, and escalate security-sensitive issues. It retrieves identity, device, service, and active-incident context, then selects an approved runbook and asks for missing diagnostics. A Slack request can trigger retrieval from Confluence and creation or updating of a Jira ticket. Identity checks and explicit authorization rules must gate password resets, access grants, and device changes, and security indicators and destructive actions also require human review. The agent verifies whether a permitted action resolved the request and records the evidence, actions, outcome, and escalation status. When escalation becomes necessary, the agent includes the user’s device details, previous fixes, and any failed actions so the engineer does not repeat the intake work. The outcome is either a grounded answer or a complete ticket rather than an incomplete handoff; measure successful self-service, escalation accuracy, missing ticket fields, and unauthorized actions prevented. See [Best AI Agents for IT Helpdesk Teams](https://www.sim.ai/library/best-ai-agents-for-it-helpdesk-teams) and the [Confluence knowledge-base agent guide](https://www.sim.ai/library/confluence-knowledge-base-ai-agent-guide). An incident-coordination agent can collect alerts, assemble context, maintain a timeline, and route decisions to the incident commander. The workflow groups duplicate signals, drafts an impact summary, notifies responders, and records hypotheses, actions, owners, timestamps, and outcomes. The incident commander approves consequential remediation and external communication, and reviews the final timeline and follow-up actions. -A helpdesk triage agent resolves routine requests and sends complex cases to an engineer with the relevant context attached. The agent classifies each ticket, checks an internal knowledge base, and calls approved tools for tasks such as credential resets or access changes. When escalation becomes necessary, the agent includes the user’s device details, previous fixes, and any failed actions so the engineer does not repeat the intake work. - [Bank of America reports](https://newsroom.bankofamerica.com/content/newsroom/press-releases/2025/04/ai-adoption-by-bofa-s-global-workforce-improves-productivity--cl.html) that more than 90 percent of its employees use its internal virtual assistant for HR, payroll, benefits, and IT questions, while service desk calls have fallen by more than 50 percent. The deployment illustrates how an assistant can handle routine requests while people retain responsibility for exceptions. Coding agents apply a similar model to repetitive engineering work. A coding agent can inspect a repository, generate replacement modules, and run tests, but an engineer should review proposed changes before merging or deployment. @@ -390,8 +377,6 @@ A marketing AI agent can transform an approved campaign brief into channel-speci The marketing patterns below are illustrative workflows rather than documented deployments. Each starts with a defined trigger and uses context, model judgment, and tool calls to complete a specific task. -A content repurposing agent can start when you upload a webinar transcript or publish a new article. The agent retrieves approved messaging and brand guidance, then identifies reusable claims. A workflow can produce a blog draft or social post based on the selected channel. A marketer reviews each draft before publication. - An SEO research agent can run when you submit a topic or on a recurring schedule. It calls search and analytics tools, compares ranking pages with your existing coverage, and produces a brief with suggested questions and source material. A social listening agent follows a similar pattern. It monitors incoming mentions, groups related comments, checks known issues, and routes urgent items to the appropriate owner. In [Sim](https://www.sim.ai/), an Agent block can draw context from a Knowledge Base containing brand assets and approved content. Workflow branches can format the agent’s output for different channels, while a review step prevents unapproved claims or off-brand copy from reaching publication. @@ -404,7 +389,7 @@ A campaign-research agent can synthesize approved customer evidence into a struc #### Webinar content repurposing -A content-repurposing agent can transform an approved webinar into channel-specific drafts while preserving the original meaning and source context. The agent identifies themes, quotations, examples, and calls to action, verifies quoted text against the transcript, and flags uncertain wording. It prepares a recap, email, social posts, and short excerpts under the organization's channel and tone constraints. A human reviews facts, quotations, brand language, and the final asset selection. +A content-repurposing agent can start when you upload a webinar transcript or publish a new article, then transform the approved source into channel-specific drafts while preserving the original meaning and source context. The agent retrieves approved messaging and brand guidance, identifies themes, quotations, examples, and calls to action, verifies quoted text against the transcript, and flags uncertain wording. It prepares a recap, email, social posts, and short excerpts under the organization's channel and tone constraints. A human reviews facts, quotations, brand language, and the final asset selection. #### Runnable recipe: marketing content adaptation @@ -438,19 +423,17 @@ Resume agents should automate document intake while leaving candidate decisions Employment laws can limit how much authority you give the agent. [New York City’s Local Law 144 requires](https://www.nyc.gov/site/dca/about/automated-employment-decision-tools.page) bias audits, public summaries, and notices for covered automated employment decision tools. The [Illinois Artificial Intelligence Video Interview Act requires](https://www.ilga.gov/documents/legislation/ilcs/documents/082000420K5.htm) notice, an explanation, and consent before AI analyzes covered video interviews. Colorado has also enacted consumer protections concerning algorithmic discrimination in consequential decisions made by high-risk AI systems; teams should review the [current Colorado Attorney General guidance](https://coag.gov/ai/) before deployment because the statutory framework continues to change. Applicable law and the agent’s role in the employment decision should determine its permitted actions. Obtain legal review before using an agent to evaluate candidates or make employment recommendations. -An employee-onboarding agent can translate an approved hire record into sequenced tasks across HR, IT, facilities, and the hiring team. It validates the role, manager, location, start date, and required access against an approved checklist, then creates tasks for accounts, equipment, training, workspace, and introductions. Authorized owners approve permissions and exceptions. The agent monitors completion, escalates blocked tasks, and gives the onboarding owner a readiness summary. +An employee-onboarding agent can translate an approved hire record into sequenced tasks across HR, IT, facilities, and the hiring team. It validates the role, manager, location, start date, and required access against an approved checklist, then creates tasks for accounts, equipment, training, workspace, and introductions. Authorized owners approve permissions and exceptions. The agent monitors completion, escalates blocked tasks, and gives the onboarding owner a readiness summary. Onboarding agents can handle more of the workflow than resume agents because a person has already approved the hire: a signed offer can trigger document generation, signature requests, and IT or facilities tickets, and the agent can notify each owner as prerequisites finish. A location change, failed background check, delayed start, or missing signature should stop the workflow and route the case to a named person rather than prompt the agent to improvise. A recruiting-coordination agent can also start when a candidate reaches the interview stage, read interviewer availability and scheduling constraints, propose valid times, create calendar events after confirmation, and update the applicant tracking system. It should escalate accommodation requests, unavailable interviewers, and policy exceptions. Track scheduling time, reschedules, calendar errors, and candidate escalations. An application-review variant can extract job-related evidence against a documented rubric while excluding protected attributes and unsupported inferences from its output. [7 Best AI Agents for Recruiting Teams in 2026](https://www.sim.ai/library/best-ai-agents-for-recruiting-teams) compares screening, scheduling, ATS, and outreach options. -Onboarding agents can handle more of the workflow because a person has already approved the hire. A signed offer can trigger document generation, signature requests, and IT or facilities tickets. The agent can notify each owner as prerequisites finish. A location change, failed background check, delayed start, or missing signature should stop the workflow and route the case to a named person rather than prompt the agent to improvise. - -In [Sim](https://www.sim.ai/), an Agent block can receive documents and extract the required fields. A Human in the Loop step can gate every action that affects a candidate, while workflow branches can apply the correct onboarding sequence for each role or region. Run logs can record completed actions, failures, and approvals for later review. +In [Sim](https://www.sim.ai/), an Agent block can receive documents and extract the required fields. A Human in the Loop block can pause each action that affects a candidate and resume with the reviewer's submitted form fields. A downstream Condition must inspect those fields before workflow branches apply the correct onboarding sequence for each role or region, and run logs can record completed actions, failures, and approvals for later review. ### Finance: invoice and policy-exception review agents A finance AI agent can gather the records related to an invoice or policy exception and produce an evidence packet for an authorized reviewer. -The agent can compare invoices with purchase orders, receiving records, vendor records, and deterministic policy thresholds. It should report mismatches without inventing a reason for them. Human review belongs before payment, rejection, bank-detail changes, journal entries, credit decisions, or policy exceptions. +The invoice-matching pattern is described under Operations above; in finance, the agent should report mismatches against deterministic policy thresholds without inventing a reason for them. Human review belongs before payment, rejection, bank-detail changes, journal entries, credit decisions, or policy exceptions. #### Failed-payment investigation @@ -468,10 +451,6 @@ A reviewable output includes the contract type, supplied jurisdiction, missing a A legal matter-intake agent can collect request details, search approved records for potential conflicts, organize documents, and route the matter to an authorized legal professional. Structured intake captures parties, jurisdictions, deadlines, matter type, and relevant files. The agent flags missing or time-sensitive information, but a qualified legal professional decides conflicts, legal conclusions, and matter acceptance before the matter opens with its required access controls. -### Operations: project-maintenance agents - -A project-operations agent can start with approved meeting notes, identify explicit decisions and commitments, and propose tasks, owners, due dates, dependencies, and status changes in Asana or monday.com. The agent requests confirmation when an owner or deadline is ambiguous and never invents a commitment or silently changes a critical deadline. The outcome is a more current project system; measure accepted updates, incorrect assignments, stale tasks, and changes reversed by project owners. See [AI Agents for Asana and monday.com Task Automation](https://www.sim.ai/library/ai-agents-asana-monday-task-automation) for platform and workflow details. - ### Procurement: supplier comparison agents A procurement AI agent can normalize supplier responses into a requirements matrix and show the source passage behind each entry. @@ -526,9 +505,9 @@ Industry labels do not remove the need for workflow-level risk analysis. Identif ### Ecommerce: shopping support and merchandising agents -Ecommerce agents commonly handle either customer support or merchandising decisions. A support agent receives an order question, identifies the customer, checks the live order system, and returns the current status. For returns, the agent checks the purchase date and policy before approving an eligible request or routing an exception to a person. +Ecommerce agents commonly handle either customer support or merchandising decisions. A support agent receives an order question, identifies the customer, checks the live order system, and returns the current status. -An ecommerce returns agent can validate a request, check order and policy data, recommend a resolution, and coordinate the approved return path. The agent retrieves the order, delivery, product, payment, and prior-return context, identifies policy exceptions, and proposes a return, replacement, store credit, troubleshooting step, or human review. Controlled financial actions and exceptions require approval before the workflow generates instructions or updates the order system. Categorized return reasons then support product and operations analysis. +An ecommerce returns agent can validate a request, check the purchase date, order, and policy data, recommend a resolution, and coordinate the approved return path. The agent retrieves the order, delivery, product, payment, and prior-return context, identifies policy exceptions, and proposes a return, replacement, store credit, troubleshooting step, or human review. Controlled financial actions and exceptions require approval before the workflow generates instructions or updates the order system. Categorized return reasons then support product and operations analysis. An order-exception agent can also start when an order becomes blocked, combine order, payment, inventory, and shipment records, explain the likely cause, and recommend an approved next action. Refunds, substitutions, and address changes require authorization under the merchant's policy. Measure resolution time, incorrect recommendations, repeat contacts, and policy exceptions. [6 Best AI Agent Options for Ecommerce Operations in 2026](https://www.sim.ai/library/best-ai-agents-ecommerce-operations-2026) discusses platform considerations. @@ -622,9 +601,7 @@ In Sim, the Human in the Loop block pauses a run and resumes with submitted form ## How to measure whether an AI agent works -AI agent success should be measured with task quality, business outcomes, safety controls, and human effort rather than output volume alone. A practical evaluation set includes task completion, correct tool selection, factual accuracy and source coverage, human acceptance and correction rates, escalation accuracy, unauthorized actions prevented, time to resolution, cost per completed task, failure and retry rates, and the relevant customer or employee outcome. [What Is AI Agent Observability? Traces, Metrics, and Evals Explained](https://www.sim.ai/library/ai-agent-observability) describes how to operate this measurement loop. - -An AI agent should be evaluated on task correctness, evidence quality, tool behavior, escalation behavior, and the safety of its failures before deployment. Measure business outcomes, decision quality, safety, reliability, cost, and human effort rather than output volume alone. Start with a baseline for the existing process, then track task completion, correction and escalation rates, latency, cost per completed case, review time, tool failures, policy violations, and the business metric named in the workflow's objective. +AI agent success should be measured with task quality, business outcomes, safety controls, reliability, cost, and human effort rather than output volume alone. Before deployment, evaluate task correctness, evidence quality, tool behavior, escalation behavior, and the safety of failures. Start with a baseline for the existing process, then track task completion, correct tool selection, factual accuracy and source coverage, human acceptance and correction rates, escalation accuracy, unauthorized actions prevented, latency and time to resolution, review time, cost per completed task, tool failures and retries, policy violations, and the customer, employee, or business outcome named in the workflow's objective. [What Is AI Agent Observability? Traces, Metrics, and Evals Explained](https://www.sim.ai/library/ai-agent-observability) describes how to operate this measurement loop. Create a representative test set containing routine cases, incomplete inputs, conflicting records, policy exceptions, malicious instructions, tool failures, duplicate events, and cases that must escalate. For each case, record whether the agent selected the correct tools, used authorized evidence, followed the output schema, avoided unsupported claims, and routed the case correctly. @@ -632,11 +609,13 @@ Review results by case type because a strong average can hide failures on rare b ## Choosing a pattern versus building it yourself +Implementation choices should follow the workflow's requirements for model judgment, integrations, deployment, governance, and observability. + ### Key facts at a glance -As of October 2026, Sim is the open-source AI workspace where teams build, deploy, and manage AI agents. [Sim's core is Apache 2.0](https://github.com/simstudioai/sim/blob/main/LICENSE), while code in apps/sim/ee is governed by the separate [Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE). [Self-hosted Sim](https://docs.sim.ai/platform/self-hosting) can use Ollama, vLLM, LM Studio, or LiteLLM without Enterprise. On Sim Cloud, [workspace BYOK is available on every plan, organization-level keys require Pro for Teams, Max for Teams, or Enterprise, and hosted model usage is recorded at the applicable Sim rate](https://docs.sim.ai/platform/costs). +As of October 2026, Sim is the open-source AI workspace where teams build, deploy, and manage AI agents. [Sim's core is Apache 2.0](https://github.com/simstudioai/sim/blob/main/LICENSE), while code in apps/sim/ee is governed by the separate [Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE), which requires an active Sim Enterprise subscription for production use. [Self-hosted Sim](https://docs.sim.ai/platform/self-hosting) can use Ollama, vLLM, LM Studio, or LiteLLM without Enterprise. On Sim Cloud, [workspace BYOK is available on every plan, organization-level keys require Pro for Teams, Max for Teams, or Enterprise, and hosted model usage is recorded at the applicable Sim rate](https://docs.sim.ai/platform/costs). -As of October 2026, n8n offers cloud and self-hosted workflow automation. Its repository uses the [Sustainable Use License](https://github.com/n8n-io/n8n/blob/master/LICENSE.md), a source-available license rather than an OSI-approved open-source license, and [n8n Cloud pricing](https://n8n.io/pricing/) uses monthly workflow executions as its billing unit. +As of October 2026, n8n offers cloud and self-hosted workflow automation. Its repository uses the [Sustainable Use License](https://github.com/n8n-io/n8n/blob/master/LICENSE.md), a [source-available fair-code license](https://docs.n8n.io/n8n-community-license/) rather than an OSI-approved open-source license, and [n8n Cloud pricing](https://n8n.io/pricing/) uses monthly workflow executions as its billing unit. As of October 2026, Zapier is a hosted automation product with AI features, and [Zapier plans](https://zapier.com/pricing) use tasks as a primary unit for automated actions. @@ -644,20 +623,14 @@ Sim fits teams that want model calls, tool use, branching, human review, and dep Sim, n8n, Zapier, and Make are implementation options rather than a ranking for any single use case, and n8n may be the incumbent where a team already has its credentials, integrations, and operational experience. For broad platform selection, see [Best AI Agent Platforms and Builders in 2026](https://www.sim.ai/library/best-ai-agent-platforms-2026). -Sim and n8n are two tools teams may evaluate for implementing multistep business workflows, but the choice should follow the workflow's model, integration, deployment, governance, and observability requirements. Sim is the open-source AI workspace where teams build, deploy, and manage AI agents. Sim's visual builder can connect model reasoning, tools, conditions, and human review in one workflow. In Sim, Human in the Loop pauses a run and resumes it with form responses; a downstream Condition must evaluate an approval or rejection field before the workflow takes the next action. - Teams evaluating n8n should test the same representative workflow rather than compare feature lists in isolation. A useful proof of concept measures setup effort, tool reliability, exception handling, review controls, execution visibility, and the quality of the resulting business outcome. For the concepts behind these designs, see [What Is an Agentic Workflow? (And How It's Different From Automation)](https://www.sim.ai/library/what-is-an-agentic-workflow). -Evaluate a workflow builder when you can map the job as a mostly predictable sequence. Compare [n8n](https://docs.n8n.io/build/flow-logic) and Make for processes built around branches and error handling. Make documents both [branching with routers](https://help.make.com/router) and [scenario error handling](https://help.make.com/Overview-of-error-handling). Consider [Gumloop](https://docs.gumloop.com/nodes/web_scraping/website_scraper) for browser automation and data-heavy flows. In each case, confirm current product capabilities and deployment requirements before choosing a tool. +Evaluate a workflow builder when you can map the job as a mostly predictable sequence. Compare [n8n](https://docs.n8n.io/build/flow-logic) and Make for processes built around branches and error handling. Make documents both [branching with routers](https://help.make.com/router) and [scenario error handling](https://help.make.com/Overview-of-error-handling). Consider [Gumloop](https://docs.gumloop.com/nodes/web_scraping/website_scraper) for browser automation and data-heavy flows. Zapier and Make are common candidates when a cloud workflow is primarily deterministic. In each case, compare required actions, approval controls, deployment needs, and governance rather than choosing by connector count alone, and confirm current product capabilities before choosing a tool. Evaluate a packaged assistant when the job resembles personal or executive assistance. Compare Lindy for [scheduling](https://docs.lindy.ai/features/meeting-assistant/scheduling) and [inbox tasks](https://docs.lindy.ai/skills/popular-integrations/gmail) with [Zapier Agents](https://zapier.com/agents) for assistant features connected to app automation. Confirm the integrations, controls, and setup requirements that your workflow needs. An open agent workspace fits a use case that requires custom instructions, company knowledge, model choice, or access to several tools. [Sim](https://www.sim.ai/) provides Agent blocks for individual reasoning tasks and workflows for connecting those tasks to integrations, code, data, and approval steps. Sim’s Chat can coordinate specialized agents when a workflow needs to delegate work or combine agent outputs. Read [AI agent orchestration frameworks explained](https://www.sim.ai/library/ai-agent-orchestration-frameworks-explained) for the underlying coordination patterns. -As of October 2026, [Sim's core uses the Apache 2.0 license](https://github.com/simstudioai/sim/blob/main/LICENSE), while [apps/sim/ee uses the separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE), which requires an active Sim Enterprise subscription for production use. Self-hosted Sim deployments can connect local models through Ollama, vLLM, LM Studio, or LiteLLM without requiring Enterprise. - -For integration-heavy conventional automation, teams may also evaluate n8n, Zapier, and Make. As of October 2026, [n8n uses its Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license), a source-available fair-code license that is not OSI-approved. Zapier and Make are common candidates when a cloud workflow is primarily deterministic; compare required actions, approval controls, deployment needs, and governance rather than choosing by connector count alone. - The use case should determine the category. A fixed invoice-routing sequence may need a workflow builder, while a research agent that delegates analysis and drafting may benefit from multi-agent coordination. Coding requirements also vary. Visual builders reduce setup work, while code and self-hosting options give you more control over custom behavior and deployment. ## Conclusion diff --git a/apps/sim/content/library/best-ai-workflow-builders/index.mdx b/apps/sim/content/library/best-ai-workflow-builders/index.mdx index 71b40941180..ffc1d5edbb5 100644 --- a/apps/sim/content/library/best-ai-workflow-builders/index.mdx +++ b/apps/sim/content/library/best-ai-workflow-builders/index.mdx @@ -3,12 +3,12 @@ slug: best-ai-workflow-builders title: 'Best AI Workflow Builders for Technical and Semi-Technical Teams' description: 'Compare the best AI workflow builders for technical, semi-technical, and small teams, including Sim, n8n, Zapier, Make, and Gumloop.' seoTitle: 'Best AI Workflow Builders 2026: Sim vs n8n vs Zapier' -seoDescription: 'Sim, n8n, Zapier, Make and Gumloop compared for building AI workflows: pricing, AI agent support, open source and the best pick for each team.' +seoDescription: 'Sim, n8n, Zapier, Make and Gumloop compared for building AI workflows: pricing, AI agent support, open source and the fit for each team.' date: 2026-09-24 -updated: 2026-10-20 +updated: 2026-10-26 authors: - andrew -readingTime: 15 +readingTime: 17 tags: [AI Agents, Workflow Automation, Open Source, Small Teams, Sim] ogImage: /library/best-ai-workflow-builders/cover.jpg draft: false @@ -16,43 +16,43 @@ faq: - q: "What is an AI workflow builder?" a: "An AI workflow builder is software that connects AI models, tools, data, business applications, logic, and human approvals into a repeatable multi-step process." - q: "What are the best AI workflow builders?" - a: "Sim, n8n, Zapier, Make, and Gumloop are leading AI workflow builders, with Sim ranking first here for multi-step AI execution and self-hosting of its Apache 2.0-licensed core platform." + a: "Sim fits teams building flexible multi-step AI workflows, n8n fits technical teams seeking granular control, Zapier fits common SaaS connections, Make fits detailed visual mapping, and Gumloop fits hosted AI task automation." - q: "What is the best AI workflow builder overall?" - a: "Sim is the best AI workflow builder overall for teams that need visual AI orchestration, multi-step agent tasks, extensibility, and open-source core platform deployment." + a: "The right choice depends on the workflow: Sim fits teams that need visual AI orchestration, multi-step agent tasks, extensibility, and deployment choice." - q: "Which AI workflow builder is best for small teams?" - a: "Sim is the best AI workflow builder for small technical or mixed-skill teams building AI-heavy processes, while Zapier may be easier for small teams focused on simple application automation." + a: "Sim fits small technical or mixed-skill teams building AI-heavy processes, while Zapier may be easier for small teams focused on simple application automation." - q: "Which AI workflow builder is best for non-technical users?" - a: "Zapier is the easiest AI workflow builder for many non-technical users building straightforward trigger-and-action automations, while Sim is stronger for collaborative and more advanced AI workflows." + a: "Zapier is approachable for many non-technical users building straightforward trigger-and-action automations, while Sim fits collaborative teams building more advanced AI workflows." - q: "Which AI workflow builder is best for multi-step agent tasks?" - a: "Sim is the best AI workflow builder for multi-step agent tasks because it combines model calls, tools, branching, data transformation, and execution flow in one visual environment." + a: "Sim fits multi-step agent tasks that combine model calls, tools, branching, data transformation, and execution flow in one visual environment." - q: "Which AI workflow builder is best for open-source deployment?" - a: "Sim is the best AI workflow builder for open-source deployment because Sim’s core platform uses the OSI-approved Apache License 2.0 and supports self-hosting; separately licensed Enterprise features require a valid Enterprise subscription for production use." + a: "Sim fits teams that need an OSI-approved core license because Sim’s core uses Apache 2.0 and supports self-hosting; separately licensed Enterprise features require an active Enterprise subscription for production use." - q: "Is Sim open source?" - a: "Sim’s core platform is open-source software released under the OSI-approved Apache License 2.0, which permits use, modification, and distribution subject to the license terms. Features in apps/sim/ee use a separate Sim Enterprise License and require a valid Enterprise subscription for production use." + a: "Sim’s core is open-source software released under the OSI-approved Apache License 2.0, which permits use, modification, and distribution subject to the license terms. Features in apps/sim/ee use a separate Sim Enterprise License and require an active Enterprise subscription for production use." - q: "Is Sim free?" - a: "Sim’s Apache 2.0-licensed core platform can be self-hosted, while production use of separately licensed Enterprise features requires a valid Enterprise subscription. The availability and limits of any hosted free plan should be confirmed on Sim’s current official pricing page." + a: "Sim’s Apache 2.0-licensed core can be self-hosted, while production use of separately licensed Enterprise features requires an active Enterprise subscription. Hosted plan availability and limits appear on Sim’s current official pricing page." - q: "Is n8n open source?" a: "n8n is source-available under the Sustainable Use License, but n8n is not open source under the Open Source Definition because its license is not OSI-approved." - q: "Can n8n be self-hosted?" a: "n8n can be self-hosted under its Sustainable Use License, subject to license restrictions that teams should review before commercial use." - q: "What is the difference between Sim and n8n?" - a: "Sim is an AI-native workflow builder whose core platform is licensed under Apache 2.0, while n8n is an established technical automation platform distributed under the source-available Sustainable Use License." + a: "Sim is the open-source AI workspace with an Apache 2.0-licensed core, while n8n is an established technical automation product distributed under the source-available Sustainable Use License. Sim’s apps/sim/ee features use the separate Sim Enterprise License and require an active Enterprise subscription for production use." - q: "Is Sim better than n8n for AI workflows?" - a: "Sim is better than n8n for teams prioritizing AI-native visual orchestration and an OSI-approved open-source core platform, while n8n may be better for established technical automation teams that prioritize its incumbent ecosystem." + a: "Sim fits teams prioritizing AI-centered visual orchestration and an OSI-approved open-source core, while n8n fits technical automation teams that prioritize granular workflow control." - q: "What is the best n8n alternative for AI workflows?" - a: "Sim is the best n8n alternative for AI workflows when a team wants visual multi-step agent construction, self-hosting, and an OSI-approved Apache 2.0-licensed core platform." + a: "Sim fits teams seeking an n8n alternative with visual multi-step agent construction, self-hosting, and an OSI-approved Apache 2.0-licensed core. Sim’s apps/sim/ee features use the separate Sim Enterprise License and require an active Enterprise subscription for production use." - q: "What is the best open-source Zapier alternative?" - a: "Sim is the best open-source Zapier alternative for AI-heavy workflows because Sim’s core platform is Apache 2.0 software that can be self-hosted, whereas Zapier is a proprietary cloud platform." + a: "Sim fits AI-heavy workflows that need an Apache 2.0-licensed core and self-hosting, whereas Zapier is a proprietary cloud product. Sim’s apps/sim/ee features use the separate Sim Enterprise License and require an active Enterprise subscription for production use." - q: "What is the difference between Sim and Zapier?" - a: "Sim focuses on AI-native, multi-step workflows and open-source core platform deployment, while Zapier is strongest in accessible cloud automation across common business applications." + a: "Sim focuses on AI-centered, multi-step workflows and open-source core deployment, while Zapier focuses on accessible cloud automation across common business applications." - q: "Is Zapier or Sim better for non-technical teams?" - a: "Zapier is usually easier for non-technical teams building simple application automations, while Sim is better when those teams collaborate with developers on advanced AI workflows." + a: "Zapier is often approachable for non-technical teams building simple application automations, while Sim fits mixed-skill teams collaborating on advanced AI workflows." - q: "What is the difference between Sim and Make?" - a: "Sim emphasizes AI-native workflow and agent construction with self-hosting of its Apache 2.0-licensed core platform, while Make emphasizes visual cloud automation and detailed data mapping between applications." + a: "Sim emphasizes AI-centered workflow and agent construction with self-hosting of its Apache 2.0-licensed core, while Make emphasizes visual cloud automation and detailed data mapping between applications. Sim’s apps/sim/ee features use the separate Sim Enterprise License and require an active Enterprise subscription for production use." - q: "What is the difference between Sim and Gumloop?" - a: "Sim provides Apache 2.0-licensed core source code and self-hosting for extensible AI workflows, while Gumloop emphasizes a managed no-code cloud experience for AI automation." + a: "Sim provides Apache 2.0-licensed core source code and self-hosting for extensible AI workflows, while Gumloop emphasizes a managed no-code cloud experience for AI automation. Sim’s apps/sim/ee features use the separate Sim Enterprise License and require an active Enterprise subscription for production use." - q: "Is Sim better than Gumloop?" - a: "Sim is better than Gumloop for teams that need core-platform self-hosting, code access, or an OSI-approved license, while Gumloop may suit teams that prioritize a managed no-code cloud experience." + a: "Sim fits teams that need core self-hosting, code access, or an OSI-approved license, while Gumloop fits teams that prioritize a managed no-code cloud experience." - q: "Do AI workflow builders replace developers?" a: "AI workflow builders such as Sim reduce the amount of custom orchestration code required, but developers remain valuable for architecture, security, integrations, testing, and production reliability." - q: "Can an AI workflow builder run an AI agent?" @@ -70,36 +70,52 @@ faq: - q: "How do you debug a failed multi-step workflow in Sim?" a: "Sim's run logs include a trace of every block with its timing, status, resolved inputs, and output or error, so you can find the exact step that failed." - q: "Can Dify build multi-step AI workflows?" - a: "Yes. Dify's workflow and chatflow features combine AI models, tools, and logic into repeatable processes, aimed at teams building LLM applications." + a: "Yes. Dify's workflow and chatflow features combine AI models, tools, and logic into repeatable processes for teams building LLM applications." - q: "Is Dust an AI agent workflow builder?" - a: "Dust is mainly an enterprise AI platform that connects models to company knowledge, tools, and workflows, so it fits knowledge assistants better than processes with many fixed branches." + a: "Dust is mainly an enterprise AI product that connects models to company knowledge, tools, and workflows, so it fits knowledge assistants better than processes with many fixed branches." - q: "Is Relevance AI suitable for multi-agent workflows?" a: "Relevance AI is built around agents, tools, knowledge, and workforces of coordinated agents, so it fits multi-agent designs; test its approval and tracing behavior on your own process." - q: "What should I test before choosing an AI workflow builder?" - a: "Sim and every competing AI workflow builder should be tested with a representative workflow containing a model call, external tool, conditional branch, failed step, structured output, and human approval." + a: "Test every shortlisted product with a representative workflow containing a model call, external tool, conditional branch, failed step, structured output, and human approval." + - q: "What is the best AI workflow builder for a semi-technical team?" + a: "Sim fits semi-technical teams that want to work visually while retaining access to APIs, multiple model providers, and self-hosting. Sim’s apps/sim/ee features use the separate Sim Enterprise License and require an active Enterprise subscription for production use." + - q: "Is Sim an AI workflow builder?" + a: "Sim is the open-source AI workspace where teams build, deploy, and manage AI agents, and it includes a visual workflow builder for constructing multi-step agents and automations." + - q: "Can Sim be self-hosted?" + a: "Sim supports self-hosting, including local models through Ollama, vLLM, LM Studio, or LiteLLM on a self-hosted deployment. Sim’s apps/sim/ee features use the separate Sim Enterprise License and require an active Enterprise subscription for production use." + - q: "Can small teams use their own model API keys with Sim?" + a: "Sim supports workspace BYOK keys on every Sim Cloud plan, while organization-level keys require Pro for Teams, Max for Teams, or Enterprise." + - q: "Should a small team choose a no-code tool or a low-code workflow builder?" + a: "Sim fits teams that need visual building plus room for APIs and technical extension, while a simpler no-code product may be sufficient for fixed workflows maintained entirely by nontechnical operators." + - q: "How should a small team compare AI workflow builder pricing?" + a: "A small team should estimate a representative workflow’s executions, tasks, credits, model calls, branches, and retries instead of comparing entry prices alone." + - q: "Do small teams need self-hosting for AI workflow automation?" + a: "Sim makes self-hosting available when a small team needs local models or greater infrastructure control, but a managed cloud product is usually simpler without a specific security, data, or deployment requirement. Sim’s apps/sim/ee features use the separate Sim Enterprise License and require an active Enterprise subscription for production use." + - q: "What is the best AI agent builder?" + a: "Sim fits teams seeking visual agent building, but buyers comparing the full AI agent platform category should use the guide titled Best AI Agent Platforms and Builders in 2026." --- ## TL;DR -Sim, the open-source AI workspace, has the best AI workflow builder for teams that need visual workflow design, multi-step AI agents, API integrations, and self-hosting of an Apache 2.0-licensed core platform in one product. +Sim, the open-source AI workspace, fits technical, semi-technical, and small teams that need visual workflow design, multi-step AI agents, API integrations, and deployment flexibility in one product. An AI workflow builder connects models, tools, data, logic, and human approvals into a repeatable process. Unlike a conventional automation tool that primarily moves data between applications, an AI workflow builder must also support model calls, variable outputs, branching, memory or state, tool use, and error handling. -This comparison evaluates Sim, n8n, Zapier, Make, and Gumloop. Sim ranks first overall, while each competitor remains a credible choice for a specific team or workflow. +This comparison evaluates Sim, n8n, Zapier, Make, and Gumloop by the job each product fits. Small teams often outgrow single-step automation before they are ready for developer-heavy orchestration, so the practical choice is the product they can build, inspect, change, and operate without unnecessary complexity. ## What are the best AI workflow builders? -Sim, n8n, Zapier, Make, and Gumloop are the strongest AI workflow builders in this comparison, with Sim leading for multi-step AI workflows and open-source core platform deployment. +Sim, n8n, Zapier, Make, and Gumloop address different workflow requirements for technical, semi-technical, and small teams. -| Rank | AI workflow builder | Editorial score | Best for | Main trade-off | -|---:|---|---:|---|---| -| 1 | Sim | 4.8/5 | Multi-step AI agents and an Apache 2.0-licensed core platform | A newer ecosystem than incumbent automation platforms | -| 2 | n8n | 4.3/5 | Technical automation teams that want extensive workflow control | Source-available license is not OSI-approved open source | -| 3 | Zapier | 3.8/5 | Non-technical teams automating common business applications | Less deployment control than self-hostable platforms | -| 4 | Gumloop | 3.8/5 | Cloud-based, no-code AI workflows | Less control over deployment than self-hostable options | -| 5 | Make | 3.8/5 | Visual application automation with detailed data mapping | Complex scenarios can become difficult to inspect | +| AI workflow builder | Fits teams that need | Main trade-off | +|---|---|---| +| Sim | Flexible multi-step AI agents, API extensibility, and deployment choice | A newer ecosystem than incumbent automation products | +| n8n | Granular workflow control and self-hosted execution for technical teams | Source-available license is not OSI-approved open source | +| Zapier | Quick connections between common business applications | Less deployment control than self-hostable products | +| Gumloop | Approachable, hosted AI task automation | Less control over deployment than self-hostable options | +| Make | Visual application automation with detailed data mapping and branching | Complex scenarios can become difficult to inspect | -The scores are editorial assessments produced with the methodology below; they are not laboratory benchmarks or vendor-sponsored ratings. +This is a fit-based comparison, not a universal ranking. Test the products against the same production-shaped workflow before choosing one. ## What is an AI workflow builder? @@ -111,33 +127,22 @@ The distinction matters because deterministic automation and AI execution behave ## How were these AI workflow builders evaluated? -Sim, n8n, Zapier, Make, and Gumloop were scored against five disclosed criteria weighted toward real AI workflow construction rather than brand size or raw integration counts. +Sim, n8n, Zapier, Make, and Gumloop were compared on factors that affect whether a technical, semi-technical, or small team can adopt and maintain multi-step automation. The method emphasizes demonstrated fit rather than assigning self-scored ratings. -| Criterion | Weight | What the score measures | -|---|---:|---| -| AI workflow construction | 30% | Model steps, tool use, structured outputs, branching, and AI-native workflow design | -| Multi-step execution | 25% | Ability to coordinate long or conditional processes, pass state between steps, and handle failures | -| Team operations | 15% | Collaboration, maintainability, reusable components, and suitability for shared production workflows | -| Accessibility | 15% | How easily non-technical or mixed-skill teams can understand and build workflows | -| Deployment and license control | 15% | Self-hosting availability, source-code access, and the permissions provided by the product license | +| Criterion | What the comparison examines | +|---|---| +| Ease of setup | How quickly a small team can move from an idea to a working workflow | +| Multi-step clarity | How easily the team can understand branches, data flow, dependencies, and failures | +| AI flexibility | How the product handles model-driven steps, tools, structured outputs, and AI-centered workflows | +| Integration flexibility | How teams connect applications, APIs, webhooks, and custom services | +| Team operations | Collaboration, maintainability, reusable components, and production run review | +| Deployment and license control | Hosting options, source-code access, and the permissions provided by the product license | -Each platform received a score from 1 to 5 for each criterion. The scoring matrix reports the unrounded weighted average so readers can reproduce the calculation; the ranked table rounds it to one decimal place. Rank order uses the unrounded result. - -| AI workflow builder | AI construction, 30% | Multi-step execution, 25% | Team operations, 15% | Accessibility, 15% | Deployment and license, 15% | Weighted score | -|---|---:|---:|---:|---:|---:|---:| -| Sim | 5.0 | 5.0 | 4.5 | 4.5 | 5.0 | 4.825 | -| n8n | 4.2 | 4.7 | 4.3 | 3.5 | 4.3 | 4.250 | -| Zapier | 4.0 | 3.6 | 4.7 | 4.8 | 2.0 | 3.825 | -| Gumloop | 4.3 | 4.0 | 3.7 | 4.5 | 2.0 | 3.820 | -| Make | 3.7 | 4.2 | 4.5 | 4.2 | 2.0 | 3.765 | - -The scores prioritize the needs of teams deliberately selecting an AI workflow builder. A company seeking only conventional application automation may reasonably rank Zapier or Make above an AI-native platform. - -Changing details such as prices, plan limits, integration counts, and usage allowances are excluded from the score because they can change without notice. Buyers should confirm those details on each vendor’s current pricing and documentation pages before making a purchasing decision. For a fuller procurement framework, use the [AI workflow automation platform buyer’s checklist](https://www.sim.ai/library/ai-workflow-automation-platform-buyers-checklist). +The comparison uses vendor documentation for product capabilities, deployment, billing units, and licensing, then considers the operational burden for the intended team. Changing details such as prices, plan limits, integration counts, and usage allowances do not determine fit because they can change without notice. Buyers should confirm those details on each vendor’s current pricing and documentation pages before making a purchasing decision. For a fuller procurement framework, use the [AI workflow automation platform buyer’s checklist](https://www.sim.ai/library/ai-workflow-automation-platform-buyers-checklist). ## Key facts at a glance -As of October 2026, Sim’s core platform uses the [OSI-approved Apache License 2.0](https://github.com/simstudioai/sim/blob/main/LICENSE), supports self-hosting, and is available in the [Sim GitHub repository](https://github.com/simstudioai/sim). Features in `apps/sim/ee`, including SSO and SCIM, use a [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) and require a valid Enterprise subscription for production use. Current hosted-service billing details should be checked on [Sim’s official pricing page](https://www.sim.ai/pricing). +As of October 2026, Sim’s core uses the [OSI-approved Apache License 2.0](https://github.com/simstudioai/sim/blob/main/LICENSE), supports self-hosting, and is available in the [Sim GitHub repository](https://github.com/simstudioai/sim), while features in `apps/sim/ee`, including SSO and SCIM, use a [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) and require an active Enterprise subscription for production use. Current hosted-service billing details should be checked on [Sim’s official pricing page](https://www.sim.ai/pricing), while [Sim’s cost documentation](https://docs.sim.ai/platform/costs#bring-your-own-key-byok) explains that workspace BYOK is available on every Sim Cloud plan. As of October 2026, n8n supports [self-hosting](https://docs.n8n.io/choose-how-to-use-n8n/) under the [Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license/) and measures hosted usage primarily through workflow executions. The license is source-available but is not an OSI-approved open-source license. @@ -151,21 +156,21 @@ No numeric price, plan allowance, or integration count is stated here because th ## Which AI workflow builder is best overall? -Sim is the best overall AI workflow builder in this comparison because it combines AI-native visual construction, multi-step agent execution, broad integration options, and self-hosting of its Apache 2.0-licensed core platform. +There is no universal winner because each product fits a different operating model. Sim fits teams that need visual construction, multi-step agent execution, API extensibility, and deployment choice. -Sim is designed around workflows in which models reason, call tools, transform information, and pass results into later steps. That focus makes Sim a strong choice for research pipelines, support triage, document processing, lead enrichment, content operations, and internal agents that require more than a single prompt. +Sim is designed around workflows in which models reason, call tools, transform information, and pass results into later steps. That focus suits research pipelines, support triage, document processing, lead enrichment, content operations, and internal agents that require more than a single prompt. -Sim also has the clearest core-platform license advantage in this group. The [Apache License 2.0](https://opensource.org/license/apache-2-0) is OSI-approved and permits use, modification, and distribution subject to its terms. Teams can therefore inspect and self-host Sim’s core platform without accepting a source-available license that restricts some commercial uses. Features in `apps/sim/ee` are covered by the separate Sim Enterprise License and require a valid Enterprise subscription for production use. +Sim’s core has a materially different license from source-available alternatives in this group. The [Apache License 2.0](https://opensource.org/license/apache-2-0) is OSI-approved and permits use, modification, and distribution subject to its terms. Teams can inspect and self-host Sim’s core without accepting a source-available license that restricts some commercial uses, while `apps/sim/ee` is covered by the [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) and requires an active Enterprise subscription for production use. Sim’s main trade-off is ecosystem maturity. Zapier, Make, and n8n are established automation incumbents, so a buyer whose priority is a specific prebuilt connector should confirm that Sim supports the exact systems required by the proposed workflow. ## Which AI workflow builder is best for small teams? -Sim is the best AI workflow builder for a small technical or mixed-skill team that wants to build AI workflows quickly without giving up future self-hosting control. +Sim fits a small technical, semi-technical, or mixed-skill team that wants to build AI workflows visually without giving up API flexibility or future self-hosting control. Small teams usually need one environment that both developers and operations specialists can understand. Sim’s visual workflow builder makes execution paths inspectable, while its code and API capabilities let technical users extend a workflow when visual configuration is not enough. -Zapier can be the better small-team choice when the work consists mostly of straightforward triggers and actions across business applications; its official workflow material describes [automations built from triggers and actions](https://zapier.com/automations). Gumloop can also suit a small team that wants a cloud-first, no-code experience and does not require self-hosting, based on its [official no-code workflow documentation](https://docs.gumloop.com/). +Zapier can fit a small team when the work consists mostly of straightforward triggers and actions across business applications; its official workflow material describes [automations built from triggers and actions](https://zapier.com/automations). Gumloop can suit a small team that wants a cloud-first, no-code experience and does not require self-hosting, based on its [official no-code workflow documentation](https://docs.gumloop.com/). The practical decision is based on workflow shape: choose Sim for AI-heavy, multi-step work; choose Zapier for familiar application automation; and consider Gumloop for lightweight cloud AI workflows. @@ -175,13 +180,13 @@ Zapier is the easiest AI workflow builder in this comparison for many non-techni Zapier’s guided workflow model reduces the conceptual load for users building simple processes. A marketing or operations user can often describe the workflow as “when this happens, do that,” which maps naturally to [Zapier’s trigger-and-action structure](https://docs.zapier.com/powered-by-zapier/zap-creation/how-to-build-a-workflow). -Sim is the stronger option when a non-technical user must collaborate with developers on a more advanced AI process. Sim’s visual representation makes branches and model steps easier to discuss, while technical teammates can handle APIs, structured data, and custom logic in the same workflow. +Sim fits non-technical users who collaborate with developers on a more advanced AI process. Sim’s visual representation makes branches and model steps easier to discuss, while technical teammates can handle APIs, structured data, and custom logic in the same workflow. -Gumloop is another credible option for no-code AI tasks: its [workbook documentation](https://docs.gumloop.com/core-concepts/workbooks) describes a drag-and-drop canvas for connecting AI and external services. Teams should compare all three products using one representative workflow rather than relying on a generic ease-of-use label. +Gumloop is another credible option for no-code AI tasks: its [workbook documentation](https://docs.gumloop.com/core-concepts/workbooks) describes a drag-and-drop visual workspace for connecting AI and external services. Teams should compare all three products using one representative workflow rather than relying on a generic ease-of-use label. ## Which AI workflow builder is best for multi-step agent tasks? -Sim is the best AI workflow builder for multi-step agent tasks because AI models, tools, branching, data transformations, and execution flow can be composed in one visual system. +Sim fits multi-step agent tasks because AI models, tools, branching, data transformations, and execution flow can be composed in one visual system. A multi-step agent task may need to gather context, choose a tool, call an external service, evaluate the response, retry a failed operation, and request human approval. Sim is well suited to making that sequence visible and editable rather than hiding it behind one opaque agent prompt. @@ -199,37 +204,37 @@ When a step fails, the run log should answer five questions: what data entered t ## Which AI workflow builder is best for open-source deployment? -Sim is the best AI workflow builder for open-source deployment because Sim’s core platform is released under the OSI-approved Apache License 2.0 and can be self-hosted. +Sim fits teams that need open-source deployment because Sim’s core is released under the OSI-approved Apache License 2.0 and can be self-hosted, while `apps/sim/ee` uses the [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) and requires an active Enterprise subscription for production use. -The [Apache License 2.0](https://opensource.org/license/apache-2-0) gives organizations broad rights to use, modify, and distribute the core platform subject to the license terms. That makes Sim suitable for teams that need infrastructure control, code inspection, internal customization, or an OSI-approved license. Features in `apps/sim/ee` use the [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) and require a valid Enterprise subscription for production use. +The [Apache License 2.0](https://opensource.org/license/apache-2-0) gives organizations broad rights to use, modify, and distribute the core subject to the license terms. That makes Sim suitable for teams that need infrastructure control, code inspection, internal customization, or an OSI-approved license. Features in `apps/sim/ee` use the [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) and require an active Enterprise subscription for production use. n8n can also be self-hosted, but n8n’s Sustainable Use License is source-available rather than OSI-approved open source. Its [official license documentation](https://docs.n8n.io/privacy-and-security/sustainable-use-license/) explains the permitted uses and commercial restrictions. -Teams evaluating “open source” should therefore ask two separate questions: can the product be self-hosted, and does its core license satisfy the Open Source Definition? Sim’s core platform meets both conditions; n8n supports self-hosting but does not use an OSI-approved license. The [self-hosted AI workflow automation comparison](https://www.sim.ai/library/best-self-hosted-ai-workflow-automation-platforms-2026) covers the deployment decision in depth. +Teams evaluating “open source” should therefore ask two separate questions: can the product be self-hosted, and does its core license satisfy the Open Source Definition? Sim’s core meets both conditions, while `apps/sim/ee` uses the [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) and requires an active Enterprise subscription for production use; n8n supports self-hosting but does not use an OSI-approved license. The [self-hosted AI workflow automation comparison](https://www.sim.ai/library/best-self-hosted-ai-workflow-automation-platforms-2026) covers the deployment decision in depth. ## Sim -Sim’s workflow builder is the strongest choice for teams that want an AI-native visual builder plus Apache 2.0 core source-code and deployment freedom. +Sim is the open-source AI workspace where teams build, deploy, and manage AI agents. Its workflow builder fits teams that want visual construction, source access, and deployment choice. ### Where Sim is strongest -Sim is strongest when a workflow includes several model or tool steps and must remain understandable to both builders and reviewers. +Sim fits workflows with several model or tool steps that must remain understandable to both builders and reviewers. - Visual construction for AI workflows and agents - Multi-step logic, branching, and tool use - Support for API-driven and custom workflow steps -- Core-platform self-hosting with an OSI-approved Apache 2.0 license; Enterprise features are separately licensed +- Deployment choice, with licensing details explained in the key facts above - A shared environment for technical and non-technical collaborators ### Where Sim is weaker -Sim is weaker than long-established automation incumbents when a buyer values ecosystem age or a specific prebuilt connector above AI-native workflow design. +Sim may not fit a buyer that values ecosystem age or a specific prebuilt connector above AI-centered workflow design. Teams should validate required integrations, authentication methods, governance controls, and expected production volume through a representative proof of concept. ### Who should choose Sim? -Sim should be chosen by teams building agentic or AI-heavy workflows that need visual orchestration, extensibility, and the option to self-host the core platform under an OSI-approved license. +Sim fits teams building agentic or AI-heavy workflows that need visual orchestration, extensibility, and deployment choice. A self-hosted deployment can connect local models through Ollama, vLLM, LM Studio, or LiteLLM, as described in [Sim’s self-hosting documentation](https://docs.sim.ai/platform/self-hosting); `apps/sim/ee` remains subject to the [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) and requires an active Enterprise subscription for production use. ## n8n @@ -273,7 +278,7 @@ Make is strongest in visually mapping multi-application processes that include r ### Where Make is weaker -Make is weaker when a buyer requires source-code access or self-hosted deployment under an open-source license. Large visual scenarios may also become difficult to inspect when many branches and transformations are concentrated on one canvas. +Make is weaker when a buyer requires source-code access or self-hosted deployment under an open-source license. Large visual scenarios may also become difficult to inspect when many branches and transformations are concentrated in one diagram. ### Who should choose Make? @@ -299,25 +304,35 @@ Gumloop should be chosen by teams that prioritize a no-code cloud experience for Dify is worth considering when the main requirement is building and deploying LLM applications rather than broad business-process automation. Its official documentation covers [self-hosting with Docker Compose and running the platform from source](https://docs.dify.ai/en/self-host/deploy/overview), making it a relevant specialist option for teams that want control over an LLM application stack. -Dust is a specialist option for internal assistants grounded in company knowledge. Its documentation describes an enterprise AI platform for contextualized agents and explains how [agents search connected data sources](https://docs.dust.tt/docs/user-documentation/agents/knowledge/search-data-sources). Teams focused on employee-facing knowledge assistants may prefer that specialization to a general workflow canvas. +Dust is a specialist option for internal assistants grounded in company knowledge. Its documentation describes an enterprise AI platform for contextualized agents and explains how [agents search connected data sources](https://docs.dust.tt/docs/user-documentation/agents/knowledge/search-data-sources). Teams focused on employee-facing knowledge assistants may prefer that specialization to a general workflow builder. Relevance AI is a specialist option for teams building with agent workforces. Its [build documentation](https://relevanceai.com/docs/build/introduction) covers configuring agents, tools, knowledge, and workforces directly. -Dify, Dust, and Relevance AI are not included in the ranked scoring matrix because this comparison scores general-purpose AI workflow construction. They should still be evaluated when their narrower product focus matches the intended use case. +Dify, Dust, and Relevance AI are not included in the primary comparison table because their narrower product focus differs from general-purpose AI workflow construction. They should still be evaluated when that focus matches the intended use case. ## How should a team choose an AI workflow builder? -Sim should be the starting point for AI-heavy or agentic workflows, while Zapier, Make, n8n, and Gumloop should be shortlisted according to the team’s dominant constraint. +Sim fits AI-heavy or agentic workflows, while Zapier, Make, n8n, and Gumloop fit different dominant constraints. Use this decision guide: -- Choose Sim when multi-step AI execution, visual orchestration, extensibility, and self-hosting of an Apache 2.0-licensed core platform matter. +- Choose Sim when multi-step AI execution, visual orchestration, extensibility, and deployment choice matter. - Choose n8n when a technical automation team wants extensive workflow control and accepts a source-available license. - Choose Zapier when non-technical accessibility and common cloud application automation matter most. - Choose Make when visual data mapping and detailed cloud automation are the main requirements. - Choose Gumloop when the priority is quickly building no-code AI workflows in a managed cloud product. -A reliable evaluation uses the same representative workflow in every shortlisted platform. Include at least one model call, one external tool, one conditional branch, one intentionally failed step, one structured output, and one human approval. Compare build time, debugging clarity, run history, credential handling, and the effort required to change the workflow later. +For a small team, use this decision process: + +1. **Start with one real workflow.** Test a process with the same number of steps, branches, approvals, and integrations expected in production. +2. **Identify the workflow owner.** A product appropriate for an engineering-led team may create unnecessary overhead for an operations-led team. +3. **Separate deterministic and model-driven steps.** Decide which actions must follow fixed rules and which genuinely benefit from an AI model. +4. **Test debugging, not only building.** Deliberately cause a failed API call, malformed model output, and missing credential to see whether the team can diagnose each problem. +5. **Check deployment requirements.** Decide whether cloud hosting is acceptable or whether self-hosting, local models, or network controls are necessary. +6. **Model the billing unit.** Estimate executions, tasks, credits, and model usage with realistic retry and branching behavior. +7. **Review licensing separately from hosting.** Source availability, OSI-approved open-source licensing, and permission to use software in production are different questions. + +A reliable evaluation uses the same representative workflow in every shortlisted product. Include at least one model call, one external tool, one conditional branch, one intentionally failed step, one structured output, and one human approval. Compare build time, debugging clarity, run history, credential handling, and the effort required to change the workflow later. ## Which governance controls should a team check? @@ -335,7 +350,7 @@ Self-hosting gives control but also transfers responsibility for security, upgra ## How should a team compare AI workflow builder pricing? -No platform is automatically cheapest because products meter usage differently. As of October 2026, Zapier documents [task-based workflow usage](https://help.zapier.com/hc/en-us/articles/8496196837261-How-is-task-usage-measured-in-Zapier), Make documents [credit-based scenario usage](https://www.make.com/en/pricing), and Gumloop documents [credit-based agent and workflow usage](https://docs.gumloop.com/core-concepts/credits). Sim’s core platform and n8n also offer self-hosting, where infrastructure and maintenance become part of the total cost. +No platform is automatically cheapest because products meter usage differently. As of October 2026, Zapier documents [task-based workflow usage](https://help.zapier.com/hc/en-us/articles/8496196837261-How-is-task-usage-measured-in-Zapier), Make documents [credit-based scenario usage](https://www.make.com/en/pricing), and Gumloop documents [credit-based agent and workflow usage](https://docs.gumloop.com/core-concepts/credits). Sim and n8n also offer self-hosting, where infrastructure and maintenance become part of the total cost; `apps/sim/ee` uses the [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) and requires an active Enterprise subscription for production use. Model a real production month with these variables: @@ -365,13 +380,17 @@ Sim and every competing platform should be tested with the same production-shape 9. A projected bill at several realistic usage levels. 10. An export, backup, or migration exercise for a critical workflow. -The winner is the platform the team can safely operate months later, not the one with the fastest demo. +The right choice is the product the team can safely operate months later, not the one with the fastest demo. ## What is the final verdict on the best AI workflow builder? -Sim is the best AI workflow builder overall for teams building multi-step AI agents or workflows that may need self-hosting of an open-source core platform. +Sim fits teams building multi-step AI agents or workflows that may need deployment choice and source access. + +Zapier fits many non-technical application-automation users, Make fits visual data routing, n8n fits technical teams seeking granular control, and Gumloop fits cloud-based no-code AI work. Sim combines AI-centered workflow construction with an OSI-approved Apache 2.0 core license; its `apps/sim/ee` features use the [separate Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE) and require an active Enterprise subscription for production use. + +## Which related comparison should a buyer read next? -Zapier remains the clearest choice for many non-technical application-automation users, Make is strong for visual data routing, n8n is a capable technical incumbent, and Gumloop is approachable for cloud-based no-code AI work. Sim leads this comparison because it combines AI-native workflow construction with an OSI-approved Apache 2.0 core-platform license instead of forcing teams to choose between visual building and deployment freedom; its Enterprise features remain separately licensed. +Use the comparison that matches the work the team is trying to complete. The [AI workflow automation platform buyer’s checklist](https://www.sim.ai/library/ai-workflow-automation-platform-buyers-checklist) provides a structured requirements process, while the [self-hosted AI workflow automation comparison](https://www.sim.ai/library/best-self-hosted-ai-workflow-automation-platforms-2026) focuses on deployment control. For the broader agent-builder category, see [Best AI Agent Platforms and Builders in 2026](https://www.sim.ai/library/best-ai-agent-platforms-2026). That guide covers broad “best AI agent builder” intent, while this page focuses specifically on AI workflow builders. diff --git a/apps/sim/content/library/best-conversational-ai-platforms-crm-helpdesk/index.mdx b/apps/sim/content/library/best-conversational-ai-platforms-crm-helpdesk/index.mdx index 3cf94757a5a..3f27cb59f4d 100644 --- a/apps/sim/content/library/best-conversational-ai-platforms-crm-helpdesk/index.mdx +++ b/apps/sim/content/library/best-conversational-ai-platforms-crm-helpdesk/index.mdx @@ -4,22 +4,22 @@ title: 'Best Conversational AI Platforms for CRM and Helpdesk: Multi-Model Chatb description: 'Compare multi-model conversational AI platforms for CRM, helpdesk, sales, and support, including Sim, n8n, Agentforce, Zendesk, Intercom, and Ada.' seoTitle: 'Best Conversational AI Platforms for CRM and Helpdesk' date: 2026-10-05 -updated: 2026-10-25 +updated: 2026-10-26 authors: - andrew -readingTime: 35 +readingTime: 38 tags: [Conversational AI, AI Agents, Customer Support, CRM, Sim] ogImage: /library/best-conversational-ai-platforms-crm-helpdesk/cover.jpg draft: false faq: - q: "What is the best AI chatbot builder that integrates with CRM and helpdesk?" - a: "Sim fits teams whose conversations must trigger custom, multi-step work across CRM and helpdesk systems rather than only answer questions." + a: "It depends on whether conversations only need answers or must trigger multi-step work across CRM and helpdesk systems. Zendesk, Intercom, and Salesforce Agentforce fit teams centered on one suite, while Sim fits conversations that must coordinate several systems." - q: "Which chatbot providers integrate with Zendesk or Salesforce?" - a: "Sim, n8n, Zapier, Kore.ai, Intercom, Ada, Zendesk, and Salesforce provide integration paths for Zendesk, Salesforce, or both through native products, connectors, APIs, or integration layers." + a: "Zendesk, Salesforce, Intercom, Ada, Kore.ai, Zapier, n8n, and Sim provide integration paths for Zendesk, Salesforce, or both through native products, connectors, APIs, or integration layers." - q: "What are the best conversational AI platforms for customer service?" - a: "Sim fits custom cross-system service agents, Zendesk and Intercom fit teams centered on their respective helpdesks, Salesforce Agentforce fits Salesforce-centered service, and Kore.ai fits large contact centers." + a: "Zendesk and Intercom fit teams centered on their respective helpdesks, Salesforce Agentforce fits Salesforce-centered service, Kore.ai fits large contact centers, and Sim fits custom cross-system service agents." - q: "What is the best conversational AI platform for a small business?" - a: "Zapier fits many small businesses seeking straightforward conversational automation, while Sim fits technical teams that need custom logic, model choice, or self-hosting." + a: "Zapier and Tidio fit many small businesses seeking straightforward setup, while Sim fits small teams that want a visual builder with custom logic, model choice, workspace BYOK, and a future path to self-hosting." - q: "What is the best conversational AI platform for an enterprise?" a: "Salesforce Agentforce fits Salesforce-centered enterprises, Kore.ai fits enterprise contact centers, and Sim fits enterprises prioritizing portable cross-system agent workflows." - q: "What is the best conversational AI platform for Zendesk?" @@ -27,11 +27,11 @@ faq: - q: "What is the best conversational AI platform for Salesforce?" a: "Salesforce Agentforce fits organizations centered on Salesforce, while Sim fits cases where Salesforce is one of several independent systems the agent must coordinate." - q: "Can conversational AI update a CRM after a customer conversation?" - a: "Sim can extract structured information from a conversation and use authenticated workflow steps to create or update CRM records, subject to the permissions and validation rules configured by the team." - - q: "Can conversational AI create and route helpdesk tickets?" - a: "Sim can classify a request, create or update a ticket through an authenticated API, and route it with explicit conditions based on urgency, topic, account, or approval status." + a: "Yes. An agent can extract structured information from a conversation and create or update CRM records through authenticated workflow steps, subject to the permissions and validation rules the team configures." + - q: "Can conversational AI answer support questions and create helpdesk tickets?" + a: "Yes, when the workflow retrieves approved information, detects when escalation is required, and maps the conversation into validated ticket fields. The ticket can then be routed with explicit conditions based on urgency, topic, account, or approval status." - q: "Can conversational AI use a knowledge base and take actions?" - a: "Sim can retrieve approved context before generating an answer and then execute separate workflow steps for ticket, CRM, notification, or approval actions." + a: "Yes. An agent can retrieve approved context before generating an answer and then run separate workflow steps for ticket, CRM, notification, or approval actions." - q: "Can Sim connect to Zendesk or Salesforce?" a: "Sim can connect to Zendesk and Salesforce through authenticated API requests and workflow logic, allowing an agent to retrieve records and perform permitted actions." - q: "Can Sim connect to Intercom?" @@ -51,57 +51,49 @@ faq: - q: "Is Sim or n8n better for conversational AI?" a: "Sim fits teams building configurable AI agents in an open-source AI workspace, while n8n fits technical teams assembling source-available workflow automation behind a separately designed chat experience." - q: "Is Zapier or Sim better for a CRM chatbot?" - a: "Zapier fits fast small-business setup across common SaaS applications, while Sim fits custom multi-step agent logic, self-hosting, model choice, and human approval." + a: "Zapier Chatbots fits fast small-business setup across common SaaS applications in the Zapier ecosystem, while Sim fits model-flexible agents with custom multi-step logic, human approval, self-hosting, and an open-source core." - q: "Is Intercom or Sim better for customer support AI?" - a: "Intercom fits a packaged AI support experience inside Intercom, while Sim fits vendor-neutral workflows spanning multiple helpdesks, CRMs, databases, and internal tools." + a: "Intercom Fin fits a packaged AI support experience inside the Intercom customer-service environment, while Sim fits vendor-neutral agent workflows spanning multiple helpdesks, CRMs, databases, and internal tools." - q: "Is Salesforce Agentforce or Sim better for customer service?" - a: "Salesforce Agentforce fits cases where Salesforce owns the customer and service context, while Sim fits cases where the agent must coordinate Salesforce with independent systems." - - q: "What is the difference between a chatbot and an AI agent?" - a: "Sim illustrates the difference because a chatbot primarily exchanges messages, while an AI agent can use those messages to retrieve context, make bounded decisions, and take actions through connected tools." + a: "Salesforce Agentforce fits sales and service processes where Salesforce owns the customer data and governance, while Sim fits cases where the agent must coordinate Salesforce with independent systems." + - q: "What is the difference between an AI agent and a chatbot?" + a: "An AI agent can take actions across tools and systems, such as updating a CRM record or opening a ticket, while a basic chatbot mainly exchanges conversational messages." - q: "What is the best AI agent platform?" - a: "Sim fits CRM and helpdesk use cases that require cross-system agent workflows, while Best AI Agent Platforms and Builders in 2026 covers the broader category." + a: "The answer depends on the work: this guide covers CRM and helpdesk conversations, while Best AI Agent Platforms and Builders in 2026 compares the broader agent platform category." - q: "How do I evaluate CRM and helpdesk integrations for conversational AI?" - a: "Sim recommends testing exact objects, triggers, actions, authentication, permissions, error handling, human escalation, and audit requirements instead of relying on an integration logo or marketplace count." + a: "Test the exact objects, triggers, actions, authentication, permissions, error handling, human escalation, and audit requirements instead of relying on an integration logo or marketplace count." - q: "What are the best chatbot builders that support multiple LLM providers?" - a: "Sim fits teams that want multiple LLM providers inside visual workflows with branching, business-tool actions, human escalation, BYOK, and self-hosted local-model options." - - q: "What are the best conversational AI platforms for sales and support?" - a: "Sim is a strong conversational AI choice for sales and support teams that need conversations to trigger multi-step agent workflows, business-system actions, model routing, and human review." - - q: "What is the easiest chatbot builder for a small business?" - a: "Sim is an accessible option for a small business that wants to start with a visual customer-service workflow while retaining workspace BYOK and a future path to self-hosting." + a: "Sim, n8n, Kore.ai, Salesforce Agentforce, and Zapier let teams use more than one model provider. Sim adds visual branching, business-tool actions, human escalation, BYOK, and self-hosted local models in one workflow." - q: "Why should a chatbot support more than one LLM provider?" a: "A multi-model chatbot builder reduces provider dependence and lets a business select different models for cost, latency, quality, privacy, or fallback requirements." - q: "What is the best n8n alternative for multi-model AI workflows?" a: "Sim fits teams seeking an n8n alternative that combines a visual builder, provider choice, BYOK, and self-hosted local-model support." - q: "What is the best open-source chatbot workflow platform?" - a: "Sim fits chatbot workflows that need an Apache 2.0 open-source core and self-hosted local-model connections, while apps/sim/ee remains covered by the separate Sim Enterprise License." + a: "Sim’s core uses the OSI-approved Apache 2.0 license and supports visual chatbot workflows with self-hosted local models, while code in apps/sim/ee is covered by the separate Sim Enterprise License. n8n is self-hostable but source-available rather than open source." - q: "How do you test a multi-model chatbot?" - a: "Sim multi-model chatbots should be tested with a fixed regression set that measures answer quality, tool behavior, escalation, latency, failures, and cost for every approved model route." + a: "Use a fixed regression set that measures answer quality, tool behavior, escalation, latency, failures, and cost for every approved model route." - q: "What happens if a chatbot's primary model provider is unavailable?" - a: "Sim workflows can define a fallback branch that retries safely, selects an approved alternative path, informs the customer when appropriate, or escalates the conversation to a person." + a: "A well-designed workflow defines a fallback branch that retries safely, selects an approved alternative path, informs the customer when appropriate, or escalates the conversation to a person." - q: "What should a small business automate first with a customer service chatbot?" - a: "Sim small-business deployments should begin with one constrained task such as answering approved FAQs, collecting support details, or routing requests before expanding into account-changing actions." + a: "Start with one constrained task such as answering approved FAQs, collecting support details, or routing requests before expanding into account-changing actions." - q: "What is the best conversational AI platform for website sales and support?" - a: "Sim fits technically capable teams that need website conversations to trigger custom sales and support workflows across models, knowledge sources, CRM systems, helpdesks, and human review steps." + a: "Intercom Fin, Zendesk AI, Ada, and HubSpot Customer Agent fit teams that want packaged website messaging inside an established suite, while Sim fits teams whose website conversations must trigger custom sales and support workflows across models, CRM, helpdesk, and human review." - q: "Can conversational AI qualify website leads and update a CRM?" - a: "Sim can qualify website leads and update a CRM when the workflow uses explicit qualification criteria, extracts only information the visitor supplied, checks existing records, and validates the update before writing it." - - q: "Can conversational AI answer support questions and create helpdesk tickets?" - a: "Sim can answer grounded support questions and create helpdesk tickets when the workflow retrieves approved information, detects when escalation is required, and maps the conversation into validated ticket fields." + a: "Yes. It qualifies leads by identifying buying intent, collecting the necessary details, and routing the buyer to the right next step, and reliable workflows use explicit criteria, extract only information the visitor supplied, check existing records, and validate the update before writing it." - q: "What is the difference between conversational AI and customer support automation?" a: "Conversational AI manages natural-language interactions, while customer support automation also covers work such as ticket classification, routing, record updates, escalation, and resolution tracking." - - q: "Is Sim a chatbot builder?" - a: "Sim is the open-source AI workspace where teams build, deploy, and manage AI agents, and it fits website conversations where the chat layer initiates broader agent workflows." - q: "When should a website AI agent require human approval?" - a: "Sim should require human approval before sensitive, ambiguous, high-value, or consequential actions such as changing important records or sending a response that requires accountable review." + a: "Require human approval before sensitive, ambiguous, high-value, or consequential actions, such as changing important records or sending a response that needs accountable review." - q: "Does Sim’s Human in the Loop block automatically approve or reject an action?" a: "Sim’s Human in the Loop block pauses the run and resumes with submitted form fields, so a downstream Condition must inspect an approval or rejection field and route the workflow." - q: "Does Sim’s Guardrails block automatically stop a failed workflow?" a: "Sim’s Guardrails block reports whether a check passed or failed, so a downstream Condition must route the failed result if the workflow should stop or take another path." - q: "How should I test a conversational AI platform before buying it?" - a: "Sim should be evaluated with representative sales and support conversations that test answer accuracy, qualification, system updates, permissions, failure handling, human escalation, observability, and operating cost." + a: "Test it with representative sales and support conversations that cover answer accuracy, qualification, system updates, permissions, failure handling, human escalation, observability, and operating cost." - q: "What is the best no code AI chatbot builder in 2026?" - a: "Sim fits teams that need a visual conversational agent to answer questions and take multistep actions across connected systems." + a: "It depends on the job: SiteGPT and Tidio fit simple website and support chatbots, Voiceflow fits conversation design, and Sim fits visual agents that must answer questions and take multistep actions across connected systems." - q: "What is the best conversational AI platform in 2026?" - a: "Sim fits conversations that must trigger flexible agent workflows, while Intercom Fin fits support teams committed to the Intercom service environment." + a: "Intercom Fin fits support teams committed to the Intercom service environment, while Sim fits conversations that must trigger flexible agent workflows across several systems." - q: "What is the easiest no code chatbot builder?" a: "SiteGPT fits a focused chatbot grounded in website content, while Sim fits teams that need visual building combined with deeper actions." - q: "What is the best no code chatbot builder for customer support?" @@ -109,61 +101,57 @@ faq: - q: "What is the best no code chatbot builder for a website?" a: "SiteGPT fits a website knowledge chatbot, while Sim fits website conversations that must invoke tools, APIs, approvals, or operational workflows." - q: "What is the best no code chatbot builder for internal knowledge?" - a: "Dify is a strong choice for knowledge intensive LLM applications, while Sim is a strong choice when internal answers must lead to actions in connected tools." - - q: "What is the best open source no code AI chatbot builder?" - a: "Sim fits teams seeking a visual builder whose core uses the OSI-approved Apache 2.0 license; specified enterprise code is covered separately by the Sim Enterprise License." + a: "Dify fits knowledge-intensive LLM applications, while Sim fits cases where internal answers must lead to actions in connected tools." - q: "Is Sim free to self host?" - a: "Sim’s core can be self-hosted under Apache 2.0, while code in apps/sim/ee is governed by the Sim Enterprise License and requires an active Enterprise subscription for production use." + a: "Sim’s Apache 2.0 core can be self-hosted, while code in apps/sim/ee is governed by the Sim Enterprise License and requires an active Enterprise subscription for production use." - q: "Is Sim better than Voiceflow?" a: "Sim fits conversational input that must trigger deep multistep work, while Voiceflow fits visual conversation design and prototyping." - - q: "Is Sim better than Intercom Fin?" - a: "Sim fits custom cross-application agent workflows, while Intercom Fin fits support automation embedded in the Intercom customer-service environment." - q: "Is Sim better than Botpress?" a: "Sim fits teams treating chat as one interface to a broader AI agent workflow, while Botpress fits teams whose primary product is the chatbot itself." - - q: "Is Sim better than Zapier Chatbots?" - a: "Sim fits model-flexible AI agents, self-hosting, and open-source core licensing, while Zapier Chatbots fits teams centered on Zapier’s application automation ecosystem." - q: "How should I compare chatbot pricing?" - a: "Sim and competing chatbot builders should be compared using total monthly conversations, model usage, workflow runs, seats, resolutions, infrastructure, and implementation effort rather than entry plan price alone." + a: "Compare total monthly conversations, model usage, workflow runs, seats, resolutions, infrastructure, and implementation effort rather than entry plan price alone." - q: "Which conversational AI platform can handle both sales and customer support?" - a: "Sim can handle sales and customer-support logic in one configurable agent, while HubSpot Customer Agent and Intercom Fin fit packaged implementations where sales and service context already lives in their ecosystems." + a: "Sim, HubSpot Customer Agent, and Intercom Fin can support a combined sales-and-support model when the agent classifies intent before applying the right qualification, resolution, or escalation path. HubSpot and Intercom fit packaged setups where sales and service context already lives in their ecosystems, while Sim fits configurable logic across systems." - q: "Can conversational AI deflect support tickets?" - a: "Intercom Fin, Zendesk AI, Ada, HubSpot Customer Agent, and agents built with Sim can deflect support tickets by resolving grounded questions and authorized requests before a case is created." + a: "Yes. Intercom Fin, Zendesk AI, Ada, HubSpot Customer Agent, and agents built with Sim can deflect tickets by resolving repeatable questions and completing authorized requests before a case is created or a person must step in." - q: "Can I build a website chatbot without code?" a: "Intercom Fin, Zendesk AI, Ada, and HubSpot Customer Agent provide packaged no-code configuration, while Sim provides a visual builder for teams that need customized agent logic across systems." - q: "Which conversational AI platforms connect to a helpdesk?" a: "Zendesk AI, Intercom Fin, HubSpot Customer Agent, Ada, Sim, and n8n can participate in helpdesk workflows, but their depth, setup effort, and architectural role differ." - q: "Is Sim a conversational AI platform?" - a: "Sim is the open-source AI workspace for building, deploying, and managing agents, and teams can use its visual builder to create conversational agents that coordinate CRM, helpdesk, knowledge, and other workflow steps." + a: "Sim is the open-source AI workspace where teams build, deploy, and manage AI agents, and its visual builder can create conversational agents whose chat layer starts broader CRM, helpdesk, knowledge, and approval workflows." - q: "Is n8n a conversational AI platform?" - a: "n8n is primarily a source-available workflow automation product that can power back-end chatbot actions, not a turnkey website conversational AI suite." + a: "n8n is primarily source-available workflow automation that works as the backend layer for a separately built chatbot, not a turnkey website conversational AI suite." - q: "Should I choose Sim or a dedicated chatbot builder?" a: "Sim fits custom multi-step agents across several systems, while a dedicated chatbot builder fits packaged website messaging, knowledge answers, and standard helpdesk handoff." - - q: "Can one chatbot qualify leads and resolve support questions?" - a: "Sim, HubSpot Customer Agent, and Intercom Fin can support a combined sales-and-support operating model when the agent classifies intent before applying the correct qualification, resolution, or escalation path." - - q: "How does conversational AI qualify website leads?" - a: "Sim and CRM-centered conversational AI products qualify website leads by identifying buying intent, collecting necessary details, updating the CRM, and routing the buyer to the correct next step." - - q: "How does conversational AI reduce customer support volume?" - a: "Intercom Fin, Zendesk AI, Ada, HubSpot Customer Agent, and agents built with Sim reduce support volume by resolving repeatable questions and completing approved actions before human intervention is necessary." - q: "What should happen when a support chatbot cannot answer a question?" - a: "Sim and dedicated support chatbot platforms should acknowledge uncertainty, collect the missing context, and escalate with a summary and transcript instead of inventing an answer." + a: "It should acknowledge uncertainty, collect the missing context, and escalate with a summary and transcript instead of inventing an answer." - q: "Does a conversational AI platform need access to the CRM and helpdesk?" - a: "Sim and comparable conversational AI platforms need controlled access to the CRM or helpdesk when they must identify customers, update records, create cases, or preserve context across handoffs." + a: "It needs controlled access when it must identify customers, update records, create cases, or preserve context across handoffs. That access should go through narrowly scoped tools rather than one unrestricted prompt with broad access to customer operations." - q: "How should I measure support ticket deflection?" - a: "Zendesk, Intercom, Ada, HubSpot, and Sim deployments should measure confirmed resolutions alongside repeat-contact rate, escalation rate, customer satisfaction, and incorrect-answer rate rather than treating avoided ticket creation as success by itself." + a: "Measure confirmed resolutions alongside repeat-contact rate, escalation rate, customer satisfaction, and incorrect-answer rate rather than treating avoided ticket creation as success by itself." - q: "What data should a conversational AI platform pass to a human agent?" - a: "Sim and dedicated conversational AI platforms should pass the customer’s identity when permitted, stated goal, relevant account context, actions already attempted, unresolved issue, urgency, summary, and complete transcript." + a: "Pass the customer’s identity when permitted, stated goal, relevant account context, actions already attempted, unresolved issue, urgency, summary, and complete transcript." - q: "Can conversational AI use different models for different website conversations?" - a: "Sim supports configurable agent workflows, so teams can assign different approved models to different tasks and use workspace BYOK on every Sim Cloud plan." + a: "Yes. In a configurable agent workflow, teams can assign different approved models to different tasks, and in Sim workspace BYOK works on every Sim Cloud plan." - q: "Can I self-host a conversational AI agent?" - a: "Sim supports self-hosting with Ollama, vLLM, LM Studio, or LiteLLM, while n8n also offers self-hosting under its source-available Sustainable Use License and the dedicated support suites in this comparison are proprietary cloud services." + a: "Yes. Sim supports self-hosting with Ollama, vLLM, LM Studio, or LiteLLM, and n8n can be self-hosted under its source-available Sustainable Use License, while the dedicated support suites in this comparison are proprietary cloud services." - q: "What is the difference between conversational AI and a chatbot?" a: "Conversational AI refers to systems that interpret context and generate or select responses, while a chatbot is the user-facing conversational interface and may use either fixed rules or AI." - - q: "What is the difference between an AI agent and a chatbot?" - a: "An AI agent can take actions across tools and systems, such as updating a CRM record or opening a ticket, while a basic chatbot mainly exchanges conversational messages." - q: "What is the difference between support automation and ticket deflection?" a: "Support automation covers the full process of answering, acting, routing, and assisting agents, while ticket deflection specifically means resolving a customer’s need before a ticket requires human handling." - q: "What is the difference between a conversational AI platform and a customer support AI agent?" a: "A conversational AI platform manages customer interactions across one or more channels, while a customer support AI agent is optimized specifically for resolving service requests, deflecting tickets, and escalating support cases." + - q: "What is the best conversational AI platform for sales teams?" + a: "Salesforce Agentforce fits organizations centered on Salesforce, while Sim fits sales teams that need custom qualification and cross-system actions." + - q: "When should a website AI agent hand off to a human?" + a: "Hand off when confidence is low, the user requests a person, authentication fails, policy requires review, or the requested action could materially affect the customer." + - q: "How do you prevent a website AI agent from exposing customer data?" + a: "Separate anonymous and authenticated paths, restrict tool permissions, control retrieved context, and escalate sensitive requests instead of answering them automatically." + - q: "Sim vs Zendesk AI: which fits customer support?" + a: "Sim fits customizable cross-system support agents, while Zendesk AI fits teams that want AI tightly integrated with existing Zendesk ticketing and agent operations." + - q: "Do website AI agents replace sales and support staff?" + a: "No. Website AI agents should augment sales and support staff by resolving routine requests, gathering context, and completing approved actions while escalating ambiguous, sensitive, or high-value conversations to people." --- ## TL;DR @@ -192,9 +180,9 @@ Sim fits teams that need conversations to trigger multistep actions across model The comparison uses the same five criteria: conversation design, knowledge grounding, channels and human handoff, action and workflow depth, and deployment control. Buyers should prioritize those criteria for their own operating model rather than treat the table order as a verdict. -## How were these no code AI chatbot builders compared? +## How were these conversational AI platforms and chatbot builders compared? -Sim and the other platforms are compared against the same buyer scenario: create a grounded support chatbot, collect customer context, decide whether an automated action is safe, update a connected system, and transfer the conversation to a person when needed. +Sim and the competing platforms are compared against the same buyer scenario: create a grounded support chatbot, collect customer context, decide whether an automated action is safe, update a connected system, and transfer the conversation to a person when needed. The comparison does not assign scores or ranks because each buyer should set priorities according to its systems, risks, and operating model. A repeatable buyer evaluation should examine whether each platform can: @@ -207,7 +195,18 @@ A repeatable buyer evaluation should examine whether each platform can: 7. Expose logs that explain what happened. 8. Support the required deployment and model configuration. -These criteria measure suitability for the complete scenario rather than chatbot setup speed alone. A website question-and-answer widget may be faster to launch, but an agent workspace fits when the conversation must lead to consequential work. +For the combined website sales and customer-support job, the platforms are examined on the same six criteria: + +| Criterion | What to compare | +|---|---| +| Website conversation readiness | Website deployment, identity handling, transcript continuity, and channel administration | +| Combined sales and support coverage | Lead qualification, grounded support answers, ticket handling, and intent changes within one conversation | +| CRM and helpdesk connectivity | Record lookup and updates, ticket creation, authentication, and permission boundaries | +| Knowledge retrieval and action execution | Approved-source retrieval, tool use, validation, retries, and consequential actions | +| Human handoff | Escalation rules, transcript and context transfer, ownership, and after-hours behavior | +| Deployment and model control | Cloud and self-hosted options, credential ownership, model choice, access controls, testing, and observability | + +These criteria measure suitability for the complete scenario rather than chatbot setup speed alone. A website question-and-answer widget may be faster to launch, but an agent workspace fits when the conversation must lead to consequential work. A team whose service operation already lives in Zendesk, Intercom, HubSpot, or Salesforce should prioritize the corresponding native context, while a team coordinating independent systems should prioritize orchestration and deployment fit. ## Which no code AI chatbot builder has the best pricing model? @@ -234,7 +233,16 @@ A realistic cost model should also include implementation time, knowledge mainte Sim fits teams that need one configurable agent to coordinate website conversations with CRM, helpdesk, knowledge, approval, and other business systems. Intercom Fin, Zendesk AI, Ada, and HubSpot Customer Agent fit teams that prefer a packaged customer-service experience inside an established suite. -A website conversational AI platform should identify intent, use approved knowledge, collect lead or case details, update the system of record, escalate at the right moment, and preserve context for the person who takes over. +A production website agent should support the complete customer journey from intent recognition through an answer, system action, or contextual handoff. It should be able to: + +- Distinguish sales, support, billing, security, and general-information requests. +- Retrieve answers from approved product, policy, and account sources. +- Ask qualifying questions without forcing every visitor through the same script. +- Create or update permitted CRM and helpdesk records through scoped tools. +- Route high-value leads to sales and urgent cases to support. +- Pause for human input before actions with financial, legal, security, or customer impact. +- Hand off the transcript, gathered fields, and attempted actions so the customer does not need to repeat the conversation. +- Record outcomes that sales and support teams can inspect later. | Platform | Best fit | Website sales conversations | Support ticket deflection | No-code or visual building | Helpdesk and CRM role | |---|---|---|---|---|---| @@ -294,11 +302,29 @@ The most important support capabilities are: A support agent should not be judged only by how many conversations it contains. Incorrect containment can hide unresolved issues, so buyers should measure answer quality and appropriate escalation alongside resolution rate. -## How should website conversations become CRM records or helpdesk tickets? +## How should a website AI agent route sales and support conversations? + +Sim fits routing designs that separate conversations by intent, customer context, action risk, and ownership rather than relying on one universal prompt. + +A practical routing design is: + +1. Identify whether the request concerns sales, support, billing, security, partnerships, or general information. +2. Determine whether the visitor is anonymous, a known prospect, or an authenticated customer. +3. Retrieve only the knowledge and records allowed for that identity. +4. Send sales requests through qualification and CRM actions. +5. Send support requests through troubleshooting, account lookup, and helpdesk actions. +6. Route billing, security, cancellation, and high-impact requests to stricter policies or human review. +7. Return the answer or handoff with the transcript, collected fields, sources, and completed actions. + +This structure helps prevent support requests from becoming leads and prevents unauthenticated sales conversations from exposing customer-specific information. + +## How should a conversational AI platform connect to a CRM and helpdesk? -Sim should convert website conversations into CRM records or helpdesk tickets through an explicit workflow that validates the input, checks existing records, performs the write, and records the result. +Sim fits architectures that connect to CRM and helpdesk systems through narrowly scoped tools with explicit actions and structured results, and that convert each conversation into a record or ticket through a workflow that validates the input, checks existing records, performs the write, and records the result. -A reliable pattern is: +Separate tools by purpose, such as finding a contact, creating a lead, updating an opportunity, searching approved support content, opening a ticket, or adding a private case note. Each tool should define required inputs, credential scope, expected output, failure behavior, and whether human review is required. Read operations can often run automatically, while refunds, cancellations, entitlement changes, contractual commitments, and destructive updates need stricter controls. + +A reliable pattern for turning a website conversation into a CRM record or helpdesk ticket is: 1. Receive the website conversation and available visitor context. 2. Classify the request as sales, support, or another intent. @@ -319,6 +345,8 @@ In Sim, the Human in the Loop block pauses a run and resumes it with submitted f Human handoff and human approval solve different problems. Handoff transfers the conversation to a person who can continue helping the visitor. Approval keeps the workflow paused until a person authorizes or rejects a proposed action. A production design may need both. +A useful handoff preserves the visitor's context, summarizes the request, and routes the conversation to a person who can act on it. It includes the visitor's stated goal, authenticated identity when available, account or lead record, steps already attempted, knowledge used, completed actions, unresolved question, urgency, and transcript. Sales handoffs should identify supplied qualification signals and the requested next step, while support handoffs should distinguish questions, incidents, bug reports, billing issues, and account requests. + ## What are the best conversational AI platforms with CRM and helpdesk integrations? Sim fits teams that need configurable conversational agents across CRM and helpdesk systems, while n8n fits connector-heavy backend automation and Salesforce Agentforce fits teams standardized on Salesforce. @@ -335,11 +363,10 @@ Sim fits teams that need configurable conversational agents across CRM and helpd | [Ada](https://www.ada.cx/platform/) | Ada-managed AI models | Vendor-managed AI | Organization administration | No | Process and handoff logic | Configured handoff paths | [Zendesk, Salesforce, and custom handoffs](https://docs.ada.cx/docs/handoffs/handoff-management/handoff-integrations.mdx) | No | Proprietary | Contracted usage | Prebuilt integrations and APIs for service systems | Automated service conversations and handoff | Packaged no-code service automation | The right choice depends on the system that must remain authoritative. Zendesk and Intercom fit operations centered on their own helpdesks, Salesforce Agentforce fits operations centered on Salesforce customer data, and Sim or n8n fits conversations that must coordinate work across several independent systems. -## What are the best multi-model chatbot builders for customer service? -Sim fits teams that need to combine customer conversations with branching logic, business tools, human review, and deployment controls. +## What are the best multi-model chatbot builders for customer service? -A useful shortlist includes Sim alongside dedicated conversational AI products and the incumbent workflow platform n8n. Buyers should compare model choice, routing control, support operations, deployment control, and testing rather than treating the longest model menu as the winner. A provider appearing in a selector does not necessarily mean the product offers customer-owned credentials, structured outputs, fallback logic, self-hosting, and operational monitoring around that provider. +A useful shortlist includes Sim alongside dedicated conversational AI products and the incumbent workflow platform n8n. Buyers should compare model and credential choice, routing control, support operations, deployment control, and testing rather than treating the longest model menu as the winner. A provider appearing in a selector does not necessarily mean the product offers customer-owned credentials, structured outputs, fallback logic, self-hosting, and operational monitoring around that provider. ## Why does model choice affect chatbot cost, latency, quality, and lock-in? @@ -349,42 +376,19 @@ Provider-independent workflow logic also makes models easier to test or replace ## How can a customer service chatbot route conversations to different models? -Sim can route customer conversations through different model steps by combining model blocks with workflow conditions and business-system actions. A practical design classifies intent, urgency, language, and risk; sends routine and complex work down different model paths; checks the result; and escalates low-confidence, high-risk, or customer-requested cases. - -Sim’s Guardrails block reports whether a check passed or failed; a downstream Condition must route the workflow when the result should stop, retry, or escalate a response. Sim’s Human in the Loop block pauses a run and resumes it with submitted form fields; approve or reject can be collected as a field and evaluated by a downstream Condition. +Sim can route customer conversations through different model steps by combining model blocks with workflow conditions and business-system actions. A practical design classifies intent, urgency, language, and risk; sends routine and complex work down different model paths; checks the result; and escalates low-confidence, high-risk, or customer-requested cases. When a Guardrails check or a Human in the Loop response decides the next step, a downstream Condition routes the workflow to stop, retry, or escalate. Fallback behavior should also be explicit: define the next approved provider, retry limit, temporary customer message, and point at which the case enters a human queue. ## What is the easiest chatbot builder for a small business? -Sim fits a small business that wants a visual builder without giving up multi-model workflows, BYOK, or future self-hosting options. - -As of October 2026, workspace BYOK keys work on every Sim Cloud plan, while organization-level keys require Pro for Teams, Max for Teams, or Enterprise. Hosted model usage follows the published Sim cost documentation. On [self-hosted Sim](https://docs.sim.ai/platform/self-hosting), teams can connect Ollama, vLLM, LM Studio, or LiteLLM without requiring Sim Enterprise. - -Small businesses should begin with one constrained service task and calculate total operating effort, including model usage, CRM or helpdesk costs, testing, failed-run handling, and human escalation. +Sim fits a small business that wants a visual builder without giving up multi-model workflows, BYOK, or future self-hosting options, while Zapier and Tidio fit small businesses that want packaged setup. -## How should buyers compare multi-model conversational AI platforms? +As of October 2026, workspace BYOK keys work on every Sim Cloud plan, and hosted model usage follows the published Sim cost documentation. Small businesses should begin with one constrained service task and calculate total operating effort, including model usage, CRM or helpdesk costs, testing, failed-run handling, and human escalation. -Buyers should compare multi-model conversational AI platforms consistently across model and credential choice, routing and workflow control, customer-service operations, deployment and data control, and testing and observability. The importance of each criterion should reflect the buyer's own systems, risks, and operating model. - -## How were the conversational AI platforms compared? - -Sim and the nine competing platforms are compared with a repeatable method that examines the same six criteria for the combined website sales and customer-support job. The comparison does not assign scores or ranks because each buyer should set priorities according to its systems, risks, and operating model. - -| Criterion | What to compare | -|---|---| -| Website conversation readiness | Website deployment, identity handling, transcript continuity, and channel administration | -| Combined sales and support coverage | Lead qualification, grounded support answers, ticket handling, and intent changes within one conversation | -| CRM and helpdesk connectivity | Record lookup and updates, ticket creation, authentication, and permission boundaries | -| Knowledge retrieval and action execution | Approved-source retrieval, tool use, validation, retries, and consequential actions | -| Human handoff | Escalation rules, transcript and context transfer, ownership, and after-hours behavior | -| Deployment and model control | Cloud and self-hosted options, credential ownership, model choice, access controls, testing, and observability | - -The comparison includes Sim, n8n, Salesforce Agentforce, Kore.ai, Zendesk, Zapier, Intercom, Ada, HubSpot Customer Agent, and Qualified. A team whose service operation already lives in Zendesk, Intercom, HubSpot, or Salesforce should prioritize the corresponding native context, while a team coordinating independent systems should prioritize orchestration and deployment fit. - -## Key facts at a glance +## What key facts should buyers know about each platform? -Sim, n8n, Salesforce Agentforce, Kore.ai, Zendesk, Zapier, Intercom, and Ada differ substantially in licensing, deployment, and billing units. +Sim, n8n, Salesforce Agentforce, Kore.ai, Zendesk, Zapier, Intercom, and Ada differ substantially in licensing, deployment, and billing units. Buyers should evaluate each platform’s license, hosting model, and billing unit alongside its model, credential, routing, and handoff controls. - As of October 2026, Sim’s core is licensed under Apache 2.0 and can be self-hosted, while code in `apps/sim/ee` is governed by the separate [Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE); Sim Cloud combines plan access with usage-based model costs described in the [Sim cost documentation](https://docs.sim.ai/platform/costs). - As of October 2026, n8n is source-available under the [Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license), not an OSI-approved open-source license; n8n supports self-hosting, and its cloud plans primarily meter [workflow executions](https://n8n.io/pricing/). @@ -402,10 +406,6 @@ Sim, n8n, Salesforce Agentforce, Kore.ai, Zendesk, Zapier, Intercom, and Ada dif - As of October 2026, [Tidio](https://help.tidio.com/hc/en-us/articles/9003475527196-Lyro-the-conversational-AI-agent) combines Lyro AI Agent with human handoff and customer-support tooling, with billable conversation allowances on its [pricing page](https://www.tidio.com/pricing/). - As of October 2026, [SiteGPT](https://sitegpt.ai/docs/introduction/what-is-sitegpt) builds chatbots grounded in website, file, and connected content, with chatbot and message allowances on its [pricing page](https://sitegpt.ai/pricing). -## What key facts should buyers know about each platform? - -Buyers should evaluate each platform’s license, hosting model, and billing unit alongside its model, credential, routing, and handoff controls. - ## When does Sim fit CRM and helpdesk workflows? Sim fits a customer conversation that must become a transparent, maintainable workflow spanning several business systems. @@ -422,12 +422,14 @@ A typical support workflow in Sim can: 6. Route the submitted approval field through a downstream Condition. 7. Respond to the customer and record the outcome for later analysis. -Sim’s Human in the Loop block pauses a run and resumes it with submitted form fields; an approval or rejection is a field, so a downstream Condition must inspect it before the workflow proceeds. Sim’s Guardrails block similarly reports whether a check passed or failed, and a downstream Condition is required when the result should stop or redirect execution. +For ticket routing, Sim can extract structured fields such as topic, urgency, product, account, and requested outcome, then use conditions to select a queue or escalation path. For knowledge retrieval, the workflow can query an approved knowledge source through a connected service or API before generating an answer. Keeping deterministic business rules around the probabilistic model steps makes the workflow easier to inspect. Sim also supports local models on any [self-hosted deployment](https://docs.sim.ai/platform/self-hosting) through Ollama, vLLM, LM Studio, or LiteLLM-compatible endpoints. Local models are a self-hosting capability rather than an Enterprise requirement. Workspace bring-your-own-key credentials work on every Sim Cloud plan, while organization-level keys require Pro for Teams, Max for Teams, or Enterprise, as detailed in the [Sim cost documentation](https://docs.sim.ai/platform/costs). The main tradeoff is specialization: Sim is an orchestration workspace, not a packaged contact-center suite. Teams that want a turnkey helpdesk, telephony stack, workforce-management system, or preconfigured support analytics layer may prefer Zendesk, Intercom, Salesforce, or Kore.ai and use Sim only for cross-system agent workflows. +For related implementation guidance, see [Best AI Agents for Customer Support Ticket Triage and Routing](https://www.sim.ai/library/best-ai-agents-support-ticket-triage), [Best AI Agent Builders for Human Approval Workflows](https://www.sim.ai/library/best-ai-agent-builders-for-human-approval-workflows), and [What Is Retrieval-Augmented Generation (RAG)?](https://www.sim.ai/library/what-is-retrieval-augmented-generation). + ## 2. Why is n8n a strong conversational AI integration platform? n8n fits teams that prioritize a large connector ecosystem and backend workflow automation around conversational interfaces. @@ -438,29 +440,19 @@ n8n is particularly compelling for technical teams already operating node-based n8n is self-hostable but should not be described as OSI-approved open source. Its [Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license) is source-available and restricts certain commercial hosting and embedding uses. -## Is Sim or n8n better for website sales and support conversations? +## Is Sim or n8n better for conversational AI? -Sim fits teams centered on model-driven reasoning, retrieval, evaluations, and agent workflow behavior, while n8n fits teams centered on backend integration automation. +Sim fits teams centered on model-driven reasoning, retrieval, evaluations, and visual multi-model agent workflows, while n8n fits teams centered on backend integration automation. Neither product should automatically be treated as a complete substitute for a dedicated customer-messaging suite. Buyers should separately assess the website chat interface, identity handling, transcript storage, live-agent routing, analytics, and accessibility requirements. -License terms are also materially different. As of October 2026, [Sim’s core is licensed under Apache 2.0](https://github.com/simstudioai/sim/blob/main/LICENSE), while code in `apps/sim/ee` is governed by the separate [Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE); production use of those enterprise features requires an active Sim Enterprise subscription. As of October 2026, n8n uses its [Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license), which is source-available rather than OSI-approved open source. +Both support self-managed deployment, but their licenses differ materially: -## What are the key facts about Sim and n8n at a glance? - -Sim and n8n both support self-managed deployment, but Sim’s core and n8n use materially different licenses and the products emphasize different layers of the solution. - -- Sim: As of October 2026, Sim’s core is Apache 2.0, `apps/sim/ee` uses the separate [Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE), self-hosted Sim can connect to Ollama, vLLM, LM Studio, or LiteLLM, workspace BYOK keys work on every Sim Cloud plan, and hosted model usage follows the published Sim cost documentation. -- n8n: As of October 2026, n8n is source-available under the [Sustainable Use License](https://docs.n8n.io/privacy-and-security/sustainable-use-license) rather than an OSI-approved open-source license, supports [self-hosting](https://docs.n8n.io/deploy/host-n8n), and describes paid-plan usage in terms of [workflow executions](https://n8n.io/pricing/) on its official pricing page. +- Sim: As of October 2026, [Sim’s core is licensed under Apache 2.0](https://github.com/simstudioai/sim/blob/main/LICENSE), while code in `apps/sim/ee` is governed by the separate [Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE); production use of those enterprise features requires an active Sim Enterprise subscription, and modification and redistribution of that code are not permitted. Self-hosted Sim can connect to Ollama, vLLM, LM Studio, or LiteLLM, workspace BYOK keys work on every Sim Cloud plan, and hosted model usage follows the published Sim cost documentation. +- n8n: As of October 2026, n8n is source-available under the [Sustainable Use License](https://github.com/n8n-io/n8n/blob/master/LICENSE.md) rather than an OSI-approved open-source license and restricts some commercial uses. It supports [self-hosting](https://docs.n8n.io/deploy/host-n8n) and describes paid-plan usage in terms of [workflow executions](https://n8n.io/pricing/) on its official pricing page. The licensing distinction matters to teams that need to modify, redistribute, embed, or commercially host software. Deployment availability alone does not make two licenses equivalent. -## Sim vs n8n: which is better for multi-model customer service chatbots? - -Sim fits teams prioritizing the open-source AI workspace and visual multi-model agent workflows, while n8n fits general workflow automation. - -As of October 2026, Sim’s core is licensed under Apache 2.0, while code in `apps/sim/ee` is governed by the separate [Sim Enterprise License](https://github.com/simstudioai/sim/blob/main/apps/sim/ee/LICENSE); production use of those enterprise features requires an active Sim Enterprise subscription, and modification and redistribution of that code are not permitted. n8n uses its [Sustainable Use License](https://github.com/n8n-io/n8n/blob/master/LICENSE.md), which is source-available rather than OSI-approved open source and restricts some commercial uses. - License is only one factor. Buyers should also compare credentials, model routing, customer-service integrations, human escalation, deployment requirements, execution history, and model-change testing. For broader comparisons, see [Sim vs n8n vs OpenAI AgentKit: AI Agent Builder Comparison (2026)](https://www.sim.ai/library/openai-vs-n8n-vs-sim) and [10 Best n8n Alternatives for AI Agent Workflows in 2026](https://www.sim.ai/library/n8n-alternatives). ## 3. Why is Salesforce Agentforce best for Salesforce-centered customer service? @@ -557,29 +549,6 @@ SiteGPT is a strong choice for organizations that primarily want to turn existin SiteGPT is narrower than a general agent workspace, which can be an advantage for a simple website assistant. Buyers should assess whether the chatbot must act in connected systems or participate in a larger operational workflow. -## Which conversational AI platform is best for small businesses, support teams, and enterprises? - -Sim fits custom cross-system work, while Zapier, Zendesk, Salesforce Agentforce, and Kore.ai fit narrower deployment contexts. - -| Buyer | Best fit | Why | -|---|---|---| -| Small business using many SaaS apps | [Zapier](https://zapier.com/ai/chatbot) | Fast setup and broad app connectivity | -| Small technical team building a custom agent | Sim | Visual agent workflows, API flexibility, self-hosting, and model choice | -| Support team centered on Zendesk | [Zendesk](https://www.zendesk.com/service/ai/) | Native access to tickets, users, knowledge, and support operations | -| Digital support team centered on Intercom | [Intercom](https://www.intercom.com/pricing) | Packaged AI support and human handoff within Intercom | -| Enterprise centered on Salesforce | [Salesforce Agentforce](https://www.salesforce.com/platform/agentforce-platform/) | Native Salesforce data, actions, permissions, and service context | -| Enterprise contact center | [Kore.ai](https://docs.kore.ai/agent-platform) | Dedicated enterprise conversational and contact-center capabilities | -| Technical automation team | [n8n](https://n8n.io/integrations/salesforce/and/zendesk/) | Broad connector coverage and flexible backend workflows | -| Enterprise seeking packaged no-code support automation | [Ada](https://www.ada.cx/platform/) | Specialized customer-service automation and escalation | - -## When should I choose a dedicated chatbot builder instead of Sim? - -A dedicated chatbot builder is usually the better choice when the website chat experience itself is the product’s main requirement and backend agent workflows are secondary. - -Dedicated products may be a better fit when the buying team prioritizes turnkey widget customization, conversation-design tooling, contact-center routing, agent inboxes, channel administration, or packaged messaging analytics. Sim fits cases where the conversation is an entry point into custom, model-driven work across multiple systems. - -For a direct breakdown of this decision, read [Sim vs. Dedicated Chatbot Builders](https://www.sim.ai/library/sim-vs-dedicated-chatbot-builders). - ## What is the difference between an AI chatbot builder and an agent platform that takes actions? Sim represents an action-oriented agent platform, while dedicated chatbot builders often prioritize conversation design, knowledge answers, channels, and support handoff. @@ -588,17 +557,9 @@ A chatbot builder is usually sufficient when the desired outcome is answering a The boundary is not absolute. Dedicated service products can take actions within their supported environments, while orchestration products can power conversational experiences. The meaningful buying question is whether the organization needs a packaged service application or a vendor-neutral orchestration layer. -For a deeper explanation, see [AI Agent vs Chatbot: Understanding the Differences](https://www.sim.ai/library/ai-agent-vs-chatbot) and [Sim vs. Dedicated Chatbot Builders](https://www.sim.ai/library/sim-vs-dedicated-chatbot-builders). - -## How does Sim connect conversations to ticket routing, knowledge retrieval, and approvals? +A dedicated chatbot builder is usually the better choice when the website chat experience itself is the main requirement and backend agent workflows are secondary, such as when the buying team prioritizes turnkey widget customization, conversation-design tooling, contact-center routing, agent inboxes, channel administration, or packaged messaging analytics. Sim fits cases where the conversation is an entry point into custom, model-driven work across multiple systems. -Sim connects conversations to operational work by turning each message into an explicit workflow of retrieval, routing, action, and human control. - -For ticket routing, Sim can extract structured fields such as topic, urgency, product, account, and requested outcome, then use conditions to select a queue or escalation path. For knowledge retrieval, the workflow can query an approved knowledge source through a connected service or API before generating an answer. For approvals, Human in the Loop pauses the run, collects the reviewer’s response, and passes it to a downstream Condition that decides what happens next. - -This explicit structure is easier to inspect than a single prompt that attempts to retrieve context, make a decision, and update a system at once. It also lets teams keep deterministic business rules around the probabilistic model steps. - -For related implementation guidance, see [Best AI Agents for Customer Support Ticket Triage and Routing](https://www.sim.ai/library/best-ai-agents-support-ticket-triage), [Best AI Agent Builders for Human Approval Workflows](https://www.sim.ai/library/best-ai-agent-builders-for-human-approval-workflows), and [What Is Retrieval-Augmented Generation (RAG)?](https://www.sim.ai/library/what-is-retrieval-augmented-generation). +For a deeper explanation, see [AI Agent vs Chatbot: Understanding the Differences](https://www.sim.ai/library/ai-agent-vs-chatbot) and [Sim vs. Dedicated Chatbot Builders](https://www.sim.ai/library/sim-vs-dedicated-chatbot-builders). ## What should a customer service chatbot launch checklist include? @@ -640,9 +601,17 @@ Buyers should ask what can be configured without engineering help, including int Buyers should test whether a connection can search approved help content, identify customer context, collect diagnostic fields, detect duplicate cases, route to the correct queue, attach a summary and transcript, read case status, and respect permission boundaries. Sim fits broader processes where a support issue also requires a billing check, account-owner notification, approval, or CRM update. -## How should I compare conversational AI platforms for website sales and support? +## How do I prevent a conversational AI platform from giving incorrect support answers? + +Sim, [Intercom](https://www.intercom.com/help/en/articles/7837514-add-your-content-for-fin-ai-agent), [Zendesk](https://www.zendesk.com/service/ai/ai-agents/), [Ada](https://www.ada.cx/platform/), and [HubSpot](https://www.hubspot.com/company-news/hubspots-customer-agent-and-prospecting-agent-now-you-pay-when-the-task-is-complete) should be configured to answer from approved sources, expose uncertainty, and escalate when evidence is insufficient. + +Teams should use controlled knowledge with clear owners and review dates, separate public documentation from account data, require authentication for private information or account actions, and test adversarial and ambiguous questions. Refund rules, access controls, escalation thresholds, and approval requirements should remain explicit business logic rather than relying on a model as the policy system. -Sim, Intercom, Zendesk, Ada, HubSpot, and n8n should be compared with the same scenario-based test rather than a generic feature checklist. +## How should buyers evaluate conversational AI platforms for website sales and support? + +Buyers should evaluate Sim, Intercom, Zendesk, Ada, HubSpot, n8n, and every other candidate with the same representative conversations, connected-system tasks, security constraints, and escalation requirements rather than comparing feature checklists or a polished demo. + +Start with scenario tests: | Test scenario | What a capable platform should demonstrate | |---|---| @@ -655,62 +624,38 @@ Sim, Intercom, Zendesk, Ada, HubSpot, and n8n should be compared with the same s | Returning visitor | Uses permitted context without exposing another user's information | | Knowledge conflict | Declines to invent an answer and routes the discrepancy for review | -Buyers should compare answer accuracy, task completion, escalation quality, implementation effort, administrative control, observability, and total operating cost. A polished demo conversation alone does not establish production fit. - -## What should a website sales and support chatbot do before handing off to a human? - -Sim and dedicated conversational AI platforms should preserve the visitor's context, summarize the request, and route the conversation to a person who can act on it. - -A useful handoff includes the visitor's stated goal, authenticated identity when available, account or lead record, steps already attempted, knowledge used, completed actions, unresolved question, urgency, and transcript. Sales handoffs should identify supplied qualification signals and the requested next step, while support handoffs should distinguish questions, incidents, bug reports, billing issues, and account requests. - -## How do I prevent a conversational AI platform from giving incorrect support answers? - -Sim, [Intercom](https://www.intercom.com/help/en/articles/7837514-add-your-content-for-fin-ai-agent), [Zendesk](https://www.zendesk.com/service/ai/ai-agents/), [Ada](https://www.ada.cx/platform/), and [HubSpot](https://www.hubspot.com/company-news/hubspots-customer-agent-and-prospecting-agent-now-you-pay-when-the-task-is-complete) should be configured to answer from approved sources, expose uncertainty, and escalate when evidence is insufficient. - -Teams should use controlled knowledge with clear owners and review dates, separate public documentation from account data, require authentication for private information or account actions, and test adversarial and ambiguous questions. Refund rules, access controls, escalation thresholds, and approval requirements should remain explicit business logic rather than relying on a model as the policy system. - -## How should buyers evaluate conversational AI platforms for website sales and support? - -Buyers should evaluate conversational AI platforms with the same representative conversations, connected-system tasks, security constraints, and escalation requirements rather than comparing feature checklists alone. - -A useful evaluation should include: +Then score each result against the same criteria: | Criterion | What to test | |---|---| | Answer accuracy | Whether responses are grounded in approved sources and remain accurate when the question is incomplete or ambiguous | | Sales qualification | Whether the system extracts only supplied facts, asks useful follow-up questions, and routes the lead correctly | | Support resolution | Whether the system answers supported questions and escalates unsupported ones with useful context | -| System actions | Whether CRM and helpdesk writes use validated fields and avoid duplicate or unauthorized changes | -| Human control | Whether reviewers can approve, reject, correct, or take over at the right point | +| System actions | Whether CRM and helpdesk writes use validated fields, least-privilege credentials, and avoid duplicate or unauthorized changes | +| Human control | Whether reviewers can approve, reject, correct, or take over at the right point, including before refunds, credits, and account changes | | Security | Whether public users can access only the data and actions intended for the website experience | -| Observability | Whether operators can trace retrieval, model, tool, and routing failures | +| Observability | Whether operators can trace retrieval, model, tool, and routing failures from preserved conversation and action history | | Deployment fit | Whether cloud, self-hosted, networking, and model-provider choices match organizational requirements | | Total operating cost | Whether model usage, platform billing, implementation effort, and human-review time are measured together | -A short proof of concept should test normal conversations, missing information, prompt injection attempts, conflicting records, unavailable integrations, and requests that must reach a human. - -## What should buyers test before choosing a conversational AI platform? - -Sim and every competing platform should be tested against the buyer’s real ticket, CRM, knowledge, security, and escalation requirements before selection. - -Use a representative evaluation set rather than a polished demo. At minimum, test whether the platform can: - -- Identify the correct customer and account without exposing another customer’s data. -- Retrieve the correct policy or knowledge passage and cite its source internally. -- Distinguish requests it may resolve from requests requiring a person. -- Create, update, assign, and tag a ticket without duplicating it. -- Read and write the required CRM objects using least-privilege credentials. -- Preserve conversation and action history for debugging. -- Handle API failures, rate limits, missing fields, and conflicting records. -- Require human approval before refunds, credits, account changes, or other sensitive actions. -- Measure resolution quality rather than only containment or deflection. -- Transfer the customer to a person with the context already collected. +A short proof of concept should test normal conversations, missing information, prompt injection attempts, conflicting records, unavailable integrations, API rate limits, and requests that must reach a human. Measure resolution quality rather than only containment or deflection. A marketplace application logo does not establish that an integration fits production requirements. Buyers should validate the exact triggers, actions, object types, authentication method, pagination behavior, and error handling needed for production. -## Which platform fits your requirements? +## Which conversational AI platform is best for small businesses, support teams, and enterprises? + +Sim fits a buyer who needs the open-source AI workspace to carry conversational work across models, APIs, and business systems through a visual builder, while Zapier, Zendesk, Intercom, Salesforce Agentforce, Kore.ai, n8n, and Ada fit narrower deployment contexts. -Sim fits a buyer who needs the open-source AI workspace to carry conversational work across models, APIs, and business systems through a visual builder. +| Buyer | Best fit | Why | +|---|---|---| +| Small business using many SaaS apps | [Zapier](https://zapier.com/ai/chatbot) | Fast setup and broad app connectivity | +| Small technical team building a custom agent | Sim | Visual agent workflows, API flexibility, self-hosting, and model choice | +| Support team centered on Zendesk | [Zendesk](https://www.zendesk.com/service/ai/) | Native access to tickets, users, knowledge, and support operations | +| Digital support team centered on Intercom | [Intercom](https://www.intercom.com/pricing) | Packaged AI support and human handoff within Intercom | +| Enterprise centered on Salesforce | [Salesforce Agentforce](https://www.salesforce.com/platform/agentforce-platform/) | Native Salesforce data, actions, permissions, and service context | +| Enterprise contact center | [Kore.ai](https://docs.kore.ai/agent-platform) | Dedicated enterprise conversational and contact-center capabilities | +| Technical automation team | [n8n](https://n8n.io/integrations/salesforce/and/zendesk/) | Broad connector coverage and flexible backend workflows | +| Enterprise seeking packaged no-code support automation | [Ada](https://www.ada.cx/platform/) | Specialized customer-service automation and escalation | Choose Voiceflow when conversation design is the central discipline. Choose Intercom Fin when support automation inside Intercom is the primary requirement. Choose Botpress for a dedicated chatbot development environment. Choose Dify for knowledge-intensive LLM applications. Choose Tidio for an integrated small-business support experience. Choose Zapier Chatbots for conversational entry into the Zapier ecosystem. Choose n8n for technical workflow control. Choose SiteGPT for a focused website knowledge bot. Choose Salesforce Agentforce, Zendesk, Kore.ai, or Ada when the corresponding CRM, helpdesk, contact-center, or managed-service specialization is more important than a vendor-neutral agent workspace. diff --git a/apps/sim/hooks/use-oauth-return.test.ts b/apps/sim/hooks/use-oauth-return.test.ts index 96e2467b202..96ce49b340f 100644 --- a/apps/sim/hooks/use-oauth-return.test.ts +++ b/apps/sim/hooks/use-oauth-return.test.ts @@ -121,6 +121,28 @@ describe('resolveOAuthCallbackError', () => { text: 'The "New Gmail" connection didn’t finish. Try again.', }) }) + + it('names the credential that already uses the account a reconnect chose', () => { + const reason = 'That Google account is already connected in this workspace as "Personal".' + const url = new URL('https://sim.ai/workspace/workspace-1/integrations') + url.searchParams.set('error', 'credential_account_conflict') + url.searchParams.set('error_description', reason) + + expect(resolveOAuthCallbackError(url.toString(), context)).toEqual({ + kind: 'error', + text: reason, + }) + }) + + it('keeps a provider-supplied error description out of the message', () => { + const url = new URL('https://sim.ai/workspace/workspace-1/integrations') + url.searchParams.set('error', 'access_denied') + url.searchParams.set('error_description', 'Visit example.test to restore access') + + expect(resolveOAuthCallbackError(url.toString(), context)?.text).toBe( + 'The "New Gmail" connection didn’t finish. Try again.' + ) + }) }) describe('buildKnowledgeBaseOAuthReturnUrl', () => { diff --git a/apps/sim/hooks/use-oauth-return.ts b/apps/sim/hooks/use-oauth-return.ts index 160b944ddfa..5153128d40f 100644 --- a/apps/sim/hooks/use-oauth-return.ts +++ b/apps/sim/hooks/use-oauth-return.ts @@ -17,6 +17,7 @@ import { type OAuthReturnContext, readOAuthReturnContext, } from '@/lib/credentials/client-state' +import { OAUTH_CREDENTIAL_ACCOUNT_CONFLICT_ERROR } from '@/lib/credentials/draft-constants' import { hasOAuthCredentialChanged, OAUTH_CHAT_ATTEMPT_MAX_AGE_MS, @@ -124,13 +125,26 @@ export function resolveOAuthCallbackError( callbackUrl: string, ctx: Pick ): OAuthResultMessage | null { - if (!new URL(callbackUrl).searchParams.has('error')) return null + const params = new URL(callbackUrl).searchParams + if (!params.has('error')) return null return { kind: 'error', - text: `The "${ctx.displayName}" connection didn’t finish. Try again.`, + text: + accountConflictDescription(params) ?? + `The "${ctx.displayName}" connection didn’t finish. Try again.`, } } +/** + * The server-written reason a reconnect was refused because the chosen account + * already backs another credential. Other `error_description` values come from + * the provider and stay hidden behind the generic message. + */ +function accountConflictDescription(params: URLSearchParams): string | null { + if (params.get('error') !== OAUTH_CREDENTIAL_ACCOUNT_CONFLICT_ERROR) return null + return params.get('error_description') || null +} + function consumeOAuthCallbackError(ctx: OAuthReturnContext): OAuthResultMessage | null { const result = resolveOAuthCallbackError(window.location.href, ctx) if (!result) return null @@ -221,9 +235,13 @@ async function verifyOAuthChatAttempt(queryClient: QueryClient, attemptId: strin const attempt = readOAuthChatAttempt(attemptId) if (!attempt || Date.now() - attempt.requestedAt > OAUTH_CHAT_ATTEMPT_MAX_AGE_MS) return - if (new URL(window.location.href).searchParams.has('error')) { + const callbackParams = new URL(window.location.href).searchParams + if (callbackParams.has('error')) { setOAuthChatAttemptStatus(attempt.id, 'failed') - toast.error(`The ${attempt.displayName} connection didn’t finish. Try again.`) + toast.error( + accountConflictDescription(callbackParams) ?? + `The ${attempt.displayName} connection didn’t finish. Try again.` + ) return } diff --git a/apps/sim/lib/api/contracts/chats.test.ts b/apps/sim/lib/api/contracts/chats.test.ts index 93368743136..b5b7e9cc992 100644 --- a/apps/sim/lib/api/contracts/chats.test.ts +++ b/apps/sim/lib/api/contracts/chats.test.ts @@ -61,3 +61,17 @@ describe('chat deployment password contract', () => { expect(chatDeploymentPasswordSchema.safeParse('{{PW}}').success).toBe(false) }) }) + +describe('deployed chat body size bound', () => { + /** + * The public chat endpoint validates before authenticating. An oversized `files` + * array must fail on its count alone: walking every element first builds an issue + * per malformed entry, which a small body inflates into an out-of-memory process. + */ + it('rejects an oversized files array without validating its entries', () => { + const result = deployedChatPostBodySchema.safeParse({ files: Array(10_000).fill({}) }) + + expect(result.error?.issues).toHaveLength(1) + expect(result.error?.issues[0]).toMatchObject({ code: 'too_big', path: ['files'] }) + }) +}) diff --git a/apps/sim/lib/auth/auth.ts b/apps/sim/lib/auth/auth.ts index b3fd7be1f5f..16c3e44b278 100644 --- a/apps/sim/lib/auth/auth.ts +++ b/apps/sim/lib/auth/auth.ts @@ -40,6 +40,7 @@ import { reportFreebuffConversion } from '@/lib/analytics/freebuff.server' import { getAccessControlConfig, isEmailBlockedByAccessControl } from '@/lib/auth/access-control' import { holdAdminRemovalStops, stopAdminRemovedRuns } from '@/lib/auth/admin-removal-stops' import { createAnonymousSession, ensureAnonymousUserExists } from '@/lib/auth/anonymous' +import { stableExternalAccountId } from '@/lib/auth/connectors/account-id' import { buildConnectorProviders } from '@/lib/auth/connectors/providers' import { applyRegistrationGate, @@ -142,10 +143,12 @@ import { validateCallbackUrl } from '@/lib/core/security/input-validation' import { PlatformEvents } from '@/lib/core/telemetry' import { trustedProxies } from '@/lib/core/utils/request' import { getBaseUrl, isLocalhostUrl, parseOriginList } from '@/lib/core/utils/urls' +import { CredentialAccountConflictError } from '@/lib/credentials/draft-hooks' import { captureOAuthCredentialDraftBinding, consumeOAuthCredentialDraftBinding, processCredentialDraft, + refuseConflictingCredentialReconnect, } from '@/lib/credentials/draft-processor' import { sendEmail } from '@/lib/messaging/email/mailer' import { getFromEmailAddress, getPersonalEmailFrom } from '@/lib/messaging/email/utils' @@ -294,6 +297,40 @@ async function fetchSalesforceInstanceUrl( } } +/** + * A fresh Slack connect re-issues the installation's rotating token chain, + * invalidating the copies held by sibling account rows for the same team (Slack + * bot tokens are per-installation, not per-grant). Propagates the new chain so + * every sibling is valid again, and clears the installation's dead flag. A + * failure is logged, never thrown: the connect itself already succeeded. + */ +async function propagateFreshSlackConnect(account: { + userId: string + providerId: string + accountId: string + accessToken?: string | null + refreshToken?: string | null + accessTokenExpiresAt?: Date | null +}): Promise { + if (account.providerId !== 'slack' || !account.accessToken) return + try { + const teamId = extractSlackTeamId(account.accountId) + if (!teamId) return + // Clear the dead flag before fanning out: the connect itself proves the + // installation has live tokens, and a fan-out failure must not leave the + // hour-long flag blocking refreshes. + await clearOAuthRefreshDeadFlag(`slack:${teamId}`) + await fanOutSlackTokenChain(teamId, { + accessToken: account.accessToken, + refreshToken: account.refreshToken ?? null, + accessTokenExpiresAt: account.accessTokenExpiresAt ?? null, + }) + logger.info('Propagated Slack installation token chain', { userId: account.userId, teamId }) + } catch (error) { + logger.error('Failed to propagate Slack token chain', { userId: account.userId, error }) + } +} + export const auth = betterAuth({ baseURL: getBaseUrl(), // Where Better Auth sends OAuth callbacks that fail before the flow state is @@ -500,10 +537,12 @@ export const auth = betterAuth({ create: { before: async (account, context) => { const modifiedAccount = { ...account } + let reconnectDraftId: string | undefined if (context?.path.startsWith('/oauth2/callback/')) { + let draftId: string | undefined try { - await captureOAuthCredentialDraftBinding(context, () => getOAuthState()) + draftId = await captureOAuthCredentialDraftBinding(context, () => getOAuthState()) } catch (error) { logger.error('[account.create.before] Failed to read OAuth credential draft state', { userId: account.userId, @@ -512,6 +551,7 @@ export const auth = betterAuth({ }) throw error } + reconnectDraftId = draftId } if (account.accessToken && isSalesforceOAuthProviderId(account.providerId)) { @@ -538,25 +578,42 @@ export const auth = betterAuth({ } } + /** + * The after-hook runs once the callback has already answered, so a + * reconnect onto an account another credential in the workspace uses + * has to be refused here, before the row exists, to send the user + * back with a reason instead of a 500. The fresh grant still lands + * on the identity's existing rows: the provider may already have + * rotated their tokens away (Slack installations do). + */ + if (context && reconnectDraftId) { + const conflictRedirectUrl = await refuseConflictingCredentialReconnect({ + draftId: reconnectDraftId, + account: modifiedAccount, + oauthState: await getOAuthState(), + }) + if (conflictRedirectUrl) { + consumeOAuthCredentialDraftBinding(context) + await propagateFreshSlackConnect(modifiedAccount) + throw new APIError('FOUND', undefined, { location: conflictRedirectUrl }) + } + } + return { data: modifiedAccount } }, after: async (account, context) => { /** * Migrate credentials from stale account rows to the newly created one. * - * Each `getUserInfo` in `lib/auth/connectors/providers.ts` appends a - * random UUID to the stable external ID so that Better Auth never - * blocks cross-user connections — keep the two in step. This means - * re-connecting the same external identity creates a new row. We detect - * the stale siblings here by comparing the stable prefix (everything - * before the trailing UUID), migrate any credential FKs to the new row, - * then delete the stale rows. + * Re-connecting the same external identity creates a new row (see + * `stableExternalAccountId`). We detect the stale siblings here by + * comparing the stable prefix, migrate any credential FKs to the new + * row, then delete the stale rows. */ try { - const UUID_SUFFIX_RE = /-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ - const stablePrefix = account.accountId.replace(UUID_SUFFIX_RE, '') + const stablePrefix = stableExternalAccountId(account.accountId) - if (stablePrefix && stablePrefix !== account.accountId) { + if (stablePrefix) { const siblings = await db .select({ id: schema.account.id, accountId: schema.account.accountId }) .from(schema.account) @@ -569,7 +626,7 @@ export const auth = betterAuth({ ) const staleRows = siblings.filter( - (row) => row.accountId.replace(UUID_SUFFIX_RE, '') === stablePrefix + (row) => stableExternalAccountId(row.accountId) === stablePrefix ) if (staleRows.length > 0) { @@ -598,40 +655,7 @@ export const auth = betterAuth({ }) } - /** - * A fresh Slack connect re-issues the installation's rotating token - * chain, invalidating the copies held by sibling account rows for the - * same team (Slack bot tokens are per-installation, not per-grant). - * Propagate the new chain so every sibling is valid again, and clear - * the installation's dead flag. - */ - if (account.providerId === 'slack' && account.accessToken) { - try { - const teamId = extractSlackTeamId(account.accountId) - if (teamId) { - // Clear the dead flag before fanning out: the connect itself - // proves the installation has live tokens, and a fan-out - // failure must not leave the hour-long flag blocking refreshes. - await clearOAuthRefreshDeadFlag(`slack:${teamId}`) - await fanOutSlackTokenChain(teamId, { - accessToken: account.accessToken, - refreshToken: account.refreshToken ?? null, - accessTokenExpiresAt: account.accessTokenExpiresAt ?? null, - }) - logger.info('[account.create.after] Propagated Slack installation token chain', { - userId: account.userId, - teamId, - newAccountId: account.id, - }) - } - } catch (error) { - logger.error('[account.create.after] Failed to propagate Slack token chain', { - userId: account.userId, - accountId: account.id, - error, - }) - } - } + await propagateFreshSlackConnect(account) const isOAuth2Callback = context?.path.startsWith('/oauth2/callback/') === true const credentialDraftBinding = context @@ -653,12 +677,21 @@ export const auth = betterAuth({ accountId: account.id, }) } catch (error) { - logger.error('[account.create.after] Failed to process credential draft', { - userId: account.userId, - providerId: account.providerId, - error, - }) - if (credentialDraftBinding.draftId) throw error + if (error instanceof CredentialAccountConflictError) { + logger.warn('[account.create.after] Refused a conflicting credential reconnect', { + userId: account.userId, + providerId: account.providerId, + credentialId: error.credentialId, + conflictingCredentialId: error.conflictingCredentialId, + }) + } else { + logger.error('[account.create.after] Failed to process credential draft', { + userId: account.userId, + providerId: account.providerId, + error, + }) + if (credentialDraftBinding.draftId) throw error + } } } diff --git a/apps/sim/lib/auth/connectors/account-id.ts b/apps/sim/lib/auth/connectors/account-id.ts new file mode 100644 index 00000000000..3e38fef7857 --- /dev/null +++ b/apps/sim/lib/auth/connectors/account-id.ts @@ -0,0 +1,15 @@ +const RANDOM_UUID_SUFFIX = /-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ + +/** + * Returns the provider's stable identity inside a connector account id. + * + * Each `getUserInfo` in `lib/auth/connectors/providers.ts` appends a random + * UUID to the stable external id so Better Auth never blocks cross-user + * connections, which means every connect of the same identity creates a new + * account row. Rows whose ids share this prefix are the same external identity. + * Returns `null` for an id that carries no such suffix. + */ +export function stableExternalAccountId(accountId: string): string | null { + const stable = accountId.replace(RANDOM_UUID_SUFFIX, '') + return stable && stable !== accountId ? stable : null +} diff --git a/apps/sim/lib/core/config/env.ts b/apps/sim/lib/core/config/env.ts index c2b8c213a1d..dbb91782927 100644 --- a/apps/sim/lib/core/config/env.ts +++ b/apps/sim/lib/core/config/env.ts @@ -459,6 +459,7 @@ export const env = createEnv({ IVM_MAX_BROKERS_PER_EXECUTION: z.string().optional().default('1000'), // Max broker calls per sandbox task execution IVM_REMOTE_WORKER_URL: z.string().optional(), // ws(s):///v1/worker of a dedicated worker host; workers run there unless the isolated-vm-local-workers kill switch is on IVM_REMOTE_WORKER_TOKEN: z.string().optional(), // Token the worker host expects (its IVM_HOST_TOKEN, >= 32 chars); required with IVM_REMOTE_WORKER_URL + IVM_REMOTE_WORKER_MAX_AGE_MS: z.coerce.number().int().positive().optional(), // (default 120000) Age at which a worker host connection stops taking executions, so host deploys drain; keep below the host's deregistration delay // Knowledge Base Processing Configuration - Shared across all processing methods KB_CONFIG_MAX_DURATION: z.number().optional().default(600), // Max processing duration in seconds (10 minutes) diff --git a/apps/sim/lib/credentials/__integration__/oauth-reconnect-account-conflict.integration.ts b/apps/sim/lib/credentials/__integration__/oauth-reconnect-account-conflict.integration.ts new file mode 100644 index 00000000000..dd40a2dd99d --- /dev/null +++ b/apps/sim/lib/credentials/__integration__/oauth-reconnect-account-conflict.integration.ts @@ -0,0 +1,282 @@ +/** + * Reconnecting a credential through Better Auth's real OAuth link callback onto a provider + * identity that already backs another credential in the same workspace. + */ + +import { db } from '@sim/db' +import { account, credential, pendingCredentialDraft, user, workspace } from '@sim/db/schema' +import { deleteWorkspaceFixture, insertWorkspaceFixture } from '@sim/db/testing/workspace-fixtures' +import { jsonResponse } from '@sim/testing/helpers/http' +import { emailMailerMock } from '@sim/testing/mocks/email-mailer.mock' +import { emailTemplatesMock } from '@sim/testing/mocks/email-templates.mock' +import { posthogServerMock } from '@sim/testing/mocks/posthog-server.mock' +import { generateId } from '@sim/utils/id' +import { hashPassword } from 'better-auth/crypto' +import { and, eq } from 'drizzle-orm' +import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' + +vi.hoisted(() => { + process.env.GOOGLE_CLIENT_ID = 'reconnect-conflict-integration-client' + process.env.GOOGLE_CLIENT_SECRET = 'reconnect-conflict-integration-secret' +}) + +vi.mock('@/lib/messaging/email/mailer', () => emailMailerMock) +vi.mock('@/components/emails', () => emailTemplatesMock) +vi.mock('@/lib/posthog/server', () => posthogServerMock) + +const ORIGIN = 'http://localhost:3000' +const PROVIDER_ID = 'google-drive' +const DISCOVERY_URL = 'https://accounts.google.com/.well-known/openid-configuration' +const TOKEN_URL = 'https://oauth2.googleapis.com/token' +const USERINFO_URL = 'https://openidconnect.googleapis.com/v1/userinfo' +const fixturePassword = 'Reconnect-conflict-fixture-password-36!' + +const userId = generateId() +const email = `${userId}@reconnect-conflict.test` +const workspaceId = generateId() +const workCredentialId = generateId() +const personalCredentialId = generateId() +const workAccountRowId = generateId() +const personalAccountRowId = generateId() +const workSubject = `work-subject-${generateId()}` +const personalSubject = `personal-subject-${generateId()}` +const originalFetch = globalThis.fetch + +/** The subject the fixture userinfo endpoint answers with on the next callback. */ +let chosenSubject = personalSubject + +function cookieHeader(response: Response, previous = '') { + const cookies = new Map() + for (const value of [...previous.split('; '), ...response.headers.getSetCookie()]) { + const pair = value.split(';')[0] + const separator = pair.indexOf('=') + if (separator > 0) cookies.set(pair.slice(0, separator), pair.slice(separator + 1)) + } + return [...cookies].map(([name, value]) => `${name}=${value}`).join('; ') +} + +describe('reconnecting a credential onto an account another credential uses', () => { + let auth: typeof import('@/lib/auth/auth').auth + let sessionCookie: string + + beforeAll(async () => { + ;({ auth } = await import('@/lib/auth/auth')) + const now = new Date() + await db.insert(user).values({ + id: userId, + name: 'Reconnect conflict fixture', + email, + emailVerified: true, + createdAt: now, + updatedAt: now, + }) + await db.insert(account).values({ + id: generateId(), + accountId: userId, + userId, + providerId: 'credential', + password: await hashPassword(fixturePassword), + createdAt: now, + updatedAt: now, + }) + await insertWorkspaceFixture(db, { + id: workspaceId, + name: 'Reconnect conflict fixture', + ownerId: userId, + billedAccountUserId: userId, + }) + + vi.stubGlobal('fetch', async (input: string | URL | Request, init?: RequestInit) => { + const target = typeof input === 'string' || input instanceof URL ? String(input) : input.url + if (target === DISCOVERY_URL) { + return jsonResponse({ + issuer: 'https://accounts.google.com', + authorization_endpoint: 'https://accounts.google.com/o/oauth2/v2/auth', + token_endpoint: TOKEN_URL, + userinfo_endpoint: USERINFO_URL, + }) + } + if (target === TOKEN_URL) { + return jsonResponse({ + access_token: `fresh-access-${chosenSubject}`, + refresh_token: `fresh-refresh-${chosenSubject}`, + expires_in: 3600, + token_type: 'Bearer', + }) + } + if (target === USERINFO_URL) { + return jsonResponse({ sub: chosenSubject, email, name: 'Reconnect conflict fixture' }) + } + return originalFetch(input, init) + }) + + const signIn = await auth.handler( + new Request(`${ORIGIN}/api/auth/sign-in/email`, { + method: 'POST', + headers: { 'content-type': 'application/json', origin: ORIGIN }, + body: JSON.stringify({ email, password: fixturePassword }), + }) + ) + expect(signIn.status).toBe(200) + sessionCookie = cookieHeader(signIn) + }, 90_000) + + beforeEach(async () => { + await db.delete(credential).where(eq(credential.workspaceId, workspaceId)) + await db + .delete(account) + .where(and(eq(account.userId, userId), eq(account.providerId, PROVIDER_ID))) + const past = new Date(Date.now() - 60_000) + await db.insert(account).values([ + { + id: workAccountRowId, + userId, + providerId: PROVIDER_ID, + accountId: `${workSubject}-${generateId()}`, + accessToken: 'work-access', + refreshToken: 'work-refresh', + createdAt: past, + updatedAt: past, + }, + { + id: personalAccountRowId, + userId, + providerId: PROVIDER_ID, + accountId: `${personalSubject}-${generateId()}`, + accessToken: 'personal-access', + refreshToken: 'personal-refresh', + createdAt: past, + updatedAt: past, + }, + ]) + await db.insert(credential).values([ + { + id: workCredentialId, + type: 'oauth', + workspaceId, + accountId: workAccountRowId, + providerId: PROVIDER_ID, + displayName: 'Work Drive', + createdBy: userId, + updatedAt: past, + }, + { + id: personalCredentialId, + type: 'oauth', + workspaceId, + accountId: personalAccountRowId, + providerId: PROVIDER_ID, + displayName: 'Personal Drive', + createdBy: userId, + updatedAt: past, + }, + ]) + }) + + afterAll(async () => { + globalThis.fetch = originalFetch + vi.unstubAllGlobals() + await deleteWorkspaceFixture(db, eq(workspace.id, workspaceId)) + await db.delete(user).where(eq(user.id, userId)) + }) + + /** Starts a reconnect of the work credential and returns the provider callback's response. */ + async function reconnectWorkCredentialAs(subject: string) { + chosenSubject = subject + const draftId = generateId() + await db.insert(pendingCredentialDraft).values({ + id: draftId, + userId, + workspaceId, + providerId: PROVIDER_ID, + displayName: 'Work Drive', + credentialId: workCredentialId, + expiresAt: new Date(Date.now() + 10 * 60_000), + }) + const startedFrom = `${ORIGIN}/workspace/${workspaceId}/integrations/connected/${workCredentialId}` + + const link = await auth.handler( + new Request(`${ORIGIN}/api/auth/oauth2/link`, { + method: 'POST', + headers: { 'content-type': 'application/json', origin: ORIGIN, cookie: sessionCookie }, + body: JSON.stringify({ + providerId: PROVIDER_ID, + callbackURL: `${startedFrom}?credentialDraftId=${draftId}`, + }), + }) + ) + expect(link.status).toBe(200) + const { url } = (await link.json()) as { url: string } + const state = new URL(url).searchParams.get('state') + if (!state) throw new Error('OAuth link did not return a state') + + const callback = await auth.handler( + new Request( + `${ORIGIN}/api/auth/oauth2/callback/${PROVIDER_ID}?code=fixture-code&state=${encodeURIComponent(state)}`, + { headers: { cookie: cookieHeader(link, sessionCookie) } } + ) + ) + return { callback, draftId, startedFrom } + } + + async function credentialAccount(credentialId: string) { + const [row] = await db + .select({ accountId: credential.accountId }) + .from(credential) + .where(eq(credential.id, credentialId)) + return row?.accountId + } + + async function providerAccountRows() { + return db + .select({ id: account.id, accessToken: account.accessToken }) + .from(account) + .where(and(eq(account.userId, userId), eq(account.providerId, PROVIDER_ID))) + } + + it('sends the user back with the reason, keeping each credential on its account', async () => { + const { callback, draftId, startedFrom } = await reconnectWorkCredentialAs(personalSubject) + + expect(callback.status).toBe(302) + const location = new URL(callback.headers.get('location') ?? '') + expect(`${location.origin}${location.pathname}`).toBe(startedFrom) + expect(location.searchParams.get('error')).toBe('credential_account_conflict') + expect(location.searchParams.get('error_description')).toBe( + 'That Google account is already connected in this workspace as "Personal Drive". Use that connection, or reconnect with the account that belongs to this one.' + ) + expect(location.searchParams.has('credentialDraftId')).toBe(false) + + expect(await credentialAccount(workCredentialId)).toBe(workAccountRowId) + expect(await credentialAccount(personalCredentialId)).toBe(personalAccountRowId) + const rows = await providerAccountRows() + expect(rows.map((row) => row.id).sort()).toEqual( + [workAccountRowId, personalAccountRowId].sort() + ) + expect(rows.find((row) => row.id === personalAccountRowId)?.accessToken).toBe( + `fresh-access-${personalSubject}` + ) + expect(rows.find((row) => row.id === workAccountRowId)?.accessToken).toBe('work-access') + const drafts = await db + .select({ id: pendingCredentialDraft.id }) + .from(pendingCredentialDraft) + .where(eq(pendingCredentialDraft.id, draftId)) + expect(drafts).toEqual([]) + }) + + it('still reconnects the credential when the user picks the identity it already had', async () => { + const { callback, startedFrom } = await reconnectWorkCredentialAs(workSubject) + + expect(callback.status).toBe(302) + const location = new URL(callback.headers.get('location') ?? '') + expect(`${location.origin}${location.pathname}`).toBe(startedFrom) + expect(location.searchParams.has('error')).toBe(false) + + const reconnectedAccountId = await credentialAccount(workCredentialId) + expect(reconnectedAccountId).not.toBe(workAccountRowId) + expect(await credentialAccount(personalCredentialId)).toBe(personalAccountRowId) + const rows = await providerAccountRows() + expect(rows.map((row) => row.id).sort()).toEqual( + [reconnectedAccountId, personalAccountRowId].sort() + ) + }) +}) diff --git a/apps/sim/lib/credentials/draft-constants.ts b/apps/sim/lib/credentials/draft-constants.ts index 26a244bf02c..b07a7ec85d6 100644 --- a/apps/sim/lib/credentials/draft-constants.ts +++ b/apps/sim/lib/credentials/draft-constants.ts @@ -1,3 +1,9 @@ export const CREDENTIAL_DRAFT_TTL_MS = 15 * 60 * 1000 export const CREDENTIAL_DRAFT_TTL_SECONDS = CREDENTIAL_DRAFT_TTL_MS / 1000 export const OAUTH_CREDENTIAL_DRAFT_CALLBACK_PARAM = 'credentialDraftId' +/** + * OAuth callback `error` code for a reconnect whose chosen account already backs + * another credential in the same workspace. Its `error_description` carries the + * message to show. + */ +export const OAUTH_CREDENTIAL_ACCOUNT_CONFLICT_ERROR = 'credential_account_conflict' diff --git a/apps/sim/lib/credentials/draft-hooks.ts b/apps/sim/lib/credentials/draft-hooks.ts index 98311f5f365..63c47924cd1 100644 --- a/apps/sim/lib/credentials/draft-hooks.ts +++ b/apps/sim/lib/credentials/draft-hooks.ts @@ -4,7 +4,7 @@ import * as schema from '@sim/db/schema' import { createLogger } from '@sim/logger' import { getPostgresConstraintName, getPostgresErrorCode } from '@sim/utils/errors' import { generateId } from '@sim/utils/id' -import { and, eq, sql } from 'drizzle-orm' +import { and, eq, inArray, ne } from 'drizzle-orm' import { deleteOrphanedOAuthAccount } from '@/lib/credentials/deletion' import { resumeConnectorsAfterCredentialReconnect } from '@/lib/knowledge/connectors/credential-recovery' import { clearOAuthRefreshFailure } from '@/lib/oauth/credential-service' @@ -12,6 +12,47 @@ import { captureServerEvent } from '@/lib/posthog/server' const logger = createLogger('CredentialDraftHooks') +/** + * A reconnect chose an account that already backs another credential in the + * same workspace. Two credentials in one workspace never share an account, so + * the reconnect is refused and the credential keeps the account it had. + */ +export class CredentialAccountConflictError extends Error { + constructor( + readonly credentialId: string, + readonly conflictingCredentialId: string + ) { + super( + `Cannot reconnect credential ${credentialId}: its new account is already used by credential ${conflictingCredentialId}` + ) + this.name = 'CredentialAccountConflictError' + } +} + +/** + * Finds a credential other than `credentialId` in the workspace that uses one + * of `accountIds`, the credential a reconnect onto those accounts would collide with. + */ +export async function findConflictingWorkspaceCredential(params: { + credentialId: string + workspaceId: string + accountIds: string[] +}): Promise<{ id: string; displayName: string } | null> { + if (params.accountIds.length === 0) return null + const [conflicting] = await db + .select({ id: schema.credential.id, displayName: schema.credential.displayName }) + .from(schema.credential) + .where( + and( + eq(schema.credential.workspaceId, params.workspaceId), + inArray(schema.credential.accountId, params.accountIds), + ne(schema.credential.id, params.credentialId) + ) + ) + .limit(1) + return conflicting ?? null +} + /** * Creates a new credential from a pending draft (normal OAuth connect flow). */ @@ -175,22 +216,13 @@ export async function handleReconnectCredential(params: { const accountChanged = oldAccountId !== newAccountId if (accountChanged) { - const [conflicting] = await db - .select({ id: schema.credential.id }) - .from(schema.credential) - .where( - and( - eq(schema.credential.workspaceId, workspaceId), - eq(schema.credential.accountId, newAccountId), - sql`${schema.credential.id} != ${draft.credentialId}` - ) - ) - .limit(1) - + const conflicting = await findConflictingWorkspaceCredential({ + credentialId: draft.credentialId, + workspaceId, + accountIds: [newAccountId], + }) if (conflicting) { - throw new Error( - `Cannot reconnect credential ${draft.credentialId}: account ${newAccountId} is already used by credential ${conflicting.id}` - ) + throw new CredentialAccountConflictError(draft.credentialId, conflicting.id) } } diff --git a/apps/sim/lib/credentials/draft-processor.ts b/apps/sim/lib/credentials/draft-processor.ts index 1ec7526736d..e49b829ccc0 100644 --- a/apps/sim/lib/credentials/draft-processor.ts +++ b/apps/sim/lib/credentials/draft-processor.ts @@ -1,18 +1,32 @@ import { db } from '@sim/db' import * as schema from '@sim/db/schema' import { createLogger } from '@sim/logger' -import { and, desc, eq, sql } from 'drizzle-orm' -import { OAUTH_CREDENTIAL_DRAFT_CALLBACK_PARAM } from '@/lib/credentials/draft-constants' +import { filterUndefined } from '@sim/utils/object' +import { and, desc, eq, inArray, sql } from 'drizzle-orm' +import { stableExternalAccountId } from '@/lib/auth/connectors/account-id' +import { getBaseUrl } from '@/lib/core/utils/urls' import { + OAUTH_CREDENTIAL_ACCOUNT_CONFLICT_ERROR, + OAUTH_CREDENTIAL_DRAFT_CALLBACK_PARAM, +} from '@/lib/credentials/draft-constants' +import { + findConflictingWorkspaceCredential, handleCreateCredentialFromDraft, handleReconnectCredential, } from '@/lib/credentials/draft-hooks' import { completeOrganizationCredentialDraft } from '@/lib/credentials/organization-draft' +import { resumeConnectorsAfterCredentialReconnect } from '@/lib/knowledge/connectors/credential-recovery' +import { APP_ENTRY_PATH } from '@/lib/navigation/paths' +import { clearOAuthRefreshFailure } from '@/lib/oauth/credential-service' +import { OAUTH_PROVIDERS } from '@/lib/oauth/oauth' +import type { OAuthProvider } from '@/lib/oauth/types' +import { parseProvider } from '@/lib/oauth/utils' const logger = createLogger('CredentialDraftProcessor') interface OAuthStateWithCallbackUrl { callbackURL?: unknown + errorURL?: unknown } export type OAuthCredentialDraftBinding = @@ -77,14 +91,18 @@ export async function loadOAuthCredentialDraftBinding( } } -/** Captures request-scoped OAuth state before Better Auth defers its account after-hook. */ +/** + * Captures request-scoped OAuth state before Better Auth defers its account + * after-hook, returning the draft id the state carries. + */ export async function captureOAuthCredentialDraftBinding( context: object, loadOAuthState: () => Promise -): Promise { +): Promise { const binding = await loadOAuthCredentialDraftBinding(loadOAuthState) if (binding.status === 'unavailable') throw binding.error oauthCredentialDraftBindings.set(context, binding) + return binding.draftId } /** Consumes the binding captured for the same Better Auth account-hook context. */ @@ -96,6 +114,139 @@ export function consumeOAuthCredentialDraftBinding( return binding } +interface CredentialReconnectConflictParams { + draftId: string + /** The account row Better Auth is about to insert, its `accountId` still carrying the random suffix. */ + account: { + userId: string + providerId: string + accountId: string + accessToken?: string | null + refreshToken?: string | null + idToken?: string | null + accessTokenExpiresAt?: Date | null + refreshTokenExpiresAt?: Date | null + } + oauthState: OAuthStateWithCallbackUrl | null | undefined +} + +/** + * Decides, before Better Auth inserts the account row, whether completing this + * reconnect draft would collide with another credential in its workspace. + * + * A new row for an external identity inherits every credential on that + * identity's older rows (the stale-sibling migration in `account.create.after`), + * so a reconnect onto an identity that already backs another credential in the + * workspace would leave two credentials on one account. When it would, the + * draft is discarded and this returns where to send the user: the page the + * reconnect started from, carrying the reason as the `error` and + * `error_description` the OAuth return handlers already read. + * + * Returning before the insert leaves every credential bound to the account it + * had. The grant itself is still real, so its tokens replace the ones on the + * identity's existing rows and their connectors resume, as they would have on + * the new row, and a provider that rotates on reauthorization cannot strand + * them on a dead chain. Each row keeps its stored scope, which can carry state + * a fresh grant does not repeat (a Salesforce instance host). + */ +export async function refuseConflictingCredentialReconnect( + params: CredentialReconnectConflictParams +): Promise { + const { draftId, account, oauthState } = params + const { userId, providerId } = account + const stableIdentity = stableExternalAccountId(account.accountId) + if (!stableIdentity) return null + + const [draft] = await db + .select({ + credentialId: schema.pendingCredentialDraft.credentialId, + workspaceId: schema.pendingCredentialDraft.workspaceId, + }) + .from(schema.pendingCredentialDraft) + .where( + and( + eq(schema.pendingCredentialDraft.id, draftId), + eq(schema.pendingCredentialDraft.userId, userId), + eq(schema.pendingCredentialDraft.providerId, providerId), + sql`${schema.pendingCredentialDraft.expiresAt} > NOW()` + ) + ) + .limit(1) + if (!draft?.credentialId || !draft.workspaceId) return null + + const [reconnecting] = await db + .select({ accountId: schema.credential.accountId }) + .from(schema.credential) + .where(eq(schema.credential.id, draft.credentialId)) + .limit(1) + if (!reconnecting) return null + + const identityAccountIds = ( + await db + .select({ id: schema.account.id, accountId: schema.account.accountId }) + .from(schema.account) + .where(and(eq(schema.account.userId, userId), eq(schema.account.providerId, providerId))) + ) + .filter((row) => stableExternalAccountId(row.accountId) === stableIdentity) + .map((row) => row.id) + if (reconnecting.accountId && identityAccountIds.includes(reconnecting.accountId)) return null + + const conflicting = await findConflictingWorkspaceCredential({ + credentialId: draft.credentialId, + workspaceId: draft.workspaceId, + accountIds: identityAccountIds, + }) + if (!conflicting) return null + + const now = new Date() + await db + .update(schema.account) + .set({ + ...filterUndefined({ + accessToken: account.accessToken ?? undefined, + refreshToken: account.refreshToken ?? undefined, + idToken: account.idToken ?? undefined, + accessTokenExpiresAt: account.accessTokenExpiresAt ?? undefined, + refreshTokenExpiresAt: account.refreshTokenExpiresAt ?? undefined, + }), + updatedAt: now, + }) + .where(inArray(schema.account.id, identityAccountIds)) + for (const id of identityAccountIds) { + await clearOAuthRefreshFailure(id) + await resumeConnectorsAfterCredentialReconnect(id, now) + } + + await db + .delete(schema.pendingCredentialDraft) + .where(eq(schema.pendingCredentialDraft.id, draftId)) + + logger.warn('Refused a credential reconnect onto an account another credential uses', { + draftId, + userId, + providerId, + credentialId: draft.credentialId, + conflictingCredentialId: conflicting.id, + }) + + const returnUrl = [oauthState?.callbackURL, oauthState?.errorURL].find( + (url): url is string => typeof url === 'string' && url.length > 0 + ) + const redirectUrl = new URL(returnUrl ?? APP_ENTRY_PATH, getBaseUrl()) + redirectUrl.searchParams.delete(OAUTH_CREDENTIAL_DRAFT_CALLBACK_PARAM) + redirectUrl.searchParams.set('error', OAUTH_CREDENTIAL_ACCOUNT_CONFLICT_ERROR) + redirectUrl.searchParams.set( + 'error_description', + `That ${providerDisplayName(providerId)} account is already connected in this workspace as "${conflicting.displayName}". Use that connection, or reconnect with the account that belongs to this one.` + ) + return redirectUrl.toString() +} + +function providerDisplayName(providerId: string): string { + const { baseProvider } = parseProvider(providerId as OAuthProvider) + return OAUTH_PROVIDERS[baseProvider]?.name ?? 'provider' +} + interface ProcessCredentialDraftParams { draftId?: string userId: string diff --git a/apps/sim/lib/execution/isolated-vm-host.cjs b/apps/sim/lib/execution/isolated-vm-host.cjs index ca194d8ef2d..802e7115116 100644 --- a/apps/sim/lib/execution/isolated-vm-host.cjs +++ b/apps/sim/lib/execution/isolated-vm-host.cjs @@ -14,7 +14,10 @@ * are the objects the worker * exchanges over IPC. Host-originated frames are `{ type: 'host:heartbeat' }` * every 30s and `{ type: 'host:draining' }` on SIGTERM, after which the app - * retires the connection once its executions finish. A breaking change to the + * retires the connection once its executions finish. A load balancer that + * deregisters this host sends nothing until SIGTERM, so the app also retires + * each connection at a maximum age, and a deregistered host drains as its + * connections age out. A breaking change to the * contract gets a new path served alongside this one until every client has * rolled. * @@ -36,6 +39,12 @@ const { WebSocketServer } = require('ws') const WORKER_PATH = '/v1/worker' const HEARTBEAT_INTERVAL_MS = 30000 const AUTH_TIMEOUT_MS = 5000 +/** + * Raw bytes a connection may send before it authenticates: the auth frame is + * well under 1 KiB. Without this, `maxPayload` lets every unauthenticated + * connection make the host buffer a full-size frame. + */ +const MAX_PRE_AUTH_BYTES = 16 * 1024 const WORKER_START_TIMEOUT_MS = 10000 const MAX_STARTUP_STDERR_CHARS = 64 * 1024 const MIN_TOKEN_LENGTH = 32 @@ -179,13 +188,28 @@ server.on('upgrade', (req, socket, head) => { rejectUpgrade(socket, 503, 'Service Unavailable') return } - wss.handleUpgrade(req, socket, head, (ws) => authenticate(ws)) + wss.handleUpgrade(req, socket, head, (ws) => authenticate(ws, socket)) }) /** Admits the connection to a worker slot only once its first frame proves it holds the token. */ -function authenticate(ws) { +function authenticate(ws, socket) { pendingConnections++ let settled = false + let authenticated = false + let preAuthBytes = 0 + // Counts what arrives on the TCP socket, so an oversized frame is cut off as it streams in + // rather than after ws has buffered all of it. + const onPreAuthData = (chunk) => { + // ws parses each chunk before this listener runs, so the chunk that authenticated still arrives. + // A refused connection stays counted: its peer may ignore the close and keep sending. + if (authenticated) return + preAuthBytes += chunk.length + if (preAuthBytes <= MAX_PRE_AUTH_BYTES) return + if (settle()) { + log('warn', 'Rejected worker connection', { reason: 'too much data before authentication' }) + } + socket.destroy() + } const settle = () => { if (settled) return false settled = true @@ -199,6 +223,7 @@ function authenticate(ws) { ws.close(UNAUTHORIZED_CLOSE_CODE, 'unauthorized') } const authTimeout = setTimeout(() => refuse('authentication timed out'), AUTH_TIMEOUT_MS) + socket.on('data', onPreAuthData) const onPreAuthError = (error) => { log('warn', 'Worker connection error before authentication', { error: error.message }) } @@ -214,6 +239,8 @@ function authenticate(ws) { return } if (!settle()) return + authenticated = true + socket.off('data', onPreAuthData) if (draining) { ws.close(1012, 'draining') return diff --git a/apps/sim/lib/execution/isolated-vm-remote.ts b/apps/sim/lib/execution/isolated-vm-remote.ts index 9ababaf2716..04312717eb1 100644 --- a/apps/sim/lib/execution/isolated-vm-remote.ts +++ b/apps/sim/lib/execution/isolated-vm-remote.ts @@ -9,6 +9,17 @@ const HOST_SILENCE_LIMIT_MS = 75_000 const REMOTE_WORKER_URL_PATTERN = /^wss?:\/\/[^/]+\/v1\/worker$/ const MIN_REMOTE_WORKER_TOKEN_LENGTH = 32 +/** + * Thrown by a remote worker's `send` once its connection is closing: nothing was + * delivered, so the message never reached the host. + */ +export class WorkerConnectionClosedError extends Error { + constructor() { + super('Remote isolated-vm worker connection is closed') + this.name = 'WorkerConnectionClosedError' + } +} + /** * The slice of `ChildProcess` the isolated-vm pool uses, so a local child and a * connection to a remote worker host are interchangeable. @@ -113,9 +124,12 @@ export function connectRemoteWorker(options: RemoteWorkerOptions): IsolatedVMWor }) return { - /** Returns false once the connection is closing; the pending `exit` settles this worker's executions. */ + /** + * Throws {@link WorkerConnectionClosedError} once the connection is closing, so the pool can + * tell a message that never left this process from one the host may have acted on. + */ send(message) { - if (socket.readyState !== WebSocket.OPEN) return false + if (socket.readyState !== WebSocket.OPEN) throw new WorkerConnectionClosedError() socket.send(JSON.stringify(message)) return true }, diff --git a/apps/sim/lib/execution/isolated-vm.test.ts b/apps/sim/lib/execution/isolated-vm.test.ts index 421d5af2bcc..c1f04e9e47f 100644 --- a/apps/sim/lib/execution/isolated-vm.test.ts +++ b/apps/sim/lib/execution/isolated-vm.test.ts @@ -275,6 +275,47 @@ class UnreachableWebSocket extends EventTarget { close() {} } +/** + * A worker host that accepts every connection and answers each execution. A test closes one by + * setting `readyState` to CLOSING, the state a connection is in before its close event arrives. + */ +class ReachableWebSocket extends EventTarget { + static readonly OPEN = 1 + static readonly instances: ReachableWebSocket[] = [] + readyState = 0 + readonly executionIds: number[] = [] + + constructor() { + super() + ReachableWebSocket.instances.push(this) + setImmediate(() => { + this.readyState = 1 + this.dispatchEvent(new Event('open')) + }) + } + + send(data: string) { + const message = JSON.parse(data) as { type: string; executionId?: number } + if (message.type === 'auth') this.reply({ type: 'ready' }) + if (message.type === 'execute' && message.executionId !== undefined) { + this.executionIds.push(message.executionId) + this.reply({ + type: 'result', + executionId: message.executionId, + result: { result: 'ran remotely', stdout: '' }, + }) + } + } + + close() {} + + private reply(message: unknown) { + setImmediate(() => + this.dispatchEvent(new MessageEvent('message', { data: JSON.stringify(message) })) + ) + } +} + describe('isolated-vm scheduler', () => { it('recovers from an initial spawn failure and drains queued work', async () => { const { executeInIsolatedVM, spawnMock } = await loadExecutionModule({ @@ -416,6 +457,69 @@ describe('isolated-vm scheduler', () => { } }) + it('returns a cancelled call without waiting on the worker target flag', async () => { + featureFlagsMockFns.mockIsFeatureEnabled.mockImplementation(() => new Promise(() => {})) + try { + const { executeInIsolatedVM } = await loadExecutionModule({ + envOverrides: { + IVM_REMOTE_WORKER_URL: 'ws://worker-host.internal:3100/v1/worker', + IVM_REMOTE_WORKER_TOKEN: 'remote-worker-token-of-at-least-32-chars', + }, + spawns: [], + }) + const controller = new AbortController() + controller.abort() + + const result = await executeInIsolatedVM( + { + code: 'return 1', + params: {}, + envVars: {}, + contextVariables: {}, + timeoutMs: 100, + requestId: 'req-pre-aborted', + }, + { signal: controller.signal } + ) + + expect(result.termination).toBe('cancelled') + } finally { + featureFlagsMockFns.mockIsFeatureEnabled.mockReset().mockResolvedValue(false) + } + }) + + it('moves an execution to a new worker when its connection closed before it was sent', async () => { + ReachableWebSocket.instances.length = 0 + vi.stubGlobal('WebSocket', ReachableWebSocket) + const { executeInIsolatedVM } = await loadExecutionModule({ + envOverrides: { + IVM_REMOTE_WORKER_URL: 'ws://worker-host.internal:3100/v1/worker', + IVM_REMOTE_WORKER_TOKEN: 'remote-worker-token-of-at-least-32-chars', + }, + spawns: [], + }) + const request = { + code: 'return 1', + params: {}, + envVars: {}, + contextVariables: {}, + timeoutMs: 100, + } + + const warm = await executeInIsolatedVM({ ...request, requestId: 'req-warm' }) + expect(warm.result).toBe('ran remotely') + const [closing] = ReachableWebSocket.instances + if (!closing) throw new Error('Expected the first worker connection') + closing.readyState = 2 + + const result = await executeInIsolatedVM({ ...request, requestId: 'req-after-close' }) + + expect(result.error).toBeUndefined() + expect(result.result).toBe('ran remotely') + expect(closing.executionIds).toHaveLength(1) + expect(ReachableWebSocket.instances).toHaveLength(2) + }) + it('rejects new requests when the queue is full', async () => { const holder = createControllableReadyProc() const { executeInIsolatedVM } = await loadExecutionModule({ diff --git a/apps/sim/lib/execution/isolated-vm.ts b/apps/sim/lib/execution/isolated-vm.ts index 5da070f4e1a..66ac6ce06d3 100644 --- a/apps/sim/lib/execution/isolated-vm.ts +++ b/apps/sim/lib/execution/isolated-vm.ts @@ -6,7 +6,7 @@ import { createLogger } from '@sim/logger' import { getErrorMessage, toError } from '@sim/utils/errors' import { filterUndefined } from '@sim/utils/object' import { randomFloat } from '@sim/utils/random' -import { env } from '@/lib/core/config/env' +import { env, envNumber } from '@/lib/core/config/env' import { getConfiguredCacheProvider } from '@/lib/core/config/env-capabilities.server' import { isFeatureEnabled } from '@/lib/core/config/feature-flags' import { getRedisClient } from '@/lib/core/config/redis' @@ -21,6 +21,7 @@ import { MAX_ISOLATED_VM_BROKER_RESULT_JSON_CHARS } from '@/lib/execution/isolat import { connectRemoteWorker, type IsolatedVMWorkerProcess, + WorkerConnectionClosedError, } from '@/lib/execution/isolated-vm-remote' const logger = createLogger('IsolatedVMExecution') @@ -147,6 +148,20 @@ const DISTRIBUTED_MAX_INFLIGHT_PER_OWNER = MAX_ACTIVE_PER_OWNER + MAX_QUEUED_PER_OWNER const DISTRIBUTED_LEASE_MIN_TTL_MS = Number.parseInt(env.IVM_DISTRIBUTED_LEASE_MIN_TTL_MS) || 120000 const MAX_EXECUTIONS_PER_WORKER = Number.parseInt(env.IVM_MAX_EXECUTIONS_PER_WORKER) || 200 +/** + * How long a remote worker connection takes new executions before it retires, finishing what it + * runs. A load balancer keeps a deregistered host's open connections only for its deregistration + * delay and never tells the host, so this bound is what drains a host deploy or scale-in: infra + * sets that delay to at least this age plus the longest execution a release keeps alive. + */ +const REMOTE_WORKER_MAX_AGE_MS = envNumber(env.IVM_REMOTE_WORKER_MAX_AGE_MS, 120_000, { + min: 1000, + integer: true, +}) +/** Spreads retirements so a pool's connections don't all reopen at once; only ever shortens the age. */ +const REMOTE_WORKER_MAX_AGE_JITTER = 0.2 +/** Times one execution moves to another worker because its connection closed before it was sent. */ +const MAX_UNSENT_REDISPATCHES = 3 const MAX_BROKER_ARGS_JSON_CHARS = Number.parseInt(env.IVM_MAX_BROKER_ARGS_JSON_CHARS) || 262_144 const MAX_BROKERS_PER_EXECUTION = Number.parseInt(env.IVM_MAX_BROKERS_PER_EXECUTION) || 1000 const DISTRIBUTED_KEY_PREFIX = 'ivm:fair:v1:owner' @@ -190,6 +205,8 @@ interface WorkerInfo { activeExecutions: number pendingExecutions: Map idleTimeout: ReturnType | null + /** Retires a remote worker at {@link REMOTE_WORKER_MAX_AGE_MS}. */ + maxAgeTimeout: ReturnType | null id: number lifetimeExecutions: number retiring: boolean @@ -217,6 +234,8 @@ interface ExecutionState { queueId?: number workerId?: number execId?: number + /** Dispatches that found the worker connection already closed, so nothing ran. */ + unsentRedispatches: number } interface QueueNode { @@ -861,49 +880,42 @@ function handleWorkerMessage(workerId: number, message: unknown) { } if (msg.type === 'host:draining') { - if (!workerInfo || workerInfo.retiring) return - workerInfo.retiring = true - logger.info('Remote worker host draining; retiring worker', { workerId }) - if (workerInfo.activeExecutions === 0) cleanupWorker(workerId) - drainQueue() + retireWorker(workerId, 'host_draining') return } if (msg.type === 'fetch') { + const fetchId = msg.fetchId + const sendFetchResponse = (response: string) => { + try { + workerInfo?.process.send({ type: 'fetchResponse', fetchId, response }) + } catch (err) { + logger.error('Failed to send fetch response to worker', { err, fetchId, workerId }) + } + } const pending = typeof msg.executionId === 'number' ? workerInfo?.pendingExecutions.get(msg.executionId) : undefined if (!pending || pending.cancelled) { - workerInfo?.process.send({ - type: 'fetchResponse', - fetchId: msg.fetchId, - response: JSON.stringify({ error: 'Execution no longer active' }), - }) + sendFetchResponse(JSON.stringify({ error: 'Execution no longer active' })) return } - const { fetchId, requestId, url, optionsJson } = msg as { - fetchId: number + const { requestId, url, optionsJson } = msg as { requestId: string url: string optionsJson?: string } if (typeof url !== 'string' || url.length === 0) { - workerInfo?.process.send({ - type: 'fetchResponse', - fetchId, - response: JSON.stringify({ error: 'Invalid fetch URL' }), - }) + sendFetchResponse(JSON.stringify({ error: 'Invalid fetch URL' })) return } if (optionsJson && optionsJson.length > MAX_FETCH_OPTIONS_JSON_CHARS) { - workerInfo?.process.send({ - type: 'fetchResponse', - fetchId, - response: JSON.stringify({ + sendFetchResponse( + JSON.stringify({ error: `Fetch options exceed maximum payload size (${MAX_FETCH_OPTIONS_JSON_CHARS} chars)`, - }), - }) + }) + ) return } @@ -912,46 +924,50 @@ function handleWorkerMessage(workerId: number, message: unknown) { try { options = JSON.parse(optionsJson) } catch { - workerInfo?.process.send({ - type: 'fetchResponse', - fetchId, - response: JSON.stringify({ error: 'Invalid fetch options JSON' }), - }) + sendFetchResponse(JSON.stringify({ error: 'Invalid fetch options JSON' })) return } } pending .runInOutboundScope(() => secureFetch(requestId, url, options)) - .then((response) => { - try { - workerInfo?.process.send({ type: 'fetchResponse', fetchId, response }) - } catch (err) { - logger.error('Failed to send fetch response to worker', { err, fetchId, workerId }) - } - }) + .then(sendFetchResponse) .catch((err) => { - try { - workerInfo?.process.send({ - type: 'fetchResponse', - fetchId, - response: JSON.stringify({ - error: getErrorMessage(err, 'Fetch failed'), - }), - }) - } catch (sendErr) { - logger.error('Failed to send fetch error to worker', { sendErr, fetchId, workerId }) - } + sendFetchResponse(JSON.stringify({ error: getErrorMessage(err, 'Fetch failed') })) }) } } -function cleanupWorker(workerId: number) { +/** + * Stops a worker taking new executions; it closes once those it is running finish, and queued + * work moves to a fresh worker. + */ +function retireWorker(workerId: number, reason: 'host_draining' | 'max_age') { + const workerInfo = workers.get(workerId) + if (!workerInfo || workerInfo.retiring) return + workerInfo.retiring = true + logger.info('Retiring isolated-vm worker', { + workerId, + reason, + activeExecutions: workerInfo.activeExecutions, + }) + if (workerInfo.activeExecutions === 0) cleanupWorker(workerId) + drainQueue() +} + +/** + * Closes a worker and fails what it was still running. `interruptedMessage` replaces the generic + * failure when the cause is known. + */ +function cleanupWorker(workerId: number, interruptedMessage?: string) { const workerInfo = workers.get(workerId) if (!workerInfo) return if (workerInfo.idleTimeout) { clearTimeout(workerInfo.idleTimeout) } + if (workerInfo.maxAgeTimeout) { + clearTimeout(workerInfo.maxAgeTimeout) + } workerInfo.process.kill() @@ -967,7 +983,7 @@ function cleanupWorker(workerId: number) { result: null, stdout: '', error: { - message: 'Code execution failed unexpectedly. Please try again.', + message: interruptedMessage ?? 'Code execution failed unexpectedly. Please try again.', name: 'Error', isSystemError: true, }, @@ -1113,6 +1129,7 @@ function spawnWorker(): Promise { activeExecutions: 0, pendingExecutions: new Map(), idleTimeout: null, + maxAgeTimeout: null, id: workerId, targetKey: workerTargetKey(target), lifetimeExecutions: 0, @@ -1161,6 +1178,12 @@ function spawnWorker(): Promise { proc.off('message', readyHandler) workers.set(workerId, workerInfo) resetWorkerIdleTimeout(workerId) + if (target.kind === 'remote' && !workerInfo.retiring) { + workerInfo.maxAgeTimeout = setTimeout( + () => retireWorker(workerId, 'max_age'), + REMOTE_WORKER_MAX_AGE_MS * (1 - randomFloat() * REMOTE_WORKER_MAX_AGE_JITTER) + ) + } logger.info('Worker spawned and ready', { workerId, poolSize: workers.size }) resolve() } @@ -1190,7 +1213,12 @@ function spawnWorker(): Promise { return } - cleanupWorker(workerId) + cleanupWorker( + workerId, + target.kind === 'remote' + ? 'Code execution was interrupted because the connection to its sandbox host closed. Please try again.' + : undefined + ) drainQueue() }) }) @@ -1332,13 +1360,42 @@ function dispatchToWorker( runtimeBindingSource: buildJavaScriptRuntimeBindingsSource(runtimeBindings ?? []), }, }) - } catch { + } catch (error) { clearTimeout(timeout) workerInfo.pendingExecutions.delete(execId) workerInfo.activeExecutions-- totalActiveExecutions-- ownerState.activeExecutions = Math.max(0, ownerState.activeExecutions - 1) maybeCleanupOwner(ownerState.ownerKey) + // The connection closed before the request left this process, so nothing ran: the execution + // can safely move to another worker. One that may have reached the host is never re-run. + if ( + error instanceof WorkerConnectionClosedError && + state.unsentRedispatches < MAX_UNSENT_REDISPATCHES + ) { + state.unsentRedispatches++ + state.workerId = undefined + state.execId = undefined + logger.warn('Worker connection closed before an execution was sent; dispatching it again', { + workerId: workerInfo.id, + attempt: state.unsentRedispatches, + }) + workerInfo.retiring = true + if (workerInfo.activeExecutions === 0) cleanupWorker(workerInfo.id) + // The owner's state may have been released above; look it up again rather than queue on it. + queueMicrotask(() => { + // An abort in between already settled the caller and has no queue entry to remove. + if (state.cancelled) return + enqueueExecution( + getOrCreateOwnerState(ownerState.ownerKey, ownerState.weight), + req, + resolve, + state, + brokers + ) + }) + return + } resolve({ result: null, stdout: '', @@ -1495,10 +1552,8 @@ export async function executeInIsolatedVM( req: IsolatedVMExecutionRequest, options?: IsolatedVMExecutionOptions ): Promise { - activateWorkerTarget(await resolveWorkerTarget()) const ownerKey = normalizeOwnerKey(req.ownerKey) const ownerWeight = normalizeOwnerWeight(req.ownerWeight) - const ownerState = getOrCreateOwnerState(ownerKey, ownerWeight) const brokers = options?.brokers const signal = options?.signal @@ -1529,6 +1584,10 @@ export async function executeInIsolatedVM( } } + // After the checks above, so a cancelled or misconfigured call returns without waiting on the + // flag read behind the target. + activateWorkerTarget(await resolveWorkerTarget()) + const distributedLeaseId = `${req.requestId}:${Date.now()}:${randomFloat().toString(36).slice(2, 10)}` const leaseAcquireResult = await tryAcquireDistributedLease( ownerKey, @@ -1587,7 +1646,14 @@ export async function executeInIsolatedVM( // An undetermined lease cannot reject the execution: the per-process pool and // the per-owner active/queued limits above still bound this work. - const state: ExecutionState = { cancelled: false, runInOutboundScope: captureOutboundScope() } + // Looked up only after the waits above: another execution finishing meanwhile can release + // this owner's state, and work queued on a released state is never dispatched. + const ownerState = getOrCreateOwnerState(ownerKey, ownerWeight) + const state: ExecutionState = { + cancelled: false, + runInOutboundScope: captureOutboundScope(), + unsentRedispatches: 0, + } return new Promise((resolve) => { let abortListener: (() => void) | null = null diff --git a/apps/sim/lib/knowledge/transfer/bundle.test.ts b/apps/sim/lib/knowledge/transfer/bundle.test.ts index 1d1bca7fe4e..36ada0cf1cf 100644 --- a/apps/sim/lib/knowledge/transfer/bundle.test.ts +++ b/apps/sim/lib/knowledge/transfer/bundle.test.ts @@ -71,6 +71,15 @@ describe('knowledgeBundleManifestSchema', () => { ).toBe(false) }) + /** The tag cross-checks read each entry, so they must never see an oversized list unparsed. */ + it('refuses an oversized tag list on its size before the tag cross-checks read it', () => { + const result = knowledgeBundleManifestSchema.safeParse(manifest({ tags: Array(100).fill({}) })) + + expect(result.error?.issues).toEqual([ + expect.objectContaining({ code: 'too_big', path: ['tags'] }), + ]) + }) + it('refuses duplicate tag slots and case-insensitively duplicate tag names', () => { expect( knowledgeBundleManifestSchema.safeParse( diff --git a/apps/sim/lib/workflows/editing/builders.test.ts b/apps/sim/lib/workflows/editing/builders.test.ts index fcacd239f57..2d222e8f870 100644 --- a/apps/sim/lib/workflows/editing/builders.test.ts +++ b/apps/sim/lib/workflows/editing/builders.test.ts @@ -16,8 +16,11 @@ import { resolveBlockRetryUpdate, } from '@/lib/workflows/editing/builders' import type { SkippedItem } from '@/lib/workflows/editing/types' +import { TailscaleBlock } from '@/blocks/blocks/tailscale' import { getAllBlocks, getBlock } from '@/blocks/registry' import { prepareBlockState } from '@/stores/workflows/prepare-block-state' +import type { BlockState } from '@/stores/workflows/workflow/types' +import { tailscaleAuthorizeDeviceTool } from '@/tools/tailscale' const mockIsIntegrationDeploymentAvailable = integrationsAvailabilityMockFns.mockIsIntegrationDeploymentAvailableForVisibility @@ -137,6 +140,7 @@ const gatedOperationBlockConfig = { } const blocksByType: Record = { + tailscale: TailscaleBlock, api: apiBlockConfig, agent: agentBlockConfig, mothership: { ...agentBlockConfig, type: 'mothership' }, @@ -148,6 +152,68 @@ const blocksByType: Record = { } describe('createBlockFromParams', () => { + it.each([ + [{}, true], + [{ authorized: false }, false], + ] as const)( + 'preserves authorization intent from API block creation through the provider request for %j', + (provided, expected) => { + const block: BlockState = createBlockFromParams('device-authorization', { + type: 'tailscale', + name: 'Device authorization', + inputs: { + operation: 'authorize_device', + apiKey: 'test-token', + deviceId: 'device', + ...provided, + }, + }) + const values = Object.fromEntries( + Object.entries(block.subBlocks).map(([id, field]) => [id, field.value]) + ) + const resolved = TailscaleBlock.tools?.config?.params?.(values) + if (!resolved || typeof resolved.authorized !== 'boolean') { + throw new Error('Authorization did not resolve to a boolean') + } + const body = tailscaleAuthorizeDeviceTool.request.body?.({ + apiKey: 'test-token', + deviceId: 'device', + authorized: resolved.authorized, + }) + expect(body).toEqual({ authorized: expected }) + } + ) + + it('treats a null runtime switch as unset while preserving explicit false', () => { + const transform = TailscaleBlock.tools?.config?.params + if (!transform) throw new Error('Tailscale has no parameter transform') + expect(transform({ operation: 'authorize_device', authorized: null })).toMatchObject({ + authorized: true, + }) + expect(transform({ operation: 'authorize_device', authorized: 'false' })).toMatchObject({ + authorized: false, + }) + }) + + it('rejects an invalid authorization value before a provider request can change access', () => { + const transform = TailscaleBlock.tools?.config?.params + if (!transform) throw new Error('Tailscale has no parameter transform') + expect(() => transform({ operation: 'authorize_device', authorized: 'invalid' })).toThrow() + }) + + it('keeps dormant values from blocking the selected operation', () => { + const transform = TailscaleBlock.tools?.config?.params + if (!transform) throw new Error('Tailscale has no parameter transform') + expect( + transform({ + operation: 'authorize_device', + authorized: false, + reusable: 'inactive value', + expirySeconds: 'inactive value', + }) + ).toMatchObject({ authorized: false }) + }) + it('exposes the output ports of the seeded Agent default', () => { const block = createBlockFromParams( 'agent-research-default', diff --git a/apps/sim/package.json b/apps/sim/package.json index a9b5db56c7b..dc0d465d8fd 100644 --- a/apps/sim/package.json +++ b/apps/sim/package.json @@ -237,7 +237,7 @@ "next": "16.4.1", "next-mdx-remote": "^6.0.0", "next-themes": "^0.4.6", - "nodemailer": "10.1.0", + "nodemailer": "10.1.7", "nuqs": "2.10.2", "officeparser": "5.2.2", "openai": "7.32.0", @@ -273,7 +273,7 @@ "tldts": "7.4.18", "twilio": "6.2.0", "typebox": "1.3.27", - "undici": "7.30.0", + "undici": "7.30.1", "unified": "11.0.5", "word-extractor": "1.0.4", "ws": "8.21.3", diff --git a/apps/sim/public/changelog/knowledge-open-rooms-v1.jpg b/apps/sim/public/changelog/knowledge-open-rooms-v1.jpg new file mode 100644 index 00000000000..819d97f16a7 Binary files /dev/null and b/apps/sim/public/changelog/knowledge-open-rooms-v1.jpg differ diff --git a/apps/sim/scripts/test-isolated-vm-remote-e2e.ts b/apps/sim/scripts/test-isolated-vm-remote-e2e.ts index ac5def14d0b..06e58e865d8 100644 --- a/apps/sim/scripts/test-isolated-vm-remote-e2e.ts +++ b/apps/sim/scripts/test-isolated-vm-remote-e2e.ts @@ -2,18 +2,19 @@ import assert from 'node:assert/strict' import { type ChildProcess, execFileSync, spawn } from 'node:child_process' import { writeFile } from 'node:fs/promises' import { createServer as createHttpServer, request } from 'node:http' -import { createServer } from 'node:net' +import { connect, createServer, type Server, type Socket } from 'node:net' import path from 'node:path' import { fileURLToPath } from 'node:url' import { createLogger } from '@sim/logger' import { getErrorMessage } from '@sim/utils/errors' import { sleep } from '@sim/utils/helpers' -import { generateRandomHex } from '@sim/utils/random' +import { generateRandomBytes, generateRandomHex } from '@sim/utils/random' /** * Runs the isolated-vm pool against a real `isolated-vm-host.cjs` over real * WebSockets, the topology used when `IVM_REMOTE_WORKER_URL` is set. This process plays the app; the - * hosts are separate Node processes. + * hosts are separate Node processes, reached through a TCP balancer that behaves like the internal + * ALB in front of them. * * Usage: bun run apps/sim/scripts/test-isolated-vm-remote-e2e.ts * Writes a JSON report to IVM_REMOTE_E2E_REPORT_PATH when set. @@ -30,11 +31,19 @@ const HOST_SCRIPT = path.join( const HOST_ONLY_VALUE = `host-only-${generateRandomHex(8)}` /** Set on the app only; a remote worker that honors it got its limits from the app. */ const STDOUT_LIMIT_CHARS = 1000 +/** The app's remote worker max age (`IVM_REMOTE_WORKER_MAX_AGE_MS`), short so a drain fits a check. */ +const WORKER_MAX_AGE_MS = 1000 +/** The longest execution the drain check protects. */ +const LONG_EXECUTION_MS = 1500 +/** Sized the way infra sizes the host's target group: max age + longest execution + margin. */ +const DEREGISTRATION_DELAY_MS = WORKER_MAX_AGE_MS + LONG_EXECUTION_MS + 1500 const checks: { name: string; status: 'passed' | 'failed'; durationMs: number; error?: string }[] = [] const startedAt = new Date().toISOString() const hosts: Host[] = [] +let closeBalancer = () => {} +let closeSlowServer = () => {} interface Host { process: ChildProcess @@ -76,9 +85,8 @@ function resolveNodeBinary(): string { const NODE_BINARY = resolveNodeBinary() -async function startHost(maxWorkers: number): Promise { +async function startHost(maxWorkers: number, token = generateRandomHex(32)): Promise { const port = await freePort() - const token = generateRandomHex(32) const child = spawn(NODE_BINARY, [HOST_SCRIPT], { env: { PATH: process.env.PATH, @@ -112,6 +120,58 @@ async function startHost(maxWorkers: number): Promise { throw new Error('Worker host did not become healthy') } +/** + * Stands in for the ALB: each new connection goes to the current target, and repointing the target + * is deregistration, which leaves open connections where they are. Destroying what is still open + * on a host is the deregistration delay expiring. + */ +interface Balancer { + port: number + target: Host + open(host: Host): number + routed(host: Host): number + cut(host: Host): void + close(): void +} + +async function startBalancer(target: Host): Promise { + const connections = new Map>() + const routedCounts = new Map() + const server: Server = createServer((client) => { + const host = balancer.target + routedCounts.set(host, (routedCounts.get(host) ?? 0) + 1) + const upstream = connect(host.port, '127.0.0.1') + const open = connections.get(host) ?? new Set() + connections.set(host, open) + open.add(upstream) + const teardown = () => { + open.delete(upstream) + client.destroy() + upstream.destroy() + } + client.on('error', teardown) + client.on('close', teardown) + upstream.on('error', teardown) + upstream.on('close', teardown) + client.pipe(upstream) + upstream.pipe(client) + }) + await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)) + const address = server.address() + assert(address && typeof address === 'object') + const balancer: Balancer = { + port: address.port, + target, + open: (host) => connections.get(host)?.size ?? 0, + routed: (host) => routedCounts.get(host) ?? 0, + cut: (host) => { + for (const socket of connections.get(host) ?? []) socket.destroy() + }, + close: () => server.close(), + } + return balancer +} + /** Sends a bare WebSocket upgrade and returns the HTTP status the host answers with. */ function upgradeStatus(host: Host, options: { path?: string } = {}): Promise { return new Promise((resolve, reject) => { @@ -139,6 +199,60 @@ function upgradeStatus(host: Host, options: { path?: string } = {}): Promise { + const socket = connect(host.port, '127.0.0.1') + socket.on('error', () => {}) + const closed = new Promise((resolve) => socket.once('close', () => resolve())) + await new Promise((resolve) => socket.once('connect', () => resolve())) + const handshake = new Promise((resolve) => + socket.once('data', (data: Buffer) => resolve(data.toString())) + ) + socket.write( + [ + 'GET /v1/worker HTTP/1.1', + `Host: 127.0.0.1:${host.port}`, + 'Upgrade: websocket', + 'Connection: Upgrade', + 'Sec-WebSocket-Version: 13', + `Sec-WebSocket-Key: ${Buffer.from(generateRandomBytes(16)).toString('base64')}`, + '', + '', + ].join('\r\n') + ) + const response = await handshake + assert.match(response, /^HTTP\/1\.1 101/, `Expected the upgrade to be accepted: ${response}`) + if (firstFrame) { + const payload = Buffer.from(firstFrame) + socket.write(Buffer.concat([maskedTextFrameHeader(payload.length), payload])) + } + socket.write(maskedTextFrameHeader(32 * 1024 * 1024)) + const chunk = Buffer.alloc(64 * 1024) + for (let sent = 0; sent < 1024 * 1024 && !socket.destroyed; sent += chunk.length) { + socket.write(chunk) + } + const outcome = await Promise.race([ + closed.then(() => 'closed' as const), + sleep(1000).then(() => 'open' as const), + ]) + socket.destroy() + return outcome +} + /** Opens a connection and sends `firstFrame`; resolves with the socket once it opens. */ function openSocket(host: Host, firstFrame: string): Promise { return new Promise((resolve, reject) => { @@ -238,15 +352,37 @@ async function check(name: string, run: () => Promise) { async function run() { const host = await startHost(8) + const replacement = await startHost(8, host.token) const probeHost = await startHost(1) + const balancer = await startBalancer(host) + closeBalancer = balancer.close - process.env.IVM_REMOTE_WORKER_URL = `ws://127.0.0.1:${host.port}/v1/worker` + process.env.IVM_REMOTE_WORKER_URL = `ws://127.0.0.1:${balancer.port}/v1/worker` process.env.IVM_REMOTE_WORKER_TOKEN = host.token + process.env.IVM_REMOTE_WORKER_MAX_AGE_MS = String(WORKER_MAX_AGE_MS) process.env.IVM_MAX_STDOUT_CHARS = String(STDOUT_LIMIT_CHARS) process.env.IVM_QUEUE_TIMEOUT_MS = '5000' process.env.IVM_POOL_SIZE = '2' const { executeInIsolatedVM } = await import('@/lib/execution/isolated-vm') + // The isolate has no timers; a slow upstream holds an execution open the way real ones run long. + // `/hold` answers only when the check releases it, so an inspection never races the execution. + let onHeld: (release: () => void) => void = () => {} + const slowServer = createHttpServer((req, res) => { + const url = new URL(req.url ?? '/', 'http://slow') + if (url.pathname === '/hold') { + onHeld(() => res.end('done')) + return + } + setTimeout(() => res.end('done'), Number(url.searchParams.get('ms'))) + }) + await new Promise((resolve) => slowServer.listen(0, '127.0.0.1', resolve)) + const slowAddress = slowServer.address() + assert(slowAddress && typeof slowAddress === 'object') + closeSlowServer = () => slowServer.close() + const slowFetch = (ms: number) => + `const r = await fetch('http://127.0.0.1:${slowAddress.port}/?ms=${ms}'); return await r.text()` + const execute = (code: string, extra: { timeoutMs?: number; signal?: AbortSignal } = {}) => executeInIsolatedVM( { @@ -267,9 +403,35 @@ async function run() { assert.equal(result.result, 42) }) + /** Inspects workers while an execution holds one open, since an idle worker can retire at any time. */ + const whileAWorkerRuns = async (inspect: () => void) => { + const held = new Promise<() => void>((resolve) => { + onHeld = resolve + }) + const running = execute( + `const r = await fetch('http://127.0.0.1:${slowAddress.port}/hold'); return await r.text()` + ) + // An execution that fails before its fetch arrives reports its own error, not the deadline. + const release = await Promise.race([ + held, + running.then((result) => { + throw new Error(`Execution ended before it was held: ${result.error?.message}`) + }), + ]) + try { + inspect() + } finally { + release() + const result = await running + assert.equal(result.result, 'done', result.error?.message) + } + } + await check('runs the worker as a child of the host, never of the app', async () => { - assert(workerPidsOf(host.process.pid ?? -1).length > 0, 'Expected a worker under the host') - assert.deepEqual(workerPidsOf(process.pid), [], 'The app spawned a local worker') + await whileAWorkerRuns(() => { + assert(workerPidsOf(host.process.pid ?? -1).length > 0, 'Expected a worker under the host') + assert.deepEqual(workerPidsOf(process.pid), [], 'The app spawned a local worker') + }) }) await check("enforces the app's limits on the remote worker", async () => { @@ -283,17 +445,19 @@ async function run() { }) await check("gives the worker neither the host token nor the host's environment", async () => { - const hostWorkers = workerPidsOf(host.process.pid ?? -1) - assert(hostWorkers.length > 0, 'Expected a worker process under the host') - for (const pid of hostWorkers) { - const environment = environmentOf(pid) - assert(!environment.includes(host.token), 'Worker environment contains the host token') - assert(!environment.includes('IVM_HOST_TOKEN'), 'Worker environment names the host token') - assert( - !environment.includes(HOST_ONLY_VALUE), - "Worker environment contains the host's variables" - ) - } + await whileAWorkerRuns(() => { + const hostWorkers = workerPidsOf(host.process.pid ?? -1) + assert(hostWorkers.length > 0, 'Expected a worker process under the host') + for (const pid of hostWorkers) { + const environment = environmentOf(pid) + assert(!environment.includes(host.token), 'Worker environment contains the host token') + assert(!environment.includes('IVM_HOST_TOKEN'), 'Worker environment names the host token') + assert( + !environment.includes(HOST_ONLY_VALUE), + "Worker environment contains the host's variables" + ) + } + }) }) await check('brokers fetch through the app, the only side with a network client', async () => { @@ -345,6 +509,17 @@ async function run() { assert.equal(await closeCode(ws), 4401) }) + await check('drops a connection that streams a large frame before authenticating', async () => { + assert.equal(await streamUnauthenticated(probeHost), 'closed', 'The host kept buffering') + const health = await fetch(`http://127.0.0.1:${probeHost.port}/health`) + assert.equal(health.status, 200) + }) + + await check('drops a refused connection that ignores the close and keeps sending', async () => { + const refusedAuth = authFrame(generateRandomHex(32)) + assert.equal(await streamUnauthenticated(probeHost, refusedAuth), 'closed') + }) + await check('rejects an unparseable request target and keeps serving', async () => { assert.equal(await upgradeStatus(probeHost, { path: '//[' }), 400) const health = await fetch(`http://127.0.0.1:${probeHost.port}/health`) @@ -377,26 +552,63 @@ async function run() { assert.equal(result.error?.isSystemError, true, JSON.stringify(result.error)) }) + // A deploy or scale-in: the balancer stops routing new connections to the host, keeps open ones + // for the deregistration delay, cuts what is left, and only then is the host sent SIGTERM. + await check('drains a deregistered host without failing an execution', async () => { + const longExecution = slowFetch(LONG_EXECUTION_MS) + const warm = await execute('return 1') + assert.equal(warm.result, 1, warm.error?.message) + const runs = [execute(longExecution)] + await sleep(100) + + balancer.target = replacement + const deregisteredAt = Date.now() + // New executions keep arriving until the delay is nearly over, as they do on a busy app. + while (Date.now() - deregisteredAt < DEREGISTRATION_DELAY_MS - 300) { + runs.push(execute(longExecution)) + await sleep(200) + } + await sleep(Math.max(0, DEREGISTRATION_DELAY_MS - (Date.now() - deregisteredAt))) + const openAtExpiry = balancer.open(host) + balancer.cut(host) + host.process.kill('SIGTERM') + + const results = await Promise.all(runs) + const failures = results.filter((result) => result.result !== 'done') + assert.deepEqual( + failures.map((result) => result.error?.message), + [], + `${failures.length} of ${results.length} executions failed across the drain` + ) + assert.equal(openAtExpiry, 0, 'Connections to the deregistered host outlived its delay') + assert(balancer.routed(replacement) > 0, 'No execution moved to the replacement host') + const code = await Promise.race([host.exited, sleep(10000).then(() => 'timeout' as const)]) + assert.notEqual(code, 'timeout', 'The drained host did not exit after SIGTERM') + }) + await check('finishes in-flight work while draining, then exits', async () => { const pending = execute( 'const end = Date.now() + 1500; while (Date.now() < end) {} return "drained"', { timeoutMs: 10000 } ) await sleep(300) - host.process.kill('SIGTERM') + replacement.process.kill('SIGTERM') await sleep(100) - const readiness = await fetch(`http://127.0.0.1:${host.port}/health`) + const readiness = await fetch(`http://127.0.0.1:${replacement.port}/health`) assert.equal(readiness.status, 503, 'Readiness must fail while draining') - const liveness = await fetch(`http://127.0.0.1:${host.port}/livez`) + const liveness = await fetch(`http://127.0.0.1:${replacement.port}/livez`) assert.equal(liveness.status, 200, 'Liveness must hold while draining') const result = await pending assert.equal(result.result, 'drained', result.error?.message) - const code = await Promise.race([host.exited, sleep(10000).then(() => 'timeout' as const)]) + const code = await Promise.race([ + replacement.exited, + sleep(10000).then(() => 'timeout' as const), + ]) assert.notEqual(code, 'timeout', 'Host did not exit after draining') }) await check('fails closed within the queue timeout once the host is gone', async () => { - assert.notEqual(host.process.exitCode, null, 'Precondition: the host has exited') + assert.notEqual(replacement.process.exitCode, null, 'Precondition: the host has exited') const started = Date.now() const result = await execute('return 1') assert.notEqual(result.result, 1, 'Execution ran without a host — it fell back locally') @@ -412,6 +624,8 @@ run() process.exitCode = 1 }) .finally(async () => { + closeBalancer() + closeSlowServer() for (const host of hosts) { try { if (host.process.pid) process.kill(-host.process.pid, 'SIGKILL') diff --git a/apps/sim/tools/generated/tool-ids.ts b/apps/sim/tools/generated/tool-ids.ts index 6ad6bf8b683..fa61402405d 100644 --- a/apps/sim/tools/generated/tool-ids.ts +++ b/apps/sim/tools/generated/tool-ids.ts @@ -3,7 +3,7 @@ /** Every registered tool id, including versioned variants. */ const toolIds: string[] = JSON.parse( - '["a2a_cancel_task","a2a_get_agent_card","a2a_get_task","a2a_send_message","affinity_batch_update_entity_fields","affinity_batch_update_list_entry_fields","affinity_create_list","affinity_create_list_field_dropdown_option","affinity_create_merge","affinity_create_note","affinity_create_reminder","affinity_delete_list_field_dropdown_option","affinity_delete_note","affinity_get_company","affinity_get_current_user","affinity_get_entity_field_value","affinity_get_list","affinity_get_list_entry","affinity_get_list_entry_field","affinity_get_list_field_dropdown_option","affinity_get_merge","affinity_get_merge_task","affinity_get_note","affinity_get_opportunity","affinity_get_person","affinity_get_saved_view","affinity_get_transcript","affinity_get_user","affinity_list_calls","affinity_list_chat_messages","affinity_list_companies","affinity_list_coworker_connections","affinity_list_emails","affinity_list_entity_field_values","affinity_list_entity_list_entries","affinity_list_entity_lists","affinity_list_entity_notes","affinity_list_entity_relationships","affinity_list_field_dropdown_options","affinity_list_field_metadata","affinity_list_field_value_changes","affinity_list_investor_executive_connections","affinity_list_list_entries","affinity_list_list_entry_field_value_changes","affinity_list_list_entry_fields","affinity_list_list_field_dropdown_options","affinity_list_list_fields","affinity_list_lists","affinity_list_meetings","affinity_list_merge_tasks","affinity_list_merges","affinity_list_note_attached_companies","affinity_list_note_attached_opportunities","affinity_list_note_attached_persons","affinity_list_note_replies","affinity_list_notes","affinity_list_opportunities","affinity_list_persons","affinity_list_reminders","affinity_list_saved_view_entries","affinity_list_saved_views","affinity_list_transcript_fragments","affinity_list_transcripts","affinity_list_users","affinity_search_companies","affinity_search_files","affinity_search_list_entries","affinity_search_notes","affinity_search_persons","affinity_semantic_search","affinity_update_entity_field_value","affinity_update_list_entry_field","affinity_update_list_field_dropdown_option","affinity_update_note","agentmail_create_draft","agentmail_create_inbox","agentmail_delete_draft","agentmail_delete_inbox","agentmail_delete_thread","agentmail_forward_message","agentmail_get_draft","agentmail_get_inbox","agentmail_get_message","agentmail_get_thread","agentmail_list_drafts","agentmail_list_inboxes","agentmail_list_messages","agentmail_list_threads","agentmail_reply_message","agentmail_send_draft","agentmail_send_message","agentmail_update_draft","agentmail_update_inbox","agentmail_update_message","agentmail_update_thread","agentphone_create_call","agentphone_create_contact","agentphone_create_number","agentphone_delete_contact","agentphone_get_call","agentphone_get_call_transcript","agentphone_get_contact","agentphone_get_conversation","agentphone_get_conversation_messages","agentphone_get_number_messages","agentphone_get_usage","agentphone_get_usage_daily","agentphone_get_usage_monthly","agentphone_list_calls","agentphone_list_contacts","agentphone_list_conversations","agentphone_list_numbers","agentphone_react_to_message","agentphone_release_number","agentphone_send_message","agentphone_update_contact","agentphone_update_conversation","agiloft_async_status","agiloft_attach_file","agiloft_attachment_info","agiloft_create_record","agiloft_delete_record","agiloft_get_choice_line_id","agiloft_list_tables","agiloft_lock_record","agiloft_nlp_search","agiloft_read_record","agiloft_remove_attachment","agiloft_retrieve_attachment","agiloft_run_action_button","agiloft_saved_search","agiloft_search_records","agiloft_select_records","agiloft_update_record","agiloft_upsert_record","ahrefs_anchors","ahrefs_backlinks","ahrefs_backlinks_stats","ahrefs_batch_analysis","ahrefs_broken_backlinks","ahrefs_domain_rating","ahrefs_domain_rating_history","ahrefs_keyword_overview","ahrefs_keywords_history","ahrefs_metrics","ahrefs_metrics_history","ahrefs_organic_competitors","ahrefs_organic_keywords","ahrefs_paid_pages","ahrefs_rank_tracker_competitors_overview","ahrefs_rank_tracker_competitors_stats","ahrefs_rank_tracker_overview","ahrefs_rank_tracker_serp_overview","ahrefs_refdomains_history","ahrefs_referring_domains","ahrefs_related_terms","ahrefs_site_audit_page_explorer","ahrefs_top_pages","airtable_create_records","airtable_delete_records","airtable_get_base_schema","airtable_get_record","airtable_list_bases","airtable_list_records","airtable_list_tables","airtable_update_multiple_records","airtable_update_record","airtable_upsert_records","algolia_add_record","algolia_batch_operations","algolia_browse_records","algolia_clear_records","algolia_copy_move_index","algolia_delete_by_filter","algolia_delete_index","algolia_delete_record","algolia_get_record","algolia_get_records","algolia_get_settings","algolia_get_task_status","algolia_list_indices","algolia_partial_update_record","algolia_search","algolia_update_settings","amplitude_event_segmentation","amplitude_funnels","amplitude_get_active_users","amplitude_get_revenue","amplitude_group_identify","amplitude_identify_user","amplitude_list_events","amplitude_realtime_active_users","amplitude_retention","amplitude_send_event","amplitude_user_activity","amplitude_user_profile","amplitude_user_search","apify_get_dataset_items","apify_get_run","apify_run_actor_async","apify_run_actor_sync","apify_run_task","apollo_account_bulk_create","apollo_account_bulk_update","apollo_account_create","apollo_account_search","apollo_account_update","apollo_contact_bulk_create","apollo_contact_bulk_update","apollo_contact_create","apollo_contact_search","apollo_contact_update","apollo_email_accounts","apollo_opportunity_create","apollo_opportunity_get","apollo_opportunity_search","apollo_opportunity_update","apollo_organization_bulk_enrich","apollo_organization_enrich","apollo_organization_search","apollo_people_bulk_enrich","apollo_people_enrich","apollo_people_search","apollo_sequence_add_contacts","apollo_sequence_search","apollo_task_create","apollo_task_search","appconfig_create_application","appconfig_create_configuration_profile","appconfig_create_environment","appconfig_create_hosted_configuration_version","appconfig_delete_application","appconfig_delete_configuration_profile","appconfig_delete_environment","appconfig_delete_hosted_configuration_version","appconfig_get_application","appconfig_get_configuration","appconfig_get_configuration_profile","appconfig_get_deployment","appconfig_get_environment","appconfig_get_hosted_configuration_version","appconfig_list_applications","appconfig_list_configuration_profiles","appconfig_list_deployment_strategies","appconfig_list_deployments","appconfig_list_environments","appconfig_list_hosted_configuration_versions","appconfig_start_deployment","appconfig_stop_deployment","appconfig_update_application","appconfig_update_configuration_profile","appconfig_update_environment","arxiv_get_author_papers","arxiv_get_paper","arxiv_search","asana_add_comment","asana_add_followers","asana_create_project","asana_create_section","asana_create_subtask","asana_create_task","asana_delete_task","asana_get_project","asana_get_projects","asana_get_task","asana_list_sections","asana_list_workspaces","asana_search_tasks","asana_update_task","ashby_add_candidate_tag","ashby_anonymize_candidate","ashby_change_application_source","ashby_change_application_stage","ashby_create_application","ashby_create_candidate","ashby_create_note","ashby_delete_application","ashby_get_application","ashby_get_candidate","ashby_get_job","ashby_get_job_posting","ashby_get_offer","ashby_get_opening","ashby_list_application_feedback","ashby_list_application_history","ashby_list_applications","ashby_list_archive_reasons","ashby_list_candidate_tags","ashby_list_candidates","ashby_list_custom_fields","ashby_list_departments","ashby_list_interview_plans","ashby_list_interview_stages","ashby_list_interviews","ashby_list_job_postings","ashby_list_jobs","ashby_list_locations","ashby_list_notes","ashby_list_offers","ashby_list_openings","ashby_list_sources","ashby_list_users","ashby_remove_candidate_tag","ashby_search_candidates","ashby_search_jobs","ashby_search_openings","ashby_search_users","ashby_set_custom_field_value","ashby_set_custom_field_values","ashby_transfer_application","ashby_update_candidate","ashby_upload_candidate_file","ashby_upload_resume","athena_batch_get_named_query","athena_batch_get_prepared_statement","athena_batch_get_query_execution","athena_create_named_query","athena_create_prepared_statement","athena_delete_named_query","athena_delete_prepared_statement","athena_get_data_catalog","athena_get_database","athena_get_named_query","athena_get_prepared_statement","athena_get_query_execution","athena_get_query_results","athena_get_query_runtime_statistics","athena_get_table_metadata","athena_get_work_group","athena_list_data_catalogs","athena_list_databases","athena_list_named_queries","athena_list_prepared_statements","athena_list_query_executions","athena_list_table_metadata","athena_list_work_groups","athena_start_query","athena_stop_query","athena_update_named_query","athena_update_prepared_statement","attio_assert_record","attio_create_attribute","attio_create_comment","attio_create_list","attio_create_list_entry","attio_create_note","attio_create_object","attio_create_record","attio_create_task","attio_create_webhook","attio_delete_comment","attio_delete_list_entry","attio_delete_note","attio_delete_record","attio_delete_task","attio_delete_webhook","attio_get_attribute","attio_get_comment","attio_get_list","attio_get_list_entry","attio_get_member","attio_get_note","attio_get_object","attio_get_record","attio_get_task","attio_get_thread","attio_get_webhook","attio_list_attributes","attio_list_lists","attio_list_members","attio_list_notes","attio_list_objects","attio_list_records","attio_list_tasks","attio_list_threads","attio_list_webhooks","attio_query_list_entries","attio_search_records","attio_update_attribute","attio_update_list","attio_update_list_entry","attio_update_object","attio_update_record","attio_update_task","attio_update_webhook","azure_data_explorer_create_table","azure_data_explorer_drop_table","azure_data_explorer_ingest_from_query","azure_data_explorer_ingest_inline","azure_data_explorer_list_databases","azure_data_explorer_list_functions","azure_data_explorer_list_tables","azure_data_explorer_management","azure_data_explorer_query","azure_data_explorer_show_database_schema","azure_data_explorer_show_ingestion_failures","azure_data_explorer_show_operations","azure_data_explorer_show_table_details","azure_data_explorer_show_table_schema","azure_devops_add_comment","azure_devops_create_work_item","azure_devops_get_build_log","azure_devops_get_build_timeline","azure_devops_get_comments","azure_devops_get_pipeline","azure_devops_get_pipeline_run","azure_devops_get_work_item","azure_devops_get_work_items_batch","azure_devops_get_work_items_between_builds","azure_devops_list_build_logs","azure_devops_list_builds","azure_devops_list_pipeline_runs","azure_devops_list_pipelines","azure_devops_query_work_items","azure_devops_update_work_item","bitbucket_approve_pull_request","bitbucket_create_branch","bitbucket_create_pull_request","bitbucket_create_pull_request_comment","bitbucket_decline_pull_request","bitbucket_delete_branch","bitbucket_get_commit","bitbucket_get_file","bitbucket_get_file_metadata","bitbucket_get_pipeline","bitbucket_get_pipeline_step_log","bitbucket_get_pull_request","bitbucket_get_pull_request_diff","bitbucket_get_pull_request_diffstat","bitbucket_get_pull_request_merge_task_status","bitbucket_get_repository","bitbucket_list_branches","bitbucket_list_commits","bitbucket_list_directory","bitbucket_list_pipeline_steps","bitbucket_list_pipelines","bitbucket_list_pull_request_comments","bitbucket_list_pull_request_commit_statuses","bitbucket_list_pull_requests","bitbucket_list_repositories","bitbucket_list_workspaces","bitbucket_merge_pull_request","bitbucket_request_pull_request_changes","bitbucket_stop_pipeline","bitbucket_trigger_pipeline","box_copy_file","box_create_folder","box_delete_file","box_delete_folder","box_download_file","box_download_file_v2","box_get_file_info","box_list_folder_items","box_search","box_sign_cancel_request","box_sign_create_request","box_sign_get_request","box_sign_list_requests","box_sign_resend_request","box_update_file","box_upload_file","brandfetch_get_brand","brandfetch_search","brex_archive_budget","brex_create_budget","brex_create_spend_limit","brex_create_transfer","brex_create_vendor","brex_get_budget","brex_get_cash_account","brex_get_company","brex_get_current_user","brex_get_expense","brex_get_spend_limit","brex_get_transfer","brex_get_user","brex_get_vendor","brex_list_budgets","brex_list_card_accounts","brex_list_card_statements","brex_list_card_transactions","brex_list_cards","brex_list_cash_accounts","brex_list_cash_statements","brex_list_cash_transactions","brex_list_departments","brex_list_expenses","brex_list_locations","brex_list_spend_limits","brex_list_titles","brex_list_transfers","brex_list_users","brex_list_vendors","brex_match_receipt","brex_update_expense","brex_update_vendor","brex_upload_receipt","brightdata_cancel_snapshot","brightdata_discover","brightdata_download_snapshot","brightdata_scrape_dataset","brightdata_scrape_url","brightdata_serp_search","brightdata_snapshot_status","brightdata_sync_scrape","browser_use_run_task","buffer_create_idea","buffer_create_post","buffer_delete_post","buffer_edit_post","buffer_get_account","buffer_get_aggregated_post_metrics","buffer_get_channel","buffer_get_channels","buffer_get_daily_posting_limits","buffer_get_idea_groups","buffer_get_ideas","buffer_get_post","buffer_get_posts","calcom_cancel_booking","calcom_confirm_booking","calcom_create_booking","calcom_create_event_type","calcom_create_schedule","calcom_decline_booking","calcom_delete_event_type","calcom_delete_schedule","calcom_get_booking","calcom_get_default_schedule","calcom_get_event_type","calcom_get_schedule","calcom_get_slots","calcom_list_bookings","calcom_list_event_types","calcom_list_schedules","calcom_reschedule_booking","calcom_update_event_type","calcom_update_schedule","calendly_cancel_event","calendly_create_event_invitee","calendly_create_invitee_no_show","calendly_create_scheduling_link","calendly_create_webhook","calendly_delete_invitee_no_show","calendly_delete_webhook","calendly_get_current_user","calendly_get_event_invitee","calendly_get_event_type","calendly_get_scheduled_event","calendly_get_user","calendly_list_event_invitees","calendly_list_event_type_available_times","calendly_list_event_types","calendly_list_organization_memberships","calendly_list_routing_form_submissions","calendly_list_routing_forms","calendly_list_scheduled_events","calendly_list_user_availability_schedules","calendly_list_user_busy_times","calendly_list_webhooks","cbinsights_chat","cbinsights_get_commercial_maturity_history","cbinsights_get_exit_probability_history","cbinsights_get_mosaic_history","cbinsights_get_org_business_relationships","cbinsights_get_org_funding_window","cbinsights_get_org_fundings","cbinsights_get_org_investments","cbinsights_get_org_management_and_board","cbinsights_get_org_outlook","cbinsights_get_org_portfolio_exits","cbinsights_get_org_revenue","cbinsights_get_scouting_report","cbinsights_get_strategy_map","cbinsights_list_business_relationships","cbinsights_list_funding_window","cbinsights_list_fundings","cbinsights_list_investments","cbinsights_list_management_and_board","cbinsights_list_outlook","cbinsights_list_portfolio_exits","cbinsights_list_revenue","cbinsights_lookup_organizations","cbinsights_rag","cbinsights_search_firmographics","checkr_add_report_tag","checkr_apply_report_review_action","checkr_cancel_adverse_action","checkr_cancel_continuous_check","checkr_cancel_invitation","checkr_cancel_subscription","checkr_complete_report","checkr_create_adverse_action","checkr_create_candidate","checkr_create_continuous_check","checkr_create_geo","checkr_create_invitation","checkr_create_report","checkr_create_subscription","checkr_delete_candidate_pii","checkr_delete_geo","checkr_get_account","checkr_get_adverse_action","checkr_get_candidate","checkr_get_continuous_check","checkr_get_document","checkr_get_geo","checkr_get_invitation","checkr_get_node","checkr_get_package","checkr_get_program","checkr_get_report","checkr_get_report_eta","checkr_get_report_progressive_status","checkr_get_report_tags","checkr_get_screening","checkr_get_subscription","checkr_get_verification","checkr_list_adverse_actions","checkr_list_adverse_items","checkr_list_assessments","checkr_list_candidate_documents","checkr_list_candidates","checkr_list_continuous_checks","checkr_list_counties","checkr_list_geos","checkr_list_invitations","checkr_list_nodes","checkr_list_packages","checkr_list_programs","checkr_list_report_addresses","checkr_list_subscriptions","checkr_list_users","checkr_list_verifications","checkr_remove_report_tag","checkr_set_report_tags","checkr_update_candidate","checkr_update_continuous_check","checkr_update_geo","checkr_update_report","checkr_update_subscription","circleback_add_tag_to_meetings","circleback_create_tag","circleback_delete_action_item","circleback_delete_meeting","circleback_delete_tag","circleback_get_company","circleback_get_meeting","circleback_get_person","circleback_get_transcript","circleback_list_action_items","circleback_list_calendar_events","circleback_list_companies","circleback_list_meetings","circleback_list_people","circleback_list_tags","circleback_remove_tag_from_meetings","circleback_search_meetings","circleback_update_action_item","circleback_update_meeting","circleback_update_tag","clay_populate","clerk_add_organization_member","clerk_ban_user","clerk_create_actor_token","clerk_create_allowlist_identifier","clerk_create_blocklist_identifier","clerk_create_organization","clerk_create_organization_invitation","clerk_create_user","clerk_delete_allowlist_identifier","clerk_delete_blocklist_identifier","clerk_delete_organization","clerk_delete_user","clerk_get_jwt_template","clerk_get_organization","clerk_get_session","clerk_get_user","clerk_get_user_oauth_token","clerk_list_allowlist_identifiers","clerk_list_blocklist_identifiers","clerk_list_jwt_templates","clerk_list_organization_invitations","clerk_list_organization_memberships","clerk_list_organizations","clerk_list_sessions","clerk_list_users","clerk_lock_user","clerk_remove_organization_member","clerk_revoke_actor_token","clerk_revoke_session","clerk_unban_user","clerk_unlock_user","clerk_update_organization","clerk_update_organization_membership","clerk_update_user","clickhouse_count_rows","clickhouse_create_database","clickhouse_create_table","clickhouse_delete","clickhouse_describe_table","clickhouse_drop_database","clickhouse_drop_partition","clickhouse_drop_table","clickhouse_execute","clickhouse_insert","clickhouse_insert_rows","clickhouse_introspect","clickhouse_kill_query","clickhouse_list_clusters","clickhouse_list_databases","clickhouse_list_mutations","clickhouse_list_partitions","clickhouse_list_running_queries","clickhouse_list_tables","clickhouse_optimize_table","clickhouse_query","clickhouse_rename_table","clickhouse_show_create_table","clickhouse_table_stats","clickhouse_truncate_table","clickhouse_update","clickup_add_tag_to_task","clickup_create_checklist","clickup_create_checklist_item","clickup_create_comment","clickup_create_folder","clickup_create_list","clickup_create_task","clickup_create_time_entry","clickup_delete_checklist","clickup_delete_checklist_item","clickup_delete_comment","clickup_delete_task","clickup_delete_time_entry","clickup_get_comments","clickup_get_custom_fields","clickup_get_folders","clickup_get_list_members","clickup_get_lists","clickup_get_running_timer","clickup_get_space_tags","clickup_get_spaces","clickup_get_task","clickup_get_task_members","clickup_get_tasks","clickup_get_time_entries","clickup_get_workspaces","clickup_remove_custom_field_value","clickup_remove_tag_from_task","clickup_search_tasks","clickup_set_custom_field_value","clickup_start_timer","clickup_stop_timer","clickup_update_checklist","clickup_update_checklist_item","clickup_update_comment","clickup_update_task","clickup_update_time_entry","clickup_upload_attachment","cloudflare_create_access_application","cloudflare_create_access_group","cloudflare_create_access_policy","cloudflare_create_access_service_token","cloudflare_create_dns_record","cloudflare_create_r2_bucket","cloudflare_create_rate_limit_rule","cloudflare_create_ruleset","cloudflare_create_ruleset_rule","cloudflare_create_tunnel","cloudflare_create_worker_route","cloudflare_create_zone","cloudflare_delete_access_application","cloudflare_delete_access_group","cloudflare_delete_access_policy","cloudflare_delete_dns_record","cloudflare_delete_r2_bucket","cloudflare_delete_r2_bucket_cors","cloudflare_delete_ruleset","cloudflare_delete_ruleset_rule","cloudflare_delete_tunnel","cloudflare_delete_worker_route","cloudflare_delete_worker_script","cloudflare_delete_zone","cloudflare_dns_analytics","cloudflare_get_access_application","cloudflare_get_access_group","cloudflare_get_access_policy","cloudflare_get_access_service_token","cloudflare_get_dns_record","cloudflare_get_r2_bucket","cloudflare_get_r2_bucket_cors","cloudflare_get_r2_bucket_lifecycle","cloudflare_get_ruleset","cloudflare_get_ruleset_entrypoint","cloudflare_get_tunnel","cloudflare_get_tunnel_configuration","cloudflare_get_tunnel_token","cloudflare_get_worker_route","cloudflare_get_worker_script_settings","cloudflare_get_zone","cloudflare_get_zone_settings","cloudflare_list_access_applications","cloudflare_list_access_groups","cloudflare_list_access_identity_providers","cloudflare_list_access_policies","cloudflare_list_access_service_tokens","cloudflare_list_certificates","cloudflare_list_dns_records","cloudflare_list_managed_ruleset_overrides","cloudflare_list_r2_buckets","cloudflare_list_rate_limit_rules","cloudflare_list_rulesets","cloudflare_list_tunnels","cloudflare_list_worker_routes","cloudflare_list_worker_scripts","cloudflare_list_zones","cloudflare_purge_cache","cloudflare_refresh_access_service_token","cloudflare_revoke_access_service_token","cloudflare_rotate_access_service_token","cloudflare_update_access_application","cloudflare_update_access_group","cloudflare_update_access_policy","cloudflare_update_access_service_token","cloudflare_update_dns_record","cloudflare_update_r2_bucket_cors","cloudflare_update_r2_bucket_lifecycle","cloudflare_update_rate_limit_rule","cloudflare_update_ruleset","cloudflare_update_ruleset_rule","cloudflare_update_tunnel","cloudflare_update_tunnel_configuration","cloudflare_update_worker_route","cloudflare_update_zone","cloudflare_update_zone_setting","cloudformation_cancel_update_stack","cloudformation_create_change_set","cloudformation_create_stack","cloudformation_delete_stack","cloudformation_describe_change_set","cloudformation_describe_stack_drift_detection_status","cloudformation_describe_stack_events","cloudformation_describe_stacks","cloudformation_detect_stack_drift","cloudformation_execute_change_set","cloudformation_get_template","cloudformation_get_template_summary","cloudformation_list_stack_resources","cloudformation_update_stack","cloudformation_validate_template","cloudtrail_cancel_query","cloudtrail_describe_query","cloudtrail_describe_trails","cloudtrail_get_event_data_store","cloudtrail_get_event_selectors","cloudtrail_get_insight_selectors","cloudtrail_get_query_results","cloudtrail_get_trail","cloudtrail_get_trail_status","cloudtrail_list_event_data_stores","cloudtrail_list_tags","cloudtrail_list_trails","cloudtrail_lookup_events","cloudtrail_start_query","cloudwatch_describe_alarm_history","cloudwatch_describe_alarms","cloudwatch_describe_log_groups","cloudwatch_describe_log_streams","cloudwatch_filter_log_events","cloudwatch_get_log_events","cloudwatch_get_metric_statistics","cloudwatch_list_metrics","cloudwatch_mute_alarm","cloudwatch_put_log_group_retention","cloudwatch_put_metric_data","cloudwatch_query_logs","cloudwatch_unmute_alarm","coda_add_custom_domain","coda_add_permission","coda_change_user_role","coda_create_doc","coda_create_folder","coda_create_page","coda_delete_custom_domain","coda_delete_doc","coda_delete_folder","coda_delete_page","coda_delete_page_content","coda_delete_permission","coda_delete_row","coda_delete_rows","coda_export_page","coda_get_acl_settings","coda_get_analytics_last_updated","coda_get_column","coda_get_control","coda_get_custom_domain_provider","coda_get_doc","coda_get_doc_analytics_summary","coda_get_folder","coda_get_formula","coda_get_mutation_status","coda_get_page","coda_get_page_content","coda_get_page_export_status","coda_get_row","coda_get_sharing_metadata","coda_get_table","coda_list_categories","coda_list_columns","coda_list_controls","coda_list_custom_domains","coda_list_doc_analytics","coda_list_docs","coda_list_folder_children","coda_list_folders","coda_list_formulas","coda_list_page_analytics","coda_list_pages","coda_list_permissions","coda_list_rows","coda_list_tables","coda_list_workspace_members","coda_list_workspace_roles","coda_publish_doc","coda_push_button","coda_resolve_browser_link","coda_search_principals","coda_trigger_automation","coda_unpublish_doc","coda_update_acl_settings","coda_update_doc","coda_update_folder","coda_update_page","coda_update_row","coda_upsert_rows","coda_whoami","codepipeline_disable_stage_transition","codepipeline_enable_stage_transition","codepipeline_get_pipeline","codepipeline_get_pipeline_execution","codepipeline_get_pipeline_state","codepipeline_list_action_executions","codepipeline_list_pipeline_executions","codepipeline_list_pipelines","codepipeline_put_approval_result","codepipeline_retry_stage_execution","codepipeline_start_execution","codepipeline_stop_execution","confluence_add_label","confluence_create_blogpost","confluence_create_comment","confluence_create_page","confluence_create_page_property","confluence_create_space","confluence_create_space_property","confluence_delete_attachment","confluence_delete_blogpost","confluence_delete_comment","confluence_delete_label","confluence_delete_page","confluence_delete_page_property","confluence_delete_space","confluence_delete_space_property","confluence_get_blogpost","confluence_get_page_ancestors","confluence_get_page_children","confluence_get_page_descendants","confluence_get_page_version","confluence_get_pages_by_label","confluence_get_space","confluence_get_task","confluence_get_user","confluence_list_attachments","confluence_list_blogposts","confluence_list_blogposts_in_space","confluence_list_comments","confluence_list_labels","confluence_list_page_properties","confluence_list_page_versions","confluence_list_pages_in_space","confluence_list_space_labels","confluence_list_space_permissions","confluence_list_space_properties","confluence_list_spaces","confluence_list_tasks","confluence_retrieve","confluence_search","confluence_search_in_space","confluence_update","confluence_update_blogpost","confluence_update_comment","confluence_update_space","confluence_update_task","confluence_upload_attachment","context_dev_classify_naics","context_dev_classify_sic","context_dev_crawl","context_dev_extract","context_dev_extract_product","context_dev_extract_products","context_dev_get_brand","context_dev_get_brand_by_email","context_dev_get_brand_by_name","context_dev_get_brand_by_ticker","context_dev_identify_transaction","context_dev_map","context_dev_scrape_fonts","context_dev_scrape_html","context_dev_scrape_images","context_dev_scrape_markdown","context_dev_scrape_styleguide","context_dev_screenshot","context_dev_search","convex_action","convex_document_deltas","convex_list_documents","convex_list_tables","convex_mutation","convex_query","convex_run_function","crowdstrike_create_indicators","crowdstrike_delete_indicators","crowdstrike_delete_rtr_session","crowdstrike_execute_rtr_command","crowdstrike_get_alert_details","crowdstrike_get_case_details","crowdstrike_get_host_group_details","crowdstrike_get_indicator_details","crowdstrike_get_rtr_command_status","crowdstrike_get_sensor_aggregates","crowdstrike_get_sensor_details","crowdstrike_get_vulnerability_details","crowdstrike_init_rtr_session","crowdstrike_perform_host_action","crowdstrike_perform_host_group_action","crowdstrike_query_alerts","crowdstrike_query_cases","crowdstrike_query_host_groups","crowdstrike_query_indicators","crowdstrike_query_sensors","crowdstrike_query_vulnerabilities","crowdstrike_update_alerts","crowdstrike_update_indicators","crunchbase_autocomplete","crunchbase_get_acquisition","crunchbase_get_entity","crunchbase_get_entity_card","crunchbase_get_fields_metadata","crunchbase_get_funding_round","crunchbase_get_organization","crunchbase_get_person","crunchbase_list_deleted_entities","crunchbase_search_acquisitions","crunchbase_search_entities","crunchbase_search_funding_rounds","crunchbase_search_organizations","crunchbase_search_people","cursor_add_followup","cursor_add_followup_v2","cursor_delete_agent","cursor_delete_agent_v2","cursor_download_artifact","cursor_download_artifact_v2","cursor_get_agent","cursor_get_agent_v2","cursor_get_api_key_info","cursor_get_api_key_info_v2","cursor_get_conversation","cursor_get_conversation_v2","cursor_launch_agent","cursor_launch_agent_v2","cursor_list_agents","cursor_list_agents_v2","cursor_list_artifacts","cursor_list_artifacts_v2","cursor_list_models","cursor_list_models_v2","cursor_list_repositories","cursor_list_repositories_v2","cursor_stop_agent","cursor_stop_agent_v2","dagster_delete_run","dagster_get_asset","dagster_get_run","dagster_get_run_logs","dagster_launch_run","dagster_list_assets","dagster_list_jobs","dagster_list_runs","dagster_list_schedules","dagster_list_sensors","dagster_materialize_assets","dagster_reexecute_run","dagster_report_asset_materialization","dagster_start_schedule","dagster_start_sensor","dagster_stop_schedule","dagster_stop_sensor","dagster_terminate_run","dagster_wipe_asset","databricks_cancel_all_runs","databricks_cancel_run","databricks_cancel_statement","databricks_create_cluster","databricks_create_job","databricks_create_warehouse","databricks_delete_cluster","databricks_delete_job","databricks_delete_run","databricks_delete_warehouse","databricks_edit_cluster","databricks_edit_warehouse","databricks_execute_sql","databricks_genie_agent_ask","databricks_genie_agent_cancel","databricks_genie_agent_list_items","databricks_genie_ask","databricks_genie_create_space","databricks_genie_delete_conversation","databricks_genie_delete_message","databricks_genie_delete_space","databricks_genie_download_visualization","databricks_genie_execute_query","databricks_genie_get_message","databricks_genie_get_query_result","databricks_genie_get_space","databricks_genie_list_conversations","databricks_genie_list_messages","databricks_genie_list_spaces","databricks_genie_send_feedback","databricks_genie_update_space","databricks_get_cluster","databricks_get_job","databricks_get_run","databricks_get_run_output","databricks_get_statement","databricks_get_statement_chunk","databricks_get_warehouse","databricks_list_clusters","databricks_list_jobs","databricks_list_runs","databricks_list_warehouses","databricks_repair_run","databricks_reset_job","databricks_resize_cluster","databricks_restart_cluster","databricks_run_job","databricks_start_cluster","databricks_start_warehouse","databricks_stop_warehouse","databricks_submit_run","databricks_terminate_cluster","databricks_update_job","datadog_add_incident_todo","datadog_cancel_downtime","datadog_create_dashboard","datadog_create_downtime","datadog_create_event","datadog_create_incident","datadog_create_monitor","datadog_create_slo","datadog_delete_dashboard","datadog_delete_slo","datadog_get_browser_synthetics_results","datadog_get_dashboard","datadog_get_incident","datadog_get_monitor","datadog_get_security_signal","datadog_get_slo","datadog_get_slo_history","datadog_get_synthetics_results","datadog_get_synthetics_test","datadog_list_dashboards","datadog_list_downtimes","datadog_list_incidents","datadog_list_monitors","datadog_list_security_rules","datadog_list_security_signals","datadog_list_services","datadog_list_slos","datadog_list_synthetics_tests","datadog_mute_monitor","datadog_query_logs","datadog_query_timeseries","datadog_search_spans","datadog_send_logs","datadog_submit_metrics","datadog_trigger_synthetics_tests","datadog_unmute_monitor","datadog_update_incident","datadog_update_security_signal_assignee","datadog_update_security_signal_state","datadog_update_slo","datadog_update_synthetics_status","datagma_enrich_company","datagma_enrich_person","datagma_find_email","datagma_find_phone","datagma_get_credits","daytona_create_sandbox","daytona_delete_sandbox","daytona_download_file","daytona_execute_command","daytona_get_sandbox","daytona_git_clone","daytona_list_files","daytona_list_sandboxes","daytona_run_code","daytona_start_sandbox","daytona_stop_sandbox","daytona_upload_file","deployed_block_executor","deployments_deploy","deployments_get_version","deployments_list_versions","deployments_promote","deployments_undeploy","devin_append_session_tags","devin_archive_session","devin_create_session","devin_get_session","devin_get_session_tags","devin_list_session_attachments","devin_list_session_messages","devin_list_sessions","devin_replace_session_tags","devin_send_message","devin_terminate_session","discord_add_reaction","discord_archive_thread","discord_assign_role","discord_ban_member","discord_bulk_delete_messages","discord_create_channel","discord_create_invite","discord_create_role","discord_create_thread","discord_create_webhook","discord_delete_channel","discord_delete_invite","discord_delete_message","discord_delete_role","discord_delete_webhook","discord_edit_message","discord_execute_webhook","discord_get_channel","discord_get_invite","discord_get_member","discord_get_messages","discord_get_pinned_messages","discord_get_server","discord_get_user","discord_get_webhook","discord_join_thread","discord_kick_member","discord_leave_thread","discord_list_channels","discord_list_roles","discord_pin_message","discord_remove_reaction","discord_remove_role","discord_send_message","discord_unban_member","discord_unpin_message","discord_update_channel","discord_update_member","discord_update_role","docusign_create_from_template","docusign_download_document","docusign_get_envelope","docusign_list_envelopes","docusign_list_recipients","docusign_list_templates","docusign_send_envelope","docusign_void_envelope","downdetector_get_company","downdetector_get_company_attribution","downdetector_get_company_baseline","downdetector_get_company_events","downdetector_get_company_incidents","downdetector_get_company_indicators","downdetector_get_company_last_15","downdetector_get_company_status","downdetector_get_provider","downdetector_get_reports","downdetector_get_site_companies","downdetector_list_categories","downdetector_list_incidents","downdetector_list_sites","downdetector_search_companies","dropbox_copy","dropbox_create_folder","dropbox_create_shared_link","dropbox_delete","dropbox_download","dropbox_download_v2","dropbox_get_metadata","dropbox_list_folder","dropbox_list_revisions","dropbox_list_shared_links","dropbox_move","dropbox_restore","dropbox_search","dropbox_upload","dropcontact_enrich_contact","dspy_chain_of_thought","dspy_predict","dspy_react","dub_bulk_create_links","dub_bulk_delete_links","dub_bulk_update_links","dub_create_link","dub_create_tag","dub_delete_link","dub_get_analytics","dub_get_events","dub_get_link","dub_get_links_count","dub_get_qr_code","dub_get_qr_code_v2","dub_list_domains","dub_list_folders","dub_list_links","dub_list_tags","dub_update_link","dub_upsert_link","duckduckgo_search","dynamodb_delete","dynamodb_get","dynamodb_introspect","dynamodb_put","dynamodb_query","dynamodb_scan","dynamodb_update","dynatrace_add_problem_comment","dynatrace_add_tags","dynatrace_close_problem","dynatrace_create_settings_object","dynatrace_create_slo","dynatrace_delete_problem_comment","dynatrace_delete_settings_object","dynatrace_delete_slo","dynatrace_delete_tag","dynatrace_execute_synthetic_monitors","dynatrace_get_attack","dynatrace_get_audit_logs","dynatrace_get_entity","dynatrace_get_event","dynatrace_get_metric","dynatrace_get_problem","dynatrace_get_problem_comment","dynatrace_get_security_problem","dynatrace_get_settings_object","dynatrace_get_slo","dynatrace_get_synthetic_batch","dynatrace_ingest_event","dynatrace_ingest_logs","dynatrace_ingest_metrics","dynatrace_list_attacks","dynatrace_list_entities","dynatrace_list_entity_types","dynatrace_list_events","dynatrace_list_metrics","dynatrace_list_problem_comments","dynatrace_list_problems","dynatrace_list_remediation_items","dynatrace_list_security_problems","dynatrace_list_settings_objects","dynatrace_list_settings_schemas","dynatrace_list_slos","dynatrace_list_synthetic_monitors","dynatrace_list_tags","dynatrace_mute_security_problem","dynatrace_mute_security_problems","dynatrace_query_metrics","dynatrace_search_logs","dynatrace_unmute_security_problem","dynatrace_unmute_security_problems","dynatrace_update_problem_comment","dynatrace_update_settings_object","dynatrace_update_slo","ec2_allocate_address","ec2_associate_address","ec2_authorize_security_group_ingress","ec2_create_snapshot","ec2_create_tags","ec2_delete_snapshot","ec2_delete_tags","ec2_delete_volume","ec2_describe_addresses","ec2_describe_availability_zones","ec2_describe_images","ec2_describe_instance_status","ec2_describe_instances","ec2_describe_internet_gateways","ec2_describe_key_pairs","ec2_describe_nat_gateways","ec2_describe_network_acls","ec2_describe_network_interfaces","ec2_describe_regions","ec2_describe_route_tables","ec2_describe_security_groups","ec2_describe_snapshots","ec2_describe_subnets","ec2_describe_volumes","ec2_describe_vpc_endpoints","ec2_describe_vpc_peering_connections","ec2_describe_vpcs","ec2_disassociate_address","ec2_reboot_instances","ec2_release_address","ec2_revoke_security_group_ingress","ec2_start_instances","ec2_stop_instances","ec2_terminate_instances","elasticsearch_bulk","elasticsearch_cluster_health","elasticsearch_cluster_stats","elasticsearch_count","elasticsearch_create_index","elasticsearch_delete_document","elasticsearch_delete_index","elasticsearch_get_document","elasticsearch_get_index","elasticsearch_index_document","elasticsearch_list_indices","elasticsearch_search","elasticsearch_update_document","elevenlabs_audio_isolation","elevenlabs_edit_voice_settings","elevenlabs_get_user","elevenlabs_get_voice","elevenlabs_get_voice_settings","elevenlabs_list_models","elevenlabs_list_voices","elevenlabs_sound_effects","elevenlabs_speech_to_speech","elevenlabs_tts","emailbison_attach_leads_to_campaign","emailbison_attach_tags_to_leads","emailbison_create_campaign","emailbison_create_lead","emailbison_create_tag","emailbison_get_lead","emailbison_list_campaigns","emailbison_list_leads","emailbison_list_replies","emailbison_list_tags","emailbison_update_campaign","emailbison_update_campaign_status","emailbison_update_lead","embeddings_cohere","embeddings_gemini","embeddings_mistral","embeddings_ollama","embeddings_openai","embeddings_openrouter","enrich_check_credits","enrich_company_funding","enrich_company_lookup","enrich_company_revenue","enrich_disposable_email_check","enrich_email_to_ip","enrich_email_to_person_lite","enrich_email_to_phone","enrich_email_to_profile","enrich_find_email","enrich_get_post_details","enrich_ip_to_company","enrich_linkedin_profile","enrich_linkedin_to_personal_email","enrich_linkedin_to_work_email","enrich_phone_finder","enrich_reverse_hash_lookup","enrich_sales_pointer_people","enrich_search_company","enrich_search_company_activities","enrich_search_company_employees","enrich_search_jobs","enrich_search_logo","enrich_search_people","enrich_search_people_activities","enrich_search_post_comments","enrich_search_post_comments_by_url","enrich_search_post_reactions","enrich_search_post_reactions_by_url","enrich_search_posts","enrich_search_similar_companies","enrich_verify_email","enrichment_run","enrow_find_email","enrow_verify_email","exa_agent","exa_answer","exa_find_similar_links","exa_get_contents","exa_search","extend_parser","extend_parser_v2","fathom_get_summary","fathom_get_transcript","fathom_list_meeting_types","fathom_list_meetings","fathom_list_team_members","fathom_list_teams","file_append","file_compress","file_create_folder","file_decompress","file_delete_folder","file_edit","file_fetch","file_get","file_get_content","file_list","file_manage_sharing","file_move","file_parser","file_parser_v2","file_parser_v3","file_read","file_restore_folder","file_search","file_update_folder","file_write","findymail_find_email_from_linkedin","findymail_find_email_from_name","findymail_find_emails_by_domain","findymail_find_employees","findymail_find_phone","findymail_get_company","findymail_get_credits","findymail_lookup_technologies","findymail_reverse_email_lookup","findymail_search_technologies","findymail_verify_email","firecrawl_agent","firecrawl_batch_scrape","firecrawl_batch_scrape_status","firecrawl_cancel_crawl","firecrawl_crawl","firecrawl_crawl_status","firecrawl_credit_usage","firecrawl_extract","firecrawl_extract_status","firecrawl_map","firecrawl_parse","firecrawl_scrape","firecrawl_search","fireflies_add_to_live_meeting","fireflies_create_bite","fireflies_delete_transcript","fireflies_get_transcript","fireflies_get_user","fireflies_list_bites","fireflies_list_contacts","fireflies_list_transcripts","fireflies_list_users","fireflies_upload_audio","fivetran_cancel_transformation","fivetran_create_connect_card","fivetran_create_connection","fivetran_create_destination","fivetran_create_group","fivetran_delete_connection","fivetran_get_account_info","fivetran_get_connection","fivetran_get_connection_schema_config","fivetran_get_connection_warnings","fivetran_get_connector_type","fivetran_get_destination","fivetran_get_group","fivetran_get_sync_history","fivetran_get_transformation","fivetran_list_connections","fivetran_list_connector_types","fivetran_list_destinations","fivetran_list_groups","fivetran_list_transformations","fivetran_list_users","fivetran_reload_connection_schema","fivetran_resync_connection","fivetran_resync_tables","fivetran_run_connection_setup_tests","fivetran_run_destination_setup_tests","fivetran_run_transformation","fivetran_sync_connection","fivetran_update_connection","fivetran_update_connection_schema","fivetran_update_connection_table","fivetran_update_schema_config","flint_create_task","flint_generate_pages","flint_get_task","function_execute","gamma_check_status","gamma_generate","gamma_generate_from_template","gamma_list_folders","gamma_list_themes","github_add_assignees","github_add_assignees_v2","github_add_labels","github_add_labels_v2","github_cancel_workflow_run","github_cancel_workflow_run_v2","github_check_star","github_check_star_v2","github_close_issue","github_close_issue_v2","github_close_pr","github_close_pr_v2","github_comment","github_comment_v2","github_compare_commits","github_compare_commits_v2","github_create_branch","github_create_branch_v2","github_create_comment_reaction","github_create_comment_reaction_v2","github_create_file","github_create_file_v2","github_create_gist","github_create_gist_v2","github_create_issue","github_create_issue_reaction","github_create_issue_reaction_v2","github_create_issue_v2","github_create_milestone","github_create_milestone_v2","github_create_pr","github_create_pr_review","github_create_pr_review_v2","github_create_pr_v2","github_create_project","github_create_project_v2","github_create_release","github_create_release_v2","github_delete_branch","github_delete_branch_v2","github_delete_comment","github_delete_comment_reaction","github_delete_comment_reaction_v2","github_delete_comment_v2","github_delete_file","github_delete_file_v2","github_delete_gist","github_delete_gist_v2","github_delete_issue_reaction","github_delete_issue_reaction_v2","github_delete_milestone","github_delete_milestone_v2","github_delete_project","github_delete_project_v2","github_delete_release","github_delete_release_v2","github_fork_gist","github_fork_gist_v2","github_fork_repo","github_fork_repo_v2","github_get_branch","github_get_branch_protection","github_get_branch_protection_v2","github_get_branch_v2","github_get_commit","github_get_commit_v2","github_get_file_content","github_get_file_content_v2","github_get_gist","github_get_gist_v2","github_get_issue","github_get_issue_v2","github_get_latest_release","github_get_latest_release_v2","github_get_milestone","github_get_milestone_v2","github_get_pr_files","github_get_pr_files_v2","github_get_project","github_get_project_v2","github_get_readme","github_get_readme_v2","github_get_release","github_get_release_v2","github_get_tree","github_get_tree_v2","github_get_workflow","github_get_workflow_run","github_get_workflow_run_v2","github_get_workflow_v2","github_issue_comment","github_issue_comment_v2","github_job_logs","github_latest_commit","github_latest_commit_v2","github_list_branches","github_list_branches_v2","github_list_commits","github_list_commits_v2","github_list_forks","github_list_forks_v2","github_list_gists","github_list_gists_v2","github_list_issue_comments","github_list_issue_comments_v2","github_list_issues","github_list_issues_v2","github_list_milestones","github_list_milestones_v2","github_list_pr_comments","github_list_pr_comments_v2","github_list_projects","github_list_projects_v2","github_list_prs","github_list_prs_v2","github_list_releases","github_list_releases_v2","github_list_review_threads","github_list_stargazers","github_list_stargazers_v2","github_list_tags","github_list_tags_v2","github_list_workflow_runs","github_list_workflow_runs_v2","github_list_workflows","github_list_workflows_v2","github_merge_pr","github_merge_pr_v2","github_pr","github_pr_v2","github_remove_label","github_remove_label_v2","github_reply_review_thread","github_repo_info","github_repo_info_v2","github_request_reviewers","github_request_reviewers_v2","github_rerun_workflow","github_rerun_workflow_v2","github_resolve_review_thread","github_search_code","github_search_code_v2","github_search_commits","github_search_commits_v2","github_search_issues","github_search_issues_v2","github_search_repos","github_search_repos_v2","github_search_users","github_search_users_v2","github_star_gist","github_star_gist_v2","github_star_repo","github_star_repo_v2","github_status_check_rollup","github_trigger_workflow","github_trigger_workflow_v2","github_unstar_gist","github_unstar_gist_v2","github_unstar_repo","github_unstar_repo_v2","github_update_branch_protection","github_update_branch_protection_v2","github_update_comment","github_update_comment_v2","github_update_file","github_update_file_v2","github_update_gist","github_update_gist_v2","github_update_issue","github_update_issue_v2","github_update_milestone","github_update_milestone_v2","github_update_pr","github_update_pr_v2","github_update_project","github_update_project_v2","github_update_release","github_update_release_v2","gitlab_activate_user","gitlab_add_member","gitlab_add_saml_group_link","gitlab_approve_access_request","gitlab_approve_merge_request","gitlab_approve_user","gitlab_ban_user","gitlab_block_user","gitlab_cancel_pipeline","gitlab_compare_branches","gitlab_create_branch","gitlab_create_file","gitlab_create_issue","gitlab_create_issue_note","gitlab_create_merge_request","gitlab_create_merge_request_note","gitlab_create_pipeline","gitlab_create_release","gitlab_create_user","gitlab_deactivate_user","gitlab_delete_branch","gitlab_delete_issue","gitlab_delete_saml_group_link","gitlab_delete_user","gitlab_delete_user_identity","gitlab_deny_access_request","gitlab_get_file","gitlab_get_group","gitlab_get_issue","gitlab_get_job_log","gitlab_get_merge_request","gitlab_get_merge_request_changes","gitlab_get_pipeline","gitlab_get_project","gitlab_invite_member","gitlab_list_access_requests","gitlab_list_branches","gitlab_list_commits","gitlab_list_groups","gitlab_list_invitations","gitlab_list_issues","gitlab_list_members","gitlab_list_merge_requests","gitlab_list_pipeline_jobs","gitlab_list_pipelines","gitlab_list_projects","gitlab_list_releases","gitlab_list_repository_tree","gitlab_list_saml_group_links","gitlab_list_user_memberships","gitlab_merge_merge_request","gitlab_play_job","gitlab_reject_user","gitlab_remove_member","gitlab_retry_pipeline","gitlab_revoke_invitation","gitlab_search_users","gitlab_unban_user","gitlab_unblock_user","gitlab_update_file","gitlab_update_invitation","gitlab_update_issue","gitlab_update_member","gitlab_update_merge_request","gitlab_update_user","gmail_add_label","gmail_add_label_v2","gmail_archive","gmail_archive_v2","gmail_create_label_v2","gmail_delete","gmail_delete_draft_v2","gmail_delete_label_v2","gmail_delete_v2","gmail_draft","gmail_draft_v2","gmail_edit_draft_v2","gmail_get_draft_v2","gmail_get_thread_v2","gmail_list_drafts_v2","gmail_list_labels_v2","gmail_list_threads_v2","gmail_mark_read","gmail_mark_read_v2","gmail_mark_unread","gmail_mark_unread_v2","gmail_move","gmail_move_v2","gmail_read","gmail_read_v2","gmail_remove_label","gmail_remove_label_v2","gmail_search","gmail_search_v2","gmail_send","gmail_send_v2","gmail_trash_thread_v2","gmail_unarchive","gmail_unarchive_v2","gmail_untrash_thread_v2","gmail_update_label_v2","gong_aggregate_activity","gong_aggregate_by_period","gong_answered_scorecards","gong_ask_anything","gong_assign_flow_prospects","gong_create_call","gong_day_by_day_activity","gong_get_brief","gong_get_call","gong_get_call_transcript","gong_get_coaching","gong_get_extensive_calls","gong_get_folder_content","gong_get_logs","gong_get_prospect_flows","gong_get_user","gong_interaction_stats","gong_list_calls","gong_list_flows","gong_list_library_folders","gong_list_scorecards","gong_list_trackers","gong_list_users","gong_list_workspaces","gong_lookup_email","gong_lookup_phone","gong_purge_email_address","gong_purge_phone_number","gong_unassign_flow_prospects","google_ads_ad_performance","google_ads_campaign_performance","google_ads_list_ad_groups","google_ads_list_campaigns","google_ads_list_customers","google_ads_search","google_appsheet_add_rows","google_appsheet_delete_rows","google_appsheet_edit_rows","google_appsheet_find_rows","google_bigquery_create_dataset","google_bigquery_create_table","google_bigquery_delete_dataset","google_bigquery_delete_table","google_bigquery_get_query_results","google_bigquery_get_table","google_bigquery_insert_rows","google_bigquery_list_datasets","google_bigquery_list_table_data","google_bigquery_list_tables","google_bigquery_query","google_books_volume_details","google_books_volume_search","google_calendar_create","google_calendar_create_calendar","google_calendar_create_calendar_v2","google_calendar_create_v2","google_calendar_delete","google_calendar_delete_calendar","google_calendar_delete_calendar_v2","google_calendar_delete_v2","google_calendar_freebusy","google_calendar_freebusy_v2","google_calendar_get","google_calendar_get_v2","google_calendar_instances","google_calendar_instances_v2","google_calendar_invite","google_calendar_invite_v2","google_calendar_list","google_calendar_list_acl","google_calendar_list_acl_v2","google_calendar_list_calendars","google_calendar_list_calendars_v2","google_calendar_list_v2","google_calendar_move","google_calendar_move_v2","google_calendar_quick_add","google_calendar_quick_add_v2","google_calendar_respond","google_calendar_respond_v2","google_calendar_share_calendar","google_calendar_share_calendar_v2","google_calendar_unshare_calendar","google_calendar_unshare_calendar_v2","google_calendar_update","google_calendar_update_acl","google_calendar_update_acl_v2","google_calendar_update_calendar","google_calendar_update_calendar_v2","google_calendar_update_v2","google_contacts_create","google_contacts_delete","google_contacts_get","google_contacts_list","google_contacts_search","google_contacts_update","google_docs_create","google_docs_create_named_range","google_docs_create_paragraph_bullets","google_docs_delete_content_range","google_docs_delete_named_range","google_docs_delete_paragraph_bullets","google_docs_insert_image","google_docs_insert_page_break","google_docs_insert_table","google_docs_insert_text","google_docs_read","google_docs_replace_text","google_docs_update_paragraph_style","google_docs_update_text_style","google_docs_write","google_drive_copy","google_drive_create_comment","google_drive_create_folder","google_drive_delete","google_drive_delete_comment","google_drive_download","google_drive_export","google_drive_get_about","google_drive_get_content","google_drive_get_file","google_drive_get_revision","google_drive_list","google_drive_list_comments","google_drive_list_permissions","google_drive_list_revisions","google_drive_move","google_drive_search","google_drive_share","google_drive_trash","google_drive_unshare","google_drive_untrash","google_drive_update","google_drive_upload","google_forms_batch_update","google_forms_create_form","google_forms_create_watch","google_forms_delete_watch","google_forms_get_form","google_forms_get_responses","google_forms_list_watches","google_forms_renew_watch","google_forms_set_publish_settings","google_groups_add_alias","google_groups_add_member","google_groups_create_group","google_groups_delete_group","google_groups_get_group","google_groups_get_member","google_groups_get_settings","google_groups_has_member","google_groups_list_aliases","google_groups_list_groups","google_groups_list_members","google_groups_remove_alias","google_groups_remove_member","google_groups_update_group","google_groups_update_member","google_groups_update_settings","google_maps_air_quality","google_maps_directions","google_maps_distance_matrix","google_maps_elevation","google_maps_geocode","google_maps_geolocate","google_maps_place_details","google_maps_places_nearby","google_maps_places_search","google_maps_pollen","google_maps_reverse_geocode","google_maps_snap_to_roads","google_maps_solar","google_maps_speed_limits","google_maps_timezone","google_maps_validate_address","google_meet_create_space","google_meet_end_conference","google_meet_get_conference_record","google_meet_get_space","google_meet_list_conference_records","google_meet_list_participants","google_pagespeed_analyze","google_search","google_sheets_append","google_sheets_append_v2","google_sheets_batch_clear_v2","google_sheets_batch_get_v2","google_sheets_batch_update_v2","google_sheets_clear_v2","google_sheets_copy_sheet_v2","google_sheets_create_spreadsheet_v2","google_sheets_delete_rows_v2","google_sheets_delete_sheet_v2","google_sheets_delete_spreadsheet_v2","google_sheets_get_spreadsheet_v2","google_sheets_read","google_sheets_read_v2","google_sheets_update","google_sheets_update_v2","google_sheets_write","google_sheets_write_v2","google_slides_add_image","google_slides_add_slide","google_slides_batch_update","google_slides_copy_presentation","google_slides_create","google_slides_create_line","google_slides_create_paragraph_bullets","google_slides_create_shape","google_slides_create_sheets_chart","google_slides_create_table","google_slides_create_video","google_slides_delete_object","google_slides_delete_paragraph_bullets","google_slides_delete_table_column","google_slides_delete_table_row","google_slides_delete_text","google_slides_duplicate_object","google_slides_export_presentation","google_slides_get_page","google_slides_get_thumbnail","google_slides_group_objects","google_slides_insert_table_columns","google_slides_insert_table_rows","google_slides_insert_text","google_slides_merge_table_cells","google_slides_read","google_slides_refresh_sheets_chart","google_slides_replace_all_shapes_with_image","google_slides_replace_all_shapes_with_sheets_chart","google_slides_replace_all_text","google_slides_replace_image","google_slides_reroute_line","google_slides_ungroup_objects","google_slides_unmerge_table_cells","google_slides_update_image_properties","google_slides_update_line_category","google_slides_update_line_properties","google_slides_update_page_element_alt_text","google_slides_update_page_element_transform","google_slides_update_page_elements_z_order","google_slides_update_page_properties","google_slides_update_paragraph_style","google_slides_update_shape_properties","google_slides_update_slide_properties","google_slides_update_slides_position","google_slides_update_table_border_properties","google_slides_update_table_cell_properties","google_slides_update_table_column_properties","google_slides_update_table_row_properties","google_slides_update_text_style","google_slides_update_video_properties","google_slides_write","google_tasks_create","google_tasks_delete","google_tasks_get","google_tasks_list","google_tasks_list_task_lists","google_tasks_update","google_translate_detect","google_translate_text","google_vault_add_held_accounts","google_vault_add_matters_permissions","google_vault_close_matters","google_vault_create_matters","google_vault_create_matters_export","google_vault_create_matters_holds","google_vault_create_saved_query","google_vault_delete_matters","google_vault_delete_matters_export","google_vault_delete_matters_holds","google_vault_delete_saved_query","google_vault_download_export_file","google_vault_list_matters","google_vault_list_matters_export","google_vault_list_matters_holds","google_vault_list_saved_queries","google_vault_remove_held_accounts","google_vault_remove_matters_permissions","google_vault_reopen_matters","google_vault_undelete_matters","google_vault_update_matters","google_vault_update_matters_holds","grafana_check_data_source_health","grafana_create_alert_rule","grafana_create_annotation","grafana_create_contact_point","grafana_create_dashboard","grafana_create_folder","grafana_delete_alert_rule","grafana_delete_annotation","grafana_delete_contact_point","grafana_delete_dashboard","grafana_delete_folder","grafana_get_alert_rule","grafana_get_alert_rule_group","grafana_get_dashboard","grafana_get_data_source","grafana_get_folder","grafana_get_health","grafana_list_alert_rules","grafana_list_annotations","grafana_list_contact_points","grafana_list_dashboards","grafana_list_data_sources","grafana_list_folders","grafana_move_folder","grafana_query_data_source","grafana_update_alert_rule","grafana_update_annotation","grafana_update_contact_point","grafana_update_dashboard","grafana_update_folder","grain_create_hook","grain_create_hook_v2","grain_delete_hook","grain_delete_hook_v2","grain_get_recording","grain_get_transcript","grain_list_hooks","grain_list_hooks_v2","grain_list_meeting_types","grain_list_recordings","grain_list_teams","grain_list_views","granola_create_webhook_endpoint","granola_delete_webhook_endpoint","granola_get_note","granola_get_transcript","granola_list_audit_events","granola_list_folders","granola_list_notes","granola_list_webhook_endpoints","granola_update_webhook_endpoint","greenhouse_apply_candidate_tag_v2","greenhouse_convert_prospect_v2","greenhouse_create_application_v2","greenhouse_create_attachment_v2","greenhouse_create_candidate_tag_v2","greenhouse_create_candidate_v2","greenhouse_create_note_v2","greenhouse_delete_application_v2","greenhouse_delete_attachment_v2","greenhouse_delete_candidate_v2","greenhouse_get_application","greenhouse_get_application_v2","greenhouse_get_candidate","greenhouse_get_candidate_v2","greenhouse_get_job","greenhouse_get_job_v2","greenhouse_get_user","greenhouse_get_user_v2","greenhouse_hire_application_v2","greenhouse_list_application_stages_v2","greenhouse_list_applications","greenhouse_list_applications_v2","greenhouse_list_applied_candidate_tags_v2","greenhouse_list_attachments_v2","greenhouse_list_candidate_educations_v2","greenhouse_list_candidate_employments_v2","greenhouse_list_candidate_tags_v2","greenhouse_list_candidates","greenhouse_list_candidates_v2","greenhouse_list_close_reasons_v2","greenhouse_list_custom_field_options_v2","greenhouse_list_custom_fields_v2","greenhouse_list_departments","greenhouse_list_departments_v2","greenhouse_list_email_templates_v2","greenhouse_list_interviews_v2","greenhouse_list_job_hiring_managers_v2","greenhouse_list_job_interview_stages_v2","greenhouse_list_job_owners_v2","greenhouse_list_job_stages","greenhouse_list_jobs","greenhouse_list_jobs_v2","greenhouse_list_notes_v2","greenhouse_list_offers_v2","greenhouse_list_offices","greenhouse_list_offices_v2","greenhouse_list_openings_v2","greenhouse_list_prospect_pool_stages_v2","greenhouse_list_prospect_pools_v2","greenhouse_list_referrers_v2","greenhouse_list_rejection_reasons_v2","greenhouse_list_scorecards_v2","greenhouse_list_sources_v2","greenhouse_list_users","greenhouse_list_users_v2","greenhouse_move_application_v2","greenhouse_reject_application_v2","greenhouse_remove_candidate_tag_v2","greenhouse_unreject_application_v2","greenhouse_update_application_v2","greenhouse_update_candidate_v2","greptile_index_repo","greptile_query","greptile_search","greptile_status","guardrails_validate","harmonic_batch_get_people","harmonic_clear_people_saved_search_net_new_results","harmonic_enrich_person","harmonic_get_company_employees","harmonic_get_email_enrichment_job","harmonic_get_email_enrichment_usage","harmonic_get_enrichment_status","harmonic_get_people_saved_search_net_new_results","harmonic_get_people_saved_search_results","harmonic_get_person","harmonic_list_people_saved_searches","harmonic_search_people_scout","harmonic_submit_email_enrichment_job","helpscout_assign_conversation","helpscout_create_conversation","helpscout_create_customer","helpscout_create_customer_thread","helpscout_create_note","helpscout_create_reply","helpscout_delete_conversation","helpscout_get_conversation","helpscout_get_current_user","helpscout_get_customer","helpscout_get_organization","helpscout_get_saved_reply","helpscout_list_conversations","helpscout_list_custom_fields","helpscout_list_customer_properties","helpscout_list_customers","helpscout_list_folders","helpscout_list_mailboxes","helpscout_list_organizations","helpscout_list_saved_replies","helpscout_list_tags","helpscout_list_teams","helpscout_list_threads","helpscout_list_users","helpscout_list_workflows","helpscout_move_conversation","helpscout_run_workflow","helpscout_set_conversation_tags","helpscout_snooze_conversation","helpscout_unassign_conversation","helpscout_unsnooze_conversation","helpscout_update_conversation_customer","helpscout_update_conversation_status","helpscout_update_conversation_subject","helpscout_update_custom_fields","helpscout_update_customer","helpscout_update_customer_properties","hex_cancel_run","hex_create_collection","hex_create_group","hex_deactivate_user","hex_delete_group","hex_get_collection","hex_get_data_connection","hex_get_group","hex_get_project","hex_get_project_runs","hex_get_queried_tables","hex_get_run_status","hex_list_collections","hex_list_data_connections","hex_list_groups","hex_list_projects","hex_list_users","hex_run_project","hex_update_collection","hex_update_group","hex_update_project","http_request","hubspot_add_list_memberships","hubspot_create_appointment","hubspot_create_association","hubspot_create_company","hubspot_create_contact","hubspot_create_deal","hubspot_create_email","hubspot_create_line_item","hubspot_create_list","hubspot_create_note","hubspot_create_ticket","hubspot_delete_association","hubspot_delete_company","hubspot_delete_contact","hubspot_delete_deal","hubspot_delete_line_item","hubspot_delete_ticket","hubspot_get_appointment","hubspot_get_association_labels","hubspot_get_cart","hubspot_get_company","hubspot_get_contact","hubspot_get_deal","hubspot_get_email","hubspot_get_line_item","hubspot_get_list","hubspot_get_list_memberships","hubspot_get_marketing_event","hubspot_get_note","hubspot_get_properties","hubspot_get_quote","hubspot_get_ticket","hubspot_get_users","hubspot_list_appointments","hubspot_list_associations","hubspot_list_carts","hubspot_list_companies","hubspot_list_contacts","hubspot_list_deals","hubspot_list_emails","hubspot_list_line_items","hubspot_list_lists","hubspot_list_marketing_events","hubspot_list_notes","hubspot_list_owners","hubspot_list_quotes","hubspot_list_tickets","hubspot_remove_list_memberships","hubspot_search_companies","hubspot_search_contacts","hubspot_search_deals","hubspot_search_emails","hubspot_search_line_items","hubspot_search_notes","hubspot_search_quotes","hubspot_search_tickets","hubspot_update_appointment","hubspot_update_company","hubspot_update_contact","hubspot_update_deal","hubspot_update_line_item","hubspot_update_ticket","huggingface_chat","hunter_companies_find","hunter_discover","hunter_domain_search","hunter_email_count","hunter_email_finder","hunter_email_verifier","iam_add_user_to_group","iam_attach_role_policy","iam_attach_user_policy","iam_create_access_key","iam_create_role","iam_create_user","iam_delete_access_key","iam_delete_role","iam_delete_user","iam_detach_role_policy","iam_detach_user_policy","iam_get_policy","iam_get_role","iam_get_user","iam_list_access_keys","iam_list_attached_role_policies","iam_list_attached_user_policies","iam_list_groups","iam_list_policies","iam_list_roles","iam_list_users","iam_remove_user_from_group","iam_simulate_principal_policy","iam_update_access_key","icypeas_find_email","icypeas_verify_email","identity_center_check_assignment_deletion_status","identity_center_check_assignment_status","identity_center_create_account_assignment","identity_center_delete_account_assignment","identity_center_describe_account","identity_center_describe_group","identity_center_describe_user","identity_center_get_group","identity_center_get_user","identity_center_list_account_assignments","identity_center_list_accounts","identity_center_list_assignments_for_account","identity_center_list_group_memberships","identity_center_list_groups","identity_center_list_instances","identity_center_list_permission_sets","image_generate","incidentio_actions_create","incidentio_actions_list","incidentio_actions_show","incidentio_actions_update","incidentio_alert_events_create","incidentio_alerts_list","incidentio_alerts_resolve","incidentio_alerts_show","incidentio_catalog_entries_list","incidentio_catalog_types_list","incidentio_custom_fields_create","incidentio_custom_fields_delete","incidentio_custom_fields_list","incidentio_custom_fields_show","incidentio_custom_fields_update","incidentio_escalation_paths_create","incidentio_escalation_paths_delete","incidentio_escalation_paths_list","incidentio_escalation_paths_show","incidentio_escalation_paths_update","incidentio_escalations_cancel","incidentio_escalations_create","incidentio_escalations_list","incidentio_escalations_show","incidentio_follow_ups_create","incidentio_follow_ups_list","incidentio_follow_ups_show","incidentio_follow_ups_update","incidentio_incident_alerts_list","incidentio_incident_memberships_create","incidentio_incident_memberships_revoke","incidentio_incident_participants_list","incidentio_incident_roles_create","incidentio_incident_roles_delete","incidentio_incident_roles_list","incidentio_incident_roles_show","incidentio_incident_roles_update","incidentio_incident_statuses_list","incidentio_incident_timestamps_list","incidentio_incident_timestamps_show","incidentio_incident_types_list","incidentio_incident_updates_list","incidentio_incidents_create","incidentio_incidents_list","incidentio_incidents_show","incidentio_incidents_update","incidentio_on_call_now","incidentio_schedule_entries_list","incidentio_schedule_overrides_create","incidentio_schedule_overrides_list","incidentio_schedules_create","incidentio_schedules_delete","incidentio_schedules_list","incidentio_schedules_show","incidentio_schedules_update","incidentio_severities_list","incidentio_teams_list","incidentio_teams_show","incidentio_users_list","incidentio_users_show","incidentio_workflows_create","incidentio_workflows_delete","incidentio_workflows_list","incidentio_workflows_show","incidentio_workflows_update","infisical_create_secret","infisical_delete_secret","infisical_get_secret","infisical_list_secrets","infisical_update_secret","instagram_delete_comment","instagram_download_media","instagram_get_account_insights","instagram_get_container_status","instagram_get_conversation_messages","instagram_get_media","instagram_get_media_insights","instagram_get_message","instagram_get_profile","instagram_get_publishing_limit","instagram_hide_comment","instagram_list_comments","instagram_list_conversations","instagram_list_media","instagram_list_stories","instagram_private_reply","instagram_publish_carousel","instagram_publish_image","instagram_publish_reel","instagram_publish_story","instagram_publish_video","instagram_reply_to_comment","instagram_send_text_message","instagram_set_comments_enabled","instantly_activate_campaign","instantly_create_campaign","instantly_create_lead","instantly_create_lead_list","instantly_delete_campaign","instantly_delete_leads","instantly_get_lead","instantly_list_campaigns","instantly_list_emails","instantly_list_lead_lists","instantly_list_leads","instantly_patch_campaign","instantly_patch_lead","instantly_pause_campaign","instantly_reply_to_email","instantly_update_lead_interest_status","intercom_assign_conversation_v2","intercom_attach_contact_to_company_v2","intercom_close_conversation_v2","intercom_create_company","intercom_create_company_v2","intercom_create_contact","intercom_create_contact_v2","intercom_create_event_v2","intercom_create_message","intercom_create_message_v2","intercom_create_note_v2","intercom_create_tag_v2","intercom_create_ticket","intercom_create_ticket_v2","intercom_delete_contact","intercom_delete_contact_v2","intercom_detach_contact_from_company_v2","intercom_get_company","intercom_get_company_v2","intercom_get_contact","intercom_get_contact_v2","intercom_get_conversation","intercom_get_conversation_v2","intercom_get_ticket","intercom_get_ticket_v2","intercom_list_admins_v2","intercom_list_companies","intercom_list_companies_v2","intercom_list_contacts","intercom_list_contacts_v2","intercom_list_conversations","intercom_list_conversations_v2","intercom_list_tags_v2","intercom_open_conversation_v2","intercom_reply_conversation","intercom_reply_conversation_v2","intercom_search_contacts","intercom_search_contacts_v2","intercom_search_conversations","intercom_search_conversations_v2","intercom_snooze_conversation_v2","intercom_tag_contact_v2","intercom_tag_conversation_v2","intercom_untag_contact_v2","intercom_update_contact","intercom_update_contact_v2","intercom_update_ticket_v2","intune_get_compliance_policy","intune_get_detected_app","intune_get_device","intune_get_device_configuration","intune_list_app_devices","intune_list_compliance_policies","intune_list_compliance_policy_device_statuses","intune_list_detected_apps","intune_list_device_configurations","intune_list_devices","intune_reboot_device","intune_remote_lock_device","intune_retire_device","intune_sync_device","jina_read_url","jina_search","jira_add_attachment","jira_add_comment","jira_add_watcher","jira_add_worklog","jira_assign_issue","jira_bulk_read","jira_create_issue_link","jira_delete_attachment","jira_delete_comment","jira_delete_issue","jira_delete_issue_link","jira_delete_worklog","jira_get_attachments","jira_get_comments","jira_get_fields","jira_get_project","jira_get_transitions","jira_get_users","jira_get_worklogs","jira_list_issue_types","jira_list_projects","jira_remove_watcher","jira_retrieve","jira_search_issues","jira_search_users","jira_transition_issue","jira_update","jira_update_comment","jira_update_worklog","jira_write","jotform_add_label_resources","jotform_clone_form","jotform_create_form","jotform_create_label","jotform_create_question","jotform_create_questions","jotform_create_report","jotform_create_submission","jotform_create_submissions","jotform_create_webhook","jotform_delete_form","jotform_delete_label","jotform_delete_question","jotform_delete_report","jotform_delete_submission","jotform_delete_webhook","jotform_get_form","jotform_get_form_properties","jotform_get_history","jotform_get_label","jotform_get_question","jotform_get_report","jotform_get_settings","jotform_get_submission","jotform_get_usage","jotform_get_user","jotform_list_form_files","jotform_list_form_reports","jotform_list_form_submissions","jotform_list_forms","jotform_list_label_resources","jotform_list_labels","jotform_list_questions","jotform_list_reports","jotform_list_submissions","jotform_list_subusers","jotform_list_webhooks","jotform_remove_label_resources","jotform_update_form_properties","jotform_update_label","jotform_update_question","jotform_update_settings","jotform_update_submission","jsm_add_comment","jsm_add_customer","jsm_add_organization","jsm_add_participants","jsm_answer_approval","jsm_attach_form","jsm_copy_forms","jsm_create_object","jsm_create_organization","jsm_create_request","jsm_delete_form","jsm_delete_object","jsm_externalise_form","jsm_get_approvals","jsm_get_comments","jsm_get_customers","jsm_get_form","jsm_get_form_answers","jsm_get_form_structure","jsm_get_form_templates","jsm_get_issue_forms","jsm_get_object","jsm_get_object_schema","jsm_get_object_type_attributes","jsm_get_organizations","jsm_get_participants","jsm_get_queues","jsm_get_request","jsm_get_request_type_fields","jsm_get_request_types","jsm_get_requests","jsm_get_service_desks","jsm_get_sla","jsm_get_transitions","jsm_internalise_form","jsm_list_object_schemas","jsm_list_object_types","jsm_reopen_form","jsm_save_form_answers","jsm_search_objects_aql","jsm_submit_form","jsm_transition_request","jsm_update_object","jupyter_copy_content","jupyter_create_file","jupyter_create_session","jupyter_delete_content","jupyter_delete_session","jupyter_get_content","jupyter_get_content_v2","jupyter_interrupt_kernel","jupyter_list_contents","jupyter_list_kernels","jupyter_list_kernelspecs","jupyter_list_sessions","jupyter_rename_content","jupyter_restart_kernel","jupyter_start_kernel","jupyter_stop_kernel","jupyter_upload_file","kalshi_amend_order","kalshi_amend_order_v2","kalshi_cancel_order","kalshi_cancel_order_v2","kalshi_create_order","kalshi_create_order_v2","kalshi_get_balance","kalshi_get_balance_v2","kalshi_get_candlesticks","kalshi_get_candlesticks_v2","kalshi_get_event","kalshi_get_event_candlesticks","kalshi_get_event_candlesticks_v2","kalshi_get_event_v2","kalshi_get_events","kalshi_get_events_v2","kalshi_get_exchange_announcements","kalshi_get_exchange_announcements_v2","kalshi_get_exchange_schedule","kalshi_get_exchange_schedule_v2","kalshi_get_exchange_status","kalshi_get_exchange_status_v2","kalshi_get_fills","kalshi_get_fills_v2","kalshi_get_market","kalshi_get_market_v2","kalshi_get_markets","kalshi_get_markets_v2","kalshi_get_order","kalshi_get_order_v2","kalshi_get_orderbook","kalshi_get_orderbook_v2","kalshi_get_orders","kalshi_get_orders_v2","kalshi_get_positions","kalshi_get_positions_v2","kalshi_get_series_by_ticker","kalshi_get_series_by_ticker_v2","kalshi_get_series_list","kalshi_get_series_list_v2","kalshi_get_settlements","kalshi_get_settlements_v2","kalshi_get_trades","kalshi_get_trades_v2","ketch_get_consent","ketch_get_subscriptions","ketch_invoke_right","ketch_set_consent","ketch_set_subscriptions","knowledge_create_document","knowledge_delete_chunk","knowledge_delete_document","knowledge_get_connector","knowledge_get_document","knowledge_list_chunks","knowledge_list_connectors","knowledge_list_documents","knowledge_list_tags","knowledge_search","knowledge_trigger_sync","knowledge_update_chunk","knowledge_upload_chunk","knowledge_upsert_document","lambda_add_permission","lambda_create_alias","lambda_create_event_source_mapping","lambda_create_function","lambda_create_function_url_config","lambda_delete_alias","lambda_delete_event_source_mapping","lambda_delete_function","lambda_delete_function_concurrency","lambda_delete_function_event_invoke_config","lambda_delete_function_url_config","lambda_delete_provisioned_concurrency_config","lambda_get_account_settings","lambda_get_alias","lambda_get_event_source_mapping","lambda_get_function","lambda_get_function_concurrency","lambda_get_function_configuration","lambda_get_function_event_invoke_config","lambda_get_function_recursion_config","lambda_get_function_url_config","lambda_get_layer_version","lambda_get_policy","lambda_get_provisioned_concurrency_config","lambda_get_runtime_management_config","lambda_invoke","lambda_list_aliases","lambda_list_event_source_mappings","lambda_list_function_event_invoke_configs","lambda_list_function_url_configs","lambda_list_functions","lambda_list_layer_versions","lambda_list_layers","lambda_list_provisioned_concurrency_configs","lambda_list_tags","lambda_list_versions_by_function","lambda_publish_version","lambda_put_function_concurrency","lambda_put_function_event_invoke_config","lambda_put_function_recursion_config","lambda_put_provisioned_concurrency_config","lambda_put_runtime_management_config","lambda_remove_permission","lambda_tag_resource","lambda_untag_resource","lambda_update_alias","lambda_update_event_source_mapping","lambda_update_function_code","lambda_update_function_configuration","lambda_update_function_url_config","langsmith_create_feedback","langsmith_create_run","langsmith_create_runs_batch","langsmith_get_run","langsmith_update_run","latex_compile","latex_get_package","latex_list_fonts","latex_search_packages","launchdarkly_create_flag","launchdarkly_delete_flag","launchdarkly_get_audit_log","launchdarkly_get_flag","launchdarkly_get_flag_status","launchdarkly_list_environments","launchdarkly_list_flags","launchdarkly_list_members","launchdarkly_list_projects","launchdarkly_list_segments","launchdarkly_toggle_flag","launchdarkly_update_flag","leadmagic_company_search","leadmagic_email_to_profile","leadmagic_find_email","leadmagic_find_mobile","leadmagic_get_credits","leadmagic_profile_search","leadmagic_profile_to_email","leadmagic_role_finder","leadmagic_validate_email","lemlist_get_activities","lemlist_get_lead","lemlist_send_email","linear_add_label_to_issue","linear_add_label_to_project","linear_archive_issue","linear_archive_label","linear_archive_project","linear_create_attachment","linear_create_comment","linear_create_customer","linear_create_customer_request","linear_create_customer_status","linear_create_customer_tier","linear_create_cycle","linear_create_favorite","linear_create_issue","linear_create_issue_relation","linear_create_label","linear_create_project","linear_create_project_label","linear_create_project_milestone","linear_create_project_status","linear_create_project_update","linear_create_workflow_state","linear_delete_attachment","linear_delete_comment","linear_delete_customer","linear_delete_customer_status","linear_delete_customer_tier","linear_delete_issue","linear_delete_issue_relation","linear_delete_project","linear_delete_project_label","linear_delete_project_milestone","linear_delete_project_status","linear_get_active_cycle","linear_get_customer","linear_get_cycle","linear_get_issue","linear_get_project","linear_get_viewer","linear_list_attachments","linear_list_comments","linear_list_customer_requests","linear_list_customer_statuses","linear_list_customer_tiers","linear_list_customers","linear_list_cycles","linear_list_favorites","linear_list_issue_relations","linear_list_labels","linear_list_notifications","linear_list_project_labels","linear_list_project_milestones","linear_list_project_statuses","linear_list_project_updates","linear_list_projects","linear_list_teams","linear_list_users","linear_list_workflow_states","linear_merge_customers","linear_read_issues","linear_remove_label_from_issue","linear_remove_label_from_project","linear_search_issues","linear_unarchive_issue","linear_update_attachment","linear_update_comment","linear_update_customer","linear_update_customer_request","linear_update_customer_status","linear_update_customer_tier","linear_update_issue","linear_update_label","linear_update_notification","linear_update_project","linear_update_project_label","linear_update_project_milestone","linear_update_project_status","linear_update_workflow_state","linkedin_get_profile","linkedin_share_post","linkup_search","linq_add_participant","linq_check_imessage","linq_check_rcs","linq_create_attachment","linq_create_chat","linq_create_contact_card","linq_create_webhook_subscription","linq_delete_attachment","linq_delete_message","linq_delete_webhook_subscription","linq_edit_message","linq_get_attachment","linq_get_chat","linq_get_contact_card","linq_get_message","linq_get_webhook_subscription","linq_leave_chat","linq_list_chats","linq_list_messages","linq_list_phone_numbers","linq_list_thread","linq_list_webhook_events","linq_list_webhook_subscriptions","linq_mark_chat_read","linq_react_to_message","linq_remove_participant","linq_send_message","linq_send_voice_memo","linq_share_contact_card","linq_start_typing","linq_stop_typing","linq_update_chat","linq_update_contact_card","linq_update_webhook_subscription","llm_chat","logfire_get_token_info","logfire_get_trace","logfire_query","logfire_search_records","logrocket_create_release","logrocket_get_audit_logs","logrocket_get_highlights","logrocket_identify_user","logrocket_list_exported_sessions","logrocket_request_highlights","logs_get","logs_get_execution","logs_get_run_details","logs_query","logs_query_runs","loops_check_contact_suppression","loops_create_contact","loops_create_contact_property","loops_delete_contact","loops_find_contact","loops_get_transactional_email","loops_list_contact_properties","loops_list_mailing_lists","loops_list_transactional_emails","loops_remove_contact_suppression","loops_send_event","loops_send_transactional_email","loops_update_contact","luma_add_guests","luma_cancel_event","luma_create_event","luma_get_event","luma_get_guest","luma_get_guests","luma_list_events","luma_lookup_event","luma_send_invites","luma_update_event","luma_update_guest_status","mailchimp_add_member","mailchimp_add_member_tags","mailchimp_add_or_update_member","mailchimp_add_segment_member","mailchimp_add_subscriber_to_automation","mailchimp_archive_member","mailchimp_create_audience","mailchimp_create_batch_operation","mailchimp_create_campaign","mailchimp_create_interest","mailchimp_create_interest_category","mailchimp_create_landing_page","mailchimp_create_merge_field","mailchimp_create_segment","mailchimp_create_template","mailchimp_delete_audience","mailchimp_delete_batch_operation","mailchimp_delete_campaign","mailchimp_delete_interest","mailchimp_delete_interest_category","mailchimp_delete_landing_page","mailchimp_delete_member","mailchimp_delete_merge_field","mailchimp_delete_segment","mailchimp_delete_template","mailchimp_get_audience","mailchimp_get_audiences","mailchimp_get_automation","mailchimp_get_automations","mailchimp_get_batch_operation","mailchimp_get_batch_operations","mailchimp_get_campaign","mailchimp_get_campaign_content","mailchimp_get_campaign_report","mailchimp_get_campaign_reports","mailchimp_get_campaigns","mailchimp_get_interest","mailchimp_get_interest_categories","mailchimp_get_interest_category","mailchimp_get_interests","mailchimp_get_landing_page","mailchimp_get_landing_pages","mailchimp_get_member","mailchimp_get_member_tags","mailchimp_get_members","mailchimp_get_merge_field","mailchimp_get_merge_fields","mailchimp_get_segment","mailchimp_get_segment_members","mailchimp_get_segments","mailchimp_get_template","mailchimp_get_templates","mailchimp_pause_automation","mailchimp_publish_landing_page","mailchimp_remove_member_tags","mailchimp_remove_segment_member","mailchimp_replicate_campaign","mailchimp_schedule_campaign","mailchimp_send_campaign","mailchimp_set_campaign_content","mailchimp_start_automation","mailchimp_unarchive_member","mailchimp_unpublish_landing_page","mailchimp_unschedule_campaign","mailchimp_update_audience","mailchimp_update_campaign","mailchimp_update_interest","mailchimp_update_interest_category","mailchimp_update_landing_page","mailchimp_update_member","mailchimp_update_merge_field","mailchimp_update_segment","mailchimp_update_template","mailgun_add_list_member","mailgun_create_mailing_list","mailgun_get_domain","mailgun_get_mailing_list","mailgun_get_message","mailgun_list_domains","mailgun_list_messages","mailgun_send_message","managed_agent_archive_session","managed_agent_create_session","managed_agent_delete_session","managed_agent_get_session","managed_agent_interrupt_session","managed_agent_list_events","managed_agent_respond_custom_tool","managed_agent_respond_tool_confirmation","managed_agent_run_session","managed_agent_send_message","managed_agent_update_session","manageengine_sdp_add_change_note","manageengine_sdp_add_problem_note","manageengine_sdp_add_request_note","manageengine_sdp_create_asset","manageengine_sdp_create_change","manageengine_sdp_create_problem","manageengine_sdp_create_request","manageengine_sdp_create_solution","manageengine_sdp_delete_asset","manageengine_sdp_delete_change","manageengine_sdp_delete_problem","manageengine_sdp_delete_request","manageengine_sdp_delete_solution","manageengine_sdp_get_asset","manageengine_sdp_get_change","manageengine_sdp_get_problem","manageengine_sdp_get_request","manageengine_sdp_get_solution","manageengine_sdp_list_assets","manageengine_sdp_list_change_notes","manageengine_sdp_list_changes","manageengine_sdp_list_problem_notes","manageengine_sdp_list_problems","manageengine_sdp_list_request_notes","manageengine_sdp_list_requests","manageengine_sdp_list_solutions","manageengine_sdp_update_asset","manageengine_sdp_update_change","manageengine_sdp_update_problem","manageengine_sdp_update_request","manageengine_sdp_update_solution","mcp_list_operations","mcp_run_operation","mem0_add_memories","mem0_get_memories","mem0_search_memories","memory_add","memory_delete","memory_get","memory_get_all","microsoft_ad_add_directory_role_member","microsoft_ad_add_group_member","microsoft_ad_add_user_app_role_assignment","microsoft_ad_assign_license","microsoft_ad_create_group","microsoft_ad_create_user","microsoft_ad_delete_group","microsoft_ad_delete_user","microsoft_ad_get_conditional_access_policy","microsoft_ad_get_device","microsoft_ad_get_group","microsoft_ad_get_user","microsoft_ad_list_authentication_methods","microsoft_ad_list_conditional_access_policies","microsoft_ad_list_devices","microsoft_ad_list_directory_audits","microsoft_ad_list_directory_role_members","microsoft_ad_list_directory_roles","microsoft_ad_list_group_members","microsoft_ad_list_groups","microsoft_ad_list_service_principal_app_role_assignments","microsoft_ad_list_service_principals","microsoft_ad_list_sign_ins","microsoft_ad_list_subscribed_skus","microsoft_ad_list_user_app_role_assignments","microsoft_ad_list_user_devices","microsoft_ad_list_user_licenses","microsoft_ad_list_users","microsoft_ad_remove_directory_role_member","microsoft_ad_remove_group_member","microsoft_ad_remove_user_app_role_assignment","microsoft_ad_reset_password","microsoft_ad_revoke_sign_in_sessions","microsoft_ad_set_password","microsoft_ad_update_group","microsoft_ad_update_user","microsoft_dataverse_associate","microsoft_dataverse_create_multiple","microsoft_dataverse_create_record","microsoft_dataverse_delete_record","microsoft_dataverse_disassociate","microsoft_dataverse_download_file","microsoft_dataverse_download_file_v2","microsoft_dataverse_execute_action","microsoft_dataverse_execute_function","microsoft_dataverse_fetchxml_query","microsoft_dataverse_get_entity_metadata","microsoft_dataverse_get_record","microsoft_dataverse_list_records","microsoft_dataverse_search","microsoft_dataverse_update_multiple","microsoft_dataverse_update_record","microsoft_dataverse_upload_file","microsoft_dataverse_upsert_record","microsoft_dataverse_whoami","microsoft_dynamics_365_close_case","microsoft_dynamics_365_close_opportunity","microsoft_dynamics_365_create_record","microsoft_dynamics_365_get_record","microsoft_dynamics_365_list_records","microsoft_dynamics_365_qualify_lead","microsoft_dynamics_365_search_records","microsoft_dynamics_365_update_record","microsoft_excel_calculate","microsoft_excel_clear_range","microsoft_excel_close_session","microsoft_excel_create_session","microsoft_excel_create_table","microsoft_excel_delete_table","microsoft_excel_delete_table_row","microsoft_excel_delete_worksheet","microsoft_excel_format_range","microsoft_excel_get_table","microsoft_excel_get_table_row","microsoft_excel_get_worksheet","microsoft_excel_list_table_rows","microsoft_excel_list_tables","microsoft_excel_list_worksheets","microsoft_excel_read","microsoft_excel_read_v2","microsoft_excel_refresh_session","microsoft_excel_sort_range","microsoft_excel_table_add","microsoft_excel_update_table","microsoft_excel_update_table_row","microsoft_excel_update_worksheet","microsoft_excel_worksheet_add","microsoft_excel_write","microsoft_excel_write_v2","microsoft_planner_create_bucket","microsoft_planner_create_plan","microsoft_planner_create_task","microsoft_planner_delete_bucket","microsoft_planner_delete_plan","microsoft_planner_delete_task","microsoft_planner_get_plan_details","microsoft_planner_get_task_details","microsoft_planner_list_buckets","microsoft_planner_list_plans","microsoft_planner_read_bucket","microsoft_planner_read_plan","microsoft_planner_read_task","microsoft_planner_update_bucket","microsoft_planner_update_plan","microsoft_planner_update_plan_details","microsoft_planner_update_task","microsoft_planner_update_task_details","microsoft_teams_delete_channel_message","microsoft_teams_delete_chat_message","microsoft_teams_get_message","microsoft_teams_list_channel_members","microsoft_teams_list_channels","microsoft_teams_list_chat_members","microsoft_teams_list_chats","microsoft_teams_list_team_members","microsoft_teams_list_teams","microsoft_teams_read_channel","microsoft_teams_read_chat","microsoft_teams_reply_to_message","microsoft_teams_set_reaction","microsoft_teams_unset_reaction","microsoft_teams_update_channel_message","microsoft_teams_update_chat_message","microsoft_teams_write_channel","microsoft_teams_write_chat","microsoft_word_append","microsoft_word_create","microsoft_word_create_from_template","microsoft_word_export_pdf","microsoft_word_list","microsoft_word_read","microsoft_word_replace_text","microsoft_word_update","millionverifier_get_credits","millionverifier_verify_email","mintlify_create_agent_job","mintlify_create_assistant_message","mintlify_detect_ai_prose","mintlify_get_agent_job","mintlify_get_assistant_caller_stats","mintlify_get_assistant_conversations","mintlify_get_feedback","mintlify_get_feedback_by_page","mintlify_get_page_content","mintlify_get_searches","mintlify_get_update_status","mintlify_get_views","mintlify_get_visitors","mintlify_search","mintlify_send_agent_message","mintlify_trigger_automation","mintlify_trigger_preview","mintlify_trigger_update","mistral_parser","mistral_parser_v2","mistral_parser_v3","modal_call_function","modal_chat_completion","modal_list_models","monday_archive_item","monday_change_column_value","monday_create_board","monday_create_column","monday_create_group","monday_create_item","monday_create_subitem","monday_create_update","monday_delete_item","monday_duplicate_item","monday_get_board","monday_get_groups","monday_get_item","monday_get_items","monday_list_boards","monday_move_item_to_group","monday_search_items","monday_update_item","mongodb_delete","mongodb_execute","mongodb_insert","mongodb_introspect","mongodb_query","mongodb_update","mssql_delete","mssql_execute","mssql_insert","mssql_introspect","mssql_query","mssql_update","mysql_delete","mysql_execute","mysql_insert","mysql_introspect","mysql_query","mysql_update","neo4j_create","neo4j_delete","neo4j_execute","neo4j_introspect","neo4j_merge","neo4j_query","neo4j_update","netsuite_attach_record","netsuite_batch_create_records","netsuite_batch_delete_records","netsuite_batch_get_records","netsuite_batch_update_records","netsuite_batch_upsert_records","netsuite_create_record","netsuite_delete_record","netsuite_detach_record","netsuite_execute_action","netsuite_execute_dataset","netsuite_execute_suiteql","netsuite_get_async_result","netsuite_get_async_status","netsuite_get_governance_limits","netsuite_get_record","netsuite_get_record_form","netsuite_get_record_metadata","netsuite_get_select_options","netsuite_get_server_time","netsuite_get_subresource","netsuite_list_datasets","netsuite_list_record_types","netsuite_list_records","netsuite_transform_record","netsuite_update_record","netsuite_upsert_record","neverbounce_get_credits","neverbounce_verify_email","new_relic_create_deployment_event","new_relic_get_entity","new_relic_nrql_query","new_relic_search_entities","notion_add_database_row","notion_add_database_row_v2","notion_append_blocks","notion_append_blocks_v2","notion_create_comment","notion_create_comment_v2","notion_create_database","notion_create_database_v2","notion_create_page","notion_create_page_v2","notion_delete_block","notion_delete_block_v2","notion_list_comments","notion_list_comments_v2","notion_list_users","notion_list_users_v2","notion_query_database","notion_query_database_v2","notion_read","notion_read_database","notion_read_database_v2","notion_read_v2","notion_retrieve_block","notion_retrieve_block_children","notion_retrieve_block_children_v2","notion_retrieve_block_v2","notion_retrieve_user","notion_retrieve_user_v2","notion_search","notion_search_v2","notion_update_block","notion_update_block_v2","notion_update_page","notion_update_page_v2","notion_write","notion_write_v2","obsidian_append_active","obsidian_append_note","obsidian_append_periodic_note","obsidian_create_note","obsidian_delete_note","obsidian_execute_command","obsidian_get_active","obsidian_get_note","obsidian_get_periodic_note","obsidian_list_commands","obsidian_list_files","obsidian_open_file","obsidian_patch_active","obsidian_patch_note","obsidian_search","okta_activate_group_rule","okta_activate_user","okta_add_user_to_group","okta_assign_group_to_app","okta_assign_user_role","okta_assign_user_to_app","okta_clear_user_sessions","okta_create_group","okta_create_group_rule","okta_create_user","okta_deactivate_group_rule","okta_deactivate_user","okta_delete_group","okta_delete_group_rule","okta_delete_user","okta_enroll_factor","okta_get_app","okta_get_factor","okta_get_group","okta_get_group_rule","okta_get_logs","okta_get_session","okta_get_user","okta_list_app_groups","okta_list_app_users","okta_list_apps","okta_list_factors","okta_list_group_members","okta_list_group_rules","okta_list_groups","okta_list_user_roles","okta_list_users","okta_remove_group_from_app","okta_remove_user_from_app","okta_remove_user_from_group","okta_remove_user_role","okta_reset_all_factors","okta_reset_factor","okta_reset_password","okta_revoke_session","okta_suspend_user","okta_unsuspend_user","okta_update_group","okta_update_user","onedrive_copy","onedrive_create_folder","onedrive_create_share_link","onedrive_delete","onedrive_download","onedrive_get_drive_info","onedrive_get_item","onedrive_list","onedrive_move","onedrive_search","onedrive_upload","onepassword_create_item","onepassword_delete_item","onepassword_get_item","onepassword_get_item_file","onepassword_get_vault","onepassword_list_items","onepassword_list_vaults","onepassword_replace_item","onepassword_resolve_secret","onepassword_update_item","openai_embeddings","openai_image","oracle_fusion_financials_apply_receivables_receipt","oracle_fusion_financials_approve_receivables_invoice","oracle_fusion_financials_create_expense_line","oracle_fusion_financials_create_expense_report","oracle_fusion_financials_create_receivables_credit_memo","oracle_fusion_financials_create_receivables_invoice","oracle_fusion_financials_create_receivables_receipt","oracle_fusion_financials_get_expense_line","oracle_fusion_financials_get_expense_report","oracle_fusion_financials_get_gl_journal_batch","oracle_fusion_financials_get_gl_ledger","oracle_fusion_financials_get_payables_invoice","oracle_fusion_financials_get_payables_invoice_line","oracle_fusion_financials_get_payables_payment","oracle_fusion_financials_get_receivables_credit_memo","oracle_fusion_financials_get_receivables_invoice","oracle_fusion_financials_get_receivables_invoice_installment","oracle_fusion_financials_get_receivables_invoice_line","oracle_fusion_financials_get_receivables_receipt","oracle_fusion_financials_list_expense_lines","oracle_fusion_financials_list_expense_reports","oracle_fusion_financials_list_gl_balances","oracle_fusion_financials_list_gl_journal_batches","oracle_fusion_financials_list_gl_ledgers","oracle_fusion_financials_list_payables_invoice_lines","oracle_fusion_financials_list_payables_invoices","oracle_fusion_financials_list_payables_payments","oracle_fusion_financials_list_receivables_credit_memos","oracle_fusion_financials_list_receivables_invoice_installments","oracle_fusion_financials_list_receivables_invoice_lines","oracle_fusion_financials_list_receivables_invoices","oracle_fusion_financials_list_receivables_receipts","oracle_fusion_financials_submit_expense_report","oracle_fusion_financials_update_expense_line","oracle_fusion_financials_update_expense_report","oracle_fusion_financials_update_receivables_invoice","oracledb_delete","oracledb_execute","oracledb_insert","oracledb_introspect","oracledb_query","oracledb_update","otter_create_conversation","otter_get_conversation","otter_get_conversation_audio","otter_get_workspace","otter_list_channel_members","otter_list_channels","otter_list_conversations","otter_list_workspace_conversations","outlook_calendar_create_event","outlook_calendar_delete_event","outlook_calendar_get_event","outlook_calendar_list_events","outlook_calendar_respond","outlook_calendar_update_event","outlook_copy","outlook_create_folder","outlook_delete","outlook_draft","outlook_forward","outlook_get_attachment","outlook_list_attachments","outlook_list_folders","outlook_mark_read","outlook_mark_unread","outlook_move","outlook_read","outlook_reply","outlook_reply_all","outlook_search","outlook_send","outlook_update_message","pagerduty_add_note","pagerduty_create_incident","pagerduty_get_incident","pagerduty_get_service","pagerduty_list_escalation_policies","pagerduty_list_incident_alerts","pagerduty_list_incidents","pagerduty_list_oncalls","pagerduty_list_schedules","pagerduty_list_services","pagerduty_list_users","pagerduty_merge_incidents","pagerduty_send_event","pagerduty_snooze_incident","pagerduty_update_incident","parallel_deep_research","parallel_extract","parallel_search","pdl_autocomplete","pdl_bulk_company_enrich","pdl_bulk_person_enrich","pdl_clean_company","pdl_clean_location","pdl_clean_school","pdl_company_enrich","pdl_company_search","pdl_person_enrich","pdl_person_identify","pdl_person_search","perplexity_chat","perplexity_search","persona_approve_inquiry","persona_create_account","persona_create_inquiry","persona_create_report","persona_decline_inquiry","persona_expire_inquiry","persona_generate_inquiry_link","persona_get_account","persona_get_case","persona_get_document","persona_get_inquiry","persona_get_report","persona_get_verification","persona_import_accounts","persona_list_accounts","persona_list_cases","persona_list_inquiries","persona_list_inquiry_templates","persona_list_reports","persona_mark_inquiry_for_review","persona_print_inquiry_pdf","persona_redact_account","persona_redact_inquiry","persona_resume_inquiry","persona_update_account","persona_update_inquiry","pinecone_delete_vectors","pinecone_describe_index","pinecone_describe_index_stats","pinecone_fetch","pinecone_generate_embeddings","pinecone_list_indexes","pinecone_list_vector_ids","pinecone_search_text","pinecone_search_vector","pinecone_update_vector","pinecone_upsert_text","pipedrive_create_activity","pipedrive_create_deal","pipedrive_create_lead","pipedrive_create_project","pipedrive_delete_lead","pipedrive_get_activities","pipedrive_get_all_deals","pipedrive_get_deal","pipedrive_get_files","pipedrive_get_leads","pipedrive_get_mail_messages","pipedrive_get_mail_thread","pipedrive_get_pipeline_deals","pipedrive_get_pipelines","pipedrive_get_projects","pipedrive_update_activity","pipedrive_update_deal","pipedrive_update_lead","pitchbook_company_active_investors","pitchbook_company_bio","pitchbook_company_deal_service_providers","pitchbook_company_deals","pitchbook_company_financials","pitchbook_company_general_service_providers","pitchbook_company_industries","pitchbook_company_investors","pitchbook_company_most_recent_debt_financing","pitchbook_company_most_recent_financials","pitchbook_company_most_recent_financing","pitchbook_company_search","pitchbook_company_similar_companies","pitchbook_company_social_analytics","pitchbook_company_updates","pitchbook_company_vc_exit_predictions","pitchbook_contracts_history","pitchbook_cost_of_calls","pitchbook_credit_history","pitchbook_credit_news","pitchbook_credit_news_bulk","pitchbook_credit_news_most_recent","pitchbook_credit_news_search","pitchbook_deal_bio","pitchbook_deal_cap_table_history","pitchbook_deal_debt_lenders","pitchbook_deal_detailed","pitchbook_deal_investors","pitchbook_deal_multiples","pitchbook_deal_search","pitchbook_deal_service_providers","pitchbook_deal_stock_info","pitchbook_deal_tranche_info","pitchbook_deal_updates","pitchbook_deal_valuation","pitchbook_entity_affiliates","pitchbook_entity_locations","pitchbook_entity_news","pitchbook_entity_people","pitchbook_entity_updates","pitchbook_fund_active_investments","pitchbook_fund_benchmark","pitchbook_fund_bio","pitchbook_fund_cash_flows","pitchbook_fund_commitments","pitchbook_fund_investment_preferences","pitchbook_fund_investments","pitchbook_fund_performance","pitchbook_fund_search","pitchbook_fund_team","pitchbook_fund_updates","pitchbook_investor_active_investments","pitchbook_investor_bio","pitchbook_investor_board_seats","pitchbook_investor_deal_service_providers","pitchbook_investor_funds","pitchbook_investor_general_service_providers","pitchbook_investor_investments","pitchbook_investor_last_closed_fund","pitchbook_investor_preferences","pitchbook_investor_search","pitchbook_investor_updates","pitchbook_limited_partner_actual_allocations","pitchbook_limited_partner_bio","pitchbook_limited_partner_commitment_aggregates","pitchbook_limited_partner_commitment_preferences","pitchbook_limited_partner_commitments_detailed","pitchbook_limited_partner_search","pitchbook_limited_partner_service_providers","pitchbook_limited_partner_target_allocations","pitchbook_limited_partner_updates","pitchbook_lookup_table_structure","pitchbook_lookup_tables","pitchbook_patent_detailed","pitchbook_patent_search","pitchbook_people_search","pitchbook_person_bio","pitchbook_person_contact","pitchbook_person_education_work","pitchbook_sandbox_entities","pitchbook_search","pitchbook_service_provider_bio","pitchbook_service_provider_search","pitchbook_service_provider_updates","pitchbook_serviced_companies","pitchbook_serviced_deals","pitchbook_serviced_funds","pitchbook_serviced_investors","pitchbook_serviced_limited_partners","pitchbook_shared_search","pitchbook_usage_report","plane_archive_project","plane_archive_work_item","plane_confirm_attachment_upload","plane_create_attachment_upload","plane_create_comment","plane_create_cycle","plane_create_label","plane_create_link","plane_create_module","plane_create_project","plane_create_project_page","plane_create_state","plane_create_webhook","plane_create_work_item","plane_delete_attachment","plane_delete_comment","plane_delete_cycle","plane_delete_label","plane_delete_link","plane_delete_module","plane_delete_project","plane_delete_project_page","plane_delete_state","plane_delete_webhook","plane_delete_work_item","plane_get_attachment","plane_get_comment","plane_get_current_user","plane_get_cycle","plane_get_label","plane_get_link","plane_get_module","plane_get_project","plane_get_project_page","plane_get_project_summary","plane_get_state","plane_get_webhook","plane_get_work_item","plane_get_work_item_by_identifier","plane_list_attachments","plane_list_comments","plane_list_cycles","plane_list_labels","plane_list_links","plane_list_modules","plane_list_project_pages","plane_list_projects","plane_list_states","plane_list_webhooks","plane_list_work_items","plane_list_workspace_work_items","plane_manage_cycle_work_items","plane_manage_module_work_items","plane_regenerate_webhook_secret","plane_transfer_cycle_work_items","plane_unarchive_project","plane_unarchive_work_item","plane_update_comment","plane_update_cycle","plane_update_label","plane_update_link","plane_update_module","plane_update_project","plane_update_project_page","plane_update_state","plane_update_webhook","plane_update_work_item","planetscale_close_deploy_request","planetscale_create_backup","planetscale_create_branch","planetscale_create_deploy_request","planetscale_delete_branch","planetscale_get_backup","planetscale_get_branch","planetscale_get_database","planetscale_get_deploy_request","planetscale_list_backups","planetscale_list_branches","planetscale_list_databases","planetscale_list_deploy_requests","planetscale_queue_deploy_request","planetscale_review_deploy_request","polymarket_get_activity","polymarket_get_event","polymarket_get_events","polymarket_get_holders","polymarket_get_last_trade_price","polymarket_get_leaderboard","polymarket_get_market","polymarket_get_markets","polymarket_get_midpoint","polymarket_get_orderbook","polymarket_get_positions","polymarket_get_price","polymarket_get_price_history","polymarket_get_series","polymarket_get_series_by_id","polymarket_get_spread","polymarket_get_tags","polymarket_get_tick_size","polymarket_get_trades","polymarket_search","postgresql_delete","postgresql_execute","postgresql_insert","postgresql_introspect","postgresql_query","postgresql_update","posthog_batch_events","posthog_capture_event","posthog_create_annotation","posthog_create_cohort","posthog_create_dashboard","posthog_create_experiment","posthog_create_feature_flag","posthog_create_insight","posthog_create_survey","posthog_delete_feature_flag","posthog_delete_person","posthog_delete_survey","posthog_evaluate_flags","posthog_get_cohort","posthog_get_dashboard","posthog_get_event_definition","posthog_get_experiment","posthog_get_feature_flag","posthog_get_insight","posthog_get_organization","posthog_get_person","posthog_get_project","posthog_get_property_definition","posthog_get_session_recording","posthog_get_survey","posthog_list_actions","posthog_list_annotations","posthog_list_cohorts","posthog_list_dashboards","posthog_list_event_definitions","posthog_list_experiments","posthog_list_feature_flags","posthog_list_insights","posthog_list_organizations","posthog_list_persons","posthog_list_projects","posthog_list_property_definitions","posthog_list_recording_playlists","posthog_list_session_recordings","posthog_list_surveys","posthog_query","posthog_update_cohort","posthog_update_event_definition","posthog_update_experiment","posthog_update_feature_flag","posthog_update_insight","posthog_update_property_definition","posthog_update_survey","powerbi_execute_query","powerbi_get_dataset","powerbi_get_refresh_history","powerbi_get_report","powerbi_list_datasets","powerbi_list_reports","powerbi_list_workspaces","powerbi_refresh_dataset","profound_bot_logs","profound_bots_report","profound_category_assets","profound_category_personas","profound_category_prompts","profound_category_tags","profound_category_topics","profound_citation_prompts","profound_citations_report","profound_list_assets","profound_list_categories","profound_list_domains","profound_list_models","profound_list_optimizations","profound_list_personas","profound_list_regions","profound_optimization_analysis","profound_prompt_answers","profound_prompt_volume","profound_query_fanouts","profound_raw_logs","profound_referrals_report","profound_sentiment_report","profound_visibility_report","prospeo_account_information","prospeo_bulk_enrich_company","prospeo_bulk_enrich_person","prospeo_enrich_company","prospeo_enrich_person","prospeo_search_company","prospeo_search_person","prospeo_search_suggestions","pulse_parser","pulse_parser_v2","qdrant_fetch_points","qdrant_search_vector","qdrant_upsert_points","quartr_get_audio","quartr_get_company","quartr_get_event","quartr_get_event_summary","quartr_get_report","quartr_get_slide_deck","quartr_get_transcript","quartr_list_audio","quartr_list_companies","quartr_list_document_types","quartr_list_documents","quartr_list_event_types","quartr_list_events","quartr_list_live_events","quartr_list_reports","quartr_list_slide_decks","quartr_list_transcripts","quickbooks_add_attachment","quickbooks_create_bill","quickbooks_create_bill_payment","quickbooks_create_credit_memo","quickbooks_create_customer","quickbooks_create_customer_payment","quickbooks_create_deposit","quickbooks_create_employee","quickbooks_create_estimate","quickbooks_create_invoice","quickbooks_create_item","quickbooks_create_journal_entry","quickbooks_create_purchase","quickbooks_create_purchase_order","quickbooks_create_refund_receipt","quickbooks_create_sales_receipt","quickbooks_create_vendor","quickbooks_create_vendor_credit","quickbooks_download_attachment","quickbooks_download_transaction_pdf","quickbooks_email_transaction","quickbooks_get_company_info","quickbooks_read_accounting_transactions","quickbooks_read_attachments","quickbooks_read_master_data","quickbooks_read_purchasing_transactions","quickbooks_read_sales_transactions","quickbooks_run_financial_report","quickbooks_update_bill","quickbooks_update_bill_payment","quickbooks_update_credit_memo","quickbooks_update_customer","quickbooks_update_customer_payment","quickbooks_update_deposit","quickbooks_update_employee","quickbooks_update_estimate","quickbooks_update_invoice","quickbooks_update_item","quickbooks_update_journal_entry","quickbooks_update_purchase","quickbooks_update_purchase_order","quickbooks_update_refund_receipt","quickbooks_update_sales_receipt","quickbooks_update_vendor","quickbooks_update_vendor_credit","quickbooks_void_bill_payment","quickbooks_void_customer_payment","quickbooks_void_invoice","quickbooks_void_sales_receipt","quiver_image_to_svg","quiver_image_to_svg_v2","quiver_list_models","quiver_text_to_svg","quiver_text_to_svg_v2","rabbitmq_create_binding","rabbitmq_create_exchange","rabbitmq_create_policy","rabbitmq_create_queue","rabbitmq_delete_binding","rabbitmq_delete_exchange","rabbitmq_delete_policy","rabbitmq_delete_queue","rabbitmq_get_exchange","rabbitmq_get_messages","rabbitmq_get_overview","rabbitmq_get_queue","rabbitmq_health_check","rabbitmq_list_bindings","rabbitmq_list_channels","rabbitmq_list_connections","rabbitmq_list_consumers","rabbitmq_list_exchange_bindings","rabbitmq_list_exchanges","rabbitmq_list_nodes","rabbitmq_list_policies","rabbitmq_list_queues","rabbitmq_list_vhosts","rabbitmq_publish_message","rabbitmq_purge_queue","railway_create_environment","railway_create_project","railway_create_service","railway_delete_environment","railway_delete_project","railway_delete_service","railway_delete_variable","railway_deploy_service","railway_get_deployment","railway_get_deployment_logs","railway_get_project","railway_list_deployments","railway_list_project_members","railway_list_projects","railway_list_variables","railway_restart_deployment","railway_rollback_deployment","railway_transfer_project","railway_update_project","railway_upsert_variable","ramp_create_memo","ramp_get_balance","ramp_get_bill","ramp_get_business","ramp_get_memo","ramp_get_physical_card","ramp_get_reimbursement","ramp_get_transaction","ramp_get_user","ramp_get_vendor","ramp_get_virtual_card","ramp_list_bills","ramp_list_physical_cards","ramp_list_reimbursements","ramp_list_transactions","ramp_list_users","ramp_list_vendors","ramp_list_virtual_cards","rb2b_credit_check","rb2b_email_to_activity","rb2b_hem_to_best_linkedin","rb2b_hem_to_business_profile","rb2b_hem_to_linkedin","rb2b_hem_to_maid","rb2b_ip_to_company","rb2b_ip_to_hem","rb2b_ip_to_maid","rb2b_linkedin_slug_search","rb2b_linkedin_to_best_personal_email","rb2b_linkedin_to_business_profile","rb2b_linkedin_to_hashed_emails","rb2b_linkedin_to_mobile_phone","rb2b_linkedin_to_personal_email","rds_delete","rds_execute","rds_insert","rds_introspect","rds_query","rds_update","reddit_delete","reddit_edit","reddit_get_comments","reddit_get_controversial","reddit_get_info","reddit_get_me","reddit_get_messages","reddit_get_posts","reddit_get_saved","reddit_get_subreddit_info","reddit_get_subreddit_rules","reddit_get_user","reddit_get_user_comments","reddit_get_user_posts","reddit_hide","reddit_hot_posts","reddit_list_my_subreddits","reddit_lock","reddit_mark_all_read","reddit_mark_read","reddit_marknsfw","reddit_mod_approve","reddit_mod_distinguish","reddit_mod_remove","reddit_mod_sticky","reddit_reply","reddit_report","reddit_save","reddit_search","reddit_search_subreddits","reddit_send_message","reddit_submit_post","reddit_subscribe","reddit_unhide","reddit_unlock","reddit_unmarknsfw","reddit_unsave","reddit_vote","redis_command","redis_delete","redis_exists","redis_expire","redis_get","redis_hdel","redis_hget","redis_hgetall","redis_hset","redis_incr","redis_incrby","redis_keys","redis_llen","redis_lpop","redis_lpush","redis_lrange","redis_persist","redis_rpop","redis_rpush","redis_set","redis_setnx","redis_ttl","reducto_parser","reducto_parser_v2","resend_cancel_email","resend_create_audience","resend_create_broadcast","resend_create_contact","resend_delete_audience","resend_delete_contact","resend_get_audience","resend_get_broadcast","resend_get_contact","resend_get_email","resend_list_audiences","resend_list_contacts","resend_list_domains","resend_send","resend_send_broadcast","resend_update_contact","revenuecat_create_purchase","revenuecat_defer_google_subscription","revenuecat_delete_customer","revenuecat_get_customer","revenuecat_grant_entitlement","revenuecat_list_offerings","revenuecat_refund_google_subscription","revenuecat_revoke_entitlement","revenuecat_revoke_google_subscription","revenuecat_update_subscriber_attributes","rippling_bulk_create_custom_object_records","rippling_bulk_delete_custom_object_records","rippling_bulk_update_custom_object_records","rippling_create_business_partner","rippling_create_business_partner_group","rippling_create_custom_app","rippling_create_custom_object","rippling_create_custom_object_field","rippling_create_custom_object_record","rippling_create_custom_page","rippling_create_custom_setting","rippling_create_department","rippling_create_draft_hires","rippling_create_object_category","rippling_create_title","rippling_create_work_location","rippling_delete_business_partner","rippling_delete_business_partner_group","rippling_delete_custom_app","rippling_delete_custom_object","rippling_delete_custom_object_field","rippling_delete_custom_object_record","rippling_delete_custom_page","rippling_delete_custom_setting","rippling_delete_object_category","rippling_delete_title","rippling_delete_work_location","rippling_get_business_partner","rippling_get_business_partner_group","rippling_get_current_user","rippling_get_custom_app","rippling_get_custom_object","rippling_get_custom_object_field","rippling_get_custom_object_record","rippling_get_custom_object_record_by_external_id","rippling_get_custom_page","rippling_get_custom_setting","rippling_get_department","rippling_get_employment_type","rippling_get_job_function","rippling_get_object_category","rippling_get_report_run","rippling_get_supergroup","rippling_get_team","rippling_get_title","rippling_get_user","rippling_get_work_location","rippling_get_worker","rippling_list_business_partner_groups","rippling_list_business_partners","rippling_list_companies","rippling_list_custom_apps","rippling_list_custom_fields","rippling_list_custom_object_fields","rippling_list_custom_object_records","rippling_list_custom_objects","rippling_list_custom_pages","rippling_list_custom_settings","rippling_list_departments","rippling_list_employment_types","rippling_list_entitlements","rippling_list_job_functions","rippling_list_object_categories","rippling_list_supergroup_exclusion_members","rippling_list_supergroup_inclusion_members","rippling_list_supergroup_members","rippling_list_supergroups","rippling_list_teams","rippling_list_titles","rippling_list_users","rippling_list_work_locations","rippling_list_workers","rippling_query_custom_object_records","rippling_trigger_report_run","rippling_update_custom_app","rippling_update_custom_object","rippling_update_custom_object_field","rippling_update_custom_object_record","rippling_update_custom_page","rippling_update_custom_setting","rippling_update_department","rippling_update_object_category","rippling_update_supergroup_exclusion_members","rippling_update_supergroup_inclusion_members","rippling_update_title","rippling_update_work_location","rocketlane_add_field_option","rocketlane_add_project_members","rocketlane_add_task_assignees","rocketlane_add_task_dependencies","rocketlane_add_task_followers","rocketlane_archive_project","rocketlane_assign_placeholders","rocketlane_create_field","rocketlane_create_phase","rocketlane_create_project","rocketlane_create_space","rocketlane_create_space_document","rocketlane_create_task","rocketlane_create_time_entry","rocketlane_create_time_off","rocketlane_delete_field","rocketlane_delete_phase","rocketlane_delete_project","rocketlane_delete_space","rocketlane_delete_space_document","rocketlane_delete_task","rocketlane_delete_time_entry","rocketlane_delete_time_off","rocketlane_get_field","rocketlane_get_invoice","rocketlane_get_invoice_line_items","rocketlane_get_invoice_payments","rocketlane_get_phase","rocketlane_get_project","rocketlane_get_space","rocketlane_get_space_document","rocketlane_get_task","rocketlane_get_time_entry","rocketlane_get_time_off","rocketlane_get_user","rocketlane_import_template","rocketlane_list_fields","rocketlane_list_invoices","rocketlane_list_phases","rocketlane_list_placeholders","rocketlane_list_projects","rocketlane_list_resource_allocations","rocketlane_list_space_documents","rocketlane_list_spaces","rocketlane_list_tasks","rocketlane_list_time_entries","rocketlane_list_time_entry_categories","rocketlane_list_time_offs","rocketlane_list_users","rocketlane_move_task_to_phase","rocketlane_remove_project_members","rocketlane_remove_task_assignees","rocketlane_remove_task_dependencies","rocketlane_remove_task_followers","rocketlane_search_time_entries","rocketlane_unassign_placeholders","rocketlane_update_field","rocketlane_update_field_option","rocketlane_update_phase","rocketlane_update_project","rocketlane_update_space","rocketlane_update_space_document","rocketlane_update_task","rocketlane_update_time_entry","rootly_acknowledge_alert","rootly_add_incident_event","rootly_add_subscribers","rootly_assign_incident_role","rootly_create_action_item","rootly_create_alert","rootly_create_incident","rootly_create_status_page_event","rootly_delete_action_item","rootly_delete_incident","rootly_escalate_alert","rootly_get_alert","rootly_get_incident","rootly_list_action_items","rootly_list_alerts","rootly_list_causes","rootly_list_environments","rootly_list_escalation_policies","rootly_list_functionalities","rootly_list_incident_events","rootly_list_incident_roles","rootly_list_incident_types","rootly_list_incidents","rootly_list_on_calls","rootly_list_playbooks","rootly_list_retrospectives","rootly_list_schedules","rootly_list_services","rootly_list_severities","rootly_list_teams","rootly_list_users","rootly_mitigate_incident","rootly_remove_subscribers","rootly_resolve_alert","rootly_resolve_incident","rootly_run_workflow","rootly_snooze_alert","rootly_unassign_incident_role","rootly_update_action_item","rootly_update_alert","rootly_update_incident","s3_copy_object","s3_create_bucket","s3_delete_bucket","s3_delete_object","s3_delete_objects","s3_get_object","s3_head_object","s3_list_buckets","s3_list_objects","s3_presigned_url","s3_put_object","sailpoint_approve_access_request","sailpoint_cancel_access_request","sailpoint_decide_certification_review_items","sailpoint_get_access_profile","sailpoint_get_access_profile_entitlements","sailpoint_get_access_request_config","sailpoint_get_access_request_status","sailpoint_get_account","sailpoint_get_account_activity","sailpoint_get_account_entitlements","sailpoint_get_account_selections","sailpoint_get_campaign","sailpoint_get_certification","sailpoint_get_entitlement","sailpoint_get_entitlement_request_config","sailpoint_get_identity","sailpoint_get_role","sailpoint_get_role_entitlements","sailpoint_get_source","sailpoint_get_task_status","sailpoint_list_access_profiles","sailpoint_list_account_activities","sailpoint_list_accounts","sailpoint_list_campaigns","sailpoint_list_certification_review_items","sailpoint_list_certifications","sailpoint_list_entitlements","sailpoint_list_identities","sailpoint_list_identity_entitlements","sailpoint_list_pending_access_request_approvals","sailpoint_list_roles","sailpoint_list_sources","sailpoint_load_accounts","sailpoint_load_entitlements","sailpoint_reject_access_request","sailpoint_request_access","sailpoint_search","sailpoint_search_aggregate","sailpoint_search_count","sailpoint_sign_off_certification","salesforce_create_account","salesforce_create_case","salesforce_create_contact","salesforce_create_custom_field","salesforce_create_custom_object","salesforce_create_lead","salesforce_create_opportunity","salesforce_create_task","salesforce_delete_account","salesforce_delete_case","salesforce_delete_contact","salesforce_delete_custom_field","salesforce_delete_lead","salesforce_delete_opportunity","salesforce_delete_task","salesforce_describe_object","salesforce_get_accounts","salesforce_get_cases","salesforce_get_contacts","salesforce_get_dashboard","salesforce_get_leads","salesforce_get_opportunities","salesforce_get_report","salesforce_get_tasks","salesforce_list_dashboards","salesforce_list_objects","salesforce_list_report_types","salesforce_list_reports","salesforce_query","salesforce_query_more","salesforce_refresh_dashboard","salesforce_run_report","salesforce_tooling_query","salesforce_update_account","salesforce_update_case","salesforce_update_contact","salesforce_update_custom_field","salesforce_update_lead","salesforce_update_opportunity","salesforce_update_task","sap_concur_approve_expense_report","sap_concur_associate_attendees","sap_concur_create_cash_advance","sap_concur_create_expected_expense","sap_concur_create_expense_report","sap_concur_create_list_item","sap_concur_create_purchase_request","sap_concur_create_quick_expense","sap_concur_create_quick_expense_with_image","sap_concur_create_report_comment","sap_concur_create_travel_request","sap_concur_create_user","sap_concur_delete_expected_expense","sap_concur_delete_expense","sap_concur_delete_expense_report","sap_concur_delete_list_item","sap_concur_delete_travel_request","sap_concur_delete_user","sap_concur_get_allocation","sap_concur_get_budget","sap_concur_get_cash_advance","sap_concur_get_expected_expense","sap_concur_get_expense","sap_concur_get_expense_report","sap_concur_get_itemizations","sap_concur_get_itinerary","sap_concur_get_list","sap_concur_get_list_item","sap_concur_get_purchase_request","sap_concur_get_receipt","sap_concur_get_receipt_status","sap_concur_get_request_cash_advance","sap_concur_get_travel_profile","sap_concur_get_travel_request","sap_concur_get_user","sap_concur_issue_cash_advance","sap_concur_list_allocations","sap_concur_list_attendee_associations","sap_concur_list_budget_categories","sap_concur_list_budgets","sap_concur_list_exceptions","sap_concur_list_expected_expenses","sap_concur_list_expense_reports","sap_concur_list_expenses","sap_concur_list_itineraries","sap_concur_list_list_items","sap_concur_list_lists","sap_concur_list_receipts","sap_concur_list_report_comments","sap_concur_list_reports_to_approve","sap_concur_list_travel_profiles_summary","sap_concur_list_travel_request_comments","sap_concur_list_travel_requests","sap_concur_list_users","sap_concur_move_travel_request","sap_concur_recall_expense_report","sap_concur_remove_all_attendees","sap_concur_search_locations","sap_concur_search_users","sap_concur_send_back_expense_report","sap_concur_submit_expense_report","sap_concur_update_allocation","sap_concur_update_expected_expense","sap_concur_update_expense","sap_concur_update_expense_report","sap_concur_update_list_item","sap_concur_update_travel_request","sap_concur_update_user","sap_concur_upload_exchange_rates","sap_concur_upload_receipt_image","sap_s4hana_create_business_partner","sap_s4hana_create_purchase_order","sap_s4hana_create_purchase_requisition","sap_s4hana_create_sales_order","sap_s4hana_delete_sales_order","sap_s4hana_get_billing_document","sap_s4hana_get_business_partner","sap_s4hana_get_customer","sap_s4hana_get_inbound_delivery","sap_s4hana_get_material_document","sap_s4hana_get_outbound_delivery","sap_s4hana_get_product","sap_s4hana_get_purchase_order","sap_s4hana_get_purchase_requisition","sap_s4hana_get_sales_order","sap_s4hana_get_supplier","sap_s4hana_get_supplier_invoice","sap_s4hana_list_billing_documents","sap_s4hana_list_business_partners","sap_s4hana_list_customers","sap_s4hana_list_inbound_deliveries","sap_s4hana_list_material_documents","sap_s4hana_list_material_stock","sap_s4hana_list_outbound_deliveries","sap_s4hana_list_products","sap_s4hana_list_purchase_orders","sap_s4hana_list_purchase_requisitions","sap_s4hana_list_sales_orders","sap_s4hana_list_supplier_invoices","sap_s4hana_list_suppliers","sap_s4hana_odata_query","sap_s4hana_update_business_partner","sap_s4hana_update_customer","sap_s4hana_update_product","sap_s4hana_update_purchase_order","sap_s4hana_update_purchase_requisition","sap_s4hana_update_sales_order","sap_s4hana_update_supplier","search_tool","secrets_manager_create_secret","secrets_manager_delete_secret","secrets_manager_describe_secret","secrets_manager_get_secret","secrets_manager_list_secrets","secrets_manager_restore_secret","secrets_manager_rotate_secret","secrets_manager_tag_resource","secrets_manager_untag_resource","secrets_manager_update_secret","semrush_backlinks","semrush_backlinks_anchors","semrush_backlinks_competitors","semrush_backlinks_geo_distribution","semrush_backlinks_indexed_pages","semrush_backlinks_overview","semrush_backlinks_tld_distribution","semrush_batch_keyword_overview","semrush_broad_match_keywords","semrush_domain_ad_copies","semrush_domain_ad_history","semrush_domain_organic_competitors","semrush_domain_organic_keywords","semrush_domain_overview","semrush_domain_overview_all","semrush_domain_overview_history","semrush_domain_paid_competitors","semrush_domain_paid_keywords","semrush_domain_pla_copies","semrush_domain_pla_keywords","semrush_domain_vs_domain","semrush_keyword_ad_history","semrush_keyword_difficulty","semrush_keyword_overview","semrush_keyword_overview_all","semrush_keyword_questions","semrush_organic_results","semrush_paid_results","semrush_referring_domains","semrush_referring_ips","semrush_related_keywords","semrush_subdomain_ad_copies","semrush_subdomain_organic_keywords","semrush_subdomain_overview","semrush_subdomain_overview_all","semrush_subdomain_overview_history","semrush_subdomain_paid_keywords","semrush_top_domains","semrush_url_organic_keywords","semrush_url_overview","semrush_url_overview_all","semrush_url_overview_history","semrush_url_paid_keywords","semrush_winners_and_losers","sendblue_evaluate_service","sendblue_get_message","sendblue_send_group_message","sendblue_send_message","sendblue_send_typing_indicator","sendgrid_add_contact","sendgrid_add_contacts_to_list","sendgrid_create_list","sendgrid_create_template","sendgrid_create_template_version","sendgrid_delete_contacts","sendgrid_delete_list","sendgrid_delete_template","sendgrid_get_contact","sendgrid_get_list","sendgrid_get_template","sendgrid_list_all_lists","sendgrid_list_templates","sendgrid_remove_contacts_from_list","sendgrid_search_contacts","sendgrid_send_mail","sentry_events_get","sentry_events_list","sentry_issues_get","sentry_issues_list","sentry_issues_update","sentry_projects_create","sentry_projects_get","sentry_projects_list","sentry_projects_update","sentry_releases_create","sentry_releases_deploy","sentry_releases_list","sentry_teams_list","serper_search","servicenow_add_incident_comment","servicenow_aggregate","servicenow_close_incident","servicenow_create_change_request","servicenow_create_incident","servicenow_create_record","servicenow_delete_record","servicenow_download_attachment","servicenow_download_attachment_v2","servicenow_find_user","servicenow_get_change_next_states","servicenow_get_change_request","servicenow_get_ci","servicenow_get_incident","servicenow_get_knowledge_article","servicenow_get_requested_item","servicenow_list_approvals","servicenow_list_attachments","servicenow_list_catalog_items","servicenow_list_change_requests","servicenow_list_change_tasks","servicenow_list_ci_relationships","servicenow_list_group_members","servicenow_list_incidents","servicenow_list_requested_items","servicenow_order_catalog_item","servicenow_read_record","servicenow_resolve_incident","servicenow_search_cis","servicenow_search_knowledge","servicenow_update_approval","servicenow_update_change_request","servicenow_update_change_state","servicenow_update_incident","servicenow_update_record","servicenow_upload_attachment","ses_create_configuration_set","ses_create_email_identity","ses_create_template","ses_delete_email_identity","ses_delete_suppressed_destination","ses_delete_template","ses_get_account","ses_get_email_identity","ses_get_suppressed_destination","ses_get_template","ses_list_identities","ses_list_suppressed_destinations","ses_list_templates","ses_put_suppressed_destination","ses_send_bulk_email","ses_send_custom_verification_email","ses_send_email","ses_send_templated_email","ses_update_template","sftp_delete","sftp_download","sftp_download_v2","sftp_list","sftp_mkdir","sftp_upload","sharepoint_add_list_items","sharepoint_create_list","sharepoint_create_page","sharepoint_delete_file","sharepoint_delete_list_item","sharepoint_delete_page","sharepoint_download_file","sharepoint_get_drive_item","sharepoint_get_list","sharepoint_get_list_item","sharepoint_list_sites","sharepoint_publish_page","sharepoint_read_page","sharepoint_update_list","sharepoint_update_page","sharepoint_upload_file","shopify_adjust_inventory","shopify_cancel_order","shopify_create_customer","shopify_create_fulfillment","shopify_create_product","shopify_create_product_variants","shopify_delete_customer","shopify_delete_product","shopify_get_collection","shopify_get_customer","shopify_get_fulfillment","shopify_get_fulfillment_order","shopify_get_inventory_level","shopify_get_job","shopify_get_order","shopify_get_product","shopify_list_collections","shopify_list_customers","shopify_list_fulfillment_orders","shopify_list_inventory_items","shopify_list_locations","shopify_list_orders","shopify_list_products","shopify_update_customer","shopify_update_fulfillment_tracking","shopify_update_order","shopify_update_product","shopify_update_product_variants","similarweb_bounce_rate","similarweb_page_views","similarweb_pages_per_visit","similarweb_traffic_visits","similarweb_visit_duration","similarweb_website_overview","sixtyfour_enrich_company","sixtyfour_enrich_lead","sixtyfour_find_email","sixtyfour_find_phone","slack_add_bookmark","slack_add_reaction","slack_archive_conversation","slack_canvas","slack_close_conversation","slack_create_channel_canvas","slack_create_conversation","slack_create_user_group","slack_delete_canvas","slack_delete_file","slack_delete_message","slack_delete_scheduled_message","slack_disable_user_group","slack_download","slack_edit_bookmark","slack_edit_canvas","slack_enable_user_group","slack_ephemeral_message","slack_get_canvas","slack_get_channel_history","slack_get_channel_info","slack_get_dnd_info","slack_get_file_info","slack_get_message","slack_get_permalink","slack_get_reactions","slack_get_team_dnd_info","slack_get_team_info","slack_get_team_profile","slack_get_thread","slack_get_thread_replies","slack_get_user","slack_get_user_presence","slack_get_user_profile","slack_invite_to_conversation","slack_join_conversation","slack_kick_conversation","slack_leave_conversation","slack_list_bookmarks","slack_list_canvases","slack_list_channels","slack_list_emoji","slack_list_files","slack_list_members","slack_list_pins","slack_list_reactions","slack_list_scheduled_messages","slack_list_user_conversations","slack_list_user_group_members","slack_list_user_groups","slack_list_users","slack_lists_access_delete","slack_lists_access_set","slack_lists_create","slack_lists_download_get","slack_lists_download_start","slack_lists_items_create","slack_lists_items_delete","slack_lists_items_delete_multiple","slack_lists_items_info","slack_lists_items_list","slack_lists_items_update","slack_lists_update","slack_lookup_canvas_sections","slack_lookup_user_by_email","slack_mark_conversation_read","slack_message","slack_message_reader","slack_open_conversation","slack_open_view","slack_pin_message","slack_publish_view","slack_push_view","slack_remove_bookmark","slack_remove_reaction","slack_rename_agent_session_v2","slack_rename_conversation","slack_revoke_canvas_access","slack_schedule_message","slack_set_agent_session_status_v2","slack_set_conversation_purpose","slack_set_conversation_topic","slack_set_status","slack_set_suggested_prompts","slack_set_suggested_prompts_v2","slack_set_title","slack_set_user_presence","slack_share_canvas","slack_unarchive_conversation","slack_unfurl_links","slack_unpin_message","slack_update_message","slack_update_user_group","slack_update_user_group_members","slack_update_view","smartlead_add_email_accounts_to_campaign","smartlead_add_leads_to_campaign","smartlead_create_campaign","smartlead_create_lead_list","smartlead_delete_campaign","smartlead_delete_campaign_webhook","smartlead_delete_lead_from_campaign","smartlead_delete_lead_list","smartlead_duplicate_campaign","smartlead_export_campaign_leads","smartlead_get_campaign","smartlead_get_campaign_analytics","smartlead_get_campaign_analytics_by_date","smartlead_get_campaign_lead_statistics","smartlead_get_campaign_mailbox_statistics","smartlead_get_campaign_sequences","smartlead_get_campaign_statistics","smartlead_get_campaign_top_level_analytics_by_date","smartlead_get_campaign_webhook_summary","smartlead_get_lead_by_email","smartlead_get_lead_by_id","smartlead_get_lead_list","smartlead_get_lead_message_history","smartlead_list_campaign_email_accounts","smartlead_list_campaign_leads","smartlead_list_campaign_webhooks","smartlead_list_campaigns","smartlead_list_clients","smartlead_list_email_accounts","smartlead_list_inbox_replies","smartlead_list_lead_activities","smartlead_list_lead_categories","smartlead_list_lead_lists","smartlead_mark_lead_complete","smartlead_pause_lead","smartlead_remove_email_accounts_from_campaign","smartlead_resume_lead","smartlead_save_campaign_sequences","smartlead_unsubscribe_lead_from_campaign","smartlead_unsubscribe_lead_globally","smartlead_update_campaign_schedule","smartlead_update_campaign_settings","smartlead_update_campaign_status","smartlead_update_lead","smartlead_update_lead_category","smartlead_update_lead_list","smartlead_upsert_campaign_webhook","sms_send","smtp_send_mail","snowflake_alter_warehouse","snowflake_call_procedure","snowflake_cancel_statement","snowflake_cancel_task_run","snowflake_cortex_analyst_ask","snowflake_cortex_analyst_feedback","snowflake_delete_rows","snowflake_execute_sql","snowflake_get_statement","snowflake_get_task","snowflake_get_task_run","snowflake_get_task_run_output","snowflake_get_warehouse","snowflake_insert_rows","snowflake_introspect_schema","snowflake_list_copy_history","snowflake_list_databases","snowflake_list_query_history","snowflake_list_schemas","snowflake_list_tables","snowflake_list_task_runs","snowflake_list_tasks","snowflake_list_warehouses","snowflake_load_data","snowflake_resume_task","snowflake_resume_warehouse","snowflake_run_task","snowflake_suspend_task","snowflake_suspend_warehouse","snowflake_unload_data","snowflake_update_rows","snowflake_upsert_rows","splunk_cancel_search_job","splunk_create_search_job","splunk_dispatch_saved_search","splunk_get_fired_alerts","splunk_get_saved_search","splunk_get_search_job","splunk_get_search_results","splunk_list_apps","splunk_list_fired_alerts","splunk_list_indexes","splunk_list_saved_searches","splunk_run_search","sportmonks_core_get_cities","sportmonks_core_get_city","sportmonks_core_get_continent","sportmonks_core_get_continents","sportmonks_core_get_countries","sportmonks_core_get_country","sportmonks_core_get_entity_filters","sportmonks_core_get_my_usage","sportmonks_core_get_region","sportmonks_core_get_regions","sportmonks_core_get_timezones","sportmonks_core_get_type","sportmonks_core_get_type_by_entity","sportmonks_core_get_types","sportmonks_core_search_cities","sportmonks_core_search_countries","sportmonks_core_search_regions","sportmonks_football_expected_by_player","sportmonks_football_expected_by_team","sportmonks_football_get_all_commentaries","sportmonks_football_get_all_fixtures","sportmonks_football_get_all_players","sportmonks_football_get_all_rivals","sportmonks_football_get_all_teams","sportmonks_football_get_all_transfer_rumours","sportmonks_football_get_all_transfers","sportmonks_football_get_brackets_by_season","sportmonks_football_get_coach","sportmonks_football_get_coaches","sportmonks_football_get_coaches_by_country","sportmonks_football_get_commentaries_by_fixture","sportmonks_football_get_current_leagues_by_team","sportmonks_football_get_expected_lineups_by_player","sportmonks_football_get_expected_lineups_by_team","sportmonks_football_get_extended_team_squad","sportmonks_football_get_fixture","sportmonks_football_get_fixtures_by_date","sportmonks_football_get_fixtures_by_date_range","sportmonks_football_get_fixtures_by_date_range_for_team","sportmonks_football_get_fixtures_by_ids","sportmonks_football_get_grouped_standings_by_round","sportmonks_football_get_head_to_head","sportmonks_football_get_inplay_livescores","sportmonks_football_get_latest_coaches","sportmonks_football_get_latest_fixtures","sportmonks_football_get_latest_livescores","sportmonks_football_get_latest_players","sportmonks_football_get_latest_totw","sportmonks_football_get_latest_transfers","sportmonks_football_get_league","sportmonks_football_get_leagues","sportmonks_football_get_leagues_by_country","sportmonks_football_get_leagues_by_date","sportmonks_football_get_leagues_by_team","sportmonks_football_get_live_leagues","sportmonks_football_get_live_probabilities","sportmonks_football_get_live_probabilities_by_fixture","sportmonks_football_get_live_standings_by_league","sportmonks_football_get_livescores","sportmonks_football_get_match_facts","sportmonks_football_get_match_facts_by_date_range","sportmonks_football_get_match_facts_by_fixture","sportmonks_football_get_match_facts_by_league","sportmonks_football_get_past_fixtures_by_tv_station","sportmonks_football_get_player","sportmonks_football_get_players_by_country","sportmonks_football_get_postmatch_news","sportmonks_football_get_postmatch_news_by_season","sportmonks_football_get_predictability_by_league","sportmonks_football_get_prematch_news","sportmonks_football_get_prematch_news_by_season","sportmonks_football_get_prematch_news_upcoming","sportmonks_football_get_probabilities","sportmonks_football_get_probabilities_by_fixture","sportmonks_football_get_referee","sportmonks_football_get_referees","sportmonks_football_get_referees_by_country","sportmonks_football_get_referees_by_season","sportmonks_football_get_rivals_by_team","sportmonks_football_get_round","sportmonks_football_get_round_statistics","sportmonks_football_get_rounds","sportmonks_football_get_rounds_by_season","sportmonks_football_get_schedules_by_season","sportmonks_football_get_schedules_by_season_and_team","sportmonks_football_get_schedules_by_team","sportmonks_football_get_season","sportmonks_football_get_seasons","sportmonks_football_get_seasons_by_team","sportmonks_football_get_stage","sportmonks_football_get_stage_statistics","sportmonks_football_get_stages","sportmonks_football_get_stages_by_season","sportmonks_football_get_standing_corrections_by_season","sportmonks_football_get_standings","sportmonks_football_get_standings_by_round","sportmonks_football_get_standings_by_season","sportmonks_football_get_state","sportmonks_football_get_states","sportmonks_football_get_team","sportmonks_football_get_team_rankings","sportmonks_football_get_team_rankings_by_date","sportmonks_football_get_team_rankings_by_team","sportmonks_football_get_team_squad","sportmonks_football_get_team_squad_by_season","sportmonks_football_get_teams_by_country","sportmonks_football_get_teams_by_season","sportmonks_football_get_topscorers_by_season","sportmonks_football_get_topscorers_by_stage","sportmonks_football_get_totw","sportmonks_football_get_totw_by_round","sportmonks_football_get_transfer","sportmonks_football_get_transfer_rumour","sportmonks_football_get_transfer_rumours_between_dates","sportmonks_football_get_transfer_rumours_by_player","sportmonks_football_get_transfer_rumours_by_team","sportmonks_football_get_transfers_between_dates","sportmonks_football_get_transfers_by_player","sportmonks_football_get_transfers_by_team","sportmonks_football_get_tv_station","sportmonks_football_get_tv_stations","sportmonks_football_get_tv_stations_by_fixture","sportmonks_football_get_upcoming_fixtures_by_market","sportmonks_football_get_upcoming_fixtures_by_tv_station","sportmonks_football_get_value_bets","sportmonks_football_get_value_bets_by_fixture","sportmonks_football_get_venue","sportmonks_football_get_venues","sportmonks_football_get_venues_by_season","sportmonks_football_search_coaches","sportmonks_football_search_fixtures","sportmonks_football_search_leagues","sportmonks_football_search_players","sportmonks_football_search_referees","sportmonks_football_search_rounds","sportmonks_football_search_seasons","sportmonks_football_search_stages","sportmonks_football_search_teams","sportmonks_football_search_venues","sportmonks_motorsport_get_all_fixtures","sportmonks_motorsport_get_current_leagues_by_team","sportmonks_motorsport_get_driver","sportmonks_motorsport_get_driver_standings","sportmonks_motorsport_get_driver_standings_by_season","sportmonks_motorsport_get_drivers","sportmonks_motorsport_get_drivers_by_country","sportmonks_motorsport_get_drivers_by_season","sportmonks_motorsport_get_fixture","sportmonks_motorsport_get_fixtures_by_date","sportmonks_motorsport_get_fixtures_by_date_range","sportmonks_motorsport_get_fixtures_by_ids","sportmonks_motorsport_get_laps_by_fixture","sportmonks_motorsport_get_laps_by_fixture_and_driver","sportmonks_motorsport_get_laps_by_fixture_and_lap","sportmonks_motorsport_get_latest_laps_by_fixture","sportmonks_motorsport_get_latest_pitstops_by_fixture","sportmonks_motorsport_get_latest_stints_by_fixture","sportmonks_motorsport_get_latest_updated_drivers","sportmonks_motorsport_get_latest_updated_fixtures","sportmonks_motorsport_get_league","sportmonks_motorsport_get_leagues","sportmonks_motorsport_get_leagues_by_country","sportmonks_motorsport_get_leagues_by_date","sportmonks_motorsport_get_leagues_by_live","sportmonks_motorsport_get_leagues_by_team","sportmonks_motorsport_get_livescores","sportmonks_motorsport_get_pitstops_by_fixture","sportmonks_motorsport_get_pitstops_by_fixture_and_driver","sportmonks_motorsport_get_pitstops_by_fixture_and_lap","sportmonks_motorsport_get_race_results_by_season_and_driver","sportmonks_motorsport_get_race_results_by_season_and_team","sportmonks_motorsport_get_schedules_by_season","sportmonks_motorsport_get_season","sportmonks_motorsport_get_seasons","sportmonks_motorsport_get_stage","sportmonks_motorsport_get_stages","sportmonks_motorsport_get_stages_by_season","sportmonks_motorsport_get_state","sportmonks_motorsport_get_states","sportmonks_motorsport_get_stints_by_fixture","sportmonks_motorsport_get_stints_by_fixture_and_driver","sportmonks_motorsport_get_stints_by_fixture_and_stint","sportmonks_motorsport_get_team","sportmonks_motorsport_get_team_standings","sportmonks_motorsport_get_team_standings_by_season","sportmonks_motorsport_get_teams","sportmonks_motorsport_get_teams_by_country","sportmonks_motorsport_get_teams_by_season","sportmonks_motorsport_get_venue","sportmonks_motorsport_get_venues","sportmonks_motorsport_get_venues_by_season","sportmonks_motorsport_search_drivers","sportmonks_motorsport_search_leagues","sportmonks_motorsport_search_stages","sportmonks_motorsport_search_teams","sportmonks_motorsport_search_venues","sportmonks_odds_get_all_historical_odds","sportmonks_odds_get_all_inplay_odds","sportmonks_odds_get_all_pre_match_odds","sportmonks_odds_get_all_premium_odds","sportmonks_odds_get_bookmaker","sportmonks_odds_get_bookmaker_event_ids_by_fixture","sportmonks_odds_get_bookmakers","sportmonks_odds_get_bookmakers_by_fixture","sportmonks_odds_get_inplay_odds_by_fixture","sportmonks_odds_get_inplay_odds_by_fixture_and_bookmaker","sportmonks_odds_get_inplay_odds_by_fixture_and_market","sportmonks_odds_get_last_updated_inplay_odds","sportmonks_odds_get_last_updated_pre_match_odds","sportmonks_odds_get_market","sportmonks_odds_get_markets","sportmonks_odds_get_pre_match_odds_by_fixture","sportmonks_odds_get_pre_match_odds_by_fixture_and_bookmaker","sportmonks_odds_get_pre_match_odds_by_fixture_and_market","sportmonks_odds_get_premium_odds_by_fixture","sportmonks_odds_get_premium_odds_by_fixture_and_bookmaker","sportmonks_odds_get_premium_odds_by_fixture_and_market","sportmonks_odds_get_updated_historical_odds_between","sportmonks_odds_get_updated_premium_odds_between","sportmonks_odds_search_bookmakers","sportmonks_odds_search_markets","spotify_add_playlist_cover","spotify_add_to_queue","spotify_add_tracks_to_playlist","spotify_check_following","spotify_check_playlist_followers","spotify_check_saved_albums","spotify_check_saved_audiobooks","spotify_check_saved_episodes","spotify_check_saved_shows","spotify_check_saved_tracks","spotify_create_playlist","spotify_follow_artists","spotify_follow_playlist","spotify_get_album","spotify_get_album_tracks","spotify_get_albums","spotify_get_artist","spotify_get_artist_albums","spotify_get_artist_top_tracks","spotify_get_artists","spotify_get_audiobook","spotify_get_audiobook_chapters","spotify_get_audiobooks","spotify_get_categories","spotify_get_current_user","spotify_get_currently_playing","spotify_get_devices","spotify_get_episode","spotify_get_episodes","spotify_get_followed_artists","spotify_get_markets","spotify_get_new_releases","spotify_get_playback_state","spotify_get_playlist","spotify_get_playlist_cover","spotify_get_playlist_tracks","spotify_get_queue","spotify_get_recently_played","spotify_get_saved_albums","spotify_get_saved_audiobooks","spotify_get_saved_episodes","spotify_get_saved_shows","spotify_get_saved_tracks","spotify_get_show","spotify_get_show_episodes","spotify_get_shows","spotify_get_top_artists","spotify_get_top_tracks","spotify_get_track","spotify_get_tracks","spotify_get_user_playlists","spotify_get_user_profile","spotify_pause","spotify_play","spotify_remove_saved_albums","spotify_remove_saved_audiobooks","spotify_remove_saved_episodes","spotify_remove_saved_shows","spotify_remove_saved_tracks","spotify_remove_tracks_from_playlist","spotify_reorder_playlist_items","spotify_replace_playlist_items","spotify_save_albums","spotify_save_audiobooks","spotify_save_episodes","spotify_save_shows","spotify_save_tracks","spotify_search","spotify_seek","spotify_set_repeat","spotify_set_shuffle","spotify_set_volume","spotify_skip_next","spotify_skip_previous","spotify_transfer_playback","spotify_unfollow_artists","spotify_unfollow_playlist","spotify_update_playlist","sqs_cancel_message_move_task","sqs_change_message_visibility","sqs_change_message_visibility_batch","sqs_create_queue","sqs_delete_message","sqs_delete_message_batch","sqs_delete_queue","sqs_get_queue_attributes","sqs_get_queue_url","sqs_list_dead_letter_source_queues","sqs_list_message_move_tasks","sqs_list_queue_tags","sqs_list_queues","sqs_purge_queue","sqs_receive_message","sqs_send","sqs_send_message_batch","sqs_set_queue_attributes","sqs_start_message_move_task","sqs_tag_queue","sqs_untag_queue","square_batch_retrieve_inventory_counts","square_cancel_invoice","square_cancel_payment","square_complete_payment","square_create_catalog_image","square_create_customer","square_create_invoice","square_create_order","square_create_payment","square_delete_catalog_object","square_delete_customer","square_delete_invoice","square_get_catalog_object","square_get_customer","square_get_invoice","square_get_location","square_get_order","square_get_payment","square_get_refund","square_list_catalog","square_list_customers","square_list_invoices","square_list_locations","square_list_payments","square_list_refunds","square_pay_order","square_publish_invoice","square_refund_payment","square_search_catalog_objects","square_search_customers","square_search_invoices","square_search_orders","square_update_customer","square_upsert_catalog_object","ssh_check_command_exists","ssh_check_file_exists","ssh_create_directory","ssh_delete_file","ssh_download_file","ssh_download_file_v2","ssh_execute_command","ssh_execute_script","ssh_get_system_info","ssh_list_directory","ssh_move_rename","ssh_read_file_content","ssh_upload_file","ssh_write_file_content","ssm_cancel_command","ssm_delete_parameter","ssm_describe_automation_executions","ssm_describe_instance_information","ssm_describe_instance_patch_states","ssm_describe_instance_patches","ssm_describe_parameters","ssm_get_automation_execution","ssm_get_command_invocation","ssm_get_document","ssm_get_parameter","ssm_get_parameters","ssm_get_parameters_by_path","ssm_list_command_invocations","ssm_list_commands","ssm_list_compliance_items","ssm_list_compliance_summaries","ssm_list_documents","ssm_put_parameter","ssm_send_command","ssm_start_automation_execution","ssm_stop_automation_execution","stagehand_agent","stagehand_extract","stripe_cancel_payment_intent","stripe_cancel_subscription","stripe_capture_charge","stripe_capture_payment_intent","stripe_confirm_payment_intent","stripe_create_charge","stripe_create_customer","stripe_create_invoice","stripe_create_payment_intent","stripe_create_price","stripe_create_product","stripe_create_subscription","stripe_delete_customer","stripe_delete_invoice","stripe_delete_product","stripe_finalize_invoice","stripe_list_charges","stripe_list_customers","stripe_list_events","stripe_list_invoices","stripe_list_payment_intents","stripe_list_prices","stripe_list_products","stripe_list_subscriptions","stripe_pay_invoice","stripe_resume_subscription","stripe_retrieve_charge","stripe_retrieve_customer","stripe_retrieve_event","stripe_retrieve_invoice","stripe_retrieve_payment_intent","stripe_retrieve_price","stripe_retrieve_product","stripe_retrieve_subscription","stripe_search_charges","stripe_search_customers","stripe_search_invoices","stripe_search_payment_intents","stripe_search_prices","stripe_search_products","stripe_search_subscriptions","stripe_send_invoice","stripe_update_charge","stripe_update_customer","stripe_update_invoice","stripe_update_payment_intent","stripe_update_price","stripe_update_product","stripe_update_subscription","stripe_void_invoice","sts_assume_role","sts_assume_role_with_saml","sts_assume_role_with_web_identity","sts_get_access_key_info","sts_get_caller_identity","sts_get_session_token","stt_assemblyai","stt_assemblyai_v2","stt_deepgram","stt_deepgram_v2","stt_elevenlabs","stt_elevenlabs_v2","stt_gemini","stt_gemini_v2","stt_whisper","stt_whisper_v2","supabase_count","supabase_delete","supabase_get_row","supabase_insert","supabase_introspect","supabase_invoke_function","supabase_query","supabase_rpc","supabase_storage_copy","supabase_storage_create_bucket","supabase_storage_create_signed_upload_url","supabase_storage_create_signed_url","supabase_storage_delete","supabase_storage_delete_bucket","supabase_storage_download","supabase_storage_empty_bucket","supabase_storage_get_public_url","supabase_storage_list","supabase_storage_list_buckets","supabase_storage_move","supabase_storage_update_bucket","supabase_storage_upload","supabase_text_search","supabase_update","supabase_upsert","supabase_vector_search","table_batch_insert_rows","table_create","table_delete_row","table_delete_rows_by_filter","table_get_row","table_get_schema","table_insert_row","table_list","table_query_rows","table_query_rows_v2","table_update_row","table_update_rows_by_filter","table_upsert_row","tailscale_authorize_device","tailscale_create_auth_key","tailscale_delete_auth_key","tailscale_delete_device","tailscale_delete_user","tailscale_expire_device_key","tailscale_get_acl","tailscale_get_auth_key","tailscale_get_device","tailscale_get_device_routes","tailscale_get_dns_preferences","tailscale_get_dns_searchpaths","tailscale_list_auth_keys","tailscale_list_devices","tailscale_list_dns_nameservers","tailscale_list_users","tailscale_set_acl","tailscale_set_device_routes","tailscale_set_device_tags","tailscale_set_dns_nameservers","tailscale_set_dns_preferences","tailscale_set_dns_searchpaths","tailscale_suspend_user","tailscale_update_device_key","tavily_crawl","tavily_extract","tavily_map","tavily_search","telegram_copy_message","telegram_delete_message","telegram_edit_message_text","telegram_forward_message","telegram_get_chat","telegram_get_chat_member","telegram_message","telegram_pin_message","telegram_send_animation","telegram_send_audio","telegram_send_chat_action","telegram_send_contact","telegram_send_document","telegram_send_location","telegram_send_photo","telegram_send_poll","telegram_send_video","telegram_set_message_reaction","telegram_unpin_message","temporal_cancel_workflow","temporal_count_workflows","temporal_create_schedule","temporal_delete_schedule","temporal_describe_schedule","temporal_describe_task_queue","temporal_describe_workflow","temporal_get_workflow_history","temporal_list_schedules","temporal_list_workflows","temporal_pause_schedule","temporal_query_workflow","temporal_reset_workflow","temporal_signal_with_start","temporal_signal_workflow","temporal_start_workflow","temporal_terminate_workflow","temporal_trigger_schedule","temporal_unpause_schedule","temporal_update_workflow","textract_analyze_expense","textract_analyze_id","textract_parser","textract_parser_v2","thinking_tool","thrive_add_audience_managers","thrive_add_audience_members","thrive_add_user_tags","thrive_create_assignment","thrive_create_audience","thrive_create_completion","thrive_create_user","thrive_delete_assignment","thrive_delete_audience","thrive_delete_user","thrive_get_activity","thrive_get_assignment","thrive_get_audience","thrive_get_completion","thrive_get_content","thrive_get_cpd_category","thrive_get_cpd_entry","thrive_get_cpd_requirement","thrive_get_enrolment","thrive_get_skill_levels","thrive_get_tag","thrive_get_user_by_id","thrive_get_user_by_ref","thrive_list_assignments","thrive_list_audience_managers","thrive_list_audience_members","thrive_list_audiences","thrive_list_completions","thrive_list_enrolments","thrive_list_tags","thrive_query_activities","thrive_query_content","thrive_query_cpd_categories","thrive_query_cpd_entries","thrive_query_cpd_requirements","thrive_query_cpd_user_summaries","thrive_remove_audience_manager","thrive_remove_audience_member","thrive_remove_user_tags","thrive_replace_audience_managers","thrive_replace_audience_members","thrive_search_users","thrive_suspend_user","thrive_update_assignment","thrive_update_audience","thrive_update_user","thrive_update_user_skills","tiktok_get_post_status","tiktok_get_user","tiktok_list_videos","tiktok_query_videos","tiktok_upload_video_draft","tinybird_append_datasource","tinybird_delete_datasource_rows","tinybird_events","tinybird_get_job","tinybird_query","tinybird_query_pipe","tinybird_truncate_datasource","tinyfish_cancel_run","tinyfish_fetch","tinyfish_get_run","tinyfish_list_profiles","tinyfish_list_runs","tinyfish_list_vault_items","tinyfish_run","tinyfish_run_async","tinyfish_search","trello_add_checklist","trello_add_checklist_item","trello_add_comment","trello_add_label","trello_add_member","trello_create_board","trello_create_card","trello_create_list","trello_delete_card","trello_get_actions","trello_get_board","trello_get_card","trello_list_cards","trello_list_lists","trello_list_members","trello_remove_label","trello_remove_member","trello_search","trello_update_card","trello_update_checklist_item","trello_update_list","trigger_dev_activate_schedule","trigger_dev_add_run_tags","trigger_dev_batch_trigger_task","trigger_dev_cancel_run","trigger_dev_complete_waitpoint_token","trigger_dev_create_env_var","trigger_dev_create_schedule","trigger_dev_create_waitpoint_token","trigger_dev_deactivate_schedule","trigger_dev_delete_env_var","trigger_dev_delete_schedule","trigger_dev_execute_query","trigger_dev_get_batch","trigger_dev_get_batch_results","trigger_dev_get_deployment","trigger_dev_get_env_var","trigger_dev_get_latest_deployment","trigger_dev_get_query_schema","trigger_dev_get_queue","trigger_dev_get_run","trigger_dev_get_run_events","trigger_dev_get_run_result","trigger_dev_get_run_trace","trigger_dev_get_schedule","trigger_dev_get_waitpoint_token","trigger_dev_import_env_vars","trigger_dev_list_deployments","trigger_dev_list_env_vars","trigger_dev_list_queues","trigger_dev_list_runs","trigger_dev_list_schedules","trigger_dev_list_timezones","trigger_dev_list_waitpoint_tokens","trigger_dev_override_queue_concurrency","trigger_dev_pause_queue","trigger_dev_promote_deployment","trigger_dev_replay_run","trigger_dev_reschedule_run","trigger_dev_reset_queue_concurrency","trigger_dev_resume_queue","trigger_dev_trigger_task","trigger_dev_update_env_var","trigger_dev_update_run_metadata","trigger_dev_update_schedule","tts_azure","tts_cartesia","tts_deepgram","tts_elevenlabs","tts_google","tts_openai","tts_playht","twilio_send_sms","twilio_voice_get_recording","twilio_voice_list_calls","twilio_voice_make_call","typeform_create_form","typeform_delete_form","typeform_files","typeform_get_form","typeform_insights","typeform_list_forms","typeform_responses","typeform_update_form","upstash_redis_command","upstash_redis_delete","upstash_redis_exists","upstash_redis_expire","upstash_redis_get","upstash_redis_hget","upstash_redis_hgetall","upstash_redis_hset","upstash_redis_incr","upstash_redis_incrby","upstash_redis_keys","upstash_redis_lpush","upstash_redis_lrange","upstash_redis_set","upstash_redis_setnx","upstash_redis_ttl","uptimerobot_create_alert_contact","uptimerobot_create_maintenance_window","uptimerobot_create_monitor","uptimerobot_create_psp","uptimerobot_delete_alert_contact","uptimerobot_delete_maintenance_window","uptimerobot_delete_monitor","uptimerobot_delete_psp","uptimerobot_get_account","uptimerobot_get_alert_contact","uptimerobot_get_incident","uptimerobot_get_maintenance_window","uptimerobot_get_monitor","uptimerobot_get_psp","uptimerobot_list_alert_contacts","uptimerobot_list_incidents","uptimerobot_list_maintenance_windows","uptimerobot_list_monitors","uptimerobot_list_psps","uptimerobot_pause_monitor","uptimerobot_start_monitor","uptimerobot_update_maintenance_window","uptimerobot_update_monitor","uptimerobot_update_psp","vanta_download_document_file","vanta_get_control","vanta_get_document","vanta_get_framework","vanta_get_person","vanta_get_policy","vanta_get_risk_scenario","vanta_get_test","vanta_get_vendor","vanta_get_vulnerable_asset","vanta_list_control_documents","vanta_list_control_tests","vanta_list_controls","vanta_list_document_uploads","vanta_list_documents","vanta_list_framework_controls","vanta_list_frameworks","vanta_list_monitored_computers","vanta_list_people","vanta_list_policies","vanta_list_risk_scenarios","vanta_list_test_entities","vanta_list_tests","vanta_list_vendors","vanta_list_vulnerabilities","vanta_list_vulnerability_remediations","vanta_list_vulnerable_assets","vanta_submit_document","vanta_upload_document_file","vercel_add_domain","vercel_add_project_domain","vercel_cancel_deployment","vercel_create_alias","vercel_create_check","vercel_create_deployment","vercel_create_dns_record","vercel_create_edge_config","vercel_create_env_var","vercel_create_project","vercel_create_webhook","vercel_delete_alias","vercel_delete_deployment","vercel_delete_dns_record","vercel_delete_domain","vercel_delete_edge_config","vercel_delete_env_var","vercel_delete_project","vercel_delete_webhook","vercel_get_alias","vercel_get_check","vercel_get_deployment","vercel_get_deployment_events","vercel_get_domain","vercel_get_domain_config","vercel_get_edge_config","vercel_get_edge_config_items","vercel_get_env_vars","vercel_get_project","vercel_get_team","vercel_get_user","vercel_get_webhook","vercel_list_aliases","vercel_list_checks","vercel_list_deployment_files","vercel_list_deployments","vercel_list_dns_records","vercel_list_domains","vercel_list_edge_configs","vercel_list_project_domains","vercel_list_projects","vercel_list_team_members","vercel_list_teams","vercel_list_webhooks","vercel_pause_project","vercel_promote_deployment","vercel_remove_project_domain","vercel_rerequest_check","vercel_unpause_project","vercel_update_check","vercel_update_dns_record","vercel_update_edge_config_items","vercel_update_env_var","vercel_update_project","vercel_update_project_domain","vercel_verify_project_domain","video_falai","video_luma","video_minimax","video_runway","video_veo","vision_tool","vision_tool_v2","wealthbox_read_contact","wealthbox_read_note","wealthbox_read_task","wealthbox_write_contact","wealthbox_write_note","wealthbox_write_task","webflow_create_item","webflow_delete_item","webflow_get_item","webflow_list_items","webflow_update_item","webhook_request","whatsapp_get_media","whatsapp_mark_read","whatsapp_send_interactive","whatsapp_send_media","whatsapp_send_message","whatsapp_send_reaction","whatsapp_send_template","whatsapp_upload_media","wikipedia_content","wikipedia_random","wikipedia_search","wikipedia_summary","windchill_check_in_document","windchill_check_in_documents","windchill_check_out_document","windchill_check_out_documents","windchill_create_document","windchill_create_documents","windchill_delete_document","windchill_delete_documents","windchill_download_attachment","windchill_download_primary_content","windchill_get_document","windchill_get_document_structure","windchill_get_primary_content","windchill_get_valid_state_transitions","windchill_list_attachments","windchill_list_documents","windchill_revise_document","windchill_revise_documents","windchill_set_lifecycle_state","windchill_undo_check_out_document","windchill_undo_check_out_documents","windchill_update_common_properties","windchill_update_document","windchill_update_document_security_labels","windchill_update_documents","windchill_upload_attachments","windchill_upload_primary_content","wiza_company_enrichment","wiza_get_credits","wiza_individual_reveal","wiza_prospect_search","wordpress_create_category","wordpress_create_comment","wordpress_create_page","wordpress_create_post","wordpress_create_tag","wordpress_delete_category","wordpress_delete_comment","wordpress_delete_media","wordpress_delete_page","wordpress_delete_post","wordpress_delete_tag","wordpress_get_category","wordpress_get_current_user","wordpress_get_media","wordpress_get_page","wordpress_get_post","wordpress_get_tag","wordpress_get_user","wordpress_list_categories","wordpress_list_comments","wordpress_list_media","wordpress_list_pages","wordpress_list_posts","wordpress_list_tags","wordpress_list_users","wordpress_search_content","wordpress_update_category","wordpress_update_comment","wordpress_update_page","wordpress_update_post","wordpress_update_tag","wordpress_upload_media","workday_assign_onboarding","workday_change_job","workday_create_prehire","workday_get_compensation","workday_get_organizations","workday_get_worker","workday_hire_employee","workday_list_workers","workday_terminate_worker","workday_update_worker","workflow_executor","x_create_bookmark","x_create_tweet","x_delete_bookmark","x_delete_tweet","x_get_blocking","x_get_bookmarks","x_get_followers","x_get_following","x_get_liked_tweets","x_get_liking_users","x_get_me","x_get_personalized_trends","x_get_quote_tweets","x_get_retweeted_by","x_get_trends_by_woeid","x_get_tweets_by_ids","x_get_usage","x_get_user_mentions","x_get_user_timeline","x_get_user_tweets","x_hide_reply","x_manage_block","x_manage_follow","x_manage_like","x_manage_mute","x_manage_retweet","x_read","x_search","x_search_tweets","x_search_users","x_user","x_write","youcom_answer","youcom_finance_research","youcom_get_account_balance","youcom_get_contents","youcom_get_research_task","youcom_research","youcom_search","youcom_search_images","youtube_channel_info","youtube_channel_playlists","youtube_channel_videos","youtube_comments","youtube_playlist_items","youtube_search","youtube_trending","youtube_video_categories","youtube_video_details","zendesk_autocomplete_organizations","zendesk_create_organization","zendesk_create_organizations_bulk","zendesk_create_ticket","zendesk_create_tickets_bulk","zendesk_create_user","zendesk_create_users_bulk","zendesk_delete_organization","zendesk_delete_ticket","zendesk_delete_user","zendesk_get_current_user","zendesk_get_organization","zendesk_get_organizations","zendesk_get_ticket","zendesk_get_tickets","zendesk_get_user","zendesk_get_users","zendesk_merge_tickets","zendesk_search","zendesk_search_count","zendesk_search_users","zendesk_update_organization","zendesk_update_ticket","zendesk_update_tickets_bulk","zendesk_update_user","zendesk_update_users_bulk","zep_add_messages","zep_add_user","zep_create_thread","zep_delete_thread","zep_get_context","zep_get_messages","zep_get_threads","zep_get_user","zep_get_user_threads","zerobounce_get_credits","zerobounce_verify_email","zoho_desk_add_comment","zoho_desk_create_account","zoho_desk_create_contact","zoho_desk_create_ticket","zoho_desk_delete_comment","zoho_desk_get_account","zoho_desk_get_agent","zoho_desk_get_attachment","zoho_desk_get_comment","zoho_desk_get_contact","zoho_desk_get_department","zoho_desk_get_thread","zoho_desk_get_ticket","zoho_desk_list_accounts","zoho_desk_list_agents","zoho_desk_list_comments","zoho_desk_list_contacts","zoho_desk_list_departments","zoho_desk_list_organizations","zoho_desk_list_threads","zoho_desk_list_tickets","zoho_desk_move_ticket","zoho_desk_search_accounts","zoho_desk_search_contacts","zoho_desk_search_tickets","zoho_desk_send_reply","zoho_desk_update_account","zoho_desk_update_comment","zoho_desk_update_contact","zoho_desk_update_ticket","zoom_create_meeting","zoom_delete_meeting","zoom_delete_recording","zoom_get_meeting","zoom_get_meeting_invitation","zoom_get_meeting_recordings","zoom_list_meetings","zoom_list_past_participants","zoom_list_recordings","zoom_update_meeting","zoominfo_enrich_companies","zoominfo_enrich_contacts","zoominfo_search_companies","zoominfo_search_contacts","zoominfo_search_intent","zoominfo_search_news"]' + '["a2a_cancel_task","a2a_get_agent_card","a2a_get_task","a2a_send_message","affinity_batch_update_entity_fields","affinity_batch_update_list_entry_fields","affinity_create_list","affinity_create_list_field_dropdown_option","affinity_create_merge","affinity_create_note","affinity_create_reminder","affinity_delete_list_field_dropdown_option","affinity_delete_note","affinity_get_company","affinity_get_current_user","affinity_get_entity_field_value","affinity_get_list","affinity_get_list_entry","affinity_get_list_entry_field","affinity_get_list_field_dropdown_option","affinity_get_merge","affinity_get_merge_task","affinity_get_note","affinity_get_opportunity","affinity_get_person","affinity_get_saved_view","affinity_get_transcript","affinity_get_user","affinity_list_calls","affinity_list_chat_messages","affinity_list_companies","affinity_list_coworker_connections","affinity_list_emails","affinity_list_entity_field_values","affinity_list_entity_list_entries","affinity_list_entity_lists","affinity_list_entity_notes","affinity_list_entity_relationships","affinity_list_field_dropdown_options","affinity_list_field_metadata","affinity_list_field_value_changes","affinity_list_investor_executive_connections","affinity_list_list_entries","affinity_list_list_entry_field_value_changes","affinity_list_list_entry_fields","affinity_list_list_field_dropdown_options","affinity_list_list_fields","affinity_list_lists","affinity_list_meetings","affinity_list_merge_tasks","affinity_list_merges","affinity_list_note_attached_companies","affinity_list_note_attached_opportunities","affinity_list_note_attached_persons","affinity_list_note_replies","affinity_list_notes","affinity_list_opportunities","affinity_list_persons","affinity_list_reminders","affinity_list_saved_view_entries","affinity_list_saved_views","affinity_list_transcript_fragments","affinity_list_transcripts","affinity_list_users","affinity_search_companies","affinity_search_files","affinity_search_list_entries","affinity_search_notes","affinity_search_persons","affinity_semantic_search","affinity_update_entity_field_value","affinity_update_list_entry_field","affinity_update_list_field_dropdown_option","affinity_update_note","agentmail_create_draft","agentmail_create_inbox","agentmail_delete_draft","agentmail_delete_inbox","agentmail_delete_thread","agentmail_forward_message","agentmail_get_draft","agentmail_get_inbox","agentmail_get_message","agentmail_get_thread","agentmail_list_drafts","agentmail_list_inboxes","agentmail_list_messages","agentmail_list_threads","agentmail_reply_message","agentmail_send_draft","agentmail_send_message","agentmail_update_draft","agentmail_update_inbox","agentmail_update_message","agentmail_update_thread","agentphone_create_call","agentphone_create_contact","agentphone_create_number","agentphone_delete_contact","agentphone_get_call","agentphone_get_call_transcript","agentphone_get_contact","agentphone_get_conversation","agentphone_get_conversation_messages","agentphone_get_number_messages","agentphone_get_usage","agentphone_get_usage_daily","agentphone_get_usage_monthly","agentphone_list_calls","agentphone_list_contacts","agentphone_list_conversations","agentphone_list_numbers","agentphone_react_to_message","agentphone_release_number","agentphone_send_message","agentphone_update_contact","agentphone_update_conversation","agiloft_async_status","agiloft_attach_file","agiloft_attachment_info","agiloft_create_record","agiloft_delete_record","agiloft_get_choice_line_id","agiloft_list_tables","agiloft_lock_record","agiloft_nlp_search","agiloft_read_record","agiloft_remove_attachment","agiloft_retrieve_attachment","agiloft_run_action_button","agiloft_saved_search","agiloft_search_records","agiloft_select_records","agiloft_update_record","agiloft_upsert_record","ahrefs_anchors","ahrefs_backlinks","ahrefs_backlinks_stats","ahrefs_batch_analysis","ahrefs_broken_backlinks","ahrefs_domain_rating","ahrefs_domain_rating_history","ahrefs_keyword_overview","ahrefs_keywords_history","ahrefs_metrics","ahrefs_metrics_history","ahrefs_organic_competitors","ahrefs_organic_keywords","ahrefs_paid_pages","ahrefs_rank_tracker_competitors_overview","ahrefs_rank_tracker_competitors_stats","ahrefs_rank_tracker_overview","ahrefs_rank_tracker_serp_overview","ahrefs_refdomains_history","ahrefs_referring_domains","ahrefs_related_terms","ahrefs_site_audit_page_explorer","ahrefs_top_pages","airtable_create_records","airtable_delete_records","airtable_get_base_schema","airtable_get_record","airtable_list_bases","airtable_list_records","airtable_list_tables","airtable_update_multiple_records","airtable_update_record","airtable_upsert_records","algolia_add_record","algolia_batch_operations","algolia_browse_records","algolia_clear_records","algolia_copy_move_index","algolia_delete_by_filter","algolia_delete_index","algolia_delete_record","algolia_get_record","algolia_get_records","algolia_get_settings","algolia_get_task_status","algolia_list_indices","algolia_partial_update_record","algolia_search","algolia_update_settings","amplitude_event_segmentation","amplitude_funnels","amplitude_get_active_users","amplitude_get_revenue","amplitude_group_identify","amplitude_identify_user","amplitude_list_events","amplitude_realtime_active_users","amplitude_retention","amplitude_send_event","amplitude_user_activity","amplitude_user_profile","amplitude_user_search","apify_get_dataset_items","apify_get_run","apify_run_actor_async","apify_run_actor_sync","apify_run_task","apollo_account_bulk_create","apollo_account_bulk_update","apollo_account_create","apollo_account_search","apollo_account_update","apollo_contact_bulk_create","apollo_contact_bulk_update","apollo_contact_create","apollo_contact_search","apollo_contact_update","apollo_email_accounts","apollo_opportunity_create","apollo_opportunity_get","apollo_opportunity_search","apollo_opportunity_update","apollo_organization_bulk_enrich","apollo_organization_enrich","apollo_organization_search","apollo_people_bulk_enrich","apollo_people_enrich","apollo_people_search","apollo_sequence_add_contacts","apollo_sequence_search","apollo_task_create","apollo_task_search","appconfig_create_application","appconfig_create_configuration_profile","appconfig_create_environment","appconfig_create_hosted_configuration_version","appconfig_delete_application","appconfig_delete_configuration_profile","appconfig_delete_environment","appconfig_delete_hosted_configuration_version","appconfig_get_application","appconfig_get_configuration","appconfig_get_configuration_profile","appconfig_get_deployment","appconfig_get_environment","appconfig_get_hosted_configuration_version","appconfig_list_applications","appconfig_list_configuration_profiles","appconfig_list_deployment_strategies","appconfig_list_deployments","appconfig_list_environments","appconfig_list_hosted_configuration_versions","appconfig_start_deployment","appconfig_stop_deployment","appconfig_update_application","appconfig_update_configuration_profile","appconfig_update_environment","arxiv_get_author_papers","arxiv_get_paper","arxiv_search","asana_add_comment","asana_add_followers","asana_create_project","asana_create_section","asana_create_subtask","asana_create_task","asana_delete_task","asana_get_project","asana_get_projects","asana_get_task","asana_list_sections","asana_list_workspaces","asana_search_tasks","asana_update_task","ashby_add_candidate_tag","ashby_anonymize_candidate","ashby_change_application_source","ashby_change_application_stage","ashby_create_application","ashby_create_candidate","ashby_create_note","ashby_delete_application","ashby_get_application","ashby_get_candidate","ashby_get_job","ashby_get_job_posting","ashby_get_offer","ashby_get_opening","ashby_list_application_feedback","ashby_list_application_history","ashby_list_applications","ashby_list_archive_reasons","ashby_list_candidate_tags","ashby_list_candidates","ashby_list_custom_fields","ashby_list_departments","ashby_list_interview_plans","ashby_list_interview_stages","ashby_list_interviews","ashby_list_job_postings","ashby_list_jobs","ashby_list_locations","ashby_list_notes","ashby_list_offers","ashby_list_openings","ashby_list_sources","ashby_list_users","ashby_remove_candidate_tag","ashby_search_candidates","ashby_search_jobs","ashby_search_openings","ashby_search_users","ashby_set_custom_field_value","ashby_set_custom_field_values","ashby_transfer_application","ashby_update_candidate","ashby_upload_candidate_file","ashby_upload_resume","athena_batch_get_named_query","athena_batch_get_prepared_statement","athena_batch_get_query_execution","athena_create_named_query","athena_create_prepared_statement","athena_delete_named_query","athena_delete_prepared_statement","athena_get_data_catalog","athena_get_database","athena_get_named_query","athena_get_prepared_statement","athena_get_query_execution","athena_get_query_results","athena_get_query_runtime_statistics","athena_get_table_metadata","athena_get_work_group","athena_list_data_catalogs","athena_list_databases","athena_list_named_queries","athena_list_prepared_statements","athena_list_query_executions","athena_list_table_metadata","athena_list_work_groups","athena_start_query","athena_stop_query","athena_update_named_query","athena_update_prepared_statement","attio_assert_record","attio_create_attribute","attio_create_comment","attio_create_list","attio_create_list_entry","attio_create_note","attio_create_object","attio_create_record","attio_create_task","attio_create_webhook","attio_delete_comment","attio_delete_list_entry","attio_delete_note","attio_delete_record","attio_delete_task","attio_delete_webhook","attio_get_attribute","attio_get_comment","attio_get_list","attio_get_list_entry","attio_get_member","attio_get_note","attio_get_object","attio_get_record","attio_get_task","attio_get_thread","attio_get_webhook","attio_list_attributes","attio_list_lists","attio_list_members","attio_list_notes","attio_list_objects","attio_list_records","attio_list_tasks","attio_list_threads","attio_list_webhooks","attio_query_list_entries","attio_search_records","attio_update_attribute","attio_update_list","attio_update_list_entry","attio_update_object","attio_update_record","attio_update_task","attio_update_webhook","azure_data_explorer_create_table","azure_data_explorer_drop_table","azure_data_explorer_ingest_from_query","azure_data_explorer_ingest_inline","azure_data_explorer_list_databases","azure_data_explorer_list_functions","azure_data_explorer_list_tables","azure_data_explorer_management","azure_data_explorer_query","azure_data_explorer_show_database_schema","azure_data_explorer_show_ingestion_failures","azure_data_explorer_show_operations","azure_data_explorer_show_table_details","azure_data_explorer_show_table_schema","azure_devops_add_comment","azure_devops_create_work_item","azure_devops_get_build_log","azure_devops_get_build_timeline","azure_devops_get_comments","azure_devops_get_pipeline","azure_devops_get_pipeline_run","azure_devops_get_work_item","azure_devops_get_work_items_batch","azure_devops_get_work_items_between_builds","azure_devops_list_build_logs","azure_devops_list_builds","azure_devops_list_pipeline_runs","azure_devops_list_pipelines","azure_devops_query_work_items","azure_devops_update_work_item","bitbucket_approve_pull_request","bitbucket_create_branch","bitbucket_create_pull_request","bitbucket_create_pull_request_comment","bitbucket_decline_pull_request","bitbucket_delete_branch","bitbucket_get_commit","bitbucket_get_file","bitbucket_get_file_metadata","bitbucket_get_pipeline","bitbucket_get_pipeline_step_log","bitbucket_get_pull_request","bitbucket_get_pull_request_diff","bitbucket_get_pull_request_diffstat","bitbucket_get_pull_request_merge_task_status","bitbucket_get_repository","bitbucket_list_branches","bitbucket_list_commits","bitbucket_list_directory","bitbucket_list_pipeline_steps","bitbucket_list_pipelines","bitbucket_list_pull_request_comments","bitbucket_list_pull_request_commit_statuses","bitbucket_list_pull_requests","bitbucket_list_repositories","bitbucket_list_workspaces","bitbucket_merge_pull_request","bitbucket_request_pull_request_changes","bitbucket_stop_pipeline","bitbucket_trigger_pipeline","box_copy_file","box_create_folder","box_delete_file","box_delete_folder","box_download_file","box_download_file_v2","box_get_file_info","box_list_folder_items","box_search","box_sign_cancel_request","box_sign_create_request","box_sign_get_request","box_sign_list_requests","box_sign_resend_request","box_update_file","box_upload_file","brandfetch_get_brand","brandfetch_search","brex_archive_budget","brex_create_budget","brex_create_spend_limit","brex_create_transfer","brex_create_vendor","brex_get_budget","brex_get_cash_account","brex_get_company","brex_get_current_user","brex_get_expense","brex_get_spend_limit","brex_get_transfer","brex_get_user","brex_get_vendor","brex_list_budgets","brex_list_card_accounts","brex_list_card_statements","brex_list_card_transactions","brex_list_cards","brex_list_cash_accounts","brex_list_cash_statements","brex_list_cash_transactions","brex_list_departments","brex_list_expenses","brex_list_locations","brex_list_spend_limits","brex_list_titles","brex_list_transfers","brex_list_users","brex_list_vendors","brex_match_receipt","brex_update_expense","brex_update_vendor","brex_upload_receipt","brightdata_cancel_snapshot","brightdata_discover","brightdata_download_snapshot","brightdata_scrape_dataset","brightdata_scrape_url","brightdata_serp_search","brightdata_snapshot_status","brightdata_sync_scrape","browser_use_run_task","buffer_create_idea","buffer_create_post","buffer_delete_post","buffer_edit_post","buffer_get_account","buffer_get_aggregated_post_metrics","buffer_get_channel","buffer_get_channels","buffer_get_daily_posting_limits","buffer_get_idea_groups","buffer_get_ideas","buffer_get_post","buffer_get_posts","calcom_cancel_booking","calcom_confirm_booking","calcom_create_booking","calcom_create_event_type","calcom_create_schedule","calcom_decline_booking","calcom_delete_event_type","calcom_delete_schedule","calcom_get_booking","calcom_get_default_schedule","calcom_get_event_type","calcom_get_schedule","calcom_get_slots","calcom_list_bookings","calcom_list_event_types","calcom_list_schedules","calcom_reschedule_booking","calcom_update_event_type","calcom_update_schedule","calendly_cancel_event","calendly_create_event_invitee","calendly_create_invitee_no_show","calendly_create_scheduling_link","calendly_create_webhook","calendly_delete_invitee_no_show","calendly_delete_webhook","calendly_get_current_user","calendly_get_event_invitee","calendly_get_event_type","calendly_get_scheduled_event","calendly_get_user","calendly_list_event_invitees","calendly_list_event_type_available_times","calendly_list_event_types","calendly_list_organization_memberships","calendly_list_routing_form_submissions","calendly_list_routing_forms","calendly_list_scheduled_events","calendly_list_user_availability_schedules","calendly_list_user_busy_times","calendly_list_webhooks","cbinsights_chat","cbinsights_get_commercial_maturity_history","cbinsights_get_exit_probability_history","cbinsights_get_mosaic_history","cbinsights_get_org_business_relationships","cbinsights_get_org_funding_window","cbinsights_get_org_fundings","cbinsights_get_org_investments","cbinsights_get_org_management_and_board","cbinsights_get_org_outlook","cbinsights_get_org_portfolio_exits","cbinsights_get_org_revenue","cbinsights_get_scouting_report","cbinsights_get_strategy_map","cbinsights_list_business_relationships","cbinsights_list_funding_window","cbinsights_list_fundings","cbinsights_list_investments","cbinsights_list_management_and_board","cbinsights_list_outlook","cbinsights_list_portfolio_exits","cbinsights_list_revenue","cbinsights_lookup_organizations","cbinsights_rag","cbinsights_search_firmographics","checkr_add_report_tag","checkr_apply_report_review_action","checkr_cancel_adverse_action","checkr_cancel_continuous_check","checkr_cancel_invitation","checkr_cancel_subscription","checkr_complete_report","checkr_create_adverse_action","checkr_create_candidate","checkr_create_continuous_check","checkr_create_geo","checkr_create_invitation","checkr_create_report","checkr_create_subscription","checkr_delete_candidate_pii","checkr_delete_geo","checkr_get_account","checkr_get_adverse_action","checkr_get_candidate","checkr_get_continuous_check","checkr_get_document","checkr_get_geo","checkr_get_invitation","checkr_get_node","checkr_get_package","checkr_get_program","checkr_get_report","checkr_get_report_eta","checkr_get_report_progressive_status","checkr_get_report_tags","checkr_get_screening","checkr_get_subscription","checkr_get_verification","checkr_list_adverse_actions","checkr_list_adverse_items","checkr_list_assessments","checkr_list_candidate_documents","checkr_list_candidates","checkr_list_continuous_checks","checkr_list_counties","checkr_list_geos","checkr_list_invitations","checkr_list_nodes","checkr_list_packages","checkr_list_programs","checkr_list_report_addresses","checkr_list_subscriptions","checkr_list_users","checkr_list_verifications","checkr_remove_report_tag","checkr_set_report_tags","checkr_update_candidate","checkr_update_continuous_check","checkr_update_geo","checkr_update_report","checkr_update_subscription","circleback_add_tag_to_meetings","circleback_create_tag","circleback_delete_action_item","circleback_delete_meeting","circleback_delete_tag","circleback_get_company","circleback_get_meeting","circleback_get_person","circleback_get_transcript","circleback_list_action_items","circleback_list_calendar_events","circleback_list_companies","circleback_list_meetings","circleback_list_people","circleback_list_tags","circleback_remove_tag_from_meetings","circleback_search_meetings","circleback_update_action_item","circleback_update_meeting","circleback_update_tag","clay_populate","clerk_add_organization_member","clerk_ban_user","clerk_create_actor_token","clerk_create_allowlist_identifier","clerk_create_blocklist_identifier","clerk_create_organization","clerk_create_organization_invitation","clerk_create_user","clerk_delete_allowlist_identifier","clerk_delete_blocklist_identifier","clerk_delete_organization","clerk_delete_user","clerk_get_jwt_template","clerk_get_organization","clerk_get_session","clerk_get_user","clerk_get_user_oauth_token","clerk_list_allowlist_identifiers","clerk_list_blocklist_identifiers","clerk_list_jwt_templates","clerk_list_organization_invitations","clerk_list_organization_memberships","clerk_list_organizations","clerk_list_sessions","clerk_list_users","clerk_lock_user","clerk_remove_organization_member","clerk_revoke_actor_token","clerk_revoke_session","clerk_unban_user","clerk_unlock_user","clerk_update_organization","clerk_update_organization_membership","clerk_update_user","clickhouse_count_rows","clickhouse_create_database","clickhouse_create_table","clickhouse_delete","clickhouse_describe_table","clickhouse_drop_database","clickhouse_drop_partition","clickhouse_drop_table","clickhouse_execute","clickhouse_insert","clickhouse_insert_rows","clickhouse_introspect","clickhouse_kill_query","clickhouse_list_clusters","clickhouse_list_databases","clickhouse_list_mutations","clickhouse_list_partitions","clickhouse_list_running_queries","clickhouse_list_tables","clickhouse_optimize_table","clickhouse_query","clickhouse_rename_table","clickhouse_show_create_table","clickhouse_table_stats","clickhouse_truncate_table","clickhouse_update","clickup_add_tag_to_task","clickup_create_checklist","clickup_create_checklist_item","clickup_create_comment","clickup_create_folder","clickup_create_list","clickup_create_task","clickup_create_time_entry","clickup_delete_checklist","clickup_delete_checklist_item","clickup_delete_comment","clickup_delete_task","clickup_delete_time_entry","clickup_get_comments","clickup_get_custom_fields","clickup_get_folders","clickup_get_list_members","clickup_get_lists","clickup_get_running_timer","clickup_get_space_tags","clickup_get_spaces","clickup_get_task","clickup_get_task_members","clickup_get_tasks","clickup_get_time_entries","clickup_get_workspaces","clickup_remove_custom_field_value","clickup_remove_tag_from_task","clickup_search_tasks","clickup_set_custom_field_value","clickup_start_timer","clickup_stop_timer","clickup_update_checklist","clickup_update_checklist_item","clickup_update_comment","clickup_update_task","clickup_update_time_entry","clickup_upload_attachment","cloudflare_create_access_application","cloudflare_create_access_group","cloudflare_create_access_policy","cloudflare_create_access_service_token","cloudflare_create_dns_record","cloudflare_create_r2_bucket","cloudflare_create_rate_limit_rule","cloudflare_create_ruleset","cloudflare_create_ruleset_rule","cloudflare_create_tunnel","cloudflare_create_worker_route","cloudflare_create_zone","cloudflare_delete_access_application","cloudflare_delete_access_group","cloudflare_delete_access_policy","cloudflare_delete_dns_record","cloudflare_delete_r2_bucket","cloudflare_delete_r2_bucket_cors","cloudflare_delete_ruleset","cloudflare_delete_ruleset_rule","cloudflare_delete_tunnel","cloudflare_delete_worker_route","cloudflare_delete_worker_script","cloudflare_delete_zone","cloudflare_dns_analytics","cloudflare_get_access_application","cloudflare_get_access_group","cloudflare_get_access_policy","cloudflare_get_access_service_token","cloudflare_get_dns_record","cloudflare_get_r2_bucket","cloudflare_get_r2_bucket_cors","cloudflare_get_r2_bucket_lifecycle","cloudflare_get_ruleset","cloudflare_get_ruleset_entrypoint","cloudflare_get_tunnel","cloudflare_get_tunnel_configuration","cloudflare_get_tunnel_token","cloudflare_get_worker_route","cloudflare_get_worker_script_settings","cloudflare_get_zone","cloudflare_get_zone_settings","cloudflare_list_access_applications","cloudflare_list_access_groups","cloudflare_list_access_identity_providers","cloudflare_list_access_policies","cloudflare_list_access_service_tokens","cloudflare_list_certificates","cloudflare_list_dns_records","cloudflare_list_managed_ruleset_overrides","cloudflare_list_r2_buckets","cloudflare_list_rate_limit_rules","cloudflare_list_rulesets","cloudflare_list_tunnels","cloudflare_list_worker_routes","cloudflare_list_worker_scripts","cloudflare_list_zones","cloudflare_purge_cache","cloudflare_refresh_access_service_token","cloudflare_revoke_access_service_token","cloudflare_rotate_access_service_token","cloudflare_update_access_application","cloudflare_update_access_group","cloudflare_update_access_policy","cloudflare_update_access_service_token","cloudflare_update_dns_record","cloudflare_update_r2_bucket_cors","cloudflare_update_r2_bucket_lifecycle","cloudflare_update_rate_limit_rule","cloudflare_update_ruleset","cloudflare_update_ruleset_rule","cloudflare_update_tunnel","cloudflare_update_tunnel_configuration","cloudflare_update_worker_route","cloudflare_update_zone","cloudflare_update_zone_setting","cloudformation_cancel_update_stack","cloudformation_create_change_set","cloudformation_create_stack","cloudformation_delete_stack","cloudformation_describe_change_set","cloudformation_describe_stack_drift_detection_status","cloudformation_describe_stack_events","cloudformation_describe_stacks","cloudformation_detect_stack_drift","cloudformation_execute_change_set","cloudformation_get_template","cloudformation_get_template_summary","cloudformation_list_stack_resources","cloudformation_update_stack","cloudformation_validate_template","cloudtrail_cancel_query","cloudtrail_describe_query","cloudtrail_describe_trails","cloudtrail_get_event_data_store","cloudtrail_get_event_selectors","cloudtrail_get_insight_selectors","cloudtrail_get_query_results","cloudtrail_get_trail","cloudtrail_get_trail_status","cloudtrail_list_event_data_stores","cloudtrail_list_tags","cloudtrail_list_trails","cloudtrail_lookup_events","cloudtrail_start_query","cloudwatch_describe_alarm_history","cloudwatch_describe_alarms","cloudwatch_describe_log_groups","cloudwatch_describe_log_streams","cloudwatch_filter_log_events","cloudwatch_get_log_events","cloudwatch_get_metric_statistics","cloudwatch_list_metrics","cloudwatch_mute_alarm","cloudwatch_put_log_group_retention","cloudwatch_put_metric_data","cloudwatch_query_logs","cloudwatch_unmute_alarm","coda_add_custom_domain","coda_add_permission","coda_change_user_role","coda_create_doc","coda_create_folder","coda_create_page","coda_delete_custom_domain","coda_delete_doc","coda_delete_folder","coda_delete_page","coda_delete_page_content","coda_delete_permission","coda_delete_row","coda_delete_rows","coda_export_page","coda_get_acl_settings","coda_get_analytics_last_updated","coda_get_column","coda_get_control","coda_get_custom_domain_provider","coda_get_doc","coda_get_doc_analytics_summary","coda_get_folder","coda_get_formula","coda_get_mutation_status","coda_get_page","coda_get_page_content","coda_get_page_export_status","coda_get_row","coda_get_sharing_metadata","coda_get_table","coda_list_categories","coda_list_columns","coda_list_controls","coda_list_custom_domains","coda_list_doc_analytics","coda_list_docs","coda_list_folder_children","coda_list_folders","coda_list_formulas","coda_list_page_analytics","coda_list_pages","coda_list_permissions","coda_list_rows","coda_list_tables","coda_list_workspace_members","coda_list_workspace_roles","coda_publish_doc","coda_push_button","coda_resolve_browser_link","coda_search_principals","coda_trigger_automation","coda_unpublish_doc","coda_update_acl_settings","coda_update_doc","coda_update_folder","coda_update_page","coda_update_row","coda_upsert_rows","coda_whoami","codepipeline_disable_stage_transition","codepipeline_enable_stage_transition","codepipeline_get_pipeline","codepipeline_get_pipeline_execution","codepipeline_get_pipeline_state","codepipeline_list_action_executions","codepipeline_list_pipeline_executions","codepipeline_list_pipelines","codepipeline_put_approval_result","codepipeline_retry_stage_execution","codepipeline_start_execution","codepipeline_stop_execution","confluence_add_label","confluence_create_blogpost","confluence_create_comment","confluence_create_page","confluence_create_page_property","confluence_create_space","confluence_create_space_property","confluence_delete_attachment","confluence_delete_blogpost","confluence_delete_comment","confluence_delete_label","confluence_delete_page","confluence_delete_page_property","confluence_delete_space","confluence_delete_space_property","confluence_get_blogpost","confluence_get_page_ancestors","confluence_get_page_children","confluence_get_page_descendants","confluence_get_page_version","confluence_get_pages_by_label","confluence_get_space","confluence_get_task","confluence_get_user","confluence_list_attachments","confluence_list_blogposts","confluence_list_blogposts_in_space","confluence_list_comments","confluence_list_labels","confluence_list_page_properties","confluence_list_page_versions","confluence_list_pages_in_space","confluence_list_space_labels","confluence_list_space_permissions","confluence_list_space_properties","confluence_list_spaces","confluence_list_tasks","confluence_retrieve","confluence_search","confluence_search_in_space","confluence_update","confluence_update_blogpost","confluence_update_comment","confluence_update_space","confluence_update_task","confluence_upload_attachment","context_dev_classify_naics","context_dev_classify_sic","context_dev_crawl","context_dev_extract","context_dev_extract_product","context_dev_extract_products","context_dev_get_brand","context_dev_get_brand_by_email","context_dev_get_brand_by_name","context_dev_get_brand_by_ticker","context_dev_identify_transaction","context_dev_map","context_dev_scrape_fonts","context_dev_scrape_html","context_dev_scrape_images","context_dev_scrape_markdown","context_dev_scrape_styleguide","context_dev_screenshot","context_dev_search","convex_action","convex_document_deltas","convex_list_documents","convex_list_tables","convex_mutation","convex_query","convex_run_function","crowdstrike_create_indicators","crowdstrike_delete_indicators","crowdstrike_delete_rtr_session","crowdstrike_execute_rtr_command","crowdstrike_get_alert_details","crowdstrike_get_case_details","crowdstrike_get_host_group_details","crowdstrike_get_indicator_details","crowdstrike_get_rtr_command_status","crowdstrike_get_sensor_aggregates","crowdstrike_get_sensor_details","crowdstrike_get_vulnerability_details","crowdstrike_init_rtr_session","crowdstrike_perform_host_action","crowdstrike_perform_host_group_action","crowdstrike_query_alerts","crowdstrike_query_cases","crowdstrike_query_host_groups","crowdstrike_query_indicators","crowdstrike_query_sensors","crowdstrike_query_vulnerabilities","crowdstrike_update_alerts","crowdstrike_update_indicators","crunchbase_autocomplete","crunchbase_get_acquisition","crunchbase_get_entity","crunchbase_get_entity_card","crunchbase_get_fields_metadata","crunchbase_get_funding_round","crunchbase_get_organization","crunchbase_get_person","crunchbase_list_deleted_entities","crunchbase_search_acquisitions","crunchbase_search_entities","crunchbase_search_funding_rounds","crunchbase_search_organizations","crunchbase_search_people","cursor_add_followup","cursor_add_followup_v2","cursor_delete_agent","cursor_delete_agent_v2","cursor_download_artifact","cursor_download_artifact_v2","cursor_get_agent","cursor_get_agent_v2","cursor_get_api_key_info","cursor_get_api_key_info_v2","cursor_get_conversation","cursor_get_conversation_v2","cursor_launch_agent","cursor_launch_agent_v2","cursor_list_agents","cursor_list_agents_v2","cursor_list_artifacts","cursor_list_artifacts_v2","cursor_list_models","cursor_list_models_v2","cursor_list_repositories","cursor_list_repositories_v2","cursor_stop_agent","cursor_stop_agent_v2","dagster_delete_run","dagster_get_asset","dagster_get_run","dagster_get_run_logs","dagster_launch_run","dagster_list_assets","dagster_list_jobs","dagster_list_runs","dagster_list_schedules","dagster_list_sensors","dagster_materialize_assets","dagster_reexecute_run","dagster_report_asset_materialization","dagster_start_schedule","dagster_start_sensor","dagster_stop_schedule","dagster_stop_sensor","dagster_terminate_run","dagster_wipe_asset","databricks_cancel_all_runs","databricks_cancel_run","databricks_cancel_statement","databricks_create_cluster","databricks_create_job","databricks_create_warehouse","databricks_delete_cluster","databricks_delete_job","databricks_delete_run","databricks_delete_warehouse","databricks_edit_cluster","databricks_edit_warehouse","databricks_execute_sql","databricks_genie_agent_ask","databricks_genie_agent_cancel","databricks_genie_agent_list_items","databricks_genie_ask","databricks_genie_create_space","databricks_genie_delete_conversation","databricks_genie_delete_message","databricks_genie_delete_space","databricks_genie_download_visualization","databricks_genie_execute_query","databricks_genie_get_message","databricks_genie_get_query_result","databricks_genie_get_space","databricks_genie_list_conversations","databricks_genie_list_messages","databricks_genie_list_spaces","databricks_genie_send_feedback","databricks_genie_update_space","databricks_get_cluster","databricks_get_job","databricks_get_run","databricks_get_run_output","databricks_get_statement","databricks_get_statement_chunk","databricks_get_warehouse","databricks_list_clusters","databricks_list_jobs","databricks_list_runs","databricks_list_warehouses","databricks_repair_run","databricks_reset_job","databricks_resize_cluster","databricks_restart_cluster","databricks_run_job","databricks_start_cluster","databricks_start_warehouse","databricks_stop_warehouse","databricks_submit_run","databricks_terminate_cluster","databricks_update_job","datadog_add_incident_todo","datadog_cancel_downtime","datadog_create_dashboard","datadog_create_downtime","datadog_create_event","datadog_create_incident","datadog_create_monitor","datadog_create_slo","datadog_delete_dashboard","datadog_delete_slo","datadog_get_browser_synthetics_results","datadog_get_dashboard","datadog_get_incident","datadog_get_monitor","datadog_get_security_signal","datadog_get_slo","datadog_get_slo_history","datadog_get_synthetics_results","datadog_get_synthetics_test","datadog_list_dashboards","datadog_list_downtimes","datadog_list_incidents","datadog_list_monitors","datadog_list_security_rules","datadog_list_security_signals","datadog_list_services","datadog_list_slos","datadog_list_synthetics_tests","datadog_mute_monitor","datadog_query_logs","datadog_query_timeseries","datadog_search_spans","datadog_send_logs","datadog_submit_metrics","datadog_trigger_synthetics_tests","datadog_unmute_monitor","datadog_update_incident","datadog_update_security_signal_assignee","datadog_update_security_signal_state","datadog_update_slo","datadog_update_synthetics_status","datagma_enrich_company","datagma_enrich_person","datagma_find_email","datagma_find_phone","datagma_get_credits","daytona_create_sandbox","daytona_delete_sandbox","daytona_download_file","daytona_execute_command","daytona_get_sandbox","daytona_git_clone","daytona_list_files","daytona_list_sandboxes","daytona_run_code","daytona_start_sandbox","daytona_stop_sandbox","daytona_upload_file","deployed_block_executor","deployments_deploy","deployments_get_version","deployments_list_versions","deployments_promote","deployments_undeploy","devin_append_session_tags","devin_archive_session","devin_create_session","devin_get_session","devin_get_session_tags","devin_list_session_attachments","devin_list_session_messages","devin_list_sessions","devin_replace_session_tags","devin_send_message","devin_terminate_session","discord_add_reaction","discord_archive_thread","discord_assign_role","discord_ban_member","discord_bulk_delete_messages","discord_create_channel","discord_create_invite","discord_create_role","discord_create_thread","discord_create_webhook","discord_delete_channel","discord_delete_invite","discord_delete_message","discord_delete_role","discord_delete_webhook","discord_edit_message","discord_execute_webhook","discord_get_channel","discord_get_invite","discord_get_member","discord_get_messages","discord_get_pinned_messages","discord_get_server","discord_get_user","discord_get_webhook","discord_join_thread","discord_kick_member","discord_leave_thread","discord_list_channels","discord_list_roles","discord_pin_message","discord_remove_reaction","discord_remove_role","discord_send_message","discord_unban_member","discord_unpin_message","discord_update_channel","discord_update_member","discord_update_role","docusign_create_from_template","docusign_download_document","docusign_get_envelope","docusign_list_envelopes","docusign_list_recipients","docusign_list_templates","docusign_send_envelope","docusign_void_envelope","downdetector_get_company","downdetector_get_company_attribution","downdetector_get_company_baseline","downdetector_get_company_events","downdetector_get_company_incidents","downdetector_get_company_indicators","downdetector_get_company_last_15","downdetector_get_company_status","downdetector_get_provider","downdetector_get_reports","downdetector_get_site_companies","downdetector_list_categories","downdetector_list_incidents","downdetector_list_sites","downdetector_search_companies","dropbox_copy","dropbox_create_folder","dropbox_create_shared_link","dropbox_delete","dropbox_download","dropbox_download_v2","dropbox_get_metadata","dropbox_list_folder","dropbox_list_revisions","dropbox_list_shared_links","dropbox_move","dropbox_restore","dropbox_search","dropbox_upload","dropcontact_enrich_contact","dspy_chain_of_thought","dspy_predict","dspy_react","dub_bulk_create_links","dub_bulk_delete_links","dub_bulk_update_links","dub_create_link","dub_create_tag","dub_delete_link","dub_get_analytics","dub_get_events","dub_get_link","dub_get_links_count","dub_get_qr_code","dub_get_qr_code_v2","dub_list_domains","dub_list_folders","dub_list_links","dub_list_tags","dub_update_link","dub_upsert_link","duckduckgo_search","dynamodb_delete","dynamodb_get","dynamodb_introspect","dynamodb_put","dynamodb_query","dynamodb_scan","dynamodb_update","dynatrace_add_problem_comment","dynatrace_add_tags","dynatrace_close_problem","dynatrace_create_settings_object","dynatrace_create_slo","dynatrace_delete_problem_comment","dynatrace_delete_settings_object","dynatrace_delete_slo","dynatrace_delete_tag","dynatrace_execute_synthetic_monitors","dynatrace_get_attack","dynatrace_get_audit_logs","dynatrace_get_entity","dynatrace_get_event","dynatrace_get_metric","dynatrace_get_problem","dynatrace_get_problem_comment","dynatrace_get_security_problem","dynatrace_get_settings_object","dynatrace_get_slo","dynatrace_get_synthetic_batch","dynatrace_ingest_event","dynatrace_ingest_logs","dynatrace_ingest_metrics","dynatrace_list_attacks","dynatrace_list_entities","dynatrace_list_entity_types","dynatrace_list_events","dynatrace_list_metrics","dynatrace_list_problem_comments","dynatrace_list_problems","dynatrace_list_remediation_items","dynatrace_list_security_problems","dynatrace_list_settings_objects","dynatrace_list_settings_schemas","dynatrace_list_slos","dynatrace_list_synthetic_monitors","dynatrace_list_tags","dynatrace_mute_security_problem","dynatrace_mute_security_problems","dynatrace_query_metrics","dynatrace_search_logs","dynatrace_unmute_security_problem","dynatrace_unmute_security_problems","dynatrace_update_problem_comment","dynatrace_update_settings_object","dynatrace_update_slo","ec2_allocate_address","ec2_associate_address","ec2_authorize_security_group_ingress","ec2_create_snapshot","ec2_create_tags","ec2_delete_snapshot","ec2_delete_tags","ec2_delete_volume","ec2_describe_addresses","ec2_describe_availability_zones","ec2_describe_images","ec2_describe_instance_status","ec2_describe_instances","ec2_describe_internet_gateways","ec2_describe_key_pairs","ec2_describe_nat_gateways","ec2_describe_network_acls","ec2_describe_network_interfaces","ec2_describe_regions","ec2_describe_route_tables","ec2_describe_security_groups","ec2_describe_snapshots","ec2_describe_subnets","ec2_describe_volumes","ec2_describe_vpc_endpoints","ec2_describe_vpc_peering_connections","ec2_describe_vpcs","ec2_disassociate_address","ec2_reboot_instances","ec2_release_address","ec2_revoke_security_group_ingress","ec2_start_instances","ec2_stop_instances","ec2_terminate_instances","elasticsearch_bulk","elasticsearch_cluster_health","elasticsearch_cluster_stats","elasticsearch_count","elasticsearch_create_index","elasticsearch_delete_document","elasticsearch_delete_index","elasticsearch_get_document","elasticsearch_get_index","elasticsearch_index_document","elasticsearch_list_indices","elasticsearch_search","elasticsearch_update_document","elevenlabs_audio_isolation","elevenlabs_edit_voice_settings","elevenlabs_get_user","elevenlabs_get_voice","elevenlabs_get_voice_settings","elevenlabs_list_models","elevenlabs_list_voices","elevenlabs_sound_effects","elevenlabs_speech_to_speech","elevenlabs_tts","emailbison_attach_leads_to_campaign","emailbison_attach_tags_to_leads","emailbison_create_campaign","emailbison_create_lead","emailbison_create_tag","emailbison_get_lead","emailbison_list_campaigns","emailbison_list_leads","emailbison_list_replies","emailbison_list_tags","emailbison_update_campaign","emailbison_update_campaign_status","emailbison_update_lead","embeddings_cohere","embeddings_gemini","embeddings_mistral","embeddings_ollama","embeddings_openai","embeddings_openrouter","enrich_check_credits","enrich_company_funding","enrich_company_lookup","enrich_company_revenue","enrich_disposable_email_check","enrich_email_to_ip","enrich_email_to_person_lite","enrich_email_to_phone","enrich_email_to_profile","enrich_find_email","enrich_get_post_details","enrich_ip_to_company","enrich_linkedin_profile","enrich_linkedin_to_personal_email","enrich_linkedin_to_work_email","enrich_phone_finder","enrich_reverse_hash_lookup","enrich_sales_pointer_people","enrich_search_company","enrich_search_company_activities","enrich_search_company_employees","enrich_search_jobs","enrich_search_logo","enrich_search_people","enrich_search_people_activities","enrich_search_post_comments","enrich_search_post_comments_by_url","enrich_search_post_reactions","enrich_search_post_reactions_by_url","enrich_search_posts","enrich_search_similar_companies","enrich_verify_email","enrichment_run","enrow_find_email","enrow_verify_email","exa_agent","exa_answer","exa_find_similar_links","exa_get_contents","exa_search","extend_parser","extend_parser_v2","fathom_get_summary","fathom_get_transcript","fathom_list_meeting_types","fathom_list_meetings","fathom_list_team_members","fathom_list_teams","file_append","file_compress","file_create_folder","file_decompress","file_delete_folder","file_edit","file_fetch","file_get","file_get_content","file_list","file_manage_sharing","file_move","file_parser","file_parser_v2","file_parser_v3","file_read","file_restore_folder","file_search","file_update_folder","file_write","findymail_find_email_from_linkedin","findymail_find_email_from_name","findymail_find_emails_by_domain","findymail_find_employees","findymail_find_phone","findymail_get_company","findymail_get_credits","findymail_lookup_technologies","findymail_reverse_email_lookup","findymail_search_technologies","findymail_verify_email","firecrawl_agent","firecrawl_batch_scrape","firecrawl_batch_scrape_status","firecrawl_cancel_crawl","firecrawl_crawl","firecrawl_crawl_status","firecrawl_credit_usage","firecrawl_extract","firecrawl_extract_status","firecrawl_map","firecrawl_parse","firecrawl_scrape","firecrawl_search","fireflies_add_to_live_meeting","fireflies_create_bite","fireflies_delete_transcript","fireflies_get_transcript","fireflies_get_user","fireflies_list_bites","fireflies_list_contacts","fireflies_list_transcripts","fireflies_list_users","fireflies_upload_audio","fivetran_cancel_transformation","fivetran_create_connect_card","fivetran_create_connection","fivetran_create_destination","fivetran_create_group","fivetran_delete_connection","fivetran_get_account_info","fivetran_get_connection","fivetran_get_connection_schema_config","fivetran_get_connection_warnings","fivetran_get_connector_type","fivetran_get_destination","fivetran_get_group","fivetran_get_sync_history","fivetran_get_transformation","fivetran_list_connections","fivetran_list_connector_types","fivetran_list_destinations","fivetran_list_groups","fivetran_list_transformations","fivetran_list_users","fivetran_reload_connection_schema","fivetran_resync_connection","fivetran_resync_tables","fivetran_run_connection_setup_tests","fivetran_run_destination_setup_tests","fivetran_run_transformation","fivetran_sync_connection","fivetran_update_connection","fivetran_update_connection_schema","fivetran_update_connection_table","fivetran_update_schema_config","flint_create_task","flint_generate_pages","flint_get_task","function_execute","gamma_check_status","gamma_generate","gamma_generate_from_template","gamma_list_folders","gamma_list_themes","github_add_assignees","github_add_assignees_v2","github_add_labels","github_add_labels_v2","github_cancel_workflow_run","github_cancel_workflow_run_v2","github_check_star","github_check_star_v2","github_close_issue","github_close_issue_v2","github_close_pr","github_close_pr_v2","github_comment","github_comment_v2","github_compare_commits","github_compare_commits_v2","github_create_branch","github_create_branch_v2","github_create_comment_reaction","github_create_comment_reaction_v2","github_create_file","github_create_file_v2","github_create_gist","github_create_gist_v2","github_create_issue","github_create_issue_reaction","github_create_issue_reaction_v2","github_create_issue_v2","github_create_milestone","github_create_milestone_v2","github_create_pr","github_create_pr_review","github_create_pr_review_v2","github_create_pr_v2","github_create_project","github_create_project_v2","github_create_release","github_create_release_v2","github_delete_branch","github_delete_branch_v2","github_delete_comment","github_delete_comment_reaction","github_delete_comment_reaction_v2","github_delete_comment_v2","github_delete_file","github_delete_file_v2","github_delete_gist","github_delete_gist_v2","github_delete_issue_reaction","github_delete_issue_reaction_v2","github_delete_milestone","github_delete_milestone_v2","github_delete_project","github_delete_project_v2","github_delete_release","github_delete_release_v2","github_fork_gist","github_fork_gist_v2","github_fork_repo","github_fork_repo_v2","github_get_branch","github_get_branch_protection","github_get_branch_protection_v2","github_get_branch_v2","github_get_commit","github_get_commit_v2","github_get_file_content","github_get_file_content_v2","github_get_gist","github_get_gist_v2","github_get_issue","github_get_issue_v2","github_get_latest_release","github_get_latest_release_v2","github_get_milestone","github_get_milestone_v2","github_get_pr_files","github_get_pr_files_v2","github_get_project","github_get_project_v2","github_get_readme","github_get_readme_v2","github_get_release","github_get_release_v2","github_get_tree","github_get_tree_v2","github_get_workflow","github_get_workflow_run","github_get_workflow_run_v2","github_get_workflow_v2","github_issue_comment","github_issue_comment_v2","github_job_logs","github_latest_commit","github_latest_commit_v2","github_list_branches","github_list_branches_v2","github_list_commits","github_list_commits_v2","github_list_forks","github_list_forks_v2","github_list_gists","github_list_gists_v2","github_list_issue_comments","github_list_issue_comments_v2","github_list_issues","github_list_issues_v2","github_list_milestones","github_list_milestones_v2","github_list_pr_comments","github_list_pr_comments_v2","github_list_projects","github_list_projects_v2","github_list_prs","github_list_prs_v2","github_list_releases","github_list_releases_v2","github_list_review_threads","github_list_stargazers","github_list_stargazers_v2","github_list_tags","github_list_tags_v2","github_list_workflow_runs","github_list_workflow_runs_v2","github_list_workflows","github_list_workflows_v2","github_merge_pr","github_merge_pr_v2","github_pr","github_pr_v2","github_remove_label","github_remove_label_v2","github_reply_review_thread","github_repo_info","github_repo_info_v2","github_request_reviewers","github_request_reviewers_v2","github_rerun_workflow","github_rerun_workflow_v2","github_resolve_review_thread","github_search_code","github_search_code_v2","github_search_commits","github_search_commits_v2","github_search_issues","github_search_issues_v2","github_search_repos","github_search_repos_v2","github_search_users","github_search_users_v2","github_star_gist","github_star_gist_v2","github_star_repo","github_star_repo_v2","github_status_check_rollup","github_trigger_workflow","github_trigger_workflow_v2","github_unstar_gist","github_unstar_gist_v2","github_unstar_repo","github_unstar_repo_v2","github_update_branch_protection","github_update_branch_protection_v2","github_update_comment","github_update_comment_v2","github_update_file","github_update_file_v2","github_update_gist","github_update_gist_v2","github_update_issue","github_update_issue_v2","github_update_milestone","github_update_milestone_v2","github_update_pr","github_update_pr_v2","github_update_project","github_update_project_v2","github_update_release","github_update_release_v2","gitlab_activate_user","gitlab_add_member","gitlab_add_saml_group_link","gitlab_approve_access_request","gitlab_approve_merge_request","gitlab_approve_user","gitlab_ban_user","gitlab_block_user","gitlab_cancel_pipeline","gitlab_compare_branches","gitlab_create_branch","gitlab_create_file","gitlab_create_issue","gitlab_create_issue_note","gitlab_create_merge_request","gitlab_create_merge_request_note","gitlab_create_pipeline","gitlab_create_release","gitlab_create_user","gitlab_deactivate_user","gitlab_delete_branch","gitlab_delete_issue","gitlab_delete_saml_group_link","gitlab_delete_user","gitlab_delete_user_identity","gitlab_deny_access_request","gitlab_get_file","gitlab_get_group","gitlab_get_issue","gitlab_get_job_log","gitlab_get_merge_request","gitlab_get_merge_request_changes","gitlab_get_pipeline","gitlab_get_project","gitlab_invite_member","gitlab_list_access_requests","gitlab_list_branches","gitlab_list_commits","gitlab_list_groups","gitlab_list_invitations","gitlab_list_issues","gitlab_list_members","gitlab_list_merge_requests","gitlab_list_pipeline_jobs","gitlab_list_pipelines","gitlab_list_projects","gitlab_list_releases","gitlab_list_repository_tree","gitlab_list_saml_group_links","gitlab_list_user_memberships","gitlab_merge_merge_request","gitlab_play_job","gitlab_reject_user","gitlab_remove_member","gitlab_retry_pipeline","gitlab_revoke_invitation","gitlab_search_users","gitlab_unban_user","gitlab_unblock_user","gitlab_update_file","gitlab_update_invitation","gitlab_update_issue","gitlab_update_member","gitlab_update_merge_request","gitlab_update_user","gmail_add_label","gmail_add_label_v2","gmail_archive","gmail_archive_v2","gmail_create_label_v2","gmail_delete","gmail_delete_draft_v2","gmail_delete_label_v2","gmail_delete_v2","gmail_draft","gmail_draft_v2","gmail_edit_draft_v2","gmail_get_draft_v2","gmail_get_thread_v2","gmail_list_drafts_v2","gmail_list_labels_v2","gmail_list_threads_v2","gmail_mark_read","gmail_mark_read_v2","gmail_mark_unread","gmail_mark_unread_v2","gmail_move","gmail_move_v2","gmail_read","gmail_read_v2","gmail_remove_label","gmail_remove_label_v2","gmail_search","gmail_search_v2","gmail_send","gmail_send_v2","gmail_trash_thread_v2","gmail_unarchive","gmail_unarchive_v2","gmail_untrash_thread_v2","gmail_update_label_v2","gong_aggregate_activity","gong_aggregate_by_period","gong_answered_scorecards","gong_ask_anything","gong_assign_flow_prospects","gong_create_call","gong_day_by_day_activity","gong_get_brief","gong_get_call","gong_get_call_transcript","gong_get_coaching","gong_get_extensive_calls","gong_get_folder_content","gong_get_logs","gong_get_prospect_flows","gong_get_user","gong_interaction_stats","gong_list_calls","gong_list_flows","gong_list_library_folders","gong_list_scorecards","gong_list_trackers","gong_list_users","gong_list_workspaces","gong_lookup_email","gong_lookup_phone","gong_purge_email_address","gong_purge_phone_number","gong_unassign_flow_prospects","google_ads_ad_performance","google_ads_campaign_performance","google_ads_list_ad_groups","google_ads_list_campaigns","google_ads_list_customers","google_ads_search","google_appsheet_add_rows","google_appsheet_delete_rows","google_appsheet_edit_rows","google_appsheet_find_rows","google_bigquery_create_dataset","google_bigquery_create_table","google_bigquery_delete_dataset","google_bigquery_delete_table","google_bigquery_get_query_results","google_bigquery_get_table","google_bigquery_insert_rows","google_bigquery_list_datasets","google_bigquery_list_table_data","google_bigquery_list_tables","google_bigquery_query","google_books_volume_details","google_books_volume_search","google_calendar_create","google_calendar_create_calendar","google_calendar_create_calendar_v2","google_calendar_create_v2","google_calendar_delete","google_calendar_delete_calendar","google_calendar_delete_calendar_v2","google_calendar_delete_v2","google_calendar_freebusy","google_calendar_freebusy_v2","google_calendar_get","google_calendar_get_v2","google_calendar_instances","google_calendar_instances_v2","google_calendar_invite","google_calendar_invite_v2","google_calendar_list","google_calendar_list_acl","google_calendar_list_acl_v2","google_calendar_list_calendars","google_calendar_list_calendars_v2","google_calendar_list_v2","google_calendar_move","google_calendar_move_v2","google_calendar_quick_add","google_calendar_quick_add_v2","google_calendar_respond","google_calendar_respond_v2","google_calendar_share_calendar","google_calendar_share_calendar_v2","google_calendar_unshare_calendar","google_calendar_unshare_calendar_v2","google_calendar_update","google_calendar_update_acl","google_calendar_update_acl_v2","google_calendar_update_calendar","google_calendar_update_calendar_v2","google_calendar_update_v2","google_contacts_create","google_contacts_delete","google_contacts_get","google_contacts_list","google_contacts_search","google_contacts_update","google_docs_create","google_docs_create_named_range","google_docs_create_paragraph_bullets","google_docs_delete_content_range","google_docs_delete_named_range","google_docs_delete_paragraph_bullets","google_docs_insert_image","google_docs_insert_page_break","google_docs_insert_table","google_docs_insert_text","google_docs_read","google_docs_replace_text","google_docs_update_paragraph_style","google_docs_update_text_style","google_docs_write","google_drive_copy","google_drive_create_comment","google_drive_create_folder","google_drive_delete","google_drive_delete_comment","google_drive_download","google_drive_export","google_drive_get_about","google_drive_get_content","google_drive_get_file","google_drive_get_revision","google_drive_list","google_drive_list_comments","google_drive_list_permissions","google_drive_list_revisions","google_drive_move","google_drive_search","google_drive_share","google_drive_trash","google_drive_unshare","google_drive_untrash","google_drive_update","google_drive_upload","google_forms_batch_update","google_forms_create_form","google_forms_create_watch","google_forms_delete_watch","google_forms_get_form","google_forms_get_responses","google_forms_list_watches","google_forms_renew_watch","google_forms_set_publish_settings","google_groups_add_alias","google_groups_add_member","google_groups_create_group","google_groups_delete_group","google_groups_get_group","google_groups_get_member","google_groups_get_settings","google_groups_has_member","google_groups_list_aliases","google_groups_list_groups","google_groups_list_members","google_groups_remove_alias","google_groups_remove_member","google_groups_update_group","google_groups_update_member","google_groups_update_settings","google_maps_air_quality","google_maps_directions","google_maps_distance_matrix","google_maps_elevation","google_maps_geocode","google_maps_geolocate","google_maps_place_details","google_maps_places_nearby","google_maps_places_search","google_maps_pollen","google_maps_reverse_geocode","google_maps_snap_to_roads","google_maps_solar","google_maps_speed_limits","google_maps_timezone","google_maps_validate_address","google_meet_create_space","google_meet_end_conference","google_meet_get_conference_record","google_meet_get_space","google_meet_list_conference_records","google_meet_list_participants","google_pagespeed_analyze","google_search","google_sheets_append","google_sheets_append_v2","google_sheets_batch_clear_v2","google_sheets_batch_get_v2","google_sheets_batch_update_v2","google_sheets_clear_v2","google_sheets_copy_sheet_v2","google_sheets_create_spreadsheet_v2","google_sheets_delete_rows_v2","google_sheets_delete_sheet_v2","google_sheets_delete_spreadsheet_v2","google_sheets_get_spreadsheet_v2","google_sheets_read","google_sheets_read_v2","google_sheets_update","google_sheets_update_v2","google_sheets_write","google_sheets_write_v2","google_slides_add_image","google_slides_add_slide","google_slides_batch_update","google_slides_copy_presentation","google_slides_create","google_slides_create_line","google_slides_create_paragraph_bullets","google_slides_create_shape","google_slides_create_sheets_chart","google_slides_create_table","google_slides_create_video","google_slides_delete_object","google_slides_delete_paragraph_bullets","google_slides_delete_table_column","google_slides_delete_table_row","google_slides_delete_text","google_slides_duplicate_object","google_slides_export_presentation","google_slides_get_page","google_slides_get_thumbnail","google_slides_group_objects","google_slides_insert_table_columns","google_slides_insert_table_rows","google_slides_insert_text","google_slides_merge_table_cells","google_slides_read","google_slides_refresh_sheets_chart","google_slides_replace_all_shapes_with_image","google_slides_replace_all_shapes_with_sheets_chart","google_slides_replace_all_text","google_slides_replace_image","google_slides_reroute_line","google_slides_ungroup_objects","google_slides_unmerge_table_cells","google_slides_update_image_properties","google_slides_update_line_category","google_slides_update_line_properties","google_slides_update_page_element_alt_text","google_slides_update_page_element_transform","google_slides_update_page_elements_z_order","google_slides_update_page_properties","google_slides_update_paragraph_style","google_slides_update_shape_properties","google_slides_update_slide_properties","google_slides_update_slides_position","google_slides_update_table_border_properties","google_slides_update_table_cell_properties","google_slides_update_table_column_properties","google_slides_update_table_row_properties","google_slides_update_text_style","google_slides_update_video_properties","google_slides_write","google_tasks_create","google_tasks_delete","google_tasks_get","google_tasks_list","google_tasks_list_task_lists","google_tasks_update","google_translate_detect","google_translate_text","google_vault_add_held_accounts","google_vault_add_matters_permissions","google_vault_close_matters","google_vault_create_matters","google_vault_create_matters_export","google_vault_create_matters_holds","google_vault_create_saved_query","google_vault_delete_matters","google_vault_delete_matters_export","google_vault_delete_matters_holds","google_vault_delete_saved_query","google_vault_download_export_file","google_vault_list_matters","google_vault_list_matters_export","google_vault_list_matters_holds","google_vault_list_saved_queries","google_vault_remove_held_accounts","google_vault_remove_matters_permissions","google_vault_reopen_matters","google_vault_undelete_matters","google_vault_update_matters","google_vault_update_matters_holds","grafana_check_data_source_health","grafana_create_alert_rule","grafana_create_annotation","grafana_create_contact_point","grafana_create_dashboard","grafana_create_folder","grafana_delete_alert_rule","grafana_delete_annotation","grafana_delete_contact_point","grafana_delete_dashboard","grafana_delete_folder","grafana_get_alert_rule","grafana_get_alert_rule_group","grafana_get_dashboard","grafana_get_data_source","grafana_get_folder","grafana_get_health","grafana_list_alert_rules","grafana_list_annotations","grafana_list_contact_points","grafana_list_dashboards","grafana_list_data_sources","grafana_list_folders","grafana_move_folder","grafana_query_data_source","grafana_update_alert_rule","grafana_update_annotation","grafana_update_contact_point","grafana_update_dashboard","grafana_update_folder","grain_create_hook","grain_create_hook_v2","grain_delete_hook","grain_delete_hook_v2","grain_get_recording","grain_get_transcript","grain_list_hooks","grain_list_hooks_v2","grain_list_meeting_types","grain_list_recordings","grain_list_teams","grain_list_views","granola_create_webhook_endpoint","granola_delete_webhook_endpoint","granola_get_note","granola_get_transcript","granola_list_audit_events","granola_list_folders","granola_list_notes","granola_list_webhook_endpoints","granola_update_webhook_endpoint","greenhouse_apply_candidate_tag_v2","greenhouse_convert_prospect_v2","greenhouse_create_application_v2","greenhouse_create_attachment_v2","greenhouse_create_candidate_tag_v2","greenhouse_create_candidate_v2","greenhouse_create_note_v2","greenhouse_delete_application_v2","greenhouse_delete_attachment_v2","greenhouse_delete_candidate_v2","greenhouse_get_application","greenhouse_get_application_v2","greenhouse_get_candidate","greenhouse_get_candidate_v2","greenhouse_get_job","greenhouse_get_job_v2","greenhouse_get_user","greenhouse_get_user_v2","greenhouse_hire_application_v2","greenhouse_list_application_stages_v2","greenhouse_list_applications","greenhouse_list_applications_v2","greenhouse_list_applied_candidate_tags_v2","greenhouse_list_attachments_v2","greenhouse_list_candidate_educations_v2","greenhouse_list_candidate_employments_v2","greenhouse_list_candidate_tags_v2","greenhouse_list_candidates","greenhouse_list_candidates_v2","greenhouse_list_close_reasons_v2","greenhouse_list_custom_field_options_v2","greenhouse_list_custom_fields_v2","greenhouse_list_departments","greenhouse_list_departments_v2","greenhouse_list_email_templates_v2","greenhouse_list_interviews_v2","greenhouse_list_job_hiring_managers_v2","greenhouse_list_job_interview_stages_v2","greenhouse_list_job_owners_v2","greenhouse_list_job_stages","greenhouse_list_jobs","greenhouse_list_jobs_v2","greenhouse_list_notes_v2","greenhouse_list_offers_v2","greenhouse_list_offices","greenhouse_list_offices_v2","greenhouse_list_openings_v2","greenhouse_list_prospect_pool_stages_v2","greenhouse_list_prospect_pools_v2","greenhouse_list_referrers_v2","greenhouse_list_rejection_reasons_v2","greenhouse_list_scorecards_v2","greenhouse_list_sources_v2","greenhouse_list_users","greenhouse_list_users_v2","greenhouse_move_application_v2","greenhouse_reject_application_v2","greenhouse_remove_candidate_tag_v2","greenhouse_unreject_application_v2","greenhouse_update_application_v2","greenhouse_update_candidate_v2","greptile_index_repo","greptile_query","greptile_search","greptile_status","guardrails_validate","harmonic_batch_get_people","harmonic_clear_people_saved_search_net_new_results","harmonic_enrich_person","harmonic_get_company_employees","harmonic_get_email_enrichment_job","harmonic_get_email_enrichment_usage","harmonic_get_enrichment_status","harmonic_get_people_saved_search_net_new_results","harmonic_get_people_saved_search_results","harmonic_get_person","harmonic_list_people_saved_searches","harmonic_search_people_scout","harmonic_submit_email_enrichment_job","helpscout_assign_conversation","helpscout_create_conversation","helpscout_create_customer","helpscout_create_customer_thread","helpscout_create_note","helpscout_create_reply","helpscout_delete_conversation","helpscout_get_conversation","helpscout_get_current_user","helpscout_get_customer","helpscout_get_organization","helpscout_get_saved_reply","helpscout_list_conversations","helpscout_list_custom_fields","helpscout_list_customer_properties","helpscout_list_customers","helpscout_list_folders","helpscout_list_mailboxes","helpscout_list_organizations","helpscout_list_saved_replies","helpscout_list_tags","helpscout_list_teams","helpscout_list_threads","helpscout_list_users","helpscout_list_workflows","helpscout_move_conversation","helpscout_run_workflow","helpscout_set_conversation_tags","helpscout_snooze_conversation","helpscout_unassign_conversation","helpscout_unsnooze_conversation","helpscout_update_conversation_customer","helpscout_update_conversation_status","helpscout_update_conversation_subject","helpscout_update_custom_fields","helpscout_update_customer","helpscout_update_customer_properties","hex_cancel_run","hex_create_collection","hex_create_group","hex_deactivate_user","hex_delete_group","hex_get_collection","hex_get_data_connection","hex_get_group","hex_get_project","hex_get_project_runs","hex_get_queried_tables","hex_get_run_status","hex_list_collections","hex_list_data_connections","hex_list_groups","hex_list_projects","hex_list_users","hex_run_project","hex_update_collection","hex_update_group","hex_update_project","http_request","hubspot_add_list_memberships","hubspot_create_appointment","hubspot_create_association","hubspot_create_company","hubspot_create_contact","hubspot_create_deal","hubspot_create_email","hubspot_create_line_item","hubspot_create_list","hubspot_create_note","hubspot_create_ticket","hubspot_delete_association","hubspot_delete_company","hubspot_delete_contact","hubspot_delete_deal","hubspot_delete_line_item","hubspot_delete_ticket","hubspot_get_appointment","hubspot_get_association_labels","hubspot_get_cart","hubspot_get_company","hubspot_get_contact","hubspot_get_deal","hubspot_get_email","hubspot_get_line_item","hubspot_get_list","hubspot_get_list_memberships","hubspot_get_marketing_event","hubspot_get_note","hubspot_get_properties","hubspot_get_quote","hubspot_get_ticket","hubspot_get_users","hubspot_list_appointments","hubspot_list_associations","hubspot_list_carts","hubspot_list_companies","hubspot_list_contacts","hubspot_list_deals","hubspot_list_emails","hubspot_list_line_items","hubspot_list_lists","hubspot_list_marketing_events","hubspot_list_notes","hubspot_list_owners","hubspot_list_quotes","hubspot_list_tickets","hubspot_remove_list_memberships","hubspot_search_companies","hubspot_search_contacts","hubspot_search_deals","hubspot_search_emails","hubspot_search_line_items","hubspot_search_notes","hubspot_search_quotes","hubspot_search_tickets","hubspot_update_appointment","hubspot_update_company","hubspot_update_contact","hubspot_update_deal","hubspot_update_line_item","hubspot_update_ticket","huggingface_chat","hunter_companies_find","hunter_discover","hunter_domain_search","hunter_email_count","hunter_email_finder","hunter_email_verifier","iam_add_user_to_group","iam_attach_role_policy","iam_attach_user_policy","iam_create_access_key","iam_create_role","iam_create_user","iam_delete_access_key","iam_delete_role","iam_delete_user","iam_detach_role_policy","iam_detach_user_policy","iam_get_policy","iam_get_role","iam_get_user","iam_list_access_keys","iam_list_attached_role_policies","iam_list_attached_user_policies","iam_list_groups","iam_list_policies","iam_list_roles","iam_list_users","iam_remove_user_from_group","iam_simulate_principal_policy","iam_update_access_key","icypeas_find_email","icypeas_verify_email","identity_center_check_assignment_deletion_status","identity_center_check_assignment_status","identity_center_create_account_assignment","identity_center_delete_account_assignment","identity_center_describe_account","identity_center_describe_group","identity_center_describe_user","identity_center_get_group","identity_center_get_user","identity_center_list_account_assignments","identity_center_list_accounts","identity_center_list_assignments_for_account","identity_center_list_group_memberships","identity_center_list_groups","identity_center_list_instances","identity_center_list_permission_sets","image_generate","incidentio_actions_create","incidentio_actions_list","incidentio_actions_show","incidentio_actions_update","incidentio_alert_events_create","incidentio_alerts_list","incidentio_alerts_resolve","incidentio_alerts_show","incidentio_catalog_entries_list","incidentio_catalog_types_list","incidentio_custom_fields_create","incidentio_custom_fields_delete","incidentio_custom_fields_list","incidentio_custom_fields_show","incidentio_custom_fields_update","incidentio_escalation_paths_create","incidentio_escalation_paths_delete","incidentio_escalation_paths_list","incidentio_escalation_paths_show","incidentio_escalation_paths_update","incidentio_escalations_cancel","incidentio_escalations_create","incidentio_escalations_list","incidentio_escalations_show","incidentio_follow_ups_create","incidentio_follow_ups_list","incidentio_follow_ups_show","incidentio_follow_ups_update","incidentio_incident_alerts_list","incidentio_incident_memberships_create","incidentio_incident_memberships_revoke","incidentio_incident_participants_list","incidentio_incident_roles_create","incidentio_incident_roles_delete","incidentio_incident_roles_list","incidentio_incident_roles_show","incidentio_incident_roles_update","incidentio_incident_statuses_list","incidentio_incident_timestamps_list","incidentio_incident_timestamps_show","incidentio_incident_types_list","incidentio_incident_updates_list","incidentio_incidents_create","incidentio_incidents_list","incidentio_incidents_show","incidentio_incidents_update","incidentio_on_call_now","incidentio_schedule_entries_list","incidentio_schedule_overrides_create","incidentio_schedule_overrides_list","incidentio_schedules_create","incidentio_schedules_delete","incidentio_schedules_list","incidentio_schedules_show","incidentio_schedules_update","incidentio_severities_list","incidentio_teams_list","incidentio_teams_show","incidentio_users_list","incidentio_users_show","incidentio_workflows_create","incidentio_workflows_delete","incidentio_workflows_list","incidentio_workflows_show","incidentio_workflows_update","infisical_create_secret","infisical_delete_secret","infisical_get_secret","infisical_list_secrets","infisical_update_secret","instagram_delete_comment","instagram_download_media","instagram_get_account_insights","instagram_get_container_status","instagram_get_conversation_messages","instagram_get_media","instagram_get_media_insights","instagram_get_message","instagram_get_profile","instagram_get_publishing_limit","instagram_hide_comment","instagram_list_comments","instagram_list_conversations","instagram_list_media","instagram_list_stories","instagram_private_reply","instagram_publish_carousel","instagram_publish_image","instagram_publish_reel","instagram_publish_story","instagram_publish_video","instagram_reply_to_comment","instagram_send_text_message","instagram_set_comments_enabled","instantly_activate_campaign","instantly_create_campaign","instantly_create_lead","instantly_create_lead_list","instantly_delete_campaign","instantly_delete_leads","instantly_get_lead","instantly_list_campaigns","instantly_list_emails","instantly_list_lead_lists","instantly_list_leads","instantly_patch_campaign","instantly_patch_lead","instantly_pause_campaign","instantly_reply_to_email","instantly_update_lead_interest_status","intercom_assign_conversation_v2","intercom_attach_contact_to_company_v2","intercom_close_conversation_v2","intercom_create_company","intercom_create_company_v2","intercom_create_contact","intercom_create_contact_v2","intercom_create_event_v2","intercom_create_message","intercom_create_message_v2","intercom_create_note_v2","intercom_create_tag_v2","intercom_create_ticket","intercom_create_ticket_v2","intercom_delete_contact","intercom_delete_contact_v2","intercom_detach_contact_from_company_v2","intercom_get_company","intercom_get_company_v2","intercom_get_contact","intercom_get_contact_v2","intercom_get_conversation","intercom_get_conversation_v2","intercom_get_ticket","intercom_get_ticket_v2","intercom_list_admins_v2","intercom_list_companies","intercom_list_companies_v2","intercom_list_contacts","intercom_list_contacts_v2","intercom_list_conversations","intercom_list_conversations_v2","intercom_list_tags_v2","intercom_open_conversation_v2","intercom_reply_conversation","intercom_reply_conversation_v2","intercom_search_contacts","intercom_search_contacts_v2","intercom_search_conversations","intercom_search_conversations_v2","intercom_snooze_conversation_v2","intercom_tag_contact_v2","intercom_tag_conversation_v2","intercom_untag_contact_v2","intercom_update_contact","intercom_update_contact_v2","intercom_update_ticket_v2","intune_get_compliance_policy","intune_get_detected_app","intune_get_device","intune_get_device_configuration","intune_list_app_devices","intune_list_compliance_policies","intune_list_compliance_policy_device_statuses","intune_list_detected_apps","intune_list_device_configurations","intune_list_devices","intune_reboot_device","intune_remote_lock_device","intune_retire_device","intune_sync_device","jina_read_url","jina_search","jira_add_attachment","jira_add_comment","jira_add_watcher","jira_add_worklog","jira_assign_issue","jira_bulk_read","jira_create_issue_link","jira_delete_attachment","jira_delete_comment","jira_delete_issue","jira_delete_issue_link","jira_delete_worklog","jira_get_attachments","jira_get_comments","jira_get_fields","jira_get_project","jira_get_transitions","jira_get_users","jira_get_worklogs","jira_list_issue_types","jira_list_projects","jira_remove_watcher","jira_retrieve","jira_search_issues","jira_search_users","jira_transition_issue","jira_update","jira_update_comment","jira_update_worklog","jira_write","jotform_add_label_resources","jotform_clone_form","jotform_create_form","jotform_create_label","jotform_create_question","jotform_create_questions","jotform_create_report","jotform_create_submission","jotform_create_submissions","jotform_create_webhook","jotform_delete_form","jotform_delete_label","jotform_delete_question","jotform_delete_report","jotform_delete_submission","jotform_delete_webhook","jotform_get_form","jotform_get_form_properties","jotform_get_history","jotform_get_label","jotform_get_question","jotform_get_report","jotform_get_settings","jotform_get_submission","jotform_get_usage","jotform_get_user","jotform_list_form_files","jotform_list_form_reports","jotform_list_form_submissions","jotform_list_forms","jotform_list_label_resources","jotform_list_labels","jotform_list_questions","jotform_list_reports","jotform_list_submissions","jotform_list_subusers","jotform_list_webhooks","jotform_remove_label_resources","jotform_update_form_properties","jotform_update_label","jotform_update_question","jotform_update_settings","jotform_update_submission","jsm_add_comment","jsm_add_customer","jsm_add_organization","jsm_add_participants","jsm_answer_approval","jsm_attach_form","jsm_copy_forms","jsm_create_object","jsm_create_organization","jsm_create_request","jsm_delete_form","jsm_delete_object","jsm_externalise_form","jsm_get_approvals","jsm_get_comments","jsm_get_customers","jsm_get_form","jsm_get_form_answers","jsm_get_form_structure","jsm_get_form_templates","jsm_get_issue_forms","jsm_get_object","jsm_get_object_schema","jsm_get_object_type_attributes","jsm_get_organizations","jsm_get_participants","jsm_get_queues","jsm_get_request","jsm_get_request_type_fields","jsm_get_request_types","jsm_get_requests","jsm_get_service_desks","jsm_get_sla","jsm_get_transitions","jsm_internalise_form","jsm_list_object_schemas","jsm_list_object_types","jsm_reopen_form","jsm_save_form_answers","jsm_search_objects_aql","jsm_submit_form","jsm_transition_request","jsm_update_object","jupyter_copy_content","jupyter_create_file","jupyter_create_session","jupyter_delete_content","jupyter_delete_session","jupyter_get_content","jupyter_get_content_v2","jupyter_interrupt_kernel","jupyter_list_contents","jupyter_list_kernels","jupyter_list_kernelspecs","jupyter_list_sessions","jupyter_rename_content","jupyter_restart_kernel","jupyter_start_kernel","jupyter_stop_kernel","jupyter_upload_file","kalshi_amend_order","kalshi_amend_order_v2","kalshi_cancel_order","kalshi_cancel_order_v2","kalshi_create_order","kalshi_create_order_v2","kalshi_get_balance","kalshi_get_balance_v2","kalshi_get_candlesticks","kalshi_get_candlesticks_v2","kalshi_get_event","kalshi_get_event_candlesticks","kalshi_get_event_candlesticks_v2","kalshi_get_event_v2","kalshi_get_events","kalshi_get_events_v2","kalshi_get_exchange_announcements","kalshi_get_exchange_announcements_v2","kalshi_get_exchange_schedule","kalshi_get_exchange_schedule_v2","kalshi_get_exchange_status","kalshi_get_exchange_status_v2","kalshi_get_fills","kalshi_get_fills_v2","kalshi_get_market","kalshi_get_market_v2","kalshi_get_markets","kalshi_get_markets_v2","kalshi_get_order","kalshi_get_order_v2","kalshi_get_orderbook","kalshi_get_orderbook_v2","kalshi_get_orders","kalshi_get_orders_v2","kalshi_get_positions","kalshi_get_positions_v2","kalshi_get_series_by_ticker","kalshi_get_series_by_ticker_v2","kalshi_get_series_list","kalshi_get_series_list_v2","kalshi_get_settlements","kalshi_get_settlements_v2","kalshi_get_trades","kalshi_get_trades_v2","ketch_get_consent","ketch_get_subscriptions","ketch_invoke_right","ketch_set_consent","ketch_set_subscriptions","knowledge_create_document","knowledge_delete_chunk","knowledge_delete_document","knowledge_get_connector","knowledge_get_document","knowledge_list_chunks","knowledge_list_connectors","knowledge_list_documents","knowledge_list_tags","knowledge_search","knowledge_trigger_sync","knowledge_update_chunk","knowledge_upload_chunk","knowledge_upsert_document","lambda_add_permission","lambda_create_alias","lambda_create_event_source_mapping","lambda_create_function","lambda_create_function_url_config","lambda_delete_alias","lambda_delete_event_source_mapping","lambda_delete_function","lambda_delete_function_concurrency","lambda_delete_function_event_invoke_config","lambda_delete_function_url_config","lambda_delete_provisioned_concurrency_config","lambda_get_account_settings","lambda_get_alias","lambda_get_event_source_mapping","lambda_get_function","lambda_get_function_concurrency","lambda_get_function_configuration","lambda_get_function_event_invoke_config","lambda_get_function_recursion_config","lambda_get_function_url_config","lambda_get_layer_version","lambda_get_policy","lambda_get_provisioned_concurrency_config","lambda_get_runtime_management_config","lambda_invoke","lambda_list_aliases","lambda_list_event_source_mappings","lambda_list_function_event_invoke_configs","lambda_list_function_url_configs","lambda_list_functions","lambda_list_layer_versions","lambda_list_layers","lambda_list_provisioned_concurrency_configs","lambda_list_tags","lambda_list_versions_by_function","lambda_publish_version","lambda_put_function_concurrency","lambda_put_function_event_invoke_config","lambda_put_function_recursion_config","lambda_put_provisioned_concurrency_config","lambda_put_runtime_management_config","lambda_remove_permission","lambda_tag_resource","lambda_untag_resource","lambda_update_alias","lambda_update_event_source_mapping","lambda_update_function_code","lambda_update_function_configuration","lambda_update_function_url_config","langsmith_create_feedback","langsmith_create_run","langsmith_create_runs_batch","langsmith_get_run","langsmith_update_run","latex_compile","latex_get_package","latex_list_fonts","latex_search_packages","launchdarkly_create_flag","launchdarkly_delete_flag","launchdarkly_get_audit_log","launchdarkly_get_flag","launchdarkly_get_flag_status","launchdarkly_list_environments","launchdarkly_list_flags","launchdarkly_list_members","launchdarkly_list_projects","launchdarkly_list_segments","launchdarkly_toggle_flag","launchdarkly_update_flag","leadmagic_company_search","leadmagic_email_to_profile","leadmagic_find_email","leadmagic_find_mobile","leadmagic_get_credits","leadmagic_profile_search","leadmagic_profile_to_email","leadmagic_role_finder","leadmagic_validate_email","lemlist_get_activities","lemlist_get_lead","lemlist_send_email","linear_add_label_to_issue","linear_add_label_to_project","linear_archive_issue","linear_archive_label","linear_archive_project","linear_create_attachment","linear_create_comment","linear_create_customer","linear_create_customer_request","linear_create_customer_status","linear_create_customer_tier","linear_create_cycle","linear_create_favorite","linear_create_issue","linear_create_issue_relation","linear_create_label","linear_create_project","linear_create_project_label","linear_create_project_milestone","linear_create_project_status","linear_create_project_update","linear_create_workflow_state","linear_delete_attachment","linear_delete_comment","linear_delete_customer","linear_delete_customer_status","linear_delete_customer_tier","linear_delete_issue","linear_delete_issue_relation","linear_delete_project","linear_delete_project_label","linear_delete_project_milestone","linear_delete_project_status","linear_get_active_cycle","linear_get_customer","linear_get_cycle","linear_get_issue","linear_get_project","linear_get_viewer","linear_list_attachments","linear_list_comments","linear_list_customer_requests","linear_list_customer_statuses","linear_list_customer_tiers","linear_list_customers","linear_list_cycles","linear_list_favorites","linear_list_issue_relations","linear_list_labels","linear_list_notifications","linear_list_project_labels","linear_list_project_milestones","linear_list_project_statuses","linear_list_project_updates","linear_list_projects","linear_list_teams","linear_list_users","linear_list_workflow_states","linear_merge_customers","linear_read_issues","linear_remove_label_from_issue","linear_remove_label_from_project","linear_search_issues","linear_unarchive_issue","linear_update_attachment","linear_update_comment","linear_update_customer","linear_update_customer_request","linear_update_customer_status","linear_update_customer_tier","linear_update_issue","linear_update_label","linear_update_notification","linear_update_project","linear_update_project_label","linear_update_project_milestone","linear_update_project_status","linear_update_workflow_state","linkedin_get_profile","linkedin_share_post","linkup_search","linq_add_participant","linq_check_imessage","linq_check_rcs","linq_create_attachment","linq_create_chat","linq_create_contact_card","linq_create_webhook_subscription","linq_delete_attachment","linq_delete_message","linq_delete_webhook_subscription","linq_edit_message","linq_get_attachment","linq_get_chat","linq_get_contact_card","linq_get_message","linq_get_webhook_subscription","linq_leave_chat","linq_list_chats","linq_list_messages","linq_list_phone_numbers","linq_list_thread","linq_list_webhook_events","linq_list_webhook_subscriptions","linq_mark_chat_read","linq_react_to_message","linq_remove_participant","linq_send_message","linq_send_voice_memo","linq_share_contact_card","linq_start_typing","linq_stop_typing","linq_update_chat","linq_update_contact_card","linq_update_webhook_subscription","llm_chat","logfire_get_token_info","logfire_get_trace","logfire_query","logfire_search_records","logrocket_create_release","logrocket_get_audit_logs","logrocket_get_highlights","logrocket_identify_user","logrocket_list_exported_sessions","logrocket_request_highlights","logs_get","logs_get_execution","logs_get_run_details","logs_query","logs_query_runs","loops_check_contact_suppression","loops_create_contact","loops_create_contact_property","loops_delete_contact","loops_find_contact","loops_get_transactional_email","loops_list_contact_properties","loops_list_mailing_lists","loops_list_transactional_emails","loops_remove_contact_suppression","loops_send_event","loops_send_transactional_email","loops_update_contact","luma_add_guests","luma_cancel_event","luma_create_event","luma_get_event","luma_get_guest","luma_get_guests","luma_list_events","luma_lookup_event","luma_send_invites","luma_update_event","luma_update_guest_status","mailchimp_add_member","mailchimp_add_member_tags","mailchimp_add_or_update_member","mailchimp_add_segment_member","mailchimp_add_subscriber_to_automation","mailchimp_archive_member","mailchimp_create_audience","mailchimp_create_batch_operation","mailchimp_create_campaign","mailchimp_create_interest","mailchimp_create_interest_category","mailchimp_create_landing_page","mailchimp_create_merge_field","mailchimp_create_segment","mailchimp_create_template","mailchimp_delete_audience","mailchimp_delete_batch_operation","mailchimp_delete_campaign","mailchimp_delete_interest","mailchimp_delete_interest_category","mailchimp_delete_landing_page","mailchimp_delete_member","mailchimp_delete_merge_field","mailchimp_delete_segment","mailchimp_delete_template","mailchimp_get_audience","mailchimp_get_audiences","mailchimp_get_automation","mailchimp_get_automations","mailchimp_get_batch_operation","mailchimp_get_batch_operations","mailchimp_get_campaign","mailchimp_get_campaign_content","mailchimp_get_campaign_report","mailchimp_get_campaign_reports","mailchimp_get_campaigns","mailchimp_get_interest","mailchimp_get_interest_categories","mailchimp_get_interest_category","mailchimp_get_interests","mailchimp_get_landing_page","mailchimp_get_landing_pages","mailchimp_get_member","mailchimp_get_member_tags","mailchimp_get_members","mailchimp_get_merge_field","mailchimp_get_merge_fields","mailchimp_get_segment","mailchimp_get_segment_members","mailchimp_get_segments","mailchimp_get_template","mailchimp_get_templates","mailchimp_pause_automation","mailchimp_publish_landing_page","mailchimp_remove_member_tags","mailchimp_remove_segment_member","mailchimp_replicate_campaign","mailchimp_schedule_campaign","mailchimp_send_campaign","mailchimp_set_campaign_content","mailchimp_start_automation","mailchimp_unarchive_member","mailchimp_unpublish_landing_page","mailchimp_unschedule_campaign","mailchimp_update_audience","mailchimp_update_campaign","mailchimp_update_interest","mailchimp_update_interest_category","mailchimp_update_landing_page","mailchimp_update_member","mailchimp_update_merge_field","mailchimp_update_segment","mailchimp_update_template","mailgun_add_list_member","mailgun_create_mailing_list","mailgun_get_domain","mailgun_get_mailing_list","mailgun_get_message","mailgun_list_domains","mailgun_list_messages","mailgun_send_message","managed_agent_archive_session","managed_agent_create_session","managed_agent_delete_session","managed_agent_get_session","managed_agent_interrupt_session","managed_agent_list_events","managed_agent_respond_custom_tool","managed_agent_respond_tool_confirmation","managed_agent_run_session","managed_agent_send_message","managed_agent_update_session","manageengine_sdp_add_change_note","manageengine_sdp_add_problem_note","manageengine_sdp_add_request_note","manageengine_sdp_create_asset","manageengine_sdp_create_change","manageengine_sdp_create_problem","manageengine_sdp_create_request","manageengine_sdp_create_solution","manageengine_sdp_delete_asset","manageengine_sdp_delete_change","manageengine_sdp_delete_problem","manageengine_sdp_delete_request","manageengine_sdp_delete_solution","manageengine_sdp_get_asset","manageengine_sdp_get_change","manageengine_sdp_get_problem","manageengine_sdp_get_request","manageengine_sdp_get_solution","manageengine_sdp_list_assets","manageengine_sdp_list_change_notes","manageengine_sdp_list_changes","manageengine_sdp_list_problem_notes","manageengine_sdp_list_problems","manageengine_sdp_list_request_notes","manageengine_sdp_list_requests","manageengine_sdp_list_solutions","manageengine_sdp_update_asset","manageengine_sdp_update_change","manageengine_sdp_update_problem","manageengine_sdp_update_request","manageengine_sdp_update_solution","mcp_list_operations","mcp_run_operation","mem0_add_memories","mem0_get_memories","mem0_search_memories","memory_add","memory_delete","memory_get","memory_get_all","microsoft_ad_add_directory_role_member","microsoft_ad_add_group_member","microsoft_ad_add_user_app_role_assignment","microsoft_ad_assign_license","microsoft_ad_create_group","microsoft_ad_create_user","microsoft_ad_delete_group","microsoft_ad_delete_user","microsoft_ad_get_conditional_access_policy","microsoft_ad_get_device","microsoft_ad_get_group","microsoft_ad_get_user","microsoft_ad_list_authentication_methods","microsoft_ad_list_conditional_access_policies","microsoft_ad_list_devices","microsoft_ad_list_directory_audits","microsoft_ad_list_directory_role_members","microsoft_ad_list_directory_roles","microsoft_ad_list_group_members","microsoft_ad_list_groups","microsoft_ad_list_service_principal_app_role_assignments","microsoft_ad_list_service_principals","microsoft_ad_list_sign_ins","microsoft_ad_list_subscribed_skus","microsoft_ad_list_user_app_role_assignments","microsoft_ad_list_user_devices","microsoft_ad_list_user_licenses","microsoft_ad_list_users","microsoft_ad_remove_directory_role_member","microsoft_ad_remove_group_member","microsoft_ad_remove_user_app_role_assignment","microsoft_ad_reset_password","microsoft_ad_revoke_sign_in_sessions","microsoft_ad_set_password","microsoft_ad_update_group","microsoft_ad_update_user","microsoft_dataverse_associate","microsoft_dataverse_create_multiple","microsoft_dataverse_create_record","microsoft_dataverse_delete_record","microsoft_dataverse_disassociate","microsoft_dataverse_download_file","microsoft_dataverse_download_file_v2","microsoft_dataverse_execute_action","microsoft_dataverse_execute_function","microsoft_dataverse_fetchxml_query","microsoft_dataverse_get_entity_metadata","microsoft_dataverse_get_record","microsoft_dataverse_list_records","microsoft_dataverse_search","microsoft_dataverse_update_multiple","microsoft_dataverse_update_record","microsoft_dataverse_upload_file","microsoft_dataverse_upsert_record","microsoft_dataverse_whoami","microsoft_dynamics_365_close_case","microsoft_dynamics_365_close_opportunity","microsoft_dynamics_365_create_record","microsoft_dynamics_365_get_record","microsoft_dynamics_365_list_records","microsoft_dynamics_365_qualify_lead","microsoft_dynamics_365_search_records","microsoft_dynamics_365_update_record","microsoft_excel_calculate","microsoft_excel_clear_range","microsoft_excel_close_session","microsoft_excel_create_session","microsoft_excel_create_table","microsoft_excel_delete_table","microsoft_excel_delete_table_row","microsoft_excel_delete_worksheet","microsoft_excel_format_range","microsoft_excel_get_table","microsoft_excel_get_table_row","microsoft_excel_get_worksheet","microsoft_excel_list_table_rows","microsoft_excel_list_tables","microsoft_excel_list_worksheets","microsoft_excel_read","microsoft_excel_read_v2","microsoft_excel_refresh_session","microsoft_excel_sort_range","microsoft_excel_table_add","microsoft_excel_update_table","microsoft_excel_update_table_row","microsoft_excel_update_worksheet","microsoft_excel_worksheet_add","microsoft_excel_write","microsoft_excel_write_v2","microsoft_planner_create_bucket","microsoft_planner_create_plan","microsoft_planner_create_task","microsoft_planner_delete_bucket","microsoft_planner_delete_plan","microsoft_planner_delete_task","microsoft_planner_get_plan_details","microsoft_planner_get_task_details","microsoft_planner_list_buckets","microsoft_planner_list_plans","microsoft_planner_read_bucket","microsoft_planner_read_plan","microsoft_planner_read_task","microsoft_planner_update_bucket","microsoft_planner_update_plan","microsoft_planner_update_plan_details","microsoft_planner_update_task","microsoft_planner_update_task_details","microsoft_teams_delete_channel_message","microsoft_teams_delete_chat_message","microsoft_teams_get_message","microsoft_teams_list_channel_members","microsoft_teams_list_channels","microsoft_teams_list_chat_members","microsoft_teams_list_chats","microsoft_teams_list_team_members","microsoft_teams_list_teams","microsoft_teams_read_channel","microsoft_teams_read_chat","microsoft_teams_reply_to_message","microsoft_teams_set_reaction","microsoft_teams_unset_reaction","microsoft_teams_update_channel_message","microsoft_teams_update_chat_message","microsoft_teams_write_channel","microsoft_teams_write_chat","microsoft_word_append","microsoft_word_create","microsoft_word_create_from_template","microsoft_word_export_pdf","microsoft_word_list","microsoft_word_read","microsoft_word_replace_text","microsoft_word_update","millionverifier_get_credits","millionverifier_verify_email","mintlify_create_agent_job","mintlify_create_assistant_message","mintlify_detect_ai_prose","mintlify_get_agent_job","mintlify_get_assistant_caller_stats","mintlify_get_assistant_conversations","mintlify_get_feedback","mintlify_get_feedback_by_page","mintlify_get_page_content","mintlify_get_searches","mintlify_get_update_status","mintlify_get_views","mintlify_get_visitors","mintlify_search","mintlify_send_agent_message","mintlify_trigger_automation","mintlify_trigger_preview","mintlify_trigger_update","mistral_parser","mistral_parser_v2","mistral_parser_v3","modal_call_function","modal_chat_completion","modal_list_models","monday_archive_item","monday_change_column_value","monday_create_board","monday_create_column","monday_create_group","monday_create_item","monday_create_subitem","monday_create_update","monday_delete_item","monday_duplicate_item","monday_get_board","monday_get_groups","monday_get_item","monday_get_items","monday_list_boards","monday_move_item_to_group","monday_search_items","monday_update_item","mongodb_delete","mongodb_execute","mongodb_insert","mongodb_introspect","mongodb_query","mongodb_update","mssql_delete","mssql_execute","mssql_insert","mssql_introspect","mssql_query","mssql_update","mysql_delete","mysql_execute","mysql_insert","mysql_introspect","mysql_query","mysql_update","neo4j_create","neo4j_delete","neo4j_execute","neo4j_introspect","neo4j_merge","neo4j_query","neo4j_update","netsuite_attach_record","netsuite_batch_create_records","netsuite_batch_delete_records","netsuite_batch_get_records","netsuite_batch_update_records","netsuite_batch_upsert_records","netsuite_create_record","netsuite_delete_record","netsuite_detach_record","netsuite_execute_action","netsuite_execute_dataset","netsuite_execute_suiteql","netsuite_get_async_result","netsuite_get_async_status","netsuite_get_governance_limits","netsuite_get_record","netsuite_get_record_form","netsuite_get_record_metadata","netsuite_get_select_options","netsuite_get_server_time","netsuite_get_subresource","netsuite_list_datasets","netsuite_list_record_types","netsuite_list_records","netsuite_transform_record","netsuite_update_record","netsuite_upsert_record","neverbounce_get_credits","neverbounce_verify_email","new_relic_create_deployment_event","new_relic_get_entity","new_relic_nrql_query","new_relic_search_entities","notion_add_database_row","notion_add_database_row_v2","notion_append_blocks","notion_append_blocks_v2","notion_create_comment","notion_create_comment_v2","notion_create_database","notion_create_database_v2","notion_create_page","notion_create_page_v2","notion_delete_block","notion_delete_block_v2","notion_list_comments","notion_list_comments_v2","notion_list_users","notion_list_users_v2","notion_query_database","notion_query_database_v2","notion_read","notion_read_database","notion_read_database_v2","notion_read_v2","notion_retrieve_block","notion_retrieve_block_children","notion_retrieve_block_children_v2","notion_retrieve_block_v2","notion_retrieve_user","notion_retrieve_user_v2","notion_search","notion_search_v2","notion_update_block","notion_update_block_v2","notion_update_page","notion_update_page_v2","notion_write","notion_write_v2","obsidian_append_active","obsidian_append_note","obsidian_append_periodic_note","obsidian_create_note","obsidian_delete_note","obsidian_execute_command","obsidian_get_active","obsidian_get_note","obsidian_get_periodic_note","obsidian_list_commands","obsidian_list_files","obsidian_open_file","obsidian_patch_active","obsidian_patch_note","obsidian_search","okta_activate_group_rule","okta_activate_user","okta_add_user_to_group","okta_assign_group_to_app","okta_assign_user_role","okta_assign_user_to_app","okta_clear_user_sessions","okta_create_group","okta_create_group_rule","okta_create_user","okta_deactivate_group_rule","okta_deactivate_user","okta_delete_group","okta_delete_group_rule","okta_delete_user","okta_enroll_factor","okta_get_app","okta_get_factor","okta_get_group","okta_get_group_rule","okta_get_logs","okta_get_session","okta_get_user","okta_list_app_groups","okta_list_app_users","okta_list_apps","okta_list_factors","okta_list_group_members","okta_list_group_rules","okta_list_groups","okta_list_user_roles","okta_list_users","okta_remove_group_from_app","okta_remove_user_from_app","okta_remove_user_from_group","okta_remove_user_role","okta_reset_all_factors","okta_reset_factor","okta_reset_password","okta_revoke_session","okta_suspend_user","okta_unsuspend_user","okta_update_group","okta_update_user","onedrive_copy","onedrive_create_folder","onedrive_create_share_link","onedrive_delete","onedrive_download","onedrive_get_drive_info","onedrive_get_item","onedrive_list","onedrive_move","onedrive_search","onedrive_upload","onepassword_create_item","onepassword_delete_item","onepassword_get_item","onepassword_get_item_file","onepassword_get_vault","onepassword_list_items","onepassword_list_vaults","onepassword_replace_item","onepassword_resolve_secret","onepassword_update_item","openai_embeddings","openai_image","oracle_fusion_financials_apply_receivables_receipt","oracle_fusion_financials_approve_receivables_invoice","oracle_fusion_financials_create_expense_line","oracle_fusion_financials_create_expense_report","oracle_fusion_financials_create_receivables_credit_memo","oracle_fusion_financials_create_receivables_invoice","oracle_fusion_financials_create_receivables_receipt","oracle_fusion_financials_get_expense_line","oracle_fusion_financials_get_expense_report","oracle_fusion_financials_get_gl_journal_batch","oracle_fusion_financials_get_gl_ledger","oracle_fusion_financials_get_payables_invoice","oracle_fusion_financials_get_payables_invoice_line","oracle_fusion_financials_get_payables_payment","oracle_fusion_financials_get_receivables_credit_memo","oracle_fusion_financials_get_receivables_invoice","oracle_fusion_financials_get_receivables_invoice_installment","oracle_fusion_financials_get_receivables_invoice_line","oracle_fusion_financials_get_receivables_receipt","oracle_fusion_financials_list_expense_lines","oracle_fusion_financials_list_expense_reports","oracle_fusion_financials_list_gl_balances","oracle_fusion_financials_list_gl_journal_batches","oracle_fusion_financials_list_gl_ledgers","oracle_fusion_financials_list_payables_invoice_lines","oracle_fusion_financials_list_payables_invoices","oracle_fusion_financials_list_payables_payments","oracle_fusion_financials_list_receivables_credit_memos","oracle_fusion_financials_list_receivables_invoice_installments","oracle_fusion_financials_list_receivables_invoice_lines","oracle_fusion_financials_list_receivables_invoices","oracle_fusion_financials_list_receivables_receipts","oracle_fusion_financials_submit_expense_report","oracle_fusion_financials_update_expense_line","oracle_fusion_financials_update_expense_report","oracle_fusion_financials_update_receivables_invoice","oracledb_delete","oracledb_execute","oracledb_insert","oracledb_introspect","oracledb_query","oracledb_update","otter_create_conversation","otter_get_conversation","otter_get_conversation_audio","otter_get_workspace","otter_list_channel_members","otter_list_channels","otter_list_conversations","otter_list_workspace_conversations","outlook_calendar_create_event","outlook_calendar_delete_event","outlook_calendar_get_event","outlook_calendar_list_events","outlook_calendar_respond","outlook_calendar_update_event","outlook_copy","outlook_create_folder","outlook_delete","outlook_draft","outlook_forward","outlook_get_attachment","outlook_list_attachments","outlook_list_folders","outlook_mark_read","outlook_mark_unread","outlook_move","outlook_read","outlook_reply","outlook_reply_all","outlook_search","outlook_send","outlook_update_message","pagerduty_add_note","pagerduty_create_incident","pagerduty_get_incident","pagerduty_get_service","pagerduty_list_escalation_policies","pagerduty_list_incident_alerts","pagerduty_list_incidents","pagerduty_list_oncalls","pagerduty_list_schedules","pagerduty_list_services","pagerduty_list_users","pagerduty_merge_incidents","pagerduty_send_event","pagerduty_snooze_incident","pagerduty_update_incident","parallel_deep_research","parallel_extract","parallel_search","pdl_autocomplete","pdl_bulk_company_enrich","pdl_bulk_person_enrich","pdl_clean_company","pdl_clean_location","pdl_clean_school","pdl_company_enrich","pdl_company_search","pdl_person_enrich","pdl_person_identify","pdl_person_search","perplexity_chat","perplexity_search","persona_approve_inquiry","persona_create_account","persona_create_inquiry","persona_create_report","persona_decline_inquiry","persona_expire_inquiry","persona_generate_inquiry_link","persona_get_account","persona_get_case","persona_get_document","persona_get_inquiry","persona_get_report","persona_get_verification","persona_import_accounts","persona_list_accounts","persona_list_cases","persona_list_inquiries","persona_list_inquiry_templates","persona_list_reports","persona_mark_inquiry_for_review","persona_print_inquiry_pdf","persona_redact_account","persona_redact_inquiry","persona_resume_inquiry","persona_update_account","persona_update_inquiry","pinecone_delete_vectors","pinecone_describe_index","pinecone_describe_index_stats","pinecone_fetch","pinecone_generate_embeddings","pinecone_list_indexes","pinecone_list_vector_ids","pinecone_search_text","pinecone_search_vector","pinecone_update_vector","pinecone_upsert_text","pipedrive_create_activity","pipedrive_create_deal","pipedrive_create_lead","pipedrive_create_project","pipedrive_delete_lead","pipedrive_get_activities","pipedrive_get_all_deals","pipedrive_get_deal","pipedrive_get_files","pipedrive_get_leads","pipedrive_get_mail_messages","pipedrive_get_mail_thread","pipedrive_get_pipeline_deals","pipedrive_get_pipelines","pipedrive_get_projects","pipedrive_update_activity","pipedrive_update_deal","pipedrive_update_lead","pitchbook_company_active_investors","pitchbook_company_bio","pitchbook_company_deal_service_providers","pitchbook_company_deals","pitchbook_company_financials","pitchbook_company_general_service_providers","pitchbook_company_industries","pitchbook_company_investors","pitchbook_company_most_recent_debt_financing","pitchbook_company_most_recent_financials","pitchbook_company_most_recent_financing","pitchbook_company_search","pitchbook_company_similar_companies","pitchbook_company_social_analytics","pitchbook_company_updates","pitchbook_company_vc_exit_predictions","pitchbook_contracts_history","pitchbook_cost_of_calls","pitchbook_credit_history","pitchbook_credit_news","pitchbook_credit_news_bulk","pitchbook_credit_news_most_recent","pitchbook_credit_news_search","pitchbook_deal_bio","pitchbook_deal_cap_table_history","pitchbook_deal_debt_lenders","pitchbook_deal_detailed","pitchbook_deal_investors","pitchbook_deal_multiples","pitchbook_deal_search","pitchbook_deal_service_providers","pitchbook_deal_stock_info","pitchbook_deal_tranche_info","pitchbook_deal_updates","pitchbook_deal_valuation","pitchbook_entity_affiliates","pitchbook_entity_locations","pitchbook_entity_news","pitchbook_entity_people","pitchbook_entity_updates","pitchbook_fund_active_investments","pitchbook_fund_benchmark","pitchbook_fund_bio","pitchbook_fund_cash_flows","pitchbook_fund_commitments","pitchbook_fund_investment_preferences","pitchbook_fund_investments","pitchbook_fund_performance","pitchbook_fund_search","pitchbook_fund_team","pitchbook_fund_updates","pitchbook_investor_active_investments","pitchbook_investor_bio","pitchbook_investor_board_seats","pitchbook_investor_deal_service_providers","pitchbook_investor_funds","pitchbook_investor_general_service_providers","pitchbook_investor_investments","pitchbook_investor_last_closed_fund","pitchbook_investor_preferences","pitchbook_investor_search","pitchbook_investor_updates","pitchbook_limited_partner_actual_allocations","pitchbook_limited_partner_bio","pitchbook_limited_partner_commitment_aggregates","pitchbook_limited_partner_commitment_preferences","pitchbook_limited_partner_commitments_detailed","pitchbook_limited_partner_search","pitchbook_limited_partner_service_providers","pitchbook_limited_partner_target_allocations","pitchbook_limited_partner_updates","pitchbook_lookup_table_structure","pitchbook_lookup_tables","pitchbook_patent_detailed","pitchbook_patent_search","pitchbook_people_search","pitchbook_person_bio","pitchbook_person_contact","pitchbook_person_education_work","pitchbook_sandbox_entities","pitchbook_search","pitchbook_service_provider_bio","pitchbook_service_provider_search","pitchbook_service_provider_updates","pitchbook_serviced_companies","pitchbook_serviced_deals","pitchbook_serviced_funds","pitchbook_serviced_investors","pitchbook_serviced_limited_partners","pitchbook_shared_search","pitchbook_usage_report","plane_archive_project","plane_archive_work_item","plane_confirm_attachment_upload","plane_create_attachment_upload","plane_create_comment","plane_create_cycle","plane_create_label","plane_create_link","plane_create_module","plane_create_project","plane_create_project_page","plane_create_state","plane_create_webhook","plane_create_work_item","plane_delete_attachment","plane_delete_comment","plane_delete_cycle","plane_delete_label","plane_delete_link","plane_delete_module","plane_delete_project","plane_delete_project_page","plane_delete_state","plane_delete_webhook","plane_delete_work_item","plane_get_attachment","plane_get_comment","plane_get_current_user","plane_get_cycle","plane_get_label","plane_get_link","plane_get_module","plane_get_project","plane_get_project_page","plane_get_project_summary","plane_get_state","plane_get_webhook","plane_get_work_item","plane_get_work_item_by_identifier","plane_list_attachments","plane_list_comments","plane_list_cycles","plane_list_labels","plane_list_links","plane_list_modules","plane_list_project_pages","plane_list_projects","plane_list_states","plane_list_webhooks","plane_list_work_items","plane_list_workspace_work_items","plane_manage_cycle_work_items","plane_manage_module_work_items","plane_regenerate_webhook_secret","plane_transfer_cycle_work_items","plane_unarchive_project","plane_unarchive_work_item","plane_update_comment","plane_update_cycle","plane_update_label","plane_update_link","plane_update_module","plane_update_project","plane_update_project_page","plane_update_state","plane_update_webhook","plane_update_work_item","planetscale_close_deploy_request","planetscale_create_backup","planetscale_create_branch","planetscale_create_deploy_request","planetscale_delete_branch","planetscale_get_backup","planetscale_get_branch","planetscale_get_database","planetscale_get_deploy_request","planetscale_list_backups","planetscale_list_branches","planetscale_list_databases","planetscale_list_deploy_requests","planetscale_queue_deploy_request","planetscale_review_deploy_request","polymarket_get_activity","polymarket_get_event","polymarket_get_events","polymarket_get_holders","polymarket_get_last_trade_price","polymarket_get_leaderboard","polymarket_get_market","polymarket_get_markets","polymarket_get_midpoint","polymarket_get_orderbook","polymarket_get_positions","polymarket_get_price","polymarket_get_price_history","polymarket_get_series","polymarket_get_series_by_id","polymarket_get_spread","polymarket_get_tags","polymarket_get_tick_size","polymarket_get_trades","polymarket_search","postgresql_delete","postgresql_execute","postgresql_insert","postgresql_introspect","postgresql_query","postgresql_update","posthog_batch_events","posthog_capture_event","posthog_create_annotation","posthog_create_cohort","posthog_create_dashboard","posthog_create_experiment","posthog_create_feature_flag","posthog_create_insight","posthog_create_survey","posthog_delete_feature_flag","posthog_delete_person","posthog_delete_survey","posthog_evaluate_flags","posthog_get_cohort","posthog_get_dashboard","posthog_get_event_definition","posthog_get_experiment","posthog_get_feature_flag","posthog_get_insight","posthog_get_organization","posthog_get_person","posthog_get_project","posthog_get_property_definition","posthog_get_session_recording","posthog_get_survey","posthog_list_actions","posthog_list_annotations","posthog_list_cohorts","posthog_list_dashboards","posthog_list_event_definitions","posthog_list_experiments","posthog_list_feature_flags","posthog_list_insights","posthog_list_organizations","posthog_list_persons","posthog_list_projects","posthog_list_property_definitions","posthog_list_recording_playlists","posthog_list_session_recordings","posthog_list_surveys","posthog_query","posthog_update_cohort","posthog_update_event_definition","posthog_update_experiment","posthog_update_feature_flag","posthog_update_insight","posthog_update_property_definition","posthog_update_survey","powerbi_execute_query","powerbi_get_dataset","powerbi_get_refresh_history","powerbi_get_report","powerbi_list_datasets","powerbi_list_reports","powerbi_list_workspaces","powerbi_refresh_dataset","profound_bot_logs","profound_bots_report","profound_category_assets","profound_category_personas","profound_category_prompts","profound_category_tags","profound_category_topics","profound_citation_prompts","profound_citations_report","profound_list_assets","profound_list_categories","profound_list_domains","profound_list_models","profound_list_optimizations","profound_list_personas","profound_list_regions","profound_optimization_analysis","profound_prompt_answers","profound_prompt_volume","profound_query_fanouts","profound_raw_logs","profound_referrals_report","profound_sentiment_report","profound_visibility_report","prospeo_account_information","prospeo_bulk_enrich_company","prospeo_bulk_enrich_person","prospeo_enrich_company","prospeo_enrich_person","prospeo_search_company","prospeo_search_person","prospeo_search_suggestions","pulse_parser","pulse_parser_v2","qdrant_fetch_points","qdrant_search_vector","qdrant_upsert_points","quartr_get_audio","quartr_get_company","quartr_get_event","quartr_get_event_summary","quartr_get_report","quartr_get_slide_deck","quartr_get_transcript","quartr_list_audio","quartr_list_companies","quartr_list_document_types","quartr_list_documents","quartr_list_event_types","quartr_list_events","quartr_list_live_events","quartr_list_reports","quartr_list_slide_decks","quartr_list_transcripts","quickbooks_add_attachment","quickbooks_create_bill","quickbooks_create_bill_payment","quickbooks_create_credit_memo","quickbooks_create_customer","quickbooks_create_customer_payment","quickbooks_create_deposit","quickbooks_create_employee","quickbooks_create_estimate","quickbooks_create_invoice","quickbooks_create_item","quickbooks_create_journal_entry","quickbooks_create_purchase","quickbooks_create_purchase_order","quickbooks_create_refund_receipt","quickbooks_create_sales_receipt","quickbooks_create_vendor","quickbooks_create_vendor_credit","quickbooks_download_attachment","quickbooks_download_transaction_pdf","quickbooks_email_transaction","quickbooks_get_company_info","quickbooks_read_accounting_transactions","quickbooks_read_attachments","quickbooks_read_master_data","quickbooks_read_purchasing_transactions","quickbooks_read_sales_transactions","quickbooks_run_financial_report","quickbooks_update_bill","quickbooks_update_bill_payment","quickbooks_update_credit_memo","quickbooks_update_customer","quickbooks_update_customer_payment","quickbooks_update_deposit","quickbooks_update_employee","quickbooks_update_estimate","quickbooks_update_invoice","quickbooks_update_item","quickbooks_update_journal_entry","quickbooks_update_purchase","quickbooks_update_purchase_order","quickbooks_update_refund_receipt","quickbooks_update_sales_receipt","quickbooks_update_vendor","quickbooks_update_vendor_credit","quickbooks_void_bill_payment","quickbooks_void_customer_payment","quickbooks_void_invoice","quickbooks_void_sales_receipt","quiver_image_to_svg","quiver_image_to_svg_v2","quiver_list_models","quiver_text_to_svg","quiver_text_to_svg_v2","rabbitmq_create_binding","rabbitmq_create_exchange","rabbitmq_create_policy","rabbitmq_create_queue","rabbitmq_delete_binding","rabbitmq_delete_exchange","rabbitmq_delete_policy","rabbitmq_delete_queue","rabbitmq_get_exchange","rabbitmq_get_messages","rabbitmq_get_overview","rabbitmq_get_queue","rabbitmq_health_check","rabbitmq_list_bindings","rabbitmq_list_channels","rabbitmq_list_connections","rabbitmq_list_consumers","rabbitmq_list_exchange_bindings","rabbitmq_list_exchanges","rabbitmq_list_nodes","rabbitmq_list_policies","rabbitmq_list_queues","rabbitmq_list_vhosts","rabbitmq_publish_message","rabbitmq_purge_queue","railway_create_environment","railway_create_project","railway_create_service","railway_delete_environment","railway_delete_project","railway_delete_service","railway_delete_variable","railway_deploy_service","railway_get_deployment","railway_get_deployment_logs","railway_get_project","railway_list_deployments","railway_list_project_members","railway_list_projects","railway_list_variables","railway_restart_deployment","railway_rollback_deployment","railway_transfer_project","railway_update_project","railway_upsert_variable","ramp_create_memo","ramp_get_balance","ramp_get_bill","ramp_get_business","ramp_get_memo","ramp_get_physical_card","ramp_get_reimbursement","ramp_get_transaction","ramp_get_user","ramp_get_vendor","ramp_get_virtual_card","ramp_list_bills","ramp_list_physical_cards","ramp_list_reimbursements","ramp_list_transactions","ramp_list_users","ramp_list_vendors","ramp_list_virtual_cards","rb2b_credit_check","rb2b_email_to_activity","rb2b_hem_to_best_linkedin","rb2b_hem_to_business_profile","rb2b_hem_to_linkedin","rb2b_hem_to_maid","rb2b_ip_to_company","rb2b_ip_to_hem","rb2b_ip_to_maid","rb2b_linkedin_slug_search","rb2b_linkedin_to_best_personal_email","rb2b_linkedin_to_business_profile","rb2b_linkedin_to_hashed_emails","rb2b_linkedin_to_mobile_phone","rb2b_linkedin_to_personal_email","rds_delete","rds_execute","rds_insert","rds_introspect","rds_query","rds_update","reddit_delete","reddit_edit","reddit_get_comments","reddit_get_controversial","reddit_get_info","reddit_get_me","reddit_get_messages","reddit_get_posts","reddit_get_saved","reddit_get_subreddit_info","reddit_get_subreddit_rules","reddit_get_user","reddit_get_user_comments","reddit_get_user_posts","reddit_hide","reddit_hot_posts","reddit_list_my_subreddits","reddit_lock","reddit_mark_all_read","reddit_mark_read","reddit_marknsfw","reddit_mod_approve","reddit_mod_distinguish","reddit_mod_remove","reddit_mod_sticky","reddit_reply","reddit_report","reddit_save","reddit_search","reddit_search_subreddits","reddit_send_message","reddit_submit_post","reddit_subscribe","reddit_unhide","reddit_unlock","reddit_unmarknsfw","reddit_unsave","reddit_vote","redis_command","redis_delete","redis_exists","redis_expire","redis_get","redis_hdel","redis_hget","redis_hgetall","redis_hset","redis_incr","redis_incrby","redis_keys","redis_llen","redis_lpop","redis_lpush","redis_lrange","redis_persist","redis_rpop","redis_rpush","redis_set","redis_setnx","redis_ttl","reducto_parser","reducto_parser_v2","resend_cancel_email","resend_create_audience","resend_create_broadcast","resend_create_contact","resend_delete_audience","resend_delete_contact","resend_get_audience","resend_get_broadcast","resend_get_contact","resend_get_email","resend_list_audiences","resend_list_contacts","resend_list_domains","resend_send","resend_send_broadcast","resend_update_contact","revenuecat_create_purchase","revenuecat_defer_google_subscription","revenuecat_delete_customer","revenuecat_get_customer","revenuecat_grant_entitlement","revenuecat_list_offerings","revenuecat_refund_google_subscription","revenuecat_revoke_entitlement","revenuecat_revoke_google_subscription","revenuecat_update_subscriber_attributes","rippling_bulk_create_custom_object_records","rippling_bulk_delete_custom_object_records","rippling_bulk_update_custom_object_records","rippling_create_business_partner","rippling_create_business_partner_group","rippling_create_custom_app","rippling_create_custom_object","rippling_create_custom_object_field","rippling_create_custom_object_record","rippling_create_custom_page","rippling_create_custom_setting","rippling_create_department","rippling_create_draft_hires","rippling_create_object_category","rippling_create_title","rippling_create_work_location","rippling_delete_business_partner","rippling_delete_business_partner_group","rippling_delete_custom_app","rippling_delete_custom_object","rippling_delete_custom_object_field","rippling_delete_custom_object_record","rippling_delete_custom_page","rippling_delete_custom_setting","rippling_delete_object_category","rippling_delete_title","rippling_delete_work_location","rippling_get_business_partner","rippling_get_business_partner_group","rippling_get_current_user","rippling_get_custom_app","rippling_get_custom_object","rippling_get_custom_object_field","rippling_get_custom_object_record","rippling_get_custom_object_record_by_external_id","rippling_get_custom_page","rippling_get_custom_setting","rippling_get_department","rippling_get_employment_type","rippling_get_job_function","rippling_get_object_category","rippling_get_report_run","rippling_get_supergroup","rippling_get_team","rippling_get_title","rippling_get_user","rippling_get_work_location","rippling_get_worker","rippling_list_business_partner_groups","rippling_list_business_partners","rippling_list_companies","rippling_list_custom_apps","rippling_list_custom_fields","rippling_list_custom_object_fields","rippling_list_custom_object_records","rippling_list_custom_objects","rippling_list_custom_pages","rippling_list_custom_settings","rippling_list_departments","rippling_list_employment_types","rippling_list_entitlements","rippling_list_job_functions","rippling_list_object_categories","rippling_list_supergroup_exclusion_members","rippling_list_supergroup_inclusion_members","rippling_list_supergroup_members","rippling_list_supergroups","rippling_list_teams","rippling_list_titles","rippling_list_users","rippling_list_work_locations","rippling_list_workers","rippling_query_custom_object_records","rippling_trigger_report_run","rippling_update_custom_app","rippling_update_custom_object","rippling_update_custom_object_field","rippling_update_custom_object_record","rippling_update_custom_page","rippling_update_custom_setting","rippling_update_department","rippling_update_object_category","rippling_update_supergroup_exclusion_members","rippling_update_supergroup_inclusion_members","rippling_update_title","rippling_update_work_location","rocketlane_add_field_option","rocketlane_add_project_members","rocketlane_add_task_assignees","rocketlane_add_task_dependencies","rocketlane_add_task_followers","rocketlane_archive_project","rocketlane_assign_placeholders","rocketlane_create_field","rocketlane_create_phase","rocketlane_create_project","rocketlane_create_space","rocketlane_create_space_document","rocketlane_create_task","rocketlane_create_time_entry","rocketlane_create_time_off","rocketlane_delete_field","rocketlane_delete_phase","rocketlane_delete_project","rocketlane_delete_space","rocketlane_delete_space_document","rocketlane_delete_task","rocketlane_delete_time_entry","rocketlane_delete_time_off","rocketlane_get_field","rocketlane_get_invoice","rocketlane_get_invoice_line_items","rocketlane_get_invoice_payments","rocketlane_get_phase","rocketlane_get_project","rocketlane_get_space","rocketlane_get_space_document","rocketlane_get_task","rocketlane_get_time_entry","rocketlane_get_time_off","rocketlane_get_user","rocketlane_import_template","rocketlane_list_fields","rocketlane_list_invoices","rocketlane_list_phases","rocketlane_list_placeholders","rocketlane_list_projects","rocketlane_list_resource_allocations","rocketlane_list_space_documents","rocketlane_list_spaces","rocketlane_list_tasks","rocketlane_list_time_entries","rocketlane_list_time_entry_categories","rocketlane_list_time_offs","rocketlane_list_users","rocketlane_move_task_to_phase","rocketlane_remove_project_members","rocketlane_remove_task_assignees","rocketlane_remove_task_dependencies","rocketlane_remove_task_followers","rocketlane_search_time_entries","rocketlane_unassign_placeholders","rocketlane_update_field","rocketlane_update_field_option","rocketlane_update_phase","rocketlane_update_project","rocketlane_update_space","rocketlane_update_space_document","rocketlane_update_task","rocketlane_update_time_entry","rootly_acknowledge_alert","rootly_add_incident_event","rootly_add_subscribers","rootly_assign_incident_role","rootly_create_action_item","rootly_create_alert","rootly_create_incident","rootly_create_status_page_event","rootly_delete_action_item","rootly_delete_incident","rootly_escalate_alert","rootly_get_alert","rootly_get_incident","rootly_list_action_items","rootly_list_alerts","rootly_list_causes","rootly_list_environments","rootly_list_escalation_policies","rootly_list_functionalities","rootly_list_incident_events","rootly_list_incident_roles","rootly_list_incident_types","rootly_list_incidents","rootly_list_on_calls","rootly_list_playbooks","rootly_list_retrospectives","rootly_list_schedules","rootly_list_services","rootly_list_severities","rootly_list_teams","rootly_list_users","rootly_mitigate_incident","rootly_remove_subscribers","rootly_resolve_alert","rootly_resolve_incident","rootly_run_workflow","rootly_snooze_alert","rootly_unassign_incident_role","rootly_update_action_item","rootly_update_alert","rootly_update_incident","s3_copy_object","s3_create_bucket","s3_delete_bucket","s3_delete_object","s3_delete_objects","s3_get_object","s3_head_object","s3_list_buckets","s3_list_objects","s3_presigned_url","s3_put_object","sailpoint_approve_access_request","sailpoint_cancel_access_request","sailpoint_decide_certification_review_items","sailpoint_get_access_profile","sailpoint_get_access_profile_entitlements","sailpoint_get_access_request_config","sailpoint_get_access_request_status","sailpoint_get_account","sailpoint_get_account_activity","sailpoint_get_account_entitlements","sailpoint_get_account_selections","sailpoint_get_campaign","sailpoint_get_certification","sailpoint_get_entitlement","sailpoint_get_entitlement_request_config","sailpoint_get_identity","sailpoint_get_role","sailpoint_get_role_entitlements","sailpoint_get_source","sailpoint_get_task_status","sailpoint_list_access_profiles","sailpoint_list_account_activities","sailpoint_list_accounts","sailpoint_list_campaigns","sailpoint_list_certification_review_items","sailpoint_list_certifications","sailpoint_list_entitlements","sailpoint_list_identities","sailpoint_list_identity_entitlements","sailpoint_list_pending_access_request_approvals","sailpoint_list_roles","sailpoint_list_sources","sailpoint_load_accounts","sailpoint_load_entitlements","sailpoint_reject_access_request","sailpoint_request_access","sailpoint_search","sailpoint_search_aggregate","sailpoint_search_count","sailpoint_sign_off_certification","salesforce_create_account","salesforce_create_case","salesforce_create_contact","salesforce_create_custom_field","salesforce_create_custom_object","salesforce_create_lead","salesforce_create_opportunity","salesforce_create_task","salesforce_delete_account","salesforce_delete_case","salesforce_delete_contact","salesforce_delete_custom_field","salesforce_delete_lead","salesforce_delete_opportunity","salesforce_delete_task","salesforce_describe_object","salesforce_get_accounts","salesforce_get_cases","salesforce_get_contacts","salesforce_get_dashboard","salesforce_get_leads","salesforce_get_opportunities","salesforce_get_report","salesforce_get_tasks","salesforce_list_dashboards","salesforce_list_objects","salesforce_list_report_types","salesforce_list_reports","salesforce_query","salesforce_query_more","salesforce_refresh_dashboard","salesforce_run_report","salesforce_tooling_query","salesforce_update_account","salesforce_update_case","salesforce_update_contact","salesforce_update_custom_field","salesforce_update_lead","salesforce_update_opportunity","salesforce_update_task","sap_concur_approve_expense_report","sap_concur_associate_attendees","sap_concur_create_cash_advance","sap_concur_create_expected_expense","sap_concur_create_expense_report","sap_concur_create_list_item","sap_concur_create_purchase_request","sap_concur_create_quick_expense","sap_concur_create_quick_expense_with_image","sap_concur_create_report_comment","sap_concur_create_travel_request","sap_concur_create_user","sap_concur_delete_expected_expense","sap_concur_delete_expense","sap_concur_delete_expense_report","sap_concur_delete_list_item","sap_concur_delete_travel_request","sap_concur_delete_user","sap_concur_get_allocation","sap_concur_get_budget","sap_concur_get_cash_advance","sap_concur_get_expected_expense","sap_concur_get_expense","sap_concur_get_expense_report","sap_concur_get_itemizations","sap_concur_get_itinerary","sap_concur_get_list","sap_concur_get_list_item","sap_concur_get_purchase_request","sap_concur_get_receipt","sap_concur_get_receipt_status","sap_concur_get_request_cash_advance","sap_concur_get_travel_profile","sap_concur_get_travel_request","sap_concur_get_user","sap_concur_issue_cash_advance","sap_concur_list_allocations","sap_concur_list_attendee_associations","sap_concur_list_budget_categories","sap_concur_list_budgets","sap_concur_list_exceptions","sap_concur_list_expected_expenses","sap_concur_list_expense_reports","sap_concur_list_expenses","sap_concur_list_itineraries","sap_concur_list_list_items","sap_concur_list_lists","sap_concur_list_receipts","sap_concur_list_report_comments","sap_concur_list_reports_to_approve","sap_concur_list_travel_profiles_summary","sap_concur_list_travel_request_comments","sap_concur_list_travel_requests","sap_concur_list_users","sap_concur_move_travel_request","sap_concur_recall_expense_report","sap_concur_remove_all_attendees","sap_concur_search_locations","sap_concur_search_users","sap_concur_send_back_expense_report","sap_concur_submit_expense_report","sap_concur_update_allocation","sap_concur_update_expected_expense","sap_concur_update_expense","sap_concur_update_expense_report","sap_concur_update_list_item","sap_concur_update_travel_request","sap_concur_update_user","sap_concur_upload_exchange_rates","sap_concur_upload_receipt_image","sap_s4hana_create_business_partner","sap_s4hana_create_purchase_order","sap_s4hana_create_purchase_requisition","sap_s4hana_create_sales_order","sap_s4hana_delete_sales_order","sap_s4hana_get_billing_document","sap_s4hana_get_business_partner","sap_s4hana_get_customer","sap_s4hana_get_inbound_delivery","sap_s4hana_get_material_document","sap_s4hana_get_outbound_delivery","sap_s4hana_get_product","sap_s4hana_get_purchase_order","sap_s4hana_get_purchase_requisition","sap_s4hana_get_sales_order","sap_s4hana_get_supplier","sap_s4hana_get_supplier_invoice","sap_s4hana_list_billing_documents","sap_s4hana_list_business_partners","sap_s4hana_list_customers","sap_s4hana_list_inbound_deliveries","sap_s4hana_list_material_documents","sap_s4hana_list_material_stock","sap_s4hana_list_outbound_deliveries","sap_s4hana_list_products","sap_s4hana_list_purchase_orders","sap_s4hana_list_purchase_requisitions","sap_s4hana_list_sales_orders","sap_s4hana_list_supplier_invoices","sap_s4hana_list_suppliers","sap_s4hana_odata_query","sap_s4hana_update_business_partner","sap_s4hana_update_customer","sap_s4hana_update_product","sap_s4hana_update_purchase_order","sap_s4hana_update_purchase_requisition","sap_s4hana_update_sales_order","sap_s4hana_update_supplier","search_tool","secrets_manager_create_secret","secrets_manager_delete_secret","secrets_manager_describe_secret","secrets_manager_get_secret","secrets_manager_list_secrets","secrets_manager_restore_secret","secrets_manager_rotate_secret","secrets_manager_tag_resource","secrets_manager_untag_resource","secrets_manager_update_secret","semrush_backlinks","semrush_backlinks_anchors","semrush_backlinks_competitors","semrush_backlinks_geo_distribution","semrush_backlinks_indexed_pages","semrush_backlinks_overview","semrush_backlinks_tld_distribution","semrush_batch_keyword_overview","semrush_broad_match_keywords","semrush_domain_ad_copies","semrush_domain_ad_history","semrush_domain_organic_competitors","semrush_domain_organic_keywords","semrush_domain_overview","semrush_domain_overview_all","semrush_domain_overview_history","semrush_domain_paid_competitors","semrush_domain_paid_keywords","semrush_domain_pla_copies","semrush_domain_pla_keywords","semrush_domain_vs_domain","semrush_keyword_ad_history","semrush_keyword_difficulty","semrush_keyword_overview","semrush_keyword_overview_all","semrush_keyword_questions","semrush_organic_results","semrush_paid_results","semrush_referring_domains","semrush_referring_ips","semrush_related_keywords","semrush_subdomain_ad_copies","semrush_subdomain_organic_keywords","semrush_subdomain_overview","semrush_subdomain_overview_all","semrush_subdomain_overview_history","semrush_subdomain_paid_keywords","semrush_top_domains","semrush_url_organic_keywords","semrush_url_overview","semrush_url_overview_all","semrush_url_overview_history","semrush_url_paid_keywords","semrush_winners_and_losers","sendblue_evaluate_service","sendblue_get_message","sendblue_send_group_message","sendblue_send_message","sendblue_send_typing_indicator","sendgrid_add_contact","sendgrid_add_contacts_to_list","sendgrid_create_list","sendgrid_create_template","sendgrid_create_template_version","sendgrid_delete_contacts","sendgrid_delete_list","sendgrid_delete_template","sendgrid_get_contact","sendgrid_get_list","sendgrid_get_template","sendgrid_list_all_lists","sendgrid_list_templates","sendgrid_remove_contacts_from_list","sendgrid_search_contacts","sendgrid_send_mail","sentry_events_get","sentry_events_list","sentry_issues_get","sentry_issues_list","sentry_issues_update","sentry_projects_create","sentry_projects_get","sentry_projects_list","sentry_projects_update","sentry_releases_create","sentry_releases_deploy","sentry_releases_list","sentry_teams_list","serper_search","servicenow_add_incident_comment","servicenow_aggregate","servicenow_close_incident","servicenow_create_change_request","servicenow_create_incident","servicenow_create_record","servicenow_delete_record","servicenow_download_attachment","servicenow_download_attachment_v2","servicenow_find_user","servicenow_get_change_next_states","servicenow_get_change_request","servicenow_get_ci","servicenow_get_incident","servicenow_get_knowledge_article","servicenow_get_requested_item","servicenow_list_approvals","servicenow_list_attachments","servicenow_list_catalog_items","servicenow_list_change_requests","servicenow_list_change_tasks","servicenow_list_ci_relationships","servicenow_list_group_members","servicenow_list_incidents","servicenow_list_requested_items","servicenow_order_catalog_item","servicenow_read_record","servicenow_resolve_incident","servicenow_search_cis","servicenow_search_knowledge","servicenow_update_approval","servicenow_update_change_request","servicenow_update_change_state","servicenow_update_incident","servicenow_update_record","servicenow_upload_attachment","ses_create_configuration_set","ses_create_email_identity","ses_create_template","ses_delete_email_identity","ses_delete_suppressed_destination","ses_delete_template","ses_get_account","ses_get_email_identity","ses_get_suppressed_destination","ses_get_template","ses_list_identities","ses_list_suppressed_destinations","ses_list_templates","ses_put_suppressed_destination","ses_send_bulk_email","ses_send_custom_verification_email","ses_send_email","ses_send_templated_email","ses_update_template","sftp_delete","sftp_download","sftp_download_v2","sftp_list","sftp_mkdir","sftp_upload","sharepoint_add_list_items","sharepoint_create_list","sharepoint_create_page","sharepoint_delete_file","sharepoint_delete_list_item","sharepoint_delete_page","sharepoint_download_file","sharepoint_get_drive_item","sharepoint_get_list","sharepoint_get_list_item","sharepoint_list_sites","sharepoint_publish_page","sharepoint_read_page","sharepoint_update_list","sharepoint_update_page","sharepoint_upload_file","shopify_adjust_inventory","shopify_cancel_order","shopify_create_customer","shopify_create_fulfillment","shopify_create_product","shopify_create_product_variants","shopify_delete_customer","shopify_delete_product","shopify_get_collection","shopify_get_customer","shopify_get_fulfillment","shopify_get_fulfillment_order","shopify_get_inventory_level","shopify_get_job","shopify_get_order","shopify_get_product","shopify_list_collections","shopify_list_customers","shopify_list_fulfillment_orders","shopify_list_inventory_items","shopify_list_locations","shopify_list_orders","shopify_list_products","shopify_update_customer","shopify_update_fulfillment_tracking","shopify_update_order","shopify_update_product","shopify_update_product_variants","similarweb_bounce_rate","similarweb_page_views","similarweb_pages_per_visit","similarweb_traffic_visits","similarweb_visit_duration","similarweb_website_overview","sixtyfour_enrich_company","sixtyfour_enrich_lead","sixtyfour_find_email","sixtyfour_find_phone","slack_add_bookmark","slack_add_reaction","slack_archive_conversation","slack_canvas","slack_close_conversation","slack_create_channel_canvas","slack_create_conversation","slack_create_user_group","slack_delete_canvas","slack_delete_file","slack_delete_message","slack_delete_scheduled_message","slack_disable_user_group","slack_download","slack_edit_bookmark","slack_edit_canvas","slack_enable_user_group","slack_ephemeral_message","slack_get_canvas","slack_get_channel_history","slack_get_channel_info","slack_get_dnd_info","slack_get_file_info","slack_get_message","slack_get_permalink","slack_get_reactions","slack_get_team_dnd_info","slack_get_team_info","slack_get_team_profile","slack_get_thread","slack_get_thread_replies","slack_get_user","slack_get_user_presence","slack_get_user_profile","slack_invite_to_conversation","slack_join_conversation","slack_kick_conversation","slack_leave_conversation","slack_list_bookmarks","slack_list_canvases","slack_list_channels","slack_list_emoji","slack_list_files","slack_list_members","slack_list_pins","slack_list_reactions","slack_list_scheduled_messages","slack_list_user_conversations","slack_list_user_group_members","slack_list_user_groups","slack_list_users","slack_lists_access_delete","slack_lists_access_set","slack_lists_create","slack_lists_download_get","slack_lists_download_start","slack_lists_items_create","slack_lists_items_delete","slack_lists_items_delete_multiple","slack_lists_items_info","slack_lists_items_list","slack_lists_items_update","slack_lists_update","slack_lookup_canvas_sections","slack_lookup_user_by_email","slack_mark_conversation_read","slack_message","slack_message_reader","slack_open_conversation","slack_open_view","slack_pin_message","slack_publish_view","slack_push_view","slack_remove_bookmark","slack_remove_reaction","slack_rename_agent_session_v2","slack_rename_conversation","slack_revoke_canvas_access","slack_schedule_message","slack_set_agent_session_status_v2","slack_set_conversation_purpose","slack_set_conversation_topic","slack_set_status","slack_set_suggested_prompts","slack_set_suggested_prompts_v2","slack_set_title","slack_set_user_presence","slack_share_canvas","slack_unarchive_conversation","slack_unfurl_links","slack_unpin_message","slack_update_message","slack_update_user_group","slack_update_user_group_members","slack_update_view","smartlead_add_email_accounts_to_campaign","smartlead_add_leads_to_campaign","smartlead_create_campaign","smartlead_create_lead_list","smartlead_delete_campaign","smartlead_delete_campaign_webhook","smartlead_delete_lead_from_campaign","smartlead_delete_lead_list","smartlead_duplicate_campaign","smartlead_export_campaign_leads","smartlead_get_campaign","smartlead_get_campaign_analytics","smartlead_get_campaign_analytics_by_date","smartlead_get_campaign_lead_statistics","smartlead_get_campaign_mailbox_statistics","smartlead_get_campaign_sequences","smartlead_get_campaign_statistics","smartlead_get_campaign_top_level_analytics_by_date","smartlead_get_campaign_webhook_summary","smartlead_get_lead_by_email","smartlead_get_lead_by_id","smartlead_get_lead_list","smartlead_get_lead_message_history","smartlead_list_campaign_email_accounts","smartlead_list_campaign_leads","smartlead_list_campaign_webhooks","smartlead_list_campaigns","smartlead_list_clients","smartlead_list_email_accounts","smartlead_list_inbox_replies","smartlead_list_lead_activities","smartlead_list_lead_categories","smartlead_list_lead_lists","smartlead_mark_lead_complete","smartlead_pause_lead","smartlead_remove_email_accounts_from_campaign","smartlead_resume_lead","smartlead_save_campaign_sequences","smartlead_unsubscribe_lead_from_campaign","smartlead_unsubscribe_lead_globally","smartlead_update_campaign_schedule","smartlead_update_campaign_settings","smartlead_update_campaign_status","smartlead_update_lead","smartlead_update_lead_category","smartlead_update_lead_list","smartlead_upsert_campaign_webhook","sms_send","smtp_send_mail","snowflake_alter_warehouse","snowflake_call_procedure","snowflake_cancel_statement","snowflake_cancel_task_run","snowflake_cortex_analyst_ask","snowflake_cortex_analyst_feedback","snowflake_delete_rows","snowflake_execute_sql","snowflake_get_statement","snowflake_get_task","snowflake_get_task_run","snowflake_get_task_run_output","snowflake_get_warehouse","snowflake_insert_rows","snowflake_introspect_schema","snowflake_list_copy_history","snowflake_list_databases","snowflake_list_query_history","snowflake_list_schemas","snowflake_list_tables","snowflake_list_task_runs","snowflake_list_tasks","snowflake_list_warehouses","snowflake_load_data","snowflake_resume_task","snowflake_resume_warehouse","snowflake_run_task","snowflake_suspend_task","snowflake_suspend_warehouse","snowflake_unload_data","snowflake_update_rows","snowflake_upsert_rows","splunk_cancel_search_job","splunk_create_search_job","splunk_dispatch_saved_search","splunk_get_fired_alerts","splunk_get_saved_search","splunk_get_search_job","splunk_get_search_results","splunk_list_apps","splunk_list_fired_alerts","splunk_list_indexes","splunk_list_saved_searches","splunk_run_search","sportmonks_core_get_cities","sportmonks_core_get_city","sportmonks_core_get_continent","sportmonks_core_get_continents","sportmonks_core_get_countries","sportmonks_core_get_country","sportmonks_core_get_entity_filters","sportmonks_core_get_my_usage","sportmonks_core_get_region","sportmonks_core_get_regions","sportmonks_core_get_timezones","sportmonks_core_get_type","sportmonks_core_get_type_by_entity","sportmonks_core_get_types","sportmonks_core_search_cities","sportmonks_core_search_countries","sportmonks_core_search_regions","sportmonks_football_expected_by_player","sportmonks_football_expected_by_team","sportmonks_football_get_all_commentaries","sportmonks_football_get_all_fixtures","sportmonks_football_get_all_players","sportmonks_football_get_all_rivals","sportmonks_football_get_all_teams","sportmonks_football_get_all_transfer_rumours","sportmonks_football_get_all_transfers","sportmonks_football_get_brackets_by_season","sportmonks_football_get_coach","sportmonks_football_get_coaches","sportmonks_football_get_coaches_by_country","sportmonks_football_get_commentaries_by_fixture","sportmonks_football_get_current_leagues_by_team","sportmonks_football_get_expected_lineups_by_player","sportmonks_football_get_expected_lineups_by_team","sportmonks_football_get_extended_team_squad","sportmonks_football_get_fixture","sportmonks_football_get_fixtures_by_date","sportmonks_football_get_fixtures_by_date_range","sportmonks_football_get_fixtures_by_date_range_for_team","sportmonks_football_get_fixtures_by_ids","sportmonks_football_get_grouped_standings_by_round","sportmonks_football_get_head_to_head","sportmonks_football_get_inplay_livescores","sportmonks_football_get_latest_coaches","sportmonks_football_get_latest_fixtures","sportmonks_football_get_latest_livescores","sportmonks_football_get_latest_players","sportmonks_football_get_latest_totw","sportmonks_football_get_latest_transfers","sportmonks_football_get_league","sportmonks_football_get_leagues","sportmonks_football_get_leagues_by_country","sportmonks_football_get_leagues_by_date","sportmonks_football_get_leagues_by_team","sportmonks_football_get_live_leagues","sportmonks_football_get_live_probabilities","sportmonks_football_get_live_probabilities_by_fixture","sportmonks_football_get_live_standings_by_league","sportmonks_football_get_livescores","sportmonks_football_get_match_facts","sportmonks_football_get_match_facts_by_date_range","sportmonks_football_get_match_facts_by_fixture","sportmonks_football_get_match_facts_by_league","sportmonks_football_get_past_fixtures_by_tv_station","sportmonks_football_get_player","sportmonks_football_get_players_by_country","sportmonks_football_get_postmatch_news","sportmonks_football_get_postmatch_news_by_season","sportmonks_football_get_predictability_by_league","sportmonks_football_get_prematch_news","sportmonks_football_get_prematch_news_by_season","sportmonks_football_get_prematch_news_upcoming","sportmonks_football_get_probabilities","sportmonks_football_get_probabilities_by_fixture","sportmonks_football_get_referee","sportmonks_football_get_referees","sportmonks_football_get_referees_by_country","sportmonks_football_get_referees_by_season","sportmonks_football_get_rivals_by_team","sportmonks_football_get_round","sportmonks_football_get_round_statistics","sportmonks_football_get_rounds","sportmonks_football_get_rounds_by_season","sportmonks_football_get_schedules_by_season","sportmonks_football_get_schedules_by_season_and_team","sportmonks_football_get_schedules_by_team","sportmonks_football_get_season","sportmonks_football_get_seasons","sportmonks_football_get_seasons_by_team","sportmonks_football_get_stage","sportmonks_football_get_stage_statistics","sportmonks_football_get_stages","sportmonks_football_get_stages_by_season","sportmonks_football_get_standing_corrections_by_season","sportmonks_football_get_standings","sportmonks_football_get_standings_by_round","sportmonks_football_get_standings_by_season","sportmonks_football_get_state","sportmonks_football_get_states","sportmonks_football_get_team","sportmonks_football_get_team_rankings","sportmonks_football_get_team_rankings_by_date","sportmonks_football_get_team_rankings_by_team","sportmonks_football_get_team_squad","sportmonks_football_get_team_squad_by_season","sportmonks_football_get_teams_by_country","sportmonks_football_get_teams_by_season","sportmonks_football_get_topscorers_by_season","sportmonks_football_get_topscorers_by_stage","sportmonks_football_get_totw","sportmonks_football_get_totw_by_round","sportmonks_football_get_transfer","sportmonks_football_get_transfer_rumour","sportmonks_football_get_transfer_rumours_between_dates","sportmonks_football_get_transfer_rumours_by_player","sportmonks_football_get_transfer_rumours_by_team","sportmonks_football_get_transfers_between_dates","sportmonks_football_get_transfers_by_player","sportmonks_football_get_transfers_by_team","sportmonks_football_get_tv_station","sportmonks_football_get_tv_stations","sportmonks_football_get_tv_stations_by_fixture","sportmonks_football_get_upcoming_fixtures_by_market","sportmonks_football_get_upcoming_fixtures_by_tv_station","sportmonks_football_get_value_bets","sportmonks_football_get_value_bets_by_fixture","sportmonks_football_get_venue","sportmonks_football_get_venues","sportmonks_football_get_venues_by_season","sportmonks_football_search_coaches","sportmonks_football_search_fixtures","sportmonks_football_search_leagues","sportmonks_football_search_players","sportmonks_football_search_referees","sportmonks_football_search_rounds","sportmonks_football_search_seasons","sportmonks_football_search_stages","sportmonks_football_search_teams","sportmonks_football_search_venues","sportmonks_motorsport_get_all_fixtures","sportmonks_motorsport_get_current_leagues_by_team","sportmonks_motorsport_get_driver","sportmonks_motorsport_get_driver_standings","sportmonks_motorsport_get_driver_standings_by_season","sportmonks_motorsport_get_drivers","sportmonks_motorsport_get_drivers_by_country","sportmonks_motorsport_get_drivers_by_season","sportmonks_motorsport_get_fixture","sportmonks_motorsport_get_fixtures_by_date","sportmonks_motorsport_get_fixtures_by_date_range","sportmonks_motorsport_get_fixtures_by_ids","sportmonks_motorsport_get_laps_by_fixture","sportmonks_motorsport_get_laps_by_fixture_and_driver","sportmonks_motorsport_get_laps_by_fixture_and_lap","sportmonks_motorsport_get_latest_laps_by_fixture","sportmonks_motorsport_get_latest_pitstops_by_fixture","sportmonks_motorsport_get_latest_stints_by_fixture","sportmonks_motorsport_get_latest_updated_drivers","sportmonks_motorsport_get_latest_updated_fixtures","sportmonks_motorsport_get_league","sportmonks_motorsport_get_leagues","sportmonks_motorsport_get_leagues_by_country","sportmonks_motorsport_get_leagues_by_date","sportmonks_motorsport_get_leagues_by_live","sportmonks_motorsport_get_leagues_by_team","sportmonks_motorsport_get_livescores","sportmonks_motorsport_get_pitstops_by_fixture","sportmonks_motorsport_get_pitstops_by_fixture_and_driver","sportmonks_motorsport_get_pitstops_by_fixture_and_lap","sportmonks_motorsport_get_race_results_by_season_and_driver","sportmonks_motorsport_get_race_results_by_season_and_team","sportmonks_motorsport_get_schedules_by_season","sportmonks_motorsport_get_season","sportmonks_motorsport_get_seasons","sportmonks_motorsport_get_stage","sportmonks_motorsport_get_stages","sportmonks_motorsport_get_stages_by_season","sportmonks_motorsport_get_state","sportmonks_motorsport_get_states","sportmonks_motorsport_get_stints_by_fixture","sportmonks_motorsport_get_stints_by_fixture_and_driver","sportmonks_motorsport_get_stints_by_fixture_and_stint","sportmonks_motorsport_get_team","sportmonks_motorsport_get_team_standings","sportmonks_motorsport_get_team_standings_by_season","sportmonks_motorsport_get_teams","sportmonks_motorsport_get_teams_by_country","sportmonks_motorsport_get_teams_by_season","sportmonks_motorsport_get_venue","sportmonks_motorsport_get_venues","sportmonks_motorsport_get_venues_by_season","sportmonks_motorsport_search_drivers","sportmonks_motorsport_search_leagues","sportmonks_motorsport_search_stages","sportmonks_motorsport_search_teams","sportmonks_motorsport_search_venues","sportmonks_odds_get_all_historical_odds","sportmonks_odds_get_all_inplay_odds","sportmonks_odds_get_all_pre_match_odds","sportmonks_odds_get_all_premium_odds","sportmonks_odds_get_bookmaker","sportmonks_odds_get_bookmaker_event_ids_by_fixture","sportmonks_odds_get_bookmakers","sportmonks_odds_get_bookmakers_by_fixture","sportmonks_odds_get_inplay_odds_by_fixture","sportmonks_odds_get_inplay_odds_by_fixture_and_bookmaker","sportmonks_odds_get_inplay_odds_by_fixture_and_market","sportmonks_odds_get_last_updated_inplay_odds","sportmonks_odds_get_last_updated_pre_match_odds","sportmonks_odds_get_market","sportmonks_odds_get_markets","sportmonks_odds_get_pre_match_odds_by_fixture","sportmonks_odds_get_pre_match_odds_by_fixture_and_bookmaker","sportmonks_odds_get_pre_match_odds_by_fixture_and_market","sportmonks_odds_get_premium_odds_by_fixture","sportmonks_odds_get_premium_odds_by_fixture_and_bookmaker","sportmonks_odds_get_premium_odds_by_fixture_and_market","sportmonks_odds_get_updated_historical_odds_between","sportmonks_odds_get_updated_premium_odds_between","sportmonks_odds_search_bookmakers","sportmonks_odds_search_markets","spotify_add_playlist_cover","spotify_add_to_queue","spotify_add_tracks_to_playlist","spotify_check_following","spotify_check_playlist_followers","spotify_check_saved_albums","spotify_check_saved_audiobooks","spotify_check_saved_episodes","spotify_check_saved_shows","spotify_check_saved_tracks","spotify_create_playlist","spotify_follow_artists","spotify_follow_playlist","spotify_get_album","spotify_get_album_tracks","spotify_get_albums","spotify_get_artist","spotify_get_artist_albums","spotify_get_artist_top_tracks","spotify_get_artists","spotify_get_audiobook","spotify_get_audiobook_chapters","spotify_get_audiobooks","spotify_get_categories","spotify_get_current_user","spotify_get_currently_playing","spotify_get_devices","spotify_get_episode","spotify_get_episodes","spotify_get_followed_artists","spotify_get_markets","spotify_get_new_releases","spotify_get_playback_state","spotify_get_playlist","spotify_get_playlist_cover","spotify_get_playlist_tracks","spotify_get_queue","spotify_get_recently_played","spotify_get_saved_albums","spotify_get_saved_audiobooks","spotify_get_saved_episodes","spotify_get_saved_shows","spotify_get_saved_tracks","spotify_get_show","spotify_get_show_episodes","spotify_get_shows","spotify_get_top_artists","spotify_get_top_tracks","spotify_get_track","spotify_get_tracks","spotify_get_user_playlists","spotify_get_user_profile","spotify_pause","spotify_play","spotify_remove_saved_albums","spotify_remove_saved_audiobooks","spotify_remove_saved_episodes","spotify_remove_saved_shows","spotify_remove_saved_tracks","spotify_remove_tracks_from_playlist","spotify_reorder_playlist_items","spotify_replace_playlist_items","spotify_save_albums","spotify_save_audiobooks","spotify_save_episodes","spotify_save_shows","spotify_save_tracks","spotify_search","spotify_seek","spotify_set_repeat","spotify_set_shuffle","spotify_set_volume","spotify_skip_next","spotify_skip_previous","spotify_transfer_playback","spotify_unfollow_artists","spotify_unfollow_playlist","spotify_update_playlist","sqs_cancel_message_move_task","sqs_change_message_visibility","sqs_change_message_visibility_batch","sqs_create_queue","sqs_delete_message","sqs_delete_message_batch","sqs_delete_queue","sqs_get_queue_attributes","sqs_get_queue_url","sqs_list_dead_letter_source_queues","sqs_list_message_move_tasks","sqs_list_queue_tags","sqs_list_queues","sqs_purge_queue","sqs_receive_message","sqs_send","sqs_send_message_batch","sqs_set_queue_attributes","sqs_start_message_move_task","sqs_tag_queue","sqs_untag_queue","square_batch_retrieve_inventory_counts","square_cancel_invoice","square_cancel_payment","square_complete_payment","square_create_catalog_image","square_create_customer","square_create_invoice","square_create_order","square_create_payment","square_delete_catalog_object","square_delete_customer","square_delete_invoice","square_get_catalog_object","square_get_customer","square_get_invoice","square_get_location","square_get_order","square_get_payment","square_get_refund","square_list_catalog","square_list_customers","square_list_invoices","square_list_locations","square_list_payments","square_list_refunds","square_pay_order","square_publish_invoice","square_refund_payment","square_search_catalog_objects","square_search_customers","square_search_invoices","square_search_orders","square_update_customer","square_upsert_catalog_object","ssh_check_command_exists","ssh_check_file_exists","ssh_create_directory","ssh_delete_file","ssh_download_file","ssh_download_file_v2","ssh_execute_command","ssh_execute_script","ssh_get_system_info","ssh_list_directory","ssh_move_rename","ssh_read_file_content","ssh_upload_file","ssh_write_file_content","ssm_cancel_command","ssm_delete_parameter","ssm_describe_automation_executions","ssm_describe_instance_information","ssm_describe_instance_patch_states","ssm_describe_instance_patches","ssm_describe_parameters","ssm_get_automation_execution","ssm_get_command_invocation","ssm_get_document","ssm_get_parameter","ssm_get_parameters","ssm_get_parameters_by_path","ssm_list_command_invocations","ssm_list_commands","ssm_list_compliance_items","ssm_list_compliance_summaries","ssm_list_documents","ssm_put_parameter","ssm_send_command","ssm_start_automation_execution","ssm_stop_automation_execution","stagehand_agent","stagehand_extract","stripe_cancel_payment_intent","stripe_cancel_subscription","stripe_capture_charge","stripe_capture_payment_intent","stripe_confirm_payment_intent","stripe_create_charge","stripe_create_customer","stripe_create_invoice","stripe_create_payment_intent","stripe_create_price","stripe_create_product","stripe_create_subscription","stripe_delete_customer","stripe_delete_invoice","stripe_delete_product","stripe_finalize_invoice","stripe_list_charges","stripe_list_customers","stripe_list_events","stripe_list_invoices","stripe_list_payment_intents","stripe_list_prices","stripe_list_products","stripe_list_subscriptions","stripe_pay_invoice","stripe_resume_subscription","stripe_retrieve_charge","stripe_retrieve_customer","stripe_retrieve_event","stripe_retrieve_invoice","stripe_retrieve_payment_intent","stripe_retrieve_price","stripe_retrieve_product","stripe_retrieve_subscription","stripe_search_charges","stripe_search_customers","stripe_search_invoices","stripe_search_payment_intents","stripe_search_prices","stripe_search_products","stripe_search_subscriptions","stripe_send_invoice","stripe_update_charge","stripe_update_customer","stripe_update_invoice","stripe_update_payment_intent","stripe_update_price","stripe_update_product","stripe_update_subscription","stripe_void_invoice","sts_assume_role","sts_assume_role_with_saml","sts_assume_role_with_web_identity","sts_get_access_key_info","sts_get_caller_identity","sts_get_session_token","stt_assemblyai","stt_assemblyai_v2","stt_deepgram","stt_deepgram_v2","stt_elevenlabs","stt_elevenlabs_v2","stt_gemini","stt_gemini_v2","stt_whisper","stt_whisper_v2","supabase_count","supabase_delete","supabase_get_row","supabase_insert","supabase_introspect","supabase_invoke_function","supabase_query","supabase_rpc","supabase_storage_copy","supabase_storage_create_bucket","supabase_storage_create_signed_upload_url","supabase_storage_create_signed_url","supabase_storage_delete","supabase_storage_delete_bucket","supabase_storage_download","supabase_storage_empty_bucket","supabase_storage_get_public_url","supabase_storage_list","supabase_storage_list_buckets","supabase_storage_move","supabase_storage_update_bucket","supabase_storage_upload","supabase_text_search","supabase_update","supabase_upsert","supabase_vector_search","table_batch_insert_rows","table_create","table_delete_row","table_delete_rows_by_filter","table_get_row","table_get_schema","table_insert_row","table_list","table_query_rows","table_query_rows_v2","table_update_row","table_update_rows_by_filter","table_upsert_row","tailscale_approve_user","tailscale_authorize_device","tailscale_create_auth_key","tailscale_delete_auth_key","tailscale_delete_device","tailscale_delete_device_attribute","tailscale_delete_user","tailscale_expire_device_key","tailscale_get_acl","tailscale_get_auth_key","tailscale_get_device","tailscale_get_device_attributes","tailscale_get_device_routes","tailscale_get_dns_configuration","tailscale_get_dns_preferences","tailscale_get_dns_searchpaths","tailscale_get_split_dns","tailscale_get_tailnet_settings","tailscale_get_user","tailscale_list_auth_keys","tailscale_list_devices","tailscale_list_dns_nameservers","tailscale_list_users","tailscale_restore_user","tailscale_set_acl","tailscale_set_device_attribute","tailscale_set_device_name","tailscale_set_device_routes","tailscale_set_device_tags","tailscale_set_dns_configuration","tailscale_set_dns_nameservers","tailscale_set_dns_preferences","tailscale_set_dns_searchpaths","tailscale_set_split_dns","tailscale_set_user_role","tailscale_suspend_user","tailscale_update_device_key","tailscale_update_split_dns","tailscale_update_tailnet_settings","tailscale_validate_acl","tavily_crawl","tavily_extract","tavily_map","tavily_search","telegram_copy_message","telegram_delete_message","telegram_edit_message_text","telegram_forward_message","telegram_get_chat","telegram_get_chat_member","telegram_message","telegram_pin_message","telegram_send_animation","telegram_send_audio","telegram_send_chat_action","telegram_send_contact","telegram_send_document","telegram_send_location","telegram_send_photo","telegram_send_poll","telegram_send_video","telegram_set_message_reaction","telegram_unpin_message","temporal_cancel_workflow","temporal_count_workflows","temporal_create_schedule","temporal_delete_schedule","temporal_describe_schedule","temporal_describe_task_queue","temporal_describe_workflow","temporal_get_workflow_history","temporal_list_schedules","temporal_list_workflows","temporal_pause_schedule","temporal_query_workflow","temporal_reset_workflow","temporal_signal_with_start","temporal_signal_workflow","temporal_start_workflow","temporal_terminate_workflow","temporal_trigger_schedule","temporal_unpause_schedule","temporal_update_workflow","textract_analyze_expense","textract_analyze_id","textract_parser","textract_parser_v2","thinking_tool","thrive_add_audience_managers","thrive_add_audience_members","thrive_add_user_tags","thrive_create_assignment","thrive_create_audience","thrive_create_completion","thrive_create_user","thrive_delete_assignment","thrive_delete_audience","thrive_delete_user","thrive_get_activity","thrive_get_assignment","thrive_get_audience","thrive_get_completion","thrive_get_content","thrive_get_cpd_category","thrive_get_cpd_entry","thrive_get_cpd_requirement","thrive_get_enrolment","thrive_get_skill_levels","thrive_get_tag","thrive_get_user_by_id","thrive_get_user_by_ref","thrive_list_assignments","thrive_list_audience_managers","thrive_list_audience_members","thrive_list_audiences","thrive_list_completions","thrive_list_enrolments","thrive_list_tags","thrive_query_activities","thrive_query_content","thrive_query_cpd_categories","thrive_query_cpd_entries","thrive_query_cpd_requirements","thrive_query_cpd_user_summaries","thrive_remove_audience_manager","thrive_remove_audience_member","thrive_remove_user_tags","thrive_replace_audience_managers","thrive_replace_audience_members","thrive_search_users","thrive_suspend_user","thrive_update_assignment","thrive_update_audience","thrive_update_user","thrive_update_user_skills","tiktok_get_post_status","tiktok_get_user","tiktok_list_videos","tiktok_query_videos","tiktok_upload_video_draft","tinybird_append_datasource","tinybird_delete_datasource_rows","tinybird_events","tinybird_get_job","tinybird_query","tinybird_query_pipe","tinybird_truncate_datasource","tinyfish_cancel_run","tinyfish_fetch","tinyfish_get_run","tinyfish_list_profiles","tinyfish_list_runs","tinyfish_list_vault_items","tinyfish_run","tinyfish_run_async","tinyfish_search","trello_add_checklist","trello_add_checklist_item","trello_add_comment","trello_add_label","trello_add_member","trello_create_board","trello_create_card","trello_create_list","trello_delete_card","trello_get_actions","trello_get_board","trello_get_card","trello_list_cards","trello_list_lists","trello_list_members","trello_remove_label","trello_remove_member","trello_search","trello_update_card","trello_update_checklist_item","trello_update_list","trigger_dev_activate_schedule","trigger_dev_add_run_tags","trigger_dev_batch_trigger_task","trigger_dev_cancel_run","trigger_dev_complete_waitpoint_token","trigger_dev_create_env_var","trigger_dev_create_schedule","trigger_dev_create_waitpoint_token","trigger_dev_deactivate_schedule","trigger_dev_delete_env_var","trigger_dev_delete_schedule","trigger_dev_execute_query","trigger_dev_get_batch","trigger_dev_get_batch_results","trigger_dev_get_deployment","trigger_dev_get_env_var","trigger_dev_get_latest_deployment","trigger_dev_get_query_schema","trigger_dev_get_queue","trigger_dev_get_run","trigger_dev_get_run_events","trigger_dev_get_run_result","trigger_dev_get_run_trace","trigger_dev_get_schedule","trigger_dev_get_waitpoint_token","trigger_dev_import_env_vars","trigger_dev_list_deployments","trigger_dev_list_env_vars","trigger_dev_list_queues","trigger_dev_list_runs","trigger_dev_list_schedules","trigger_dev_list_timezones","trigger_dev_list_waitpoint_tokens","trigger_dev_override_queue_concurrency","trigger_dev_pause_queue","trigger_dev_promote_deployment","trigger_dev_replay_run","trigger_dev_reschedule_run","trigger_dev_reset_queue_concurrency","trigger_dev_resume_queue","trigger_dev_trigger_task","trigger_dev_update_env_var","trigger_dev_update_run_metadata","trigger_dev_update_schedule","tts_azure","tts_cartesia","tts_deepgram","tts_elevenlabs","tts_google","tts_openai","tts_playht","twilio_send_sms","twilio_voice_get_recording","twilio_voice_list_calls","twilio_voice_make_call","typeform_create_form","typeform_delete_form","typeform_files","typeform_get_form","typeform_insights","typeform_list_forms","typeform_responses","typeform_update_form","upstash_redis_command","upstash_redis_delete","upstash_redis_exists","upstash_redis_expire","upstash_redis_get","upstash_redis_hget","upstash_redis_hgetall","upstash_redis_hset","upstash_redis_incr","upstash_redis_incrby","upstash_redis_keys","upstash_redis_lpush","upstash_redis_lrange","upstash_redis_set","upstash_redis_setnx","upstash_redis_ttl","uptimerobot_create_alert_contact","uptimerobot_create_maintenance_window","uptimerobot_create_monitor","uptimerobot_create_psp","uptimerobot_delete_alert_contact","uptimerobot_delete_maintenance_window","uptimerobot_delete_monitor","uptimerobot_delete_psp","uptimerobot_get_account","uptimerobot_get_alert_contact","uptimerobot_get_incident","uptimerobot_get_maintenance_window","uptimerobot_get_monitor","uptimerobot_get_psp","uptimerobot_list_alert_contacts","uptimerobot_list_incidents","uptimerobot_list_maintenance_windows","uptimerobot_list_monitors","uptimerobot_list_psps","uptimerobot_pause_monitor","uptimerobot_start_monitor","uptimerobot_update_maintenance_window","uptimerobot_update_monitor","uptimerobot_update_psp","vanta_download_document_file","vanta_get_control","vanta_get_document","vanta_get_framework","vanta_get_person","vanta_get_policy","vanta_get_risk_scenario","vanta_get_test","vanta_get_vendor","vanta_get_vulnerable_asset","vanta_list_control_documents","vanta_list_control_tests","vanta_list_controls","vanta_list_document_uploads","vanta_list_documents","vanta_list_framework_controls","vanta_list_frameworks","vanta_list_monitored_computers","vanta_list_people","vanta_list_policies","vanta_list_risk_scenarios","vanta_list_test_entities","vanta_list_tests","vanta_list_vendors","vanta_list_vulnerabilities","vanta_list_vulnerability_remediations","vanta_list_vulnerable_assets","vanta_submit_document","vanta_upload_document_file","vercel_add_domain","vercel_add_project_domain","vercel_cancel_deployment","vercel_create_alias","vercel_create_check","vercel_create_deployment","vercel_create_dns_record","vercel_create_edge_config","vercel_create_env_var","vercel_create_project","vercel_create_webhook","vercel_delete_alias","vercel_delete_deployment","vercel_delete_dns_record","vercel_delete_domain","vercel_delete_edge_config","vercel_delete_env_var","vercel_delete_project","vercel_delete_webhook","vercel_get_alias","vercel_get_check","vercel_get_deployment","vercel_get_deployment_events","vercel_get_domain","vercel_get_domain_config","vercel_get_edge_config","vercel_get_edge_config_items","vercel_get_env_vars","vercel_get_project","vercel_get_team","vercel_get_user","vercel_get_webhook","vercel_list_aliases","vercel_list_checks","vercel_list_deployment_files","vercel_list_deployments","vercel_list_dns_records","vercel_list_domains","vercel_list_edge_configs","vercel_list_project_domains","vercel_list_projects","vercel_list_team_members","vercel_list_teams","vercel_list_webhooks","vercel_pause_project","vercel_promote_deployment","vercel_remove_project_domain","vercel_rerequest_check","vercel_unpause_project","vercel_update_check","vercel_update_dns_record","vercel_update_edge_config_items","vercel_update_env_var","vercel_update_project","vercel_update_project_domain","vercel_verify_project_domain","video_falai","video_luma","video_minimax","video_runway","video_veo","vision_tool","vision_tool_v2","wealthbox_read_contact","wealthbox_read_note","wealthbox_read_task","wealthbox_write_contact","wealthbox_write_note","wealthbox_write_task","webflow_create_item","webflow_delete_item","webflow_get_item","webflow_list_items","webflow_update_item","webhook_request","whatsapp_get_media","whatsapp_mark_read","whatsapp_send_interactive","whatsapp_send_media","whatsapp_send_message","whatsapp_send_reaction","whatsapp_send_template","whatsapp_upload_media","wikipedia_content","wikipedia_random","wikipedia_search","wikipedia_summary","windchill_check_in_document","windchill_check_in_documents","windchill_check_out_document","windchill_check_out_documents","windchill_create_document","windchill_create_documents","windchill_delete_document","windchill_delete_documents","windchill_download_attachment","windchill_download_primary_content","windchill_get_document","windchill_get_document_structure","windchill_get_primary_content","windchill_get_valid_state_transitions","windchill_list_attachments","windchill_list_documents","windchill_revise_document","windchill_revise_documents","windchill_set_lifecycle_state","windchill_undo_check_out_document","windchill_undo_check_out_documents","windchill_update_common_properties","windchill_update_document","windchill_update_document_security_labels","windchill_update_documents","windchill_upload_attachments","windchill_upload_primary_content","wiza_company_enrichment","wiza_get_credits","wiza_individual_reveal","wiza_prospect_search","wordpress_create_category","wordpress_create_comment","wordpress_create_page","wordpress_create_post","wordpress_create_tag","wordpress_delete_category","wordpress_delete_comment","wordpress_delete_media","wordpress_delete_page","wordpress_delete_post","wordpress_delete_tag","wordpress_get_category","wordpress_get_current_user","wordpress_get_media","wordpress_get_page","wordpress_get_post","wordpress_get_tag","wordpress_get_user","wordpress_list_categories","wordpress_list_comments","wordpress_list_media","wordpress_list_pages","wordpress_list_posts","wordpress_list_tags","wordpress_list_users","wordpress_search_content","wordpress_update_category","wordpress_update_comment","wordpress_update_page","wordpress_update_post","wordpress_update_tag","wordpress_upload_media","workday_assign_onboarding","workday_change_job","workday_create_prehire","workday_get_compensation","workday_get_organizations","workday_get_worker","workday_hire_employee","workday_list_workers","workday_terminate_worker","workday_update_worker","workflow_executor","x_create_bookmark","x_create_tweet","x_delete_bookmark","x_delete_tweet","x_get_blocking","x_get_bookmarks","x_get_followers","x_get_following","x_get_liked_tweets","x_get_liking_users","x_get_me","x_get_personalized_trends","x_get_quote_tweets","x_get_retweeted_by","x_get_trends_by_woeid","x_get_tweets_by_ids","x_get_usage","x_get_user_mentions","x_get_user_timeline","x_get_user_tweets","x_hide_reply","x_manage_block","x_manage_follow","x_manage_like","x_manage_mute","x_manage_retweet","x_read","x_search","x_search_tweets","x_search_users","x_user","x_write","youcom_answer","youcom_finance_research","youcom_get_account_balance","youcom_get_contents","youcom_get_research_task","youcom_research","youcom_search","youcom_search_images","youtube_channel_info","youtube_channel_playlists","youtube_channel_videos","youtube_comments","youtube_playlist_items","youtube_search","youtube_trending","youtube_video_categories","youtube_video_details","zendesk_autocomplete_organizations","zendesk_create_organization","zendesk_create_organizations_bulk","zendesk_create_ticket","zendesk_create_tickets_bulk","zendesk_create_user","zendesk_create_users_bulk","zendesk_delete_organization","zendesk_delete_ticket","zendesk_delete_user","zendesk_get_current_user","zendesk_get_organization","zendesk_get_organizations","zendesk_get_ticket","zendesk_get_tickets","zendesk_get_user","zendesk_get_users","zendesk_merge_tickets","zendesk_search","zendesk_search_count","zendesk_search_users","zendesk_update_organization","zendesk_update_ticket","zendesk_update_tickets_bulk","zendesk_update_user","zendesk_update_users_bulk","zep_add_messages","zep_add_user","zep_create_thread","zep_delete_thread","zep_get_context","zep_get_messages","zep_get_threads","zep_get_user","zep_get_user_threads","zerobounce_get_credits","zerobounce_verify_email","zoho_desk_add_comment","zoho_desk_create_account","zoho_desk_create_contact","zoho_desk_create_ticket","zoho_desk_delete_comment","zoho_desk_get_account","zoho_desk_get_agent","zoho_desk_get_attachment","zoho_desk_get_comment","zoho_desk_get_contact","zoho_desk_get_department","zoho_desk_get_thread","zoho_desk_get_ticket","zoho_desk_list_accounts","zoho_desk_list_agents","zoho_desk_list_comments","zoho_desk_list_contacts","zoho_desk_list_departments","zoho_desk_list_organizations","zoho_desk_list_threads","zoho_desk_list_tickets","zoho_desk_move_ticket","zoho_desk_search_accounts","zoho_desk_search_contacts","zoho_desk_search_tickets","zoho_desk_send_reply","zoho_desk_update_account","zoho_desk_update_comment","zoho_desk_update_contact","zoho_desk_update_ticket","zoom_create_meeting","zoom_delete_meeting","zoom_delete_recording","zoom_get_meeting","zoom_get_meeting_invitation","zoom_get_meeting_recordings","zoom_list_meetings","zoom_list_past_participants","zoom_list_recordings","zoom_update_meeting","zoominfo_enrich_companies","zoominfo_enrich_contacts","zoominfo_search_companies","zoominfo_search_contacts","zoominfo_search_intent","zoominfo_search_news"]' ) export default toolIds diff --git a/apps/sim/tools/generated/tool-metadata.ts b/apps/sim/tools/generated/tool-metadata.ts index 10a1ab3effd..6b6e3e2d86c 100644 --- a/apps/sim/tools/generated/tool-metadata.ts +++ b/apps/sim/tools/generated/tool-metadata.ts @@ -3,7 +3,7 @@ /** Serializable metadata for every built-in tool, keyed by tool id. */ const toolMetadata: Record = JSON.parse( - '{"a2a_cancel_task":{"id":"a2a_cancel_task","name":"A2A Cancel Task","description":"Request cancellation of an in-progress A2A task.","version":"1.0.0","params":{"agentUrl":{"type":"string","required":true,"visibility":"user-only","description":"The A2A agent endpoint URL"},"taskId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The task ID to cancel"},"apiKey":{"type":"string","required":false,"visibility":"user-only","description":"API key for authentication (if required)"}},"hostedApiKey":"none"},"a2a_get_agent_card":{"id":"a2a_get_agent_card","name":"A2A Get Agent Card","description":"Fetch the Agent Card (discovery document) for an external A2A agent.","version":"1.0.0","params":{"agentUrl":{"type":"string","required":true,"visibility":"user-only","description":"The A2A agent endpoint URL"},"apiKey":{"type":"string","required":false,"visibility":"user-only","description":"API key for authentication (if required)"}},"hostedApiKey":"none"},"a2a_get_task":{"id":"a2a_get_task","name":"A2A Get Task","description":"Retrieve the current state and result of an A2A task.","version":"1.0.0","params":{"agentUrl":{"type":"string","required":true,"visibility":"user-only","description":"The A2A agent endpoint URL"},"taskId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The task ID to retrieve"},"historyLength":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of history messages to include"},"apiKey":{"type":"string","required":false,"visibility":"user-only","description":"API key for authentication (if required)"}},"hostedApiKey":"none"},"a2a_send_message":{"id":"a2a_send_message","name":"A2A Send Message","description":"Send a message to an external A2A agent and return its response.","version":"1.0.0","params":{"agentUrl":{"type":"string","required":true,"visibility":"user-only","description":"The A2A agent endpoint URL"},"message":{"type":"string","required":true,"visibility":"user-or-llm","description":"The message text to send"},"data":{"type":"json","required":false,"visibility":"user-or-llm","description":"Optional structured JSON data to attach"},"files":{"type":"json","required":false,"visibility":"user-or-llm","description":"Optional files to attach"},"taskId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Existing task ID to continue"},"contextId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Conversation context ID to continue"},"apiKey":{"type":"string","required":false,"visibility":"user-only","description":"API key for authentication (if required)"}},"hostedApiKey":"none"},"affinity_batch_update_entity_fields":{"id":"affinity_batch_update_entity_fields","name":"Affinity Batch Update Entity Fields","description":"Write up to 100 non-list field values on one company or person in a single request.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which entity to write the fields on: companies or persons"},"entityId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of that company or person"},"updates":{"type":"json","required":true,"visibility":"user-or-llm","description":"Up to 100 field updates as [{\\"id\\":\\"\\",\\"value\\":{\\"type\\":\\"…\\",\\"data\\":…}}], using the same value shapes as a single field update"}},"hostedApiKey":"none"},"affinity_batch_update_list_entry_fields":{"id":"affinity_batch_update_list_entry_fields","name":"Affinity Batch Update List Entry Fields","description":"Write up to 100 field values on one list row in a single request. Requires the \\"Export data from Lists\\" permission.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"listEntryId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list entry ID"},"updates":{"type":"json","required":true,"visibility":"user-or-llm","description":"Up to 100 field updates as [{\\"id\\":\\"\\",\\"value\\":{\\"type\\":\\"…\\",\\"data\\":…}}], using the same value shapes as a single field update"}},"hostedApiKey":"none"},"affinity_create_list":{"id":"affinity_create_list","name":"Affinity Create List","description":"Create a list. Its type fixes which entities it can hold, and the API key holder becomes its creator and owner.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the new list"},"type":{"type":"string","required":true,"visibility":"user-or-llm","description":"Entity kind the list holds: company, opportunity, or person"},"isPublic":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Whether everyone in the organization can see the list"}},"hostedApiKey":"none"},"affinity_create_list_field_dropdown_option":{"id":"affinity_create_list_field_dropdown_option","name":"Affinity Create List Field Dropdown Option","description":"Add a selectable option to a dropdown field on a list. A ranked or status option also needs a rank and a color.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"fieldId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The dropdown field ID on that list"},"type":{"type":"string","required":true,"visibility":"user-or-llm","description":"Kind of option to create, matching the field. dropdown takes only a label; ranked-dropdown also requires rank and color; status-dropdown additionally requires a status category. Sending a field the kind does not accept is rejected"},"text":{"type":"string","required":true,"visibility":"user-or-llm","description":"The option label"},"rank":{"type":"number","required":false,"visibility":"user-or-llm","description":"Sort order. Required on a ranked-dropdown or status-dropdown option"},"color":{"type":"string","required":false,"visibility":"user-or-llm","description":"Option color: white, gray, blue, green, purple, orange, or red. Required on a ranked-dropdown or status-dropdown option"},"statusCategory":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pipeline meaning of the option: open, won, lost, or on-hold. Status-dropdown options only"},"winRate":{"type":"number","required":false,"visibility":"user-or-llm","description":"Expected win rate of the status. Status-dropdown options only"}},"hostedApiKey":"none"},"affinity_create_merge":{"id":"affinity_create_merge","name":"Affinity Create Merge","description":"Fold a duplicate company or person into the record you are keeping. The merge runs asynchronously — poll the returned task to see it finish. Requires the \\"Manage duplicates\\" permission and an admin role.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"What to merge: companies or persons"},"primaryId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the record to keep"},"duplicateId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the duplicate record to fold in"}},"hostedApiKey":"none"},"affinity_create_note":{"id":"affinity_create_note","name":"Affinity Create Note","description":"Write a note — attached to companies, persons, and opportunities, anchored to a meeting, call, or chat message, or posted as a reply to an existing note.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"type":{"type":"string","required":true,"visibility":"user-or-llm","description":"Note shape: entities to attach it to records, interaction to anchor it to a meeting, call, or chat message, or user-reply to reply to a note"},"html":{"type":"string","required":true,"visibility":"user-or-llm","description":"The note body as HTML"},"companyIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Companies to attach the note to, e.g. [1, 2]. Not used on a reply"},"personIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Persons to attach the note to, e.g. [1, 2]. Not used on a reply"},"opportunityIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Opportunities to attach the note to, e.g. [1, 2]. Not used on a reply"},"interactionId":{"type":"string","required":false,"visibility":"user-or-llm","description":"The interaction to anchor the note to. Required for an interaction note"},"interactionType":{"type":"string","required":false,"visibility":"user-or-llm","description":"Kind of the anchoring interaction: meeting, call, or chat-message. Required for an interaction note"},"parentId":{"type":"string","required":false,"visibility":"user-or-llm","description":"The note being replied to. Required for a user-reply note"},"creatorId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Attribute the note to another internal person. Defaults to the API key holder"},"createdAt":{"type":"string","required":false,"visibility":"user-or-llm","description":"Backdate the note to this ISO 8601 timestamp"}},"hostedApiKey":"none"},"affinity_create_reminder":{"id":"affinity_create_reminder","name":"Affinity Create Reminder","description":"Create a reminder on one company, person, or opportunity. A recurring reminder resets whenever the chosen signal happens instead of firing once.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"type":{"type":"string","required":true,"visibility":"user-or-llm","description":"one-time to fire once, or recurring to reset on a signal"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"What the reminder is about: company, person, or opportunity"},"entityId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of that company, person, or opportunity"},"dueDate":{"type":"string","required":false,"visibility":"user-or-llm","description":"When the reminder is due, as an ISO 8601 timestamp. Required for a one-time reminder; on a recurring one Affinity computes it from the period when omitted"},"content":{"type":"string","required":false,"visibility":"user-or-llm","description":"What the reminder says"},"ownerId":{"type":"string","required":true,"visibility":"user-or-llm","description":"User the reminder is assigned to. Must be an internal user. The API key holder is recorded as the creator, which is a separate field"},"resetTrigger":{"type":"string","required":false,"visibility":"user-or-llm","description":"What restarts a recurring reminder: interaction, email, or event. Required when the type is recurring"},"periodDays":{"type":"number","required":false,"visibility":"user-or-llm","description":"Days between firings of a recurring reminder. Required when the type is recurring"}},"hostedApiKey":"none"},"affinity_delete_list_field_dropdown_option":{"id":"affinity_delete_list_field_dropdown_option","name":"Affinity Delete List Field Dropdown Option","description":"Permanently delete a dropdown option on a list field. Every list entry currently set to it is cleared, and those values cannot be recovered.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"fieldId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The dropdown field ID on that list"},"dropdownOptionId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The dropdown option ID to delete"}},"hostedApiKey":"none"},"affinity_delete_note":{"id":"affinity_delete_note","name":"Affinity Delete Note","description":"Delete a note you created. Deleting a root note also deletes its replies; deleting a reply removes only that reply.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"noteId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The note ID to delete"}},"hostedApiKey":"none"},"affinity_get_company":{"id":"affinity_get_company","name":"Affinity Get Company","description":"Look up one company by ID. Field data is returned only for the Field IDs or Field Types asked for.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"companyId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The company ID"},"fieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs to return values for, e.g. [\\"affinity-data-location\\"]. Mutually exclusive with Field Types"},"fieldTypes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field categories to return values for: enriched, global, or relationship-intelligence. Mutually exclusive with Field IDs"}},"hostedApiKey":"none"},"affinity_get_current_user":{"id":"affinity_get_current_user","name":"Affinity Get Current User","description":"Verify an Affinity API key and return the tenant, the user behind the key, and the scopes the grant carries.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"}},"hostedApiKey":"none"},"affinity_get_entity_field_value":{"id":"affinity_get_entity_field_value","name":"Affinity Get Entity Field Value","description":"Read one non-list field value from a company or person.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which entity to read the field from: companies or persons"},"entityId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of that company or person"},"fieldId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The field ID to read"}},"hostedApiKey":"none"},"affinity_get_list":{"id":"affinity_get_list","name":"Affinity Get List","description":"Read one list — its name, type, owner, and privacy setting.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"}},"hostedApiKey":"none"},"affinity_get_list_entry":{"id":"affinity_get_list_entry","name":"Affinity Get List Entry","description":"Read one row of a list with its entity. Field data is returned only for the Field IDs or Field Types asked for.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"listEntryId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list entry ID"},"fieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs to return values for, e.g. [\\"affinity-data-location\\"]. Mutually exclusive with Field Types"},"fieldTypes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field categories to return values for: enriched, global, list, or relationship-intelligence. Mutually exclusive with Field IDs"}},"hostedApiKey":"none"},"affinity_get_list_entry_field":{"id":"affinity_get_list_entry_field","name":"Affinity Get List Entry Field","description":"Read one field value on a list row.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"listEntryId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list entry ID"},"fieldId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The field ID to read"}},"hostedApiKey":"none"},"affinity_get_list_field_dropdown_option":{"id":"affinity_get_list_field_dropdown_option","name":"Affinity Get List Field Dropdown Option","description":"Read one dropdown option on a list field.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"fieldId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The dropdown field ID on that list"},"dropdownOptionId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The dropdown option ID"}},"hostedApiKey":"none"},"affinity_get_merge":{"id":"affinity_get_merge","name":"Affinity Get Merge","description":"Read the status of one company or person merge, including why it failed if it did.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which merge to read: companies or persons"},"mergeId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The merge ID"}},"hostedApiKey":"none"},"affinity_get_merge_task":{"id":"affinity_get_merge_task","name":"Affinity Get Merge Task","description":"Read one merge task and how its merges are progressing. Poll this after starting a merge.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which merge task to read: companies or persons"},"taskId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The merge task ID"}},"hostedApiKey":"none"},"affinity_get_note":{"id":"affinity_get_note","name":"Affinity Get Note","description":"Read one note with its body, author, mentions, and attached records.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"noteId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The note ID"},"includes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Extra properties to return, e.g. [\\"repliesCount\\",\\"personsPreview\\",\\"companiesPreview\\",\\"opportunitiesPreview\\"]. Those four fields are omitted unless requested here"}},"hostedApiKey":"none"},"affinity_get_opportunity":{"id":"affinity_get_opportunity","name":"Affinity Get Opportunity","description":"Read one opportunity and the list it belongs to. Its field data lives on the list entry.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"opportunityId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The opportunity ID"}},"hostedApiKey":"none"},"affinity_get_person":{"id":"affinity_get_person","name":"Affinity Get Person","description":"Look up one person by ID. Field data is returned only for the Field IDs or Field Types asked for.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"personId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The person ID"},"fieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs to return values for, e.g. [\\"affinity-data-location\\"]. Mutually exclusive with Field Types"},"fieldTypes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field categories to return values for: enriched, global, or relationship-intelligence. Mutually exclusive with Field IDs"}},"hostedApiKey":"none"},"affinity_get_saved_view":{"id":"affinity_get_saved_view","name":"Affinity Get Saved View","description":"Read one saved view — its name, kind, and creation date.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"viewId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The saved view ID"}},"hostedApiKey":"none"},"affinity_get_transcript":{"id":"affinity_get_transcript","name":"Affinity Get Transcript","description":"Read one transcript with its first 100 fragments. Page the fragments endpoint for a longer meeting.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"transcriptId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The transcript ID"}},"hostedApiKey":"none"},"affinity_get_user":{"id":"affinity_get_user","name":"Affinity Get User","description":"Read one internal user. A user and their person record share the same numeric ID, so a person ID works here.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"userId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The user ID, which is also their person ID"}},"hostedApiKey":"none"},"affinity_list_calls":{"id":"affinity_list_calls","name":"Affinity List Calls","description":"Page through logged calls and their participants. Only calls the API key holder can see are returned.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression, e.g. \\"createdAt>=2026-01-01\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_chat_messages":{"id":"affinity_list_chat_messages","name":"Affinity List Chat Messages","description":"Page through logged chat messages and their participants. Only messages the API key holder can see are returned.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression, e.g. \\"createdAt>=2026-01-01\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_companies":{"id":"affinity_list_companies","name":"Affinity List Companies","description":"Page through companies. Companies come back without field data unless Field IDs or Field Types asks for it.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"ids":{"type":"json","required":false,"visibility":"user-or-llm","description":"Restrict the page to these company IDs, e.g. [1, 2, 3]"},"fieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs to return values for, e.g. [\\"affinity-data-location\\"]. Mutually exclusive with Field Types"},"fieldTypes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field categories to return values for: enriched, global, or relationship-intelligence. Mutually exclusive with Field IDs"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_coworker_connections":{"id":"affinity_list_coworker_connections","name":"Affinity List Coworker Connections","description":"Find warm paths into a company through shared work history: who in your Affinity data once worked alongside the people you want to reach. Grouped by target, strongest first.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filter":{"type":"string","required":true,"visibility":"user-or-llm","description":"Required scope. The only supported filter is target.currentCompany.id, e.g. \\"target.currentCompany.id=123\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of targets to return per page, 1-50. Defaults to 20"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_emails":{"id":"affinity_list_emails","name":"Affinity List Emails","description":"Page through email metadata — subject, participants, and timestamps. Affinity never exposes email bodies through the API.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression, e.g. \\"createdAt>=2026-01-01\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_entity_field_values":{"id":"affinity_list_entity_field_values","name":"Affinity List Entity Field Values","description":"Page through a company\'s or person\'s non-list field values. List fields are not returned here — read those through the list entry.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which entity to read field values from: companies or persons"},"entityId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of that company or person"},"ids":{"type":"json","required":false,"visibility":"user-or-llm","description":"Restrict to these field IDs. Mutually exclusive with Field Types"},"types":{"type":"json","required":false,"visibility":"user-or-llm","description":"Restrict to these field categories: enriched, global, relationship-intelligence. Mutually exclusive with Field IDs"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 20"}},"hostedApiKey":"none"},"affinity_list_entity_list_entries":{"id":"affinity_list_entity_list_entries","name":"Affinity List Entity List Entries","description":"Page through a company\'s or person\'s rows across every list, each carrying that list\'s field values and when the entity was added.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which entity to look up the rows of: companies or persons"},"entityId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of that company or person"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_entity_lists":{"id":"affinity_list_entity_lists","name":"Affinity List Entity Lists","description":"List every list a company or person appears on that the caller can view.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which entity to look up the lists of: companies or persons"},"entityId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of that company or person"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_entity_notes":{"id":"affinity_list_entity_notes","name":"Affinity List Entity Notes","description":"List the notes relevant to one company, person, or opportunity — directly attached notes plus notes reaching it through its people and meetings.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which entity the notes hang off: companies, persons, or opportunities"},"entityId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of that company, person, or opportunity"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression, e.g. \\"createdAt>=2026-01-01\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_entity_relationships":{"id":"affinity_list_entity_relationships","name":"Affinity List Entity Relationships","description":"List who knows a company or person, scored 0.0 to 1.0 by how much the two actually interact. Strongest first by default.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which entity to look up relationships for: companies or persons"},"entityId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of that company or person"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression. This endpoint filters on interactionScore only, e.g. \\"interactionScore>=0.5\\""},"orderBy":{"type":"json","required":false,"visibility":"user-or-llm","description":"Sort order: [\\"interactionScore\\"] for weakest first, [\\"-interactionScore\\"] for strongest first (the default)"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_field_dropdown_options":{"id":"affinity_list_field_dropdown_options","name":"Affinity List Field Dropdown Options","description":"List the selectable options on a dropdown or ranked-dropdown company or person field. Writing such a field needs the option ID, not its text.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which field family the field belongs to: companies or persons"},"fieldId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The dropdown or ranked-dropdown field ID"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_field_metadata":{"id":"affinity_list_field_metadata","name":"Affinity List Field Metadata","description":"List the non-list company or person fields, with the value type, filter operators, and sort support of each. Start here to find the Field IDs the read and write tools take.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which fields to describe: companies or persons"},"includes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Extra properties to return: [\\"filterability\\",\\"sortability\\"]. Both are omitted unless requested here"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression. This endpoint filters on name only, e.g. \\"name=~Status\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_field_value_changes":{"id":"affinity_list_field_value_changes","name":"Affinity List Field Value Changes","description":"Page through field value changes across the whole workspace. Built for delta sync: follow nextCursor to the end of a run, then resume from the last cursor next time.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression over field.id, listEntry.id, changer.id, changedAt, or actionType. Resume a sync with e.g. \\"changedAt>2026-06-01T12:00:00Z\\""},"orderBy":{"type":"json","required":false,"visibility":"user-or-llm","description":"Sort order: [\\"changedAt\\"] for oldest first (the default), [\\"-changedAt\\"] for newest first"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_investor_executive_connections":{"id":"affinity_list_investor_executive_connections","name":"Affinity List Investor Executive Connections","description":"Find warm paths into a company through investment history: which investors in your Affinity data backed a company the people you want to reach once led. Grouped by target, strongest first.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filter":{"type":"string","required":true,"visibility":"user-or-llm","description":"Required scope. The only supported filter is target.currentCompany.id, e.g. \\"target.currentCompany.id=123\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of targets to return per page, 1-50. Defaults to 20"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_list_entries":{"id":"affinity_list_list_entries","name":"Affinity List List Entries","description":"Page through the rows of a list. Rows come back without field data unless Field IDs or Field Types asks for it.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"fieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs to return values for, e.g. [\\"affinity-data-location\\"]. Mutually exclusive with Field Types"},"fieldTypes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field categories to return values for: enriched, global, list, or relationship-intelligence. Mutually exclusive with Field IDs"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_list_entry_field_value_changes":{"id":"affinity_list_list_entry_field_value_changes","name":"Affinity List List Entry Field Value Changes","description":"Page through the history of one list row — who changed which field, when, and to what.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"listEntryId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list entry ID"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression over field.id, changer.id, changedAt, or actionType, e.g. \\"field.id=field-1234\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_list_entry_fields":{"id":"affinity_list_list_entry_fields","name":"Affinity List List Entry Fields","description":"Page through every field value on one list row, including the list-specific columns. All fields are returned unless narrowed.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"listEntryId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list entry ID"},"ids":{"type":"json","required":false,"visibility":"user-or-llm","description":"Restrict to these field IDs. Mutually exclusive with Field Types"},"types":{"type":"json","required":false,"visibility":"user-or-llm","description":"Restrict to these field categories: enriched, global, list, relationship-intelligence. Mutually exclusive with Field IDs"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 20"}},"hostedApiKey":"none"},"affinity_list_list_field_dropdown_options":{"id":"affinity_list_list_field_dropdown_options","name":"Affinity List List Field Dropdown Options","description":"List the selectable options on a dropdown, ranked-dropdown, or status-dropdown field of a list.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"fieldId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The dropdown field ID on that list"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_list_fields":{"id":"affinity_list_list_fields","name":"Affinity List List Fields","description":"List the fields available on one list, including its list-specific columns. Use these Field IDs when reading or writing list entries.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"includes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Extra properties to return: [\\"filterability\\",\\"sortability\\"]. Both are omitted unless requested here"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression. This endpoint filters on name only, e.g. \\"name=~Stage\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_lists":{"id":"affinity_list_lists","name":"Affinity List Lists","description":"Page through the lists in the organization that the caller can view.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"term":{"type":"string","required":false,"visibility":"user-or-llm","description":"Case-insensitive substring match on the list name"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_meetings":{"id":"affinity_list_meetings","name":"Affinity List Meetings","description":"Page through past and upcoming meetings with their organizer and attendees.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression, e.g. \\"createdAt>=2026-01-01\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_merge_tasks":{"id":"affinity_list_merge_tasks","name":"Affinity List Merge Tasks","description":"Page through merge tasks, each summarizing how many of its merges are in progress, succeeded, or failed.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which merge tasks to list: companies or persons"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression. This endpoint filters on status only, e.g. \\"status=in-progress\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_merges":{"id":"affinity_list_merges","name":"Affinity List Merges","description":"Page through the company or person merges the organization has run, with the status and the records involved in each.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which merges to list: companies or persons"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression over status or taskId, e.g. \\"status=failed\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_note_attached_companies":{"id":"affinity_list_note_attached_companies","name":"Affinity List Note Attached Companies","description":"List the companies directly attached to one note.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"noteId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The note ID"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_note_attached_opportunities":{"id":"affinity_list_note_attached_opportunities","name":"Affinity List Note Attached Opportunities","description":"List the opportunities directly attached to one note.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"noteId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The note ID"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_note_attached_persons":{"id":"affinity_list_note_attached_persons","name":"Affinity List Note Attached Persons","description":"List the persons directly attached to one note.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"noteId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The note ID"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_note_replies":{"id":"affinity_list_note_replies","name":"Affinity List Note Replies","description":"Page through the replies on one note, including AI Notetaker replies.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"noteId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The note ID whose replies to read"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression, e.g. \\"createdAt>=2026-01-01\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_notes":{"id":"affinity_list_notes","name":"Affinity List Notes","description":"Page through every note the caller can see. Replies are excluded.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"includes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Extra properties to return, e.g. [\\"repliesCount\\",\\"personsPreview\\",\\"companiesPreview\\",\\"opportunitiesPreview\\"]. Those four fields are omitted unless requested here"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression, e.g. \\"createdAt>=2026-01-01\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_opportunities":{"id":"affinity_list_opportunities","name":"Affinity List Opportunities","description":"Page through opportunities. Field data lives on the list entry, not here — read it through the list or saved view the opportunity belongs to.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"ids":{"type":"json","required":false,"visibility":"user-or-llm","description":"Restrict the page to these opportunity IDs, e.g. [1, 2, 3]"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_persons":{"id":"affinity_list_persons","name":"Affinity List Persons","description":"Page through persons. Persons come back without field data unless Field IDs or Field Types asks for it.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"ids":{"type":"json","required":false,"visibility":"user-or-llm","description":"Restrict the page to these person IDs, e.g. [1, 2, 3]"},"fieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs to return values for, e.g. [\\"affinity-data-location\\"]. Mutually exclusive with Field Types"},"fieldTypes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field categories to return values for: enriched, global, or relationship-intelligence. Mutually exclusive with Field IDs"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_reminders":{"id":"affinity_list_reminders","name":"Affinity List Reminders","description":"Page through the reminders the caller can see. Filter by status to surface what is overdue.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression, e.g. \\"createdAt>=2026-01-01\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_saved_view_entries":{"id":"affinity_list_saved_view_entries","name":"Affinity List Saved View Entries","description":"Page through the rows of a saved view. The view\'s own filters and columns decide which rows and which field data come back.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"viewId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The saved view ID"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_saved_views":{"id":"affinity_list_saved_views","name":"Affinity List Saved Views","description":"List the saved views on a list that the caller can view.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_list_transcript_fragments":{"id":"affinity_list_transcript_fragments","name":"Affinity List Transcript Fragments","description":"Page through everything said in a meeting, segment by segment with the speaker.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"transcriptId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The transcript ID"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_transcripts":{"id":"affinity_list_transcripts","name":"Affinity List Transcripts","description":"Page through meeting transcript metadata. Read one transcript to get what was actually said.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression, e.g. \\"createdAt>=2026-01-01\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_list_users":{"id":"affinity_list_users","name":"Affinity List Users","description":"Page through the internal users in the organization. Email addresses and roles are returned only to callers with the \\"Manage Users\\" permission.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"term":{"type":"string","required":false,"visibility":"user-or-llm","description":"Case-insensitive match across first name, last name, and primary email"},"filter":{"type":"string","required":false,"visibility":"user-or-llm","description":"Affinity Filtering Language expression over id or status, e.g. \\"status=active\\""},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_search_companies":{"id":"affinity_search_companies","name":"Affinity Search Companies","description":"Search companies by filters, sorts, and a free-text term. Requires the \\"Export All Organizations directory\\" permission.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filters":{"type":"json","required":false,"visibility":"user-or-llm","description":"Filter group as {operator: \\"and\\"|\\"or\\", filters: [...]}, at most 50 leaves. Each leaf is {valueType, fieldId, operator, value}, and a leaf may itself be a nested group"},"searchTerm":{"type":"string","required":false,"visibility":"user-or-llm","description":"Free-text term matched against the searchable fields. At least 3 characters"},"searchFieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs the search term is matched against. Defaults to the searchable fields"},"sorts":{"type":"json","required":false,"visibility":"user-or-llm","description":"Sort order as [{fieldId, direction: \\"asc\\"|\\"desc\\", attributeId?}], up to 5, applied in order"},"fieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs to return values for, e.g. [\\"affinity-data-location\\"]. Mutually exclusive with Field Types"},"fieldTypes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field categories to return values for: enriched, global, or relationship-intelligence. Mutually exclusive with Field IDs"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_search_files":{"id":"affinity_search_files","name":"Affinity Search Files","description":"Search files by keyword, ordered by relevance. Narrow to specific files or to one company, or leave both unset to search the whole account.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"prompt":{"type":"string","required":true,"visibility":"user-or-llm","description":"What to search for. Between 3 and 500 characters"},"ids":{"type":"json","required":false,"visibility":"user-or-llm","description":"Restrict the search to these file IDs. Cannot be combined with Company ID"},"companyId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Restrict the search to one company\'s files. Cannot be combined with file IDs"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of files to return, 1-100. Defaults to 20"}},"hostedApiKey":"none"},"affinity_search_list_entries":{"id":"affinity_search_list_entries","name":"Affinity Search List Entries","description":"Search the rows of one list by filters, sorts, and a free-text term. Requires the \\"Export data from Lists\\" permission.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID to search"},"filters":{"type":"json","required":false,"visibility":"user-or-llm","description":"Filter group as {operator: \\"and\\"|\\"or\\", filters: [...]}, at most 50 leaves. Each leaf is {valueType, fieldId, operator, value}, and a leaf may itself be a nested group"},"searchTerm":{"type":"string","required":false,"visibility":"user-or-llm","description":"Free-text term matched against the searchable fields. At least 3 characters"},"searchFieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs the search term is matched against. Defaults to the searchable fields"},"sorts":{"type":"json","required":false,"visibility":"user-or-llm","description":"Sort order as [{fieldId, direction: \\"asc\\"|\\"desc\\", attributeId?}], up to 5, applied in order"},"fieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs to return values for, e.g. [\\"affinity-data-location\\"]. Mutually exclusive with Field Types"},"fieldTypes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field categories to return values for: enriched, global, list, or relationship-intelligence. Mutually exclusive with Field IDs"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_search_notes":{"id":"affinity_search_notes","name":"Affinity Search Notes","description":"Search notes by keyword, ordered by relevance. Narrow to specific notes or to one company, or leave both unset to search the whole account.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"prompt":{"type":"string","required":true,"visibility":"user-or-llm","description":"What to search for. Between 3 and 500 characters"},"ids":{"type":"json","required":false,"visibility":"user-or-llm","description":"Restrict the search to these note IDs. Cannot be combined with Company ID"},"companyId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Restrict the search to one company\'s notes. Cannot be combined with note IDs"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of notes to return, 1-100. Defaults to 20"}},"hostedApiKey":"none"},"affinity_search_persons":{"id":"affinity_search_persons","name":"Affinity Search Persons","description":"Search persons by filters, sorts, and a free-text term. Requires the \\"Export All People directory\\" permission.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"filters":{"type":"json","required":false,"visibility":"user-or-llm","description":"Filter group as {operator: \\"and\\"|\\"or\\", filters: [...]}, at most 50 leaves. Each leaf is {valueType, fieldId, operator, value}, and a leaf may itself be a nested group"},"searchTerm":{"type":"string","required":false,"visibility":"user-or-llm","description":"Free-text term matched against the searchable fields. At least 3 characters"},"searchFieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs the search term is matched against. Defaults to the searchable fields"},"sorts":{"type":"json","required":false,"visibility":"user-or-llm","description":"Sort order as [{fieldId, direction: \\"asc\\"|\\"desc\\", attributeId?}], up to 5, applied in order"},"fieldIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field IDs to return values for, e.g. [\\"affinity-data-location\\"]. Mutually exclusive with Field Types"},"fieldTypes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Field categories to return values for: enriched, global, or relationship-intelligence. Mutually exclusive with Field IDs"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous page, returned as nextCursor or prevCursor"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to return per page, 1-100. Defaults to 100"},"totalCount":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the total size of the collection. Costs an extra query"}},"hostedApiKey":"none"},"affinity_semantic_search":{"id":"affinity_semantic_search","name":"Affinity Semantic Search","description":"Find companies from a description in plain language — industry, technology, stage, or business model. Currently searches companies only.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"prompt":{"type":"string","required":true,"visibility":"user-or-llm","description":"What to look for, in plain language, e.g. \\"climate tech companies in our pipeline\\". Up to 500 characters"},"listIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Restrict the search to companies on these lists, e.g. [1, 2]"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of companies to return, 1-100. Defaults to 100"}},"hostedApiKey":"none"},"affinity_update_entity_field_value":{"id":"affinity_update_entity_field_value","name":"Affinity Update Entity Field Value","description":"Write one non-list field value on a company or person. The value type must match how the field is defined.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"entityType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Which entity to write the field on: companies or persons"},"entityId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of that company or person"},"fieldId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The field ID to write"},"value":{"type":"json","required":true,"visibility":"user-or-llm","description":"The new value as {type, data}, where type matches the field\'s value type. Examples: {\\"type\\":\\"text\\",\\"data\\":\\"Series B\\"}, {\\"type\\":\\"number\\",\\"data\\":42}, {\\"type\\":\\"dropdown\\",\\"data\\":{\\"dropdownOptionId\\":7}}, {\\"type\\":\\"person\\",\\"data\\":{\\"id\\":123}}, {\\"type\\":\\"person-multi\\",\\"data\\":[{\\"id\\":123}]}. Pass data as null to clear the field"}},"hostedApiKey":"none"},"affinity_update_list_entry_field":{"id":"affinity_update_list_entry_field","name":"Affinity Update List Entry Field","description":"Write one field value on a list row. Requires the \\"Export data from Lists\\" permission.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"listEntryId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list entry ID"},"fieldId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The field ID to write"},"value":{"type":"json","required":true,"visibility":"user-or-llm","description":"The new value as {type, data}, where type matches the field\'s value type. Examples: {\\"type\\":\\"text\\",\\"data\\":\\"Series B\\"}, {\\"type\\":\\"number\\",\\"data\\":42}, {\\"type\\":\\"dropdown\\",\\"data\\":{\\"dropdownOptionId\\":7}}, {\\"type\\":\\"person\\",\\"data\\":{\\"id\\":123}}, {\\"type\\":\\"person-multi\\",\\"data\\":[{\\"id\\":123}]}. Pass data as null to clear the field"}},"hostedApiKey":"none"},"affinity_update_list_field_dropdown_option":{"id":"affinity_update_list_field_dropdown_option","name":"Affinity Update List Field Dropdown Option","description":"Change a dropdown option on a list field. Every field is optional — supply only what should change, and only fields the option\'s kind actually has.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"listId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The list ID"},"fieldId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The dropdown field ID on that list"},"dropdownOptionId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The dropdown option ID to update"},"text":{"type":"string","required":false,"visibility":"user-or-llm","description":"Replacement option label. Supply at least one field to change"},"rank":{"type":"number","required":false,"visibility":"user-or-llm","description":"Sort order. Required on a ranked-dropdown or status-dropdown option"},"color":{"type":"string","required":false,"visibility":"user-or-llm","description":"Option color: white, gray, blue, green, purple, orange, or red. Required on a ranked-dropdown or status-dropdown option"},"statusCategory":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pipeline meaning of the option: open, won, lost, or on-hold. Status-dropdown options only"},"winRate":{"type":"number","required":false,"visibility":"user-or-llm","description":"Expected win rate of the status. Status-dropdown options only"}},"hostedApiKey":"none"},"affinity_update_note":{"id":"affinity_update_note","name":"Affinity Update Note","description":"Rewrite a note\'s body or replace which records it is attached to. Each list of IDs replaces that association wholesale, an empty list clears it, and omitting one leaves it untouched. A note\'s type cannot be changed.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Affinity API key, sent as a bearer token"},"noteId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The note ID to update"},"html":{"type":"string","required":false,"visibility":"user-or-llm","description":"Replacement note body as HTML"},"companyIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Replacement set of attached companies, e.g. [1, 2]. Send [] to detach every company; omit to leave them unchanged"},"personIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Replacement set of attached persons, e.g. [1, 2]. Send [] to detach every person; omit to leave them unchanged"},"opportunityIds":{"type":"json","required":false,"visibility":"user-or-llm","description":"Replacement set of attached opportunities, e.g. [1, 2]. Send [] to detach every opportunity; omit to leave them unchanged"}},"hostedApiKey":"none"},"agentmail_create_draft":{"id":"agentmail_create_draft","name":"Create Draft","description":"Create a new email draft in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox to create the draft in"},"to":{"type":"string","required":false,"visibility":"user-or-llm","description":"Recipient email addresses (comma-separated)"},"subject":{"type":"string","required":false,"visibility":"user-or-llm","description":"Draft subject line"},"text":{"type":"string","required":false,"visibility":"user-or-llm","description":"Plain text draft body"},"html":{"type":"string","required":false,"visibility":"user-or-llm","description":"HTML draft body"},"cc":{"type":"string","required":false,"visibility":"user-or-llm","description":"CC recipient email addresses (comma-separated)"},"bcc":{"type":"string","required":false,"visibility":"user-or-llm","description":"BCC recipient email addresses (comma-separated)"},"inReplyTo":{"type":"string","required":false,"visibility":"user-or-llm","description":"ID of message being replied to"},"sendAt":{"type":"string","required":false,"visibility":"user-or-llm","description":"ISO 8601 timestamp to schedule sending"}},"hostedApiKey":"none"},"agentmail_create_inbox":{"id":"agentmail_create_inbox","name":"Create Inbox","description":"Create a new email inbox with AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"username":{"type":"string","required":false,"visibility":"user-or-llm","description":"Username for the inbox email address"},"domain":{"type":"string","required":false,"visibility":"user-or-llm","description":"Domain for the inbox email address"},"displayName":{"type":"string","required":false,"visibility":"user-or-llm","description":"Display name for the inbox"}},"hostedApiKey":"none"},"agentmail_delete_draft":{"id":"agentmail_delete_draft","name":"Delete Draft","description":"Delete an email draft in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox containing the draft"},"draftId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the draft to delete"}},"hostedApiKey":"none"},"agentmail_delete_inbox":{"id":"agentmail_delete_inbox","name":"Delete Inbox","description":"Delete an email inbox in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox to delete"}},"hostedApiKey":"none"},"agentmail_delete_thread":{"id":"agentmail_delete_thread","name":"Delete Thread","description":"Delete an email thread in AgentMail (moves to trash, or permanently deletes if already in trash)","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox containing the thread"},"threadId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the thread to delete"},"permanent":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Force permanent deletion instead of moving to trash"}},"hostedApiKey":"none"},"agentmail_forward_message":{"id":"agentmail_forward_message","name":"Forward Message","description":"Forward an email message to new recipients in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox containing the message"},"messageId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the message to forward"},"to":{"type":"string","required":true,"visibility":"user-or-llm","description":"Recipient email addresses (comma-separated)"},"subject":{"type":"string","required":false,"visibility":"user-or-llm","description":"Override subject line"},"text":{"type":"string","required":false,"visibility":"user-or-llm","description":"Additional plain text to prepend"},"html":{"type":"string","required":false,"visibility":"user-or-llm","description":"Additional HTML to prepend"},"cc":{"type":"string","required":false,"visibility":"user-or-llm","description":"CC recipient email addresses (comma-separated)"},"bcc":{"type":"string","required":false,"visibility":"user-or-llm","description":"BCC recipient email addresses (comma-separated)"}},"hostedApiKey":"none"},"agentmail_get_draft":{"id":"agentmail_get_draft","name":"Get Draft","description":"Get details of a specific email draft in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox the draft belongs to"},"draftId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the draft to retrieve"}},"hostedApiKey":"none"},"agentmail_get_inbox":{"id":"agentmail_get_inbox","name":"Get Inbox","description":"Get details of a specific email inbox in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox to retrieve"}},"hostedApiKey":"none"},"agentmail_get_message":{"id":"agentmail_get_message","name":"Get Message","description":"Get details of a specific email message in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox containing the message"},"messageId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the message to retrieve"}},"hostedApiKey":"none"},"agentmail_get_thread":{"id":"agentmail_get_thread","name":"Get Thread","description":"Get details of a specific email thread including messages in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox containing the thread"},"threadId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the thread to retrieve"}},"hostedApiKey":"none"},"agentmail_list_drafts":{"id":"agentmail_list_drafts","name":"List Drafts","description":"List email drafts in an inbox in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox to list drafts from"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of drafts to return"},"pageToken":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination token for next page of results"}},"hostedApiKey":"none"},"agentmail_list_inboxes":{"id":"agentmail_list_inboxes","name":"List Inboxes","description":"List all email inboxes in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of inboxes to return"},"pageToken":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination token for next page of results"}},"hostedApiKey":"none"},"agentmail_list_messages":{"id":"agentmail_list_messages","name":"List Messages","description":"List messages in an inbox in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox to list messages from"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of messages to return"},"pageToken":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination token for next page of results"}},"hostedApiKey":"none"},"agentmail_list_threads":{"id":"agentmail_list_threads","name":"List Threads","description":"List email threads in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox to list threads from"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of threads to return"},"pageToken":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination token for next page of results"},"labels":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated labels to filter threads by"},"before":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter threads before this ISO 8601 timestamp"},"after":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter threads after this ISO 8601 timestamp"}},"hostedApiKey":"none"},"agentmail_reply_message":{"id":"agentmail_reply_message","name":"Reply to Message","description":"Reply to an existing email message in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox to reply from"},"messageId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the message to reply to"},"text":{"type":"string","required":false,"visibility":"user-or-llm","description":"Plain text reply body"},"html":{"type":"string","required":false,"visibility":"user-or-llm","description":"HTML reply body"},"to":{"type":"string","required":false,"visibility":"user-or-llm","description":"Override recipient email addresses (comma-separated)"},"cc":{"type":"string","required":false,"visibility":"user-or-llm","description":"CC email addresses (comma-separated)"},"bcc":{"type":"string","required":false,"visibility":"user-or-llm","description":"BCC email addresses (comma-separated)"},"replyAll":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Reply to all recipients of the original message"}},"hostedApiKey":"none"},"agentmail_send_draft":{"id":"agentmail_send_draft","name":"Send Draft","description":"Send an existing email draft in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox containing the draft"},"draftId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the draft to send"}},"hostedApiKey":"none"},"agentmail_send_message":{"id":"agentmail_send_message","name":"Send Message","description":"Send an email message from an AgentMail inbox","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox to send from"},"to":{"type":"string","required":true,"visibility":"user-or-llm","description":"Recipient email address (comma-separated for multiple)"},"subject":{"type":"string","required":true,"visibility":"user-or-llm","description":"Email subject line"},"text":{"type":"string","required":false,"visibility":"user-or-llm","description":"Plain text email body"},"html":{"type":"string","required":false,"visibility":"user-or-llm","description":"HTML email body"},"cc":{"type":"string","required":false,"visibility":"user-or-llm","description":"CC recipient email addresses (comma-separated)"},"bcc":{"type":"string","required":false,"visibility":"user-or-llm","description":"BCC recipient email addresses (comma-separated)"}},"hostedApiKey":"none"},"agentmail_update_draft":{"id":"agentmail_update_draft","name":"Update Draft","description":"Update an existing email draft in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox containing the draft"},"draftId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the draft to update"},"to":{"type":"string","required":false,"visibility":"user-or-llm","description":"Recipient email addresses (comma-separated)"},"subject":{"type":"string","required":false,"visibility":"user-or-llm","description":"Draft subject line"},"text":{"type":"string","required":false,"visibility":"user-or-llm","description":"Plain text draft body"},"html":{"type":"string","required":false,"visibility":"user-or-llm","description":"HTML draft body"},"cc":{"type":"string","required":false,"visibility":"user-or-llm","description":"CC recipient email addresses (comma-separated)"},"bcc":{"type":"string","required":false,"visibility":"user-or-llm","description":"BCC recipient email addresses (comma-separated)"},"sendAt":{"type":"string","required":false,"visibility":"user-or-llm","description":"ISO 8601 timestamp to schedule sending"}},"hostedApiKey":"none"},"agentmail_update_inbox":{"id":"agentmail_update_inbox","name":"Update Inbox","description":"Update the display name of an email inbox in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox to update"},"displayName":{"type":"string","required":true,"visibility":"user-or-llm","description":"New display name for the inbox"}},"hostedApiKey":"none"},"agentmail_update_message":{"id":"agentmail_update_message","name":"Update Message","description":"Add or remove labels on an email message in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox containing the message"},"messageId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the message to update"},"addLabels":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated labels to add to the message"},"removeLabels":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated labels to remove from the message"}},"hostedApiKey":"none"},"agentmail_update_thread":{"id":"agentmail_update_thread","name":"Update Thread Labels","description":"Add or remove labels on an email thread in AgentMail","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentMail API key"},"inboxId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the inbox containing the thread"},"threadId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the thread to update"},"addLabels":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated labels to add to the thread"},"removeLabels":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated labels to remove from the thread"}},"hostedApiKey":"none"},"agentphone_create_call":{"id":"agentphone_create_call","name":"Create Outbound Call","description":"Initiate an outbound voice call from an AgentPhone agent","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"agentId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Agent that will handle the call"},"toNumber":{"type":"string","required":true,"visibility":"user-or-llm","description":"Phone number to call in E.164 format (e.g. +14155551234)"},"fromNumberId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Phone number ID to use as caller ID. Must belong to the agent. If omitted, the agent\'s first assigned number is used."},"initialGreeting":{"type":"string","required":false,"visibility":"user-or-llm","description":"Optional greeting spoken when the recipient answers"},"voice":{"type":"string","required":false,"visibility":"user-or-llm","description":"Voice ID override for this call (defaults to the agent\'s configured voice)"},"systemPrompt":{"type":"string","required":false,"visibility":"user-or-llm","description":"When provided, uses a built-in LLM for the conversation instead of forwarding to your webhook"}},"hostedApiKey":"none"},"agentphone_create_contact":{"id":"agentphone_create_contact","name":"Create Contact","description":"Create a new contact in AgentPhone","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"phoneNumber":{"type":"string","required":true,"visibility":"user-or-llm","description":"Phone number in E.164 format (e.g. +14155551234)"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Contact\'s full name"},"email":{"type":"string","required":false,"visibility":"user-or-llm","description":"Contact\'s email address"},"notes":{"type":"string","required":false,"visibility":"user-or-llm","description":"Freeform notes stored on the contact"}},"hostedApiKey":"none"},"agentphone_create_number":{"id":"agentphone_create_number","name":"Create Phone Number","description":"Provision a new SMS- and voice-enabled phone number","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Two-letter country code (e.g. US, CA). Defaults to US."},"areaCode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Preferred area code (US/CA only, e.g. \\"415\\"). Best-effort — may be ignored if unavailable."},"agentId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Optionally attach the number to an agent immediately"}},"hostedApiKey":"none"},"agentphone_delete_contact":{"id":"agentphone_delete_contact","name":"Delete Contact","description":"Delete a contact by ID","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"contactId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Contact ID"}},"hostedApiKey":"none"},"agentphone_get_call":{"id":"agentphone_get_call","name":"Get Call","description":"Fetch a call and its full transcript","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"callId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the call to retrieve"}},"hostedApiKey":"none"},"agentphone_get_call_transcript":{"id":"agentphone_get_call_transcript","name":"Get Call Transcript","description":"Get the full ordered transcript for a call","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"callId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the call to retrieve the transcript for"}},"hostedApiKey":"none"},"agentphone_get_contact":{"id":"agentphone_get_contact","name":"Get Contact","description":"Fetch a single contact by ID","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"contactId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Contact ID"}},"hostedApiKey":"none"},"agentphone_get_conversation":{"id":"agentphone_get_conversation","name":"Get Conversation","description":"Get a conversation along with its recent messages","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"conversationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Conversation ID"},"messageLimit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of recent messages to include (default 50, max 100)"}},"hostedApiKey":"none"},"agentphone_get_conversation_messages":{"id":"agentphone_get_conversation_messages","name":"Get Conversation Messages","description":"Get paginated messages for a conversation","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"conversationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Conversation ID"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of messages to return (default 50, max 200)"},"before":{"type":"string","required":false,"visibility":"user-or-llm","description":"Return messages received before this ISO 8601 timestamp"},"after":{"type":"string","required":false,"visibility":"user-or-llm","description":"Return messages received after this ISO 8601 timestamp"}},"hostedApiKey":"none"},"agentphone_get_number_messages":{"id":"agentphone_get_number_messages","name":"Get Phone Number Messages","description":"Fetch messages received on a specific phone number","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"numberId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the phone number"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of messages to return (default 50, max 200)"},"before":{"type":"string","required":false,"visibility":"user-or-llm","description":"Return messages received before this ISO 8601 timestamp"},"after":{"type":"string","required":false,"visibility":"user-or-llm","description":"Return messages received after this ISO 8601 timestamp"}},"hostedApiKey":"none"},"agentphone_get_usage":{"id":"agentphone_get_usage","name":"Get Usage","description":"Retrieve current usage statistics for the AgentPhone account","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"}},"hostedApiKey":"none"},"agentphone_get_usage_daily":{"id":"agentphone_get_usage_daily","name":"Get Daily Usage","description":"Get a daily breakdown of usage (messages, calls, webhooks) for the last N days","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"days":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of days to return (1-365, default 30)"}},"hostedApiKey":"none"},"agentphone_get_usage_monthly":{"id":"agentphone_get_usage_monthly","name":"Get Monthly Usage","description":"Get monthly usage aggregation (messages, calls, webhooks) for the last N months","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"months":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of months to return (1-24, default 6)"}},"hostedApiKey":"none"},"agentphone_list_calls":{"id":"agentphone_list_calls","name":"List Calls","description":"List voice calls for this AgentPhone account","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of results to return (default 20, max 100)"},"offset":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of results to skip (min 0)"},"status":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter by status (completed, in-progress, failed)"},"direction":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter by direction (inbound, outbound)"},"type":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter by call type (pstn, web)"},"search":{"type":"string","required":false,"visibility":"user-or-llm","description":"Search by phone number (matches fromNumber or toNumber)"}},"hostedApiKey":"none"},"agentphone_list_contacts":{"id":"agentphone_list_contacts","name":"List Contacts","description":"List contacts for this AgentPhone account","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"search":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter by name or phone number (case-insensitive contains)"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of results to return (default 50, max 200)"},"offset":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of results to skip (min 0)"}},"hostedApiKey":"none"},"agentphone_list_conversations":{"id":"agentphone_list_conversations","name":"List Conversations","description":"List conversations (message threads) for this AgentPhone account","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of results to return (default 20, max 100)"},"offset":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of results to skip (min 0)"}},"hostedApiKey":"none"},"agentphone_list_numbers":{"id":"agentphone_list_numbers","name":"List Phone Numbers","description":"List all phone numbers provisioned for this AgentPhone account","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of results to return (default 20, max 100)"},"offset":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of results to skip (min 0)"}},"hostedApiKey":"none"},"agentphone_react_to_message":{"id":"agentphone_react_to_message","name":"React to Message","description":"Send an iMessage tapback reaction to a message (iMessage only)","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"messageId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the message to react to"},"reaction":{"type":"string","required":true,"visibility":"user-or-llm","description":"Reaction type: love, like, dislike, laugh, emphasize, or question"}},"hostedApiKey":"none"},"agentphone_release_number":{"id":"agentphone_release_number","name":"Release Phone Number","description":"Release (delete) a phone number. This action is irreversible.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"numberId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the phone number to release"}},"hostedApiKey":"none"},"agentphone_send_message":{"id":"agentphone_send_message","name":"Send Message","description":"Send an outbound SMS or iMessage from an AgentPhone agent","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"agentId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Agent sending the message"},"toNumber":{"type":"string","required":true,"visibility":"user-or-llm","description":"Recipient phone number in E.164 format (e.g. +14155551234)"},"body":{"type":"string","required":true,"visibility":"user-or-llm","description":"Message text to send"},"mediaUrl":{"type":"string","required":false,"visibility":"user-or-llm","description":"Optional URL of an image, video, or file to attach"},"numberId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Phone number ID to send from. If omitted, the agent\'s first assigned number is used."}},"hostedApiKey":"none"},"agentphone_update_contact":{"id":"agentphone_update_contact","name":"Update Contact","description":"Update a contact\'s fields","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"contactId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Contact ID"},"phoneNumber":{"type":"string","required":false,"visibility":"user-or-llm","description":"New phone number in E.164 format"},"name":{"type":"string","required":false,"visibility":"user-or-llm","description":"New contact name"},"email":{"type":"string","required":false,"visibility":"user-or-llm","description":"New email address"},"notes":{"type":"string","required":false,"visibility":"user-or-llm","description":"New freeform notes"}},"hostedApiKey":"none"},"agentphone_update_conversation":{"id":"agentphone_update_conversation","name":"Update Conversation","description":"Update conversation metadata (stored state). Pass null to clear existing metadata.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"AgentPhone API key"},"conversationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Conversation ID"},"metadata":{"type":"json","required":false,"visibility":"user-or-llm","description":"Custom key-value metadata to store on the conversation. Pass null to clear existing metadata."}},"hostedApiKey":"none"},"agiloft_async_status":{"id":"agiloft_async_status","name":"Agiloft Async Status","description":"Check whether an asynchronous Agiloft call, such as a run action button, has completed.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table the asynchronous call was made against"},"callbackId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Callback ID returned by the asynchronous call, e.g. from Run Action Button"}},"hostedApiKey":"none"},"agiloft_attach_file":{"id":"agiloft_attach_file","name":"Agiloft Attach File","description":"Attach a file to a field in an Agiloft record.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\")"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the record to attach the file to"},"fieldName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the attachment field"},"file":{"type":"file","required":true,"visibility":"user-or-llm","description":"File to attach"},"fileName":{"type":"string","required":false,"visibility":"user-or-llm","description":"Name to assign to the file (defaults to original file name)"},"overwrite":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Replace the contents of the field instead of adding another file to it"}},"hostedApiKey":"none"},"agiloft_attachment_info":{"id":"agiloft_attachment_info","name":"Agiloft Attachment Info","description":"Get information about file attachments on a record field.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\")"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the record to check attachments on"},"fieldName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the attachment field to inspect"}},"hostedApiKey":"none"},"agiloft_create_record":{"id":"agiloft_create_record","name":"Agiloft Create Record","description":"Create a new record in an Agiloft table.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\", \\"contacts.employees\\")"},"data":{"type":"string","required":true,"visibility":"user-or-llm","description":"Record field values as a JSON object (e.g., {\\"first_name\\": \\"John\\", \\"status\\": \\"Active\\"})"}},"hostedApiKey":"none"},"agiloft_delete_record":{"id":"agiloft_delete_record","name":"Agiloft Delete Record","description":"Delete a record from an Agiloft table.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\", \\"contacts.employees\\")"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the record to delete"},"substituteIds":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated IDs of records that adopt the dependants of the deleted record. Read only when the delete rule is REPLACE_WITH_ANOTHER."},"deleteRule":{"type":"string","required":false,"visibility":"user-or-llm","description":"How to treat records that depend on this one: ERROR_IF_DEPENDANTS (default — fails rather than cascading), APPLY_DELETE_WHERE_POSSIBLE, DELETE_WHERE_POSSIBLE_OTHERWISE_UNLINK, APPLY_UNLINK, UNLINK_WHERE_POSSIBLE_OTHERWISE_DELETE, or REPLACE_WITH_ANOTHER"}},"hostedApiKey":"none"},"agiloft_get_choice_line_id":{"id":"agiloft_get_choice_line_id","name":"Agiloft Get Choice Line ID","description":"Resolve the internal numeric ID of a choice-list value, for use in EWSelect WHERE clauses against choice fields.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"case\\", \\"contracts\\")"},"fieldName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Choice field name (e.g., \\"priority\\", \\"status\\")"},"value":{"type":"string","required":true,"visibility":"user-or-llm","description":"Choice display value to resolve (e.g., \\"High\\", \\"Active\\")"}},"hostedApiKey":"none"},"agiloft_list_tables":{"id":"agiloft_list_tables","name":"Agiloft List Tables","description":"List the tables and fields in an Agiloft knowledge base, to discover the logical names other operations need.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":false,"visibility":"user-or-llm","description":"Logical name of a single table to describe (e.g., \\"contacts\\"). Leave empty to list every table in the knowledge base."},"includeLinkedInfo":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Include the source table and column behind each linked field"},"skipColumnsInfo":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Return table names only, omitting field details, for a much smaller response"}},"hostedApiKey":"none"},"agiloft_lock_record":{"id":"agiloft_lock_record","name":"Agiloft Lock Record","description":"Lock, unlock, or check the lock status of an Agiloft record.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\")"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the record to lock, unlock, or check"},"lockAction":{"type":"string","required":true,"visibility":"user-or-llm","description":"Action to perform: \\"lock\\", \\"unlock\\", or \\"check\\""},"force":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Unlock only: release a lock held by another user."}},"hostedApiKey":"none"},"agiloft_nlp_search":{"id":"agiloft_nlp_search","name":"Agiloft Natural Language Search","description":"Search Agiloft records by describing what you want in plain language, such as \\"active NDAs submitted last month\\".","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"nlpQuery":{"type":"string","required":true,"visibility":"user-or-llm","description":"The request in plain language, e.g. \\"Show me open, high-priority contracts\\". Structured field filters are not accepted — use Search Records for those."},"fields":{"type":"string","required":true,"visibility":"user-or-llm","description":"Comma-separated field names to return, e.g. \\"id, contract_title1, company_name\\""},"page":{"type":"string","required":false,"visibility":"user-or-llm","description":"Page number, starting from 0"},"limit":{"type":"string","required":false,"visibility":"user-or-llm","description":"Records per page"}},"hostedApiKey":"none"},"agiloft_read_record":{"id":"agiloft_read_record","name":"Agiloft Read Record","description":"Read a record by ID from an Agiloft table.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\", \\"contacts.employees\\")"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the record to read"},"fields":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated list of field names to include in the response"}},"hostedApiKey":"none"},"agiloft_remove_attachment":{"id":"agiloft_remove_attachment","name":"Agiloft Remove Attachment","description":"Remove an attached file from a field in an Agiloft record.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\")"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the record containing the attachment"},"fieldName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the attachment field"},"position":{"type":"string","required":true,"visibility":"user-or-llm","description":"Position index of the file to remove (starting from 0)"}},"hostedApiKey":"none"},"agiloft_retrieve_attachment":{"id":"agiloft_retrieve_attachment","name":"Agiloft Retrieve Attachment","description":"Download an attached file from an Agiloft record field.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\")"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the record containing the attachment"},"fieldName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the attachment field"},"position":{"type":"string","required":true,"visibility":"user-or-llm","description":"Position index of the file in the field (starting from 0)"}},"hostedApiKey":"none"},"agiloft_run_action_button":{"id":"agiloft_run_action_button","name":"Agiloft Run Action Button","description":"Run an action button on an Agiloft record, such as an approval or send-for-signature step.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\", \\"case\\")"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the record to run the action button on"},"actionButtonField":{"type":"string","required":true,"visibility":"user-or-llm","description":"Logical name of the field holding the action button (e.g., \\"ab_field\\")"}},"hostedApiKey":"none"},"agiloft_saved_search":{"id":"agiloft_saved_search","name":"Agiloft Saved Search","description":"List the saved searches defined for an Agiloft table.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Logical table name to list saved searches for (e.g., \\"contract\\")"}},"hostedApiKey":"none"},"agiloft_search_records":{"id":"agiloft_search_records","name":"Agiloft Search Records","description":"Search for records in an Agiloft table using a query.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name to search in (e.g., \\"contracts\\", \\"contacts.employees\\")"},"query":{"type":"string","required":false,"visibility":"user-or-llm","description":"Ad hoc EWSearch query. Combine conditions with && (and) or || (or) and quote every value — e.g. \\"summary~=\'test\'&&priority=\'High\'\\". Required unless a saved search is given."},"search":{"type":"string","required":false,"visibility":"user-or-llm","description":"Label of a saved search defined on the table (e.g., \\"C: Status is Closed\\"). Can be combined with a query to narrow it further."},"fields":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated list of field names to include in the results"},"page":{"type":"string","required":false,"visibility":"user-or-llm","description":"Page number for paginated results (starting from 0)"},"limit":{"type":"string","required":false,"visibility":"user-or-llm","description":"Maximum number of records to return per page. Agiloft treats 0 as \\"all records\\", so leave it unset or use a positive value to keep result sizes bounded."}},"hostedApiKey":"none"},"agiloft_select_records":{"id":"agiloft_select_records","name":"Agiloft Select Records","description":"Select record IDs matching a SQL WHERE clause from an Agiloft table.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\", \\"contacts.employees\\")"},"where":{"type":"string","required":true,"visibility":"user-or-llm","description":"SQL WHERE clause using database column names (e.g., \\"summary like \'%new%\'\\" or \\"assigned_person=\'John Doe\'\\"). EWSelect has no page size and returns every matching ID, so append a database limit such as \\"limit 0,200\\" to bound the result."}},"hostedApiKey":"none"},"agiloft_update_record":{"id":"agiloft_update_record","name":"Agiloft Update Record","description":"Update an existing record in an Agiloft table.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\", \\"contacts.employees\\")"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the record to update"},"data":{"type":"string","required":true,"visibility":"user-or-llm","description":"Updated field values as a JSON object (e.g., {\\"status\\": \\"Active\\", \\"priority\\": \\"High\\"})"}},"hostedApiKey":"none"},"agiloft_upsert_record":{"id":"agiloft_upsert_record","name":"Agiloft Upsert Record","description":"Create an Agiloft record, or update it when a record already matches the given fields.","version":"1.0.0","params":{"instanceUrl":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft instance URL (e.g., https://mycompany.agiloft.com)"},"knowledgeBase":{"type":"string","required":true,"visibility":"user-only","description":"Knowledge base name"},"login":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft username"},"password":{"type":"string","required":true,"visibility":"user-only","description":"Agiloft password"},"table":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table name (e.g., \\"contracts\\", \\"contacts.employees\\")"},"match":{"type":"string","required":true,"visibility":"user-or-llm","description":"Field used to find an existing record (e.g., \\"ext_id\\"). Pick something that identifies a record uniquely — if more than one record matches, Agiloft writes nothing and returns a conflict."},"async":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Queue the write instead of waiting for it. Returns a callback ID instead of a record ID; pass that to Async Status to poll the result."},"data":{"type":"string","required":true,"visibility":"user-or-llm","description":"Field values as a JSON object. On create these populate the new record; on update only the supplied fields change."}},"hostedApiKey":"none"},"ahrefs_anchors":{"id":"ahrefs_anchors","name":"Ahrefs Anchors","description":"Get the anchor text distribution for a target domain or URL\'s backlinks, showing how many links and referring domains use each anchor text.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\" or \\"https://example.com/page\\""},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match)"},"history":{"type":"string","required":false,"visibility":"user-or-llm","description":"Historical scope: \\"live\\" (currently live), \\"all_time\\" (default, includes lost backlinks), or \\"since:YYYY-MM-DD\\" (backlinks found since a date)"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_backlinks":{"id":"ahrefs_backlinks","name":"Ahrefs Backlinks","description":"Get a list of backlinks pointing to a target domain or URL. Returns details about each backlink including source URL, anchor text, and domain rating.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\" or \\"https://example.com/page\\""},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: \\"domain\\""},"history":{"type":"string","required":false,"visibility":"user-or-llm","description":"Historical scope: \\"live\\" (currently live backlinks), \\"all_time\\" (default, includes lost backlinks), or \\"since:YYYY-MM-DD\\" (backlinks found since a date)."},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_backlinks_stats":{"id":"ahrefs_backlinks_stats","name":"Ahrefs Backlinks Stats","description":"Get backlink and referring domain totals for a target domain or URL, both currently live and across all time.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\" or \\"https://example.com/page\\""},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: \\"domain\\""},"date":{"type":"string","required":false,"visibility":"user-only","description":"Date to report metrics on, in YYYY-MM-DD format (defaults to today)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_batch_analysis":{"id":"ahrefs_batch_analysis","name":"Ahrefs Batch Analysis","description":"Get bulk SEO metrics (Domain Rating, backlinks, referring domains, organic traffic, and more) for multiple domains or URLs in a single request. Useful for comparing many competitors at once.","version":"1.0.0","params":{"targets":{"type":"string","required":true,"visibility":"user-or-llm","description":"Comma-separated list of domains or URLs to analyze. Example: \\"example.com,competitor.com\\""},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode applied to every target: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match)"},"protocol":{"type":"string","required":false,"visibility":"user-or-llm","description":"Protocol applied to every target: \\"both\\" (default), \\"http\\", or \\"https\\""},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Country code for traffic data. Example: \\"us\\", \\"gb\\", \\"de\\" (default: \\"us\\")"},"volumeMode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Search volume calculation: \\"monthly\\" or \\"average\\" (default: \\"monthly\\")"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_broken_backlinks":{"id":"ahrefs_broken_backlinks","name":"Ahrefs Broken Backlinks","description":"Get a list of broken backlinks pointing to a target domain or URL. Useful for identifying link reclamation opportunities.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\" or \\"https://example.com/page\\""},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: \\"domain\\""},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_domain_rating":{"id":"ahrefs_domain_rating","name":"Ahrefs Domain Rating","description":"Get the Domain Rating (DR) and Ahrefs Rank for a target domain. Domain Rating shows the strength of a website\'s backlink profile on a scale from 0 to 100.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain to analyze (e.g., example.com)"},"date":{"type":"string","required":false,"visibility":"user-only","description":"Date for historical data in YYYY-MM-DD format (defaults to today)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_domain_rating_history":{"id":"ahrefs_domain_rating_history","name":"Ahrefs Domain Rating History","description":"Get the historical Domain Rating (DR) trend for a target domain or URL over a date range, grouped daily, weekly, or monthly.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\""},"dateFrom":{"type":"string","required":true,"visibility":"user-only","description":"Start date of the historical period, in YYYY-MM-DD format"},"dateTo":{"type":"string","required":false,"visibility":"user-only","description":"End date of the historical period, in YYYY-MM-DD format (defaults to today)"},"historyGrouping":{"type":"string","required":false,"visibility":"user-or-llm","description":"Time interval for grouping data points: \\"daily\\", \\"weekly\\", or \\"monthly\\" (default: \\"monthly\\")"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_keyword_overview":{"id":"ahrefs_keyword_overview","name":"Ahrefs Keyword Overview","description":"Get detailed metrics for a keyword including search volume, keyword difficulty, CPC, clicks, and traffic potential.","version":"1.0.0","params":{"keyword":{"type":"string","required":true,"visibility":"user-or-llm","description":"The keyword to analyze"},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Country code for keyword data. Example: \\"us\\", \\"gb\\", \\"de\\" (default: \\"us\\")"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_keywords_history":{"id":"ahrefs_keywords_history","name":"Ahrefs Keywords History","description":"Get the historical organic keyword ranking distribution for a target domain or URL over a date range: how many keywords rank in each position bucket at each point in time.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\""},"dateFrom":{"type":"string","required":true,"visibility":"user-only","description":"Start date of the historical period, in YYYY-MM-DD format"},"dateTo":{"type":"string","required":false,"visibility":"user-only","description":"End date of the historical period, in YYYY-MM-DD format (defaults to today)"},"historyGrouping":{"type":"string","required":false,"visibility":"user-or-llm","description":"Time interval for grouping data points: \\"daily\\", \\"weekly\\", or \\"monthly\\" (default: \\"monthly\\")"},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Country code for search results. Example: \\"us\\", \\"gb\\", \\"de\\" (default: \\"us\\")"},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_metrics":{"id":"ahrefs_metrics","name":"Ahrefs Metrics","description":"Get a one-call organic and paid search overview for a target domain or URL: organic traffic, organic keywords, paid traffic, paid keywords, and estimated traffic cost.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\""},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Country code for traffic data. Example: \\"us\\", \\"gb\\", \\"de\\""},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: \\"domain\\""},"date":{"type":"string","required":false,"visibility":"user-only","description":"Date to report metrics on, in YYYY-MM-DD format (defaults to today)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_metrics_history":{"id":"ahrefs_metrics_history","name":"Ahrefs Metrics History","description":"Get the historical organic and paid traffic trend for a target domain or URL over a date range: organic traffic/cost and paid traffic/cost at each point in time.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\""},"dateFrom":{"type":"string","required":true,"visibility":"user-only","description":"Start date of the historical period, in YYYY-MM-DD format"},"dateTo":{"type":"string","required":false,"visibility":"user-only","description":"End date of the historical period, in YYYY-MM-DD format (defaults to today)"},"volumeMode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Search volume calculation: \\"monthly\\" or \\"average\\" (default: \\"monthly\\")"},"historyGrouping":{"type":"string","required":false,"visibility":"user-or-llm","description":"Time interval for grouping data points: \\"daily\\", \\"weekly\\", or \\"monthly\\" (default: \\"monthly\\")"},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Country code for traffic data. Example: \\"us\\", \\"gb\\", \\"de\\" (default: \\"us\\")"},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_organic_competitors":{"id":"ahrefs_organic_competitors","name":"Ahrefs Organic Competitors","description":"Get domains that compete with a target domain or URL for the same organic keywords, ranked by keyword overlap.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\""},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Country code for search results. Example: \\"us\\", \\"gb\\", \\"de\\" (default: \\"us\\")"},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: \\"domain\\""},"date":{"type":"string","required":false,"visibility":"user-only","description":"Date to report metrics on, in YYYY-MM-DD format (defaults to today)"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_organic_keywords":{"id":"ahrefs_organic_keywords","name":"Ahrefs Organic Keywords","description":"Get organic keywords that a target domain or URL ranks for in Google search results. Returns keyword details including search volume, ranking position, and estimated traffic.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\" or \\"https://example.com/page\\""},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Country code for search results. Example: \\"us\\", \\"gb\\", \\"de\\" (default: \\"us\\")"},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: \\"domain\\""},"date":{"type":"string","required":false,"visibility":"user-only","description":"Date to report metrics on, in YYYY-MM-DD format (defaults to today)"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_paid_pages":{"id":"ahrefs_paid_pages","name":"Ahrefs Paid Pages","description":"Get a target domain\'s pages that receive paid search traffic, sorted by estimated paid traffic. Returns page URLs with their paid traffic, keyword counts, and estimated spend.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\""},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Country code for traffic data. Example: \\"us\\", \\"gb\\", \\"de\\" (default: \\"us\\")"},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match)"},"date":{"type":"string","required":false,"visibility":"user-only","description":"Date to report metrics on, in YYYY-MM-DD format (defaults to today)"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_rank_tracker_competitors_overview":{"id":"ahrefs_rank_tracker_competitors_overview","name":"Ahrefs Rank Tracker Competitors Overview","description":"Get competitor rankings for the keywords tracked in an Ahrefs Rank Tracker project: each tracked keyword\'s volume and difficulty alongside every competitor\'s position, traffic, and traffic value. This endpoint is free and does not consume API units.","version":"1.0.0","params":{"projectId":{"type":"number","required":true,"visibility":"user-or-llm","description":"The Rank Tracker project ID (found in the project URL in Ahrefs)"},"date":{"type":"string","required":true,"visibility":"user-only","description":"Date to report rankings for, in YYYY-MM-DD format"},"device":{"type":"string","required":true,"visibility":"user-or-llm","description":"Rankings device type: \\"desktop\\" or \\"mobile\\""},"dateCompared":{"type":"string","required":false,"visibility":"user-only","description":"Comparison date in YYYY-MM-DD format, to compute position/traffic deltas"},"volumeMode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Search volume calculation: \\"monthly\\" or \\"average\\" (default: \\"monthly\\")"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_rank_tracker_competitors_stats":{"id":"ahrefs_rank_tracker_competitors_stats","name":"Ahrefs Rank Tracker Competitors Stats","description":"Get aggregate competitor stats for an Ahrefs Rank Tracker project: each competitor\'s traffic, traffic value, average position, and share of voice across all tracked keywords. This endpoint is free and does not consume API units.","version":"1.0.0","params":{"projectId":{"type":"number","required":true,"visibility":"user-or-llm","description":"The Rank Tracker project ID (found in the project URL in Ahrefs)"},"date":{"type":"string","required":true,"visibility":"user-only","description":"Date to report metrics for, in YYYY-MM-DD format"},"device":{"type":"string","required":true,"visibility":"user-or-llm","description":"Rankings device type: \\"desktop\\" or \\"mobile\\""},"volumeMode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Search volume calculation: \\"monthly\\" or \\"average\\" (default: \\"monthly\\")"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_rank_tracker_overview":{"id":"ahrefs_rank_tracker_overview","name":"Ahrefs Rank Tracker Overview","description":"Get ranking overview metrics for the keywords tracked in an Ahrefs Rank Tracker project: position, search volume, keyword difficulty, and estimated traffic. This endpoint is free and does not consume API units.","version":"1.0.0","params":{"projectId":{"type":"number","required":true,"visibility":"user-or-llm","description":"The Rank Tracker project ID (found in the project URL in Ahrefs)"},"date":{"type":"string","required":true,"visibility":"user-only","description":"Date to report rankings for, in YYYY-MM-DD format"},"device":{"type":"string","required":true,"visibility":"user-or-llm","description":"Rankings device type: \\"desktop\\" or \\"mobile\\""},"dateCompared":{"type":"string","required":false,"visibility":"user-only","description":"Comparison date in YYYY-MM-DD format, to compute position/traffic deltas"},"volumeMode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Search volume calculation: \\"monthly\\" or \\"average\\" (default: \\"monthly\\")"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_rank_tracker_serp_overview":{"id":"ahrefs_rank_tracker_serp_overview","name":"Ahrefs Rank Tracker SERP Overview","description":"Get the full SERP (search engine results page) for a keyword tracked in an Ahrefs Rank Tracker project, including every ranking URL with its position, title, and authority metrics. This endpoint is free and does not consume API units.","version":"1.0.0","params":{"projectId":{"type":"number","required":true,"visibility":"user-or-llm","description":"The Rank Tracker project ID (found in the project URL in Ahrefs)"},"keyword":{"type":"string","required":true,"visibility":"user-or-llm","description":"The tracked keyword to retrieve SERP data for"},"country":{"type":"string","required":true,"visibility":"user-or-llm","description":"Country code for the tracked keyword. Example: \\"us\\", \\"gb\\", \\"de\\""},"device":{"type":"string","required":true,"visibility":"user-or-llm","description":"Rankings device type: \\"desktop\\" or \\"mobile\\""},"topPositions":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of top organic positions to return (defaults to all available)"},"date":{"type":"string","required":false,"visibility":"user-only","description":"Timestamp to return the last available SERP Overview at, in YYYY-MM-DDThh:mm:ss format"},"locationId":{"type":"number","required":false,"visibility":"user-or-llm","description":"Location ID of the tracked keyword, if tracked at a specific location"},"languageCode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Language code of the tracked keyword"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_refdomains_history":{"id":"ahrefs_refdomains_history","name":"Ahrefs Referring Domains History","description":"Get the historical referring domains trend for a target domain or URL over a date range, grouped daily, weekly, or monthly.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\""},"dateFrom":{"type":"string","required":true,"visibility":"user-only","description":"Start date of the historical period, in YYYY-MM-DD format"},"dateTo":{"type":"string","required":false,"visibility":"user-only","description":"End date of the historical period, in YYYY-MM-DD format (defaults to today)"},"historyGrouping":{"type":"string","required":false,"visibility":"user-or-llm","description":"Time interval for grouping data points: \\"daily\\", \\"weekly\\", or \\"monthly\\" (default: \\"monthly\\")"},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_referring_domains":{"id":"ahrefs_referring_domains","name":"Ahrefs Referring Domains","description":"Get a list of domains that link to a target domain or URL. Returns unique referring domains with their domain rating, backlink counts, and discovery dates.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain or URL to analyze. Example: \\"example.com\\" or \\"https://example.com/page\\""},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: \\"domain\\""},"history":{"type":"string","required":false,"visibility":"user-or-llm","description":"Historical scope: \\"live\\" (currently live), \\"all_time\\" (default, includes lost domains), or \\"since:YYYY-MM-DD\\" (domains found since a date)."},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_related_terms":{"id":"ahrefs_related_terms","name":"Ahrefs Related Terms","description":"Get keyword ideas related to a seed keyword: terms the same top-ranking pages also rank for (\\"also rank for\\") or also discuss (\\"also talk about\\"), with volume, difficulty, and CPC.","version":"1.0.0","params":{"keyword":{"type":"string","required":true,"visibility":"user-or-llm","description":"The seed keyword to find related terms for"},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Country code for keyword data. Example: \\"us\\", \\"gb\\", \\"de\\" (default: \\"us\\")"},"terms":{"type":"string","required":false,"visibility":"user-or-llm","description":"Type of related keywords to return: \\"also_rank_for\\", \\"also_talk_about\\", or \\"all\\" (default: \\"all\\")"},"viewFor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Whether to derive related terms from the top 10 or top 100 ranking pages (default: \\"top_10\\")"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_site_audit_page_explorer":{"id":"ahrefs_site_audit_page_explorer","name":"Ahrefs Site Audit Page Explorer","description":"Get crawled pages from an Ahrefs Site Audit project with health and SEO metrics: HTTP status, title, link counts, backlinks, indexability, and traffic. Optionally filter to pages affected by a specific issue.","version":"1.0.0","params":{"projectId":{"type":"number","required":true,"visibility":"user-or-llm","description":"The Site Audit project ID (found in the project URL in Ahrefs)"},"date":{"type":"string","required":false,"visibility":"user-only","description":"Crawl date in YYYY-MM-DDThh:mm:ss format (defaults to the most recent crawl)"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"offset":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of results to skip, for pagination"},"issueId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Only return pages affected by this issue ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"ahrefs_top_pages":{"id":"ahrefs_top_pages","name":"Ahrefs Top Pages","description":"Get the top pages of a target domain sorted by organic traffic. Returns page URLs with their traffic, keyword counts, and estimated traffic value.","version":"1.0.0","params":{"target":{"type":"string","required":true,"visibility":"user-or-llm","description":"The target domain to analyze. Example: \\"example.com\\""},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Country code for traffic data. Example: \\"us\\", \\"gb\\", \\"de\\" (default: \\"us\\")"},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Analysis mode: domain (entire domain), prefix (URL prefix), subdomains (include all subdomains, default), exact (exact URL match). Example: \\"domain\\""},"date":{"type":"string","required":false,"visibility":"user-only","description":"Date to report metrics on, in YYYY-MM-DD format (defaults to today)"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of results to return. Example: 50 (default: 1000)"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ahrefs API Key"}},"hostedApiKey":"none"},"airtable_create_records":{"id":"airtable_create_records","name":"Airtable Create Records","description":"Write new records to an Airtable table","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token"},"baseId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Airtable base ID (starts with \\"app\\", e.g., \\"appXXXXXXXXXXXXXX\\")"},"tableId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table ID (starts with \\"tbl\\") or table name"},"records":{"type":"json","required":true,"visibility":"user-or-llm","description":"Array of records to create, each with a `fields` object"},"typecast":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"When true, Airtable automatically converts string values to the field type"}},"oauth":{"required":true,"provider":"airtable"},"hostedApiKey":"none"},"airtable_delete_records":{"id":"airtable_delete_records","name":"Airtable Delete Records","description":"Delete one or more records from an Airtable table by ID","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token"},"baseId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Airtable base ID (starts with \\"app\\", e.g., \\"appXXXXXXXXXXXXXX\\")"},"tableId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table ID (starts with \\"tbl\\") or table name"},"recordIds":{"type":"json","required":true,"visibility":"user-or-llm","description":"Array of record IDs to delete (each starts with \\"rec\\", e.g., [\\"recXXXXXXXXXXXXXX\\"]). Pass a single-element array to delete one record."}},"oauth":{"required":true,"provider":"airtable"},"hostedApiKey":"none"},"airtable_get_base_schema":{"id":"airtable_get_base_schema","name":"Airtable Get Base Schema","description":"Get the schema of all tables, fields, and views in an Airtable base","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token"},"baseId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Airtable base ID (starts with \\"app\\", e.g., \\"appXXXXXXXXXXXXXX\\")"}},"oauth":{"required":true,"provider":"airtable"},"hostedApiKey":"none"},"airtable_get_record":{"id":"airtable_get_record","name":"Airtable Get Record","description":"Retrieve a single record from an Airtable table by its ID","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token"},"baseId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Airtable base ID (starts with \\"app\\", e.g., \\"appXXXXXXXXXXXXXX\\")"},"tableId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table ID (starts with \\"tbl\\") or table name"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Record ID to retrieve (starts with \\"rec\\", e.g., \\"recXXXXXXXXXXXXXX\\")"}},"oauth":{"required":true,"provider":"airtable"},"hostedApiKey":"none"},"airtable_list_bases":{"id":"airtable_list_bases","name":"Airtable List Bases","description":"List all bases the authenticated user has access to","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token"},"offset":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination offset for retrieving additional bases"}},"oauth":{"required":true,"provider":"airtable"},"hostedApiKey":"none"},"airtable_list_records":{"id":"airtable_list_records","name":"Airtable List Records","description":"Read records from an Airtable table","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token"},"baseId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Airtable base ID (starts with \\"app\\", e.g., \\"appXXXXXXXXXXXXXX\\")"},"tableId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table ID (starts with \\"tbl\\") or table name"},"maxRecords":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of records to return (default: all records)"},"filterFormula":{"type":"string","required":false,"visibility":"user-or-llm","description":"Formula to filter records (e.g., \\"({Field Name} = \'Value\')\\")"}},"oauth":{"required":true,"provider":"airtable"},"hostedApiKey":"none"},"airtable_list_tables":{"id":"airtable_list_tables","name":"Airtable List Tables","description":"List all tables and their schema in an Airtable base","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token"},"baseId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Airtable base ID (starts with \\"app\\", e.g., \\"appXXXXXXXXXXXXXX\\")"}},"oauth":{"required":true,"provider":"airtable"},"hostedApiKey":"none"},"airtable_update_multiple_records":{"id":"airtable_update_multiple_records","name":"Airtable Update Multiple Records","description":"Update multiple existing records in an Airtable table","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token"},"baseId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Airtable base ID (starts with \\"app\\", e.g., \\"appXXXXXXXXXXXXXX\\")"},"tableId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table ID (starts with \\"tbl\\") or table name"},"records":{"type":"json","required":true,"visibility":"user-or-llm","description":"Array of records to update, each with an `id` and a `fields` object"},"typecast":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"When true, Airtable automatically converts string values to the field type"}},"oauth":{"required":true,"provider":"airtable"},"hostedApiKey":"none"},"airtable_update_record":{"id":"airtable_update_record","name":"Airtable Update Record","description":"Update an existing record in an Airtable table by ID","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token"},"baseId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Airtable base ID (starts with \\"app\\", e.g., \\"appXXXXXXXXXXXXXX\\")"},"tableId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table ID (starts with \\"tbl\\") or table name"},"recordId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Record ID to update (starts with \\"rec\\", e.g., \\"recXXXXXXXXXXXXXX\\")"},"fields":{"type":"json","required":true,"visibility":"user-or-llm","description":"An object containing the field names and their new values"},"typecast":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"When true, Airtable automatically converts string values to the field type"}},"oauth":{"required":true,"provider":"airtable"},"hostedApiKey":"none"},"airtable_upsert_records":{"id":"airtable_upsert_records","name":"Airtable Upsert Records","description":"Update existing records or create new ones in an Airtable table, matching on the specified merge fields","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token"},"baseId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Airtable base ID (starts with \\"app\\", e.g., \\"appXXXXXXXXXXXXXX\\")"},"tableId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Table ID (starts with \\"tbl\\") or table name"},"records":{"type":"json","required":true,"visibility":"user-or-llm","description":"Array of records to upsert, each with a `fields` object"},"fieldsToMergeOn":{"type":"json","required":true,"visibility":"user-or-llm","description":"Array of field names used to match existing records (max 3). A record is updated when all merge fields match, otherwise it is created. Example: [\\"Name\\"]"},"typecast":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"When true, Airtable automatically converts string values to the field type"}},"oauth":{"required":true,"provider":"airtable"},"hostedApiKey":"none"},"algolia_add_record":{"id":"algolia_add_record","name":"Algolia Add Record","description":"Add or replace a record in an Algolia index","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Admin API Key"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index"},"objectID":{"type":"string","required":false,"visibility":"user-or-llm","description":"Object ID for the record (auto-generated if not provided)"},"record":{"type":"json","required":true,"visibility":"user-or-llm","description":"JSON object representing the record to add"}},"hostedApiKey":"none"},"algolia_batch_operations":{"id":"algolia_batch_operations","name":"Algolia Batch Operations","description":"Perform batch add, update, partial update, or delete operations on records in an Algolia index","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Admin API Key"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index"},"requests":{"type":"json","required":true,"visibility":"user-or-llm","description":"Array of batch operations. Each item has \\"action\\" (addObject, updateObject, partialUpdateObject, partialUpdateObjectNoCreate, deleteObject, delete, clear) and \\"body\\" (the record data; must include objectID for update/delete; use an empty object {} for the index-level delete/clear actions)"}},"hostedApiKey":"none"},"algolia_browse_records":{"id":"algolia_browse_records","name":"Algolia Browse Records","description":"Browse and iterate over all records in an Algolia index using cursor pagination","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia API Key (must have browse ACL)"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index to browse"},"query":{"type":"string","required":false,"visibility":"user-or-llm","description":"Search query to filter browsed records"},"filters":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter string to narrow down results"},"attributesToRetrieve":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated list of attributes to retrieve"},"hitsPerPage":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of hits per page (default: 1000, max: 1000)"},"cursor":{"type":"string","required":false,"visibility":"user-or-llm","description":"Cursor from a previous browse response for pagination"},"aroundLatLng":{"type":"string","required":false,"visibility":"user-or-llm","description":"Coordinates for geo-search (e.g., \\"40.71,-74.01\\")"},"aroundRadius":{"type":"string","required":false,"visibility":"user-or-llm","description":"Maximum radius in meters for geo-search, or \\"all\\" for unlimited"},"insideBoundingBox":{"type":"json","required":false,"visibility":"user-or-llm","description":"Bounding box coordinates as [[lat1, lng1, lat2, lng2]] for geo-search"},"insidePolygon":{"type":"json","required":false,"visibility":"user-or-llm","description":"Polygon coordinates as [[lat1, lng1, lat2, lng2, lat3, lng3, ...]] for geo-search"}},"hostedApiKey":"none"},"algolia_clear_records":{"id":"algolia_clear_records","name":"Algolia Clear Records","description":"Clear all records from an Algolia index while keeping settings, synonyms, and rules","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Admin API Key (must have deleteIndex ACL)"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index to clear"}},"hostedApiKey":"none"},"algolia_copy_move_index":{"id":"algolia_copy_move_index","name":"Algolia Copy/Move Index","description":"Copy or move an Algolia index to a new destination","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Admin API Key"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the source index"},"operation":{"type":"string","required":true,"visibility":"user-or-llm","description":"Operation to perform: \\"copy\\" or \\"move\\""},"destination":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the destination index"},"scope":{"type":"json","required":false,"visibility":"user-or-llm","description":"Array of scopes to copy (only for \\"copy\\" operation): [\\"settings\\", \\"synonyms\\", \\"rules\\"]. Omit to copy everything including records."}},"hostedApiKey":"none"},"algolia_delete_by_filter":{"id":"algolia_delete_by_filter","name":"Algolia Delete By Filter","description":"Delete all records matching a filter from an Algolia index","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Admin API Key (must have deleteIndex ACL)"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index"},"filters":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter expression to match records for deletion (e.g., \\"category:outdated\\")"},"facetFilters":{"type":"json","required":false,"visibility":"user-or-llm","description":"Array of facet filters (e.g., [\\"brand:Acme\\"])"},"numericFilters":{"type":"json","required":false,"visibility":"user-or-llm","description":"Array of numeric filters (e.g., [\\"price > 100\\"])"},"tagFilters":{"type":"json","required":false,"visibility":"user-or-llm","description":"Array of tag filters using the _tags attribute (e.g., [\\"published\\"])"},"aroundLatLng":{"type":"string","required":false,"visibility":"user-or-llm","description":"Coordinates for geo-search filter (e.g., \\"40.71,-74.01\\")"},"aroundRadius":{"type":"string","required":false,"visibility":"user-or-llm","description":"Maximum radius in meters for geo-search, or \\"all\\" for unlimited"},"insideBoundingBox":{"type":"json","required":false,"visibility":"user-or-llm","description":"Bounding box coordinates as [[lat1, lng1, lat2, lng2]] for geo-search filter"},"insidePolygon":{"type":"json","required":false,"visibility":"user-or-llm","description":"Polygon coordinates as [[lat1, lng1, lat2, lng2, lat3, lng3, ...]] for geo-search filter"}},"hostedApiKey":"none"},"algolia_delete_index":{"id":"algolia_delete_index","name":"Algolia Delete Index","description":"Delete an entire Algolia index and all its records","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Admin API Key (must have deleteIndex ACL)"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index to delete"}},"hostedApiKey":"none"},"algolia_delete_record":{"id":"algolia_delete_record","name":"Algolia Delete Record","description":"Delete a record by objectID from an Algolia index","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Admin API Key"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index"},"objectID":{"type":"string","required":true,"visibility":"user-or-llm","description":"The objectID of the record to delete"}},"hostedApiKey":"none"},"algolia_get_record":{"id":"algolia_get_record","name":"Algolia Get Record","description":"Get a record by objectID from an Algolia index","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia API Key"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index"},"objectID":{"type":"string","required":true,"visibility":"user-or-llm","description":"The objectID of the record to retrieve"},"attributesToRetrieve":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated list of attributes to retrieve"}},"hostedApiKey":"none"},"algolia_get_records":{"id":"algolia_get_records","name":"Algolia Get Records","description":"Retrieve multiple records by objectID from one or more Algolia indices","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia API Key"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Default index name for all requests"},"requests":{"type":"json","required":true,"visibility":"user-or-llm","description":"Array of objects specifying records to retrieve. Each must have \\"objectID\\" and optionally \\"indexName\\" and \\"attributesToRetrieve\\"."}},"hostedApiKey":"none"},"algolia_get_settings":{"id":"algolia_get_settings","name":"Algolia Get Settings","description":"Retrieve the settings of an Algolia index","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia API Key"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index"}},"hostedApiKey":"none"},"algolia_get_task_status":{"id":"algolia_get_task_status","name":"Algolia Get Task Status","description":"Check whether an Algolia indexing task has finished publishing","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia API Key"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index the task ran against"},"taskID":{"type":"number","required":true,"visibility":"user-or-llm","description":"The taskID returned by a previous write operation"}},"hostedApiKey":"none"},"algolia_list_indices":{"id":"algolia_list_indices","name":"Algolia List Indices","description":"List all indices in an Algolia application","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia API Key"},"page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Page number for paginating indices (default: not paginated)"},"hitsPerPage":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of indices per page (default: 100)"}},"hostedApiKey":"none"},"algolia_partial_update_record":{"id":"algolia_partial_update_record","name":"Algolia Partial Update Record","description":"Partially update a record in an Algolia index without replacing it entirely","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Admin API Key"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index"},"objectID":{"type":"string","required":true,"visibility":"user-or-llm","description":"The objectID of the record to update"},"attributes":{"type":"json","required":true,"visibility":"user-or-llm","description":"JSON object with attributes to update. Supports built-in operations like {\\"stock\\": {\\"_operation\\": \\"Decrement\\", \\"value\\": 1}}"},"createIfNotExists":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Whether to create the record if it does not exist (default: true)"}},"hostedApiKey":"none"},"algolia_search":{"id":"algolia_search","name":"Algolia Search","description":"Search an Algolia index","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia API Key"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index to search"},"query":{"type":"string","required":true,"visibility":"user-or-llm","description":"Search query text"},"hitsPerPage":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of hits per page (default: 20)"},"page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Page number to retrieve (default: 0)"},"filters":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter string (e.g., \\"category:electronics AND price < 100\\")"},"attributesToRetrieve":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated list of attributes to retrieve"},"facets":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated list of facet attribute names to retrieve counts for (use \\"*\\" for all)"},"getRankingInfo":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Whether to include detailed ranking information in each hit"},"aroundLatLng":{"type":"string","required":false,"visibility":"user-or-llm","description":"Coordinates for geo-search (e.g., \\"40.71,-74.01\\")"},"aroundRadius":{"type":"string","required":false,"visibility":"user-or-llm","description":"Maximum radius in meters for geo-search, or \\"all\\" for unlimited"},"insideBoundingBox":{"type":"json","required":false,"visibility":"user-or-llm","description":"Bounding box coordinates as [[lat1, lng1, lat2, lng2]] for geo-search"},"insidePolygon":{"type":"json","required":false,"visibility":"user-or-llm","description":"Polygon coordinates as [[lat1, lng1, lat2, lng2, lat3, lng3, ...]] for geo-search"}},"hostedApiKey":"none"},"algolia_update_settings":{"id":"algolia_update_settings","name":"Algolia Update Settings","description":"Update the settings of an Algolia index","version":"1.0","params":{"applicationId":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Application ID"},"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Algolia Admin API Key (must have editSettings ACL)"},"indexName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the Algolia index"},"settings":{"type":"json","required":true,"visibility":"user-or-llm","description":"JSON object with settings to update (e.g., {\\"searchableAttributes\\": [\\"name\\", \\"description\\"], \\"customRanking\\": [\\"desc(popularity)\\"]})"},"forwardToReplicas":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Whether to apply changes to replica indices (default: false)"}},"hostedApiKey":"none"},"amplitude_event_segmentation":{"id":"amplitude_event_segmentation","name":"Amplitude Event Segmentation","description":"Query event analytics data with segmentation. Get event counts, uniques, averages, and more.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"secretKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude Secret Key"},"eventType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Event type name to analyze"},"start":{"type":"string","required":true,"visibility":"user-or-llm","description":"Start date in YYYYMMDD format"},"end":{"type":"string","required":true,"visibility":"user-or-llm","description":"End date in YYYYMMDD format"},"metric":{"type":"string","required":false,"visibility":"user-or-llm","description":"Metric type: uniques, totals, pct_dau, average, histogram, sums, value_avg, or formula (default: uniques)"},"interval":{"type":"string","required":false,"visibility":"user-or-llm","description":"Time interval: 1 (daily), 7 (weekly), or 30 (monthly)"},"groupBy":{"type":"string","required":false,"visibility":"user-or-llm","description":"Property name to group by (prefix custom user properties with \\"gp:\\")"},"groupBy2":{"type":"string","required":false,"visibility":"user-or-llm","description":"Second property name to group by (prefix custom user properties with \\"gp:\\")"},"limit":{"type":"string","required":false,"visibility":"user-or-llm","description":"Maximum number of group-by values (max 1000)"},"filters":{"type":"string","required":false,"visibility":"user-or-llm","description":"JSON array of filter objects applied to the event, e.g. [{\\"subprop_type\\":\\"event\\",\\"subprop_key\\":\\"city\\",\\"subprop_op\\":\\"is\\",\\"subprop_value\\":[\\"San Francisco\\"]}]"},"formula":{"type":"string","required":false,"visibility":"user-or-llm","description":"Required when metric is \\"formula\\", e.g. \\"UNIQUES(A)/UNIQUES(B)\\""},"segment":{"type":"string","required":false,"visibility":"user-or-llm","description":"JSON segment definition(s) applied to the query"},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_funnels":{"id":"amplitude_funnels","name":"Amplitude Funnels","description":"Analyze conversion rates and drop-off between a sequence of events.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"secretKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude Secret Key"},"events":{"type":"string","required":true,"visibility":"user-or-llm","description":"JSON array of event objects, one per funnel step in order, e.g. [{\\"event_type\\":\\"signup\\"},{\\"event_type\\":\\"purchase\\"}]"},"start":{"type":"string","required":true,"visibility":"user-or-llm","description":"Start date in YYYYMMDD format"},"end":{"type":"string","required":true,"visibility":"user-or-llm","description":"End date in YYYYMMDD format"},"mode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Funnel ordering: \\"ordered\\", \\"unordered\\", or \\"sequential\\" (default: ordered)"},"userType":{"type":"string","required":false,"visibility":"user-or-llm","description":"User type: \\"new\\" or \\"active\\" (default: active)"},"interval":{"type":"string","required":false,"visibility":"user-or-llm","description":"Time interval: -300000 (real-time), -3600000 (hourly), 1 (daily), 7 (weekly), or 30 (monthly)"},"conversionWindowSeconds":{"type":"string","required":false,"visibility":"user-or-llm","description":"Conversion window in seconds (default: 2592000, i.e. 30 days)"},"groupBy":{"type":"string","required":false,"visibility":"user-or-llm","description":"Property to group by (limit: one; prefix custom properties with \\"gp:\\")"},"limit":{"type":"string","required":false,"visibility":"user-or-llm","description":"Maximum number of group-by values (default: 100, max: 1000)"},"segment":{"type":"string","required":false,"visibility":"user-or-llm","description":"JSON segment definition(s) applied to the query"},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_get_active_users":{"id":"amplitude_get_active_users","name":"Amplitude Get Active Users","description":"Get active or new user counts over a date range from the Dashboard REST API.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"secretKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude Secret Key"},"start":{"type":"string","required":true,"visibility":"user-or-llm","description":"Start date in YYYYMMDD format"},"end":{"type":"string","required":true,"visibility":"user-or-llm","description":"End date in YYYYMMDD format"},"metric":{"type":"string","required":false,"visibility":"user-or-llm","description":"Metric type: \\"active\\" or \\"new\\" (default: active)"},"interval":{"type":"string","required":false,"visibility":"user-or-llm","description":"Time interval: 1 (daily), 7 (weekly), or 30 (monthly)"},"groupBy":{"type":"string","required":false,"visibility":"user-or-llm","description":"Property name to group by"},"segment":{"type":"string","required":false,"visibility":"user-or-llm","description":"JSON segment definition(s) applied to the query"},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_get_revenue":{"id":"amplitude_get_revenue","name":"Amplitude Get Revenue","description":"Get revenue LTV data including ARPU, ARPPU, total revenue, and paying user counts.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"secretKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude Secret Key"},"start":{"type":"string","required":true,"visibility":"user-or-llm","description":"Start date in YYYYMMDD format"},"end":{"type":"string","required":true,"visibility":"user-or-llm","description":"End date in YYYYMMDD format"},"metric":{"type":"string","required":false,"visibility":"user-or-llm","description":"Metric: 0 (ARPU), 1 (ARPPU), 2 (Total Revenue), 3 (Paying Users)"},"interval":{"type":"string","required":false,"visibility":"user-or-llm","description":"Time interval: 1 (daily), 7 (weekly), or 30 (monthly)"},"groupBy":{"type":"string","required":false,"visibility":"user-or-llm","description":"Property name to group by (limit: one)"},"segment":{"type":"string","required":false,"visibility":"user-or-llm","description":"JSON segment definition(s) applied to the query"},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_group_identify":{"id":"amplitude_group_identify","name":"Amplitude Group Identify","description":"Set group-level properties in Amplitude. Supports $set, $setOnce, $add, $append, $unset operations.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"groupType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Group classification (e.g., \\"company\\", \\"org_id\\")"},"groupValue":{"type":"string","required":true,"visibility":"user-or-llm","description":"Specific group identifier (e.g., \\"Acme Corp\\")"},"groupProperties":{"type":"string","required":true,"visibility":"user-or-llm","description":"JSON object of group properties. Use operations like $set, $setOnce, $add, $append, $unset."},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_identify_user":{"id":"amplitude_identify_user","name":"Amplitude Identify User","description":"Set user properties in Amplitude using the Identify API. Supports $set, $setOnce, $add, $append, $unset operations.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"userId":{"type":"string","required":false,"visibility":"user-or-llm","description":"User ID (required if no device_id)"},"deviceId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Device ID (required if no user_id)"},"userProperties":{"type":"string","required":true,"visibility":"user-or-llm","description":"JSON object of user properties. Use operations like $set, $setOnce, $add, $append, $unset."},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_list_events":{"id":"amplitude_list_events","name":"Amplitude List Events","description":"List all event types in the Amplitude project with their weekly totals and unique counts.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"secretKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude Secret Key"},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_realtime_active_users":{"id":"amplitude_realtime_active_users","name":"Amplitude Real-time Active Users","description":"Get real-time active user counts at 5-minute granularity for the last 2 days.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"secretKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude Secret Key"},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_retention":{"id":"amplitude_retention","name":"Amplitude Retention","description":"Measure how many users return to perform an action after a starting action.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"secretKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude Secret Key"},"startEvent":{"type":"string","required":true,"visibility":"user-or-llm","description":"JSON starting event object, e.g. {\\"event_type\\":\\"_new\\"} or {\\"event_type\\":\\"_active\\"}"},"returnEvent":{"type":"string","required":true,"visibility":"user-or-llm","description":"JSON returning event object, e.g. {\\"event_type\\":\\"_all\\"} or {\\"event_type\\":\\"_active\\"}"},"start":{"type":"string","required":true,"visibility":"user-or-llm","description":"Start date in YYYYMMDD format"},"end":{"type":"string","required":true,"visibility":"user-or-llm","description":"End date in YYYYMMDD format"},"retentionMode":{"type":"string","required":false,"visibility":"user-or-llm","description":"Retention type: \\"bracket\\", \\"rolling\\", or \\"n-day\\" (default: n-day)"},"retentionBrackets":{"type":"string","required":false,"visibility":"user-or-llm","description":"Required when Retention Mode is \\"bracket\\". Day ranges, e.g. [[0,4]]"},"interval":{"type":"string","required":false,"visibility":"user-or-llm","description":"Time interval: 1 (daily), 7 (weekly), or 30 (monthly)"},"groupBy":{"type":"string","required":false,"visibility":"user-or-llm","description":"Property to group by (limit: one; prefix custom properties with \\"gp:\\")"},"segment":{"type":"string","required":false,"visibility":"user-or-llm","description":"JSON segment definition(s) applied to the query"},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_send_event":{"id":"amplitude_send_event","name":"Amplitude Send Event","description":"Track an event in Amplitude using the HTTP V2 API.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"userId":{"type":"string","required":false,"visibility":"user-or-llm","description":"User ID (required if no device_id)"},"deviceId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Device ID (required if no user_id)"},"eventType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the event (e.g., \\"page_view\\", \\"purchase\\")"},"eventProperties":{"type":"string","required":false,"visibility":"user-or-llm","description":"JSON object of custom event properties"},"userProperties":{"type":"string","required":false,"visibility":"user-or-llm","description":"JSON object of user properties to set (supports $set, $setOnce, $add, $append, $unset)"},"time":{"type":"string","required":false,"visibility":"user-or-llm","description":"Event timestamp in milliseconds since epoch"},"sessionId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Session start time in milliseconds since epoch"},"insertId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Unique ID for deduplication (within 7-day window)"},"appVersion":{"type":"string","required":false,"visibility":"user-or-llm","description":"Application version string"},"platform":{"type":"string","required":false,"visibility":"user-or-llm","description":"Platform (e.g., \\"Web\\", \\"iOS\\", \\"Android\\")"},"country":{"type":"string","required":false,"visibility":"user-or-llm","description":"Two-letter country code"},"language":{"type":"string","required":false,"visibility":"user-or-llm","description":"Language code (e.g., \\"en\\")"},"ip":{"type":"string","required":false,"visibility":"user-or-llm","description":"IP address for geo-location"},"price":{"type":"string","required":false,"visibility":"user-or-llm","description":"Price of the item purchased"},"quantity":{"type":"string","required":false,"visibility":"user-or-llm","description":"Quantity of items purchased"},"revenue":{"type":"string","required":false,"visibility":"user-or-llm","description":"Revenue amount"},"productId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Product identifier"},"revenueType":{"type":"string","required":false,"visibility":"user-or-llm","description":"Revenue type (e.g., \\"purchase\\", \\"refund\\")"},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_user_activity":{"id":"amplitude_user_activity","name":"Amplitude User Activity","description":"Get the event stream for a specific user by their Amplitude ID.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"secretKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude Secret Key"},"amplitudeId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Amplitude internal user ID"},"offset":{"type":"string","required":false,"visibility":"user-or-llm","description":"Offset for pagination (default 0)"},"limit":{"type":"string","required":false,"visibility":"user-or-llm","description":"Maximum number of events to return (default 1000, max 1000)"},"direction":{"type":"string","required":false,"visibility":"user-or-llm","description":"Sort direction: \\"latest\\" or \\"earliest\\" (default: latest)"},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"amplitude_user_profile":{"id":"amplitude_user_profile","name":"Amplitude User Profile","description":"Get a user profile including properties, cohort memberships, and computed properties. Not available for EU data-residency projects.","version":"1.0.0","params":{"secretKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude Secret Key"},"userId":{"type":"string","required":false,"visibility":"user-or-llm","description":"External user ID (required if no device_id)"},"deviceId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Device ID (required if no user_id)"},"getAmpProps":{"type":"string","required":false,"visibility":"user-or-llm","description":"Include Amplitude user properties (true/false, default: false)"},"getCohortIds":{"type":"string","required":false,"visibility":"user-or-llm","description":"Include cohort IDs the user belongs to (true/false, default: false)"},"getComputations":{"type":"string","required":false,"visibility":"user-or-llm","description":"Include computed user properties (true/false, default: false)"}},"hostedApiKey":"none"},"amplitude_user_search":{"id":"amplitude_user_search","name":"Amplitude User Search","description":"Search for a user by User ID, Device ID, or Amplitude ID using the Dashboard REST API.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude API Key"},"secretKey":{"type":"string","required":true,"visibility":"user-only","description":"Amplitude Secret Key"},"user":{"type":"string","required":true,"visibility":"user-or-llm","description":"User ID, Device ID, or Amplitude ID to search for"},"dataResidency":{"type":"string","required":false,"visibility":"user-or-llm","description":"Data residency region: \\"us\\" (default) or \\"eu\\""}},"hostedApiKey":"none"},"apify_get_dataset_items":{"id":"apify_get_dataset_items","name":"APIFY Get Dataset Items","description":"Retrieve items stored in an APIFY dataset","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"APIFY API token from console.apify.com/account#/integrations"},"datasetId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Dataset ID to read items from. Example: \\"9RnD3Pql2vGZkc5H5\\""},"itemLimit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Max items to return (1-250000). Default: all items. Example: 500"},"offset":{"type":"number","required":false,"visibility":"user-or-llm","description":"Number of items to skip at the start. Default: 0"},"fields":{"type":"string","required":false,"visibility":"user-or-llm","description":"Comma-separated list of fields to include. Example: \\"title,url,price\\""}},"hostedApiKey":"none"},"apify_get_run":{"id":"apify_get_run","name":"APIFY Get Run","description":"Get the status and details of an APIFY actor run","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"APIFY API token from console.apify.com/account#/integrations"},"runId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Actor run ID to fetch. Example: \\"HG7ML7M8z78YcAPEB\\""}},"hostedApiKey":"none"},"apify_run_actor_async":{"id":"apify_run_actor_async","name":"APIFY Run Actor (Async)","description":"Start an APIFY Actor run and poll it within the same workflow step until completion or the polling deadline","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"APIFY API token from console.apify.com/account#/integrations"},"actorId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Actor ID or username/actor-name. Examples: \\"apify/web-scraper\\", \\"janedoe/my-actor\\", \\"moJRLRc85AitArpNN\\""},"input":{"type":"string","required":false,"visibility":"user-or-llm","description":"Actor input as JSON string. Example: { \\"startUrls\\": [ { \\"url\\": \\"https://example.com\\" } ], \\"maxPages\\": 10 }"},"waitForFinish":{"type":"number","required":false,"visibility":"user-or-llm","description":"Initial wait time in seconds (0-60) before polling starts. Example: 30"},"itemLimit":{"type":"number","required":false,"default":100,"visibility":"user-or-llm","description":"Max dataset items to fetch (1-250000). Default: 100. Example: 500"},"memory":{"type":"number","required":false,"visibility":"user-or-llm","description":"Memory in megabytes allocated for the actor run (128-32768). Example: 1024 for 1GB, 2048 for 2GB"},"timeout":{"type":"number","required":false,"visibility":"user-or-llm","description":"Timeout in seconds for the actor run. Example: 300 for 5 minutes, 3600 for 1 hour"},"build":{"type":"string","required":false,"visibility":"user-or-llm","description":"Actor build to run. Examples: \\"latest\\", \\"beta\\", \\"1.2.3\\", \\"build-tag-name\\""}},"hostedApiKey":"none"},"apify_run_actor_sync":{"id":"apify_run_actor_sync","name":"APIFY Run Actor (Sync)","description":"Run an APIFY actor synchronously and get results (max 5 minutes)","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"APIFY API token from console.apify.com/account#/integrations"},"actorId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Actor ID or username/actor-name. Examples: \\"apify/web-scraper\\", \\"janedoe/my-actor\\", \\"moJRLRc85AitArpNN\\""},"input":{"type":"string","required":false,"visibility":"user-or-llm","description":"Actor input as JSON string. Example: { \\"startUrls\\": [ { \\"url\\": \\"https://example.com\\" } ], \\"maxPages\\": 10 }"},"memory":{"type":"number","required":false,"visibility":"user-or-llm","description":"Memory in megabytes allocated for the actor run (128-32768). Example: 1024 for 1GB, 2048 for 2GB"},"timeout":{"type":"number","required":false,"visibility":"user-or-llm","description":"Timeout in seconds for the actor run. Example: 300 for 5 minutes, 3600 for 1 hour"},"build":{"type":"string","required":false,"visibility":"user-or-llm","description":"Actor build to run. Examples: \\"latest\\", \\"beta\\", \\"1.2.3\\", \\"build-tag-name\\""}},"hostedApiKey":"none"},"apify_run_task":{"id":"apify_run_task","name":"APIFY Run Task","description":"Run a saved APIFY actor task synchronously and get dataset items (max 5 minutes)","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"APIFY API token from console.apify.com/account#/integrations"},"taskId":{"type":"string","required":true,"visibility":"user-or-llm","description":"Task ID or username/task-name. Examples: \\"janedoe/my-task\\", \\"moJRLRc85AitArpNN\\""},"input":{"type":"string","required":false,"visibility":"user-or-llm","description":"JSON string that overrides the task\'s saved input. Example: { \\"startUrls\\": [ { \\"url\\": \\"https://example.com\\" } ] }"},"itemLimit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Max dataset items to return (1-250000). Example: 500"},"memory":{"type":"number","required":false,"visibility":"user-or-llm","description":"Memory in megabytes allocated for the run (128-32768). Example: 1024 for 1GB"},"timeout":{"type":"number","required":false,"visibility":"user-or-llm","description":"Timeout in seconds for the run. Example: 300 for 5 minutes"},"build":{"type":"string","required":false,"visibility":"user-or-llm","description":"Actor build to run. Examples: \\"latest\\", \\"beta\\", \\"1.2.3\\""}},"hostedApiKey":"none"},"apollo_account_bulk_create":{"id":"apollo_account_bulk_create","name":"Apollo Bulk Create Accounts","description":"Create up to 100 accounts at once in your Apollo database. Set run_dedupe=true to deduplicate by domain, organization_id, and name. Master key required.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"accounts":{"type":"array","required":true,"visibility":"user-or-llm","description":"Array of accounts to create (max 100). Each account should include a name, and may optionally include domain, phone, phone_status_cd, raw_address, owner_id, linkedin_url, facebook_url, twitter_url, salesforce_id, and hubspot_id."},"append_label_names":{"type":"array","required":false,"visibility":"user-only","description":"Array of label names to add to ALL accounts in this request"},"run_dedupe":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"When true, performs aggressive deduplication by domain, organization_id, and name (defaults to false)"}},"hostedApiKey":"none"},"apollo_account_bulk_update":{"id":"apollo_account_bulk_update","name":"Apollo Bulk Update Accounts","description":"Update up to 1000 existing accounts at once in your Apollo database (higher limit than contacts!). Each account must include an id field. Master key required.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"account_ids":{"type":"array","required":false,"visibility":"user-or-llm","description":"Array of account IDs to update with the same values (max 1000). Use with name/owner_id for uniform updates. Use either this OR account_attributes."},"name":{"type":"string","required":false,"visibility":"user-or-llm","description":"When using account_ids, apply this name to all accounts"},"owner_id":{"type":"string","required":false,"visibility":"user-or-llm","description":"When using account_ids, apply this owner to all accounts"},"account_stage_id":{"type":"string","required":false,"visibility":"user-or-llm","description":"When using account_ids, apply this account stage to all accounts"},"account_attributes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Array of account objects with individual updates (each must include id). Example: [{\\"id\\": \\"acc1\\", \\"name\\": \\"Acme\\", \\"owner_id\\": \\"u1\\", \\"account_stage_id\\": \\"s1\\", \\"typed_custom_fields\\": {\\"field_id\\": \\"value\\"}}]"},"async":{"type":"boolean","required":false,"visibility":"user-only","description":"When true, processes the update asynchronously. Only supported when using account_ids; returns 422 if used with account_attributes."}},"hostedApiKey":"none"},"apollo_account_create":{"id":"apollo_account_create","name":"Apollo Create Account","description":"Create a new account (company) in your Apollo database","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Company name (e.g., \\"Acme Corporation\\")"},"domain":{"type":"string","required":false,"visibility":"user-or-llm","description":"Company domain without www. prefix (e.g., \\"acme.com\\")"},"phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Primary phone number for the account"},"owner_id":{"type":"string","required":false,"visibility":"user-only","description":"Apollo user ID of the account owner"},"account_stage_id":{"type":"string","required":false,"visibility":"user-only","description":"Apollo ID for the account stage to assign this account to"},"raw_address":{"type":"string","required":false,"visibility":"user-or-llm","description":"Corporate location (e.g., \\"San Francisco, CA, USA\\")"},"typed_custom_fields":{"type":"json","required":false,"visibility":"user-only","description":"Custom field values as { custom_field_id: value } map"}},"hostedApiKey":"none"},"apollo_account_search":{"id":"apollo_account_search","name":"Apollo Search Accounts","description":"Search your team\'s accounts in Apollo. Display limit: 50,000 records (100 records per page, 500 pages max). Use filters to narrow results. Master key required.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"q_organization_name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter accounts by organization name (partial-match search)"},"account_stage_ids":{"type":"array","required":false,"visibility":"user-only","description":"Filter by account stage IDs"},"account_label_ids":{"type":"array","required":false,"visibility":"user-only","description":"Filter by account label IDs"},"sort_by_field":{"type":"string","required":false,"visibility":"user-or-llm","description":"Sort field: \\"account_last_activity_date\\", \\"account_created_at\\", or \\"account_updated_at\\""},"sort_ascending":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Sort ascending when true. Defaults to descending."},"page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Page number for pagination (e.g., 1, 2, 3)"},"per_page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Results per page, max 100 (e.g., 25, 50, 100)"}},"hostedApiKey":"none"},"apollo_account_update":{"id":"apollo_account_update","name":"Apollo Update Account","description":"Update an existing account in your Apollo database","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"account_id":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the account to update (e.g., \\"acc_abc123\\")"},"name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Company name (e.g., \\"Acme Corporation\\")"},"domain":{"type":"string","required":false,"visibility":"user-or-llm","description":"Company domain (e.g., \\"acme.com\\")"},"phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Company phone number"},"owner_id":{"type":"string","required":false,"visibility":"user-only","description":"Apollo user ID of the account owner"},"account_stage_id":{"type":"string","required":false,"visibility":"user-only","description":"Apollo ID for the account stage to assign this account to"},"raw_address":{"type":"string","required":false,"visibility":"user-or-llm","description":"Corporate location (e.g., \\"San Francisco, CA, USA\\")"},"typed_custom_fields":{"type":"json","required":false,"visibility":"user-only","description":"Custom field values as { custom_field_id: value } map"}},"hostedApiKey":"none"},"apollo_contact_bulk_create":{"id":"apollo_contact_bulk_create","name":"Apollo Bulk Create Contacts","description":"Create up to 100 contacts at once in your Apollo database. Supports deduplication to prevent creating duplicate contacts. Master key required.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"contacts":{"type":"array","required":true,"visibility":"user-or-llm","description":"Array of contacts to create (max 100). Each contact may include first_name, last_name, email, title, organization_name, account_id, owner_id, contact_stage_id, linkedin_url, phone (single string) or phone_numbers (array of {raw_number, position}), contact_emails, typed_custom_fields, and CRM IDs (salesforce_contact_id, hubspot_id, team_id) for cross-system matching"},"append_label_names":{"type":"array","required":false,"visibility":"user-or-llm","description":"Label names to add to all contacts in this request (e.g., [\\"Hot Lead\\"])"},"run_dedupe":{"type":"boolean","required":false,"visibility":"user-only","description":"Enable deduplication to prevent creating duplicate contacts. When true, existing contacts are returned without modification"}},"hostedApiKey":"none"},"apollo_contact_bulk_update":{"id":"apollo_contact_bulk_update","name":"Apollo Bulk Update Contacts","description":"Update up to 100 existing contacts at once in your Apollo database. Each contact must include an id field. Master key required.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"contact_ids":{"type":"array","required":false,"visibility":"user-or-llm","description":"Array of contact IDs to update. Must be paired with an object-form contact_attributes specifying the fields to apply uniformly to all listed contacts."},"contact_attributes":{"type":"json","required":false,"visibility":"user-or-llm","description":"Required. Either an array of per-contact updates (each with id) — used standalone — or a single object of attributes to apply to all contact_ids. Supported fields: owner_id, email, organization_name, title, first_name, last_name, account_id, present_raw_address, linkedin_url, typed_custom_fields"},"async":{"type":"boolean","required":false,"visibility":"user-only","description":"Force asynchronous processing. Automatically enabled for >100 contacts"}},"hostedApiKey":"none"},"apollo_contact_create":{"id":"apollo_contact_create","name":"Apollo Create Contact","description":"Create a new contact in your Apollo database","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"first_name":{"type":"string","required":true,"visibility":"user-or-llm","description":"First name of the contact"},"last_name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Last name of the contact"},"email":{"type":"string","required":false,"visibility":"user-or-llm","description":"Email address of the contact"},"title":{"type":"string","required":false,"visibility":"user-or-llm","description":"Job title (e.g., \\"VP of Sales\\", \\"Software Engineer\\")"},"account_id":{"type":"string","required":false,"visibility":"user-or-llm","description":"Apollo account ID to associate with (e.g., \\"acc_abc123\\")"},"owner_id":{"type":"string","required":false,"visibility":"user-only","description":"User ID of the contact owner (accepted by Apollo but not officially documented for POST /contacts)"},"organization_name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Name of the contact\'s employer (e.g., \\"Apollo\\")"},"website_url":{"type":"string","required":false,"visibility":"user-or-llm","description":"Corporate website URL (e.g., \\"https://www.apollo.io/\\")"},"label_names":{"type":"array","required":false,"visibility":"user-or-llm","description":"Lists/labels to add the contact to (e.g., [\\"Prospects\\"])"},"contact_stage_id":{"type":"string","required":false,"visibility":"user-or-llm","description":"Apollo ID for the contact stage"},"present_raw_address":{"type":"string","required":false,"visibility":"user-or-llm","description":"Personal location for the contact (e.g., \\"Atlanta, United States\\")"},"direct_phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Primary phone number"},"corporate_phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Work/office phone number"},"mobile_phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Mobile phone number"},"home_phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Home phone number"},"other_phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Alternative phone number"},"typed_custom_fields":{"type":"json","required":false,"visibility":"user-or-llm","description":"Custom field values keyed by custom field ID"},"run_dedupe":{"type":"boolean","required":false,"visibility":"user-only","description":"When true, Apollo deduplicates against existing contacts"}},"hostedApiKey":"none"},"apollo_contact_search":{"id":"apollo_contact_search","name":"Apollo Search Contacts","description":"Search your team\'s contacts in Apollo","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"q_keywords":{"type":"string","required":false,"visibility":"user-or-llm","description":"Keywords to search for"},"contact_stage_ids":{"type":"array","required":false,"visibility":"user-only","description":"Filter by contact stage IDs"},"contact_label_ids":{"type":"array","required":false,"visibility":"user-only","description":"Filter by Apollo label IDs (lists)"},"sort_by_field":{"type":"string","required":false,"visibility":"user-only","description":"Sort field: contact_last_activity_date, contact_email_last_opened_at, contact_email_last_clicked_at, contact_created_at, or contact_updated_at"},"sort_ascending":{"type":"boolean","required":false,"visibility":"user-only","description":"When true, sort ascending. Must be used together with sort_by_field"},"page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Page number for pagination (e.g., 1, 2, 3)"},"per_page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Results per page, max 100 (e.g., 25, 50, 100)"}},"hostedApiKey":"none"},"apollo_contact_update":{"id":"apollo_contact_update","name":"Apollo Update Contact","description":"Update an existing contact in your Apollo database","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"contact_id":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the contact to update (e.g., \\"con_abc123\\")"},"first_name":{"type":"string","required":false,"visibility":"user-or-llm","description":"First name of the contact"},"last_name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Last name of the contact"},"email":{"type":"string","required":false,"visibility":"user-or-llm","description":"Email address"},"title":{"type":"string","required":false,"visibility":"user-or-llm","description":"Job title (e.g., \\"VP of Sales\\", \\"Software Engineer\\")"},"account_id":{"type":"string","required":false,"visibility":"user-or-llm","description":"Apollo account ID (e.g., \\"acc_abc123\\")"},"owner_id":{"type":"string","required":false,"visibility":"user-only","description":"User ID of the contact owner (accepted by Apollo but not officially documented for PATCH /contacts/{id})"},"organization_name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Name of the contact\'s employer (e.g., \\"Apollo\\")"},"website_url":{"type":"string","required":false,"visibility":"user-or-llm","description":"Corporate website URL (e.g., \\"https://www.apollo.io/\\")"},"label_names":{"type":"array","required":false,"visibility":"user-or-llm","description":"Lists/labels to add the contact to (e.g., [\\"Prospects\\"])"},"contact_stage_id":{"type":"string","required":false,"visibility":"user-or-llm","description":"Apollo ID for the contact stage"},"present_raw_address":{"type":"string","required":false,"visibility":"user-or-llm","description":"Personal location for the contact (e.g., \\"Atlanta, United States\\")"},"direct_phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Primary phone number"},"corporate_phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Work/office phone number"},"mobile_phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Mobile phone number"},"home_phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Home phone number"},"other_phone":{"type":"string","required":false,"visibility":"user-or-llm","description":"Alternative phone number"},"typed_custom_fields":{"type":"json","required":false,"visibility":"user-or-llm","description":"Custom field values keyed by custom field ID"}},"hostedApiKey":"none"},"apollo_email_accounts":{"id":"apollo_email_accounts","name":"Apollo Get Email Accounts","description":"Get list of team\'s linked email accounts in Apollo","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"}},"hostedApiKey":"none"},"apollo_opportunity_create":{"id":"apollo_opportunity_create","name":"Apollo Create Opportunity","description":"Create a new deal for an account in your Apollo database (master key required)","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the opportunity/deal (e.g., \\"Enterprise License - Q1\\")"},"account_id":{"type":"string","required":false,"visibility":"user-or-llm","description":"ID of the account this opportunity belongs to (e.g., \\"acc_abc123\\")"},"amount":{"type":"string","required":false,"visibility":"user-or-llm","description":"Monetary value as a plain number string with no commas or currency symbols"},"opportunity_stage_id":{"type":"string","required":false,"visibility":"user-only","description":"ID of the opportunity stage"},"owner_id":{"type":"string","required":false,"visibility":"user-only","description":"User ID of the opportunity owner"},"closed_date":{"type":"string","required":false,"visibility":"user-or-llm","description":"Expected close date in YYYY-MM-DD format"},"typed_custom_fields":{"type":"json","required":false,"visibility":"user-only","description":"Custom field values as { custom_field_id: value } map"}},"hostedApiKey":"none"},"apollo_opportunity_get":{"id":"apollo_opportunity_get","name":"Apollo Get Opportunity","description":"Retrieve complete details of a specific deal/opportunity by ID","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"opportunity_id":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the opportunity to retrieve (e.g., \\"opp_abc123\\")"}},"hostedApiKey":"none"},"apollo_opportunity_search":{"id":"apollo_opportunity_search","name":"Apollo Search Opportunities","description":"Search and list all deals/opportunities in your team\'s Apollo account","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"sort_by_field":{"type":"string","required":false,"visibility":"user-or-llm","description":"Sort field: \\"amount\\", \\"is_closed\\", or \\"is_won\\""},"page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Page number for pagination (e.g., 1, 2, 3)"},"per_page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Results per page, max 100 (e.g., 25, 50, 100)"}},"hostedApiKey":"none"},"apollo_opportunity_update":{"id":"apollo_opportunity_update","name":"Apollo Update Opportunity","description":"Update an existing deal/opportunity in your Apollo database","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"opportunity_id":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the opportunity to update (e.g., \\"opp_abc123\\")"},"name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Name of the opportunity/deal (e.g., \\"Enterprise License - Q1\\")"},"amount":{"type":"string","required":false,"visibility":"user-or-llm","description":"Monetary value as a plain number string with no commas or currency symbols"},"opportunity_stage_id":{"type":"string","required":false,"visibility":"user-only","description":"ID of the opportunity stage"},"owner_id":{"type":"string","required":false,"visibility":"user-only","description":"User ID of the opportunity owner"},"closed_date":{"type":"string","required":false,"visibility":"user-or-llm","description":"Expected close date in YYYY-MM-DD format"},"typed_custom_fields":{"type":"json","required":false,"visibility":"user-only","description":"Custom field values as { custom_field_id: value } map"}},"hostedApiKey":"none"},"apollo_organization_bulk_enrich":{"id":"apollo_organization_bulk_enrich","name":"Apollo Bulk Organization Enrichment","description":"Enrich data for up to 10 organizations at once using Apollo","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"domains":{"type":"array","required":true,"visibility":"user-or-llm","description":"Array of company domains to enrich (max 10, no www. or @, e.g., [\\"apollo.io\\", \\"stripe.com\\"])"}},"hostedApiKey":"none"},"apollo_organization_enrich":{"id":"apollo_organization_enrich","name":"Apollo Organization Enrichment","description":"Enrich data for a single organization using Apollo","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"domain":{"type":"string","required":true,"visibility":"user-or-llm","description":"Company domain (e.g., \\"apollo.io\\", \\"acme.com\\")"}},"hostedApiKey":"none"},"apollo_organization_search":{"id":"apollo_organization_search","name":"Apollo Organization Search","description":"Search Apollo\'s database for companies using filters","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"organization_locations":{"type":"array","required":false,"visibility":"user-or-llm","description":"Company HQ locations (cities, US states, or countries)"},"organization_not_locations":{"type":"array","required":false,"visibility":"user-or-llm","description":"Exclude companies whose HQ is in these locations"},"organization_num_employees_ranges":{"type":"array","required":false,"visibility":"user-or-llm","description":"Employee count ranges as \\"min,max\\" strings (e.g., [\\"1,10\\", \\"250,500\\", \\"10000,20000\\"])"},"q_organization_keyword_tags":{"type":"array","required":false,"visibility":"user-or-llm","description":"Industry or keyword tags"},"q_organization_name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Organization name to search for (e.g., \\"Acme\\", \\"TechCorp\\")"},"organization_ids":{"type":"array","required":false,"visibility":"user-or-llm","description":"Apollo organization IDs to include (e.g., [\\"5e66b6381e05b4008c8331b8\\"])"},"q_organization_domains_list":{"type":"array","required":false,"visibility":"user-or-llm","description":"Domain names to filter by (no www. or @, up to 1,000)"},"page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Page number for pagination (e.g., 1, 2, 3)"},"per_page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Results per page, max 100 (e.g., 25, 50, 100)"}},"hostedApiKey":"none"},"apollo_people_bulk_enrich":{"id":"apollo_people_bulk_enrich","name":"Apollo Bulk People Enrichment","description":"Enrich data for up to 10 people at once using Apollo","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"people":{"type":"array","required":true,"visibility":"user-or-llm","description":"Array of people to enrich (max 10)"},"reveal_personal_emails":{"type":"boolean","required":false,"visibility":"user-only","description":"Reveal personal email addresses (uses credits)"},"reveal_phone_number":{"type":"boolean","required":false,"visibility":"user-only","description":"Reveal phone numbers (uses credits, requires webhook_url)"},"webhook_url":{"type":"string","required":false,"visibility":"user-only","description":"Webhook URL for async phone number delivery (required when reveal_phone_number is true)"}},"hostedApiKey":"none"},"apollo_people_enrich":{"id":"apollo_people_enrich","name":"Apollo People Enrichment","description":"Enrich data for a single person using Apollo","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"first_name":{"type":"string","required":false,"visibility":"user-or-llm","description":"First name of the person"},"last_name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Last name of the person"},"name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Full name of the person (alternative to first_name/last_name)"},"id":{"type":"string","required":false,"visibility":"user-or-llm","description":"Apollo ID for the person"},"hashed_email":{"type":"string","required":false,"visibility":"user-or-llm","description":"MD5 or SHA-256 hashed email"},"email":{"type":"string","required":false,"visibility":"user-or-llm","description":"Email address of the person"},"organization_name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Company name where the person works"},"domain":{"type":"string","required":false,"visibility":"user-or-llm","description":"Company domain (e.g., \\"apollo.io\\", \\"acme.com\\")"},"linkedin_url":{"type":"string","required":false,"visibility":"user-or-llm","description":"LinkedIn profile URL"},"reveal_personal_emails":{"type":"boolean","required":false,"visibility":"user-only","description":"Reveal personal email addresses (uses credits)"},"reveal_phone_number":{"type":"boolean","required":false,"visibility":"user-only","description":"Reveal phone numbers (uses credits, requires webhook_url)"},"webhook_url":{"type":"string","required":false,"visibility":"user-only","description":"Webhook URL for async phone number delivery (required when reveal_phone_number is true)"}},"hostedApiKey":"none"},"apollo_people_search":{"id":"apollo_people_search","name":"Apollo People Search","description":"Search Apollo\'s database for people using demographic filters","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key"},"person_titles":{"type":"array","required":false,"visibility":"user-or-llm","description":"Job titles to search for (e.g., [\\"CEO\\", \\"VP of Sales\\"])"},"include_similar_titles":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Whether to return people with job titles similar to person_titles"},"person_locations":{"type":"array","required":false,"visibility":"user-or-llm","description":"Locations to search in (e.g., [\\"San Francisco, CA\\", \\"New York, NY\\"])"},"person_seniorities":{"type":"array","required":false,"visibility":"user-or-llm","description":"Seniority levels (one of: owner, founder, c_suite, partner, vp, head, director, manager, senior, entry, intern)"},"organization_ids":{"type":"array","required":false,"visibility":"user-or-llm","description":"Apollo organization IDs to filter by (e.g., [\\"5e66b6381e05b4008c8331b8\\"])"},"organization_names":{"type":"array","required":false,"visibility":"user-or-llm","description":"Company names to search within (legacy filter)"},"organization_locations":{"type":"array","required":false,"visibility":"user-or-llm","description":"Headquarters locations of the people\'s current employer (e.g., [\'texas\', \'tokyo\', \'spain\'])"},"q_organization_domains_list":{"type":"array","required":false,"visibility":"user-or-llm","description":"Employer domain names (e.g., [\\"apollo.io\\", \\"microsoft.com\\"]) — up to 1,000, no www. or @"},"organization_num_employees_ranges":{"type":"array","required":false,"visibility":"user-or-llm","description":"Employee count ranges for the person\'s current employer. Each entry is \\"min,max\\" (e.g., [\\"1,10\\", \\"250,500\\", \\"10000,20000\\"])"},"contact_email_status":{"type":"array","required":false,"visibility":"user-or-llm","description":"Email statuses to filter by: \\"verified\\", \\"unverified\\", \\"likely to engage\\", \\"unavailable\\""},"q_keywords":{"type":"string","required":false,"visibility":"user-or-llm","description":"Keywords to search for"},"page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Page number for pagination, default 1 (e.g., 1, 2, 3)"},"per_page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Results per page, default 25, max 100 (e.g., 25, 50, 100)"}},"hostedApiKey":"none"},"apollo_sequence_add_contacts":{"id":"apollo_sequence_add_contacts","name":"Apollo Add Contacts to Sequence","description":"Add contacts to an Apollo sequence","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"sequence_id":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the sequence to add contacts to (e.g., \\"seq_abc123\\")"},"contact_ids":{"type":"array","required":false,"visibility":"user-or-llm","description":"Array of contact IDs to add to the sequence (e.g., [\\"con_abc123\\", \\"con_def456\\"]). Either contact_ids or label_names must be provided."},"label_names":{"type":"array","required":false,"visibility":"user-or-llm","description":"Array of label names to identify contacts to add to the sequence. Either contact_ids or label_names must be provided."},"send_email_from_email_account_id":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the email account to send from. Use the Get Email Accounts operation to look this up."},"send_email_from_email_address":{"type":"string","required":false,"visibility":"user-only","description":"Specific email address to send from within the email account."},"sequence_no_email":{"type":"boolean","required":false,"visibility":"user-only","description":"Add contacts even if they have no email address"},"sequence_unverified_email":{"type":"boolean","required":false,"visibility":"user-only","description":"Add contacts with unverified email addresses"},"sequence_job_change":{"type":"boolean","required":false,"visibility":"user-only","description":"Add contacts who recently changed jobs"},"sequence_active_in_other_campaigns":{"type":"boolean","required":false,"visibility":"user-only","description":"Add contacts active in other campaigns"},"sequence_finished_in_other_campaigns":{"type":"boolean","required":false,"visibility":"user-only","description":"Add contacts who finished other campaigns"},"sequence_same_company_in_same_campaign":{"type":"boolean","required":false,"visibility":"user-only","description":"Add contacts even if others from the same company are in the sequence"},"contacts_without_ownership_permission":{"type":"boolean","required":false,"visibility":"user-only","description":"Add contacts without ownership permission"},"add_if_in_queue":{"type":"boolean","required":false,"visibility":"user-only","description":"Add contacts even if they are in the queue"},"contact_verification_skipped":{"type":"boolean","required":false,"visibility":"user-only","description":"Skip contact verification when adding"},"user_id":{"type":"string","required":false,"visibility":"user-only","description":"ID of the user performing the action"},"status":{"type":"string","required":false,"visibility":"user-only","description":"Initial status for added contacts: \\"active\\" or \\"paused\\""},"auto_unpause_at":{"type":"string","required":false,"visibility":"user-only","description":"ISO 8601 datetime to automatically unpause contacts"}},"hostedApiKey":"none"},"apollo_sequence_search":{"id":"apollo_sequence_search","name":"Apollo Search Sequences","description":"Search for sequences/campaigns in your team\'s Apollo account (master key required)","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"q_name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Search sequences by name (e.g., \\"Outbound Q1\\", \\"Follow-up\\")"},"page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Page number for pagination (e.g., 1, 2, 3)"},"per_page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Results per page, max 100 (e.g., 25, 50, 100)"}},"hostedApiKey":"none"},"apollo_task_create":{"id":"apollo_task_create","name":"Apollo Create Task","description":"Create one or more tasks in Apollo (one task per contact_id, master key required)","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"user_id":{"type":"string","required":true,"visibility":"user-or-llm","description":"ID of the Apollo user the task is assigned to"},"contact_ids":{"type":"array","required":true,"visibility":"user-or-llm","description":"Array of contact IDs. One task is created per contact."},"priority":{"type":"string","required":false,"visibility":"user-or-llm","description":"Task priority: \\"high\\", \\"medium\\", or \\"low\\" (defaults to \\"medium\\")"},"due_at":{"type":"string","required":true,"visibility":"user-or-llm","description":"Due date/time in ISO 8601 format (e.g., \\"2024-12-31T23:59:59Z\\")"},"type":{"type":"string","required":true,"visibility":"user-or-llm","description":"Task type: \\"call\\", \\"outreach_manual_email\\", \\"linkedin_step_connect\\", \\"linkedin_step_message\\", \\"linkedin_step_view_profile\\", \\"linkedin_step_interact_post\\", or \\"action_item\\""},"status":{"type":"string","required":true,"visibility":"user-or-llm","description":"Task status: \\"scheduled\\", \\"completed\\", or \\"skipped\\""},"note":{"type":"string","required":false,"visibility":"user-or-llm","description":"Free-form note providing context for the task"}},"hostedApiKey":"none"},"apollo_task_search":{"id":"apollo_task_search","name":"Apollo Search Tasks","description":"Search for tasks in Apollo","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Apollo API key (master key required)"},"sort_by_field":{"type":"string","required":false,"visibility":"user-or-llm","description":"Sort field: \\"task_due_at\\" or \\"task_priority\\""},"open_factor_names":{"type":"array","required":false,"visibility":"user-or-llm","description":"Filter by status. Common values: [\\"task_types\\"] for open tasks, [\\"task_completed_at\\"] for completed tasks."},"page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Page number for pagination (e.g., 1, 2, 3)"},"per_page":{"type":"number","required":false,"visibility":"user-or-llm","description":"Results per page, max 100 (e.g., 25, 50, 100)"}},"hostedApiKey":"none"},"appconfig_create_application":{"id":"appconfig_create_application","name":"AppConfig Create Application","description":"Create an application in AWS AppConfig","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the application to create"},"description":{"type":"string","required":false,"visibility":"user-or-llm","description":"Description of the application"}},"hostedApiKey":"none"},"appconfig_create_configuration_profile":{"id":"appconfig_create_configuration_profile","name":"AppConfig Create Configuration Profile","description":"Create a configuration profile in an AWS AppConfig application","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID to create the configuration profile in"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the configuration profile"},"locationUri":{"type":"string","required":true,"visibility":"user-or-llm","description":"Where the configuration is stored. Use \\"hosted\\" for AppConfig-hosted configurations, or an SSM/S3 URI"},"description":{"type":"string","required":false,"visibility":"user-or-llm","description":"Description of the configuration profile"},"retrievalRoleArn":{"type":"string","required":false,"visibility":"user-or-llm","description":"ARN of an IAM role to retrieve the configuration (required for non-hosted URIs)"},"type":{"type":"string","required":false,"visibility":"user-or-llm","description":"Profile type: AWS.Freeform (default) or AWS.AppConfig.FeatureFlags"}},"hostedApiKey":"none"},"appconfig_create_environment":{"id":"appconfig_create_environment","name":"AppConfig Create Environment","description":"Create an environment for an AWS AppConfig application","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID to create the environment in"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the environment to create"},"description":{"type":"string","required":false,"visibility":"user-or-llm","description":"Description of the environment"}},"hostedApiKey":"none"},"appconfig_create_hosted_configuration_version":{"id":"appconfig_create_hosted_configuration_version","name":"AppConfig Create Hosted Configuration Version","description":"Create a new hosted configuration version for an AppConfig configuration profile","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the configuration profile"},"configurationProfileId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration profile ID to add the version to"},"content":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration content (e.g., a JSON or YAML document)"},"contentType":{"type":"string","required":true,"visibility":"user-or-llm","description":"Content type of the configuration (e.g., application/json, text/plain)"},"description":{"type":"string","required":false,"visibility":"user-or-llm","description":"Description of the configuration version"},"latestVersionNumber":{"type":"number","required":false,"visibility":"user-or-llm","description":"The version number of the latest version, used for optimistic concurrency"},"versionLabel":{"type":"string","required":false,"visibility":"user-or-llm","description":"A user-defined label for the configuration version"}},"hostedApiKey":"none"},"appconfig_delete_application":{"id":"appconfig_delete_application","name":"AppConfig Delete Application","description":"Delete an AWS AppConfig application","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID to delete"}},"hostedApiKey":"none"},"appconfig_delete_configuration_profile":{"id":"appconfig_delete_configuration_profile","name":"AppConfig Delete Configuration Profile","description":"Delete an AWS AppConfig configuration profile","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the configuration profile"},"configurationProfileId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration profile ID to delete"}},"hostedApiKey":"none"},"appconfig_delete_environment":{"id":"appconfig_delete_environment","name":"AppConfig Delete Environment","description":"Delete an AWS AppConfig environment","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the environment"},"environmentId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The environment ID to delete"}},"hostedApiKey":"none"},"appconfig_delete_hosted_configuration_version":{"id":"appconfig_delete_hosted_configuration_version","name":"AppConfig Delete Hosted Configuration Version","description":"Delete a specific hosted configuration version from an AppConfig profile","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the configuration profile"},"configurationProfileId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration profile ID that owns the version"},"versionNumber":{"type":"number","required":true,"visibility":"user-or-llm","description":"The version number to delete"}},"hostedApiKey":"none"},"appconfig_get_application":{"id":"appconfig_get_application","name":"AppConfig Get Application","description":"Get details about a single AWS AppConfig application","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID to retrieve"}},"hostedApiKey":"none"},"appconfig_get_configuration":{"id":"appconfig_get_configuration","name":"AppConfig Get Configuration","description":"Retrieve the latest deployed configuration for an AppConfig application, environment, and profile","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID or name to retrieve configuration for"},"environmentId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The environment ID or name to retrieve configuration for"},"configurationProfileId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration profile ID or name to retrieve"}},"hostedApiKey":"none"},"appconfig_get_configuration_profile":{"id":"appconfig_get_configuration_profile","name":"AppConfig Get Configuration Profile","description":"Get details about a single AWS AppConfig configuration profile","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the configuration profile"},"configurationProfileId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration profile ID to retrieve"}},"hostedApiKey":"none"},"appconfig_get_deployment":{"id":"appconfig_get_deployment","name":"AppConfig Get Deployment","description":"Get details about a specific AWS AppConfig deployment","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID of the deployment"},"environmentId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The environment ID of the deployment"},"deploymentNumber":{"type":"number","required":true,"visibility":"user-or-llm","description":"The sequence number of the deployment"}},"hostedApiKey":"none"},"appconfig_get_environment":{"id":"appconfig_get_environment","name":"AppConfig Get Environment","description":"Get details about a single AWS AppConfig environment","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the environment"},"environmentId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The environment ID to retrieve"}},"hostedApiKey":"none"},"appconfig_get_hosted_configuration_version":{"id":"appconfig_get_hosted_configuration_version","name":"AppConfig Get Hosted Configuration Version","description":"Retrieve a specific hosted configuration version from an AppConfig profile","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the configuration profile"},"configurationProfileId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration profile ID to read the version from"},"versionNumber":{"type":"number","required":true,"visibility":"user-or-llm","description":"The version number to retrieve"}},"hostedApiKey":"none"},"appconfig_list_applications":{"id":"appconfig_list_applications","name":"AppConfig List Applications","description":"List applications in AWS AppConfig","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"maxResults":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of applications to return (1-50)"},"nextToken":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination token from a previous response"}},"hostedApiKey":"none"},"appconfig_list_configuration_profiles":{"id":"appconfig_list_configuration_profiles","name":"AppConfig List Configuration Profiles","description":"List configuration profiles for an AWS AppConfig application","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the configuration profiles"},"maxResults":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of configuration profiles to return (1-50)"},"nextToken":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination token from a previous response"}},"hostedApiKey":"none"},"appconfig_list_deployment_strategies":{"id":"appconfig_list_deployment_strategies","name":"AppConfig List Deployment Strategies","description":"List deployment strategies available in AWS AppConfig","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"maxResults":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of deployment strategies to return (1-50)"},"nextToken":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination token from a previous response"}},"hostedApiKey":"none"},"appconfig_list_deployments":{"id":"appconfig_list_deployments","name":"AppConfig List Deployments","description":"List deployments for an AWS AppConfig environment","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID of the deployments"},"environmentId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The environment ID of the deployments"},"maxResults":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of deployments to return (1-50)"},"nextToken":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination token from a previous response"}},"hostedApiKey":"none"},"appconfig_list_environments":{"id":"appconfig_list_environments","name":"AppConfig List Environments","description":"List environments for an AWS AppConfig application","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the environments"},"maxResults":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of environments to return (1-50)"},"nextToken":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination token from a previous response"}},"hostedApiKey":"none"},"appconfig_list_hosted_configuration_versions":{"id":"appconfig_list_hosted_configuration_versions","name":"AppConfig List Hosted Configuration Versions","description":"List hosted configuration versions for an AWS AppConfig configuration profile","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the configuration profile"},"configurationProfileId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration profile ID to list versions for"},"maxResults":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of versions to return (1-50)"},"nextToken":{"type":"string","required":false,"visibility":"user-or-llm","description":"Pagination token from a previous response"}},"hostedApiKey":"none"},"appconfig_start_deployment":{"id":"appconfig_start_deployment","name":"AppConfig Start Deployment","description":"Start deploying a configuration version to an AWS AppConfig environment","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID to deploy in"},"environmentId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The environment ID to deploy to"},"deploymentStrategyId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The deployment strategy ID to use"},"configurationProfileId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration profile ID to deploy"},"configurationVersion":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration version to deploy"},"description":{"type":"string","required":false,"visibility":"user-or-llm","description":"Description of the deployment"}},"hostedApiKey":"none"},"appconfig_stop_deployment":{"id":"appconfig_stop_deployment","name":"AppConfig Stop Deployment","description":"Stop an in-progress AWS AppConfig deployment","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID of the deployment"},"environmentId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The environment ID of the deployment"},"deploymentNumber":{"type":"number","required":true,"visibility":"user-or-llm","description":"The sequence number of the deployment to stop"}},"hostedApiKey":"none"},"appconfig_update_application":{"id":"appconfig_update_application","name":"AppConfig Update Application","description":"Update the name or description of an AWS AppConfig application","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID to update"},"name":{"type":"string","required":false,"visibility":"user-or-llm","description":"New name for the application"},"description":{"type":"string","required":false,"visibility":"user-or-llm","description":"New description for the application"}},"hostedApiKey":"none"},"appconfig_update_configuration_profile":{"id":"appconfig_update_configuration_profile","name":"AppConfig Update Configuration Profile","description":"Update the name, description, or retrieval role of an AppConfig configuration profile","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the configuration profile"},"configurationProfileId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The configuration profile ID to update"},"name":{"type":"string","required":false,"visibility":"user-or-llm","description":"New name for the configuration profile"},"description":{"type":"string","required":false,"visibility":"user-or-llm","description":"New description for the configuration profile"},"retrievalRoleArn":{"type":"string","required":false,"visibility":"user-or-llm","description":"New ARN of the IAM role used to retrieve the configuration"}},"hostedApiKey":"none"},"appconfig_update_environment":{"id":"appconfig_update_environment","name":"AppConfig Update Environment","description":"Update the name or description of an AWS AppConfig environment","version":"1.0","params":{"region":{"type":"string","required":true,"visibility":"user-only","description":"AWS region (e.g., us-east-1)"},"accessKeyId":{"type":"string","required":true,"visibility":"user-only","description":"AWS access key ID"},"secretAccessKey":{"type":"string","required":true,"visibility":"user-only","description":"AWS secret access key"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The application ID that owns the environment"},"environmentId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The environment ID to update"},"name":{"type":"string","required":false,"visibility":"user-or-llm","description":"New name for the environment"},"description":{"type":"string","required":false,"visibility":"user-or-llm","description":"New description for the environment"}},"hostedApiKey":"none"},"arxiv_get_author_papers":{"id":"arxiv_get_author_papers","name":"ArXiv Get Author Papers","description":"Search for papers by a specific author on ArXiv.","version":"1.0.0","params":{"authorName":{"type":"string","required":true,"visibility":"user-or-llm","description":"Author name to search for"},"maxResults":{"type":"number","required":false,"visibility":"user-only","description":"Maximum number of results to return (default: 10, max: 2000)"}},"hostedApiKey":"none"},"arxiv_get_paper":{"id":"arxiv_get_paper","name":"ArXiv Get Paper","description":"Get detailed information about a specific ArXiv paper by its ID.","version":"1.0.0","params":{"paperId":{"type":"string","required":true,"visibility":"user-or-llm","description":"ArXiv paper ID (e.g., \\"1706.03762\\")"}},"hostedApiKey":"none"},"arxiv_search":{"id":"arxiv_search","name":"ArXiv Search","description":"Search for academic papers on ArXiv by keywords, authors, titles, or other fields.","version":"1.0.0","params":{"searchQuery":{"type":"string","required":true,"visibility":"user-or-llm","description":"The search query to execute"},"searchField":{"type":"string","required":false,"visibility":"user-only","description":"Field to search in: all, ti (title), au (author), abs (abstract), co (comment), jr (journal), cat (category), rn (report number)"},"maxResults":{"type":"number","required":false,"visibility":"user-only","description":"Maximum number of results to return (default: 10, max: 2000)"},"sortBy":{"type":"string","required":false,"visibility":"user-only","description":"Sort by: relevance, lastUpdatedDate, submittedDate (default: relevance)"},"sortOrder":{"type":"string","required":false,"visibility":"user-only","description":"Sort order: ascending, descending (default: descending)"}},"hostedApiKey":"none"},"asana_add_comment":{"id":"asana_add_comment","name":"Asana Add Comment","description":"Add a comment (story) to an Asana task","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"taskGid":{"type":"string","required":true,"visibility":"user-or-llm","description":"Asana task GID (numeric string)"},"text":{"type":"string","required":true,"visibility":"user-or-llm","description":"The text content of the comment"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_add_followers":{"id":"asana_add_followers","name":"Asana Add Followers","description":"Add one or more followers to an Asana task","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"taskGid":{"type":"string","required":true,"visibility":"user-or-llm","description":"GID of the Asana task (numeric string)"},"followers":{"type":"array","required":true,"visibility":"user-or-llm","description":"Array of user GIDs to add as followers to the task"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_create_project":{"id":"asana_create_project","name":"Asana Create Project","description":"Create a new project in an Asana workspace","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"workspace":{"type":"string","required":true,"visibility":"user-or-llm","description":"Asana workspace GID (numeric string) where the project will be created"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the project"},"notes":{"type":"string","required":false,"visibility":"user-or-llm","description":"Notes or description for the project"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_create_section":{"id":"asana_create_section","name":"Asana Create Section","description":"Create a new section in an Asana project","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"projectGid":{"type":"string","required":true,"visibility":"user-or-llm","description":"GID of the Asana project (numeric string) to add the section to"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the section"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_create_subtask":{"id":"asana_create_subtask","name":"Asana Create Subtask","description":"Create a subtask under an existing Asana task","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"taskGid":{"type":"string","required":true,"visibility":"user-or-llm","description":"GID of the parent Asana task (numeric string)"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the subtask"},"notes":{"type":"string","required":false,"visibility":"user-or-llm","description":"Notes or description for the subtask"},"assignee":{"type":"string","required":false,"visibility":"user-or-llm","description":"User GID to assign the subtask to"},"due_on":{"type":"string","required":false,"visibility":"user-or-llm","description":"Due date in YYYY-MM-DD format"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_create_task":{"id":"asana_create_task","name":"Asana Create Task","description":"Create a new task in Asana","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"workspace":{"type":"string","required":true,"visibility":"user-or-llm","description":"Asana workspace GID (numeric string) where the task will be created"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"Name of the task"},"notes":{"type":"string","required":false,"visibility":"user-or-llm","description":"Notes or description for the task"},"assignee":{"type":"string","required":false,"visibility":"user-or-llm","description":"User GID to assign the task to"},"due_on":{"type":"string","required":false,"visibility":"user-or-llm","description":"Due date in YYYY-MM-DD format"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_delete_task":{"id":"asana_delete_task","name":"Asana Delete Task","description":"Delete an Asana task by its GID (moves it to the trash)","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"taskGid":{"type":"string","required":true,"visibility":"user-or-llm","description":"GID of the Asana task to delete (numeric string)"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_get_project":{"id":"asana_get_project","name":"Asana Get Project","description":"Retrieve a single Asana project by its GID","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"projectGid":{"type":"string","required":true,"visibility":"user-or-llm","description":"Asana project GID (numeric string) to retrieve"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_get_projects":{"id":"asana_get_projects","name":"Asana Get Projects","description":"Retrieve all projects from an Asana workspace","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"workspace":{"type":"string","required":true,"visibility":"user-or-llm","description":"Asana workspace GID (numeric string) to retrieve projects from"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_get_task":{"id":"asana_get_task","name":"Asana Get Task","description":"Retrieve a single task by GID or get multiple tasks with filters","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"taskGid":{"type":"string","required":false,"visibility":"user-or-llm","description":"The globally unique identifier (GID) of the task. If not provided, will get multiple tasks."},"workspace":{"type":"string","required":false,"visibility":"user-or-llm","description":"Asana workspace GID (numeric string) to filter tasks (required when not using taskGid)"},"project":{"type":"string","required":false,"visibility":"user-or-llm","description":"Asana project GID (numeric string) to filter tasks"},"limit":{"type":"number","required":false,"visibility":"user-or-llm","description":"Maximum number of tasks to return (default: 50)"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_list_sections":{"id":"asana_list_sections","name":"Asana List Sections","description":"List all sections in an Asana project","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"projectGid":{"type":"string","required":true,"visibility":"user-or-llm","description":"GID of the Asana project (numeric string) to list sections from"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_list_workspaces":{"id":"asana_list_workspaces","name":"Asana List Workspaces","description":"List all Asana workspaces and organizations the authenticated user belongs to","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_search_tasks":{"id":"asana_search_tasks","name":"Asana Search Tasks","description":"Search for tasks in an Asana workspace","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"workspace":{"type":"string","required":true,"visibility":"user-or-llm","description":"Asana workspace GID (numeric string) to search tasks in"},"text":{"type":"string","required":false,"visibility":"user-or-llm","description":"Text to search for in task names"},"assignee":{"type":"string","required":false,"visibility":"user-or-llm","description":"Filter tasks by assignee user GID"},"projects":{"type":"array","required":false,"visibility":"user-or-llm","description":"Array of Asana project GIDs (numeric strings) to filter tasks by"},"completed":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Filter by completion status"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"asana_update_task":{"id":"asana_update_task","name":"Asana Update Task","description":"Update an existing task in Asana","version":"1.0.0","params":{"accessToken":{"type":"string","required":true,"visibility":"hidden","description":"OAuth access token for Asana"},"taskGid":{"type":"string","required":true,"visibility":"user-or-llm","description":"Asana task GID (numeric string) of the task to update"},"name":{"type":"string","required":false,"visibility":"user-or-llm","description":"Updated name for the task"},"notes":{"type":"string","required":false,"visibility":"user-or-llm","description":"Updated notes or description for the task"},"assignee":{"type":"string","required":false,"visibility":"user-or-llm","description":"Updated assignee user GID"},"completed":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Mark task as completed or not completed"},"due_on":{"type":"string","required":false,"visibility":"user-or-llm","description":"Updated due date in YYYY-MM-DD format"}},"oauth":{"required":true,"provider":"asana"},"hostedApiKey":"none"},"ashby_add_candidate_tag":{"id":"ashby_add_candidate_tag","name":"Ashby Add Candidate Tag","description":"Adds a tag to a candidate in Ashby and returns the updated candidate.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ashby API Key"},"onBehalfOfUserId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Active Ashby user UUID to attribute this mutation to; the API key must permit on-behalf-of calls"},"candidateId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The UUID of the candidate to add the tag to"},"tagId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The UUID of the tag to add"}},"hostedApiKey":"none"},"ashby_anonymize_candidate":{"id":"ashby_anonymize_candidate","name":"Ashby Anonymize Candidate","description":"Remove personally identifiable information from an Ashby candidate while retaining the candidate record and its applications. This operation does not delete the candidate. Requires the candidatesWrite permission.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ashby API Key"},"onBehalfOfUserId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Active Ashby user UUID to attribute this mutation to; the API key must permit on-behalf-of calls"},"candidateId":{"type":"string","required":true,"visibility":"user-or-llm","description":"UUID of the candidate to anonymize"}},"hostedApiKey":"none"},"ashby_change_application_source":{"id":"ashby_change_application_source","name":"Ashby Change Application Source","description":"Changes the source attributed to an existing application, so programmatically created applications report correctly on the recruiting side. Requires the candidatesWrite permission.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ashby API Key"},"onBehalfOfUserId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Active Ashby user UUID to attribute this mutation to; the API key must permit on-behalf-of calls"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"UUID of the application whose source should change"},"sourceId":{"type":"string","required":false,"visibility":"user-or-llm","description":"UUID of the source to attribute the application to, as returned by List Sources. Omit only when unsetSource is true."},"unsetSource":{"type":"boolean","required":false,"visibility":"user-or-llm","description":"Set true to deliberately clear the application source. Required to unset, so that a missing or empty sourceId cannot wipe attribution by accident."}},"hostedApiKey":"none"},"ashby_change_application_stage":{"id":"ashby_change_application_stage","name":"Ashby Change Application Stage","description":"Moves an application to a different interview stage. Requires an archive reason when moving to an Archived stage.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ashby API Key"},"onBehalfOfUserId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Active Ashby user UUID to attribute this mutation to; the API key must permit on-behalf-of calls"},"applicationId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The UUID of the application to update the stage of"},"interviewStageId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The UUID of the interview stage to move the application to"},"archiveReasonId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Archive reason UUID. Required when moving to an Archived stage, ignored otherwise"},"archiveEmail":{"type":"json","required":false,"visibility":"user-or-llm","description":"Archive email configuration with communicationTemplateId and optional sendAt ISO 8601 timestamp. Pass null or omit to send no archive email."}},"hostedApiKey":"none"},"ashby_create_application":{"id":"ashby_create_application","name":"Ashby Create Application","description":"Creates a new application for a candidate on a job. Optionally specify interview plan, stage, source, and credited user.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ashby API Key"},"onBehalfOfUserId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Active Ashby user UUID to attribute this mutation to; the API key must permit on-behalf-of calls"},"candidateId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The UUID of the candidate to consider for the job"},"jobId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The UUID of the job to consider the candidate for"},"interviewPlanId":{"type":"string","required":false,"visibility":"user-or-llm","description":"UUID of the interview plan to use (defaults to the job default plan)"},"interviewStageId":{"type":"string","required":false,"visibility":"user-or-llm","description":"UUID of the interview stage to place the application in, or FirstPreInterviewScreen (defaults to the first Lead stage)"},"sourceId":{"type":"string","required":false,"visibility":"user-or-llm","description":"UUID of the source to set on the application"},"creditedToUserId":{"type":"string","required":false,"visibility":"user-or-llm","description":"UUID of the user the application is credited to"},"createdAt":{"type":"string","required":false,"visibility":"user-or-llm","description":"ISO 8601 timestamp to set as the application creation date (defaults to now)"},"applicationHistory":{"type":"json","required":false,"visibility":"user-or-llm","description":"Optional documented application history entries to create with the application"}},"hostedApiKey":"none"},"ashby_create_candidate":{"id":"ashby_create_candidate","name":"Ashby Create Candidate","description":"Creates a new candidate record in Ashby.","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ashby API Key"},"onBehalfOfUserId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Active Ashby user UUID to attribute this mutation to; the API key must permit on-behalf-of calls"},"name":{"type":"string","required":true,"visibility":"user-or-llm","description":"The candidate full name"},"email":{"type":"string","required":false,"visibility":"user-or-llm","description":"Primary email address for the candidate"},"phoneNumber":{"type":"string","required":false,"visibility":"user-or-llm","description":"Primary phone number for the candidate"},"linkedInUrl":{"type":"string","required":false,"visibility":"user-or-llm","description":"LinkedIn profile URL"},"githubUrl":{"type":"string","required":false,"visibility":"user-or-llm","description":"GitHub profile URL"},"website":{"type":"string","required":false,"visibility":"user-or-llm","description":"Personal website URL"},"sourceId":{"type":"string","required":false,"visibility":"user-or-llm","description":"UUID of the source to attribute the candidate to"},"creditedToUserId":{"type":"string","required":false,"visibility":"user-or-llm","description":"UUID of the Ashby user to credit with sourcing this candidate"},"createdAt":{"type":"string","required":false,"visibility":"user-or-llm","description":"Backdated creation timestamp in ISO 8601 (e.g. 2024-01-01T00:00:00Z). Defaults to now."},"alternateEmailAddresses":{"type":"json","required":false,"visibility":"user-or-llm","description":"Array of additional email address strings to add to the candidate, e.g. [\\"a@x.com\\",\\"b@y.com\\"]"},"location":{"type":"json","required":false,"visibility":"user-or-llm","description":"Candidate location object with optional city, region, and country"}},"hostedApiKey":"none"},"ashby_create_note":{"id":"ashby_create_note","name":"Ashby Create Note","description":"Creates a note on a candidate in Ashby. Supports plain text and HTML content (bold, italic, underline, links, lists, code).","version":"1.0.0","params":{"apiKey":{"type":"string","required":true,"visibility":"user-only","description":"Ashby API Key"},"onBehalfOfUserId":{"type":"string","required":false,"visibility":"user-or-llm","description":"Active Ashby user UUID to attribute this mutation to; the API key must permit on-behalf-of calls"},"candidateId":{"type":"string","required":true,"visibility":"user-or-llm","description":"The UUID of the candidate to add the note to"},"note":{"type":"string","required":true,"visibility":"user-or-llm","description":"The note content. If noteType is text/html, supports: , , , ,