Skip to main content

Integrations & channels

An "integration" is anything that lives behind a third-party service: chat platforms, smart-home controllers, mail providers. The gateway loads them via IntegrationManager (src/core/integration_manager.py) from JSON manifests.

Three archetypes

IntegrationManager._instantiate_bundle recognizes three shapes:

  1. Channel-style (Discord, Slack, Telegram, WhatsApp): connector + controller + channel + processor — bidirectional messaging surface
  2. Tool-only (Home Assistant, iCloud, Google): connector + controller — exposes tools to the agent but doesn't receive inbound messages
  3. Service-style (image_generation, vision, stt, tts, llm): controller only — the controller picks one of N providers from a registry on demand

controller is mandatory. Other components are optional based on archetype.

Base classes

  • BaseConnectorsrc/integrations/base_connector.py. Owns the SDK client (e.g. discord.Client), handles auth and lifecycle
  • BaseChannelsrc/gateway/channels/base.py. Facade exposing connection state and helpers
  • BaseChannelProcessorsrc/gateway/channel_processing.py. Handles inbound messages, routes them into the agent session engine
  • BaseController — single base for all controllers (no separate BaseConnectorController)

Manifest discovery

IntegrationManager walks two roots:

  • Built-in: src/integrations/<id>/manifest.json
  • User plugins: ~/.youkore/plugins/<id>/plugin.json

Each manifest declares provides.{connector, controller, channel, processor, tools_module} with class paths in module:ClassName form. The manager resolves the classes lazily and instantiates them only for enabled integrations whose dependencies are present.

Hot-plug

IntegrationManager.reload_connector(integration_id):

  1. Disconnects and disposes the old bundle
  2. Re-imports + instantiates the new one
  3. Calls _refresh_tool_manager() so freshly registered tools become visible to agents immediately

Toggling an integration in the UI takes effect without a gateway restart.

Inbound flow (channel-style)

external service ──> connector callback (e.g. on_message)
├─ processor.handle_inbound(message)
├─ resolve user / channel / thread
├─ start or continue an agent session
└─ run agent → reply via connector.send()

Owner identity

get_owner_user_id() (src/gateway/users.py) is the single source of identity inside the gateway. WhatsApp groups also resolve to a single owner via lid_map.json so memories don't get scattered across pseudonymous JIDs.