slack

package
v0.25.0 Latest Latest
Warning

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

Go to latest
Published: Jun 25, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package slack — send.go: local agent-proxy send handler + reply helpers.

Purpose: HTTP handler for POST /integrations/slack/send (localhost-only),

Block-Kit reply helpers (postReply, postReplyWithFooter, signedContextBlock),
and the ConnectorTokenFn type alias.

Caller: Channel.HTTPHandlers() mounts sendHandler(); postChunked calls

postReply / postReplyWithFooter.

Dependencies: slackgo, appname, zerolog. Main Functions:

  • sendHandler() — HTTP proxy endpoint, bot or user-token post
  • postReply() — plain-text thread reply with backoff
  • postReplyWithFooter() — Block Kit reply with muted footer
  • signedContextBlock() — builds "Sent using <@BOT>" context block

Side Effects: none (mutates no global state; userTokenCache is per-Channel).

Package slack implements the Slack transport for the agents channel registry. See package channels for the shared interfaces (Channel, SessionChecker, SessionStartHook, …) — this package only adds the Slack-specific concrete type.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AuthTestWithToken added in v0.13.0

func AuthTestWithToken(ctx context.Context, token string) (userID string, err error)

AuthTestWithToken calls auth.test for the given xoxp token and returns the Slack UserID of the token owner. Used by the server's connector-token lookup to match a user_token connector row to a Slack user ID.

Types

type Channel

type Channel struct {
	// contains filtered or unexported fields
}

Channel implements agentchannels.Channel for Slack, supporting both Socket Mode (default — no public URL required) and HTTP Event API (requires public URL).

Lifecycle (per incoming message):

  1. Parse event → extract channel_id, thread_ts, user_id, text
  2. Access control check (everyone / users / groups)
  3. Meta-command intercept (dashboard, reset, status, log, agent)
  4. Dispatch to pool via sendFn
  5. On agent events: update reactions + post chunked final reply

Hot-reload: call Reload(ctx, newCfg, pubURL) to apply new credentials without restarting the server.

func New

New builds a Slack Channel from the operator-supplied config alone. All other dependencies are wired by *agentchannels.Registry via the corresponding Set* setters before Start.

func NewWithOwner added in v0.17.0

func NewWithOwner(cfg agentconfig.SlackChannelConfig, ownerUserID string) *Channel

NewWithOwner creates a Slack Channel tied to a specific wick user owner. ownerUserID="" means the App Owner's channel (user_id = NULL row).

func (*Channel) API added in v0.13.0

func (s *Channel) API() *slackgo.Client

API returns the live Slack web-API client. Returns nil when the channel isn't configured yet — callers must nil-check before use. The workflow action subpackage (slack/workflow) uses this to invoke chat.postMessage, views.open, reactions.add, etc.

func (*Channel) HTTPHandler

func (s *Channel) HTTPHandler() http.Handler

HTTPHandler returns the webhook handler. Verifies HMAC-SHA256 + handles url_verification challenge synchronously; everything else dispatched async.

func (*Channel) HTTPHandlers added in v0.13.0

func (s *Channel) HTTPHandlers() map[string]http.Handler

HTTPHandlers satisfies channels.MultiHTTPHandlerProvider. Returns two routes:

  • POST /integrations/slack/events — inbound Slack webhook
  • POST /integrations/slack/send — local agent proxy, no external auth

