Skip to content

[Bug]: Typing indicator expires during long LLM inference – no keepalive in createTypingCallbacks #25882

@timbrd

Description

@timbrd

Summary

Description

When using the Matrix channel plugin (and likely other channel plugins), the typing indicator disappears after ~5 seconds while the agent is still processing a request. This happens during long LLM inference calls (e.g. DeepSeek V3.2, which can take 30-60+ seconds for complex responses).

The user sees the typing indicator for approximately 5 seconds at the start, then it disappears, leaving no visual feedback that the agent is still working. This creates confusion about whether the agent has crashed or is still processing. Note: while the Matrix server-side typing timeout is 30s, clients like Cinny appear to expire the indicator much sooner (~5s) without a refresh event.

Root Cause

createTypingCallbacks in the plugin SDK (src/security/channel-metadata.ts region / plugin-sdk/channels/typing) fires start() exactly once in onReplyStart and never re-sends it:

function createTypingCallbacks(params) {
    const stop = params.stop;
    const onReplyStart = async () => {
        try {
            await params.start();
        } catch (err) {
            params.onStartError(err);
        }
    };
    const fireStop = stop ? () => {
        stop().catch((err) => (params.onStopError ?? params.onStartError)(err));
    } : void 0;
    return {
        onReplyStart,
        onIdle: fireStop,
        onCleanup: fireStop
    };
}

The Matrix plugin calls setTyping(roomId, true, 30_000) – a 30-second server-side timeout. However, clients like Cinny appear to expire the typing indicator after approximately 5 seconds without a refresh event. Since createTypingCallbacks never re-sends, the indicator disappears almost immediately.

The session.typingIntervalSeconds config option appears to be unused by the SDK's typing callback mechanism.

Expected Behavior

The typing indicator should remain visible for as long as the agent is processing. onReplyStart should start a periodic interval that re-calls start() every N seconds (respecting session.typingIntervalSeconds) until onIdle or onCleanup is called.

Suggested Fix

function createTypingCallbacks(params) {
    const stop = params.stop;
    let keepaliveInterval: ReturnType<typeof setInterval> | undefined;

    const onReplyStart = async () => {
        try {
            await params.start();
            // Re-send typing every 4s (under the ~5s client-side expiry)
            keepaliveInterval = setInterval(async () => {
                try {
                    await params.start();
                } catch (err) {
                    params.onStartError(err);
                }
            }, 4_000);
        } catch (err) {
            params.onStartError(err);
        }
    };

    const fireStop = () => {
        if (keepaliveInterval) {
            clearInterval(keepaliveInterval);
            keepaliveInterval = undefined;
        }
        stop?.().catch((err) => (params.onStopError ?? params.onStartError)(err));
    };

    return {
        onReplyStart,
        onIdle: fireStop,
        onCleanup: fireStop
    };
}

Ideally the interval duration should be configurable via session.typingIntervalSeconds (which already exists in config but is currently unused here).

Environment

  • OpenClaw: 2026.2.23
  • Matrix plugin: @openclaw/matrix 2026.2.23
  • Homeserver: Continuwuity v0.5.1
  • Client: Cinny (self-hosted)
  • LLM backend: DeepSeek V3.2 (response times 30-60s+)

Impact

Affects all channel plugins that use createTypingCallbacks from the plugin SDK – not limited to Matrix. Any channel where typing indicators have a server-side timeout will experience the same issue during long inference calls.

Steps to reproduce

  1. Configure Matrix channel plugin with a homeserver (e.g. Continuwuity)
  2. Set session.typingIntervalSeconds: 1 in openclaw.json
  3. Send a message to the agent that triggers a long LLM inference (e.g. a complex reasoning task via DeepSeek V3.2, typical response time 30-60s)
  4. Observe the typing indicator in the Matrix client (tested with Cinny)
  5. The typing indicator appears for ~5 seconds, then disappears while the agent is still processing
  6. The response eventually arrives, but there is no visual feedback during the wait

Expected behavior

The typing indicator should remain visible continuously from the moment the agent starts processing until the response is delivered.

Actual behavior

The typing indicator appears for approximately 5 seconds after the agent starts processing, then disappears. The agent continues working silently with no visual feedback. The response eventually arrives after 30-60+ seconds, but during that time the user has no way of knowing whether the agent is still processing or has encountered an error.

OpenClaw version

2026.2.23

Operating system

MacOS

Install method

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions