Capabilities
A capability is a named thing a connector can do, stated as intent rather than vendor: conversations.note, orders.hold, calls.status-sync. Operators request capabilities; connectors provide them; configuration binds the two. This indirection is why replacing one vendor with another is a configuration change, not a rewrite.
The indirection
An operator never names a vendor. It declares the capabilities it needs, grouped by family: ticketing capabilities like conversations.read and conversations.note, order-management capabilities like orders.read and orders.hold, telephony capabilities like calls.events. Which concrete system answers each request is decided by configuration, per tenant.
Requests capabilities by intent: orders.read, conversations.note. Never learns the vendor’s name.
Configuration maps each capability, or a whole role such as support, to one installed connector.
Provides the capability against a real system: Kustomer, Magento, Amazon Connect, or a hardware gateway.
The live catalog states this contract directly. The Order Risk operator’s requirements are written as roles, not products: a commerce connector (Magento or Shopify) for order state, a support connector (Kustomer or Zendesk) for conversation context, and a shipping source for scan events. The operator’s reasoning, its trust policy, and its receipts are identical whichever vendor fills each role. Swapping Kustomer for Zendesk changes one binding and nothing else.
How a connector declares capability
Connectors are written with the Connector SDK. A ConnectorDef declares its identity, its auth scheme, a record of tools (the capabilities it provides), and optionally the events it emits. The shapes below are the current source from packages/connector-sdk/src/index.ts.
export interface ToolDef {
input?: (args: unknown) => Record<string, unknown>;
sideEffecting?: boolean; // true → routes through the deterministic executor + TrustPolicy
handler: (ctx: ConnectorCtx, args: Record<string, unknown>) => Promise<unknown> | unknown;
}
export type ConnectorCategory =
| 'crm' | 'commerce' | 'voice' | 'shipping'
| 'comms' | 'data' | 'hardware' | 'ai-operator';
export interface ConnectorDef {
id: string;
version: string;
category: ConnectorCategory;
publisher?: 'first-party' | 'partner' | 'private';
auth: AuthSchema;
tools: Record<string, ToolDef>;
events?: Record<string, { kind: 'webhook' | 'poll'; topic?: string }>;
probe?: (ctx: ConnectorCtx) => { status: string; metric?: { label: string; value: unknown } };
}
Two details in ToolDef carry the governance model. A tool with sideEffecting: true can never be invoked directly: it routes through the deterministic executor, where the tenant’s TrustPolicy decides it fail-closed and single-flight and idempotency apply. A read tool runs immediately. Events declared under events arrive as event envelopes, by webhook or poll.
A realistic excerpt for a Kustomer connector, declaring one read capability and one side-effecting capability:
import { defineConnector, tool, apiKey } from "@fibric/connector-sdk";
export default defineConnector({
id: "kustomer",
version: "1.4.0",
category: "comms",
publisher: "first-party",
auth: apiKey(),
tools: {
"conversations.read": tool({
async handler(ctx, args) {
// read-only: runs immediately, no policy gate
return fetchConversations(ctx, args);
},
}),
"conversations.note": tool({
sideEffecting: true, // executor + TrustPolicy + idempotency
async handler(ctx, args) {
return writeNote(ctx, args);
},
}),
},
events: {
"conversation.message.created": { kind: "webhook" },
},
});
The SDK has one shape for SaaS, hardware, and operators; an operator is a connector with category ai-operator. The kernel hardcodes none of them, which is why the same capability machinery governs a help desk, a building gateway, and an AI worker.
Binding capabilities to connectors
Installing a connector under a role binds every capability it provides to that role. You can also bind a single capability explicitly. Both operations are configuration; no operator code changes.
# install the Kustomer connector as the tenant's support system
fibric connectors add kustomer --as support
# bind one capability explicitly (overrides the role default)
fibric capabilities bind conversations.assign --connector kustomer
# see every capability and what currently provides it
fibric capabilities ls
An operator’s requires list is checked against this table at deploy time. If a required capability has no binding, the operator does not start; there is no partial mode where a missing capability silently no-ops.
Capabilities in the live catalog
Five marketplace listings run in production today: two operators (Order Risk, Operations Analyst) and three connectors (Kustomer, Magento, Amazon Connect). The table maps their published senses and acts onto the capability vocabulary. Everything else in the marketplace is early access, including the Zendesk, Shopify, and ShipStation listings that fill the same roles.
| Capability | Kind | Provided by | Notes |
|---|---|---|---|
conversations.read |
sense | Kustomer (cn-kustomer) |
Conversations and messages, customer records, SLA state, satisfaction, reopens. |
conversations.note |
act | Kustomer (cn-kustomer) |
Writes notes idempotently; side-effecting, so it passes the executor and trust policy. |
conversations.assign |
act | Kustomer (cn-kustomer) |
Updates conversation status and assignment. |
orders.read |
sense | Magento (cn-magento) |
Orders, line items, status changes, proof approvals and revisions, invoices and shipments. Requires Magento 2.4+ REST. |
orders.comment |
act | Magento (cn-magento) |
Adds order comments idempotently. |
orders.status |
act | Magento (cn-magento) |
Updates order status within allowed transitions only. |
calls.events |
sense | Amazon Connect (cn-amazon-connect) |
Contact events stream and contact trace records. |
calls.recordings |
sense | Amazon Connect (cn-amazon-connect) |
Call recordings landing in the instance’s S3 bucket. Auth is a cross-account IAM role; no long-lived keys leave the account. |
calls.status-sync |
act | Amazon Connect (cn-amazon-connect) |
Syncs call status onto the customer record idempotently; updates contact attributes within limits. |
orders.hold |
act | Consumed by Order Risk (op-order-sentinel) |
Places or releases an order hold with the reason on the record, through whichever commerce connector fills the role. |
notify.send |
act | Consumed by Order Risk (op-order-sentinel) |
Notifies the account owner with the order, the signal, and the recommended fix. |
metrics.read |
sense | Consumed by Operations Analyst (op-radar-analyst) |
Governed metrics: one canonical definition per number, tagged with its source, answered with provenance. |
The operator rows are consumption, not provision: Order Risk and Operations Analyst require these capabilities and use whatever binding the tenant has configured. Order Risk additionally requires a shipping source for scan events; the shipping connectors in the marketplace are early access.
Swap walkthrough: Kustomer to Zendesk
Suppose a tenant running Order Risk against Kustomer moves its help desk to Zendesk. Zendesk is an early-access listing, so the connector is provisioned through the early-access program; once installed, the swap is one rebinding of the support role.
# install the new connector under the same role
fibric connectors add zendesk --as support
# confirm the rebinding
fibric capabilities ls
What did not change: the Order Risk operator itself, its goal, its requires list, the tenant’s trust policy, and the shape of its receipts. The operator asked for conversations.read before the swap and asks for it after. Policy rules written against the capability name, such as a rule gating conversations.note, keep applying because they never mentioned a vendor either.
A TrustPolicy can match on connector, tool, or both. Rules scoped to the capability survive a vendor swap unchanged; rules scoped to a connector id must be reviewed when the binding moves. Prefer the capability unless the rule is genuinely about one vendor.
Related pages
- Connectors: what a connector is and how it reaches software and hardware.
- Connector SDK and defineConnector(): writing a connector that provides capabilities.
- Operators: how an operator’s
requireslist consumes capabilities. - Governance & trust: how side-effecting capabilities are gated fail-closed.