channels

package
v0.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 14, 2026 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package channels defines the gateway's channel-adapter contract: a normalized inbound message and the interface each external surface (Telegram, Discord, Slack, …) implements. Adapters own their own connection to their platform; the gateway router (internal/gateway/server) maps inbound messages to agent work and posts replies back through Send. Keeping the contract this thin is what lets a new surface be "one more adapter" rather than a new subsystem.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Chunk

func Chunk(s string, max int) []string

Chunk splits s into pieces of at most max runes, preferring to break at a newline near the limit so code blocks and paragraphs aren't cut mid-line. It is the ONE splitter every adapter shares: Hermes and OpenClaw both grew message-too-long bugs precisely where a side path bypassed the shared chunker (or a second, divergent splitter stripped indentation differently), so all outbound text goes through here.

An empty string yields a single empty piece, and the split is loss-free: the concatenation of the result always equals the input (only the exact newline we break on moves to the end of a piece, never dropped).

Types

type Channel

type Channel interface {
	// Name is the adapter's stable identifier (matches Inbound.Channel).
	Name() string
	// Start owns the connection and hands each inbound message to the sink until
	// ctx is cancelled, returning ctx.Err() on clean shutdown. It must NOT return
	// on transient network errors — reconnect/back off instead, so a flaky
	// platform never takes the gateway down. It acknowledges the provider only
	// after Deliver returns nil.
	Start(ctx context.Context, sink Sink) error
	// Send posts a reply to the given conversation. Safe to call while Start runs.
	Send(ctx context.Context, conversation string, msg Outbound) error
}

Channel is a bidirectional chat surface.

type Inbound

type Inbound struct {
	Channel      string // adapter name, matches Channel.Name() ("telegram", …)
	Conversation string // opaque per-channel chat/thread id the reply routes back to
	Principal    string // who sent it (id or @handle) — for authz + audit
	Text         string // the message body: the task handed to the agent
	// MessageID is the platform's stable, unique id for this delivery (Telegram
	// update_id, Discord message id, Slack event ts, GitHub delivery, WhatsApp
	// wamid). The router dedups on (Channel, MessageID) so a redelivery — after a
	// restart, reconnect, or provider retry — never re-runs as a fresh agent turn.
	// Empty means the adapter couldn't supply one; the router then can't dedup it.
	MessageID string
	// Trusted marks an inbound whose SENDER is already cryptographically
	// authenticated by the transport (a signature-verified webhook), so the
	// router's per-channel allow-list doesn't apply. Chat messages leave this
	// false and are gated by the allow-list; a signed GitHub delivery sets it.
	Trusted bool
	// IsDirect is true for a 1:1 direct message. A DM always triggers the agent;
	// a message in a group/channel triggers only when the bot is addressed (see
	// Mentioned) or the channel is configured to respond to all.
	IsDirect bool
	// Mentioned is true when the bot was explicitly addressed — @mentioned, or
	// replied-to — so a group message meant for it triggers even without
	// respond_to_all. Detected structurally by each adapter, never by substring.
	Mentioned bool
}

Inbound is a normalized message arriving from a channel.

type Outbound

type Outbound struct {
	Text string
}

Outbound is a reply to post back to a conversation.

type Sink

type Sink interface {
	Deliver(ctx context.Context, inb Inbound) error
}

Sink receives inbound messages from an adapter. Deliver applies the gateway's gating and authorization and, for a message that should run, durably records it for processing. A nil return means the adapter may acknowledge the provider (the message was recorded, was a duplicate, or was intentionally dropped); a non-nil error means it was NOT durably recorded, so the adapter must NOT ack — the provider will redeliver. Acking only after a nil return is what makes delivery durable: a crash before the record simply causes a redelivery.

Directories

Path Synopsis
Package discord is the gateway's Discord channel adapter.
Package discord is the gateway's Discord channel adapter.
Package slack is the gateway's Slack channel adapter.
Package slack is the gateway's Slack channel adapter.
Package telegram is the gateway's Telegram channel adapter.
Package telegram is the gateway's Telegram channel adapter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL