Repository navigation
feat(mcp): add create_thread capability for agent-initiated thread creation - #1532
Closed
Alexguitar-zz wants to merge 1 commit into
Closed
Alexguitar-zz wants to merge 1 commit into
Alexguitar-zz wants to merge 1 commit into
Conversation
…eation Agents currently have no supported way to create threads in a target channel. The only path was direct Discord REST API calls from agent exec scripts, which risks using the wrong bot's token (identity mix-ups) and leaks credentials into logs and LLM context. This adds a `create_thread` tool to the OAB MCP Facade, backed by a new `ThreadSource` capability source. The adapter uses its own authenticated HTTP client, so the thread owner is always the bot itself — no token is exposed to the agent subprocess. Changes: - `ChatAdapter::create_thread_in_channel`: new trait method (default: unsupported) for standalone thread creation without a trigger message - `DiscordAdapter::create_thread_in_channel`: Discord implementation using serenity's `ChannelId::create_thread` + starter message via `send_message` - `ThreadSource`: new `CapabilitySource` impl exposing `create_thread` via the MCP facade's `execute_capability` dispatch - `main.rs`: register `ThreadSource` when a Discord adapter is available, consolidating the shared adapter construction (previously duplicated for the cron scheduler) The tool accepts `channel_id`, `name`, and optional `content`, and returns the new thread's channel ID. Title is truncated at 100 chars (Discord limit) with char-boundary safety for multi-byte text (中文/Emoji). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Contributor
|
Caution This PR is missing a Discord Discussion URL in the body. All PRs must reference a prior Discord discussion to ensure community alignment before implementation. Please edit the PR description to include a link like: |
|
🔒 Auto-closing: this PR has had the If you'd like to continue working on this, please submit a new PR and link to this one if necessary. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem does this solve?
Agents currently have no supported way to create threads in a target channel. The only path was direct Discord REST API calls from agent exec scripts (e.g.
requests.post('/channels/{id}/threads')), which has two safety issues:DISCORD_BOT_TOKENenv var), causing threads to be created under the wrong bot's identity. Thread ownership is determined by the creating token and cannot be changed afterward.This PR closes that gap by routing thread creation through the adapter's own authenticated HTTP client. The agent calls
execute_capabilitywithchannel_id,name, and optionalcontent— no token is ever exposed to the agent subprocess.Closes #
Discord Discussion URL:
Review Contract
Goal
Agents can create threads in a target channel via the MCP facade's
execute_capabilitywithout handling platform credentials. The thread owner is always the bot itself — no token is exposed to the agent subprocess.Non-goals
create_forum_post) — separate API surface, not included.Accepted Residual Risks
create_threadtool is available to all agents with access to the MCP facade. An operator who registers the facade with a Discord adapter implicitly grants thread creation to all connected agents. Mitigation: the tool only creates threads in channels the bot already has permission to; Discord's channel permission model is the enforcement boundary.send_messagefor the starter content is a separate API call after thread creation. If it fails, the thread exists but is empty. The error is returned to the caller; no partial state is hidden.Acceptance Criteria
ChatAdapter::create_thread_in_channeldefault impl returns "not supported" — existing adapters compile unchangedDiscordAdapter::create_thread_in_channelcreates a public thread viaChannelId::create_threadand sends starter content viasend_messageThreadSourceadvertisescreate_threadintools()and dispatches viacall()— returns(thread_id, parent_id, platform)on success,(error, is_error=true)on failurecargo checkpassescargo clippy -- -D warningspassescargo test— 18/18 binary tests pass (1 pre-existing failure insecrets::tests::resolve_exec_nonzero_exitunrelated to this PR, confirmed failing onmain)Follow-ups
create_thread_in_channel(Slack supports thread creation viaconversations.create+ posting the starter message)At a Glance
Prior Art & Industry Research
OpenClaw:
Not applicable — OpenClaw is a game-engine project, not a chat-to-agent harness. No thread-creation abstraction exists.
Hermes Agent:
Not applicable — Hermes Agent has been removed from OpenAB's supported agents (PR #1523). No prior thread-creation capability existed in its integration.
Other references:
POST /channels/{channel_id}/threadswithname,type, and optionalcontentfields.ChannelId::create_thread— wraps the above endpoint;CreateThreadbuilder sets name, auto-archive duration, and thread type.ChatAdapter::create_thread(from-message variant) already uses serenity's authenticated HTTP client; this PR adds the standalone variant using the same security model.Proposed Solution
Add a new
create_thread_in_channelmethod to theChatAdaptertrait with a default "unsupported" implementation, and implement it forDiscordAdapterusing serenity'sChannelId::create_thread(start thread without message) followed bysend_messagefor the starter content.Expose this via a new
ThreadSourcecapability source registered with the MCP facade when a Discord adapter is available. The agent callsexecute_capability("create_thread", {channel_id, name, content})— the facade dispatches toThreadSource, which callscreate_thread_in_channelon the adapter. The adapter uses its own authenticated HTTP client, so the thread owner is the bot itself.Consolidate the shared Discord adapter construction in
main.rs(previously duplicated: once for the cron scheduler, once for the MCP facade block) into a single earlier construction site.Why this approach?
CapabilitySourceinfrastructure; no new transport, no new config section, no per-session proxy.Httpclient is constructed at startup from the bot's config; the agent subprocess never sees it. This is the same security model as the existingcreate_thread(from-message) andsend_messagemethods.CreateThreadbuilder doesn't support acontentfield for the "without message" variant. Creating the thread then sending a message via the existingsend_messagemethod is simpler than a raw HTTP call and reuses existing message-splitting logic.Alternatives Considered
session/create_thread): rejected — ACP is an agent-protocol surface, not a platform-adapter surface; thread creation is platform-specific and belongs in the adapter layer.CreateThreadbuilder doesn't expose thecontentfield; a raw HTTP call would bypass serenity's rate limiter and error handling.Validation
cargo checkpassescargo clippy -- -D warningspassescargo test— 18/18 binary tests pass (1 pre-existing failure insecrets::tests::resolve_exec_nonzero_exitunrelated to this PR, confirmed failing onmain)execute_capabilitywithcreate_threadand verifies thread appears in target channel with correct bot identityGenerated with Devin