Connectors
How Ductor reaches the outside world — providers, actions, triggers, and connections — the governed action inventory the execute stage draws on.
A connector is how a Ductor workflow step, routing hook, or API call reaches
a third-party system — and its actions are the governed units of work the
executed stage of the clearing lifecycle draws on. Ductor ships a catalog of
hundreds of providers — spanning CRM, e-commerce, payments, communications,
LMS, and dozens more categories — each action carrying machine-readable
semantics (mutation class, idempotency, retry, approval) and a parity tier that
records how completely it is implemented. The same machinery lets you add your
own without touching the core engine. Browse the live directory at
ductor.io/connectors; provider icons are served at
https://cdn.ductor.io/providers/<key>.svg.
Where the commercial layer stands
Because every action already carries typed semantics and per-execution usage
metering, the catalog is the foundation for a priced action inventory. Two
of its axes now ship as opt-in surfaces: the
pricing engine resolves an action's price
before it executes (connector_pricing.enabled), and the
assurance axis resolves a certified-or-community
tier and projects it onto catalog reads (connector_assurance.enabled). Both
are off by default.
An agent worker's capped connector-action spend now settles: max_cost_cents
is enforced against the resolved price before provider I/O, and a durable,
default-off projector posts that spend to the balanced settlement journal as
showback (the tenant's wallet is debited, the platform credited). What is
roadmap: paying a seller — an action price carries no
payee, so a settled purchase credits the platform, never a marketplace
publisher — and settling governed-skill spend, which is capped but writes no
durable record to settle from.
This section is the deep reference for that machinery: the registries that describe providers, how a connection is authenticated and its credentials encrypted, how triggers deliver inbound events, and how you author a provider of your own. If you only want the one-paragraph mental model, the Connectors concept page has it; this page starts the long-form tour.
The vocabulary
Four nouns show up constantly, and they are not the same thing. Getting them straight is most of the battle.
| Term | What it is | Where it lives |
|---|---|---|
| Provider | A third-party system Ductor knows how to talk to (hubspot, salesforce, slack). A provider definition declares its display name, categories, supported auth types, and the keys of the actions and triggers it exposes. Providers are Go code — there is no runtime loader. | domain/connector/provider.go (Provider struct) |
| Action | One operation in a provider's catalog (hubspot.create_contact). An immutable ActionSpec carries input and output schemas, access requirements, execution semantics, related operations, and an explicit runtime status. Executable actions bind a runtime function; catalog-only actions remain discoverable without pretending they can run. | domain/connector/action.go (ActionSpec) |
| Trigger | An event source a provider exposes (hubspot.contact_created). Delivered by webhook or by polling. | domain/connector/trigger.go (TriggerSpec) |
| Connection | One tenant's authenticated instance of a provider — the HubSpot account this customer linked, with its own encrypted credentials, config, and status. This is the thing a step actually dispatches against. | domain/connector/connection.go (Connection) |
Provider vs. provider config vs. connection
There is a fourth layer between provider and connection: a provider config
(ProviderConfigKey + EnvironmentID) is your configured instance of a provider family — your
OAuth client credentials, allowed scopes, and egress policy for, say, HubSpot in prod. A
connection then belongs to a provider config and represents one end-customer's linked account
under it. So the chain is: provider family (hubspot) → provider config (hubspot-main
in prod) → connection (Acme's HubSpot portal).
The mental model
A provider is a catalog entry plus code. It says "here is HubSpot, here are
the 40 actions and 12 triggers it supports, here is how you authenticate to it."
It carries no tenant data and no secrets — a provider's BaseURL is an authoring
template that "must not contain tokens, headers, or tenant secrets."
A connection is where the tenant data lives. When Acme links their HubSpot
account, Ductor stores a Connection row: which provider, which tenant, the
encrypted credentials, non-secret config like the region, and a status. Nothing
in that row is plaintext-sensitive — credentials are AEAD ciphertext, decrypted
only in-process at dispatch time.
At dispatch, a caller names a (providerKey, actionKey) and a connection. Ductor
looks up the ActionSpec, resolves the connection into a short-lived, decrypted
AuthContext, runs the action's Execute function against the provider, and
records the outcome as a durable attempt.
Catalog breadth and runtime availability are separate
Some actions are imported as schema-rich catalog contracts before a safe provider runtime exists.
Their runtime_status is metadata_only or needs_runtime, with a stable runtime_reason. They
are available to search, inspect, and plan against, but execution remains blocked until a native
runtime is registered. The catalog UI labels these actions Catalog only.
Where connectors sit
Connectors are an egress layer. They are invoked from three surfaces, all of which converge on the same central action executor:
- Workflow steps — an
actionstep (or anai_action/ai_agentstep) names a connector action. This is the common case; the Coordinator dispatches it to a Step Worker, which executes it and records aneec_workflow_step_attempt(theeec_prefix marks Ductor's durable Enterprise Eventing Core tables). - The management API —
POST /api/v2/connector/execute-actionruns an action synchronously, andPOST /api/v2/connector/action-jobsenqueues a durable async job. Both are covered under Connections. - Routing hooks — a routing decision can dispatch a connector action as a side effect of finalization.
A connector call is a durable attempt, not a fire-and-forget SDK call
Because dispatch runs through the durable attempt model, a connector action inherits retries, at-least-once delivery, and uniform observability for free. It also means an action can run more than once across a crash, so actions that mutate downstream state should carry an idempotency key — see Architecture and Idempotency & Exactly-Once.
What's in this section
Architecture
The ProviderRegistry, ActionRegistry, and ConnectionService; how an action is dispatched; the durable attempt and async job models; action semantics.
Authentication
Every auth type, how AuthContext is resolved at dispatch, and how credentials are AEAD-encrypted at rest with XChaCha20-Poly1305, BYOK, and key rotation.
Connections
Creating and resolving connections, direct vs. route mode, and the management API with real request/response payloads.
Credential Lifecycle
Credential health facts, the requirement scanner, hosted Connect-Link authorization requests, and auto-resume on reconnect.
Triggers & Polling
Source components, provider webhook subscriptions, the provider-event envelope, the three trigger modes, signature verification, and coalescing.
The Sync Engine
Cached provider-record replication — sync variants, the scheduler, run leases, retention, and realtime sync channels.
Data Mapping
Mappers that normalize provider payloads, field catalogs and mapping profiles, and the governed connector function runtime.
The Catalog
The ~864-provider inventory, generated parity matrix, categories, release stages, the colocated provider layout, and the code generators.
Building a Provider
Author a provider with ProviderSpec and RegisterFromSpec, write an action's Execute function, and declare input/output schemas.
Assisted Authoring
Draft, compile, dry-run, repair, and stage connector functions without bypassing governance.
Certification & Testing
The certification workbench, synthetic canaries, provider API drift intelligence, and the simulator/fixture dev tooling.
Marketplace & Deployments
Immutable, promotable integration deployments and the extension marketplace gateway with destructive-change guardrails.
External MCP Providers
Import a remote MCP server's tools as governed connector actions, with every call re-gated through the normal executor.
Outbound Integrations
Ductor as the event source — the iPaaS webhook adapter and the n8n community node for Zapier/n8n/custom consumers.
Policies, Quotas & Audit
Egress/placement policy, tenant provider policy, quota facts, execution admission, connection selection, GCRA rate limiting, and the audit hash chain.
Writing a Certified Strategy
Implement the Strategy interface, register it with the registry, add tunable params and capabilities, and declare a contract for certification.
Connector Architecture
The registries, the ConnectionService, action dispatch, action semantics, and the durable attempt and async-job execution models.