Skip to content

Expand bash tool guidance to prioritize dedicated Kubernetes tools - #2151

Open
aantn wants to merge 4 commits into
masterfrom
claude/k8s-no-bash-approval-fix
Open

aantn wants to merge 4 commits into
masterfrom
claude/k8s-no-bash-approval-fix

Conversation

@aantn

@aantn aantn commented Jun 7, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Significantly expands the bash tool instructions to guide users toward dedicated Kubernetes tools (kubernetes_jq_query, kubernetes_tabular_query, kubernetes_count) instead of bash pipelines for aggregation, filtering, grouping, and counting operations. This improves user experience by reducing approval prompts and token usage while increasing reliability.

Key Changes

  • New "Tool Selection" section explaining why dedicated tools should be preferred over bash for Kubernetes operations:

    • Approval prompts interrupt user flow (compound bash constructs require explicit approval)
    • Bash allowlist gates every pipeline segment, blocking entire pipelines if one segment isn't allowed
    • Text parsing is fragile and fails silently (e.g., wc -l counts headers, awk breaks with column shifts)
    • Server-side filtering in dedicated tools keeps token budgets small
    • Structured calls produce readable, reviewable traces
  • Common anti-patterns section with concrete examples of what to avoid:

    • Counting/grouping with kubectl get ... | awk | sort | uniq -c → use kubernetes_count
    • Counting rows with kubectl get ... | wc -l → use kubernetes_count
    • Selecting distinct values with kubectl get ... | awk | sort -u → use kubernetes_jq_query
    • Iterating with for loops → use single batched kubernetes_jq_query or kubernetes_tabular_query
  • Updated pipe example from kubectl get pods | grep Running | head -5 to cat /var/log/app.log | grep ERROR | head -20 with a note warning against piping kubectl output through aggregation tools

  • Clarified bash use cases: Single kubectl get calls, specific kubectl flags (-o yaml, -o wide, --show-labels), and non-kubectl tools are appropriate; grouping, counting, joining, and set operations are not

  • Refined guidance on loops/conditionals: Added emphasis to minimize approval prompts by checking if a dedicated tool or batched kubectl get can accomplish the task first

  • Minor formatting: Changed "Requires user approval -" to "Requires user approval —" for consistency

https://claude.ai/code/session_01ShMKrLaC9Dddn41ZJM6CWW

Summary by CodeRabbit

  • Documentation
    • Added guidance recommending dedicated Kubernetes tools or batched queries instead of complex Bash aggregation/filtering.
    • Clarified examples and anti-patterns to avoid (e.g., per-item loops and pipe-based aggregation) and adjusted approval-prompt guidance to minimize unnecessary prompts and favor simpler approaches.

claude added 2 commits June 7, 2026 10:15
The previous bash instructions used `kubectl get pods | grep Running | head -5`
as the canonical "pipe is auto-approved" example. That implicitly endorsed
piping kubectl output through awk/sort/uniq -c/wc to do grouping and counting,
which is exactly the anti-pattern that produces the customer pain reported in
this branch: instead of a single kubernetes_count / kubernetes_jq_query /
kubernetes_tabular_query call, the LLM stitched together shell pipelines that
either required approval (loops, command substitution) or produced noisy
investigation traces.

This change adds a "Tool Selection — Prefer Dedicated Tools" section at the
top of the bash instructions that:

  * Tells the model to check for a dedicated K8s tool before reaching for bash.
  * Enumerates the four most common anti-patterns (group-by-uniq, wc -l counts,
    distinct-via-sort-u, per-resource for-loops) and points each one at the
    dedicated tool that replaces it.
  * Carves out the legitimate uses of bash — one-off `kubectl get` with a
    specific flag, non-kubectl invocations — so the guidance does not over-rotate.

Two smaller edits below:

  * The "Pipes" example is changed from `kubectl get pods | grep ...` to a
    log-grep example, with a one-line reminder pointing at the new section.
  * The "go ahead and use loops" line is replaced with a check-first prompt
    that mentions the cost of approval prompts.

This is prompt guidance, not a behavior gate — the model can still pipe kubectl
when it judges that the right choice (e.g. when no dedicated tool fits). The
goal is to flip the default for grouping/counting/joining work back to the
dedicated tools.

Pairs with the 259/260/261/262/263/264 evals on this branch which lock in the
preference. Verification against opus-4.6 with full iteration counts is
pending — the OpenRouter weekly credit limit was hit during testing.

