Overview
The Gateway is Weaver’s central coordinator that:
Manages communication channel connections (Telegram, Discord, Slack, etc.)
Routes messages between channels and agents via the message bus
Provides REST API and health check endpoints
Coordinates cron jobs and heartbeat monitoring
Handles device event notifications
Architecture
The gateway runs as a single long-lived process that orchestrates all agent communication:
Starting the Gateway
From cmd/weaver/main.go:520-690:
func gatewayCmd () {
cfg , _ := loadConfig ()
provider , _ := providers . CreateProvider ( cfg )
// Core components
msgBus := bus . NewMessageBus ()
agentLoop := agent . NewAgentLoop ( cfg , msgBus , provider )
channelManager , _ := channels . NewManager ( cfg , msgBus )
// Services
cronService := setupCronTool ( agentLoop , msgBus , workspace , restrict )
heartbeatService := heartbeat . NewHeartbeatService ( ... )
deviceService := devices . NewService ( ... )
healthServer := health . NewServer ( host , port , agentLoop )
// Start everything
cronService . Start ()
heartbeatService . Start ()
deviceService . Start ( ctx )
channelManager . StartAll ( ctx )
healthServer . Start ()
agentLoop . Run ( ctx )
}
Docker Compose
CLI
Docker Run
services :
weaver-gateway :
image : operatoronline/weaver:latest
command : gateway
volumes :
- ./workspace:/root/.weaver/workspace
- ./config.json:/root/.weaver/config.json
environment :
- GEMINI_API_KEY=${GEMINI_API_KEY}
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
ports :
- "8080:8080"
restart : unless-stopped
Start with: docker compose up -d weaver-gateway
docker run -d \
--name weaver-gateway \
-v $( pwd ) /workspace:/root/.weaver/workspace \
-v $( pwd ) /config.json:/root/.weaver/config.json \
-e GEMINI_API_KEY= $GEMINI_API_KEY \
-e TELEGRAM_BOT_TOKEN= $TELEGRAM_BOT_TOKEN \
-p 8080:8080 \
operatoronline/weaver gateway
Startup Sequence
When the gateway starts, it initializes components in order:
Load Configuration
Read ~/.weaver/config.json and environment variables: {
"gateway" : {
"host" : "0.0.0.0" ,
"port" : 8080
},
"channels" : {
"telegram" : { "enabled" : true },
"discord" : { "enabled" : true }
}
}
Initialize Agent Loop
Create agent with tool registry: 📦 Agent Status:
• Tools: 15 loaded
• Skills: 3/8 available
Start Channel Manager
Connect to enabled channels: ✓ Channels enabled: [telegram, discord, slack]
Start Services
✓ Cron service started
✓ Heartbeat service started
✓ Device event service started
Start HTTP Server
✓ Gateway started on 0.0.0.0:8080
✓ Gateway REST API available at http://0.0.0.0:8080/chat
✓ Health endpoints available at /health and /ready
Press Ctrl+C to stop
REST API
The gateway exposes HTTP endpoints for direct agent interaction:
POST /chat
Send a message to the agent:
curl -X POST http://localhost:8080/chat \
-H "Content-Type: application/json" \
-d '{
"message": "What files are in the current directory?",
"session_key": "api-user-123"
}'
Response:
{
"response" : "Here are the files in the workspace: \n - AGENT.md \n - sessions/ \n - cron/ \n " ,
"ui_commands" : []
}
The user’s message to the agent
Session identifier for conversation history. Defaults to "rest:default"
Target channel context. Defaults to "cli"
Chat identifier for tool execution context
Media generation config (for image generation): {
"type" : "image" ,
"size" : "1024x1024" ,
"aspect_ratio" : "1:1"
}
GET /health
Basic liveness check:
curl http://localhost:8080/health
Response:
{
"status" : "ok" ,
"timestamp" : 1704067200
}
GET /ready
Readiness check with system details:
curl http://localhost:8080/ready
Response:
{
"status" : "ready" ,
"agent" : {
"model" : "google/gemini-3-flash" ,
"workspace" : "/root/.weaver/workspace" ,
"sessions" : [
{ "key" : "cli:default" , "message_count" : 12 },
{ "key" : "telegram:123" , "message_count" : 8 }
],
"subagents" : [
{ "id" : "task-abc" , "status" : "running" , "task" : "Analyze logs" }
]
}
}
Channel Manager
From pkg/channels/manager.go:20-43:
type Manager struct {
channels map [ string ] Channel
bus * bus . MessageBus
config * config . Config
dispatchTask * asyncTask
}
func ( m * Manager ) StartAll ( ctx context . Context ) error {
// Start outbound message dispatcher
go m . dispatchOutbound ( ctx )
// Start each enabled channel
for name , channel := range m . channels {
channel . Start ( ctx )
}
}
The channel manager automatically initializes enabled channels:
if cfg . Channels . Telegram . Enabled && cfg . Channels . Telegram . Token != "" {
telegram , _ := NewTelegramChannel ( cfg , bus )
m . channels [ "telegram" ] = telegram
}
Configuration: {
"channels" : {
"telegram" : {
"enabled" : true ,
"token" : "YOUR_BOT_TOKEN"
}
}
}
if cfg . Channels . Discord . Enabled && cfg . Channels . Discord . Token != "" {
discord , _ := NewDiscordChannel ( cfg . Channels . Discord , bus )
m . channels [ "discord" ] = discord
}
Configuration: {
"channels" : {
"discord" : {
"enabled" : true ,
"token" : "YOUR_BOT_TOKEN"
}
}
}
if cfg . Channels . Slack . Enabled && cfg . Channels . Slack . BotToken != "" {
slack , _ := NewSlackChannel ( cfg . Channels . Slack , bus )
m . channels [ "slack" ] = slack
}
Configuration: {
"channels" : {
"slack" : {
"enabled" : true ,
"bot_token" : "xoxb-..." ,
"app_token" : "xapp-..."
}
}
}
See Channels for complete list of supported platforms.
Message Dispatch
The gateway runs an outbound message dispatcher:
func ( m * Manager ) dispatchOutbound ( ctx context . Context ) {
for {
select {
case <- ctx . Done ():
return
default :
msg , ok := m . bus . SubscribeOutbound ( ctx )
if ! ok {
continue
}
// Skip internal channels (cli, system, subagent)
if constants . IsInternalChannel ( msg . Channel ) {
continue
}
channel , exists := m . channels [ msg . Channel ]
if ! exists {
continue
}
channel . Send ( ctx , msg )
}
}
}
Messages on internal channels (cli, system, subagent) are logged but not sent to external channels.
Services
Cron Service
Scheduled task execution:
cronService := cron . NewCronService ( storePath , nil )
cronService . SetOnJob ( func ( job * cron . CronJob ) ( string , error ) {
result := cronTool . ExecuteJob ( context . Background (), job )
return result , nil
})
cronService . Start ()
Jobs are executed by the agent with optional delivery:
{
"id" : "job-abc" ,
"message" : "Check system health" ,
"deliver" : true ,
"channel" : "telegram" ,
"to" : "123456"
}
Heartbeat Service
Periodic agent checks:
heartbeatService := heartbeat . NewHeartbeatService (
workspace ,
cfg . Heartbeat . Interval , // e.g., 300000 (5 minutes)
cfg . Heartbeat . Enabled ,
)
heartbeatService . SetHandler ( func ( prompt , channel , chatID string ) * tools . ToolResult {
response , _ := agentLoop . ProcessHeartbeat ( ctx , prompt , channel , chatID )
return tools . SilentResult ( response )
})
Heartbeats run independently without session history.
Device Service
USB device monitoring (Linux only):
deviceService := devices . NewService ( devices . Config {
Enabled : cfg . Devices . Enabled ,
MonitorUSB : cfg . Devices . MonitorUSB ,
}, stateManager )
deviceService . SetBus ( msgBus )
deviceService . Start ( ctx )
On device connect/disconnect, sends notification to last active channel.
Monitoring
The gateway provides observability through structured logging:
logger . InfoCF ( "channels" , "Message received" , map [ string ] interface {}{
"channel" : "telegram" ,
"chat_id" : "123456" ,
"sender" : "@username" ,
})
logger . InfoCF ( "agent" , "LLM request" , map [ string ] interface {}{
"model" : "gemini-3-flash" ,
"tools_count" : 15 ,
"iteration" : 1 ,
})
Enable debug logging:
Logs are written to:
Console (stdout)
File: ~/.weaver/logs/weaver.log (if configured)
Graceful Shutdown
The gateway handles SIGINT/SIGTERM gracefully:
sigChan := make ( chan os . Signal , 1 )
signal . Notify ( sigChan , os . Interrupt )
<- sigChan
fmt . Println ( " \n Shutting down..." )
cancel () // Cancel context
healthServer . Stop ( ctx )
deviceService . Stop ()
heartbeatService . Stop ()
cronService . Stop ()
agentLoop . Stop ()
channelManager . StopAll ( ctx )
This ensures:
In-flight messages are processed
Channels disconnect cleanly
Session state is saved
Cron jobs are persisted
High Availability
For production deployments:
Shared Workspace
Mount workspace on shared storage (NFS, EBS, etc.): volumes :
- /mnt/shared/workspace:/root/.weaver/workspace
Load Balancer
Run multiple gateway instances behind a load balancer: services :
weaver-1 :
image : operatoronline/weaver
# ...
weaver-2 :
image : operatoronline/weaver
# ...
nginx :
image : nginx
ports :
- "80:80"
depends_on : [ weaver-1 , weaver-2 ]
Health Checks
Configure load balancer health checks: upstream weaver {
server weaver-1:8080;
server weaver-2:8080;
}
location /health {
proxy_pass http://weaver;
proxy_connect_timeout 1s ;
}
Channel connections (Telegram, Discord) must be handled by a single gateway instance. Use sticky sessions or dedicated channel gateways.
Next Steps
Channels Configure communication channels
Configuration Learn about gateway configuration options