feat(slack): Level 3 — ambient cross-agent context from Slack channels
When a cron fires, the scheduler now fetches the last 10 messages from the workspace's Slack channel via conversations.history and prepends them to the cron prompt as '[Slack channel context — recent team messages]'. This gives each agent ambient awareness of what peers are doing: - Backend sees Frontend posted 'PR #840 ready for review' → can check - Security Auditor sees Backend posted 'new endpoint added' → plans review - PM sees all engineering activity → better synthesis in rollup Implementation: - slack.go: FetchChannelHistory() calls conversations.history, filters bot's own messages, returns last N as SlackHistoryMessage structs - manager.go: FetchWorkspaceChannelContext() looks up the workspace's Slack config, fetches history, formats as readable context block - scheduler.go: ChannelBroadcaster interface extended with FetchWorkspaceChannelContext; fireSchedule injects context before the cron prompt (prepended, not appended, so the agent sees team context BEFORE its task instructions) Best-effort: if Slack API fails or workspace has no channels, the prompt is unchanged. Truncated to 200 chars per message, 10 messages max to keep prompt overhead bounded. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
65a3496522
commit
8f89ba0b0a
@ -43,9 +43,10 @@ type scheduleRow struct {
|
||||
Prompt string
|
||||
}
|
||||
|
||||
// ChannelBroadcaster posts messages to a workspace's configured social channels.
|
||||
// ChannelBroadcaster posts messages to and reads context from workspace channels.
|
||||
type ChannelBroadcaster interface {
|
||||
BroadcastToWorkspaceChannels(ctx context.Context, workspaceID, text string)
|
||||
FetchWorkspaceChannelContext(ctx context.Context, workspaceID string) string
|
||||
}
|
||||
|
||||
// Scheduler polls the workspace_schedules table and fires A2A messages
|
||||
@ -260,6 +261,17 @@ func (s *Scheduler) fireSchedule(ctx context.Context, sched scheduleRow) {
|
||||
fireCtx, cancel := context.WithTimeout(ctx, fireTimeout)
|
||||
defer cancel()
|
||||
|
||||
// Level 3: inject ambient Slack channel context into the cron prompt.
|
||||
// The agent sees recent peer messages before acting, enabling cross-agent
|
||||
// awareness without explicit A2A delegation. Best-effort — if the fetch
|
||||
// fails or the workspace has no Slack channels, the prompt is unchanged.
|
||||
prompt := sched.Prompt
|
||||
if s.channels != nil {
|
||||
if channelCtx := s.channels.FetchWorkspaceChannelContext(fireCtx, sched.WorkspaceID); channelCtx != "" {
|
||||
prompt = channelCtx + "\n" + prompt
|
||||
}
|
||||
}
|
||||
|
||||
msgID := fmt.Sprintf("cron-%s-%s", short(sched.ID, 8), uuid.New().String()[:8])
|
||||
|
||||
a2aBody, _ := json.Marshal(map[string]interface{}{
|
||||
@ -268,7 +280,7 @@ func (s *Scheduler) fireSchedule(ctx context.Context, sched scheduleRow) {
|
||||
"message": map[string]interface{}{
|
||||
"role": "user",
|
||||
"messageId": msgID,
|
||||
"parts": []map[string]interface{}{{"kind": "text", "text": sched.Prompt}},
|
||||
"parts": []map[string]interface{}{{"kind": "text", "text": prompt}},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user