Skip to content

Add per-call tool gate hook#377

Merged
JackChen-me merged 2 commits into
open-multi-agent:mainfrom
scarab-systems:scarab-systems/open-multi-agent-96-repair
Jul 16, 2026
Merged

Add per-call tool gate hook#377
JackChen-me merged 2 commits into
open-multi-agent:mainfrom
scarab-systems:scarab-systems/open-multi-agent-96-repair

Conversation

@scarab-systems

@scarab-systems scarab-systems commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

What

Adds an optional per-call onToolCall gate for tool execution. The hook runs after tool input validation and before the tool implementation, and can return allow or deny for that specific call.

Denied calls return a normal error ToolResult without invoking the tool, and trace events include compact gate metadata when a gate evaluates a tool call.

Why

Part of #96.

This gives applications a policy hook for risk decisions around built-in shell/filesystem tools without changing the existing default-deny, allowlist, denylist, or tool preset behavior.

Validation

  • npm run lint
  • npm test
  • npm run build
  • npm run test:coverage
  • npm run test:scaffold
  • package smoke checks for built entry-point imports, CLI help, template typecheck, and tarball file lists

Checklist

  • npm run lint passes
  • npm test passes
  • Added/updated tests for changed behavior
  • No new runtime dependencies (or justified in the PR description)

Disclosure: I used AI-assisted coding tools while preparing this PR. I reviewed the changes myself, tested them, and take responsibility for the implementation and any follow-up revisions needed.

@JackChen-me

Copy link
Copy Markdown
Member

Core approach looks right, but I hit four edge cases locally: aborting while the async gate is pending still executes the tool, malformed decisions can reject ToolExecutor, gateReason bypasses trace redaction, and output-validation failures drop gate metadata. Please add fixes and regression coverage for those paths.

@scarab-systems

Copy link
Copy Markdown
Contributor Author

Pushed db17a75 addressing the four edge cases:

  • Re-check abortSignal after an async onToolCall gate resolves, before tool execution.
  • Treat malformed gate decisions as error ToolResults instead of letting them execute or reject the executor.
  • Redact gateReason before emitting it on tool_call traces.
  • Preserve gate metadata on output-schema validation failures.

Added regression coverage for each path. Local validation run:

  • npm run lint
  • npm -w @open-multi-agent/core test -- tests/tool-executor.test.ts tests/trace.test.ts
  • npm test
  • npm run build
  • npm run test:coverage
  • npm run test:scaffold
  • package smoke checks for entry-point imports, CLI help, template typecheck, and tarball contents

The branch is updated and GitHub checks should rerun on the new head.

@JackChen-me
JackChen-me merged commit e87080b into open-multi-agent:main Jul 16, 2026
7 checks passed
JackChen-me added a commit that referenced this pull request Jul 16, 2026
…rs subpath (#382)

Ships an opt-in, dependency-free shell risk classifier for the onToolCall gate
(#377). classifyBashCommand(command) returns safe | review | high so users get
the taxonomy from #96 without writing regex tables by hand.

- safe: read-only inspection (ls, cat, grep/rg with a path, git status/log/diff)
- review: context bombs and unknowns (ls -R, find / without -maxdepth,
  grep -r / rg -r without scope, tree, du, unrecognised commands)
- high: destructive/sensitive (rm, sudo, curl | bash, dd, mkfs, chmod 777/-R,
  git push --force, npm publish)

Compound commands are segmented on shell separators and the highest risk wins;
quoted strings are stripped so patterns inside a string do not match. Convenience
heuristic, not a security boundary. Exported only via
@open-multi-agent/core/classifiers so pattern tables never load unless imported.

Closes #379
JackChen-me added a commit that referenced this pull request Jul 16, 2026
…example

Third split of #96 (follow-up to #379). The onToolCall gate shipped in #377 and
the classifyBashCommand classifier in #379; this documents both and adds a
runnable example.

- docs/tool-configuration.md: a "Per-call gating with onToolCall" section (where
  it sits, ToolCallContext/ToolCallDecision, deny returns an error ToolResult not
  a throw, agent overrides orchestrator default, orthogonal to onApproval,
  gated/gateAction/gateReason on the trace with gateReason redacted, not a
  security boundary) plus a shell risk classifier subsection.
- examples/patterns/risk-gated-bash.ts: a security-audit agent that classifies
  each bash command and routes safe/review/high to allow/human-approval/deny.
- AGENTS.md: cross-links in the tool-layer notes + /classifiers in the exports map.

Closes #380
JackChen-me added a commit that referenced this pull request Jul 16, 2026
…example

Third split of #96 (follow-up to #379). The onToolCall gate shipped in #377 and
the classifyBashCommand classifier in #379; this documents both and adds a
runnable example.

- docs/tool-configuration.md: a "Per-call gating with onToolCall" section (where
  it sits, ToolCallContext/ToolCallDecision, deny returns an error ToolResult not
  a throw, agent overrides orchestrator default, orthogonal to onApproval,
  gated/gateAction/gateReason on the trace with gateReason redacted, not a
  security boundary) plus a shell risk classifier subsection.
- examples/patterns/risk-gated-bash.ts: a security-audit agent that classifies
  each bash command and routes safe/review/high to allow/human-approval/deny.
- AGENTS.md: cross-links in the tool-layer notes + /classifiers in the exports map.

Closes #380
JackChen-me added a commit that referenced this pull request Jul 16, 2026
…example (#383)

Third split of #96 (follow-up to #379). The onToolCall gate shipped in #377 and
the classifyBashCommand classifier in #379; this documents both and adds a
runnable example.

- docs/tool-configuration.md: a "Per-call gating with onToolCall" section (where
  it sits, ToolCallContext/ToolCallDecision, deny returns an error ToolResult not
  a throw, agent overrides orchestrator default, orthogonal to onApproval,
  gated/gateAction/gateReason on the trace with gateReason redacted, not a
  security boundary) plus a shell risk classifier subsection.
- examples/patterns/risk-gated-bash.ts: a security-audit agent that classifies
  each bash command and routes safe/review/high to allow/human-approval/deny.
- AGENTS.md: cross-links in the tool-layer notes + /classifiers in the exports map.

Closes #380
@scarab-systems
scarab-systems deleted the scarab-systems/open-multi-agent-96-repair branch July 16, 2026 18:02
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