Signed-off-by: Claude <noreply@anthropic.com>
The previous "Tool Selection" section told the LLM what to do but not why,
so it couldn't apply the principle to novel question shapes it hadn't seen
before. Replace the generic "faster, more reliable, cleaner trace" line
with the five concrete costs of choosing bash when a dedicated tool fits:

  1. Compound bash (loops, ifs, command substitution) requires explicit
     user approval per call and interrupts the user mid-investigation.
     Dedicated tools and simple kubectl gets are auto-approved.
  2. The bash allowlist gates every pipeline segment. A pipeline is only
     auto-approved if every segment (awk, sort, uniq, wc, grep, cut, ...)
     is on the configured allowlist; if one isn't, the whole pipeline
     blocks waiting for approval — or fails outright in deployments that
     auto-deny. Dedicated tools sidestep the allowlist entirely.
  3. Text parsing is fragile and fails silently. wc -l counts headers,
     awk column indexing breaks under -o wide, empty awk matches look
     like "0 results" rather than "bad pipeline". Dedicated tools work
     on JSON via jq and return actionable errors instead of plausible
     false answers.
  4. Server-side filtering keeps token budgets small. kubernetes_jq_query
     projects only the asked-for fields on the API server; kubectl get -A
     pipes the full status of every resource into the conversation. On
     real clusters with hundreds of pods, this difference is enormous
     and persists across every subsequent turn until compaction.
  5. Structured tool calls produce readable traces. A
     kubernetes_count(kind=..., jq=...) line survives compaction with
     its intent intact; a 200-character shell pipeline does not.

These are exactly the reasons opus-4.6 sometimes still picked the bash
path in our internal probes even after the first "Tool Selection" pass —
the principle was abstract and didn't connect to consequences the model
could weigh against the convenience of a one-liner. With the five costs
spelled out, the model has the information needed to make the same
trade-off on cases that aren't in the explicit anti-pattern list.

Signed-off-by: Claude <noreply@anthropic.com>

@claude claude 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.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@github-actions

github-actions Bot commented Jun 7, 2026 •

Copy link
Copy Markdown
Contributor

📂 Previous Runs

⚠️ 1 older run truncated

Older runs were omitted to stay under GitHub's 64KB comment size limit.


✅ Results of HolmesGPT evals

Automatically triggered by commit 868d5fd on branch claude/k8s-no-bash-approval-fix

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 14/14 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost Total tokens Input Max input Output Max output Cached Non-cached Reasoning Compactions Denied commands Src
✅ 09_crashpod 28.0s 4 7 $0.2085 72,686 71,233 19,822 1,453 668 50,613 20,620 107 — — src
✅ 101_loki_historical_logs_pod_deleted 41.3s 4 8 $0.2389 73,974 71,558 20,831 2,416 813 50,451 21,107 350 — — src
✅ 112_find_pvcs_by_uuid 13.7s 2 2 $0.1617 35,003 34,137 18,881 866 448 15,253 18,884 289 — — src
✅ 12_job_crashing 27.7s 4 9 $0.2283 77,204 75,508 21,765 1,696 454 53,129 22,379 132 — — src
✅ 176_network_policy_blocking_traffic_no_skills 39.7s 5 13 $0.2618 97,115 94,715 21,984 2,400 683 71,786 22,929 374 — — src
✅ 227_count_configmaps_per_namespace[0] 14.4s 3 6 $0.1568 49,174 48,459 17,598 715 437 30,857 17,602 36 — — src
✅ 243_pod_names_contain_service 25.5s 3 7 $0.1959 52,523 50,894 18,999 1,629 573 31,224 19,670 227 — — src
✅ 24_misconfigured_pvc 30.8s 5 11 $0.2338 92,596 90,821 20,335 1,775 576 69,192 21,629 117 — — src
✅ 254_elasticsearch_dr_test_log_check 61.2s 8 11 $0.2607 104,643 101,138 17,170 3,505 1,050 83,959 17,179 231 — — src
✅ 259_wrong_cluster_logs_confusion 58.7s 8 11 $0.2705 112,332 108,915 18,069 3,417 861 90,368 18,547 268 — — src
✅ 260_global_es_remote_cluster_logs 52.8s 7 11 $0.2552 99,077 95,775 16,772 3,302 807 77,865 17,910 402 — — src
✅ 43_current_datetime_from_prompt 3.8s 1 — $0.1081 15,362 15,240 15,240 122 122 0 15,240 78 — — src
✅ 51_logs_summarize_errors 18.2s 3 2 $0.1621 49,562 48,776 17,967 786 414 30,805 17,971 40 — — src
✅ 61_exact_match_counting 7.7s 2 1 $0.1216 31,020 30,798 15,578 222 153 15,217 15,581 35 — — src
Total 30.2s avg 4.2 avg 7.6 avg $2.8638 962,271 937,967 21,984 24,304 1,050 670,719 267,248 2,686 — —
Benchmark Comparison Details

Master baseline: latest master-* experiment (post-merge regression eval)
Status: 11 test/model combinations loaded

Benchmark baseline: latest ci-benchmark experiment on master
Status: 185 test/model combinations loaded

Time comparison (seconds):

Test case This branch master (5h ago) Δ vs master benchmark (12h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 28.0s 26.2s ±0% 41.4s ↓32%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 41.3s 47.6s ↓13% 65.7s ↓37%
112_find_pvcs_by_uuid (opus-4.6) 📄 13.7s 10.6s ↑30% 19.0s ↓28%
12_job_crashing (opus-4.6) 📄 27.7s 27.6s ±0% 42.6s ↓35%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 39.7s 32.6s ↑22% 44.3s ↓10%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 14.4s 13.2s ±0% 18.4s ↓22%
243_pod_names_contain_service (opus-4.6) 📄 25.5s 28.8s ↓12% 35.1s ↓27%
24_misconfigured_pvc (opus-4.6) 📄 30.8s 31.4s ±0% 40.6s ↓24%
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 61.2s — — — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 58.7s — — — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 52.8s — — — —
43_current_datetime_from_prompt (opus-4.6) 📄 3.8s 3.1s ↑23% 3.5s ±0%
51_logs_summarize_errors (opus-4.6) 📄 18.2s 18.8s ±0% 19.7s ±0%
61_exact_match_counting (opus-4.6) 📄 7.7s 7.1s ±0% 10.2s ↓25%
Total (all, n=14) 30.2s 22.5s — 31.0s —
Comparable (m=11, b=11) 22.8s 22.5s ±0% 31.0s ↓26%

Cost comparison:

Test case This branch master (5h ago) Δ vs master benchmark (12h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 $0.2085 $0.2032 ±0% $0.3101 ↓33%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 $0.2389 $0.2642 ±0% $0.3829 ↓38%
112_find_pvcs_by_uuid (opus-4.6) 📄 $0.1617 $0.1368 ↑18% $0.2047 ↓21%
12_job_crashing (opus-4.6) 📄 $0.2283 $0.2173 ±0% $0.3167 ↓28%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 $0.2618 $0.2524 ±0% $0.3179 ↓18%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 $0.1568 $0.1464 ±0% $0.2048 ↓23%
243_pod_names_contain_service (opus-4.6) 📄 $0.1959 $0.1872 ±0% $0.2662 ↓26%
24_misconfigured_pvc (opus-4.6) 📄 $0.2338 $0.2240 ±0% $0.3110 ↓25%
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 $0.2607 — — — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 $0.2705 — — — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 $0.2552 — — — —
43_current_datetime_from_prompt (opus-4.6) 📄 $0.1081 $0.0110 ↑884% $0.1190 ±0%
51_logs_summarize_errors (opus-4.6) 📄 $0.1621 $0.1488 ±0% $0.2018 ↓20%
61_exact_match_counting (opus-4.6) 📄 $0.1216 $0.1112 ±0% $0.1518 ↓20%
Total (all, n=14) $0.2046 $0.1730 — $0.2534 —
Comparable (m=11, b=11) $0.1889 $0.1730 ±0% $0.2534 ↓25%

Total tokens comparison:

Test case This branch master (5h ago) Δ vs master benchmark (12h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 72,686 67,778 ±0% 132,351 ↓45%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 73,974 88,307 ↓16% 144,907 ↓49%
112_find_pvcs_by_uuid (opus-4.6) 📄 35,003 30,686 ↑14% 61,219 ↓43%
12_job_crashing (opus-4.6) 📄 77,204 69,487 ↑11% 136,570 ↓43%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 97,115 108,726 ↓11% 113,514 ↓14%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 49,174 44,988 ±0% 76,715 ↓36%
243_pod_names_contain_service (opus-4.6) 📄 52,523 48,612 ±0% 104,698 ↓50%
24_misconfigured_pvc (opus-4.6) 📄 92,596 68,923 ↑34% 132,672 ↓30%
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 104,643 — — — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 112,332 — — — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 99,077 — — — —
43_current_datetime_from_prompt (opus-4.6) 📄 15,362 13,970 ±0% 17,001 ±0%
51_logs_summarize_errors (opus-4.6) 📄 49,562 45,163 ±0% 77,120 ↓36%
61_exact_match_counting (opus-4.6) 📄 31,020 28,231 ±0% 52,716 ↓41%
Total (all, n=14) 68,734 55,897 — 95,408 —
Comparable (m=11, b=11) 58,747 55,897 ±0% 95,408 ↓38%

Cached tokens comparison:

Test case This branch master (5h ago) Δ vs master benchmark (12h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 50,613 46,700 ±0% 102,543 ↓51%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 50,451 64,209 ↓21% 109,927 ↓54%
112_find_pvcs_by_uuid (opus-4.6) 📄 15,253 13,861 ↑10% 38,090 ↓60%
12_job_crashing (opus-4.6) 📄 53,129 46,249 ↑15% 107,265 ↓50%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 71,786 84,274 ↓15% 82,679 ↓13%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 30,857 28,072 ±0% 54,602 ↓43%
243_pod_names_contain_service (opus-4.6) 📄 31,224 28,690 ±0% 78,754 ↓60%
24_misconfigured_pvc (opus-4.6) 📄 69,192 46,110 ↑50% 103,729 ↓33%
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 83,959 — — — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 90,368 — — — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 77,865 — — — —
43_current_datetime_from_prompt (opus-4.6) 📄 — 13,845 — — —
51_logs_summarize_errors (opus-4.6) 📄 30,805 28,012 ±0% 55,156 ↓44%
61_exact_match_counting (opus-4.6) 📄 15,217 13,825 ↑10% 34,481 ↓56%
Total (all, n=14) 47,908 37,622 — 69,748 —
Comparable (m=10, b=10) 41,853 40,000 ±0% 76,723 ↓45%

Turns comparison:

Test case This branch master (5h ago) Δ vs master benchmark (12h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 4 4 ±0% 6 ↓33%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 4 5 ↓20% 6 ↓33%
112_find_pvcs_by_uuid (opus-4.6) 📄 2 2 ±0% 3 ↓33%
12_job_crashing (opus-4.6) 📄 4 4 ±0% 6 ↓33%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 5 6 ↓17% 5 ±0%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 3 3 ±0% 4 ↓25%
243_pod_names_contain_service (opus-4.6) 📄 3 3 ±0% 5 ↓40%
24_misconfigured_pvc (opus-4.6) 📄 5 4 ↑25% 6 ↓17%
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 8 — — — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 8 — — — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 7 — — — —
43_current_datetime_from_prompt (opus-4.6) 📄 1 1 ±0% 1 ±0%
51_logs_summarize_errors (opus-4.6) 📄 3 3 ±0% 4 ↓25%
61_exact_match_counting (opus-4.6) 📄 2 2 ±0% 3 ↓33%
Total (all, n=14) 4.2 3.4 — 4.5 —
Comparable (m=11, b=11) 3.3 3.4 ±0% 4.5 ↓27%

Tool calls comparison:

Test case This branch master (5h ago) Δ vs master benchmark (12h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 7 8 ↓12% 13 ↓46%
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 8 11 ↓27% 14 ↓43%
112_find_pvcs_by_uuid (opus-4.6) 📄 2 2 ±0% 4 ↓50%
12_job_crashing (opus-4.6) 📄 9 9 ±0% 15 ↓40%
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 13 12 ±0% 15 ↓13%
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 6 6 ±0% 9 ↓33%
243_pod_names_contain_service (opus-4.6) 📄 7 7 ±0% 11 ↓36%
24_misconfigured_pvc (opus-4.6) 📄 11 13 ↓15% 15 ↓27%
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 11 — — — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 11 — — — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 11 — — — —
43_current_datetime_from_prompt (opus-4.6) 📄 — — — — —
51_logs_summarize_errors (opus-4.6) 📄 2 2 ±0% 5 ↓60%
61_exact_match_counting (opus-4.6) 📄 1 1 ±0% 3 ↓67%
Total (all, n=14) 7.1 7.1 — 10.4 —
Comparable (m=10, b=10) 6.6 7.1 ±0% 10.4 ↓37%

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/k8s-no-bash-approval-fix -f markers=regression -f filter=

Option 1: Comment on this PR with /eval:

/eval
tags: regression

Or with more options (one per line):

/eval
model: gpt-4o
tags: regression
id: 09_crashpod
iterations: 5

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

/eval
branch: master
tags: regression
Option Description
model Model(s) to test (default: same as automatic runs)
tags Pytest tags / markers (no default - runs all tests!)
id Eval ID / 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"

Option 3: Add PR labels to include extra evals (applies to both automatic runs and /eval comments):

Label Effect
evals-tag-<name> Run tests with tag <name> alongside regression
evals-id-<name> Run a specific eval by test ID
evals-model-<name> Override the model (use model list name, e.g. sonnet-4.5)

Examples: evals-tag-easy, evals-id-09_crashpod, evals-model-sonnet-4.5

🏷️ Valid tags

benchmark, chain-of-causation, compaction, confluence, context_window, conversation_worker, coralogix, counting, database, datadog, datetime, db-connectors, easy, elasticsearch, embeds, fast, frontend, grafana, hard, images, integration, kafka, kubernetes, leaked-information, logs, loki, manual, mcp, medium, metrics, multi-cluster, network, newrelic, no-cicd, numerical, one-test, port-forward, prometheus, question-answer, regression, skills, slackbot, storage, token-limit, toolset-limitation, traces, transparency, victorialogs

🤖 Valid models

deepseek-chat, deepseek-r1-reasoner, deepseek-reasoner, deepseek-v3.2-chat, gemini-3-flash-preview, gemini-3-pro-preview, gemini-3.1-pro-preview, gpt-4.1, gpt-5.2-high-reasoning, gpt-5.3-codex, gpt-5.4, haiku-4.5, kimi-2.5, kimi-2.5-openrouter, opus-4.5, opus-4.6, opus-4.7, qwen-next-80B-instruct, qwen-next-80B-thinking, sonnet-4.5, sonnet-4.6


Commands: /eval · /rerun · /list

CLI: gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref claude/k8s-no-bash-approval-fix -f markers=regression -f filter=

@coderabbitai

coderabbitai Bot commented Jun 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4392651c-2df7-4693-9612-6714aebede61

📥 Commits

Reviewing files that changed from the base of the PR and between b8838f6 and 5c2dc6f.

📒 Files selected for processing (1)
  • holmes/plugins/toolsets/bash/bash_instructions.jinja2
🚧 Files skipped from review as they are similar to previous changes (1)
  • holmes/plugins/toolsets/bash/bash_instructions.jinja2

Walkthrough

The bash instruction template is expanded with a new "Tool Selection — Prefer Dedicated Tools" section that identifies anti-patterns for Kubernetes data processing in bash (counting, grouping, distinct, select, iteration) and revises guidance for approval-interrupting constructs to discourage loops and conditionals in favor of dedicated tools or batched kubectl get queries.

Changes

Bash Tool Instructions Expansion

Layer / File(s) Summary
Tool Selection and Approval Guidance
holmes/plugins/toolsets/bash/bash_instructions.jinja2
New "Tool Selection — Prefer Dedicated Tools" section explains when to use dedicated Kubernetes tools vs. bash and lists anti-patterns. Approval prompt guidance is revised from permissive to prescriptive: minimize prompts by preferring dedicated tools or batched kubectl get before using loops or conditionals.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

  • HolmesGPT/holmesgpt#1360: The bash instructions changes directly align with the redesigned bash approval/prompting flow by updating guidance on when to minimize approvals and prefer dedicated tools over bash loops.

Suggested reviewers

  • arikalon1
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Expand bash tool guidance to prioritize dedicated Kubernetes tools' directly and clearly summarizes the main change: expanding bash tool instructions to steer users toward dedicated Kubernetes tools instead of bash pipelines.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 Jun 7, 2026 •

Copy link
Copy Markdown
Contributor

✅ Docker images ready for 60a0cc11d (built in 4m 25s)

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

Use these tags to pull the images 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:60a0cc11d
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:60a0cc11d me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:60a0cc11d
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:60a0cc11d
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes-operator:60a0cc11d
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes-operator:60a0cc11d me-west1-docker.pkg.dev/robusta-development/development/holmes-operator-dev:60a0cc11d
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-operator-dev:60a0cc11d

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:60a0cc11d \
  --set operator.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set operator.image=holmes-operator-dev:60a0cc11d

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:60a0cc11d \
  --set holmes.operator.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.operator.image=holmes-operator-dev:60a0cc11d

@netlify

netlify Bot commented Jun 7, 2026 •

Copy link
Copy Markdown

❌ Deploy Preview for holmes-docs failed. Why did it fail? →

Name Link
🔨 Latest commit 868d5fd
🔍 Latest deploy log https://app.netlify.com/projects/holmes-docs/deploys/6a258e7a99c9b00008b3afc4

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
holmes/plugins/toolsets/bash/bash_instructions.jinja2 (1)

3-6: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add explicit failure-report requirements for bash errors.

This template should explicitly require returning rich error context on command failure (full command executed, relevant parameters/filters/time bounds, exit status, and raw stderr) so the model can self-correct consistently.

As per coding guidelines: “All toolsets MUST return detailed error messages from underlying APIs … include the exact query/command executed, time ranges/parameters/filters used, and full API error response (status code and message).”

Proposed patch
 Use the `bash` tool to execute shell commands. You must provide:
 1. `command`: The bash command to execute
 2. `suggested_prefixes`: Array of prefixes, one per command segment
+3. On failure, return detailed error context for self-correction:
+   - Exact command/segment executed
+   - Parameters/filters/time bounds used (when applicable)
+   - Exit status and full stderr/error message from execution

Also applies to: 91-96

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@holmes/plugins/toolsets/bash/bash_instructions.jinja2` around lines 3 - 6,
Update the bash tool template to require rich failure reporting when a shell
command fails: for the `bash` tool (referencing the `command` and
`suggested_prefixes` fields) ensure the failure response includes the full
command executed, any relevant parameters/filters/time bounds passed, the
numeric exit status, and the raw stderr output (and any runtime error message);
modify the template text around the `bash` usage instructions so callers are
explicitly instructed to return that detailed error context on non-zero exits
and failed executions.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@holmes/plugins/toolsets/bash/bash_instructions.jinja2`:
- Around line 19-20: The guidance text claiming simple `kubectl get` calls are
"auto-approved" conflicts with the allowlist gating mentioned later; update the
phrase containing "kubectl get" so it explicitly states such calls are
auto-approved only when they match the configured allowlist (or are otherwise
permitted by the allowlist policy), and mirror the same clarified wording in the
later section that references auto-approval and allowlist matching (the
paragraph that currently explains allowlist-based auto-approval) so both places
consistently state that auto-approval is conditional on an allowlist match.

---

Outside diff comments:
In `@holmes/plugins/toolsets/bash/bash_instructions.jinja2`:
- Around line 3-6: Update the bash tool template to require rich failure
reporting when a shell command fails: for the `bash` tool (referencing the
`command` and `suggested_prefixes` fields) ensure the failure response includes
the full command executed, any relevant parameters/filters/time bounds passed,
the numeric exit status, and the raw stderr output (and any runtime error
message); modify the template text around the `bash` usage instructions so
callers are explicitly instructed to return that detailed error context on
non-zero exits and failed executions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 09c50c59-d96f-4b41-a045-5f97382f787d

📥 Commits

Reviewing files that changed from the base of the PR and between 478a181 and b8838f6.

📒 Files selected for processing (1)
  • holmes/plugins/toolsets/bash/bash_instructions.jinja2

Comment thread holmes/plugins/toolsets/bash/bash_instructions.jinja2 Outdated
claude added 2 commits June 7, 2026 10:55
CodeRabbit caught an inconsistency: the motivation section claimed
"Dedicated tools and simple kubectl get calls are auto-approved" with
no caveat, but later in the same file the "Auto-approved" section
correctly conditions bash auto-approval on the prefix matching the
configured allowlist. Reconcile the two:

- Dedicated tools are auto-approved unconditionally (they're separate
  tools, not bash, and don't go through the allowlist).
- Simple kubectl get is auto-approved only when its prefix is on the
  configured allowlist (which it is by default).

Same prompt-engineering intent (push the model away from compound
bash), just no longer overclaiming about the always-auto-approved
status of kubectl.

Signed-off-by: Claude <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

2 participants