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

Custom Integrations

Custom integrations are only available for enterprise clients at this time. Please reach out to sales@edisonscientific.com for commercial inquiries.

Overview

An integration gives an agent authenticated access to an external API — the mechanism behind the built-in Notion, Slack, Teams, Google Drive, and GitHub connections. This page covers registering your own API as a first-class integration, using that same interface.

The agent never accesses your credential. Keys are stored in a secret manager, and the sandbox's egress proxy injects them into outbound requests in transit. The key is not in the agent's environment at all — so it cannot be exfiltrated by a prompt injection or leaked in a transcript.

How it works

your agent ──HTTP──► network sidecar ──► your API

                          └── looks up the provider by domain,
                              injects the credential from Secret Manager
  1. A provider entry in the integrations catalog declares the API: its domains, how the credential is presented, and a URL to validate a key against.

  2. That entry drives the sandbox proxy's TLS-intercept domain list and its credential-injection rules.

  3. A connection attaches an actual credential at user or organization scope.

  4. At request time, resolution prefers the calling user's own credential and falls back to the organization's.

1. Register the provider

from edison_client import EdisonClient

client = EdisonClient()

glyph = client.create_custom_integration(
    CustomIntegrationSpec(
        name="Glyph Structure Recognition",
        domains=["glyph.ml.internal.example.com"],
        auth_method=IntegrationAuthMethod.BEARER,
        auth_flow=IntegrationAuthFlow.STATIC_KEY,
        header_name="Authorization",
        validation_url="https://glyph.ml.internal.example.com/v1/models",
        instructions=(
            "Paste a Glyph API token from the ML platform console. "
            "Read scope on /v1/ocsr and /v1/markush is sufficient."
        ),
        image="https://cdn.example.com/glyph-logo.png",
    ),
    organization_id=42,  # omit to publish tenant-wide
)
glyph.id  # UUID used by every call below

Registering creates the catalog entry only — no credential is stored yet.

CustomIntegrationSpec

Field
Type
Required
Meaning

name

str

yes

Display name. Unique across the catalog.

domains

list[str]

yes

Hosts the proxy intercepts and injects credentials for. Bare hostnames — no scheme, no path.

auth_method

IntegrationAuthMethod

yes

How the credential is presented (below)

auth_flow

IntegrationAuthFlow

no (static_key)

How the credential is obtained

header_name

str

no (Authorization)

Header the credential is injected into; for query_param, the parameter name

instructions

str

yes

Shown in the connect dialog: where a user gets a key

image

str

yes

Logo URL for the UI tile

validation_url

str | None

no

Cheap authenticated GET used to prove a stored key works

oauth_authorization_url

str | None

OAuth only

Authorization endpoint

oauth_token_url

str | None

OAuth only

Token endpoint

oauth_scopes

list[str] | None

OAuth only

Requested scopes

IntegrationAuthMethod — how the credential rides on the request:

Value
Result

bearer

Authorization: Bearer <key>

header

<header_name>: <key>

query_param

?<param_name>=<key>

query_param is declarable but not yet injectable. The credential lookup path raises NotImplementedError for it. Use bearer or header until that lands.

IntegrationAuthFlow:

Value
Meaning

static_key

A long-lived key pasted by a user or admin

oauth2

Authorize → callback → refresh loop

2. Attach a credential

Organization scope — admin only, and by default all member's agents inherit it:

User scope — personal, and takes priority over the org credential for that user's agents:

Parameter
Type
Meaning

provider_catalog_id

UUID

Provider to connect

api_key

str

Your key for that API

organization_id

int | None

None → user scope; set → org scope (admin)

expires_at

datetime | None

Optional expiry, surfaced in the UI before it bites

The key goes straight to the secret manager; only a secret reference is written to the backend.

3. Validate before anyone depends on it

Re-probes the stored credential against validation_url. Runs automatically on connect, and on demand thereafter — the cheapest way to distinguish "the integration is broken" from "the agent did something wrong".

4. Use it

Nothing further is required of the agent or of you. The agent calls the API normally, with no credential anywhere in its code:

In practice you would pair the integration with a skill — a markdown guide telling the agent which endpoints exist, how to choose between them, and how to report results.

To guarantee an agent always has that guidance rather than discovering it, name the skill in a profile's auto_skills and deploy that profile as your own job:

The integration handles access; the skill handles judgment; the profile guarantees the skill is loaded. See configuration.md.

5. Rotate and offboard

Rotation can be achieved by overwriting, and offboarding via a revoke method.

revoke_integration disconnects the provider and deletes the stored credential.

Listing what is available

IntegrationProvider

Field
Type
Meaning

id

UUID

Catalog ID used by connect / validate / revoke

name

str

Display name

domains

list[str]

Intercepted hosts

auth_flow

IntegrationAuthFlow

static_key or oauth2

connected

bool

Whether a usable credential is attached for the caller

org_managed

bool

Credential comes from the organization, not the user

last_validated

datetime | None

Last successful validation

last_used

datetime | None

Last agent request that used it

expires_at

datetime | None

Credential expiry, if declared

IntegrationConnection

Field
Type

provider

str

provider_catalog_id

UUID

scope

IntegrationScopeuser or organization

connected

bool

IntegrationValidation

Field
Type

provider

str

valid

bool

error

str | None

Constraints worth knowing up front

  • Provider name is globally unique in the catalog.

  • A new domain becomes interceptable only after the sandbox proxy configuration regenerates. This happens on an infrastructure level within minutes but is not instant.

  • query_param credentials are not injectable yet (see above).

  • User credentials override org credentials.

  • Providers can be mutually exclusive. The catalog supports a mutex group, so at most one provider in a group may be connected per user — relevant if you register several entries for the same underlying service.

Last updated