# Connector

A Connector carries messages between one outside channel (a chat platform, a live room) and Cowork's Gateway. Register it with `api.registerConnector(definition)`.

## ConnectorDefinition

| Field | Type | Required | Description |
|---|---|---|---|
| `id` | `string` | Yes in 0.1.41; No <Badge type="warning" text="Not yet released" /> | Lowercase letters, digits and hyphens. When `dozin.connectors` lists ids, it must be one of them; without that list any valid id works, up to 16 Connectors. In 0.1.41 it is required and must be listed. From the next version it defaults to the package name |
| `systemPrompt` <Badge type="warning" text="Not yet released" /> | `string` | No | Rules every chat of this Connector follows, at most 4000 characters; the person cannot edit them |
| `chat` <Badge type="warning" text="Not yet released" /> | `{ title, roles?, maxLength?, maxPerMinute? }` | No | Messages go into one chat that replies with `gateway_send`. `title` 1–80 characters; `roles` up to 16 entries, id lowercase (`host`, `viewer`, `self`) → label of 1–24 characters; `maxLength` 1–4000 (default 500); `maxPerMinute` 1–30 (default 6). An invalid `chat` is refused whole |
| `start(ctx)` | function | Yes | See below |
| `stop()` | function | Yes | See below |
| `send(reply)` | function | Yes | See below |

## start(ctx)

Called when the Connector starts. Open connections, timers and page observers here.

| Name | Type | Description |
|---|---|---|
| `ctx` | `ConnectorContext` | `emit`, `log`, and `browser` with that capability |

Returns `void` or a promise. Limit: 5 seconds.

## stop()

Called when the Connector stops. Close everything `start` opened. Must be safe to call more than once. Limit: 5 seconds.

## send(reply)

Delivers one reply from Cowork to the channel.

| Name | Type | Description |
|---|---|---|
| `reply.text` | `string` | The reply |
| `reply.channelKey` | `string` | Where it goes, as given by `emit` |
| `reply.idempotencyKey` | `string` | The same key is sent at most once |
| `reply.replyTo` <Badge type="warning" text="Not yet released" /> | `{ id, senderId, senderName, role }` | With `chat`: the message this answers |

Returns `Promise<{ ok: boolean, error?: string, externalKey?: string, verified?: boolean }>`. `externalKey` is the platform's own key for this conversation. `verified` <Badge type="warning" text="Not yet released" /> means the reply was seen on the other side (defaults to `ok`).

| Result `error` | When |
|---|---|
| `send_timeout` | `send` took more than 30 seconds |
| `unknown_connector` | No Connector with that id is registered |
| `invalid_reply` | The reply Cowork passed could not be read |
| `invalid_send_result` | `send` returned something without a boolean `ok` |
| The thrown message | `send` threw |

## ctx.emit(message)

Hands one incoming message to Cowork.

| Field | Type | Required | Description |
|---|---|---|---|
| `text` | `string` | Yes | What the chat shows |
| `channelKey` | `string` | No | `<connectorId>/<kind>/<channelId>`; default `<connectorId>/group/default` |
| `senderId` | `string` | No | The platform's fixed id of the sender |
| `senderName` | `string` | No | Display name |
| `msgId` | `string` | No | Used to drop duplicates |
| `at` | `number` | No | Platform time in milliseconds |
| `trigger` | `boolean` | No | `false`: context only, sent along with the next message that gets a reply |
| `contextText` | `string` | No | What the model reads instead of `text` |
| `role` <Badge type="warning" text="Not yet released" /> | `string` | No | With `chat`: who spoke (`host`, `viewer`, `self`); `self` is context only |
| `modality` <Badge type="warning" text="Not yet released" /> | `'text' \| 'voice'` | No | `voice`: transcribed from speech |

Returns nothing.

## ctx.log(text)

Writes one line to the Extension's log. Returns nothing.

```js
ctx.log('connected to room 42');
```

## Example

```js
export function activate(api) {
  let timer;
  api.registerConnector({
    id: 'demo',
    start(ctx) { timer = setInterval(() => ctx.emit({ text: 'ping', senderId: 'bot' }), 60000); },
    stop() { clearInterval(timer); },
    async send(reply) { return { ok: true }; }
  });
}
```

## Related

- [Entry and Registration](https://docs.micromeet.ai/extension-sdk/entry.md): `registerConnector`
- [Browser](https://docs.micromeet.ai/extension-sdk/browser.md): `ctx.browser`, for Connectors that read web pages
- [Gateway: Outside Messages](https://docs.micromeet.ai/connections/gateway.md): Where the messages go
