For the complete documentation index, see llms.txt. This page is also available as Markdown.

Custom Adapters

The Custom Adapter feature lets you author an adapter in Python and store it outside any single integration, together with a typed configuration schema. You can reuse one custom adapter across integrations, and each adapter can hold several named configurations that each supply their own values.

Custom Adapters share the Shared Code page with Shared Modules and appear under the Custom Adapters tab.

Permissions

Users must have the can_use_custom_adapters permission to access the Custom Adapters tab. This permission is independent of can_use_shared_modules; a user might have either, both, or neither.

Anatomy

Users with the permission see the Custom Adapters tab on the Shared Code page.

A custom adapter comprises two kinds of object:

  • A Custom Adapter Code — the Python source and its configuration schema. This is the reusable definition.

  • One or more Configs — concrete sets of values that satisfy a Custom Adapter Code's schema. Each config belongs to exactly one Custom Adapter Code.

The tab contains these elements:

  • Adapter Selection Pane: Select an existing custom adapter, or start a new one.

  • Adapter Name: Name the adapter. The read-only System ID hint beneath this field shows the identifier that the platform derives from the name.

  • Description: Enter an optional free-text description.

  • Adapter Code: Enter the Python source for the adapter.

  • Config Schema: Define the configuration fields and their types.

  • Save and Delete: Save or remove the Custom Adapter Code.

  • Configs table: Lists the configs defined for the adapter, their active state, and their validation status. This table appears after you save the adapter.

Custom Adapter Code

Field
Description

Name

REQUIRED | Unique display name for the adapter.

System ID

DERIVED, READ-ONLY | Identifier used to reference the adapter. See System Identifier.

Description

OPTIONAL | Free-text description.

Adapter Code

REQUIRED | Python source for the adapter. See Adapter Code.

Config Schema

REQUIRED | Field names and their types. See Config Schema.

System Identifier

The platform derives the System ID automatically from the name; you cannot edit it directly. To derive it, the platform replaces each run of non-alphanumeric characters with a single underscore, removes leading and trailing underscores, and uppercases the result.

Name
System ID

My REST API

MY_REST_API

acct-lookup (v2)

ACCT_LOOKUP_V2

The System ID must be unique across all custom adapters. If you save a name that derives to an identifier already in use, the platform rejects it with a validation error.

Config Schema

The config schema is a JSON object mapping each field name to a type. It defines which values a config for this adapter must supply.

Type
Config value
Notes

string

text

integer

whole number

float

number

boolean

true / false

array

JSON array

Enter as JSON in the config dialog.

object

JSON object

Enter as JSON in the config dialog.

encrypted_string

text

The platform encrypts this value at rest. See Encrypted Fields.

file

file upload

The platform encrypts this value at rest as a base64 string. Maximum size 1 MB. See Encrypted Fields.

Field names must be strings. The platform rejects any type outside this list when you save the adapter.

Configs

A config is a named set of values for one Custom Adapter Code. You enter a config through the config dialog. Each config has:

Field
Description

Name

REQUIRED | Name of the config.

Active

Whether the config is available for use.

Config Values

One input per schema field, typed according to the schema.

A config's values must match the adapter's schema exactly: every schema field must be present, no config can supply an unlisted field, and each value must match its field's type. You cannot save a config that does not satisfy these rules.

Encrypted Fields

The platform stores encrypted_string and file fields encrypted at rest, separately from the other config values.

In the config dialog and in API responses, the platform masks a stored encrypted value with the sentinel __ENCRYPTED__ instead of showing it. When you edit an existing config:

  • Leave the masked value in place to preserve the stored encrypted value.

  • Enter a new value to replace it.

The config dialog shows encrypted_string fields as password inputs. A file field shows an "uploaded" state with a Replace action. The platform reads each uploaded file as base64, and the file must not exceed 1 MB.

Adapter Code

The platform compiles and executes adapter code server-side. The Python editor performs syntax checking as you write the code.

Available Names

The platform injects these names into the adapter code's namespace; you do not need to import them:

Name
Description

BaseAdapter

Base class the adapter class extends.

AdapterRequest

The request object passed to execute().

AdapterResponse

The response object execute() returns.

AdapterFlowController

Flow-control helper for sequencing steps.

MessageTypes

Message-type constants used when reporting errors on a response.

base64

Python's base64 module, for decoding file fields.

The standard import statement is available for other modules (for example import requests).

Required Structure

Adapter code must define a class named exactly CustomAdapter that extends BaseAdapter:

If your code does not define a class named CustomAdapter, execution fails with the error "Custom adapter code must define a class named 'CustomAdapter'."

  • execute(self, request) is required. It receives an AdapterRequest and must return an AdapterResponse.

  • validate_config(self) is optional. The platform calls it during config validation; see Config Validation.

The Request Object

Attribute
Description

request.payload

The field mappings the integration passes to the adapter.

request.service_name

The name of the service request invoking the adapter.

Access the Configuration

Inside the adapter, self.config is a plain dictionary of the resolved config values, with any encrypted fields already decrypted. Access values by key:

file fields arrive as base64-encoded strings. Decode them with the injected base64 module:

Return a Response

Build and return an AdapterResponse. Set success and payload, and report failures with add_message_and_stack_trace(message_type, message):

If the adapter does not handle an exception raised in execute(), the platform catches it and returns a failed AdapterResponse with the message type MessageTypes.UNCATEGORIZED_ERROR.

Example: Default Template

New adapters open with the following template, which authenticates with a bearer token, posts the request payload, and maps common request failures onto message types:

The template ships with a matching schema of base_url (string), api_key (encrypted_string), and timeout (integer).

Config Validation

The Validate action on a single config, and Validate All on the adapter, instantiate the adapter with that config and call its validate_config() method:

  • A validate_config() that returns without raising marks the config as passed.

  • An exception from validate_config() marks the config as failed. View the raised message through the config's View Log action.

  • A config whose code fails to compile fails validation with "Failed to compile custom adapter code: …".

Validation runs asynchronously; each config shows one of the following states:

State
Meaning

Spinner

Validation in progress.

Green check

Passed.

Red error icon

Failed. Open View Log for the message.

Amber warning

Result unknown. The validation process did not report a result.

Not yet validated.

Custom Adapter Usage

A saved Custom Adapter Code's System ID identifies it. A config for that adapter must be active before the integration can use it. You invoke adapters from within an integration with the calladapter special function.

After the adapter is bound and active, it receives the integration's field mappings as request.payload and returns its AdapterResponse to the integration.

Limitations and Notes

  • Custom adapters provide no built-in authentication. You must implement any authentication a request requires in the adapter code, using values from the config schema. For example, store a token or password in an encrypted_string field. See How to authenticate custom adapter requests.

  • Adapter code must define a class named exactly CustomAdapter.

  • The platform derives the System ID from the name and changes it when you rename the adapter.

  • Deleting a Custom Adapter Code also deletes all of its configs. Before you delete, the interface reports the number of configs it removes.

  • Changing an adapter's config schema can invalidate existing configs. The interface warns you before you save such a change.

  • file fields have a 1 MB limit.

  • The platform stores encrypted_string and file values encrypted at rest and masks them in the interface and API.

Last updated

Was this helpful?