Skip to content

Module System

The operator uses a router-based modular architecture. Each module encapsulates a domain (AI, tools, MCP, etc.) and registers message handlers on a central router.

Router

File: internal/module/router.go

The router maps message types to handler functions:

go
type Router struct {
    handlers map[string]Handler
    mu       sync.RWMutex
}

type Handler func(msg Message, respond Responder) error
type Responder func(payload any) error

func (r *Router) Register(msgType string, handler Handler)
func (r *Router) Handle(msg Message, respond Responder) error

When a message arrives via any transport (TCP, HTTP, WebSocket), it's dispatched to the matching handler by type field.

Dependencies

All modules receive shared dependencies at registration time:

go
type Dependencies struct {
    Agents    *agent.Registry
    Tools     *tool.Registry
    Providers *provider.Registry
    Runner    *runner.Runner
    MCP       *mcp.Client
    Skills    *skill.Manager
    Hooks     *hook.Manager
    State     *state.Store
    Sessions  *session.Manager
    Context   *context.Manager
    OAuth     *oauth.Manager
}

This is explicit dependency injection — no global state, no service locator.

Module Interface

go
type Module interface {
    Name() string
    Register(router *Router, deps *Dependencies)
}

Each module's Register() method adds its handlers to the router.

Built-in Modules

AI Module

Handles agent dispatch and chat operations:

Message TypeDescription
dispatchOne-shot agent dispatch
dispatch.streamStreaming agent dispatch
chatMessage-based chat
chat.streamStreaming chat

Agent Module

Manages agent configuration:

Message TypeDescription
agents.listList all available agents
agents.getGet agent config by ID

Tool Module

Tool discovery and management:

Message TypeDescription
tools.listList available tools for current agent

Provider Module

AI provider management:

Message TypeDescription
providers.listList providers with their models

MCP Module

MCP server management:

Message TypeDescription
mcp.serversList connected MCP servers
mcp.connectConnect to an MCP server
mcp.disconnectDisconnect from a server
mcp.toolsList tools from MCP servers

Skill Module

Skill loading and management:

Message TypeDescription
skills.listList loaded skills
skills.loadLoad skills from a directory

Session Module

Session persistence:

Message TypeDescription
sessions.listList saved sessions
sessions.loadRestore a saved session
sessions.saveSave current session
sessions.deleteDelete a saved session

Context Module

Project and mode context:

Message TypeDescription
context.set_projectSet active project path
context.set_modeSet code/UI mode
context.set_componentSet selected component
context.getGet current context

Auth Module

Authentication and credentials:

Message TypeDescription
auth.set_tokenStore auth token
auth.set_api_baseSet provider API base URL
auth.device_codeStart device code OAuth flow
auth.statusCheck auth status

OAuth Module

OAuth flow management:

Message TypeDescription
oauth.startInitiate OAuth flow for a provider
oauth.callbackHandle OAuth callback
oauth.refreshRefresh expired token

State Module

Direct state access:

Message TypeDescription
state.getRead a state value
state.setWrite a state value

Adding a Module

To add a new module:

  1. Create a package under internal/:
go
package myfeature

import "operator/internal/module"

type Module struct{}

func (m *Module) Name() string { return "myfeature" }

func (m *Module) Register(router *module.Router, deps *module.Dependencies) {
    router.Register("myfeature.action", m.handleAction(deps))
}

func (m *Module) handleAction(deps *module.Dependencies) module.Handler {
    return func(msg module.Message, respond module.Responder) error {
        // Handle the message
        return respond(map[string]any{"result": "done"})
    }
}
  1. Register it in main.go:
go
router.RegisterModule(&myfeature.Module{})

The module will immediately start receiving messages matching its registered types.

Construct Team — Internal Developer Documentation