Skip to content

fix: skip heartbeat when agent has an active turn#1980

Open
KristjanKruusRIA wants to merge 7 commits intosipeed:mainfrom
KristjanKruusRIA:fix/heartbeat-skip-when-busy-clean
Open

fix: skip heartbeat when agent has an active turn#1980
KristjanKruusRIA wants to merge 7 commits intosipeed:mainfrom
KristjanKruusRIA:fix/heartbeat-skip-when-busy-clean

Conversation

@KristjanKruusRIA
Copy link
Copy Markdown

@KristjanKruusRIA KristjanKruusRIA commented Mar 24, 2026

📝 Description

Prevents the heartbeat system from interrupting active agent conversations. When a user is mid-conversation with the agent, the heartbeat timer can fire and inject autonomous content (e.g. social media posts), disrupting the flow. This fix adds a busy-check guard at the top of ProcessHeartbeat that returns a HEARTBEAT_SKIPPED sentinel when any turn is active.

🗣️ Type of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📖 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

🔗 Related Issue

📚 Technical Context (Skip for Docs)

  • Reference URL: N/A
  • Reasoning: ProcessHeartbeat in pkg/agent/loop.go had no guard against firing while the agent is actively processing a user turn. The fix uses the existing activeTurnStates sync.Map (via getAnyActiveTurnState()) to detect busy state and skip the heartbeat cycle, returning HEARTBEAT_SKIPPED instead of invoking the LLM.

🧪 Test Environment

  • Hardware: PC (x86_64)
  • OS: Windows 11 / Alpine Linux (Docker)
  • Model/Provider: N/A (unit tests only, LLM mocked)
  • Channels: N/A

📸 Evidence (Optional)

Click to view Logs/Screenshots

All 4 new tests pass:

=== RUN   TestProcessHeartbeat_SkipsWhenAgentBusy
--- PASS: TestProcessHeartbeat_SkipsWhenAgentBusy (0.00s)
=== RUN   TestProcessHeartbeat_RunsWhenIdle
--- PASS: TestProcessHeartbeat_RunsWhenIdle (0.00s)
=== RUN   TestProcessHeartbeat_SkipsForAnyActiveSession
--- PASS: TestProcessHeartbeat_SkipsForAnyActiveSession (0.00s)
=== RUN   TestProcessHeartbeat_ProceedsAfterTurnClears
--- PASS: TestProcessHeartbeat_ProceedsAfterTurnClears (0.00s)
PASS
ok  	github.com/sipeed/picoclaw/pkg/agent	0.040s

☑️ Checklist

  • My code/docs follow the style of this project.
  • I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.

- Check activeTurnStates before processing heartbeat
- Return HEARTBEAT_OK immediately when agent is busy
- Log the skipped heartbeat with the active session key
- Add 4 tests covering busy, idle, multi-session, and clear scenarios
Copilot AI review requested due to automatic review settings March 24, 2026 18:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR prevents the scheduled heartbeat turn from starting while the agent is already processing another turn, avoiding concurrent-turn interference during active conversations.

Changes:

  • Add an early “agent busy” guard to AgentLoop.ProcessHeartbeat that skips heartbeat execution when any active turn exists.
  • Add unit tests covering heartbeat skip/proceed behavior based on presence/absence of active turns.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
pkg/agent/loop.go Adds a busy-check to skip heartbeat execution when any turn is active.
pkg/agent/loop_test.go Adds tests intended to validate skip/proceed behavior for heartbeat processing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@sipeed-bot sipeed-bot bot added type: bug Something isn't working domain: agent go Pull requests that update go code labels Mar 24, 2026
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 24, 2026 18:51
KristjanKruusRIA and others added 3 commits March 24, 2026 20:51
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Use registerActiveTurn/clearActiveTurn helpers instead of direct map access
- Update assertions to check HEARTBEAT_SKIPPED (matching new sentinel)
- Strengthen idle/proceeds tests to assert Mock response and err==nil
Copilot AI review requested due to automatic review settings March 24, 2026 19:16
- Fix dogsled: reduce blank identifiers in newTestAgentLoop calls
- Fix gci: auto-fixed import ordering in loop_test.go
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@afjcjsbx
Copy link
Copy Markdown
Collaborator

Hi, great insight, but it could happen that for those who use picoclaw frequently, this could always have an active turn during the heartbeat and therefore this is always skipped or postponed a lot

@afjcjsbx afjcjsbx self-requested a review March 24, 2026 21:00
@KristjanKruusRIA
Copy link
Copy Markdown
Author

Yes that might be an issue. It could be that #1937 is enough for most needs, it's just that personally the heartbeat kept constantly interjecting with old data which kept messing up the chat.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: agent go Pull requests that update go code type: bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants