> Source: https://wexa.ai/docs/concepts/connectors

# Connectors

A **connector** is the platform's link to an external system on a project's behalf — a search
service, a document handler, a database, a business application. It is what makes that system
reachable from inside Wexa, both to agents that want to act on it and to
[ingestion](/docs/concepts/ingestion), which brings its data into the project's stores.

The two tools on this page are turned on separately, so a deployment can have one and not the other.
The missing one is absent from the tool list rather than present and failing. If exactly one of
[`provision-connector`](/docs/tools/provision-connector) and
[`connector-read`](/docs/tools/connector-read) is missing, that is why.

## Provision is the only verb

Documentation names one verb for bringing a connector into being: you **provision** it. Not create,
not connect, not add, not install. The single name is deliberate, because the operation does more
than one thing and calling it by four names hides that.

Provisioning is idempotent. Provisioning a connector that already exists returns the existing one
and creates nothing, and the response says so. Calling it twice is safe; it is not an error and it
is not a duplicate.

## Provisioning mints skills

This is the part worth reading twice, because it is the answer to a question that usually gets asked
later and separately.

A **skill** is a capability an agent may use, and an **action** is a single operation a skill
performs. Provisioning a connector creates **one skill per action the connector supports**. That is
not a side effect you can opt out of — it is what provisioning is for, and it is the only way skills
come into a new project.

So the sequence that actually gets an agent working is:

1. Provision a connector.
2. Call [`list-skills`](/docs/tools/list-skills) to get the identifiers of the skills that now exist.
3. Reference those identifiers when you define an agent, or a
   [process flow](/docs/concepts/process-flows) that names agents.

Step 2 is not optional busywork. An agent references skills by identifier, and the identifiers are
minted at provisioning time, so they can only be read back and not predicted.

## What can be provisioned through the API

Only connectors that need no credentials. Anything requiring an API key or an OAuth authorization is
still a console step, because the credential has to be entered somewhere that is not a tool call.
Attempting to provision one of those is refused with a message listing what *can* be provisioned
without credentials, so a caller who guesses wrong is told the right answer rather than just no.

Call the tool with no category to get that list rather than memorizing it — the set moves as
connectors are added.

A couple of connectors are deliberately excluded even though they need no credentials, and the
refusal explains why in each case. One has no enabled actions, so provisioning it would leave the
project holding a connector with zero skills — a success that leaves the caller no better off.
Another declares a
credential it gives no way to supply, so provisioning it could mint skills that all fail at run
time, which is worse than not having them.

## Reading through a connector without ingesting

[`connector-read`](/docs/tools/connector-read) runs a governed, **read-only** query against the
source system, live. Nothing is copied into Wexa. That makes it the right tool for large
warehouse and database sources, where ingesting the rows would mean maintaining a stale copy of
something that already exists.

It works two ways. If the connector has a synced read action, name that action and pass its
parameters. If it does not — which is typical of a database source — pass the connector's identifier
along with a read-only `SELECT`, a table name, or a read-only aggregation, depending on the kind of
source.

Three things constrain it, and each of them prevents a specific mistake:

- **Writes are rejected.** Write and modify actions are blocked rather than attempted, and the
  block fails closed: an action whose read-only status is not established is refused, not allowed.
- **It is for rows, not for structure.** To find out which tables exist and what fields they have,
  read the catalog's assets out of the context graph with
  [`query-context`](/docs/tools/query-context) instead. That is a local traversal rather than a
  round trip to the source, and it is how you find the connector identifier in the first place.
- **Not every asset is live-readable.** Assets that arrived as crawled metadata carry no connector
  identifier and cannot be read live. Filter on the live-readable flag before you try, or the call
  will tell you the connector identifier is invalid, which is a confusing way to learn it.

A read that policy declines comes back as an explicit governance refusal rather than as an empty
result, so a blocked read is never mistaken for a source with no rows. See
[policy and approvals](/docs/concepts/policy-and-approvals).

## What a connector is not

**It is not a repository connection.** A project's link to a source-code repository is a separate
concept with its own path: it is established by the code-sync client rather than provisioned, it
mints no skills, and what it produces is the code graph rather than a set of actions an agent can
call. See [code sync](/docs/concepts/code-sync).

**It is not an MCP connection.** A link Wexa holds to a third-party MCP server, chosen from a
marketplace so that its tools become available inside Wexa, is a different mechanism from a
connector. Neither is the Wexa MCP server, which is one of the four surfaces Wexa itself is
exposed over.

**It is not, by itself, data in your project.** Provisioning makes a source reachable. Bringing its
contents into the [context graph](/docs/concepts/context-graph) and the
[data catalog](/docs/concepts/data-catalog) is [ingestion](/docs/concepts/ingestion), and it is a
separate thing that happens afterwards.
