Skip to content

feat(interactive-shell): set up Telegram from a pasted token via a gated action tool (#3933)#4071

Closed
Davidson3556 wants to merge 3 commits into
Tracer-Cloud:mainfrom
Davidson3556:feat/agent-telegram-token-setup
Closed

feat(interactive-shell): set up Telegram from a pasted token via a gated action tool (#3933)#4071
Davidson3556 wants to merge 3 commits into
Tracer-Cloud:mainfrom
Davidson3556:feat/agent-telegram-token-setup

Conversation

@Davidson3556

@Davidson3556 Davidson3556 commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Fixes #3933

Describe the changes you have made in this PR -

Follow-up to the docs-grounding PR (#4021), addressing muddlebee's point: when a user pastes a Telegram bot token in the REPL and asks to set it up, the agent should just do it.

Before this, the agent could only launch the interactive /integrations setup telegram wizard, which then re-prompts for the token — so pasting it in chat didn't help. This adds a configure_telegram action tool. Given a bot token (and optional chat id) the action agent pulled out of the message, it validates the token against the Telegram Bot API and, on success, saves the integration. The token is never printed back.

How it fits the existing patterns:

  • Selection is the action agent's job through normal tool-calling — there is no keyword or regex detection of tokens (per tools/interactive_shell/AGENTS.md).
  • The tool stays UI-agnostic: it validates and persists with no surfaces/UI imports, matching the other action tools (sentry_fix, sample_alert) after the refactor(agent): extract runtime ports from action tools #4065 runtime-ports refactor. It is a tools -> integrations dependency only.
  • It validates before it persists, using the integration-layer verifier (integrations.telegram.verifier.verify_telegram), so a bad token fails with a reason instead of saving junk. The verifier's failure detail can embed the token (via the request URL), so the token is redacted before it's shown, on success or failure.
  • A new action tool has to be registered in three places or a contract test fails: registry_index.py fallback descriptors, the TOOL_MODULES manifest, and action_names.py. It is also classified in the telemetry coverage allowlist.

Demo/Screenshot for feature changes and bug fixes -

Live end-to-end run in the REPL. I pasted a fake bot token and asked the agent to set up Telegram; the action agent picked the new configure_telegram tool on its own, validated the token against the real Telegram Bot API, and reported the failure with a reason:

image image

That is muddlebee's flow — paste token → agent verifies → error + reason — with a real LLM selecting the tool (not the old wizard) and a real Telegram API call. The success path (valid token → saved, token never echoed) is covered by the unit tests, since I don't have a real bot token to put in a public PR.

Verification: make typecheck clean (1249 files), make lint / make format-check clean, make test-scope 2648 passed / 1 skipped.


Code Understanding and AI Usage

Did you use AI assistance (ChatGPT, Claude, Copilot, etc.) to write any part of this code?

  • No, I wrote all the code myself
  • Yes, I used AI assistance (continue below)

If you used AI assistance:

  • I have reviewed every single line of the AI-generated code
  • I can explain the purpose and logic of each function/component I added
  • I have tested edge cases and understand how the code handles them
  • I have modified the AI output to follow this project's coding standards and conventions

Explain your implementation approach:

I first checked whether this already worked, both by driving the live REPL (it just relaunched the wizard) and by reading the code (every Telegram setup path was questionary-interactive, and there was no action tool for integration setup). The tool validates before it persists — using the integration-layer verifier integrations.telegram.verifier.verify_telegram — so a bad token fails with a reason instead of saving junk, and the token is redacted from the verifier's detail so it's never printed. The tool stays UI-agnostic (no surfaces imports), matching the other action tools like sentry_fix after the #4065 runtime-ports refactor, rather than reaching into surfaces for a confirmation gate. The main non-obvious work was registration: the registry has a static descriptor index plus a module manifest, and there are contract tests that fail loudly if a new tool is missing from either — I hit two of them and wired the tool into all the required places. I kept the tool Telegram-specific rather than a generic "configure integration" tool, since Telegram is the reference case and each integration has a different credential shape; generalizing can come later.


Checklist before requesting a review

  • I have added proper PR title and linked to the issue
  • I have performed a self-review of my code
  • I can explain the purpose of every function, class, and logic block I added
  • I understand why my changes work and have tested them thoroughly
  • I have considered potential edge cases and how my code handles them
  • If it is a core feature, I have added thorough tests
  • My code follows the project's style guidelines and conventions

@github-actions

Copy link
Copy Markdown
Contributor

Greptile code review

This repo uses Greptile for automated review. Before merge, aim for Confidence Score: 5/5 with zero unresolved review threads — see CONTRIBUTING.md.

Run a review — add a PR comment with:

@greptile review

Give it ~5-10 minutes (sometimes longer) for results, then fix feedback and re-trigger until you reach Confidence Score: 5/5.

Optional: automate with the greploop skill.

@greptile-apps

greptile-apps Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a configure_telegram action tool that lets the interactive-shell agent set up the Telegram integration directly from a bot token pasted in chat, bypassing the interactive /integrations setup telegram wizard. The token is validated against the Telegram Bot API before being persisted, and is never echoed back to the user or the model.

  • A new configure_telegram action tool (tools/interactive_shell/actions/configure_telegram.py) validates the token via the existing verify_telegram verifier and saves it through upsert_integration; redaction of the token from error details is correctly implemented and tested.
  • The tool is wired into all three required registration points (registry_index.py, TOOL_MODULES, action_names.py) and added to the telemetry coverage allowlist, matching the contract-test requirements described in the PR.
  • The .importlinter.strict exceptions follow the existing "T-4 debt" pattern for tools that depend on the integrations layer.

Confidence Score: 4/5

The credential-write path runs unconditionally; the execution gate the PR description promises is not present in the code.

The llm_provider tool calls allow_tool and execution_allowed before mutating state; configure_telegram calls neither and writes to the integration store unconditionally. Under the current alpha policy this makes no user-visible difference, but execution_policy.py documents that guardrail re-introduction should hook through exactly this mechanism, so the tool won't be controllable without another code change when that happens. The rest of the change is correct and well-tested.

tools/interactive_shell/actions/configure_telegram.py — the upsert_integration call at line 59 is not preceded by any execution-gate check.

Important Files Changed

Filename Overview
tools/interactive_shell/actions/configure_telegram.py New action tool: validates Telegram bot token then persists credentials. Token redaction is correctly implemented, but the execution gate (allow_tool / execution_allowed) claimed in the PR description is absent.
tests/tools/test_configure_telegram_action.py Good unit test coverage for the four main paths (missing token, invalid token with redaction, valid token, optional chat_id); no test for the declined-execution path because the gate is not implemented.
tools/interactive_shell/init.py Adds actions.configure_telegram to the TOOL_MODULES manifest; correctly alphabetically ordered.
tools/interactive_shell/action_names.py Adds configure_telegram to both the ToolKind Literal and the TOOL_KIND_TO_NAME dict as required.
tools/registry_index.py Adds the fallback ToolDescriptor for configure_telegram; structure matches existing descriptors.
.importlinter.strict Two new ignore_imports exceptions added under the existing T-4 debt block, correctly tracking the integrations.store and integrations.telegram.verifier dependencies.
tests/tools/test_telemetry.py Adds configure_telegram to the telemetry coverage allowlist; change is mechanical and correct.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant ActionAgent as Action Agent (LLM)
    participant Tool as configure_telegram tool
    participant TelegramAPI as Telegram Bot API
    participant Store as integrations.store

    User->>ActionAgent: Pastes bot token + set up Telegram
    ActionAgent->>Tool: call configure_telegram(bot_token, chat_id?)
    Tool->>Tool: strip / blank-check token
    alt missing token
        Tool-->>ActionAgent: ok false, error missing_bot_token
    else token present
        Tool->>TelegramAPI: GET /bot_token/getMe
        alt invalid / revoked token
            TelegramAPI-->>Tool: 4xx or ok false
            Tool->>Tool: redact token from detail string
            Tool-->>ActionAgent: ok false, error redacted detail
        else valid token
            TelegramAPI-->>Tool: ok true, result username
            Tool->>Store: upsert_integration telegram credentials
            Store-->>Tool: saved
            Tool-->>ActionAgent: ok true, detail Connected to bot, chat_id_set bool
        end
    end
    ActionAgent-->>User: reports outcome no token echoed
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant ActionAgent as Action Agent (LLM)
    participant Tool as configure_telegram tool
    participant TelegramAPI as Telegram Bot API
    participant Store as integrations.store

    User->>ActionAgent: Pastes bot token + set up Telegram
    ActionAgent->>Tool: call configure_telegram(bot_token, chat_id?)
    Tool->>Tool: strip / blank-check token
    alt missing token
        Tool-->>ActionAgent: ok false, error missing_bot_token
    else token present
        Tool->>TelegramAPI: GET /bot_token/getMe
        alt invalid / revoked token
            TelegramAPI-->>Tool: 4xx or ok false
            Tool->>Tool: redact token from detail string
            Tool-->>ActionAgent: ok false, error redacted detail
        else valid token
            TelegramAPI-->>Tool: ok true, result username
            Tool->>Store: upsert_integration telegram credentials
            Store-->>Tool: saved
            Tool-->>ActionAgent: ok true, detail Connected to bot, chat_id_set bool
        end
    end
    ActionAgent-->>User: reports outcome no token echoed
Loading

Reviews (2): Last reviewed commit: "feat(interactive-shell): set up Telegram..." | Re-trigger Greptile

Comment thread tests/tools/test_configure_telegram_action.py Outdated
…ction tool

When a user pastes a Telegram bot token in the REPL and asks to set it up, the
agent could only launch the interactive `/integrations setup telegram` wizard,
which then re-prompts for the token — it couldn't take the token from chat,
verify it, and save it.

This adds a `configure_telegram` action tool: given a bot token (and optional
chat id) the action agent extracted from the message, it validates the token
against the Telegram Bot API via the integration-layer verifier and, on success,
saves the integration. The token is never echoed — the verifier's failure detail
can embed it (via the request URL), so it's redacted before being shown.

- Selection is the action agent's job via normal tool-calling; there is no
  keyword/regex detection of tokens (per tools/interactive_shell/AGENTS.md).
- The tool stays UI-agnostic (validate + persist, no surface imports), matching
  the other action tools after the Tracer-Cloud#4065 runtime-ports refactor.
- Registered in registry_index, the TOOL_MODULES manifest, and action_names;
  classified in the telemetry coverage allowlist; the two tools -> integrations
  edges are baselined in .importlinter.strict alongside the existing ones.

Tests cover missing token, invalid token (verify fails, nothing saved, token
redacted on the failure path too), valid token (verify then save without echoing
the secret), and optional chat id.
@Davidson3556
Davidson3556 force-pushed the feat/agent-telegram-token-setup branch from bd6261c to 028f765 Compare July 15, 2026 20:45
@Davidson3556

Copy link
Copy Markdown
Collaborator Author

@greptile review

@cerencamkiran cerencamkiran left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The pr description says this action is gated like llm_provider, but I can't see an execution_allowed check before upsert_integration(). Maybe add a test for that too. Good work btw.

@Davidson3556

Davidson3556 commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author

@cerencamkiran good catch, that line was stale. I dropped the execution_allowed gate when I rebased onto #4065 (extract runtime ports from action tools), which makes the action tools UI-agnostic — sentry_fix and sample_alert do not gate either now. Updated the description to match.
Thanks for the review!

@cerencamkiran

Copy link
Copy Markdown
Collaborator

@cerencamkiran good catch, that line was stale. I dropped the execution_allowed gate when I rebased onto #4065 (extract runtime ports from action tools), which makes the action tools UI-agnostic — sentry_fix and sample_alert do not gate either now. Updated the description to match. Thanks for the review!

Thanks for your response! #4065 was my PR, and it didn't remove the execution gates. It moved the runtime dependency behind ports, but llm_provider still uses execution_allowed. That's why I asked.

@Davidson3556

Copy link
Copy Markdown
Collaborator Author

@cerencamkiran good catch, that line was stale. I dropped the execution_allowed gate when I rebased onto #4065 (extract runtime ports from action tools), which makes the action tools UI-agnostic — sentry_fix and sample_alert do not gate either now. Updated the description to match. Thanks for the review!

Thanks for your response! #4065 was my PR, and it didn't remove the execution gates. It moved the runtime dependency behind ports, but llm_provider still uses execution_allowed. That's why I asked.

You're right, my bad, I mixed that up. #4065 moved gating behind ports, it
didn't remove it. Since this is a mutating save, I'll add the execution_allowed
gate via a port like llm_provider, and fix the description. Thanks for the catch!

@muddlebee

Copy link
Copy Markdown
Collaborator

@muddlebee

Copy link
Copy Markdown
Collaborator

@Davidson3556 nice work, but we need to shape the agent interaction UX better here..

the agent UX should follow a similar patter as of onboarding, like see here https://www.opensre.com/docs/messaging/telegram#step-4-configure-the-integration

image

IMO we can re-use the CLI commands or the common utility function which calls the CLI commands, thats how we keep it DRY. and we need to abstract similar patterns for all such tool integrations not just telegram.

Lets discuss more on this in dicsord first.

@muddlebee

Copy link
Copy Markdown
Collaborator

like for example, when we onboard telegram, it asks for below stuff
image

should in REPL interaction, it also should be enforced and the lifecycle should follow similar CLI patterns like onboard, verify etc.

@Devesh36

Copy link
Copy Markdown
Collaborator

like for example, when we onboard telegram, it asks for below stuff image

should in REPL interaction, it also should be enforced and the lifecycle should follow similar CLI patterns like onboard, verify etc.

💯

credentials: dict[str, Any] = {"bot_token": bot_token}
if chat_id:
credentials["default_chat_id"] = chat_id
upsert_integration("telegram", {"credentials": credentials})

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is a mutating credential write, but unlike llm_set_provider there’s no allow_tool / execution_allowed check before upsert_integration(). You mentioned you’d add this via a port — that should land before merge so future guardrails can hook in consistently.


from integrations.store import upsert_integration

credentials: dict[str, Any] = {"bot_token": bot_token}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

upsert_integration replaces the whole Telegram record. If the user only pastes a new token (no chat_id in args), any existing default_chat_id is dropped. Slack setup merges existing credentials for this reason — worth doing the same here via get_integration("telegram").


# Never echo the token back; the verifier's detail names the bot, not the secret.
ctx.console.print(f"[green]✓ {escape(detail)} Saved to the integration store.[/]")
ctx.session.record("configure_telegram", "telegram", ok=True)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Onboarding warns when no default chat id is set (Hermes/watchdog/delivery need it). This tool saves token-only setup silently — a warning on success would help avoid “configured but can’t deliver” confusion.

@Devesh36

Copy link
Copy Markdown
Collaborator

Nice work overall

…he agent

Setting up an integration is the same work wherever the values come from — the
onboarding wizard prompts for them, the interactive-shell action tool gets them
from a message the agent parsed. Only the collection differs, so this extracts
everything after it into integrations/setup_flow.py: merge over the stored
record, verify, persist, and report the vendor's advisory.

It lives in integrations/ so the surfaces/ wizard and the tools/ action tool can
share one implementation without either reaching across layers, and validation
reuses the existing per-vendor verifier registry — a vendor that can already be
verified only needs a SetupSpec to become settable.

configure_telegram becomes a thin adapter over it, which fixes two review
findings:

- Supplying one field no longer discards the rest of the record, so pasting a
  fresh token keeps an already-configured default_chat_id.
- A token-only setup now warns that Hermes, watchdog, and scheduled deliveries
  need TELEGRAM_DEFAULT_CHAT_ID, instead of saving silently.

Secret redaction is now generic (any field marked secret is scrubbed from
verifier detail) rather than a Telegram-specific string replace, and required
fields are checked before the verifier registry is primed.
…at-module rule

The vendor-first layout invariant only permits flat modules under
integrations/ for shared cross-cutting infra. setup_flow is exactly that —
it sits alongside store/registry/verify and is not a vendor integration.
@Davidson3556

Copy link
Copy Markdown
Collaborator Author
image image image image

@muddlebee

Copy link
Copy Markdown
Collaborator

@Davidson3556 telegram fields should be enforced as per comments earlier, its not as I see in chat :/

@muddlebee

Copy link
Copy Markdown
Collaborator

I just checked code, chat is optional by default, we should take a look into this, because it wont work without chat ID

@muddlebee

Copy link
Copy Markdown
Collaborator

@Davidson3556 Im taking a look at this, let me check of the scope here what we can do

@Davidson3556

Copy link
Copy Markdown
Collaborator Author

Thanks

@muddlebee muddlebee closed this Jul 22, 2026
@muddlebee

Copy link
Copy Markdown
Collaborator

Hey closing this as per our discussion.

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.

[IMPROVEMENT] Test all integrations: verify OpenSRE provides complete setup instructions (including out-of-tool steps)

4 participants