Connectors overview

How a workflow calls external services — the connection/instance model, the connector() step, and the mapper/combiner envelope.

A connector lets a workflow call an external service — an HTTP API, an LLM, or any MCP server. The call runs as a durable job: the step parks (WAITING_CONNECTOR_JOB), a worker executes the call, and the run resumes with the result. Because it’s journaled, a connector call is the right place to put external I/O (not a plain step handler).

The model: connection → instance → operation

  • A connection is a registered service definition (its operations and their schemas).
  • An instance is a per-workspace configuration of that connection — it holds the credentials (write-only; never returned).
  • An operation is one callable action on the connection (e.g. create_transaction).
flowctl conn list                       # connections: name, description, scope
flowctl conn ops <name>                  # operations on a connection
flowctl conn schema <name> <operation>   # ONE operation's request_schema + response_schema
flowctl instance list --connection <name>
flowctl instance create <name> --name <instance> --credentials '<json>'

The connector() step

connector(name, opts) has no positional handler — the request and response are shaped by named functions in opts.

function buildReq(ctx) { return { body: { id: ctx.vars.order_id } }; }
function readResp(ctx, response) { return { payment_id: response.body.id }; }

connector("charge", {
  connection: "payment-api",        // a registered connection
  operation: "create_transaction",
  instance: "primary",              // a per-workspace instance (credentials)
  requestMapper: buildReq,          // fn(ctx) -> request matching the op's request_schema
  responseCombiner: readResp,       // fn(ctx, response) -> variable updates
  onError: "handleError",
  next: "end",
});

The one rule: match the adapter envelope

requestMapper(ctx) must return the object described by the operation’s request_schema; responseCombiner(ctx, response) receives the object described by its response_schema. The exact shape differs per adapter:

AdapterrequestMapper returnsresponseCombiner sees
generic-http{ body } (+ optional path_params / query_params){ status_code, body, headers }
llm (OpenRouter){ model, messages: [{ role, content }], … }{ id, model, choices, usage }
composioflat action args, e.g. { recipient_email, subject, body }{ data, successful, error } — check successful
mcpthe MCP tool’s argument objectthe tool’s result payload
Mismatched shapes silently write nothing

If your mapper/combiner doesn’t match the adapter envelope, the connector “succeeds” but writes no variables — the #1 connector pitfall. When unsure, run flowctl conn schema <connection> <operation> and match it exactly.

Failure handling

A connector step takes onError (and works with retryPolicy patterns described in Errors & retries). A request that fails schema validation never creates a job and routes straight to onError; a call that returns a failure routes there too, with ctx.error populated.

Where to go next