Connectors reference
Bundle
Section titled “Bundle”A version is a tar of:
manifest.json requiredindex.js optional, for JavaScript actionsui/ optional settings or panel pagesManifest
Section titled “Manifest”| Field | Type | Notes |
|---|---|---|
id |
string | Reverse DNS, for example np.example.clinic. Fixed for the connector’s life. |
version |
string | Semver. Each upload needs a new version. |
name |
string | Shown to organizations. |
auth |
object | type is none, api_key, bearer, basic or oauth. For api_key, header or query names where the key goes, and prefix is put before it. The organization enters the secrets when installing. |
config |
JSON Schema | Settings the organization fills in when installing. Rendered as a form. |
permissions |
object | hosts the connector may call (api.example.com, *.example.com, or {{config.base_url}} for the host the organization enters), and the AirFone data it may use: records:read, records:write, contacts:read, messages:send. |
actions |
array | See below. |
knowledge |
array | Optional sources the assistant can search, each backed by an action. |
triggers |
array | Optional inbound webhooks from the other system, mapped to AirFone events. |
Actions
Section titled “Actions”| Field | Notes |
|---|---|
name |
Unique in the connector. Lowercase words joined by dots, like order.create. |
description |
Shown to the assistant. Say when to use it and what it needs. |
input, output |
JSON Schema. Input is validated before the action runs, output after. |
risk |
read, change or money. |
confirm |
none, caller or staff. |
http |
A declarative HTTP action. |
js |
The name of an export in index.js. Defaults to name. |
fixtures |
Optional test calls: { input, config?, expect? }. Review runs each one, with no network, and expect must be a subset of the output. |
An action has either http or js.
Action kinds
Section titled “Action kinds”Declarative HTTP. method, url (a template with {{config.x}} and {{input.x}}), optional query, headers and body templates, and map, a JSONPath expression per output field. Secrets go in headers or query as {{secrets.name}}, never in the URL or body. errors maps status codes to messages the assistant can say. These run in the AirFone server with no JavaScript, so they are the fastest kind.
JavaScript. An async function (input, ctx) => output exported from index.js as actions.<name>. Use it for logins, chained calls or reshaping data.
Both kinds look the same to the assistant and to workflows.
Risk and confirmation
Section titled “Risk and confirmation”risk says what the action can do. confirm says who must agree before it runs.
none: the assistant runs it when needed. Allowed forreadonly.caller: the assistant reads the details back and runs it only after the customer says yes. The minimum formoney.staff: the action waits in AirFone’s approvals until a staff member approves. The customer is told they will hear back.
Organizations can make a rule stricter per action, never looser.
The ctx API
Section titled “The ctx API”| Member | What it does |
|---|---|
ctx.config |
The organization’s settings, read only. Secrets are not included. |
ctx.http.fetch(url, { method, headers, query, json, body }) |
HTTP to a declared host. Credentials from auth are added by AirFone, and an Authorization header you set is dropped. Returns { status, ok, headers, json, text }, where json is the parsed body or null. |
ctx.store.get(key), ctx.store.set(key, value), ctx.store.delete(key) |
A small key-value store per install. Keys up to 200 characters, values up to 64 KB. A { ttl } option is accepted but not applied yet. |
ctx.records.upsert(records) |
Adds or updates records on contacts. One record or an array. Needs records:write. |
| `ctx.log.info | warn |
Calls on ctx finish before they return, so await is optional. Nothing else is available: no global fetch, no timers, no file system. Code at the top of index.js runs once when the bundle loads, without ctx, and must not do I/O. For Google Sheets, use the Google Sheets connector.
Limits
Section titled “Limits”Each action call gets 64 MB of memory, 2 seconds of CPU and 10 seconds of wall time. Time spent waiting for HTTP counts toward wall time, not CPU. Each HTTP request may take 10 seconds and return 4 MB. Past any limit the call is stopped and the assistant tells the customer it could not finish. The bundle may be up to 5 MB, and index.js up to 1 MB.
Permissions
Section titled “Permissions”ctx.http.fetch reaches only permissions.hosts, and never private or local addresses, even through DNS. AirFone data needs the matching permission. Permissions are enforced by the runtime, not only by review.
Signing
Section titled “Signing”Every bundle is signed with your Ed25519 key over its id, version and sha256. airfone connector keygen creates the key. Register its public key once in the console under Connectors, Signing keys. AirFone verifies your signature and adds its own after review. Servers refuse a bundle unless both signatures and the content hash match.
Publishing
Section titled “Publishing”- Upload a version:
airfone connector publish, orairfone connector packandsign, then upload the.tarand signature in the console. - Automated review runs.
- If it passes, the version is approved. New connectors start private: you install them in your own organizations, and a human reviews before public listing.
Review checks
Section titled “Review checks”- The manifest matches the schema.
- Hosts are declared and public.
- Permission changes from the previous version are listed. Any new permission needs a human review.
- The bundle is within size.
- The code uses no banned APIs and contains nothing that looks like a secret.
index.jsloads, and every fixture inmanifest.jsonpasses in the sandbox with no network, within the limits. Output must match the action’soutputschema.
airfone connector test runs the same checks on your machine.
Versions
Section titled “Versions”- A new minor or patch version reaches installs automatically, in stages, and rolls back if its error rate rises.
- A new major version, or any new permission, waits until each organization’s admin approves it.
- A running workflow keeps the version it started on.
- AirFone can disable a version everywhere within seconds if it misbehaves.