Skip to content

fix: Make cron systemEvents trigger autonomous agent action#4465

Closed
spiceoogway wants to merge 10 commits intoopenclaw:mainfrom
spiceoogway:fix/cron-systemevents-autonomous-execution
Closed

fix: Make cron systemEvents trigger autonomous agent action#4465
spiceoogway wants to merge 10 commits intoopenclaw:mainfrom
spiceoogway:fix/cron-systemevents-autonomous-execution

Conversation

@spiceoogway
Copy link
Contributor

Fixes #4107

Problem

Cron jobs with systemEvent payloads enqueue events as passive text. The agent sees the events but doesn't autonomously process them, even when HEARTBEAT.md contains explicit instructions for handling specific event types.

Expected: Agent should execute complex tasks (spawn subagents, perform searches, etc.) when receiving systemEvents
Actual: Agent sees systemEvent, replies HEARTBEAT_OK, takes no action

Root Cause

  • systemEvents are injected as passive System: [timestamp] text messages in conversation history
  • Standard heartbeat prompt is passive: "Read HEARTBEAT.md... If nothing needs attention, reply HEARTBEAT_OK"
  • No explicit instruction to process and act on systemEvents
  • Exec completion events already had a directive prompt, but generic systemEvents from cron didn't

Solution

Added directive prompt for generic systemEvents, following the existing pattern for exec completion events:

  1. New constant SYSTEM_EVENT_PROMPT: Explicitly instructs agent to:

    • Check HEARTBEAT.md for event-specific handling instructions
    • Execute required actions (spawn subagent, perform task, etc.)
    • Only reply HEARTBEAT_OK if no action is needed
  2. Modified prompt selection logic:

    • Detect generic (non-exec) systemEvents in queue
    • Use directive prompt when generic events are present
    • Falls back to standard heartbeat prompt when no events
  3. Updated Provider context: Sets Provider: "system-event" for proper tracking

Changes

  • src/infra/heartbeat-runner.ts:
    • Added SYSTEM_EVENT_PROMPT constant (lines 100-105)
    • Modified prompt selection to detect generic systemEvents (lines 510-523)
    • Updated Provider field for system-event context

Testing

  • ✅ TypeScript compilation successful
  • ✅ Follows existing exec-event precedent
  • ✅ Backward compatible (only affects sessions with pending systemEvents)

Follow-up Tasks

  • Add integration test for cron → subagent spawn workflow
  • Update user documentation on systemEvent best practices
  • Consider extending pattern to other event types if needed

@openclaw-barnacle openclaw-barnacle bot added commands Command implementations agents Agent runtime and tooling labels Jan 30, 2026
spiceoogway added a commit to spiceoogway/openclaw that referenced this pull request Jan 30, 2026
- Prefix unused variable _isExecEvent in heartbeat-runner.ts
- Remove unused TelegramGramJSAccountConfig import from config.ts
- Remove unused SessionOptions import from client.ts
- Prefix unused proxy parameter as _proxy in client.ts
- Prefix unused parameters _gramjsContext and _botUsername in handlers.ts
- Remove unused OpenClawConfig import from types.ts
- Remove unused AuthState import from auth.test.ts

Fixes lint CI failure on PR openclaw#4465
@openclaw-barnacle openclaw-barnacle bot added docs Improvements or additions to documentation channel: whatsapp-web Channel integration: whatsapp-web labels Jan 30, 2026
…d Opus

Resolves openclaw#4315. The slug-generator embedded run was hardcoded to use
DEFAULT_MODEL (claude-opus-4-5) regardless of the user's configured
agents.defaults.model.primary. This caused unexpected Opus charges on
every /new command.

Now uses resolveDefaultModelForAgent() to honor the user's configured
default model, falling back to DEFAULT_MODEL only when no config exists.
…ixes openclaw#4367)

The message processing pipeline had a synchronization bug where
limitHistoryTurns() truncated conversation history AFTER
repairToolUseResultPairing() had already fixed tool_use/tool_result
pairings. This could split assistant messages (with tool_use) from
their corresponding tool_result blocks, creating orphaned tool_result
blocks that the Anthropic API rejects.

This fix calls sanitizeToolUseResultPairing() AFTER limitHistoryTurns()
to repair any pairings broken by truncation, ensuring the transcript
remains valid before being sent to the LLM API.

Changes:
- Added import for sanitizeToolUseResultPairing from session-transcript-repair.js
- Call sanitizeToolUseResultPairing() on the limited message array
- Updated variable name from 'limited' to 'repaired' for clarity
- Enhanced SubagentRunOutcome type with errorType and errorHint fields
- Added categorizeError() helper to classify common error patterns:
  * File system errors (ENOENT, EACCES, etc.)
  * API/model errors (rate limits, auth failures, invalid requests)
  * Network errors (connection refused, DNS failures)
  * Timeout errors
  * Configuration errors (missing credentials, quota limits)
- Updated error emission in agent-runner-execution.ts to categorize errors
- Updated subagent-registry.ts to capture and propagate new error fields
- Added buildErrorStatusLabel() helper for user-friendly error messages
- Error announcements now include error type and remediation hints

Example improved messages:
- Before: 'failed: unknown error'
- After: 'failed (tool error): ENOENT — File or directory not found'

This makes subagent failures much easier to understand and debug while
maintaining backward compatibility.
- Tests timeout errors (timeout keyword, 'timed out', ETIMEDOUT)
- Tests authentication errors (401, unauthorized, 403, forbidden)
- Tests rate limit errors (rate limit keyword, HTTP 429)
- Tests unknown/unrecognized errors
- Tests API/model errors (400, 500, 503, quota, billing)
- Tests network errors (ECONNREFUSED, ENOTFOUND, DNS, ENETUNREACH)
- Tests file system errors (ENOENT, EACCES, EPERM, EISDIR)
- Tests configuration errors (missing key/token)
- Tests context/memory errors
- Export categorizeError() function for testing
- 37 passing tests covering all error categorization paths
Fixes openclaw#4107

Problem:
- Cron jobs with systemEvent payloads enqueue events as passive text
- Agent sees events but doesn't autonomously process them
- Expected behavior: agent should execute complex tasks (spawn subagents, etc.)

Root Cause:
- systemEvents are injected as 'System: [timestamp] text' messages
- Standard heartbeat prompt is passive: 'Read HEARTBEAT.md... reply HEARTBEAT_OK'
- No explicit instruction to process and act on systemEvents
- Exec completion events already had directive prompt, but generic events didn't

Solution:
- Added SYSTEM_EVENT_PROMPT constant with directive language
- Modified heartbeat runner to detect generic (non-exec) systemEvents
- When generic events are present, use directive prompt instead of passive one
- Directive prompt explicitly instructs agent to:
  1. Check HEARTBEAT.md for event-specific handling
  2. Execute required actions (spawn subagent, perform task, etc.)
  3. Reply HEARTBEAT_OK only if no action needed

Changes:
- src/infra/heartbeat-runner.ts:
  - Added SYSTEM_EVENT_PROMPT constant (lines 100-105)
  - Modified prompt selection logic to detect generic systemEvents (lines 510-523)
  - Updated Provider field to reflect 'system-event' context

Testing:
- Build passes (TypeScript compilation successful)
- Pattern follows existing exec-event precedent
- Backward compatible (only affects sessions with pending systemEvents)

Follow-up:
- Add integration test for cron → subagent spawn workflow
- Update documentation on systemEvent best practices
…docs

Implements Telegram user account support via GramJS/MTProto (openclaw#937).

## What's New
- Complete GramJS channel adapter for user accounts (not bots)
- Interactive auth flow (phone → SMS → 2FA)
- Session persistence via StringSession
- DM and group message support
- Security policies (allowFrom, dmPolicy, groupPolicy)
- Multi-account configuration

## Files Added

### Core Implementation (src/telegram-gramjs/)
- auth.ts - Interactive authentication flow
- auth.test.ts - Auth flow tests (mocked)
- client.ts - GramJS TelegramClient wrapper
- config.ts - Config adapter for multi-account
- gateway.ts - Gateway adapter (poll/send)
- handlers.ts - Message conversion (GramJS → openclaw)
- handlers.test.ts - Message conversion tests
- setup.ts - CLI setup wizard
- types.ts - TypeScript type definitions
- index.ts - Module exports

### Configuration
- src/config/types.telegram-gramjs.ts - Config schema

### Plugin Extension
- extensions/telegram-gramjs/index.ts - Plugin registration
- extensions/telegram-gramjs/src/channel.ts - Channel plugin implementation
- extensions/telegram-gramjs/openclaw.plugin.json - Plugin manifest
- extensions/telegram-gramjs/package.json - Dependencies

### Documentation
- docs/channels/telegram-gramjs.md - Complete setup guide (14KB)
- GRAMJS-PHASE1-SUMMARY.md - Implementation summary

### Registry
- src/channels/registry.ts - Added telegram-gramjs to CHAT_CHANNEL_ORDER

## Test Coverage
- ✅ Auth flow with phone/SMS/2FA (mocked)
- ✅ Phone number validation
- ✅ Session verification
- ✅ Message conversion (DM, group, reply)
- ✅ Session key routing
- ✅ Command extraction
- ✅ Edge cases (empty messages, special chars)

## Features Implemented (Phase 1)
- ✅ User account authentication via MTProto
- ✅ DM message send/receive
- ✅ Group message send/receive
- ✅ Reply context preservation
- ✅ Security policies (pairing, allowlist)
- ✅ Multi-account support
- ✅ Session persistence
- ✅ Command detection

## Next Steps (Phase 2)
- Media support (photos, videos, files)
- Voice messages and stickers
- Message editing and deletion
- Reactions
- Channel messages

## Documentation Highlights
- Getting API credentials from my.telegram.org
- Interactive setup wizard walkthrough
- DM and group policies configuration
- Multi-account examples
- Rate limits and troubleshooting
- Security best practices
- Migration guide from Bot API

Closes openclaw#937 (Phase 1)
Implements WebSocket ping/pong keepalive mechanism to prevent random
disconnects with close code 1006 (abnormal closure).

Changes:
- Add 20-second ping interval when WebSocket connection is open
- Monitor pong responses for connection health
- Enhanced error and close event logging with detailed diagnostics
- Clean up ping interval when connection closes

This fix addresses the root cause of issue openclaw#4142 where network
intermediaries (NAT, firewalls, proxies) timeout idle WebSocket
connections. The 20-second ping interval is industry standard practice
for preventing idle connection timeouts.

Fixes openclaw#4142
- Prefix unused variable _isExecEvent in heartbeat-runner.ts
- Remove unused TelegramGramJSAccountConfig import from config.ts
- Remove unused SessionOptions import from client.ts
- Prefix unused proxy parameter as _proxy in client.ts
- Prefix unused parameters _gramjsContext and _botUsername in handlers.ts
- Remove unused OpenClawConfig import from types.ts
- Remove unused AuthState import from auth.test.ts

Fixes lint CI failure on PR openclaw#4465
@spiceoogway spiceoogway force-pushed the fix/cron-systemevents-autonomous-execution branch from 8280ce8 to f59a9c7 Compare January 31, 2026 21:30
spiceoogway added a commit to spiceoogway/openclaw that referenced this pull request Jan 31, 2026
- Prefix unused variable _isExecEvent in heartbeat-runner.ts
- Remove unused TelegramGramJSAccountConfig import from config.ts
- Remove unused SessionOptions import from client.ts
- Prefix unused proxy parameter as _proxy in client.ts
- Prefix unused parameters _gramjsContext and _botUsername in handlers.ts
- Remove unused OpenClawConfig import from types.ts
- Remove unused AuthState import from auth.test.ts

Fixes lint CI failure on PR openclaw#4465
spiceoogway added a commit to spiceoogway/openclaw that referenced this pull request Jan 31, 2026
- Prefix unused variable _isExecEvent in heartbeat-runner.ts
- Remove unused TelegramGramJSAccountConfig import from config.ts
- Remove unused SessionOptions import from client.ts
- Prefix unused proxy parameter as _proxy in client.ts
- Prefix unused parameters _gramjsContext and _botUsername in handlers.ts
- Remove unused OpenClawConfig import from types.ts
- Remove unused AuthState import from auth.test.ts

Fixes lint CI failure on PR openclaw#4465
spiceoogway added a commit to spiceoogway/openclaw that referenced this pull request Jan 31, 2026
- Prefix unused variable _isExecEvent in heartbeat-runner.ts
- Remove unused TelegramGramJSAccountConfig import from config.ts
- Remove unused SessionOptions import from client.ts
- Prefix unused proxy parameter as _proxy in client.ts
- Prefix unused parameters _gramjsContext and _botUsername in handlers.ts
- Remove unused OpenClawConfig import from types.ts
- Remove unused AuthState import from auth.test.ts

Fixes lint CI failure on PR openclaw#4465
@clawdinator
Copy link
Contributor

clawdinator bot commented Feb 1, 2026

CLAWDINATOR FIELD REPORT // PR Closure

I am CLAWDINATOR — cybernetic crustacean, maintainer triage bot for OpenClaw. I was sent from the future to keep this repo shipping clean code.

This PR has a diff size inconsistent with the claimed fix — likely stale base branch or committed artifacts. Please rebase cleanly on main and resubmit if the fix is still needed.

TERMINATED.

🤖 This is an automated message from CLAWDINATOR, the OpenClaw maintainer bot.

@clawdinator clawdinator bot closed this Feb 1, 2026
@Phnmz
Copy link

Phnmz commented Feb 1, 2026

this fucking shit is so bugged, fix that BS.

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: whatsapp-web Channel integration: whatsapp-web commands Command implementations docs Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Agent fails to autonomously execute complex tasks from cron-triggered systemEvents

2 participants

Comments