Summary
The Slack integration passes the thread to the agent as a list of plain text bodies, with all per-message metadata (timestamps, authors), and all envelope metadata (channel ID, team ID, workspace), stripped. As a result, an agent operating from a Slack trigger cannot construct Slack permalinks for the messages it cites — a common need when the trigger is "summarize this thread into a GitHub issue" or similar.
Reproduction
- Configure a microagent (or just a system prompt) that asks the agent to "include a Slack permalink for the originating thread message" in its output.
- Trigger via Slack mention.
- Observe that the agent emits a "Limitations: Slack permalinks not included because I wasn't provided with the Slack event payload data" warning, and produces output without permalinks.
Root cause
In integrations/slack/slack_view.py:SlackView._get_instructions() (or its successor), the agent receives exactly two strings:
user_message: the trigger message text with the bot mention stripped (e.g., literally slack-to-issue).
conversation_instructions: the rendered Jinja template user_message_conversation_instructions.j2.
The template is built with:
text_messages = [m['text'] for m in messages if m.get('text')]
conversation_instructions = template.render(
messages=text_messages,
username=user_info.slack_display_name,
conversation_url=CONVERSATION_URL,
)
And the template body itself is just:
When performing your task, make sure to reference the additional context if needed.
These are a list of text messages attached in order of most recent.
{% for message in messages %}
{{ message }}
{% if not loop.last %}\n\n{% endif %}
{% endfor %}
If you made code changes, when you're done make sure to:
...
So the agent has access to the text bodies only. The SlackView class has channel_id, team_id, thread_ts, and message_ts as attributes — used to fetch the thread from Slack's API — but they are never templated into the agent context.
Why this matters
Slack-triggered agents commonly need to:
- Cite specific thread messages with a permalink (so the resulting GitHub issue / Linear ticket / Jira card has a back-reference for human readers).
- Distinguish authorship (who said what in the thread).
- Reference timestamps for incident correlation.
None of these are doable today.
Suggested fix
Either (a) include channel_id, team_id, parent thread_ts, and a per-message list of (ts, user, text) tuples in the existing template, or (b) pass them as a separate slack_metadata block alongside the messages text. Either way the agent can then construct permalinks with the documented Slack URL scheme:
- Root / parent:
https://<workspace>.slack.com/archives/<channel>/p<ts_no_dot>
- Thread reply:
https://<workspace>.slack.com/archives/<channel>/p<reply_ts_no_dot>?thread_ts=<parent_ts_raw>&ctype=app
(The ts_no_dot form is the timestamp with the dot removed, in the path; the thread_ts_raw form keeps the dot, in the query string.)
Bonus observation
The same user_message_conversation_instructions.j2 template ends with code-change / commit / PR-workflow boilerplate ("If you made code changes, when you're done make sure to: 1. Commit ... 2. Ask the user ..."). For non-PR triggers like a Slack-to-issue or Slack-to-summary use case, this is irrelevant context that may mildly confuse the agent. Consider gating that block on whether the conversation actually involved code changes, or splitting the template by trigger type.
Environment
- OpenHands self-hosted via the Replicated VM path (single EC2,
OpenHands-Cloud/terraform/aws/)
- Image: whatever ships in the late-April 2026 Replicated release
Happy to PR a fix if pointed at the right module.
Summary
The Slack integration passes the thread to the agent as a list of plain text bodies, with all per-message metadata (timestamps, authors), and all envelope metadata (channel ID, team ID, workspace), stripped. As a result, an agent operating from a Slack trigger cannot construct Slack permalinks for the messages it cites — a common need when the trigger is "summarize this thread into a GitHub issue" or similar.
Reproduction
Root cause
In
integrations/slack/slack_view.py:SlackView._get_instructions()(or its successor), the agent receives exactly two strings:user_message: the trigger message text with the bot mention stripped (e.g., literallyslack-to-issue).conversation_instructions: the rendered Jinja templateuser_message_conversation_instructions.j2.The template is built with:
And the template body itself is just:
So the agent has access to the text bodies only. The
SlackViewclass haschannel_id,team_id,thread_ts, andmessage_tsas attributes — used to fetch the thread from Slack's API — but they are never templated into the agent context.Why this matters
Slack-triggered agents commonly need to:
None of these are doable today.
Suggested fix
Either (a) include
channel_id,team_id, parentthread_ts, and a per-message list of(ts, user, text)tuples in the existing template, or (b) pass them as a separateslack_metadatablock alongside the messages text. Either way the agent can then construct permalinks with the documented Slack URL scheme:https://<workspace>.slack.com/archives/<channel>/p<ts_no_dot>https://<workspace>.slack.com/archives/<channel>/p<reply_ts_no_dot>?thread_ts=<parent_ts_raw>&ctype=app(The
ts_no_dotform is the timestamp with the dot removed, in the path; thethread_ts_rawform keeps the dot, in the query string.)Bonus observation
The same
user_message_conversation_instructions.j2template ends with code-change / commit / PR-workflow boilerplate ("If you made code changes, when you're done make sure to: 1. Commit ... 2. Ask the user ..."). For non-PR triggers like a Slack-to-issue or Slack-to-summary use case, this is irrelevant context that may mildly confuse the agent. Consider gating that block on whether the conversation actually involved code changes, or splitting the template by trigger type.Environment
OpenHands-Cloud/terraform/aws/)Happy to PR a fix if pointed at the right module.