Skip to content

feat: Add bot API endpoints for reading messages and adding reactions#190

Open
jpshackelford wants to merge 6 commits intobasecamp:mainfrom
jpshackelford:feature/bot-read-messages
Open

feat: Add bot API endpoints for reading messages and adding reactions#190
jpshackelford wants to merge 6 commits intobasecamp:mainfrom
jpshackelford:feature/bot-read-messages

Conversation

@jpshackelford
Copy link
Copy Markdown

@jpshackelford jpshackelford commented Apr 8, 2026

Summary

Adds two new API endpoints for bots:

  1. GET /rooms/:room_id/:bot_key/messages - Read messages from rooms
  2. POST /rooms/:room_id/:bot_key/messages/:message_id/boosts - Add emoji reactions to messages

Motivation

Currently, bots can only receive individual messages via webhooks when they are @mentioned (or all messages in DMs). This makes it difficult for AI-powered bots and other automated agents to understand the conversation context when formulating responses.

These changes enable bots to:

  • Fetch recent message history to understand conversation context
  • Reference earlier messages in a thread
  • Build more intelligent, context-aware responses
  • Acknowledge messages with reactions (e.g., 👀 when mentioned) to provide immediate feedback before generating a full response

Changes

Endpoint 1: Read Messages

GET /rooms/:room_id/:bot_key/messages

Response Format (JSON):

{
  "room": {
    "id": 1,
    "name": "General"
  },
  "messages": [
    {
      "id": 123,
      "body": {
        "plain": "Hello world",
        "html": "<p>Hello world</p>"
      },
      "created_at": "2024-01-15T10:30:00Z",
      "creator": {
        "id": 42,
        "name": "Jane Doe",
        "is_bot": false
      }
    }
  ],
  "pagination": {
    "oldest_id": 100,
    "newest_id": 123,
    "has_more": true
  }
}

Pagination:

  • ?before=:id - Get messages before this message ID
  • ?after=:id - Get messages after this message ID

Endpoint 2: Add Reaction (Boost)

POST /rooms/:room_id/:bot_key/messages/:message_id/boosts

Request Body:

{
  "content": "👀"
}

Behavior:

  • Validates the bot is a member of the room
  • Validates the message exists in the room
  • Broadcasts the boost to connected clients via Turbo Streams
  • Returns 201 Created on success, 404 if room/message not found

Security Considerations

  • Uses the existing bot authentication mechanism (bot_key in URL)
  • Bots can only read messages from rooms they are members of
  • Bots can only react to messages in rooms they are members of
  • The standard /rooms/:room_id/messages endpoint remains forbidden for bots

Tests

Added tests for:

Read Messages endpoint:

  • Basic JSON response structure
  • Message detail inclusion
  • Pagination support (before/after parameters)
  • Invalid bot key handling
  • Verification that standard messages endpoint remains forbidden for bots

Add Reaction endpoint:

  • Successful boost creation
  • Invalid bot key handling
  • Message not found handling
  • Room membership validation

This PR was created by an AI assistant (OpenHands) on behalf of @jpshackelford.

Adds a new GET endpoint at /rooms/:room_id/:bot_key/messages that allows
bots to read messages from rooms they are members of.

The endpoint returns JSON with:
- Room info (id, name)
- Messages array with body (plain/html), created_at, and creator info
- Pagination info (oldest_id, newest_id, has_more)

Supports pagination via ?before=:id and ?after=:id query parameters,
consistent with the existing pagination in the messages controller.

This enables AI bots and other automated agents to understand conversation
context when responding to messages, rather than only receiving the single
message that triggered the webhook.

Co-authored-by: openhands <openhands@all-hands.dev>
Copilot AI review requested due to automatic review settings April 8, 2026 17:53
Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Added explicit RecordNotFound handling to return 404 when a bot tries to
read messages from a room it's not a member of. This matches the security
model used by the create action.

Added tests to verify:
- Bot gets 404 when trying to read from room it's not a member of
- Bot can successfully read from room it IS a member of

Co-authored-by: openhands <openhands@all-hands.dev>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +86 to +89
test "index supports pagination with after parameter" do
get room_bot_messages_index_url(@room, users(:bender).bot_key, after: Message.first.id)
assert_response :success
end
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

This test uses Message.first.id which is 1, but message 1 belongs to the 'designers' room, not the 'watercooler' room (@room). When the controller tries to find this message in the watercooler room, it will raise a RecordNotFound error. Use a message ID that actually belongs to the watercooler room, such as creating a message in setup or using a message ID from the watercooler fixtures.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in commit c82a8d3 - now using messages(:fourth) and messages(:thirteenth) which are fixtures belonging to the watercooler room where the bender bot is a member.

jpshackelford and others added 2 commits April 8, 2026 13:59
Both create and index now return HTTP 404 Not Found when a bot tries to
access a room it's not a member of. This is consistent with REST API
security best practices (not revealing resource existence) and ensures
read and write permissions are handled identically.

Changed create action to no longer call super (which rendered HTML) and
instead directly handle the request with proper JSON API error responses.

Added test to verify create returns 404 for non-member rooms.

Co-authored-by: openhands <openhands@all-hands.dev>
Fixed test bug identified by Copilot code review: pagination tests were
using Message.first and Message.last which could return messages from
different rooms than the test's @room (watercooler).

Now explicitly using messages(:fourth) and messages(:thirteenth) which
are fixtures belonging to the watercooler room where bender bot is a member.

Co-authored-by: openhands <openhands@all-hands.dev>
Copilot AI review requested due to automatic review settings April 8, 2026 18:45
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

creator: {
id: message.creator.id,
name: message.creator.name,
is_bot: message.creator.role == "bot"
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

Use the enum predicate method bot? instead of comparing to the string "bot". This is consistent with how the codebase checks enum values elsewhere (e.g., administrator? in User::Role) and is the idiomatic Rails pattern for enum checks.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in e8c1349 - now using message.creator.bot? which is the idiomatic Rails enum predicate pattern.

Changed `message.creator.role == "bot"` to `message.creator.bot?` per
Copilot code review. This is the idiomatic Rails pattern for enum checks
and consistent with how other role checks are done in the codebase.

Co-authored-by: openhands <openhands@all-hands.dev>
@jpshackelford
Copy link
Copy Markdown
Author

@flavorjones This is the same level of rights we have for the OpenHands agent in our Slack integration which allows humans to discuss an issue in channel and then one can just ask the agent to fix it and the agent then can obtain the context needed to start work without requiring a user to reiterate the entire discussion in a new message to the bot.

jpshackelford added a commit to jpshackelford/OpenPaw that referenced this pull request Apr 8, 2026
Updated setup script to use jpshackelford/once-campfire:bot-read-messages
which includes the bot message reading API (PR #190 to basecamp/once-campfire).

This allows bots to read conversation context when responding to messages.

Changes:
- Default image changed to fork with bot read API
- Added --campfire-image flag for custom image
- Added --use-official-campfire flag to use upstream image

Once PR #190 is merged upstream, we can switch back to the official image.

PR: basecamp/once-campfire#190

Co-authored-by: openhands <openhands@all-hands.dev>
Adds a new endpoint that allows bots to add emoji reactions (boosts) to messages:
POST /rooms/:room_id/:bot_key/messages/:message_id/boosts

This enables bots to acknowledge messages with reactions like 👀 (eyes) when
mentioned, providing immediate feedback to users before generating a full response.

The endpoint:
- Validates the bot is a member of the room
- Validates the message exists in the room
- Broadcasts the boost to connected clients via Turbo Streams
- Returns 201 Created on success, 404 if room/message not found

Co-authored-by: openhands <openhands@all-hands.dev>
Copilot AI review requested due to automatic review settings April 9, 2026 00:45
@jpshackelford jpshackelford changed the title feat: Add bot API endpoint for reading room messages feat: Add bot API endpoints for reading messages and adding reactions Apr 9, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

2 participants