Phase 1: Gateway & Channel Foundation
This phase establishes the messaging infrastructure that makes AgenC agents reachable via external platforms (Telegram, Discord, etc.). The Gateway wraps the ex
Phase 1: Gateway & Channel Foundation
Overview
This phase establishes the messaging infrastructure that makes AgenC agents reachable via external platforms (Telegram, Discord, etc.). The Gateway wraps the existing AgentRuntime and adds multi-channel communication, session management, lifecycle hooks, and a chat execution loop that turns user messages into task completions.
What this enables:
Dependencies
None β This is a greenfield implementation.
Existing runtime infrastructure used:
AgentRuntime / AgentBuilder for lifecycleConnectionManager for RPCPolicyEngine for permissionsToolRegistry for tool dispatchMemoryBackend for session storageLLMTaskExecutor pattern for chat executionIssue Dependency Graph
Implementation Order
- 1053 β Gateway core process and WebSocket control plane (L)
- Foundation class, runtime integration, control socket for management
- 1051 β Unified message format (S)
- Type definitions for all message flows
- 1054 β Channel plugin interface and ChannelContext (S)
- Plugin contract, context object, plugin catalog
- 1055 β Session management (M)
- Session state, scoping, reset, compaction
- 1056 β Lifecycle hook system (M)
- Event hooks, dispatcher, built-in hooks
- 1052 β Slash commands handler (S)
- Command parser, built-in commands
- 1060 β Telegram channel plugin (M)
- First concrete channel implementation
- 1061 β Discord channel plugin (M)
- Second channel, validates plugin interface
- 1063 β Agent loop integration (L)
- ChatExecutor, model fallback, tool integration
- 1057 β Cross-channel identity linking (M)
- Link Telegram/Discord identities to single user profile
- 1058 β Gateway CLI commands and setup wizard (M)
- CLI for gateway start/stop/status, interactive setup
- 1059 β Media pipeline (M)
- Voice transcription, image description
Rationale: Core gateway β message types β plugin interface β session/hooks β first channels β agent loop β identity/CLI/media.
Issue Details
1.1: Gateway core process and WebSocket control plane (#1053)
Goal: Create the Gateway service that wraps AgentRuntime and exposes a WebSocket control interface.
Files to create:
gateway/src/index.ts β module barrelgateway/src/gateway.ts β Gateway classgateway/src/types.ts β GatewayConfig, GatewayStategateway/src/control/server.ts β WebSocket control planegateway/src/control/protocol.ts β Control message protocolgateway/package.json β new package @agenc/gatewaygateway/tsconfig.jsongateway/vitest.config.tsgateway/src/gateway.test.tsFiles to modify:
package.json (root) β add gateway to workspacesIntegration points:
AgentRuntime from @agenc/runtimeConnectionManager for RPC healthMemoryBackend for session storage~/.agenc/gateway.sockPatterns to follow:
runtime/src/runtime.tsruntime/src/connection/manager.tsruntime/src/types/errors.tsKey interfaces:
interface GatewayConfig {
runtime: AgentRuntime;
controlSocketPath?: string;
sessionBackend: MemoryBackend;
}
interface Gateway {
start(): Promisevoid>;
stop(): Promisevoid>;
getState(): GatewayState;
registerChannel(plugin: ChannelPlugin): void;
}
interface ControlMessage {
type: 'ping' | 'status' | 'reload' | 'stop';
payload?: unknown;
}Testing strategy:
AgentRuntime with stub start/stopMemoryBackendEstimated scope: L (500-800 lines)
1.2: Unified message format (GatewayMessage / OutboundMessage) (#1051)
Goal: Define the canonical message types flowing through the gateway.
Files to create:
gateway/src/messages/types.ts β GatewayMessage, OutboundMessage, MessageAttachmentgateway/src/messages/index.ts β module barrelgateway/src/messages/types.test.tsFiles to modify:
gateway/src/index.ts β export message typesIntegration points:
Patterns to follow:
runtime/src/events/types.tsKey interfaces:
interface GatewayMessage {
id: string;
channelType: string;
channelUserId: string;
text: string;
attachments?: MessageAttachment[];
timestamp: number;
}
interface OutboundMessage {
text: string;
attachments?: MessageAttachment[];
replyTo?: string;
}Testing strategy:
Estimated scope: S (200-300 lines)
1.3: Channel plugin interface and ChannelContext (#1054)
Goal: Define the plugin contract and context object passed to channels.
Files to create:
gateway/src/channels/plugin.ts β ChannelPlugin interfacegateway/src/channels/context.ts β ChannelContext classgateway/src/channels/catalog.ts β PluginCatalog (registry)gateway/src/channels/index.ts β module barrelgateway/src/channels/plugin.test.tsFiles to modify:
gateway/src/gateway.ts β add registerChannel() methodgateway/src/index.ts β export channel typesIntegration points:
runtime/src/tools/registry.tsPatterns to follow:
runtime/src/skills/types.tsruntime/src/tools/registry.tsKey interfaces:
interface ChannelPlugin {
readonly name: string;
initialize(context: ChannelContext): Promisevoid>;
shutdown(): Promisevoid>;
sendMessage(userId: string, message: OutboundMessage): Promisevoid>;
}
interface ChannelContext {
gateway: Gateway;
onMessage(handler: (msg: GatewayMessage) => Promisevoid>): void;
logger: Logger;
}Testing strategy:
Estimated scope: S (300-400 lines)
1.4: Telegram channel plugin (#1060)
Goal: Implement Telegram channel using telegraf library.
Files to create:
gateway/src/channels/telegram/plugin.ts β TelegramChannelPlugingateway/src/channels/telegram/config.ts β TelegramConfiggateway/src/channels/telegram/index.tsgateway/src/channels/telegram/plugin.test.tsFiles to modify:
gateway/package.json β add telegraf as optional dependencygateway/src/channels/index.ts β export TelegramChannelPluginIntegration points:
ensureLazyModule() to load telegrafPatterns to follow:
runtime/src/utils/lazy-import.tsruntime/src/llm/providers/grok.tsKey interfaces:
interface TelegramConfig {
botToken: string;
allowedUsers?: number[];
webhookUrl?: string;
}
class TelegramChannelPlugin implements ChannelPlugin {
readonly name = 'telegram';
// implementation
}Testing strategy:
Estimated scope: M (400-600 lines)
1.5: Discord channel plugin (#1061)
Goal: Implement Discord channel using discord.js library.
Files to create:
gateway/src/channels/discord/plugin.ts β DiscordChannelPlugingateway/src/channels/discord/config.ts β DiscordConfiggateway/src/channels/discord/index.tsgateway/src/channels/discord/plugin.test.tsFiles to modify:
gateway/package.json β add discord.js as optional dependencygateway/src/channels/index.ts β export DiscordChannelPluginIntegration points:
ensureLazyModule() to load discord.jsPatterns to follow:
Key interfaces:
interface DiscordConfig {
botToken: string;
allowedGuilds?: string[];
allowedChannels?: string[];
}
class DiscordChannelPlugin implements ChannelPlugin {
readonly name = 'discord';
// implementation
}Testing strategy:
Estimated scope: M (400-600 lines)
1.6: Session management (scoping, reset, compaction) (#1055)
Goal: Manage conversation sessions with memory backend integration.
Files to create:
gateway/src/session/manager.ts β SessionManager classgateway/src/session/types.ts β Session, SessionConfiggateway/src/session/compaction.ts β Session compaction logicgateway/src/session/index.tsgateway/src/session/manager.test.tsFiles to modify:
gateway/src/gateway.ts β integrate SessionManagergateway/src/index.ts β export session typesIntegration points:
MemoryBackend for storagesession:{channelType}:{userId}Patterns to follow:
runtime/src/memory/types.tsKey interfaces:
interface Session {
id: string;
userId: string;
channelType: string;
createdAt: number;
lastActivityAt: number;
}
interface SessionManager {
getOrCreate(channelType: string, userId: string): PromiseSession>;
reset(sessionId: string): Promisevoid>;
compact(sessionId: string): Promisevoid>;
}Testing strategy:
Estimated scope: M (400-500 lines)
1.7: Lifecycle hook system (HookDispatcher) (#1056)
Goal: Provide event hooks for message lifecycle (before/after send, on error, etc.).
Files to create:
gateway/src/hooks/dispatcher.ts β HookDispatcher classgateway/src/hooks/types.ts β HookHandler, HookEventgateway/src/hooks/builtin.ts β Built-in hooks (logging, metrics)gateway/src/hooks/index.tsgateway/src/hooks/dispatcher.test.tsFiles to modify:
gateway/src/gateway.ts β integrate HookDispatchergateway/src/index.ts β export hook typesIntegration points:
EventMonitor subscription patternPatterns to follow:
runtime/src/events/monitor.tsruntime/src/types/errors.tsKey interfaces:
interface HookEvent {
type: 'message:before' | 'message:after' | 'send:before' | 'send:after' | 'error';
data: unknown;
timestamp: number;
}
interface HookHandler {
handle(event: HookEvent): Promisevoid>;
}
interface HookDispatcher {
register(type: HookEvent['type'], handler: HookHandler): void;
dispatch(event: HookEvent): Promisevoid>;
}Testing strategy:
Estimated scope: M (350-450 lines)
1.8: Slash commands handler (#1052)
Goal: Parse and execute slash commands (/help, /reset, etc.).
Files to create:
gateway/src/commands/parser.ts β Command parsergateway/src/commands/registry.ts β Command registrygateway/src/commands/builtin.ts β Built-in commandsgateway/src/commands/types.ts β Command, CommandContextgateway/src/commands/index.tsgateway/src/commands/parser.test.tsFiles to modify:
gateway/src/gateway.ts β integrate command dispatchgateway/src/index.ts β export command typesIntegration points:
Patterns to follow:
runtime/src/tools/registry.tsKey interfaces:
interface Command {
name: string;
description: string;
execute(ctx: CommandContext, args: string[]): Promisestring>;
}
interface CommandContext {
session: Session;
gateway: Gateway;
}Testing strategy:
Estimated scope: S (250-350 lines)
1.9: Cross-channel identity linking (#1057)
Goal: Link Telegram and Discord identities to a single user profile.
Files to create:
gateway/src/identity/linker.ts β IdentityLinker classgateway/src/identity/types.ts β UserProfile, IdentityLinkgateway/src/identity/storage.ts β Storage adaptergateway/src/identity/index.tsgateway/src/identity/linker.test.tsFiles to modify:
gateway/src/gateway.ts β integrate IdentityLinkergateway/src/session/manager.ts β use linked identity for session keysgateway/src/index.ts β export identity typesIntegration points:
/link <code> commandPatterns to follow:
runtime/src/memory/types.tsKey interfaces:
interface UserProfile {
canonicalId: string;
linkedIdentities: IdentityLink[];
createdAt: number;
}
interface IdentityLink {
channelType: string;
channelUserId: string;
linkedAt: number;
}
interface IdentityLinker {
link(fromChannel: string, fromUserId: string, toUserId: string): Promisevoid>;
resolve(channelType: string, userId: string): Promisestring>;
}Testing strategy:
Estimated scope: M (350-450 lines)
1.10: Gateway CLI commands and setup wizard (#1058)
Goal: CLI for gateway start/stop/status and interactive setup.
Files to create:
gateway/src/cli/gateway.ts β Gateway CLI commandsgateway/src/cli/wizard.ts β Interactive setup wizardgateway/src/cli/index.tsgateway/src/bin/cli.ts β CLI entry pointFiles to modify:
gateway/package.json β add bin entry for agenc-gatewayruntime/src/bin/cli.ts β add gateway subcommands (or keep separate)Integration points:
~/.agenc/gateway.jsonPatterns to follow:
runtime/src/bin/cli.tsruntime/src/cli/health.tsKey interfaces:
interface GatewayCommand {
name: string;
description: string;
execute(args: string[]): Promisevoid>;
}
interface SetupWizard {
run(): PromiseGatewayConfig>;
}Testing strategy:
Estimated scope: M (400-500 lines)
1.11: Agent loop integration (ChatExecutor + model fallback) (#1063)
Goal: Execute chat messages through LLM with tool calling and model fallback.
Files to create:
gateway/src/executor/chat-executor.ts β ChatExecutor classgateway/src/executor/types.ts β ChatExecutorConfig, ChatResultgateway/src/executor/fallback.ts β Model fallback logicgateway/src/executor/index.tsgateway/src/executor/chat-executor.test.tsFiles to modify:
gateway/src/gateway.ts β integrate ChatExecutorgateway/src/index.ts β export executor typesIntegration points:
runtime/src/llm/runtime/src/tools/Patterns to follow:
runtime/src/llm/executor.tsKey interfaces:
interface ChatExecutorConfig {
primaryModel: LLMProvider;
fallbackModels?: LLMProvider[];
tools: ToolRegistry;
memory: MemoryBackend;
maxToolRounds?: number;
}
interface ChatExecutor {
execute(message: GatewayMessage, session: Session): PromiseOutboundMessage>;
}Testing strategy:
Estimated scope: L (600-800 lines)
1.12: Media pipeline (voice transcription, image description) (#1059)
Goal: Process voice and image attachments before sending to LLM.
Files to create:
gateway/src/media/pipeline.ts β MediaPipeline classgateway/src/media/transcription.ts β Voice transcription (Whisper API)gateway/src/media/vision.ts β Image description (GPT-4V or similar)gateway/src/media/types.ts β MediaProcessor interfacegateway/src/media/index.tsgateway/src/media/pipeline.test.tsFiles to modify:
gateway/src/executor/chat-executor.ts β run media pipeline before LLMgateway/package.json β add form-data dependencygateway/src/index.ts β export media typesIntegration points:
Patterns to follow:
runtime/src/llm/providers/Key interfaces:
interface MediaProcessor {
process(attachment: MessageAttachment): Promisestring>;
}
interface MediaPipeline {
processAttachments(attachments: MessageAttachment[]): Promisestring[]>;
}
interface TranscriptionConfig {
apiKey: string;
model?: string;
}Testing strategy:
Estimated scope: M (400-500 lines)
Integration Checklist
After completing all issues: