feat: Add pluggable channel system for remote messaging via Telegram#410
Draft
feat: Add pluggable channel system for remote messaging via Telegram#410
Conversation
Add a transport-agnostic channel abstraction that lets external messaging platforms (Telegram, WhatsApp, etc.) act as inbound/outbound bridges to the agent. Channel messages flow through the existing ConversationRepository and MessageQueue, reusing the agent's session management and auto-compaction. - Channel interface (domain.Channel) with Start/Send/Stop lifecycle - ChannelManager service with registry, auth allowlist, EventBridge routing - Telegram channel implementation using go-telegram/bot SDK (long-polling) - Per-channel allowlist security (secure-by-default: empty list rejects all) - Full documentation, Docker Compose example, and test coverage Closes #380
5065eb3 to
9ce8847
Compare
Adds a configurable max_workers setting (default: 5) that caps the number of agent subprocesses running in parallel. New messages wait for a slot when all workers are busy.
Split agent system prompt to custom instructions and system prompt configurations also allow the operator to completely remove the defaults when not needed. It's essential for minimal tests of the agent. Agent was tested via telegram and seems to work as expected now I might create an RC soon.
Contributor
Author
Previously, processSyncResponse saved content and tool_calls as separate assistant messages. This broke the API contract where assistant(tool_calls) must be immediately followed by tool(result), causing DeepSeek and other providers to reject the conversation history with "insufficient tool messages following tool_calls message".
…h command state management - Add SessionRolloverManager for automatic conversation rollover on idle/context limits - Introduce BackgroundTaskRegistry to unify A2A and shell task tracking - Add BackgroundTasksWaiter for batch-mode task draining - Fix bash command failure flow: carry all state in BashCommandCompletedEvent and emit side effects via tea.Sequence after EndToolExecution() state transition - Decouple channel manager from agent, add Telegram example with A2A browser agent - Add max_workers semaphore support for concurrent agent subprocesses
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Summary
infer channels-managercommand runs as a standalone long-running daemon, completely decoupled from the agentinfer agent --session-id <id>as a subprocess — the agent has no knowledge of channelsArchitecture
What's included
domain.Channel) withStart/Send/Stoplifecyclego-telegram/botSDK (long-polling, no webhook needed)infer channels-managercommand — standalone daemon with signal handling--session-idnow persists the provided ID even when the session doesn't exist yetdocs/channels.md), Docker Compose example, and test coverageKey design decisions
infer agent --session-id <id>, giving crash isolation and clean lifecyclechannel-{name}-{senderID}, so conversations persist across messages using the existing ConversationRepository and auto-compactTODOs
Closes #380