Skip to content

feat(messages): forward batches and auto-preserve albums#129

Merged
chigwell merged 4 commits into
chigwell:mainfrom
samplec0de:feat/forward-multi-and-grouped-id
May 22, 2026
Merged

feat(messages): forward batches and auto-preserve albums#129
chigwell merged 4 commits into
chigwell:mainfrom
samplec0de:feat/forward-multi-and-grouped-id

Conversation

@samplec0de
Copy link
Copy Markdown
Contributor

Summary

Three related changes to make forwarding work well in agent / MCP-client use:

  1. forward_message accepts Union[int, List[int]]. Passing a list of ids in a single call lets Telethon's forward_messages preserve Telegram album grouping (messages sharing grouped_id arrive as one grouped album, not detached items).

  2. list_messages and get_message_context include grouped_id in each record when the message is part of an album. Callers can detect album membership programmatically (it was not exposed before).

  3. New forward_messages tool (plural) with a pure List[int] signature, plus server-side album auto-expansion in forward_message: when called with a single int and the target message has a grouped_id, the server now fetches a small contiguous window of neighbour ids, filters siblings sharing the same grouped_id, and forwards them all in one Telethon call. An expand_album: bool = True flag lets callers opt out for the rare case of forwarding one specific item out of an album.

Motivation

When driven by a small MCP-client model (e.g. gpt-oss-20b in LM Studio), the upstream behavior reliably broke for multi-photo channel posts: the model would call forward_message with the album's anchor id only and the destination received one detached photo. Tool-description directives and skill prompts did not move the needle.

The two failure modes addressed:

  • No way to express "forward N items as a group" — the single-int signature forced loops, which break atomicity, defeat album grouping, and trip flood-wait limits.
  • No way for the agent to detect an album — without grouped_id exposure, a client cannot tell that a message is part of a group, so it cannot construct the list even if the tool accepted one.

The server-side auto-expand path (3) means the most common case ("forward this post") works correctly without any client intelligence at all.

Backward compatibility

  • forward_message(message_id=<int>, ...) — same call signature, but now expands albums by default. Opt out with expand_album=False to restore the previous one-message behavior.
  • forward_message(message_id=<list>, ...) — new capability, no behavior change for any existing caller.
  • forward_messages is new; no conflict.
  • grouped_id in list_messages / get_message_context is an additive field that only appears when non-null; existing consumers ignoring unknown keys are unaffected.

Commits

  • aaa4f28 feat(messages): forward list of ids and expose grouped_id
  • 095d00b feat(messages): add forward_messages (batch) tool and strengthen guidance
  • 85a8f39 feat(forward_message): auto-expand albums on single-int forwards

Testing notes

Verified end-to-end against a real personal account: forwarding a 3-photo post from a public channel via the auto-expand path delivers one grouped album with the original "Forwarded from <source>" header to the destination, matching the result of forwarding the same post manually from the Telegram client.

Happy to split into separate PRs or rework the API surface if that fits the project direction better.

`forward_message` now accepts `Union[int, List[int]]` for `message_id`.
When given a list, Telethon's `forward_messages` preserves Telegram album
grouping (messages sharing a `grouped_id`) in the destination chat, which
was impossible with the previous single-int signature.

`list_messages` and `get_message_context` now include `grouped_id` in
each record when present, so callers can detect album membership and
forward all parts atomically.

Motivated by an agent use case: forwarding multi-photo posts (3+ photos
with a caption) produced one detached photo at a time. Without
`grouped_id` exposure there was no way to discover sibling messages, and
without list-id forward there was no way to preserve the album.
…ance

Small models hosting the MCP client often pick the simpler branch of
`Union[int, List[int]]` and fall back to looping single-int forwards,
defeating the album-grouping preservation added in the previous commit.

Two changes to nudge them toward the correct path:

1. `forward_message`: rewrite the docstring as a directive ("USE A LIST
   WHENEVER FORWARDING >1 MESSAGE") with an Args block FastMCP parses
   for per-parameter descriptions. The model now sees the rule front and
   center in the tool description, not buried in a paragraph.

2. New tool `forward_messages` (plural) with a pure `List[int]` signature
   — no Union, no anyOf in the resulting JSON Schema. A list-only schema
   is unambiguous: the model has no "int branch" to fall back on.

Backward-compatible: `forward_message` still accepts both `int` and
`List[int]`.
Smaller MCP-client models reliably fail to check grouped_id before
forwarding and end up calling forward_message with the album anchor id
only — delivering one detached photo instead of the full post. Skill
prompts and tool-description directives don't move the needle on this.

Move the smarts server-side: when forward_message receives a single
int and the target message has a grouped_id, fetch a small window of
nearby ids (albums are allocated contiguously), filter siblings with
the same grouped_id, and forward them all in one Telethon call. The
destination receives the full grouped album intact.

Adds expand_album: bool = True so callers can opt out for the rare
case of forwarding exactly one item out of an album. List inputs are
left untouched — they remain the explicit batch path.

Net effect: the agent can be naive ("forward this post") and the
server still delivers the album correctly. Result message now states
when an expansion happened so the user is aware.
@chigwell
Copy link
Copy Markdown
Owner

chigwell commented May 22, 2026

Hey @samplec0de, thank you for the contribution! Could I please ask you to fix the black formatting so the CI tests will pass? Thank you!

@samplec0de samplec0de force-pushed the feat/forward-multi-and-grouped-id branch from b332f2e to dfc12ec Compare May 22, 2026 16:28
@chigwell chigwell merged commit cf20e55 into chigwell:main May 22, 2026
4 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.

2 participants