Skip to content

Add Slack IO module to SDK #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

devin-ai-integration[bot]
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot commented Aug 8, 2025

Add Slack IO module to SDK

Summary

Implements Python Slack IO functionality by porting the JavaScript implementation from sdk-js/src/io/slack.ts. The new module provides:

  • Slack class with support for both slack-event and slack-message payload types
  • SlackEventPayload & SlackMessagePayload classes for handling different Slack webhook formats
  • parse_slack function for converting raw bytes to Slack objects with validation
  • send_reply method with OpenTelemetry tracing and proper error handling
  • Common property getters (text, user, channel) that work across both payload types
  • Type interfaces added to types.py for consistency with existing IO modules

The implementation follows established patterns from existing IO modules (telegram.py, email.py, discord.py) and mirrors the JavaScript functionality including OpenTelemetry tracing, proper authentication header handling, and structured error responses.

Review & Testing Checklist for Human

⚠️ This code is untested and requires thorough verification before merging

  • End-to-end testing: Test with real Slack event/message webhooks to ensure parsing and reply functionality works correctly
  • Backend API compatibility: Verify the /slack/reply endpoint expects the exact payload structure being sent (agentId, channel, text, blocks, thread_ts)
  • OpenTelemetry tracing: Confirm tracing spans are created correctly and attributes are set properly
  • Authentication flow: Verify that slack-auth-token metadata extraction matches the actual Slack integration setup
  • Error handling: Test edge cases like malformed payloads, missing auth tokens, API failures, and network timeouts

Recommended Test Plan:

  1. Create unit tests for parse_slack with various payload formats
  2. Test both slack-event and slack-message parsing paths
  3. Mock the /slack/reply API and verify request structure
  4. Test send_reply with different reply formats (text, blocks, threaded)
  5. Verify error cases throw appropriate exceptions

Diagram

%%{ init : { "theme" : "default" }}%%
graph TB
    subgraph "agentuity/io"
        init["__init__.py<br/>Export Module"]:::minor-edit
        slack["slack.py<br/>New Slack Class"]:::major-edit
        telegram["telegram.py<br/>Reference Pattern"]:::context
    end
    
    subgraph "agentuity/server"  
        types["types.py<br/>Add Interfaces"]:::minor-edit
    end
    
    subgraph "Key Components"
        SlackClass["Slack Class<br/>Event + Message Support"]:::major-edit
        ParseFunc["parse_slack()<br/>Bytes to Object"]:::major-edit  
        SendReply["send_reply()<br/>API + Tracing"]:::major-edit
    end
    
    slack --> SlackClass
    slack --> ParseFunc
    slack --> SendReply
    types --> slack
    telegram -.-> slack
    
    subgraph Legend
        L1[Major Edit]:::major-edit
        L2[Minor Edit]:::minor-edit  
        L3[Context/No Edit]:::context
    end
    
    classDef major-edit fill:#90EE90
    classDef minor-edit fill:#87CEEB  
    classDef context fill:#FFFFFF
Loading

Notes

Summary by CodeRabbit

  • New Features
    • Added comprehensive support for handling Slack messages and events, including parsing, representing, and interacting with Slack event and slash command payloads.
    • Introduced the ability to send replies to Slack messages directly from the application.
    • Enabled asynchronous processing of Slack message data within the app’s data handling system.
  • Enhancements
    • Added new interfaces for Slack messaging and services, enabling integration with Slack alongside existing messaging platforms.

Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Contributor

coderabbitai bot commented Aug 8, 2025

Walkthrough

Slack messaging support has been integrated into the Agentuity SDK. This includes new data structures and interfaces for Slack events and messages, a Slack class for message abstraction and replies, and utility functions for parsing and sending Slack messages. Public exports and interface contracts were updated to support Slack alongside existing messaging platforms. The Data class was extended to asynchronously parse Slack messages from raw data.

Changes

Cohort / File(s) Change Summary
Slack IO Integration
agentuity/io/slack.py
Introduces Slack event/message data classes, the Slack class implementing SlackMessageInterface, async reply sending with OpenTelemetry tracing, and the parse_slack function for parsing Slack payloads. Handles authorization, error cases, and HTTP interactions for replies.
IO Module Exports
agentuity/io/__init__.py
Imports and exports Slack and parse_slack from .slack, updating the __all__ list for public API exposure.
Server Messaging Interfaces
agentuity/server/types.py
Adds SlackMessageInterface and SlackServiceInterface abstract base classes, updates DataInterface with an async slack() method, defining required properties and reply method signatures for Slack messaging.
Server Data Handling
agentuity/server/data.py
Adds async method slack() to Data class that reads raw bytes and returns a parsed Slack message object using parse_slack.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AgentuitySDK
    participant SlackAPI

    Client->>AgentuitySDK: Sends Slack event/message payload (raw bytes)
    AgentuitySDK->>AgentuitySDK: parse_slack(data)
    AgentuitySDK->>AgentuitySDK: Create Slack object
    Client->>AgentuitySDK: Calls Slack.send_reply(req, ctx, reply)
    AgentuitySDK->>SlackAPI: POST reply via Agentuity Slack API
    SlackAPI-->>AgentuitySDK: Response (success/failure)
    AgentuitySDK-->>Client: Reply sent status
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–20 minutes

Possibly related PRs

  • [AGENT-489] Telegram IO #83: Adds Telegram message handling and integration analogous to this Slack integration, sharing similar structural and interface patterns.

Suggested reviewers

  • jsw324
  • jhaynie

Poem

A rabbit hops with code so neat,
Now Slack and Agentuity meet!
Payloads parsed and messages sent,
With tracing lines and intent.
Across the wire, replies will fly—
🐇✨ Slack support is now nearby!
Hooray for code that multiplies!


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 21957d3 and 67f0658.

📒 Files selected for processing (1)
  • agentuity/server/data.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • agentuity/server/data.py
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1754659597-add-slack-io

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai bot requested review from jhaynie and jsw324 August 8, 2025 13:33
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (2)
agentuity/server/types.py (1)

96-100: Add a docstring for the new slack() accessor

All other accessors (email(), discord(), telegram()) are self-documenting via naming, but a short description of the expected return (SlackMessageInterface) would improve IDE hints and keep the interface symmetrical.

agentuity/io/slack.py (1)

168-176: thread_ts property ignores slash-command payloads

When handling slash-command (slack-message) inputs, thread_ts might be present on the root payload, but the current implementation only inspects event payloads.
Consider:

if self._message_payload:
    return getattr(self._message_payload, "thread_ts", None)

to provide consistent access across message types.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 626e924 and c280f09.

📒 Files selected for processing (3)
  • agentuity/io/__init__.py (1 hunks)
  • agentuity/io/slack.py (1 hunks)
  • agentuity/server/types.py (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
agentuity/server/types.py (1)
agentuity/io/slack.py (7)
  • message_type (116-117)
  • token (120-121)
  • team_id (124-125)
  • text (186-191)
  • user (194-199)
  • channel (202-207)
  • send_reply (335-390)
agentuity/io/slack.py (1)
agentuity/server/types.py (26)
  • AgentRequestInterface (21-39)
  • AgentContextInterface (42-56)
  • SlackMessageInterface (310-349)
  • agentId (45-46)
  • channel (338-339)
  • text (70-71)
  • text (162-163)
  • text (275-276)
  • text (328-329)
  • data (24-25)
  • data (109-110)
  • data (120-121)
  • get (38-39)
  • user (333-334)
  • token (318-319)
  • team_id (323-324)
  • message_type (313-314)
  • metadata (34-35)
  • api_key (55-56)
  • base_url (50-51)
  • send_reply (220-226)
  • send_reply (231-234)
  • send_reply (284-291)
  • send_reply (304-307)
  • send_reply (342-349)
  • send_reply (354-357)
🔇 Additional comments (2)
agentuity/io/__init__.py (1)

2-4: Public-API addition looks good

Slack and parse_slack are properly re-exported; nothing else to address here.

agentuity/io/slack.py (1)

369-389: OpenTelemetry status API changed in 1.17+

trace.Status is deprecated; use:

from opentelemetry.trace import Status, StatusCode
...
span.set_status(Status(StatusCode.OK))

to avoid runtime warnings / forward-compatibility breaks.

Comment on lines +17 to +26
class SlackReplyPayload:
"""
Payload structure for Slack reply requests.
"""
agentId: str
channel: str
text: Optional[str] = None
blocks: Optional[str] = None
thread_ts: Optional[str] = None

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Allow structured blocks in the reply payload

blocks can be a list of block objects, yet the dataclass types it as Optional[str].
Typing it as Optional[list | dict | str] (or Any) prevents mypy errors when callers pass the canonical list form.

-    blocks: Optional[str] = None
+    blocks: Optional[Union[list, dict, str]] = None

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In agentuity/io/slack.py around lines 17 to 26, the SlackReplyPayload class
types the blocks attribute as Optional[str], but blocks can be a list or dict
representing structured block objects. Change the type annotation of blocks to
Optional[list | dict | str] or use Any to correctly reflect the possible types
and prevent mypy type errors when callers pass the canonical list form.

Comment on lines +335 to +341
async def send_reply(
self,
req: AgentRequestInterface,
ctx: AgentContextInterface,
reply: Union[str, dict],
options: dict = {}
) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Replace mutable default argument

options: dict = {} risks state bleed across invocations. Use None sentinel instead:

-        options: dict = {}
+        options: dict | None = None

and initialise with options = options or {}.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async def send_reply(
self,
req: AgentRequestInterface,
ctx: AgentContextInterface,
reply: Union[str, dict],
options: dict = {}
) -> None:
async def send_reply(
self,
req: AgentRequestInterface,
ctx: AgentContextInterface,
reply: Union[str, dict],
options: dict | None = None
) -> None:
🤖 Prompt for AI Agents
In agentuity/io/slack.py around lines 335 to 341, the method send_reply uses a
mutable default argument options: dict = {}, which can cause state to persist
across calls. Change the default value of options to None and inside the method
initialize it with options = options or {} to avoid shared mutable state.

Comment on lines +393 to +419
async def parse_slack(data: bytes, message_type: str = 'slack-event') -> Slack:
"""
Parse a slack message from bytes and return a Slack object.

Args:
data: The raw bytes data containing the Slack message.
message_type: The type of message ('slack-event' or 'slack-message').

Returns:
A Slack object representing the parsed message.

Raises:
ValueError: If the data cannot be parsed as a valid Slack message.
"""
try:
msg_data = json.loads(data.decode('utf-8'))

if message_type == 'slack-event':
payload = SlackEventPayload(msg_data)
if not payload.token or not payload.type or not payload.team_id:
raise ValueError("Invalid Slack event: missing required fields")
else:
payload = SlackMessagePayload(msg_data)
if not payload.token or not payload.team_id or not payload.channel_id or not payload.user_id:
raise ValueError("Invalid Slack message: missing required fields")

return Slack(payload, message_type)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

parse_slack assumes JSON – slash commands arrive url-encoded

Slash-command requests (application/x-www-form-urlencoded) will fail JSON decoding.
Either branch on message_type or attempt urllib.parse.parse_qs fallback before raising.

if content_type == "application/x-www-form-urlencoded":
    msg_data = dict(parse_qsl(data.decode()))
🤖 Prompt for AI Agents
In agentuity/io/slack.py between lines 393 and 419, the parse_slack function
currently assumes the input data is JSON, which causes failure when handling
slash-command requests that are url-encoded. To fix this, modify the function to
check the content type or message_type and if it indicates a url-encoded form,
decode the data using urllib.parse.parse_qsl to convert it into a dictionary
before processing. This fallback should be implemented before raising a
ValueError to properly handle both JSON and url-encoded inputs.

Comment on lines +309 to +349

class SlackMessageInterface(ABC):
@property
@abstractmethod
def message_type(self) -> str:
pass

@property
@abstractmethod
def token(self) -> str:
pass

@property
@abstractmethod
def team_id(self) -> str:
pass

@property
@abstractmethod
def text(self) -> str:
pass

@property
@abstractmethod
def user(self) -> str:
pass

@property
@abstractmethod
def channel(self) -> str:
pass

@abstractmethod
async def send_reply(
self,
request: "AgentRequestInterface",
context: "AgentContextInterface",
reply: str,
options: dict = None,
) -> None:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Broaden reply type in the interface

SlackMessageInterface.send_reply() restricts reply to str, yet the concrete implementation in agentuity/io/slack.py also accepts dict (text + blocks).
Adopt Union[str, dict] here so code typed against the interface can legally send rich-format payloads.

-        reply: str,
+        reply: Union[str, dict],

Also change the default for options from None instead of {} to avoid the mutable-default trap.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class SlackMessageInterface(ABC):
@property
@abstractmethod
def message_type(self) -> str:
pass
@property
@abstractmethod
def token(self) -> str:
pass
@property
@abstractmethod
def team_id(self) -> str:
pass
@property
@abstractmethod
def text(self) -> str:
pass
@property
@abstractmethod
def user(self) -> str:
pass
@property
@abstractmethod
def channel(self) -> str:
pass
@abstractmethod
async def send_reply(
self,
request: "AgentRequestInterface",
context: "AgentContextInterface",
reply: str,
options: dict = None,
) -> None:
pass
class SlackMessageInterface(ABC):
@property
@abstractmethod
def message_type(self) -> str:
pass
@property
@abstractmethod
def token(self) -> str:
pass
@property
@abstractmethod
def team_id(self) -> str:
pass
@property
@abstractmethod
def text(self) -> str:
pass
@property
@abstractmethod
def user(self) -> str:
pass
@property
@abstractmethod
def channel(self) -> str:
pass
@abstractmethod
async def send_reply(
self,
request: "AgentRequestInterface",
context: "AgentContextInterface",
- reply: str,
+ reply: Union[str, dict],
options: dict = None,
) -> None:
pass
🤖 Prompt for AI Agents
In agentuity/server/types.py between lines 309 and 349, update the send_reply
method in SlackMessageInterface to accept reply as Union[str, dict] instead of
just str to allow rich-format payloads, and change the default value of options
parameter from an empty dict to None to avoid mutable default argument issues.

Comment on lines +352 to +357
class SlackServiceInterface(ABC):
@abstractmethod
async def send_reply(
self, agent_id: str, channel: str, text: str, options: dict = None
) -> None:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Align service signature with message interface

For the same reason as above, allow rich text/blocks objects:

-    async def send_reply(
-        self, agent_id: str, channel: str, text: str, options: dict = None
+    async def send_reply(
+        self, agent_id: str, channel: str, text: Union[str, dict], options: dict | None = None
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class SlackServiceInterface(ABC):
@abstractmethod
async def send_reply(
self, agent_id: str, channel: str, text: str, options: dict = None
) -> None:
pass
class SlackServiceInterface(ABC):
@abstractmethod
async def send_reply(
self, agent_id: str, channel: str, text: Union[str, dict], options: dict | None = None
) -> None:
pass
🤖 Prompt for AI Agents
In agentuity/server/types.py around lines 352 to 357, the send_reply method in
SlackServiceInterface currently only accepts a plain text string for the
message. To align with the message interface and support rich content, modify
the method signature to accept both rich text and blocks objects, allowing more
flexible message formatting. Update the parameters to include options for rich
text or blocks instead of just a plain text string.

- Add missing slack() method to Data class following same pattern as telegram(), email(), discord()
- This resolves the 'Can't instantiate abstract class Data with abstract method slack' errors
- Fixes 57 test failures and 33 errors in CI for Python 3.11 and 3.12

Co-Authored-By: [email protected] <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c280f09 and 21957d3.

📒 Files selected for processing (1)
  • agentuity/server/data.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
agentuity/server/data.py (2)
agentuity/server/types.py (1)
  • slack (98-99)
agentuity/io/slack.py (1)
  • parse_slack (393-423)
🪛 GitHub Check: Deploy
agentuity/server/data.py

[failure] 418-418: Ruff (F821)
agentuity/server/data.py:418:31: F821 Undefined name SlackMessageInterface

🪛 GitHub Actions: Run Tests
agentuity/server/data.py

[error] 418-418: ESLint: Undefined name SlackMessageInterface (F821) at line 418.

🪛 GitHub Actions: Build
agentuity/server/data.py

[error] 418-418: Ruff: Undefined name SlackMessageInterface (F821)

@@ -414,6 +414,12 @@

data_bytes = await self.binary()
return await parse_telegram(data_bytes)

async def slack(self) -> "SlackMessageInterface":
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Fix Ruff F821: import SlackMessageInterface and drop quotes in annotation

Ruff flags SlackMessageInterface as undefined. Import it from agentuity.server.types and use a non-string annotation to satisfy the linter.

Apply:

-    async def slack(self) -> "SlackMessageInterface":
+    async def slack(self) -> SlackMessageInterface:

Also add the missing import at the top of this file:

 from agentuity.server.types import (
     DataInterface,
     EmailInterface,
     DiscordMessageInterface,
     TelegramMessageInterface,
+    SlackMessageInterface,
 )

Run to verify the import and annotation are present:


🏁 Script executed:

#!/bin/bash
rg -n $'from agentuity.server.types import \\([\\s\\S]*SlackMessageInterface' agentuity/server/data.py
rg -n $'^\\s*async def slack\\(self\\) -> SlackMessageInterface' agentuity/server/data.py

Length of output: 188


🏁 Script executed:

#!/bin/bash
# Check all occurrences of SlackMessageInterface in the file
rg -n 'SlackMessageInterface' agentuity/server/data.py

# Show the async def slack snippet with context
rg -n '^ *async def slack' -A2 agentuity/server/data.py

# Show the import block from agentuity.server.types
rg -n '^from agentuity.server.types import' -A5 agentuity/server/data.py

Length of output: 517


Add missing import and update annotation for SlackMessageInterface

The slack method is still using a string annotation and SlackMessageInterface isn’t imported. Please update as follows in agentuity/server/data.py:

• At the top import block, include SlackMessageInterface:

 from agentuity.server.types import (
     DataInterface,
     EmailInterface,
     DiscordMessageInterface,
     TelegramMessageInterface,
+    SlackMessageInterface,
 )

• Change the method signature to use the real type instead of a string:

-    async def slack(self) -> "SlackMessageInterface":
+    async def slack(self) -> SlackMessageInterface:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async def slack(self) -> "SlackMessageInterface":
# ── at the top of agentuity/server/data.py ──
from agentuity.server.types import (
DataInterface,
EmailInterface,
DiscordMessageInterface,
TelegramMessageInterface,
SlackMessageInterface,
)
# ── update the method signature at line 418 ──
async def slack(self) -> SlackMessageInterface:
🧰 Tools
🪛 GitHub Check: Deploy

[failure] 418-418: Ruff (F821)
agentuity/server/data.py:418:31: F821 Undefined name SlackMessageInterface

🪛 GitHub Actions: Run Tests

[error] 418-418: ESLint: Undefined name SlackMessageInterface (F821) at line 418.

🪛 GitHub Actions: Build

[error] 418-418: Ruff: Undefined name SlackMessageInterface (F821)

🤖 Prompt for AI Agents
In agentuity/server/data.py at line 418, the slack method uses a string
annotation for SlackMessageInterface and the interface is not imported. Fix this
by adding an import statement for SlackMessageInterface at the top of the file
and update the method signature to use SlackMessageInterface directly as the
return type annotation instead of a string.

Comment on lines +421 to +422
data_bytes = await self.binary()
return await parse_slack(data_bytes)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Support both Slack payload types (event and message) with a safe fallback

Currently this always parses as 'slack-event', breaking 'slack-message' payloads. Try event first, then fall back to message. This matches the PR’s goal to support both payload types.

Apply:

-        data_bytes = await self.binary()
-        return await parse_slack(data_bytes)
+        data_bytes = await self.binary()
+        try:
+            return await parse_slack(data_bytes, 'slack-event')
+        except ValueError as e_event:
+            try:
+                return await parse_slack(data_bytes, 'slack-message')
+            except ValueError as e_msg:
+                raise ValueError(
+                    f"Slack parsing failed for both event and message payloads; "
+                    f"event_error={e_event}; message_error={e_msg}"
+                )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
data_bytes = await self.binary()
return await parse_slack(data_bytes)
data_bytes = await self.binary()
try:
return await parse_slack(data_bytes, 'slack-event')
except ValueError as e_event:
try:
return await parse_slack(data_bytes, 'slack-message')
except ValueError as e_msg:
raise ValueError(
f"Slack parsing failed for both event and message payloads; "
f"event_error={e_event}; message_error={e_msg}"
)
🤖 Prompt for AI Agents
In agentuity/server/data.py around lines 421 to 422, the code currently parses
the payload only as a 'slack-event', which fails for 'slack-message' payloads.
Modify the code to first attempt parsing as a 'slack-event', and if that fails,
safely fall back to parsing as a 'slack-message'. Implement this by trying the
event parse in a try-except block and on exception, parse as a message to
support both payload types.

- Add SlackMessageInterface to imports in data.py following existing pattern
- Resolves F821 undefined name error in CI linting stage

Co-Authored-By: [email protected] <[email protected]>
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.

0 participants