OAuth routes (start/callback) have moved to the generic connector manager at /manager/connectors/slack/oauth/* and are no longer registered here.

func (*Channel) HealthCheck added in v0.10.0

func (s *Channel) HealthCheck() []agentchannels.HealthCheck

HealthCheck satisfies channels.HealthChecker. Each entry corresponds to one upstream call the channel makes during normal operation. Calls run sequentially — Slack rate limits per-method, not per-app — and each is given a short timeout so a single hung call doesn't block the whole probe.

Transport mode is probed separately at the end: for socket mode the current subscription state is reported and an async Reconnect is kicked off when disconnected/errored (anti-duplicate guard inside Reconnect). For http mode the public webhook URL is verified.

func (*Channel) IsConfigured

func (s *Channel) IsConfigured() bool

IsConfigured returns true when the config has the minimum required fields to start. Required fields by mode:

  • socket: BotToken + AppToken
  • http: BotToken + SigningSecret

func (*Channel) Lookup added in v0.10.0

func (s *Channel) Lookup(source, query string) ([]agentchannels.LookupItem, error)

Lookup satisfies channels.LookupProvider. Supported sources:

  • "slack.users" → workspace users (skips bots / deleted)
  • "slack.usergroups" → user groups (matches name + handle)
  • "slack.channels" → public + private channels the bot can see

func (*Channel) Name

func (s *Channel) Name() string

Name satisfies Channel.

func (*Channel) NotifyState

func (s *Channel) NotifyState(sessionKey, state, text string)

NotifyState updates reaction + posts reply for the latest turn of sessionKey.

func (*Channel) OnAgentEvent

func (s *Channel) OnAgentEvent(sessionKey string, ev event.AgentEvent)

OnAgentEvent satisfies channels.AgentEventReceiver.

func (*Channel) OnApprovalRequest

func (s *Channel) OnApprovalRequest(sessionID string, req gate.ApprovalRequest)

OnApprovalRequest satisfies channels.ApprovalReceiver.

func (*Channel) OnApprovalResolved

func (s *Channel) OnApprovalResolved(sessionID, requestID, decision string)

OnApprovalResolved satisfies channels.ApprovalReceiver. Decision / expiry / revoke all funnel here — in every case we delete the prompt so the thread stays clean (no permanent "Approved" / "Blocked" / "Expired" residue).

func (*Channel) Reconnect added in v0.14.23

func (s *Channel) Reconnect(ctx context.Context)

Reconnect re-establishes the Socket Mode connection when the current state is not connecting/connected. No-op when already connecting or connected (anti-duplicate-subscribe guard). HTTP mode is a no-op. Runs Reload in a goroutine so callers (health probe, test panel) do not block on the reconnect handshake.

func (*Channel) RefreshTokenMap added in v0.13.0

func (s *Channel) RefreshTokenMap(ctx context.Context)

RefreshTokenMap rebuilds the userID→token map from connector rows. Debounced: skips if called within 60s of last refresh.

func (*Channel) Reload

func (s *Channel) Reload(ctx context.Context, cfg agentconfig.SlackChannelConfig, pubURL string)

Reload stops the current connection, applies new credentials, and restarts if the new config is valid.

func (*Channel) SetApproveFn

func (s *Channel) SetApproveFn(fn agentchannels.ApproveFn)

SetApproveFn satisfies channels.ApproveFnSetter.

func (*Channel) SetConnectorTokenFn added in v0.13.0

func (s *Channel) SetConnectorTokenFn(fn ConnectorTokenFn)

SetConnectorTokenFn wires an optional user-token lookup function so sendHandler can post messages appearing to come from a specific user. Safe to call after New; nil = no user-token DM support (default).

func (*Channel) SetOwnerFn added in v0.17.0

func (s *Channel) SetOwnerFn(fn func(ctx context.Context, sessionID, userID string))

SetOwnerFn wires a function that stamps a wick user ID on a session.

func (*Channel) SetPublicURL

func (s *Channel) SetPublicURL(u string)

SetPublicURL satisfies channels.PublicURLSetter.

func (*Channel) SetSendFunc

func (s *Channel) SetSendFunc(fn agentchannels.SendFunc)

SetSendFunc satisfies channels.SendFuncSetter.

func (*Channel) SetSessionChecker

func (s *Channel) SetSessionChecker(c agentchannels.SessionChecker)

SetSessionChecker satisfies channels.SessionCheckerSetter.

func (*Channel) SetSessionStartHook

func (s *Channel) SetSessionStartHook(fn agentchannels.SessionStartHook)

SetSessionStartHook satisfies channels.SessionStartHookSetter.

func (*Channel) SetTokenRefreshFn added in v0.13.0

func (s *Channel) SetTokenRefreshFn(fn func(ctx context.Context) map[string]string)

SetTokenRefreshFn wires a function that rebuilds the full userID→token map. Called at startup and triggered on-demand when a lookup misses.

func (*Channel) SetWickUserIDFn added in v0.17.0

func (s *Channel) SetWickUserIDFn(fn WickUserIDFn)

SetWickUserIDFn wires a Slack→wick user mapping function for session ownership.

func (*Channel) SetWorkflowEventSink added in v0.13.0

func (s *Channel) SetWorkflowEventSink(fn WorkflowEventSink)

SetWorkflowEventSink wires the sink. Safe to call before Start (the channel just holds the closure until the first event arrives).

func (*Channel) SocketState added in v0.14.23

func (s *Channel) SocketState() (string, time.Time)

SocketState returns the current Socket Mode lifecycle state and when it was last updated. Empty state means the channel is in HTTP mode or has not started yet. Used by the integration test panel to report "subscribed / not subscribed" without re-initiating a connection.

func (*Channel) Start

func (s *Channel) Start(ctx context.Context) error

Start begins listening for Slack events. Blocks until ctx is cancelled or Stop/Reload is called.

func (*Channel) Status added in v0.14.23

func (s *Channel) Status() []agentchannels.StatusField

Status satisfies channels.StatusReporter — returns identity + transport state for the admin UI panel under the Test Integration button.

func (*Channel) Stop

func (s *Channel) Stop()

Stop signals the current Start() to exit gracefully.

func (*Channel) SupportsSession added in v0.13.0

func (s *Channel) SupportsSession() bool

SupportsSession reports that Slack can originate multi-turn agent sessions (thread = session boundary).

func (*Channel) WorkflowActionSpecs added in v0.13.0

func (s *Channel) WorkflowActionSpecs() []agentchannels.WorkflowActionSpec

WorkflowActionSpecs declares the outbound op catalog for Slack action nodes. Schemas match what WorkflowSend accepts.

func (*Channel) WorkflowSend added in v0.13.0

func (s *Channel) WorkflowSend(ctx context.Context, op string, args map[string]any) (any, error)

WorkflowSend dispatches one outbound op against the live Slack API.

func (*Channel) WorkflowTriggerSpecs added in v0.13.0

func (s *Channel) WorkflowTriggerSpecs() []agentchannels.WorkflowTriggerSpec

WorkflowTriggerSpecs declares the inbound event classes the Slack channel emits into the workflow router.

type ConfigSource

type ConfigSource struct {
	// contains filtered or unexported fields
}

ConfigSource implements agentchannels.ConfigSource for *Channel.

func NewConfigSource

func NewConfigSource(store agentchannels.SlackConfigStore, ch *Channel) *ConfigSource

NewConfigSource binds a Slack channel to a config store so the registry watcher can hot-reload it.

func NewConfigSourceKeyed added in v0.17.0

func NewConfigSourceKeyed(store agentchannels.SlackConfigStore, ch *Channel, userID string) *ConfigSource

NewConfigSourceKeyed creates a ConfigSource that loads config for a specific user's Slack channel row. userID="" loads the App Owner row.

func (*ConfigSource) Hash

func (s *ConfigSource) Hash() string

Hash fingerprints fields that materially affect connection state.

func (*ConfigSource) Reload

func (s *ConfigSource) Reload(ctx context.Context) error

Reload re-reads the config and applies it to the bound channel.

type ConnectorTokenFn added in v0.13.0

type ConnectorTokenFn func(ctx context.Context, slackUserID string) (token string, found bool)

ConnectorTokenFn resolves an xoxp user token from the connectors service for the given Slack user ID. Called by sendHandler when sender_user_id is set. Return found=false when no connector row holds a token for that user.

type WickUserIDFn added in v0.17.0

type WickUserIDFn func(ctx context.Context, slackUserID string) (wickUserID string, found bool)

WickUserIDFn resolves a Slack user ID to a wick platform user ID. Returns ("", false) when no mapping is found (e.g. user never connected OAuth).

type WorkflowEventSink added in v0.13.0

type WorkflowEventSink func(ctx context.Context, event string, payload map[string]any)

WorkflowEventSink is the closure the slack channel calls for every inbound Slack event that should be routable as a workflow trigger. The `event` argument matches one of the descriptors registered in internal/agents/channels/slack/workflow (message, app_mention, block_action, view_submission, view_closed, shortcut, command, app_home_opened). Payload mirrors the corresponding event-payload struct in that subpackage, flattened to map[string]any so the workflow router can apply match rules generically.

Production wiring: setup composer constructs a sink that adapts the (event, payload) pair into a workflow.Event and calls Router.Dispatch. Tests pass a closure that records calls.

Directories

Path Synopsis
Slack picker resolvers — feed workflow_picker_resolve so AI authors editing a trigger match (channel_id whitelist, user whitelist) can get real IDs instead of guessing C123/U456.
Slack picker resolvers — feed workflow_picker_resolve so AI authors editing a trigger match (channel_id whitelist, user whitelist) can get real IDs instead of guessing C123/U456.

Jump to

Keyboard shortcuts

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