Connectors & capabilities
A connector is how Fibric reaches a real system: software like a help desk or an order book, or hardware like locks, sensors, and HVAC. A capability is a named thing a connector can do, expressed by intent rather than by vendor. Operators request capabilities; configuration binds each one to a connector. That single layer of indirection is why swapping a vendor is a config change, not a rewrite.
The capability model
Fibric draws a hard line between what you want done and which system does it. The what is a capability: a stable, intent-named verb like orders.read, orders.hold, access.unlock, or hvac.setpoint. The which is a connector: the concrete adapter that knows how to talk to Magento, or a Kustomer help desk, or a specific lock controller on a floor.
Operators only ever speak in capabilities. A ship-risk operator asks for orders.hold; it has no idea whether the order system behind that is Magento or NetSuite or something you wrote yesterday. That ignorance is deliberate, and it is the source of almost everything good about the model.
Good: orders.hold, access.unlock, hvac.setpoint. Avoid: magento.cancel, kustomer.note. The moment a vendor's name leaks into a capability, you have bound an operator to a vendor and lost the swap.
Capability over connector indirection
Between the operator and the real system sits one layer of indirection. The operator names a capability; configuration resolves that capability to a connector; the connector reaches the system. Four boxes, one arrow each.
The binding in the middle is configuration. The operator on the left and the system on the right never touch directly. Change the connector and the operator does not notice; change the operator and the connector does not notice. The capability is the only thing both sides agree on, and it is just a name and a shape.
# which connector backs each capability, for this tenant
bindings:
orders.read: magento
orders.hold: magento
notify.send: connect
access.unlock: lock-controller-a
hvac.setpoint: bms-gateway
Every connector is MCP
Connectors are not a bespoke plugin format. Every connector is built on MCP, the Model Context Protocol, so a SaaS API, a piece of hardware, and even an operator all present the same interface to the kernel. The kernel does not know or care whether access.unlock ends at an HTTP endpoint or a relay on a wall. It speaks one protocol to all of them.
This is what makes Fibric vertical-agnostic in practice and not just in slogan. The kernel hardcodes no integration. Operators and connectors are the integrations, and because they all speak MCP, adding a new system is adding a connector, never patching the kernel.
Because every connector is MCP, a help desk and a door lock are the same kind of thing to the executor. An ExecutionPlan that sends a message and unlocks a door is one plan, disposed the same way, with one receipt per action.
Provides and requires: the contract
Two declarations make the whole system check out before anything runs. A connector provides capabilities. An operator requires capabilities. The kernel matches them at install time, so a missing or mistyped binding is caught up front, not in production.
Connector provides
A connector declares the capabilities it can serve and the shape of each one's arguments. The magento connector provides orders.read and orders.hold. If a capability is not in the provides list, this connector cannot back it.
Operator requires
An operator declares the capabilities it needs to read and to act. The ship-risk operator requires orders.read, orders.hold, and notify.send. It can never reach a capability outside this set, even if the model proposes one.
export default defineConnector({
name: "magento",
auth: { kind: "apiKey", secret: "MAGENTO_KEY" },
// the capabilities this connector PROVIDES
provides: {
"orders.read": tool({
input: z.object({ status: z.string().optional() }),
async run({ input, client }) {
return client.get("/orders", { status: input.status });
},
}),
"orders.hold": tool({
input: z.object({ order: z.string(), reason: z.string() }),
async run({ input, client }) {
return client.post(`/orders/${input.order}/hold`, input);
},
}),
},
});
Swap is config
Here is the payoff. Because operators speak capabilities and connectors provide them, replacing one vendor with another is a binding change. Nothing in the operator moves. Below, a help-desk capability moves from one connector to another, and every operator that uses it keeps running, untouched.
tickets.note → kustomer
The capability was backed by the Kustomer connector. Operators called tickets.note.
tickets.note → zendesk
One binding changes. The capability is now backed by the Zendesk connector. Operators unchanged.
# swap the help desk behind tickets.* from Kustomer to Zendesk
fibric capabilities bind tickets.read --connector zendesk
fibric capabilities bind tickets.note --connector zendesk
# no operator edits. no redeploy of the reasoning.
# the capability is the contract; the connector behind it is config.
This is the fourth tenet of the platform stated as a daily fact: capability to connector indirection means swapping a help desk from Kustomer to Zendesk is configuration. The operator that proposes tickets.note never knew the vendor's name, so there is nothing in it to change.
Building a connector
Building a connector is declaring what it provides and how each capability runs. The flow is short.
1. Name it and authenticate
Give the connector a stable name and declare its auth. Secrets resolve from the tenant's vault, never from source, so a connector definition is safe to commit.
2. Declare what it provides
For each capability, give a typed input schema and a run. The schema is enforced before run is ever called, so a malformed argument is rejected at the boundary, not deep inside a vendor API.
3. Let the kernel govern it
You do not write retries, single-flight, idempotency, or receipts into a connector. Those are kernel primitives that wrap every capability call. Your connector's job is to talk to one system correctly; the kernel makes that call safe.
An operator cannot call a connector directly, and neither can the model. Capability calls flow through the executor, which checks them against your trust policy first. A connector that provides access.unlock still only fires when policy allows it.
Keep going
- Connector SDK, the full surface for
defineConnector,tool, and auth. - Operators, how an operator's
requiresmeet a connector'sprovides. - Governance & trust, why every capability call is vetted before it reaches a connector.
- Core concepts, the nine ideas behind the whole kernel.