Skip to content

feat: add pre_tool_call rewrite support for plugin tool arg transformation#19305

Open
elasticdotventures wants to merge 6 commits into
NousResearch:mainfrom
PromptExecution:feat/pre-tool-rewrite-hook
Open

feat: add pre_tool_call rewrite support for plugin tool arg transformation#19305
elasticdotventures wants to merge 6 commits into
NousResearch:mainfrom
PromptExecution:feat/pre-tool-rewrite-hook

Conversation

@elasticdotventures

Copy link
Copy Markdown

Summary

Adds get_pre_tool_call_directives() — a single-hook function that fires pre_tool_call once and returns both block and rewrite directives. Plugins can now return:

{"action": "block", "message": "Reason"}   # existing
{"action": "rewrite", "args": {...}}         # new — transform tool args

Motivation

Guard interposition (command sanitization, path normalization, security middleware) needs the ability to transform tool arguments before execution, not just block them. Rather than forking terminal_tool.py to add custom backends, this provides a general plugin extension point.

Changes

3 files, +85 / -35 lines:

File Change
hermes_cli/plugins.py get_pre_tool_call_directives() — fires hook once, returns (block_msg, rewritten_args). Backward-compat aliases preserved.
run_agent.py Updated all 3 call sites (_invoke_tool, concurrent, sequential) to use directives
model_tools.py Updated handle_function_call to use directives

Backward Compatibility

get_pre_tool_call_block_message() kept as an exact alias — zero breakage for existing plugins and tests. All 111 plugin/shell-hook tests pass.

Rationale

The hook fires once per tool call instead of N times (once per directive type). This is both more efficient and semantically cleaner — a plugin only needs one callback pass to express its intent.

…ation

Adds get_pre_tool_call_directives() that fires pre_tool_call hook
ONCE and returns both block_message and rewritten_args.

Existing get_pre_tool_call_block_message() kept as backward-compat alias.
New get_pre_tool_call_rewrite() alias added.

Updates all 3 call sites (_invoke_tool, concurrent loop, sequential loop)
and handle_function_call in model_tools.py to use the combined function.

Copilot AI 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.

Pull request overview

This PR adds a richer pre_tool_call plugin hook contract so plugins can rewrite tool arguments before execution, not just block the call. It extends the plugin layer and updates the agent/tool dispatch paths that consume pre-tool directives.

Changes:

  • Added hermes_cli.plugins.get_pre_tool_call_directives() to collect block and rewrite directives from a single pre_tool_call hook invocation.
  • Updated run_agent.py tool execution paths to consume block/rewrite directives before dispatching tools.
  • Updated model_tools.py dispatch to honor rewritten args when the pre-tool hook is evaluated there.

Reviewed changes

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

File Description
run_agent.py Swaps pre-tool block checks over to the new directives helper in _invoke_tool, concurrent execution, and sequential execution.
model_tools.py Uses the new directives helper in handle_function_call so registry-dispatched tools can be blocked or rewritten.
hermes_cli/plugins.py Introduces the single-pass directive helper and keeps compatibility wrappers for legacy block-only callers.

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

Comment thread run_agent.py Outdated
Comment on lines +9452 to +9455
except Exception:
block_message = None
pass

if block_message is not None:
block_result = json.dumps({"error": block_message}, ensure_ascii=False)
else:
if block_result is None and _block_msg is None:
Comment thread run_agent.py
Comment on lines +9445 to +9448
elif _rewritten is not None:
function_args = _rewritten
# Re-check guardrails with rewritten args
guardrail_decision = self._tool_guardrails.before_call(function_name, function_args)
Comment thread hermes_cli/plugins.py
Comment on lines +1211 to +1216
elif action == "rewrite" and rewritten_args is None:
new_args = result.get("args")
if isinstance(new_args, dict):
rewritten_args = new_args

return block_message, rewritten_args
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins comp/agent Core agent loop, run_agent.py, prompt builder labels May 3, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Implements #18988. Related to #18148 (runtime extension hooks) and #11816 (pre_tool_call approve action).

1 similar comment
@alt-glitch

Copy link
Copy Markdown
Collaborator

Implements #18988. Related to #18148 (runtime extension hooks) and #11816 (pre_tool_call approve action).

Routes terminal commands through b00t hive run --dry-run guards.
Intercepts pre_tool_call hook to block, warn, or rewrite commands.
Handles pip->uv, docker->podman, main-branch protection, and more.
elasticdotventures added a commit to elasticdotventures/_b00t_ that referenced this pull request May 4, 2026
…ite patch

Vendor submodule pointing to PromptExecution/hermes-agent-b00t on
feat/pre-tool-rewrite-hook branch. Contains the get_pre_tool_call_directives()
patch required for b00t guard interposition via Hermes plugin hooks.

Upstream PR: NousResearch/hermes-agent#19305
Internal PR: PromptExecution/hermes-agent-b00t#1
elasticdotventures added a commit to elasticdotventures/_b00t_ that referenced this pull request May 4, 2026
…ite patch

Vendor submodule pointing to PromptExecution/hermes-agent-b00t on
feat/pre-tool-rewrite-hook branch. Contains the get_pre_tool_call_directives()
patch required for b00t guard interposition via Hermes plugin hooks.

Upstream PR: NousResearch/hermes-agent#19305
Internal PR: PromptExecution/hermes-agent-b00t#1
elasticdotventures added a commit to elasticdotventures/_b00t_ that referenced this pull request May 4, 2026
…tocol (#369)

* chore: remove plantuml-server embedded repo from git index

* feat: guard escalation, parser stages, b00t-ast CLI, b00t-py bindings, violation persistence

- Guard violation counter with JSONL persistence (~/.b00t/guard-violations.jsonl)
- 🦨→💩 escalation: Warn→Block when violation_count >= repeat_threshold
- check_guards() auto-persists violations on every match
- K0mmand3rStage guards: pattern = { stage = "pre_parse" } in hive-guards.hive.toml
- parser_stages wired into KmdLine::parse() at 7 phases
- b00t-ast CLI binary: b00t-ast dir <path> [--format json|mcp|counts]
- b00t-py: guard_check, emoji_lookup, register_stage_guard bindings
- KmdLine fields made pub for serde serialization
- Schema datums moved to _b00t_/schema/ (uppercase convention)
- k0mmand3r crate edition 2024, clean lints
- Rust 2024: #![allow]→removed, set_var unsafe wrappers
- b00t_env_backend.py promoted from DESIGN to working Python backend
- Hermes backend symlinked: just hermes-backend-enable

* chore: add hermes-agent-b00t vendor submodule with pre_tool_call rewrite patch

Vendor submodule pointing to PromptExecution/hermes-agent-b00t on
feat/pre-tool-rewrite-hook branch. Contains the get_pre_tool_call_directives()
patch required for b00t guard interposition via Hermes plugin hooks.

Upstream PR: NousResearch/hermes-agent#19305
Internal PR: PromptExecution/hermes-agent-b00t#1

* feat: add SCM convention guards — branch naming, main protection, conventional commits

New hive guards block or warn before git commands reach the shell:
- BLOCK: git checkout main/master — use feature branches
- BLOCK: git push origin main — use PRs instead
- BLOCK: git merge main — use gh pr merge
- WARN: git checkout -b without type/ — use feat/fix/chore/ prefix
- WARN: git commit -m without colon — use Conventional Commits format

* feat: add regex_match() to Rhai engine + SCM convention guards

- Registered regex_match(cmd, pattern) on Rhai engine in hive.rs
  for future guard pattern matching
- Added 5 SCM guards to hive-guards.hive.toml:
  BLOCK: git checkout main/master, git push origin main, git merge main
  WARN: branch without type/ prefix, commit without conventional format
- All guards use simple cmd.contains() — readable, no escaping hell

* feat: add b00t guard interposition Hermes plugin

Bumps vendor/hermes-agent-b00t to include the new plugins/b00t/
directory with pre_tool_call hook that routes terminal commands
through b00t hive run --dry-run guard evaluation.

* crypto-sign: ed25519 signing for peer_facts in IrontologyPeerStore

* hive-peers: gossip, mDNS discover, list --health, peer GC

* docs: initial review plan

Agent-Logs-Url: https://github.com/elasticdotventures/_b00t_/sessions/b13588c4-07c5-4b06-8575-5be55c579fb1

Co-authored-by: elasticdotventures <35611074+elasticdotventures@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
elasticdotventures added a commit to elasticdotventures/_b00t_ that referenced this pull request May 4, 2026
#373)

* feat: guard escalation, parser stages, b00t-ast CLI, b00t-py bindings, violation persistence

- Guard violation counter with JSONL persistence (~/.b00t/guard-violations.jsonl)
- 🦨→💩 escalation: Warn→Block when violation_count >= repeat_threshold
- check_guards() auto-persists violations on every match
- K0mmand3rStage guards: pattern = { stage = "pre_parse" } in hive-guards.hive.toml
- parser_stages wired into KmdLine::parse() at 7 phases
- b00t-ast CLI binary: b00t-ast dir <path> [--format json|mcp|counts]
- b00t-py: guard_check, emoji_lookup, register_stage_guard bindings
- KmdLine fields made pub for serde serialization
- Schema datums moved to _b00t_/schema/ (uppercase convention)
- k0mmand3r crate edition 2024, clean lints
- Rust 2024: #![allow]→removed, set_var unsafe wrappers
- b00t_env_backend.py promoted from DESIGN to working Python backend
- Hermes backend symlinked: just hermes-backend-enable

* chore: add hermes-agent-b00t vendor submodule with pre_tool_call rewrite patch

Vendor submodule pointing to PromptExecution/hermes-agent-b00t on
feat/pre-tool-rewrite-hook branch. Contains the get_pre_tool_call_directives()
patch required for b00t guard interposition via Hermes plugin hooks.

Upstream PR: NousResearch/hermes-agent#19305
Internal PR: PromptExecution/hermes-agent-b00t#1

* feat: add SCM convention guards — branch naming, main protection, conventional commits

New hive guards block or warn before git commands reach the shell:
- BLOCK: git checkout main/master — use feature branches
- BLOCK: git push origin main — use PRs instead
- BLOCK: git merge main — use gh pr merge
- WARN: git checkout -b without type/ — use feat/fix/chore/ prefix
- WARN: git commit -m without colon — use Conventional Commits format

* feat: add regex_match() to Rhai engine + SCM convention guards

- Registered regex_match(cmd, pattern) on Rhai engine in hive.rs
  for future guard pattern matching
- Added 5 SCM guards to hive-guards.hive.toml:
  BLOCK: git checkout main/master, git push origin main, git merge main
  WARN: branch without type/ prefix, commit without conventional format
- All guards use simple cmd.contains() — readable, no escaping hell

* crypto-sign: ed25519 signing for peer_facts in IrontologyPeerStore

* chore: update vendor/l3dg3rr submodule to ledgrrr (rebranded upstream)

- Submodule URL: https://github.com/PromptExecution/l3dg3rr → git@github.com:PromptExecution/ledgrrr
- Submodule pointer: 1ed3b3d → 2168595 (includes PR #80, dashboard-generated-panels-51-rebased)
- Remote changed from HTTPS to SSH for consistent auth
Adds b00t Integration category to COMMAND_REGISTRY: /b00t routes any command to b00t-cli, /hive is an alias for /b00t hive. Adds h3rmes-capability plugin that checks subsystem health (b00t-cli, b00t-mcp, irontology-mcp, codebase-memory, guard-plugin) on session start and auto-remediates critical/high gaps.
elasticdotventures and others added 2 commits May 30, 2026 18:02
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Brian Horakh <35611074+elasticdotventures@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants