Add your tools to Captain
Captain tools live in the Replynivo/tools repository on GitHub. Add a folder with a manifest and a README, open a pull request, and the Replynivo team reviews it. Merged tools appear in this catalog.
Fork Replynivo/tools and add a folder
Add one folder at the repository root for the service you are connecting. Its name becomes the page URL, so keep it short and lowercase, like shopify. Each folder needs a toolset.yml and a README.md, and the README becomes the page people read here.
Optional: add logo.png and logo-dark.png beside the manifest. SVG, WebP, and AVIF are also supported. Use one file per variant, up to 2 MiB and 4096 by 4096 pixels. Logos are converted to WebP.
Replynivo/tools tools/ ├── stripe/ └── shopify/ ├── README.md ├── toolset.yml ├── logo.png (optional) └── logo-dark.png (optional)Declare the tools
The manifest is data, and nothing in it executes. It has three parts: the settings and credentials an account must supply, the HTTP requests Captain is allowed to make, and the placeholders that wire the two together.
Set
authorto your GitHub username or organization, without the @. It must be an existing GitHub account, and the catalog shows it with its avatar.Set one
categoryusing the exact spelling: Commerce, Payments & billing, Shipping, CRM, Engineering & status, Scheduling, Business data & research, Identity & access, Marketing, Others. If omitted, it defaults to Others. Custom categories and lists are rejected.Optional top-level
headersapply to every tool. Use up to 16 HTTP field names with fixed string values of at most 1 KiB each. Quote dates in YAML, for examplex-api-version: '2026-05-01'. Header names are case insensitive and cannot contain spaces or repeat. Captain reserves Authorization, Host, Content-Length, Content-Type, and any header starting with X-Replynivo. Keep credentials in secrets and auth_config; header values cannot contain placeholders or control characters.Every field is checked on build, and unknown fields are rejected. A typo in a field name keeps the whole manifest out of the catalog rather than publishing it half-read.
shopify/toolset.yml version: 1.0.0kind: captain_toolsetname: Shopify Support Toolscategory: Commercedescription: Look up Shopify orders for support conversations.author: your-github-username inputs: shop_domain: label: Shopify store domain type: string required: true secrets: admin_api_access_token: label: Admin API access token type: password required: true tools: - id: get_shopify_order title: Get Shopify Order description: Retrieve an order by its numeric resource ID. http_method: GET requires_email_verification: true endpoint_url: https://${{ inputs.shop_domain }}/admin/api/orders/{{ order_id }}.json auth_type: api_key auth_config: name: X-Shopify-Access-Token key: ${{ secrets.admin_api_access_token }} param_schema: - name: order_id type: integer description: The numeric Shopify order resource ID. required: trueThe two placeholders
- ${{ inputs.name }} ${{ secrets.name }}
- Filled in once, when someone installs your tools. Pulls from the values they entered for your inputs and secrets. Works in the URL, in auth_config, and in a request body.
- {{ order_id }}
- Filled in on every call, by Captain. Each one needs a matching param_schema entry. Captain picks the value out of the conversation using the description you write there.
Protect customer data
If a tool returns or changes a customer's own data, such as orders, billing, or bookings, it should run only after the customer verifies their email with a one-time code. Set
requires_email_verification: trueon the tool. If the tool looks the customer up by email, give that parametersource: verified.emailinstead. Replynivo then fills in the verified email, and Captain can't pass a different one.stripe/toolset.yml tools: - id: find_customers_by_email title: Find Customers by Email description: Find Stripe customers by email address. http_method: GET requires_email_verification: true endpoint_url: https://api.stripe.com/v1/customers/search?query=email:"{{ email | url_encode }}" auth_type: bearer auth_config: token: ${{ secrets.api_key }} param_schema: - name: email type: string description: The customer's email address. required: true source: verified.emailValidate the manifest
Paste toolset.yml into the validator and resolve every reported issue. It uses the same schema and Liquid checks as catalog indexing.
Open a pull request
Open a pull request against Replynivo/tools. The Replynivo team reviews every tool, and once it is merged it appears in this catalog.
- Short, lowercase folder name
- author set to your GitHub account
- README covers setup and permissions
- No credentials in the manifest
- Semantic version in toolset.yml
- Read-only calls unless a write is needed
- Customer data tools require a verified email
Give this to your coding agent
Paste these instructions into a coding agent in your fork of Replynivo/tools. It will ask which service you want to support, then add a valid folder for it.
Help me add Captain tools to this repository, a fork of https://github.com/chatwoot/tools.
Start by asking me which service the tools should support and which GitHub username or organization to credit as the author. Do not make any files or assumptions until I answer.
Before writing files, inspect the service's official API documentation and the existing folders in this repository. Do not invent endpoints, authentication fields, parameters, or response behavior.
Create one short, lowercase, URL-safe folder at the repository root named after the service, for example stripe. It must not already exist. The folder contains:
- toolset.yml: the strict Captain manifest
- README.md: setup instructions, required permissions, and a concise description of every tool
Follow this manifest contract:
- The schema is implicitly v1. Do not add schema_version or toolset_version.
- Set version to a semantic release version such as 1.0.0.
- Set kind to exactly captain_toolset.
- Set author to the GitHub username or organization I gave you, without the @. It must be an existing GitHub account.
- Include name, description, and 1–50 tools. inputs and secrets are optional maps.
- Choose one category using its exact spelling: Commerce, Payments & billing, Shipping, CRM, Engineering & status, Scheduling, Business data & research, Identity & access, Marketing, Others. Omitted category defaults to Others; custom values and lists are rejected.
- Use inputs for non-sensitive configuration and secrets for credentials.
- Optional top-level headers apply to every tool. Use fixed string values only, with no credentials, control characters, or placeholders. Quote date-like YAML values, for example x-api-version: '2026-05-01'.
- Tool IDs must be stable snake_case matching ^[a-z][a-z0-9_]*$.
- Every tool needs id, title, description, http_method, endpoint_url, and auth_type.
- http_method must be GET, POST, PUT, PATCH, or DELETE.
- Use ${{ inputs.name }} and ${{ secrets.name }} for install-time values.
- Use {{ name }} for call-time values and declare each one in param_schema.
- Add request_template only when the request needs a body.
- Do not add undocumented fields or commit literal credentials.
- Write tool descriptions that explain when Captain should call the tool.
Exact schema:
- Top level: version (required semver string), kind (required literal captain_toolset), name (required, 1–100 characters), description (required, 1–500 characters), author (required GitHub username or organization, without the @), category (optional, one of the allowed categories above, defaults to Others), headers (optional map, defaults to {}), inputs (optional, defaults to {}), secrets (optional, defaults to {}), and tools (required, 1–50 items). No other top-level fields are valid.
- headers accepts up to 16 HTTP field names and literal string values of at most 1 KiB each. Names are case insensitive, cannot repeat, and must follow HTTP field name rules; no X- prefix is required. Authorization, Host, Content-Length, Content-Type, and any header starting with X-Chatwoot are reserved regardless of case. Values cannot contain control characters or placeholders.
- Each input or secret supports only label (required, 1–80 characters), type (optional: string, password, number, boolean, or select; defaults to string), placeholder (optional, up to 200 characters), required (optional boolean; defaults to false), and options (optional list of strings).
- Each tool supports only id, title, description, http_method, endpoint_url, auth_type, auth_config, param_schema, request_template, response_template, enabled, and requires_email_verification.
- Required tool fields: id; title (1–100 characters); description (1–500 characters); http_method; endpoint_url (1–2,000 characters); and auth_type (1–50 characters).
- Optional tool fields: auth_config (map), param_schema (list of maps), request_template (1–20,000 characters), response_template (Liquid string with no explicit length limit), enabled (boolean, defaults to true), and requires_email_verification (boolean, defaults to false).
- auth_config and each param_schema item are flexible maps interpreted by Chatwoot. The manifest, each input or secret, and each tool are strict objects.
- A param_schema item may have source: verified.email. In customer conversations, Chatwoot fills that parameter with the customer's verified email and hides it from Captain, so Captain cannot pass a different one. A parameter with a source must have type: string. verified.email is the only allowed source.
- A tool with a source parameter requires email verification even if requires_email_verification is false.
Placeholder rules:
- Every install-time placeholder must reference a declared input or secret.
- Every call-time placeholder must have a param_schema item with the same name.
- Placeholders may appear in endpoint_url, auth_config values, and request_template.
- response_template formats the HTTP response as plain text using strict Liquid. Its syntax, global variables, and filters are validated when the catalog indexes the manifest.
- In response_template, response contains the parsed JSON body or raw response string; r is an alias for the same value.
- If response_template is omitted or blank, Captain receives the raw response body.
- Response status and headers are not available to the Liquid template.
Use this minimal valid manifest as a structural reference:
version: 1.0.0
kind: captain_toolset
name: Example Support Tools
category: Others
description: Look up account information for support conversations.
author: your-github-username
headers:
x-api-version: '2026-05-01'
secrets:
api_token:
label: API token
type: password
required: true
tools:
- id: get_account
title: Get Account
description: Retrieve an account when support needs current account details.
http_method: GET
endpoint_url: https://api.example.com/accounts/{{ account_id }}
auth_type: bearer
auth_config:
token: ${{ secrets.api_token }}
param_schema:
- name: account_id
type: string
description: The account identifier supplied by the customer.
required: true
enabled: true
Keep the first version focused on safe, useful support workflows. Prefer read operations unless a write action is explicitly requested.
Protect customer data. If a tool returns or changes a customer's own data, such as billing, bookings, or CRM records, set requires_email_verification: true so it runs only after the customer verifies their email with a one-time code. If the tool looks the customer up by email, give that parameter source: verified.email instead.
Before finishing:
1. Validate the completed manifest with:
curl -X POST /api/captain/tools/validate -H 'Content-Type: application/yaml' --data-binary @path/to/toolset.yml
Resolve every returned issue and repeat until the response has valid: true.
2. Check the YAML for duplicate keys and aliases; neither is allowed.
3. Check every object against the exact allowed fields above.
4. Check every placeholder against its input, secret, or param_schema declaration.
5. Confirm every endpoint, method, authentication setting, and parameter against official documentation.
6. Summarize the files, tools, inputs, and secrets you added. Do not commit or open a pull request unless asked.Ready when you are
Open a pull request against Replynivo/tools. The existing folders show how other tools are laid out.