Skip to content

Add periodic toolset status refresh for server mode - #1354

Merged
RoiGlinik merged 3 commits into
masterfrom
claude/fix-toolset-status-check-W0yHB
Jan 15, 2026
Merged

RoiGlinik merged 3 commits into
masterfrom
claude/fix-toolset-status-check-W0yHB

Conversation

@arikalon1

@arikalon1 arikalon1 commented Jan 10, 2026 •

Copy link
Copy Markdown
Collaborator

Toolset availability can change after server startup (e.g., a database becoming available after Holmes starts). This adds a background task that periodically re-checks toolset prerequisites and updates the ToolExecutor when status changes.

Changes:

  • Add TOOLSET_STATUS_REFRESH_INTERVAL_SECONDS env var (default 300s)
  • Add refresh_server_toolsets_and_get_changes() to detect status changes
  • Add refresh_server_tool_executor() to Config for updating toolsets
  • Add background refresh thread that logs when toolset states change
  • Set interval to 0 to disable periodic refresh

Summary by CodeRabbit

  • New Features

    • Automatic background toolset status refresh runs at startup and periodically, logging detected status changes.
    • On-demand refresh returns detected status changes so updates can be applied without restart.
    • Optional "silent" mode to suppress prerequisite-check logging and reduce noise during toolset listing.
  • Chores

    • Configurable refresh interval via environment variable (default 300 seconds); setting ≤0 disables the periodic loop.

✏️ Tip: You can customize this high-level summary in your review settings.

@linux-foundation-easycla

linux-foundation-easycla Bot commented Jan 10, 2026 •

Copy link
Copy Markdown

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: RoiGlinik / name: Roi Glinik (21199d8)

@github-actions

github-actions Bot commented Jan 10, 2026 •

Copy link
Copy Markdown
Contributor

📂 Previous Runs

📜 Run @ 45bec40 (#21032504026)

✅ Results of HolmesGPT evals

Automatically triggered by commit 45bec40 on branch claude/fix-toolset-status-check-W0yHB

View workflow logs

⚠️ No eval report was generated.

📜 Run @ 796a89c (#20877126940)

✅ Results of HolmesGPT evals

Automatically triggered by commit 796a89c on branch claude/fix-toolset-status-check-W0yHB

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 43.4s ↑32% 7 14 $0.1827
✅ 101_loki_historical_logs_pod_deleted 43.2s ↓24% 6 11 $0.1717
✅ 111_pod_names_contain_service 51.2s ↑31% 8 19 $0.1915
✅ 12_job_crashing 60.6s ↑18% 9 20 $0.2343
✅ 162_get_runbooks 55.2s ±0% 8 14 $0.2071
✅ 176_network_policy_blocking_traffic_no_runbooks 47.4s ↑11% 8 16 $0.2036
✅ 24_misconfigured_pvc 44.6s ↑15% 7 18 $0.1823
✅ 43_current_datetime_from_prompt 4.2s ↑26% 1 — $0.0618
✅ 61_exact_match_counting 13.0s ↑18% 3 3 $0.0859
Total 40.3s avg 6.3 avg 14.4 avg $1.5208

Time/Cost columns show % change vs historical average (↑slower/costlier, ↓faster/cheaper). Changes under 10% shown as ±0%.

Historical Comparison Details

Filter: excluding branch 'claude/fix-toolset-status-check-W0yHB'

Status: Success - 12 test/model combinations loaded

Experiments compared (30):

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)
📜 Run @ 67efa45 (#20876371951)

✅ Results of HolmesGPT evals

Automatically triggered by commit 67efa45 on branch claude/fix-toolset-status-check-W0yHB

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 33.3s ±0% 5 12 $0.1520
✅ 101_loki_historical_logs_pod_deleted 38.9s ↓30% 5 11 $0.1604
✅ 111_pod_names_contain_service 44.3s ↑13% 7 16 $0.1854
✅ 12_job_crashing 56.2s ±0% 9 20 $0.2253
✅ 162_get_runbooks 45.1s ↓16% 6 16 $0.1972
✅ 176_network_policy_blocking_traffic_no_runbooks 50.2s ↑15% 8 15 $0.1907
✅ 24_misconfigured_pvc 40.3s ±0% 7 17 $0.1775
✅ 43_current_datetime_from_prompt 3.5s ±0% 1 — $0.0618
✅ 61_exact_match_counting 11.8s ±0% 3 3 $0.0859
Total 36.0s avg 5.7 avg 13.8 avg $1.4362

Time/Cost columns show % change vs historical average (↑slower/costlier, ↓faster/cheaper). Changes under 10% shown as ±0%.

Historical Comparison Details

Filter: excluding branch 'claude/fix-toolset-status-check-W0yHB'

Status: Success - 14 test/model combinations loaded

Experiments compared (30):

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)
📜 Run @ 995a93f (#20875249835)

✅ Results of HolmesGPT evals

Automatically triggered by commit 995a93f on branch claude/fix-toolset-status-check-W0yHB

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 34.1s ±0% 6 13 $0.1648
✅ 101_loki_historical_logs_pod_deleted 60.3s ±0% 8 18 $0.2549
✅ 111_pod_names_contain_service 36.5s ±0% 6 15 $0.1713
✅ 12_job_crashing 49.6s ±0% 9 20 $0.2378
✅ 162_get_runbooks 56.1s ±0% 8 16 $0.2400
✅ 176_network_policy_blocking_traffic_no_runbooks 43.0s ±0% 7 15 $0.1917
✅ 24_misconfigured_pvc 37.3s ±0% 7 17 $0.1798
✅ 43_current_datetime_from_prompt 3.4s ±0% 1 — $0.0618
✅ 61_exact_match_counting 11.2s ±0% 3 3 $0.0859
Total 36.8s avg 6.1 avg 14.6 avg $1.5880

Time/Cost columns show % change vs historical average (↑slower/costlier, ↓faster/cheaper). Changes under 10% shown as ±0%.

Historical Comparison Details

Filter: excluding branch 'claude/fix-toolset-status-check-W0yHB'

Status: Success - 14 test/model combinations loaded

Experiments compared (30):

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)

✅ Results of HolmesGPT evals

Automatically triggered by commit 21199d8 on branch claude/fix-toolset-status-check-W0yHB

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 34.8s ±0% 6 13 $0.1656
✅ 101_loki_historical_logs_pod_deleted 61.1s ±0% 9 18 $0.2323
✅ 111_pod_names_contain_service 41.6s ±0% 7 15 $0.1774
✅ 12_job_crashing 54.9s ↑13% 9 19 $0.2324
✅ 162_get_runbooks 43.8s ↓15% 7 14 $0.2077
✅ 176_network_policy_blocking_traffic_no_runbooks 40.2s ±0% 7 14 $0.1845
✅ 24_misconfigured_pvc 44.9s ↑15% 8 18 $0.1951
✅ 43_current_datetime_from_prompt 3.4s ±0% 1 — $0.0618
✅ 61_exact_match_counting 10.9s ±0% 3 3 $0.0859
Total 37.3s avg 6.3 avg 14.2 avg $1.5426

Time/Cost columns show % change vs historical average (↑slower/costlier, ↓faster/cheaper). Changes under 10% shown as ±0%.

Historical Comparison Details

Filter: excluding branch 'claude/fix-toolset-status-check-W0yHB'

Status: Success - 16 test/model combinations loaded

Experiments compared (30):

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)
📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: /eval comments always run using the workflow from master, not from this PR branch. If you modified the GitHub Action (e.g., added secrets or env vars), those changes won't take effect.

To test workflow changes, use the GitHub CLI or Actions UI instead:

gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref claude/fix-toolset-status-check-W0yHB -f markers=regression -f filter=

Option 1: Comment on this PR with /eval:

/eval
markers: regression

Or with more options (one per line):

/eval
model: gpt-4o
markers: regression
filter: 09_crashpod
iterations: 5

Run evals on a different branch (e.g., master) for comparison:

/eval
branch: master
markers: regression
Option Description
model Model(s) to test (default: same as automatic runs)
markers Pytest markers (no default - runs all tests!)
filter Pytest -k filter (use /list to see valid eval names)
iterations Number of runs, max 10
branch Run evals on a different branch (for cross-branch comparison)

Quick re-run: Use /rerun to re-run the most recent /eval on this PR with the same parameters.

Option 2: Trigger via GitHub Actions UI → "Run workflow"

🏷️ Valid markers

benchmark, chain-of-causation, compaction, context_window, coralogix, counting, database, datadog, datetime, easy, elasticsearch, embeds, frontend, grafana-dashboard, hard, kafka, kubernetes, leaked-information, logs, loki, medium, metrics, network, newrelic, no-cicd, numerical, one-test, port-forward, prometheus, question-answer, regression, runbooks, slackbot, storage, toolset-limitation, traces, transparency


Commands: /eval · /rerun · /list

CLI: gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref claude/fix-toolset-status-check-W0yHB -f markers=regression -f filter=

@coderabbitai

coderabbitai Bot commented Jan 10, 2026 •

Copy link
Copy Markdown
Contributor

Walkthrough

Adds an environment-configurable background loop that periodically refreshes server toolset statuses, a new env var, a ToolsetManager method to compute status changes, a Config method to apply them, and silent-mode prerequisite checks to reduce logging during listing.

Changes

Cohort / File(s) Summary
Environment Configuration
holmes/common/env_vars.py
Added TOOLSET_STATUS_REFRESH_INTERVAL_SECONDS (env-driven integer, default 300; 0 disables refresh).
Toolset Manager
holmes/core/toolset_manager.py
Added refresh_server_toolsets_and_get_changes(current_toolsets, dal) to list server toolsets, compare statuses, and return (new_toolsets, changes); added silent parameter to _list_all_toolsets and propagated to prerequisite checks.
Toolset Prerequisite Handling
holmes/core/tools.py
Toolset.check_prerequisites(self, silent: bool = False) — added silent flag to suppress success/failure logging when True.
Config Integration
holmes/config.py
Added refresh_server_tool_executor(self, dal: Optional["SupabaseDal"]) -> list[tuple[str,str,str]] to invoke the manager refresh, rebuild server executor if changes, and return list of (name, old_status, new_status).
Server Startup & Background Loop
server.py
Imported TOOLSET_STATUS_REFRESH_INTERVAL_SECONDS; added _toolset_status_refresh_loop() which starts a daemon thread that uses the env interval to call config.refresh_server_tool_executor(dal) periodically and logs per-change or no-change events; started during readiness/startup and at main.

Sequence Diagram(s)

sequenceDiagram
    participant Server
    participant Bg as BackgroundThread
    participant Config
    participant TM as ToolsetManager
    participant DAL

    Server->>Bg: start refresh loop (interval from env)
    loop every interval
        Bg->>Config: refresh_server_tool_executor(dal)
        Config->>Config: inspect current server executor toolsets
        Config->>TM: refresh_server_toolsets_and_get_changes(current_toolsets, dal)
        TM->>DAL: list server toolsets (may check prerequisites, silent)
        TM-->>Config: (new_toolsets, changes)
        alt changes exist
            Config->>Config: rebuild server_tool_executor with new_toolsets
        end
        Config-->>Bg: return changes
        Bg->>Bg: log changes or "no changes"
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Fix server loading tools #534 — Modifies holmes/core/toolset_manager.py and _list_all_toolsets usage; likely touches the same listing and prerequisite logic this PR extends.

Suggested reviewers

  • arikalon1
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add periodic toolset status refresh for server mode' accurately summarizes the main change: introducing a background periodic mechanism to refresh toolset status in server mode.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jan 10, 2026 •

Copy link
Copy Markdown
Contributor

✅ Docker image ready for 9e53564 (built in 58s)

⚠️ Warning: does not support ARM (ARM images are built on release only - not on every PR)

Use this tag to pull the image for testing.

📋 Copy commands

⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:

gcloud auth configure-docker us-central1-docker.pkg.dev
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:9e53564
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:9e53564 me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:9e53564
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:9e53564

Patch Helm values in one line (choose the chart you use):

HolmesGPT chart:

helm upgrade --install holmesgpt ./helm/holmes \
  --set registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set image=holmes-dev:9e53564

Robusta wrapper chart:

helm upgrade --install robusta robusta/robusta \
  --reuse-values \
  --set holmes.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.image=holmes-dev:9e53564

@netlify

netlify Bot commented Jan 10, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for holmes-docs ready!

Name Link
🔨 Latest commit 21199d8
🔍 Latest deploy log https://app.netlify.com/projects/holmes-docs/deploys/6968f8e5682be800086c7b46
😎 Deploy Preview https://deploy-preview-1354--holmes-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @server.py:
- Around line 114-146: Move the "import threading" out of
_toolset_status_refresh_loop and place it at module-level with the other
imports; remove the in-function import so threading.Thread is referenced from
the top-level import. Additionally, if you want the first refresh to run
immediately instead of waiting the full interval, call
config.refresh_server_tool_executor(dal) once (handling and logging
changes/exceptions exactly as done in refresh_loop) before entering the while
True: time.sleep(interval) loop inside the refresh_loop function.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 35276a8 and 995a93fbb2b4a09c29bc2cee91c185631927ed21.

📒 Files selected for processing (4)
  • holmes/common/env_vars.py
  • holmes/config.py
  • holmes/core/toolset_manager.py
  • server.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Always place Python imports at the top of the file, not inside functions or methods
Use Ruff for formatting and linting with configuration in pyproject.toml
Type hints required (mypy configuration in pyproject.toml)
Pre-commit hooks enforce quality checks on Python files

Files:

  • holmes/core/toolset_manager.py
  • holmes/common/env_vars.py
  • server.py
  • holmes/config.py
🧬 Code graph analysis (3)
holmes/core/toolset_manager.py (1)
holmes/core/tools.py (3)
  • Toolset (525-769)
  • ToolsetStatusEnum (123-126)
  • check_prerequisites (674-748)
server.py (1)
holmes/config.py (2)
  • refresh_server_tool_executor (286-311)
  • dal (123-126)
holmes/config.py (2)
holmes/core/toolset_manager.py (1)
  • refresh_server_toolsets_and_get_changes (385-421)
holmes/core/tools_utils/tool_executor.py (1)
  • ToolExecutor (14-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build
  • GitHub Check: llm_evals
  • GitHub Check: build (3.12)
  • GitHub Check: build (3.10)
  • GitHub Check: build (3.11)
🔇 Additional comments (5)
holmes/common/env_vars.py (1)

132-137: LGTM! Clean addition of the refresh interval configuration.

The constant follows the existing pattern in the file, has clear documentation, and the 5-minute default interval is reasonable for a background health check task.

holmes/core/toolset_manager.py (1)

385-422: LGTM! Well-implemented refresh and change detection method.

The logic correctly:

  • Captures the current state of all toolsets
  • Re-runs prerequisite checks via _list_all_toolsets
  • Detects and reports status transitions (e.g., FAILED → ENABLED)

Note: The method only reports changes for toolsets that already exist (Line 418's old_status is not None check). Newly discovered toolsets won't appear in the changes list, which aligns with the PR's focus on detecting status changes rather than toolset discovery.

holmes/config.py (1)

286-311: LGTM! Clean integration of the refresh mechanism.

The method properly:

  • Handles the bootstrap case when no executor exists yet (Lines 295-298)
  • Delegates change detection to ToolsetManager
  • Only recreates the executor when changes are detected (optimization)
  • Returns a clean, serializable format with string values instead of enums
server.py (2)

41-41: LGTM! Import correctly placed at module level.


486-486: LGTM! Correct placement in startup sequence.

The refresh loop is started after the initial toolset sync (line 485) and before the server begins accepting requests. The daemon thread ensures it won't prevent clean shutdown.

Comment thread server.py
@arikalon1
arikalon1 force-pushed the claude/fix-toolset-status-check-W0yHB branch from 995a93f to 67efa45 Compare January 10, 2026 09:35

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @holmes/config.py:
- Around line 286-303: The method refresh_server_tool_executor reads and
replaces self._server_tool_executor without synchronization, risking race
conditions; add a threading.Lock attribute (e.g., _server_tool_executor_lock) to
the Config class and use it to protect both the read of
self._server_tool_executor.toolsets in refresh_server_tool_executor and the
write that assigns self._server_tool_executor = ToolExecutor(new_toolsets); also
acquire the same lock around any other accesses (notably create_tool_executor
and any request-handling getters) to ensure consistent reads/writes to
_server_tool_executor.
🧹 Nitpick comments (1)
holmes/core/toolset_manager.py (1)

385-407: Consider documenting performance characteristics.

The method re-checks prerequisites for all toolsets on each call, which involves I/O operations (network checks, command execution, etc.). While the 5-minute default interval makes this acceptable, users reducing TOOLSET_STATUS_REFRESH_INTERVAL_SECONDS significantly might experience performance issues. Consider adding a comment documenting this behavior or suggesting a minimum safe interval.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 995a93fbb2b4a09c29bc2cee91c185631927ed21 and 67efa45499eac5fc63f73be92e0298476dda5e54.

📒 Files selected for processing (4)
  • holmes/common/env_vars.py
  • holmes/config.py
  • holmes/core/toolset_manager.py
  • server.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • server.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Always place Python imports at the top of the file, not inside functions or methods
Use Ruff for formatting and linting with configuration in pyproject.toml
Type hints required (mypy configuration in pyproject.toml)
Pre-commit hooks enforce quality checks on Python files

Files:

  • holmes/common/env_vars.py
  • holmes/core/toolset_manager.py
  • holmes/config.py
🧬 Code graph analysis (2)
holmes/core/toolset_manager.py (1)
holmes/core/tools.py (2)
  • Toolset (525-769)
  • ToolsetStatusEnum (123-126)
holmes/config.py (2)
holmes/core/toolset_manager.py (1)
  • refresh_server_toolsets_and_get_changes (385-407)
holmes/core/tools_utils/tool_executor.py (1)
  • ToolExecutor (14-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: llm_evals
  • GitHub Check: build (3.10)
  • GitHub Check: build (3.12)
  • GitHub Check: build (3.11)
🔇 Additional comments (2)
holmes/common/env_vars.py (1)

132-137: LGTM! Well-documented environment variable.

The constant follows the established pattern, has a reasonable default (5 minutes), and includes clear documentation about the disable-via-zero behavior.

holmes/core/toolset_manager.py (1)

385-407: LGTM! Logic correctly detects toolset status changes.

The method appropriately:

  • Maps old statuses from current toolsets
  • Re-checks prerequisites via _list_all_toolsets()
  • Identifies only actual status changes (ignoring new toolsets)
  • Returns both updated toolsets and the change list

One observation: removed toolsets (present in current_toolsets but absent in new_toolsets) won't be reported. If this is intentional for server mode, consider adding a comment to clarify.

Comment thread holmes/config.py
Toolset availability can change after server startup (e.g., a database
becoming available after Holmes starts). This adds a background task
that periodically re-checks toolset prerequisites and updates the
ToolExecutor when status changes.

Changes:
- Add TOOLSET_STATUS_REFRESH_INTERVAL_SECONDS env var (default 300s)
- Add refresh_server_toolsets_and_get_changes() to detect status changes
- Add refresh_server_tool_executor() to Config for updating toolsets
- Add background refresh thread that logs when toolset states change
- Add silent parameter to check_prerequisites() to suppress logs during
  periodic refresh (only status changes are logged)
- Set interval to 0 to disable periodic refresh

Signed-off-by: Claude <noreply@anthropic.com>
@arikalon1
arikalon1 force-pushed the claude/fix-toolset-status-check-W0yHB branch from 67efa45 to 796a89c Compare January 10, 2026 10:43

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
holmes/config.py (1)

286-303: Consider thread safety for concurrent access.

The _server_tool_executor is accessed from multiple places (API endpoints via create_tool_executor and the background refresh thread). While Python's GIL makes the reference assignment atomic, there's a potential race where an ongoing request could be using the old executor while the refresh is happening.

This is likely acceptable for this use case since:

  1. The old executor remains valid until garbage collected
  2. Requests in flight will complete with the old executor
  3. New requests will pick up the new executor

However, if you want stronger guarantees, consider adding a threading.Lock around the executor access/assignment.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67efa45499eac5fc63f73be92e0298476dda5e54 and 796a89c.

📒 Files selected for processing (5)
  • holmes/common/env_vars.py
  • holmes/config.py
  • holmes/core/tools.py
  • holmes/core/toolset_manager.py
  • server.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • holmes/common/env_vars.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Always place Python imports at the top of the file, not inside functions or methods
Use Ruff for formatting and linting with configuration in pyproject.toml
Type hints required (mypy configuration in pyproject.toml)
Pre-commit hooks enforce quality checks on Python files

Files:

  • holmes/core/tools.py
  • holmes/core/toolset_manager.py
  • server.py
  • holmes/config.py
🧠 Learnings (1)
📚 Learning: 2026-01-05T11:14:20.222Z
Learnt from: CR
Repo: HolmesGPT/holmesgpt PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-05T11:14:20.222Z
Learning: Applies to holmes/plugins/toolsets/**/*.py : Include health check in prerequisites_callable() method for Python toolsets

Applied to files:

  • holmes/core/tools.py
  • holmes/core/toolset_manager.py
🧬 Code graph analysis (2)
holmes/core/toolset_manager.py (1)
holmes/core/tools.py (3)
  • Toolset (525-771)
  • check_prerequisites (674-750)
  • ToolsetStatusEnum (123-126)
holmes/config.py (2)
holmes/core/toolset_manager.py (1)
  • refresh_server_toolsets_and_get_changes (386-409)
holmes/core/tools_utils/tool_executor.py (1)
  • ToolExecutor (14-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build (3.12)
  • GitHub Check: llm_evals
  • GitHub Check: build (3.10)
  • GitHub Check: build (3.11)
🔇 Additional comments (6)
holmes/core/tools.py (1)

674-750: LGTM!

The silent parameter addition is well-implemented with a sensible default of False to maintain backward compatibility. The guards around logging statements (if not silent) correctly suppress both failure and success messages during silent mode, which is appropriate for the periodic refresh use case to avoid log spam.

server.py (2)

115-143: LGTM!

The background refresh loop implementation is well-structured:

  • Correctly checks for disabled state (interval <= 0) and returns early
  • Uses a daemon thread, ensuring it won't block server shutdown
  • Sleeps before the first check, avoiding redundant work right after startup
  • Has proper exception handling with exc_info=True for debugging
  • Logs changes at INFO level and no-changes at DEBUG level, which is appropriate to avoid log noise

483-485: LGTM!

The placement of _toolset_status_refresh_loop() is correct - it runs after sync_before_server_start() completes (which does initial toolset sync) and before the server starts accepting requests.

holmes/core/toolset_manager.py (3)

95-102: LGTM!

The silent parameter is properly added to _list_all_toolsets with a backward-compatible default of False.


175-183: LGTM!

The silent parameter is correctly propagated through check_toolset_prerequisites to each individual toolset's check_prerequisites call.


386-409: Verify that not reporting new/removed toolsets is intentional.

The change detection logic only reports status changes for toolsets that existed in both the old and new sets. If a toolset is newly added or removed entirely, it won't appear in the changes list.

This is likely intentional since:

  1. New toolsets would have no "old status" to compare against
  2. Removed toolsets wouldn't be in the new list to iterate over

If you want to also log when toolsets are added or removed, additional logic would be needed.

@RoiGlinik
RoiGlinik enabled auto-merge (squash) January 15, 2026 14:25

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@server.py`:
- Around line 115-143: The refresh loop can race with request handlers because
_server_tool_executor is replaced without synchronization; add a dedicated
threading.Lock (e.g., _server_tool_executor_lock) and use it to guard all
accesses: acquire the lock around the check-and-cache logic in
create_tool_executor and around the read-and-replace logic inside
refresh_server_tool_executor (the code invoked by _toolset_status_refresh_loop),
ensuring the refresh thread holds the lock while updating _server_tool_executor
and request threads hold the lock while reading/caching it so no concurrent
read/write occurs.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 796a89c and 21199d8.

📒 Files selected for processing (1)
  • server.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Always place Python imports at the top of the file, not inside functions or methods
Use Ruff for formatting and linting with configuration in pyproject.toml
Type hints required (mypy configuration in pyproject.toml)
Pre-commit hooks enforce quality checks on Python files

Files:

  • server.py
**/*.{js,ts,tsx,jsx,py,java,cs,go,rb,php}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,tsx,jsx,py,java,cs,go,rb,php}: Use semantic, descriptive names for variables, functions, and components
Write clear, concise comments that explain 'why' rather than 'what'

Files:

  • server.py
🧬 Code graph analysis (1)
server.py (1)
holmes/config.py (2)
  • refresh_server_tool_executor (286-303)
  • dal (123-126)
🔇 Additional comments (2)
server.py (2)

26-26: LGTM!

The threading import has been correctly moved to module level as per the coding guidelines, and the new environment variable import is appropriately placed with other imports from holmes.common.env_vars.

Also applies to: 42-42


487-489: The refresh loop runs in the production deployment as intended.

The codebase is deployed via python3 -u server.py (as shown in the Helm chart), which executes the __main__ block and starts the refresh loop as a daemon thread. This is the documented deployment method. There is no evidence of support for alternative deployment methods (e.g., uvicorn server:app or gunicorn), so the hypothetical concern does not apply.

Likely an incorrect or invalid review comment.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread server.py
@RoiGlinik
RoiGlinik merged commit a1621ff into master Jan 15, 2026
16 of 17 checks passed
@RoiGlinik
RoiGlinik deleted the claude/fix-toolset-status-check-W0yHB branch January 15, 2026 15:26
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.

3 participants