Skip to content

fix(telegram): forum topic replies route to root chat + ACP spawn fails from forum topics#56060

Merged
obviyus merged 10 commits into
openclaw:mainfrom
one27001:feat/telegram-child-thread-binding
Mar 31, 2026
Merged

fix(telegram): forum topic replies route to root chat + ACP spawn fails from forum topics#56060
obviyus merged 10 commits into
openclaw:mainfrom
one27001:feat/telegram-child-thread-binding

Conversation

@one27001

@one27001 one27001 commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Fix 1: forum topic replies route to root chat

Regression from #24152. The cross-channel guard set lastThreadId = turnSourceThreadId, but Telegram never sets turnSourceThreadId — the thread ID lives in session context. All forum topic replies silently lost message_thread_id and landed in root chat.

Fix: Fall back to session threadId when turn-source channel + destination match the session. Extra to check prevents shared-session race (Codex P1, 17c62aa).

Fix 2: ACP spawn from forum topics fails

sessions_spawn(runtime=acp, thread=true) from a forum topic errored with "Telegram recipient must be a numeric chat ID". Three causes:

  • extractExplicitGroupId returned topic-qualified IDs (e.g. -100...:topic:1264)
  • agentGroupId never wired in inline tool dispatch
  • Thread binding produced conversationIds the delivery pipeline can't parse for Telegram topics

Fix: Strip :topic:.* from group IDs, wire agentGroupId, and skip thread binding for Telegram forum topics. The delivery plan already routes correctly via origin.to + origin.threadId without binding — child output goes back to the same topic.

Why skip binding? resolveConversationDeliveryTarget isn't Telegram-topic-aware. With binding, it produces channel:-prefixed targets that parseTelegramTarget rejects. Without binding, delivery falls through to the requester's origin which already works. The requestThreadBinding = false guard is intentional — Codex flagged it as P1, but it is the fix.

Tests

  • 4 regression tests (threadId fallback) + 9 new tests (extractExplicitGroupId)
  • acp-spawn 37/37 passed, group-id 9/9 passed
  • Live tested: topic routing ✓, cross-topic movement ✓, ACP spawn with output in same topic ✓
  • Pre-existing: targets.test.ts WhatsApp import failure, thread-bindings.test.ts 1 timeout

AI-assisted

  • Marked as AI-assisted
  • Degree of testing: unit tested + live forum group testing
  • Author understands what the code does
  • Codex review: ran locally (codex review --base upstream/main), P1 findings addressed — binding path bypassed for Telegram forum topics

@openclaw-barnacle openclaw-barnacle Bot added channel: telegram Channel integration: telegram size: S labels Mar 27, 2026
@greptile-apps

greptile-apps Bot commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR extends the Telegram thread-bindings adapter to support \"child\" placement, enabling ACP subagent orchestration on Telegram forum-enabled supergroups. When a child binding is requested, the adapter creates a new forum topic via createForumTopicTelegram and binds the subagent session to the resulting chatId:topic:topicId conversation ID. The change is well-scoped to thread-bindings.ts and re-uses an existing API helper.

Key findings:

  • The existing test \"does not support child placement\" in thread-bindings.test.ts (line 61) now asserts a BINDING_CAPABILITY_UNSUPPORTED rejection that the implementation will no longer produce, causing a CI failure. This test must be updated or removed before merging.
  • When neither parentConversationId nor conversationId starts with \"-\" (e.g. a bare topic number), the fallback to groupIds[0] can silently target the wrong Telegram group in multi-group deployments without any log indication that a fallback was applied.

Confidence Score: 4/5

Not safe to merge without fixing the stale test that will cause CI failure.

One P1 finding (stale test asserting the superseded BINDING_CAPABILITY_UNSUPPORTED error code) will break the test suite. The implementation logic itself is sound for the common path, but the broken test is a blocking issue that must be resolved before merge.

extensions/telegram/src/thread-bindings.test.ts — stale "does not support child placement" test must be updated or removed.

Important Files Changed

Filename Overview
extensions/telegram/src/thread-bindings.ts Adds "child" to the adapter's placements capability and wires it to createForumTopicTelegram; group ID resolution contains a silent fallback that may misroute in multi-group configs.

Comments Outside Diff (1)

  1. extensions/telegram/src/thread-bindings.test.ts, line 61-82 (link)

    P1 Stale test now asserts the wrong error code

    This test was written to document that "child" placement was unsupported, and it expects a BINDING_CAPABILITY_UNSUPPORTED rejection. Now that "child" is included in the adapter's placements capability array, the session-binding service will no longer reject the call at the capability gate. Instead, bind will be entered and will attempt to call loadConfig() / resolveTelegramToken() / createForumTopicTelegram(), failing with a completely different error (e.g. missing token or network) — not BINDING_CAPABILITY_UNSUPPORTED. The test will fail.

    This test needs to be updated to either:

    • Be removed (if the old "unsupported" contract is no longer relevant), or
    • Be replaced with a test that mocks loadConfig/resolveTelegramToken/createForumTopicTelegram and verifies the new child-binding happy path and failure modes.
    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: extensions/telegram/src/thread-bindings.test.ts
    Line: 61-82
    
    Comment:
    **Stale test now asserts the wrong error code**
    
    This test was written to document that `"child"` placement was unsupported, and it expects a `BINDING_CAPABILITY_UNSUPPORTED` rejection. Now that `"child"` is included in the adapter's `placements` capability array, the session-binding service will no longer reject the call at the capability gate. Instead, `bind` will be entered and will attempt to call `loadConfig()` / `resolveTelegramToken()` / `createForumTopicTelegram()`, failing with a completely different error (e.g. missing token or network) — not `BINDING_CAPABILITY_UNSUPPORTED`. The test will fail.
    
    This test needs to be updated to either:
    - Be removed (if the old "unsupported" contract is no longer relevant), or
    - Be replaced with a test that mocks `loadConfig`/`resolveTelegramToken`/`createForumTopicTelegram` and verifies the new child-binding happy path and failure modes.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/telegram/src/thread-bindings.test.ts
Line: 61-82

Comment:
**Stale test now asserts the wrong error code**

This test was written to document that `"child"` placement was unsupported, and it expects a `BINDING_CAPABILITY_UNSUPPORTED` rejection. Now that `"child"` is included in the adapter's `placements` capability array, the session-binding service will no longer reject the call at the capability gate. Instead, `bind` will be entered and will attempt to call `loadConfig()` / `resolveTelegramToken()` / `createForumTopicTelegram()`, failing with a completely different error (e.g. missing token or network) — not `BINDING_CAPABILITY_UNSUPPORTED`. The test will fail.

This test needs to be updated to either:
- Be removed (if the old "unsupported" contract is no longer relevant), or
- Be replaced with a test that mocks `loadConfig`/`resolveTelegramToken`/`createForumTopicTelegram` and verifies the new child-binding happy path and failure modes.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/telegram/src/thread-bindings.ts
Line: 585-590

Comment:
**First-configured-group fallback is non-deterministic in multi-group setups**

When neither `parentConversationId` nor `conversationId` starts with `"-"` (e.g. a bare topic number like `"77"` is provided), the code silently falls back to `groupIds[0]`:

```ts
const groupIds = Object.keys(cfg?.channels?.telegram?.groups ?? {});
if (groupIds.length > 0) {
  chatId = groupIds[0];
}
```

`Object.keys` on a plain object preserves insertion order in modern JS engines, but the insertion order of a parsed JSON config is effectively the order the user wrote their config — which may have no relation to the desired target group. In a deployment with two or more Telegram groups configured, this will silently spawn the child topic in whichever group appears first in the config file, with no log message indicating that a fallback occurred.

Consider either:
1. Logging a warning that a fallback was applied (`logVerbose` is already imported), or
2. Returning `null` when the chat ID cannot be unambiguously resolved, to surface the error clearly to the orchestrator.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "feat(telegram): add child thread-binding..." | Re-trigger Greptile

Comment thread extensions/telegram/src/thread-bindings.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aa95a00f95

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread extensions/telegram/src/thread-bindings.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5a51db6000

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread extensions/telegram/src/thread-bindings.ts
@openclaw-barnacle openclaw-barnacle Bot added the agents Agent runtime and tooling label Mar 27, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6eda22c6f7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/acp-spawn.ts Outdated
@one27001 one27001 changed the title feat(telegram): add child thread-binding placement via createForumTopic [AI-assisted] feat(telegram): forum topic child thread-binding + fix reply routing to root chat [AI-assisted] Mar 28, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f5525c98eb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/infra/outbound/targets.ts Outdated
@one27001
one27001 force-pushed the feat/telegram-child-thread-binding branch from 88b27e6 to 091430d Compare March 28, 2026 08:41

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 091430d429

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/infra/outbound/targets.ts
@one27001
one27001 force-pushed the feat/telegram-child-thread-binding branch from 02e564d to f5525c9 Compare March 30, 2026 08:54
@one27001
one27001 force-pushed the feat/telegram-child-thread-binding branch from f5525c9 to 09f930f Compare March 30, 2026 09:28
@one27001 one27001 changed the title feat(telegram): forum topic child thread-binding + fix reply routing to root chat [AI-assisted] fix(telegram): forum topic replies land in root chat + enable ACP child thread spawn Mar 30, 2026
@one27001
one27001 force-pushed the feat/telegram-child-thread-binding branch from 17c62aa to 492f6db Compare March 30, 2026 09:42
@one27001

Copy link
Copy Markdown
Contributor Author

@joshp123 @obviyus ready for review when you get a chance i see you are telegram maintainers

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 492f6dbd34

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/acp-spawn.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9c411c9b3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/acp-spawn.ts Outdated
@one27001 one27001 changed the title fix(telegram): forum topic replies land in root chat + enable ACP child thread spawn fix(telegram): forum topic replies route to root chat + ACP spawn fails from forum topics Mar 30, 2026
@one27001

one27001 commented Mar 30, 2026

Copy link
Copy Markdown
Contributor Author

Scope update: Dropped createForumTopic child thread-binding after live testing — bad UX (orphan topics). Child ACP output now routes back to the same topic via requester origin. All Codex/Greptile review comments addressed. See updated description.

@joshp123 @obviyus ready for re-review.

@obviyus

obviyus commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Pushed a small follow-up on the PR branch.

Root issue in the last ACP change: Telegram forum-topic spawns were still choosing mode="session", then disabling thread binding afterward. That left a persistent ACP session without an actual bound conversation for follow-ups.

Fix: remove that special case and derive the canonical Telegram topic conversation ID up front (chatId:topic:threadId). Then the normal current-conversation binding path works, so the ACP session stays attached to the same forum topic the user started from.

Also fixed the stale targets.test.ts WhatsApp import so the branch checks pass cleanly.

one27001 and others added 10 commits March 31, 2026 10:14
Enable ACP subagent spawn on Telegram by adding "child" placement
support to the thread-bindings adapter. When a child binding is
requested, the adapter creates a new forum topic via the Telegram
Bot API and binds the subagent session to it using the canonical
chatId:topic:topicId conversation ID format.

When the ACP spawn context provides only a topic ID (not a full
group chat ID), the adapter resolves the group from the configured
Telegram groups in openclaw.json.

This mirrors the Discord adapter's child placement behavior
(thread creation + session binding) and unblocks the orchestrator
pattern on Telegram forum-enabled groups.

Closes openclaw#5737
Ref openclaw#23414
…de test

- Simplify bare-topic-ID guards in thread-bindings.ts: split into
  separate !chatId and !chatId.startsWith("-") checks, removing
  unreachable second condition
- Add regression test confirming explicit turnSourceThreadId overrides
  session lastThreadId on same channel
Codex review P1: when turnSourceTo differs from the session's stored
to, the session threadId may belong to a different chat/topic. Only
fall back to context.threadId when the destination also matches.
extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264)
instead of bare group chat IDs, breaking agentGroupId resolution.
agentGroupId was also never wired in the inline actions path.

For Telegram forum topics, skip thread binding entirely — the delivery
plan already routes correctly via requester origin (to + threadId).
Creating new forum topics per child session is unnecessary; output goes
back to the same topic the user asked from.
@obviyus
obviyus force-pushed the feat/telegram-child-thread-binding branch from 20d7a19 to 8a47841 Compare March 31, 2026 04:47

@obviyus obviyus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed latest changes; landing now.

@obviyus
obviyus merged commit f7ced43 into openclaw:main Mar 31, 2026
8 checks passed
@obviyus

obviyus commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Landed on main.

Thanks @one27001.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8a47841572

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/acp-spawn.ts
Comment on lines +388 to +393
chatId = chatId
.replace(/:topic:\d+$/i, "")
.replace(/:\d+$/i, "")
.trim();
if (/^-?\d+$/.test(chatId)) {
return normalizedThreadId ? `${chatId}:topic:${normalizedThreadId}` : chatId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Preserve topic suffix when deriving Telegram conversation IDs

Do not strip :topic:<id> unconditionally here. In the Telegram branch, the code removes any topic suffix from to/groupId and only adds it back when threadId is separately provided, so a topic-qualified target like telegram:group:-100...:topic:42 with no explicit threadId is downgraded to -100.... In that case thread=true ACP spawns bind to the root chat and follow-up delivery can route outside the intended forum topic instead of staying in the requested topic.

Useful? React with 👍 / 👎.

pgondhi987 pushed a commit to pgondhi987/openclaw that referenced this pull request Mar 31, 2026
…ne27001)

* feat(telegram): add child thread-binding placement via createForumTopic

Enable ACP subagent spawn on Telegram by adding "child" placement
support to the thread-bindings adapter. When a child binding is
requested, the adapter creates a new forum topic via the Telegram
Bot API and binds the subagent session to it using the canonical
chatId:topic:topicId conversation ID format.

When the ACP spawn context provides only a topic ID (not a full
group chat ID), the adapter resolves the group from the configured
Telegram groups in openclaw.json.

This mirrors the Discord adapter's child placement behavior
(thread creation + session binding) and unblocks the orchestrator
pattern on Telegram forum-enabled groups.

Closes openclaw#5737
Ref openclaw#23414

* fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind

* telegram: fix ACP child thread spawn with group chat ID from agentGroupId

* telegram: scope agentGroupId substitution to telegram channel only

* Telegram: fix forum topic replies routing to root chat instead of topic thread

* fix: clean up dead guard in child bind + add explicit threadId override test

- Simplify bare-topic-ID guards in thread-bindings.ts: split into
  separate !chatId and !chatId.startsWith("-") checks, removing
  unreachable second condition
- Add regression test confirming explicit turnSourceThreadId overrides
  session lastThreadId on same channel

* fix: guard threadId fallback against shared-session race

Codex review P1: when turnSourceTo differs from the session's stored
to, the session threadId may belong to a different chat/topic. Only
fall back to context.threadId when the destination also matches.

* fix(telegram): enable ACP spawn from forum topics without thread binding

extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264)
instead of bare group chat IDs, breaking agentGroupId resolution.
agentGroupId was also never wired in the inline actions path.

For Telegram forum topics, skip thread binding entirely — the delivery
plan already routes correctly via requester origin (to + threadId).
Creating new forum topics per child session is unnecessary; output goes
back to the same topic the user asked from.

* fix(acp): bind Telegram forum sessions to current topic

* fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001)

---------

Co-authored-by: openclaw <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
pgondhi987 pushed a commit to pgondhi987/openclaw that referenced this pull request Mar 31, 2026
…ne27001)

* feat(telegram): add child thread-binding placement via createForumTopic

Enable ACP subagent spawn on Telegram by adding "child" placement
support to the thread-bindings adapter. When a child binding is
requested, the adapter creates a new forum topic via the Telegram
Bot API and binds the subagent session to it using the canonical
chatId:topic:topicId conversation ID format.

When the ACP spawn context provides only a topic ID (not a full
group chat ID), the adapter resolves the group from the configured
Telegram groups in openclaw.json.

This mirrors the Discord adapter's child placement behavior
(thread creation + session binding) and unblocks the orchestrator
pattern on Telegram forum-enabled groups.

Closes openclaw#5737
Ref openclaw#23414

* fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind

* telegram: fix ACP child thread spawn with group chat ID from agentGroupId

* telegram: scope agentGroupId substitution to telegram channel only

* Telegram: fix forum topic replies routing to root chat instead of topic thread

* fix: clean up dead guard in child bind + add explicit threadId override test

- Simplify bare-topic-ID guards in thread-bindings.ts: split into
  separate !chatId and !chatId.startsWith("-") checks, removing
  unreachable second condition
- Add regression test confirming explicit turnSourceThreadId overrides
  session lastThreadId on same channel

* fix: guard threadId fallback against shared-session race

Codex review P1: when turnSourceTo differs from the session's stored
to, the session threadId may belong to a different chat/topic. Only
fall back to context.threadId when the destination also matches.

* fix(telegram): enable ACP spawn from forum topics without thread binding

extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264)
instead of bare group chat IDs, breaking agentGroupId resolution.
agentGroupId was also never wired in the inline actions path.

For Telegram forum topics, skip thread binding entirely — the delivery
plan already routes correctly via requester origin (to + threadId).
Creating new forum topics per child session is unnecessary; output goes
back to the same topic the user asked from.

* fix(acp): bind Telegram forum sessions to current topic

* fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001)

---------

Co-authored-by: openclaw <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
@one27001
one27001 deleted the feat/telegram-child-thread-binding branch March 31, 2026 13:57
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…ne27001)

* feat(telegram): add child thread-binding placement via createForumTopic

Enable ACP subagent spawn on Telegram by adding "child" placement
support to the thread-bindings adapter. When a child binding is
requested, the adapter creates a new forum topic via the Telegram
Bot API and binds the subagent session to it using the canonical
chatId:topic:topicId conversation ID format.

When the ACP spawn context provides only a topic ID (not a full
group chat ID), the adapter resolves the group from the configured
Telegram groups in openclaw.json.

This mirrors the Discord adapter's child placement behavior
(thread creation + session binding) and unblocks the orchestrator
pattern on Telegram forum-enabled groups.

Closes openclaw#5737
Ref openclaw#23414

* fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind

* telegram: fix ACP child thread spawn with group chat ID from agentGroupId

* telegram: scope agentGroupId substitution to telegram channel only

* Telegram: fix forum topic replies routing to root chat instead of topic thread

* fix: clean up dead guard in child bind + add explicit threadId override test

- Simplify bare-topic-ID guards in thread-bindings.ts: split into
  separate !chatId and !chatId.startsWith("-") checks, removing
  unreachable second condition
- Add regression test confirming explicit turnSourceThreadId overrides
  session lastThreadId on same channel

* fix: guard threadId fallback against shared-session race

Codex review P1: when turnSourceTo differs from the session's stored
to, the session threadId may belong to a different chat/topic. Only
fall back to context.threadId when the destination also matches.

* fix(telegram): enable ACP spawn from forum topics without thread binding

extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264)
instead of bare group chat IDs, breaking agentGroupId resolution.
agentGroupId was also never wired in the inline actions path.

For Telegram forum topics, skip thread binding entirely — the delivery
plan already routes correctly via requester origin (to + threadId).
Creating new forum topics per child session is unnecessary; output goes
back to the same topic the user asked from.

* fix(acp): bind Telegram forum sessions to current topic

* fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001)

---------

Co-authored-by: openclaw <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…ne27001)

* feat(telegram): add child thread-binding placement via createForumTopic

Enable ACP subagent spawn on Telegram by adding "child" placement
support to the thread-bindings adapter. When a child binding is
requested, the adapter creates a new forum topic via the Telegram
Bot API and binds the subagent session to it using the canonical
chatId:topic:topicId conversation ID format.

When the ACP spawn context provides only a topic ID (not a full
group chat ID), the adapter resolves the group from the configured
Telegram groups in openclaw.json.

This mirrors the Discord adapter's child placement behavior
(thread creation + session binding) and unblocks the orchestrator
pattern on Telegram forum-enabled groups.

Closes openclaw#5737
Ref openclaw#23414

* fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind

* telegram: fix ACP child thread spawn with group chat ID from agentGroupId

* telegram: scope agentGroupId substitution to telegram channel only

* Telegram: fix forum topic replies routing to root chat instead of topic thread

* fix: clean up dead guard in child bind + add explicit threadId override test

- Simplify bare-topic-ID guards in thread-bindings.ts: split into
  separate !chatId and !chatId.startsWith("-") checks, removing
  unreachable second condition
- Add regression test confirming explicit turnSourceThreadId overrides
  session lastThreadId on same channel

* fix: guard threadId fallback against shared-session race

Codex review P1: when turnSourceTo differs from the session's stored
to, the session threadId may belong to a different chat/topic. Only
fall back to context.threadId when the destination also matches.

* fix(telegram): enable ACP spawn from forum topics without thread binding

extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264)
instead of bare group chat IDs, breaking agentGroupId resolution.
agentGroupId was also never wired in the inline actions path.

For Telegram forum topics, skip thread binding entirely — the delivery
plan already routes correctly via requester origin (to + threadId).
Creating new forum topics per child session is unnecessary; output goes
back to the same topic the user asked from.

* fix(acp): bind Telegram forum sessions to current topic

* fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001)

---------

Co-authored-by: openclaw <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…ne27001)

* feat(telegram): add child thread-binding placement via createForumTopic

Enable ACP subagent spawn on Telegram by adding "child" placement
support to the thread-bindings adapter. When a child binding is
requested, the adapter creates a new forum topic via the Telegram
Bot API and binds the subagent session to it using the canonical
chatId:topic:topicId conversation ID format.

When the ACP spawn context provides only a topic ID (not a full
group chat ID), the adapter resolves the group from the configured
Telegram groups in openclaw.json.

This mirrors the Discord adapter's child placement behavior
(thread creation + session binding) and unblocks the orchestrator
pattern on Telegram forum-enabled groups.

Closes openclaw#5737
Ref openclaw#23414

* fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind

* telegram: fix ACP child thread spawn with group chat ID from agentGroupId

* telegram: scope agentGroupId substitution to telegram channel only

* Telegram: fix forum topic replies routing to root chat instead of topic thread

* fix: clean up dead guard in child bind + add explicit threadId override test

- Simplify bare-topic-ID guards in thread-bindings.ts: split into
  separate !chatId and !chatId.startsWith("-") checks, removing
  unreachable second condition
- Add regression test confirming explicit turnSourceThreadId overrides
  session lastThreadId on same channel

* fix: guard threadId fallback against shared-session race

Codex review P1: when turnSourceTo differs from the session's stored
to, the session threadId may belong to a different chat/topic. Only
fall back to context.threadId when the destination also matches.

* fix(telegram): enable ACP spawn from forum topics without thread binding

extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264)
instead of bare group chat IDs, breaking agentGroupId resolution.
agentGroupId was also never wired in the inline actions path.

For Telegram forum topics, skip thread binding entirely — the delivery
plan already routes correctly via requester origin (to + threadId).
Creating new forum topics per child session is unnecessary; output goes
back to the same topic the user asked from.

* fix(acp): bind Telegram forum sessions to current topic

* fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001)

---------

Co-authored-by: openclaw <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…ne27001)

* feat(telegram): add child thread-binding placement via createForumTopic

Enable ACP subagent spawn on Telegram by adding "child" placement
support to the thread-bindings adapter. When a child binding is
requested, the adapter creates a new forum topic via the Telegram
Bot API and binds the subagent session to it using the canonical
chatId:topic:topicId conversation ID format.

When the ACP spawn context provides only a topic ID (not a full
group chat ID), the adapter resolves the group from the configured
Telegram groups in openclaw.json.

This mirrors the Discord adapter's child placement behavior
(thread creation + session binding) and unblocks the orchestrator
pattern on Telegram forum-enabled groups.

Closes openclaw#5737
Ref openclaw#23414

* fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind

* telegram: fix ACP child thread spawn with group chat ID from agentGroupId

* telegram: scope agentGroupId substitution to telegram channel only

* Telegram: fix forum topic replies routing to root chat instead of topic thread

* fix: clean up dead guard in child bind + add explicit threadId override test

- Simplify bare-topic-ID guards in thread-bindings.ts: split into
  separate !chatId and !chatId.startsWith("-") checks, removing
  unreachable second condition
- Add regression test confirming explicit turnSourceThreadId overrides
  session lastThreadId on same channel

* fix: guard threadId fallback against shared-session race

Codex review P1: when turnSourceTo differs from the session's stored
to, the session threadId may belong to a different chat/topic. Only
fall back to context.threadId when the destination also matches.

* fix(telegram): enable ACP spawn from forum topics without thread binding

extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264)
instead of bare group chat IDs, breaking agentGroupId resolution.
agentGroupId was also never wired in the inline actions path.

For Telegram forum topics, skip thread binding entirely — the delivery
plan already routes correctly via requester origin (to + threadId).
Creating new forum topics per child session is unnecessary; output goes
back to the same topic the user asked from.

* fix(acp): bind Telegram forum sessions to current topic

* fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001)

---------

Co-authored-by: openclaw <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
Nachx639 pushed a commit to Nachx639/clawdbot that referenced this pull request Jun 17, 2026
…ne27001)

* feat(telegram): add child thread-binding placement via createForumTopic

Enable ACP subagent spawn on Telegram by adding "child" placement
support to the thread-bindings adapter. When a child binding is
requested, the adapter creates a new forum topic via the Telegram
Bot API and binds the subagent session to it using the canonical
chatId:topic:topicId conversation ID format.

When the ACP spawn context provides only a topic ID (not a full
group chat ID), the adapter resolves the group from the configured
Telegram groups in openclaw.json.

This mirrors the Discord adapter's child placement behavior
(thread creation + session binding) and unblocks the orchestrator
pattern on Telegram forum-enabled groups.

Closes openclaw#5737
Ref openclaw#23414

* fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind

* telegram: fix ACP child thread spawn with group chat ID from agentGroupId

* telegram: scope agentGroupId substitution to telegram channel only

* Telegram: fix forum topic replies routing to root chat instead of topic thread

* fix: clean up dead guard in child bind + add explicit threadId override test

- Simplify bare-topic-ID guards in thread-bindings.ts: split into
  separate !chatId and !chatId.startsWith("-") checks, removing
  unreachable second condition
- Add regression test confirming explicit turnSourceThreadId overrides
  session lastThreadId on same channel

* fix: guard threadId fallback against shared-session race

Codex review P1: when turnSourceTo differs from the session's stored
to, the session threadId may belong to a different chat/topic. Only
fall back to context.threadId when the destination also matches.

* fix(telegram): enable ACP spawn from forum topics without thread binding

extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264)
instead of bare group chat IDs, breaking agentGroupId resolution.
agentGroupId was also never wired in the inline actions path.

For Telegram forum topics, skip thread binding entirely — the delivery
plan already routes correctly via requester origin (to + threadId).
Creating new forum topics per child session is unnecessary; output goes
back to the same topic the user asked from.

* fix(acp): bind Telegram forum sessions to current topic

* fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001)

---------

Co-authored-by: openclaw <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: telegram Channel integration: telegram size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants