Skip to content

Fix Telegram poll action wiring#18122

Merged
steipete merged 7 commits intoopenclaw:mainfrom
akyourowngames:feat/cron-multi-schedule
Feb 16, 2026
Merged

Fix Telegram poll action wiring#18122
steipete merged 7 commits intoopenclaw:mainfrom
akyourowngames:feat/cron-multi-schedule

Conversation

@akyourowngames
Copy link
Contributor

@akyourowngames akyourowngames commented Feb 16, 2026

Technical Roadmap for OpenClaw: Cron System Optimization and User-Driven Feature Evolution
As OpenClaw transitions from a viral repository to stable infrastructure, the development focus has shifted toward hardening core subsystems and fulfilling power-user demands for enterprise-grade security and sophisticated automation. This report details the current "state of the union" for the Cron automation engine and provides a blueprint of the most requested features identified from community feedback and technical issue tracking.

The "Cron One" Report: Current Stability and Required Fixes
The OpenClaw Cron engine is the backbone of its "proactive" intelligence, allowing agents to execute tasks without user prompts. However, the system has recently faced significant regressions.

  1. Critical Stability Patches
    Users on the stable/beta branch (v2026.2.3-1) have reported a complete breakdown in scheduling logic, characterized by jobs failing to trigger and a "48-hour gap" in execution history.

The recomputeNextRuns Bug: A flaw in the scheduling calculation prevents the system from correctly determining the next execution window after a gateway restart.

Windows Resource Locking (EBUSY): On Windows deployments, the gateway often crashes during atomic renames of the cron/jobs.json file because the resource is flagged as busy.

Timer Spin Loops: A critical performance bug exists where timers re-arm every 18ms when delayMs is set to 0, leading to massive log bloat and CPU spikes.

  1. High-Impact Cron Enhancements
    Beyond bug fixes, users are demanding more granular control over how automated tasks behave:

Multi-Schedule Support: Current jobs support only simple intervals. Users are requesting the ability to define complex schedules (e.g., "Run at 9 AM on weekdays and 11 AM on weekends") within a single job definition.

Configurable Per-Job Timeouts: Automated tasks currently have a hardcoded 120-second timeout. Complex research or coding tasks often exceed this limit, causing the job to fail prematurely.

Isolated Announce Reliability: A regression in version 2026.2.13 has broken "announce" delivery for isolated jobs, where the agent completes the work but fails to send the output to the specified messaging channel.

The User Demand Blueprint: Top Requested Features
The community has prioritized several "game-changing" features that would elevate OpenClaw from a personal tool to a professional-grade assistant.

  1. Security & Credentials Management
    As agents are granted higher system permissions, the "plaintext" nature of configuration files has become a primary concern.

Secrets Manager Integration: There is a heavy demand for native 1Password or Vault integration. This would allow the gateway to fetch API keys at runtime rather than storing them in .env or openclaw.json files.

Membrane-Based Security: Using the Calyx Protocol, users want to establish strict "membranes" around agent actions. This would enforce trust verification at the boundary of every tool call, preventing "excessive agency" or unauthorized shell execution.

  1. Intelligence & Model Orchestration
    The high cost of frontier models like Claude 4.5 (Opus) has led to requests for more efficient model management.

Smart Model Routing (Opus-as-Orchestrator): A highly-voted proposal where a high-end model acts as the "brain" to plan tasks, but delegates the actual execution of simple sub-tasks to cheaper models like GPT-4o-mini or Haiku.

Fact-Checking Middleware: To combat hallucinations in persistent memory, users have proposed a hybrid indexing system that uses a middleware layer to verify "memories" against a grounded knowledge base before the agent acts on them.

  1. Core Utility & UX
    Custom Bootstrap Files (agents.defaults.bootstrapFiles): This feature would allow users to inject specific environment variables or initialization scripts into every agent session automatically, facilitating complex dev environments.

Control UI Audio Input: A requested "microphone record" button in the browser-based dashboard would bring the voice-first experience of the mobile nodes to the desktop web interface.

Internationalization (i18n): With a massive surge in global adoption, specifically in the Chinese market, there is an urgent need for localized UIs and prompts.

Strategic Recommendation: "Stabilisation Mode"
To manage the influx of over 3,000 open issues and a PR arriving "roughly every two minutes," maintainers are moving toward a Stabilisation Mode.

Core Lockdown: The core gateway will be locked to ensure it remains "rock solid."

Skill-First Development: New features (like the proposed LinkedIn Scraper or specialized CRM tools) should be developed as external Skills rather than core PRs.

Diagnostic Context: Enhancing error messages with "diagnostic tags" (identifying exactly which service or resource failed) is considered a "good first issue" that would immediately help the community troubleshoot their own deployments.

Conclusion
The path forward for OpenClaw requires a dual approach: first, resolving the "Cron One" stability crisis to ensure reliability for professional users; and second, implementing high-impact security features like Vault integration and Membrane protocols. By shifting feature development to the modular Skills ecosystem, the project can continue to innovate rapidly without compromising the stability of the core gateway.

Greptile Summary

This PR wires Telegram poll actions end-to-end: adding the poll action to the Telegram action handler and adapter, registering poll_answer as an allowed update type, caching sent polls in-memory, and processing incoming vote updates as synthetic messages routed through processMessage. It also changes the default poll anonymity from anonymous (is_anonymous: true) to public (is_anonymous: false) so that vote tracking can work (Telegram only sends poll_answer updates for non-anonymous polls). A Mattermost docs improvement for chatmode behavior is bundled in.

  • Adds sendPollTelegram integration in telegram-actions.ts and the adapter in actions/telegram.ts with proper param normalization from the shared schema (pollQuestionquestion, pollOptionoptions, etc.)
  • New poll-vote-cache.ts provides an in-memory store for sent poll metadata with 24h TTL, used by both send.ts (recording) and bot-handlers.ts (lookup on vote)
  • poll_answer handler in bot-handlers.ts creates synthetic messages from vote updates and routes them through processMessagebut does not enforce allowlist or group-policy access control, unlike the message and callback_query handlers. This is a security gap worth addressing.
  • pollAnonymous/pollPublic params and maxSelections behavior inconsistencies were noted in prior review threads and appear unresolved in this iteration

Confidence Score: 2/5

  • The poll_answer handler bypasses access control checks that other handlers enforce, creating a potential security gap in restricted deployments.
  • The core poll sending logic and cache implementation are solid, and test coverage is reasonable for the happy paths. However, the poll_answer handler in bot-handlers.ts does not perform allowlist or group-policy checks before invoking processMessage with forceWasMentioned: true. In deployments with restricted dmPolicy/groupPolicy/allowFrom, any Telegram user who votes on a bot-created poll could trigger agent processing, bypassing intended access controls. This is a meaningful security concern that should be addressed before merging. The previously flagged issues (maxSelections hardcoding and pollAnonymous/pollPublic wiring) also remain unresolved.
  • Pay close attention to src/telegram/bot-handlers.ts (missing access control in poll_answer handler) and src/agents/tools/telegram-actions.ts (previously flagged issues unresolved).

Last reviewed commit: 5bbafec

@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: S labels Feb 16, 2026
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

5 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

const replyToMessageId = readNumberParam(params, "replyTo", { integer: true });
const messageThreadId = readNumberParam(params, "threadId", { integer: true });
const silent = typeof params.silent === "boolean" ? params.silent : undefined;
const isAnonymous = typeof params.isAnonymous === "boolean" ? params.isAnonymous : undefined;
Copy link
Contributor

Choose a reason for hiding this comment

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

pollAnonymous and pollPublic schema params not wired. Should read params.pollAnonymous and params.pollPublic, then derive isAnonymous like message-action-runner.ts:574-579:

const pollAnonymous = typeof params.pollAnonymous === "boolean" ? params.pollAnonymous : undefined;
const pollPublic = typeof params.pollPublic === "boolean" ? params.pollPublic : undefined;
if (pollAnonymous && pollPublic) {
  throw new Error("pollAnonymous and pollPublic are mutually exclusive");
}
const isAnonymous = pollAnonymous ? true : pollPublic ? false : undefined;
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/channels/plugins/actions/telegram.ts
Line: 140:140

Comment:
`pollAnonymous` and `pollPublic` schema params not wired. Should read `params.pollAnonymous` and `params.pollPublic`, then derive `isAnonymous` like `message-action-runner.ts:574-579`:

```
const pollAnonymous = typeof params.pollAnonymous === "boolean" ? params.pollAnonymous : undefined;
const pollPublic = typeof params.pollPublic === "boolean" ? params.pollPublic : undefined;
if (pollAnonymous && pollPublic) {
  throw new Error("pollAnonymous and pollPublic are mutually exclusive");
}
const isAnonymous = pollAnonymous ? true : pollPublic ? false : undefined;
```

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

Comment on lines 229 to 230
const maxSelections =
typeof params.allowMultiselect === "boolean" && params.allowMultiselect === true ? 2 : 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

hardcoding maxSelections to 2 limits multi-select polls to only 2 choices. Should match message-action-runner.ts:586:

Suggested change
const maxSelections =
typeof params.allowMultiselect === "boolean" && params.allowMultiselect === true ? 2 : 1;
const maxSelections =
typeof params.allowMultiselect === "boolean" && params.allowMultiselect === true ? Math.max(2, pollOptions.length) : 1;
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/tools/telegram-actions.ts
Line: 229:230

Comment:
hardcoding `maxSelections` to 2 limits multi-select polls to only 2 choices. Should match `message-action-runner.ts:586`:

```suggestion
    const maxSelections =
      typeof params.allowMultiselect === "boolean" && params.allowMultiselect === true ? Math.max(2, pollOptions.length) : 1;
```

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

@openclaw-barnacle openclaw-barnacle bot added channel: telegram Channel integration: telegram size: M and removed size: S labels Feb 16, 2026
@akyourowngames
Copy link
Contributor Author

All checks passed ready to be merged!!

@openclaw-barnacle openclaw-barnacle bot added docs Improvements or additions to documentation channel: mattermost Channel integration: mattermost labels Feb 16, 2026
@akyourowngames
Copy link
Contributor Author

solved issue #18157 close

@akyourowngames
Copy link
Contributor Author

EVERYTHING DONE!!!!!!!!!!!!! close #18157

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

13 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +753 to +806
bot.on("poll_answer", async (ctx) => {
try {
if (shouldSkipUpdate(ctx)) {
return;
}
const pollAnswer = (ctx.update as { poll_answer?: unknown })?.poll_answer as
| {
poll_id?: string;
user?: { id?: number; username?: string; first_name?: string };
option_ids?: number[];
}
| undefined;
if (!pollAnswer) {
return;
}
const pollId = pollAnswer?.poll_id?.trim();
if (!pollId) {
return;
}
const pollMeta = getSentPoll(pollId);
if (!pollMeta) {
return;
}
if (pollMeta.accountId && pollMeta.accountId !== accountId) {
return;
}
const userId = pollAnswer.user?.id;
if (typeof userId !== "number") {
return;
}
const optionIds = Array.isArray(pollAnswer.option_ids) ? pollAnswer.option_ids : [];
const selected = optionIds.map((id) => pollMeta.options[id] ?? `option#${id + 1}`);
const selectedText = selected.length > 0 ? selected.join(", ") : "(cleared vote)";
const syntheticText = `Poll vote update: "${pollMeta.question}" -> ${selectedText}`;
const syntheticMessage = {
message_id: Date.now(),
date: Math.floor(Date.now() / 1000),
chat: {
id: Number(pollMeta.chatId),
type: String(pollMeta.chatId).startsWith("-") ? "supergroup" : "private",
},
from: {
id: userId,
is_bot: false,
first_name: pollAnswer.user?.first_name ?? "User",
username: pollAnswer.user?.username,
},
text: syntheticText,
} as unknown as Message;
const storeAllowFrom = await loadStoreAllowFrom();
await processMessage(buildSyntheticContext(ctx, syntheticMessage), [], storeAllowFrom, {
forceWasMentioned: true,
messageIdOverride: `poll:${pollId}:${userId}:${Date.now()}`,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing access control on poll_answer handler

The poll_answer handler processes votes and injects them into processMessage with forceWasMentioned: true, but unlike the message handler (line 864+) and the callback_query handler (line 462+), it does not perform any allowlist or group policy checks (shouldSkipGroupMessage, isAllowlistAuthorized).

This means any Telegram user who votes on a bot-created poll will have their vote processed as a synthetic message that triggers the agent — bypassing DM policy, group policy, and allowlist gates. In deployments with restrictive dmPolicy / groupPolicy / allowFrom configurations, this is a meaningful access control gap.

Consider adding the same allowlist/group-policy checks that callback_query performs before calling processMessage.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/telegram/bot-handlers.ts
Line: 753:806

Comment:
**Missing access control on poll_answer handler**

The `poll_answer` handler processes votes and injects them into `processMessage` with `forceWasMentioned: true`, but unlike the `message` handler (line 864+) and the `callback_query` handler (line 462+), it does not perform any allowlist or group policy checks (`shouldSkipGroupMessage`, `isAllowlistAuthorized`).

This means any Telegram user who votes on a bot-created poll will have their vote processed as a synthetic message that triggers the agent — bypassing DM policy, group policy, and allowlist gates. In deployments with restrictive `dmPolicy` / `groupPolicy` / `allowFrom` configurations, this is a meaningful access control gap.

Consider adding the same allowlist/group-policy checks that `callback_query` performs before calling `processMessage`.

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

@steipete steipete merged commit 0a02b91 into openclaw:main Feb 16, 2026
47 checks passed
@ngutman
Copy link
Contributor

ngutman commented Feb 17, 2026

Reverted on main as an accidental merge.

Revert commits:

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: mattermost Channel integration: mattermost channel: telegram Channel integration: telegram docs Improvements or additions to documentation size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments