Connecting a service
Everything here is stored in your operating system keyring — Keychain on macOS, DPAPI on Windows, libsecret on Linux — and brokered by Studio, so an automation never holds a credential. Connect once in Settings → Connections and every automation on the machine can use it.
Nothing here is a Claritty account. Where a service needs an OAuth app — Gmail, Jira, WhatsApp — you create your own. There is no Claritty client id to sign into, which is the point: your automations talk to your accounts.
The 13 you can connect
Airtable
Create a personal access token at https://airtable.com/create/tokens with the data.records:read and data.records:write scopes, and grant it access to the base.
| Field | ||
|---|---|---|
token | Personal access token | secret · e.g. pat… |
Tools an automation can call: airtable.list_records, airtable.create_record
Brave Search
Create a free key at https://api-dashboard.search.brave.com/ (the free tier allows 2,000 queries a month).
| Field | ||
|---|---|---|
api_key | API key | secret · e.g. BSA… |
Tools an automation can call: brave-search.web
GitHub
Create a fine-grained personal access token at https://github.com/settings/tokens with access to the repositories this automation should touch.
| Field | ||
|---|---|---|
token | Personal access token | secret · e.g. github_pat_… |
Tools an automation can call: github.list_issues, github.create_issue, github.comment
Gmail
Gmail needs YOUR OWN Google app — Studio never uses a Claritty one, so nothing here depends on an app we control. At https://console.cloud.google.com/apis/credentials create an OAuth client (type: Desktop app), enable the Gmail API, and add the https://www.googleapis.com/auth/gmail.modify scope. Then get a refresh token for it — https://developers.google.com/oauthplayground with "Use your own OAuth credentials" ticked is the quickest way. Paste the client id, client secret and refresh token below; the access token is derived and never stored.
| Field | ||
|---|---|---|
client_id | OAuth client id | not secret · e.g. …apps.googleusercontent.com |
client_secret | OAuth client secret | secret · e.g. GOCSPX-… |
refresh_token | Refresh token | secret · e.g. 1//0… |
Tools an automation can call: gmail.send, gmail.search, gmail.get_message
Jira
Create an API token at https://id.atlassian.com/manage-profile/security/api-tokens, then give your site (the yourcompany.atlassian.net part, no https://), the email you sign in with, and that token. Jira Cloud authenticates the pair as HTTP basic — there is no OAuth app to register and no admin needed.
| Field | ||
|---|---|---|
site | Site | not secret · e.g. yourcompany.atlassian.net |
email | Account email | not secret · e.g. you@company.com |
api_token | API token | secret |
Tools an automation can call: jira.create_issue, jira.search_jql, jira.add_comment
Linear
Create a personal API key in Linear under Settings → Security & access → Personal API keys.
| Field | ||
|---|---|---|
api_key | API key | secret · e.g. lin_api_… |
Tools an automation can call: linear.create_issue
Notion
Create an integration at https://www.notion.so/my-integrations, copy the Internal Integration Secret, then share the target page or database with it from Notion’s ⋯ menu — otherwise it sees nothing.
| Field | ||
|---|---|---|
token | Internal integration secret | secret · e.g. ntn_… |
Tools an automation can call: notion.create_page, notion.query_database
Outbound webhook
No credential needed. Give the automation a URL and it will POST JSON to it — useful for Zapier, Make, n8n, or anything you already run.
| Field |
|---|
Tools an automation can call: outbound-webhook.post
Email (Resend)
Create an API key at https://resend.com/api-keys and verify the domain you want to send from. The free tier covers a few thousand emails a month, which is more than an automation needs.
| Field | ||
|---|---|---|
api_key | API key | secret · e.g. re_… |
Tools an automation can call: resend.send
Slack
Create an app at https://api.slack.com/apps, add the chat:write scope under OAuth & Permissions, install it to your workspace, and copy the Bot User OAuth Token. Invite the bot to any channel it should post in. To let it RECEIVE instructions too: turn on Socket Mode, subscribe to the app_mention event, and generate an app-level token with connections:write. Studio dials out to Slack, so nothing needs a public URL and there is no webhook to expose.
| Field | ||
|---|---|---|
bot_token | Bot user OAuth token | secret · e.g. xoxb-… |
app_token | App-level token (optional, to receive messages) | secret · e.g. xapp-… |
Tools an automation can call: slack.post_message
Stripe
Copy a restricted key from https://dashboard.stripe.com/apikeys. Give it read access only unless the automation genuinely needs to move money.
| Field | ||
|---|---|---|
api_key | Secret or restricted key | secret · e.g. rk_live_… |
Tools an automation can call: stripe.list_invoices
Telegram
Message @BotFather in Telegram, send /newbot, and copy the token it gives you. Then message your new bot once and open https://api.telegram.org/bot<TOKEN>/getUpdates to find your chat id.
| Field | ||
|---|---|---|
bot_token | Bot token | secret · e.g. 123456:ABC-DEF… |
chat_id | Default chat id | not secret · e.g. 123456789 |
Tools an automation can call: telegram.send_message
WhatsApp needs YOUR OWN Meta app — Studio never brokers this. At https://developers.facebook.com create an app, add the WhatsApp product, and from its API Setup page copy the phone number id and a permanent access token (generate one from a System User in Business Settings; the sample token shown there expires in 24 hours). Message your own number from that page once, so WhatsApp will let the number receive messages back.
| Field | ||
|---|---|---|
access_token | Access token | secret · e.g. EAA… |
phone_number_id | Phone number id | not secret · e.g. 1234567890 |
to | Your number, with country code | not secret · e.g. 447700900000 |
Tools an automation can call: whatsapp.send_message
The other 27, which Studio cannot broker yet
The hosted platform provides these. Studio has no connector for them, so an automation that calls one fails at run time, however sensible the id looks.
They are listed in full rather than hidden, for two reasons. Every tool id below is real, so knowing the exact name is most of the work of adding it. And a name you can see is a name nobody has to guess: the expensive failure here is an agent inventing jira.create_issue because the shape of the id was obvious.
Accounting
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
QuickBooks (quickbooks) | Read vendor bills, vendors, and invoices from the authenticated user's QuickBooks Online company (accounts payable). | quickbooks.list_bills quickbooks.list_vendors quickbooks.get_bill quickbooks.list_vendor_credits | oauth2 |
Xero (xero) | Read supplier bills (accounts payable) and contacts from the authenticated user's Xero organisation. | xero.list_bills xero.list_vendors xero.get_bill xero.list_vendor_credits | oauth2 |
AI
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
Anthropic (anthropic) | Call Anthropic Messages directly. Most apps use the Claritty proxy instead and get this for free. | anthropic.chat anthropic.with_tools | apiKey |
OpenAI (openai) | Call OpenAI chat completions, embeddings, and image generation. Routed via the Claritty proxy when no key is configured. | openai.chat openai.embeddings openai.image_generate | apiKey |
Analytics
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
PostHog (posthog) | Capture events and run HogQL queries against your PostHog project. | posthog.query posthog.capture_event | apiKey |
Calendar
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
Calendly (calendly) | List scheduled meetings and cancel events with a Calendly personal access token. | calendly.list_events calendly.cancel_event | apiKey |
Google Calendar (google-calendar) | Read events and create events on the user's Google Calendar. | gcal.list_events gcal.create_event | oauth2 |
Outlook Calendar (outlook-calendar) | Read and write events on the user's Outlook calendar. | outcal.list_events outcal.create_event | oauth2 |
Communication
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
Discord (discord) | Send messages to Discord channels and list guilds. | discord.send_message discord.list_guilds | apiKey |
Microsoft Teams (microsoft-teams) | Post messages to Teams channels and chats. | teams.post_message teams.list_chats | oauth2 |
Twilio (twilio) | Send SMS and place voice calls. | twilio.send_sms twilio.make_call twilio.send_whatsapp | apiKey |
CRM
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
HubSpot (hubspot) | Create and search contacts, and update deals in the user's HubSpot CRM. | hubspot.create_contact hubspot.search_contacts hubspot.update_deal | oauth2 |
Pipedrive (pipedrive) | List and create deals in Pipedrive. | pipedrive.list_deals pipedrive.create_deal | apiKey |
Salesforce (salesforce) | Run SOQL, create leads, and update opportunities in Salesforce. | sfdc.soql_query sfdc.create_lead sfdc.update_opportunity | oauth2 |
Developer tools
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
GitLab (gitlab) | List issues and create merge requests in GitLab. | gitlab.list_issues gitlab.create_mr | apiKey |
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
Outlook (outlook) | Send and read email through the authenticated user's Outlook (Microsoft 365) account. | outlook.send outlook.list_messages outlook.search | oauth2 |
Files
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
Dropbox (dropbox) | List and upload files in Dropbox. | dropbox.list_files | oauth2 |
Google Drive (google-drive) | Search and list files in the user's Google Drive. | gdrive.list_files | oauth2 |
Marketing
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
Mailchimp (mailchimp) | Add subscribers and send campaigns. | mailchimp.add_subscriber mailchimp.send_campaign | apiKey |
Productivity
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
Asana (asana) | Create and list tasks in Asana projects. | asana.create_task asana.list_tasks | oauth2 |
ClickUp (clickup) | Create and list tasks in ClickUp. | clickup.create_task clickup.list_tasks | apiKey |
Trello (trello) | Create cards and list cards across Trello boards. | trello.create_card trello.list_cards | apiKey |
Social
| Service | What it does | Tools it names | Credential |
|---|---|---|---|
Facebook (facebook) | Publish to and read the posts of a Facebook Page you administer. | facebook.create_post facebook.fetch_page_posts | oauth2 |
Instagram (instagram) | Publish photos to and read the media of your Instagram Business account. | instagram.create_post instagram.fetch_media | oauth2 |
LinkedIn (linkedin) | Read the authenticated user's LinkedIn feed and publish posts to their personal feed or a Company Page they administer. | linkedin.fetch_posts linkedin.create_post linkedin.list_organizations | oauth2 |
TikTok (tiktok) | Publish videos to and list the videos of your connected TikTok creator account. | tiktok.create_post tiktok.fetch_videos | oauth2 |
X (Twitter) (x-twitter) | Post tweets and search recent tweets. | x.post_tweet x.search_tweets | oauth2 |
Adding a connector for one of the 27
This is a defined job rather than a wish, and it takes an afternoon. A connector is declarative: no code runs per service, so what you are writing is a spec the engine executes.
1. Write the request
From inside an automation, ask your coding agent for the add-an-integration skill. It produces INTEGRATION-REQUEST.md: where a person gets the credential, the fields, the auth type, and one block per operation you actually need. A connector with three used tools beats one with thirty untested ones.
Do this rather than reaching for the closest-looking tool id. A manifest naming a tool nothing implements passes validation, runs, gets skipped, and reports success, which is the worst way for an automation to fail.
2. Pick the auth type
One of the engine's, and which field carries it:
| Type | Is |
|---|---|
bearer | an Authorization: Bearer <field> header. Most APIs. |
header | a named header, with an optional prefix. |
query | a query parameter. |
basic | base64 user:pass, built from two fields. |
none | a public API, no credential. |
oauth2 | a refresh token exchanged for an access token against the provider's own token endpoint, using your own app. There is no Claritty client id to fall back on. |
If the provider only accepts a value in the URL, as Telegram does with the bot token and WhatsApp with the phone number id, name those fields in pathCredentials on the tool. That is opt-in on purpose, and every named value is scrubbed out of anything the call throws.
3. Add the spec
It goes in packages/connectors/src/catalog.ts. This is Slack, whole:
{
id: "slack",
name: "Slack",
howToConnect: "Create an app at https://api.slack.com/apps, add the chat:write scope under OAuth & Permissions, install it to your workspace, and copy the Bot User OAuth Token. Invite the bot to any channel it should post in. To let it RECEIVE instructions too: turn on Socket Mode, subscribe to the app_mention event, and generate an app-level token with connections:write. Studio dials out to Slack, so nothing needs a public URL and there is no webhook to expose.",
fields: [
{
key: "bot_token",
label: "Bot user OAuth token",
secret: true,
placeholder: "xoxb-…"
},
{
key: "app_token",
label: "App-level token (optional, to receive messages)",
secret: true,
placeholder: "xapp-…",
optional: true
}
],
tools: [
{
id: "slack.post_message",
summary: "Post a message to a channel.",
method: "POST",
url: "https://slack.com/api/chat.postMessage",
auth: {
type: "bearer",
field: "bot_token"
},
body: {
channel: "{arg.channel}",
text: "{arg.text}",
thread_ts: "{arg.thread_ts}"
},
result: "ts"
}
]
}{arg.x} is an argument from the automation. A body value that is exactly {arg.x} keeps its type; "{arg.x} items" makes it a string. result is a dotted path into the response, or omit it to return the whole body.
4. The rules the engine enforces
- A credential may not appear in a URL unless the spec names it in
pathCredentials.{creds.*}in a url or query is rejected outright, because those leak into logs, error messages and run history. Useauth. - Public hosts only. No localhost, link-local or private ranges. An automation that takes a URL as input must not become a way to reach your router or a cloud metadata endpoint.
5. Prove it, then regenerate
pnpm test # the engine, including your spec
pnpm proof:integrations # a real HTTP call through the vault, credential never leaving the host
pnpm sync:catalog # this page, the seed catalog and llms.txtThat last command is what moves the service out of the table above and into the list at the top, everywhere it is named, including on claritty.ai. Nothing about a connector is written by hand twice.