Skip to content

Conversation

@2witstudios
Copy link
Owner

@2witstudios 2witstudios commented Feb 10, 2026

Summary

  • add a channel agent mention responder that processes structured mention IDs (@[label](id:page)) and triggers in-channel agent replies
  • gate mention-triggered replies to active AI_CHAT agents the user can view and that have send_channel_message enabled
  • trigger mention responder asynchronously from POST /api/channels/[pageId]/messages without blocking normal post flow
  • format agent-origin channel sender names as Agent Name (User Full Name) in send_channel_message
  • render AI sender names consistently in inbox channel thread view and channel broadcasts
  • use AI sender names in /api/inbox channel last-message sender queries via COALESCE(cm."aiMeta"->>'senderName', u.name)

Testing

  • could not run automated tests locally: vitest is unavailable because apps/web/node_modules is not installed in this workspace (sh: vitest: command not found)

Summary by CodeRabbit

  • New Features

    • AI agents now auto-respond when mentioned in channel messages.
    • Messages include AI metadata (custom sender names, agent labels) and show appropriately in channels and inbox.
    • Message previews and broadcasts consistently use normalized message content.
  • Bug Fixes

    • Agent-sent messages correctly count as unread and attribute sender fallback to AI metadata when present.
    • Drive recipient logic avoids duplicate owner notifications and conditions agent triggers on non-empty content.
  • Tests

    • Added comprehensive unit tests for agent-mention handling and inbox/broadcast behaviors.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

Adds an agent-mention responder that detects @agent mentions in channel messages, generates contextual AI replies, posts them as AI-authored messages, and updates messaging/inbox flows to carry and display aiMeta (senderType, senderName), adjust unread logic, and normalize message content handling.

Changes

Cohort / File(s) Summary
Agent Mention Responder
apps/web/src/lib/channels/agent-mention-responder.ts, apps/web/src/lib/channels/__tests__/agent-mention-responder.test.ts
New exported responder and params interface that finds mentioned agents, checks eligibility, builds transcript/context, calls ask_agent, and posts AI replies; comprehensive tests covering success, failures, permissions, deduplication, and enablement.
Message Routing & Broadcasting
apps/web/src/app/api/channels/[pageId]/messages/route.ts
Standardizes on messageContent for storage/previews, includes drive name/slug in fetch, prefers aiMeta.senderName for lastMessageSender, conditionally triggers agent-mention responses when content non-empty, and uses ai-aware fields in broadcasts.
Inbox Query & UI Display
apps/web/src/app/api/inbox/route.ts, apps/web/src/app/dashboard/inbox/channel/[pageId]/page.tsx
Inbox queries now derive sender name from aiMeta and treat agent-sent messages as unread in counting; inbox UI adds aiMeta to MessageWithUser, computes displayName/labels, and conditionally renders avatars for AI vs human messages.
Channel AI Tools & Tests
apps/web/src/lib/ai/tools/channel-tools.ts, apps/web/src/lib/ai/tools/__tests__/channel-tools.test.ts
Refactors sender identity resolution to prefetch actor info and format agent senderName, introduces treatAsSelfAuthored for global_assistant to control read-status updates and recipient filtering, and updates tests for agent vs user broadcast behavior.
Unit Test Additions
apps/web/src/lib/channels/__tests__/*
Large new/updated test suites for mention responder and channel tools validating new behaviors, mocks, and broadcast expectations.

Sequence Diagram

sequenceDiagram
    actor User
    participant API as Message API
    participant Responder as Agent Mention Responder
    participant DB as Database
    participant AskAgent as Ask Agent Service
    participant Channel as Channel Service
    participant Broadcast as Inbox Broadcast

    User->>API: Send message with `@agent` mention
    API->>DB: Insert message (uses messageContent)
    API->>Responder: triggerMentionedAgentResponses(params)
    Responder->>DB: Resolve mentioned agents & fetch context
    DB-->>Responder: Agent metadata, channel history, members
    Responder->>Responder: Build transcript, check permissions/tools
    alt Agent Eligible
        Responder->>AskAgent: ask_agent with context & prompt
        AskAgent-->>Responder: AI response
        Responder->>Channel: send_channel_message (AI reply with aiMeta)
        Channel->>DB: Store AI message
        Channel->>Broadcast: broadcastInboxEvent (aiMeta, preview)
        Broadcast-->>User: Notify recipients
    else Not Eligible
        Responder->>Responder: Skip posting
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I hopped through channels, sniffed each line,

Called out the agents, “Reply — that’s fine!”
Context stitched tight, the answers arrive,
AiMeta stamped, the inbox comes alive.
Tiny paws applaud each AI-driven stride.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the two main changes: adding channel agent mention replies and improving sender name clarity across the application.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/channel-agent-mentions-sender-identity

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
apps/web/src/lib/ai/tools/__tests__/channel-tools.test.ts (1)

288-329: Consider asserting the inbox broadcast payload more fully.

The test validates the broadcast recipient and partial payload shape, but doesn't assert type (e.g., 'channel'). If the implementation includes a type field in the InboxEventPayload (as seen in broadcastInboxEvent's signature), asserting it here would guard against accidental payload regressions.

Proposed assertion enhancement
       expect(mockBroadcastInboxEvent).toHaveBeenCalledWith(
         'user-456',
         expect.objectContaining({
           operation: 'channel_updated',
           id: 'ch-1',
+          type: 'channel',
         })
       );

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8ca9d7bf10

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

toolCallId: `channel-mention-send-${params.sourceMessageId}-${agent.id}`,
messages: [],
experimental_context: {
userId: params.userId,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use a non-user sender context for mention auto-replies

Passing params.userId as the experimental_context.userId for send_channel_message causes mention-triggered AI replies to be treated as if the requesting user sent them. In send_channel_message, that sender identity is used to update that user’s read watermark and to skip inbox broadcast to that same user (filter(m => m.userId !== userId)), so when the AI reply arrives later (common with model latency), the requester can miss unread/inbox notifications for the response they asked for.

Useful? React with 👍 / 👎.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback! This concern is already addressed in the implementation.

Looking at the send_channel_message call in agent-mention-responder.ts (lines 274-296), the context includes:

chatSource: {
  type: 'page',
  agentPageId: agent.id,
  agentTitle: agent.title,
}

This triggers the treatAsSelfAuthored = false path in channel-tools.ts:97:

const treatAsSelfAuthored = senderIdentity.senderType === 'global_assistant';

When treatAsSelfAuthored is false (agent messages):

  1. Read watermark is NOT updated for the requesting user (line 114-123)
  2. Requester IS included in inbox broadcasts (line 211 filter condition)

So agent-triggered replies correctly:

  • Keep the message unread for the requester
  • Include the requester in inbox notifications

The fix in commit da55b4ba specifically implemented this semantic distinction.

2witstudios and others added 5 commits February 10, 2026 11:36
The mocked tool functions return `unknown`, causing Extract<unknown, T>
to resolve to `never`. Define explicit interfaces for test result types.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use `as unknown as Mock` pattern instead of `vi.mocked()` to avoid
strict type checking that expects full union including AsyncIterable.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@2witstudios 2witstudios merged commit e162abf into master Feb 10, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant