Creating Connectors¶
This guide covers how to create connectors for each execution model. For architecture details, see Connector Architecture.
Quick Start¶
The fastest way to create a connector:
- Navigate to Connectors in the sidebar
- Click New Connector
- Choose an execution model
- Fill in details and create
Execution Model Selection¶
| Model | When to Use | Complexity |
|---|---|---|
| Built-in | New instance of an existing registered type (e.g. a second Authifi tenant) | Low |
| Script | Custom integrations, user-authored logic | Medium |
| OAS-Derived | APIs with OpenAPI 3.x specs | Low |
| External | Remote services, separate processes | Low-Medium |
Note: Creating a new built-in connector type (i.e. writing the handler code) requires a server deployment. Creating a new instance of an existing built-in type is a low-complexity UI operation — see below.
Creating Built-in Connector Instances¶
Use this when you need another instance of a connector type that already exists in the registry (e.g. connecting a second Authifi tenant, or a separate LDAP directory).
Via the UI¶
- Navigate to Connectors and click New Connector
- Select Built-in as the execution model and click Next
- Choose the connector type from the dropdown (e.g.
authifi,http) - Enter a unique Name (e.g.
authifi-prod), a Description, and optionally a Category - If the type has connection config fields (API keys, URLs, etc.), fill them in — or leave them for later
- Click Next to review, then Create Connector
Via the API¶
POST /api/connectors
Content-Type: application/json
{
"name": "authifi-prod",
"type": "authifi",
"description": "Authifi connector for the production tenant",
"version": "1.0.0",
"executionModel": "built_in",
"configSchema": { ... },
"config": {
"baseUrl": "https://auth.example.com/_api",
"tenant": "prod",
"tenantId": "42",
"clientId": "my-client-id",
"clientSecret": "my-secret"
}
}
The type must match a registered built-in handler name. The config field contains connection secrets that are encrypted at rest. You can omit config and set it later via PUT /api/connectors/:id.
Creating Script Connectors¶
Script connectors run custom JavaScript in a sandboxed QuickJS environment.
Step 1: Define the connector¶
POST /api/connectors
Content-Type: application/json
{
"name": "my-crm",
"type": "my-crm",
"description": "Integration with My CRM",
"version": "1.0.0",
"executionModel": "script",
"category": "crm",
"tags": ["sales", "contacts"],
"configSchema": {
"connectionConfig": {
"baseUrl": { "type": "string", "required": true, "description": "CRM API base URL" },
"apiKey": { "type": "string", "required": true, "secret": true, "description": "API key" }
},
"commands": {
"listContacts": {
"params": ["limit", "offset"],
"description": "List contacts from the CRM",
"outputs": ["contacts", "total"],
"paramSchema": {
"limit": { "type": "number", "default": 50 },
"offset": { "type": "number", "default": 0 }
}
},
"createContact": {
"params": ["email", "firstName", "lastName"],
"description": "Create a new contact",
"outputs": ["contactId"]
},
"test": {
"params": [],
"description": "Test connectivity",
"outputs": []
}
}
},
"scriptSource": "... (see below)"
}
Step 2: Write the script¶
function listContacts() {
var url = floh.config.baseUrl + '/api/contacts';
url += '?limit=' + (floh.params.limit || 50);
url += '&offset=' + (floh.params.offset || 0);
var resp = floh.http.get(url, {
'Authorization': 'Bearer ' + floh.config.apiKey
});
if (resp.status >= 400) {
return { success: false, error: 'API returned ' + resp.status };
}
return {
success: true,
data: { contacts: resp.body.data, total: resp.body.total }
};
}
function createContact() {
var resp = floh.http.post(
floh.config.baseUrl + '/api/contacts',
JSON.stringify({
email: floh.params.email,
first_name: floh.params.firstName,
last_name: floh.params.lastName
}),
{ 'Authorization': 'Bearer ' + floh.config.apiKey }
);
if (resp.status >= 400) {
return { success: false, error: 'Failed to create contact: ' + resp.status };
}
return { success: true, data: { contactId: resp.body.id } };
}
function test() {
var resp = floh.http.get(floh.config.baseUrl + '/api/health', {
'Authorization': 'Bearer ' + floh.config.apiKey
});
return { success: resp.status < 400 };
}
Step 3: Test the connector¶
Script API Reference (floh.*)¶
All script connectors have access to the floh global object:
floh.http¶
| Method | Signature | Description |
|---|---|---|
get |
floh.http.get(url, headers?) |
HTTP GET request |
post |
floh.http.post(url, body?, headers?) |
HTTP POST request |
put |
floh.http.put(url, body?, headers?) |
HTTP PUT request |
patch |
floh.http.patch(url, body?, headers?) |
HTTP PATCH request |
delete |
floh.http.delete(url, headers?) |
HTTP DELETE request |
Response format:
{
status: 200, // HTTP status code
body: { ... }, // Parsed JSON body
headers: { ... } // Response headers
}
All HTTP calls are proxied through the main thread. The sandbox has no direct network access.
floh.log¶
| Method | Description |
|---|---|
floh.log.trace(message) |
Trace-level log |
floh.log.debug(message) |
Debug-level log |
floh.log.info(message) |
Info-level log |
floh.log.warn(message) |
Warning-level log |
floh.log.error(message) |
Error-level log |
Logs are routed through the connector's ConnectorLogger and respect the configured logLevel.
floh.config¶
The connector's decrypted connection configuration. Contains the fields defined in connectionConfig:
floh.config.baseUrl // "https://api.example.com"
floh.config.apiKey // "sk-abc123..." (decrypted at runtime)
floh.params¶
The step parameters passed from the workflow. Contains the fields specified in the step's config:
floh.variables¶
The workflow run's current variable state:
Return Format¶
Every command function must return a ConnectorResult:
// Success
return {
success: true,
data: { contacts: [...], total: 42 },
outputVariables: { contactCount: 42 }
};
// Error
return {
success: false,
error: "Connection refused"
};
Creating OAS-Derived Connectors¶
Via the UI¶
- Navigate to Connectors → Import from OpenAPI
- Paste the OpenAPI 3.x JSON spec
- Click Parse Spec to preview generated commands
- Select/deselect commands to include
- Review the generated script and connection config
- Click Create Connector
Via the API¶
POST /api/connectors/parse-oas
Content-Type: application/json
{
"spec": {
"openapi": "3.0.3",
"info": { "title": "My API", "version": "1.0.0" },
"paths": { ... },
"components": {
"securitySchemes": {
"bearerAuth": { "type": "http", "scheme": "bearer" }
}
}
}
}
The response contains a draft connector definition ready to be sent to POST /api/connectors.
Supported Security Schemes¶
| OAS Scheme | Generated Config Fields |
|---|---|
apiKey |
Named field with secret: true |
http/bearer |
bearerToken |
http/basic |
username, password |
oauth2 |
clientId, clientSecret, tokenUrl |
Creating External Connectors¶
External connectors communicate with Floh via a standardized HTTP protocol.
Protocol Endpoints¶
Your service must implement:
| Endpoint | Method | Description |
|---|---|---|
/execute |
POST | Execute a connector command |
/schema |
GET | Return the connector's schema (optional) |
/health |
GET | Return health status (optional) |
Execute Request¶
{
"command": "listUsers",
"config": { "apiKey": "..." },
"params": { "limit": 50 },
"variables": { "project_id": "proj-1" },
"metadata": {
"stepId": "step-1",
"runId": "run-123",
"timeout": 30000
}
}
Execute Response¶
Registration¶
POST /api/connectors
Content-Type: application/json
{
"name": "my-external-service",
"type": "my-external-service",
"executionModel": "external",
"endpointUrl": "https://connector.example.com",
"version": "1.0.0",
"configSchema": { ... }
}
On-Premise Agent¶
For connectors that need to reach services inside a private network, use the on-premise agent. The agent establishes an outbound WebSocket connection to Floh, so no inbound ports need to be opened.
Agent Registration¶
WebSocket: wss://floh.example.com/api/connectors/agents/ws
Registration message:
{
"agentId": "agent-prod-01",
"agentName": "Production Agent",
"connectorNames": ["internal-ldap", "sap-hr"],
"apiToken": "..."
}
Command Flow¶
Floh Server ──WebSocket──▶ Agent ──HTTP──▶ Internal Service
│
Agent ◀──HTTP──────────────────────────────────┘
│
Floh Server ◀──WebSocket──┘
The agent receives AgentCommand messages, executes them against internal services, and returns AgentResponse messages.
AI-Assisted Building¶
The Floh MCP server provides tools for AI-assisted connector development:
| MCP Tool | Description |
|---|---|
generate_connector_script |
Generate a JavaScript script from a description |
parse_openapi_spec |
Parse an OAS spec into a connector definition |
create_connector |
Create a connector via the API |
update_connector_script |
Update a connector's script |
test_connector |
Test a connector's connectivity |
execute_connector_command |
Execute a specific command |
Example AI Workflow¶
- Ask the AI: "Create a connector for the Acme CRM API"
- Provide the OpenAPI spec or describe the API endpoints
- The AI uses
parse_openapi_specorgenerate_connector_script - Review and refine the generated connector
- The AI uses
create_connectorandtest_connectorto deploy and verify