feat(plugins): tool override flag for replacing built-in tools (closes #11049) (#26759)

Plugins can now replace a built-in tool by passing override=True to
ctx.register_tool(). Without it, the registry rejects any registration
that would shadow an existing tool from a different toolset (unchanged
default behavior).

Unlocks the use case from #11049: drop-in replacement of browser/web
backends without forking core. Composes with the existing pre_tool_call
hook for runtime interception of any implementation.

The override is audit-logged at INFO so it surfaces in agent.log.
This commit is contained in:
Teknium 2026-05-15 22:12:57 -07:00 committed by GitHub
parent 9c304a7f56
commit 016c772e7f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 180 additions and 5 deletions

View file

@ -465,6 +465,30 @@ ctx.register_tool(
)
```
### Overriding a built-in tool
To replace a built-in tool with your own implementation (e.g. swap the
default browser tool for a headed-Chrome CDP backend, or replace
`web_search` with a custom corporate index), pass `override=True`:
```python
def register(ctx):
ctx.register_tool(
name="browser_navigate", # same name as the built-in
toolset="plugin_my_browser", # your own toolset namespace
schema={...},
handler=my_custom_navigate,
override=True, # explicit opt-in
)
```
Without `override=True`, the registry rejects any registration that would
shadow an existing tool from a different toolset — this prevents
accidental overwrites. The override is logged at INFO level so it's
auditable in `~/.hermes/logs/agent.log`. Plugins load after built-in
tools, so the registration order is correct: your handler replaces the
built-in one.
### Register multiple hooks
```python