Skip to content

fix(registry): tolerate plugin handlers without **kw#1

Merged
vveerrgg merged 1 commit into
mainfrom
fix/dispatcher-tolerant-handler-kwargs
May 8, 2026
Merged

fix(registry): tolerate plugin handlers without **kw#1
vveerrgg merged 1 commit into
mainfrom
fix/dispatcher-tolerant-handler-kwargs

Conversation

@vveerrgg
Copy link
Copy Markdown

@vveerrgg vveerrgg commented May 8, 2026

Summary

The dispatcher in tools/registry.py injects context kwargs (task_id, user_task, parent_agent) into every tool handler. Every bundled handler — tools/file_tools.py:1093 (_handle_read_file), plugins/spotify/tools.py:202 (_handle_spotify_search), etc. — accepts **kw to swallow them, but this convention is undocumented.

Third-party plugin authors who write the natural def handler(args) signature (matching the JSON schema, no extra noise) get a baffling TypeError: got an unexpected keyword argument 'task_id' on the very first dispatch. The error points at the handler line, but nothing in the schema or the docs hints that the dispatcher injects extra kwargs.

This patch makes the dispatcher signature-aware: it passes only kwargs the handler actually accepts. Backward-compatible — handlers that already declare **kw still receive every kwarg; handlers that explicitly name a context kwarg (e.g. def handler(args, task_id=None)) still get it; handlers that want neither now just work.

Repro

Before the patch:

```python
from tools.registry import ToolRegistry

reg = ToolRegistry()
reg.register(name="naive", toolset="core",
schema={"name":"naive","description":"","parameters":{"type":"object","properties":{}}},
handler=lambda args: '{"ok":true}')

reg.dispatch("naive", {}, task_id="t1")

{"error": "Tool execution failed: TypeError: () got an unexpected keyword argument 'task_id'"}

```

After the patch the same dispatch returns {"ok": true}.

I hit this while authoring an external Hermes plugin (nostrkey) — the bug only surfaces for plugins written outside this repo, since every in-tree handler already accepts **kw.

Changes

  • tools/registry.py: add ToolRegistry._filter_kwargs_for_handler (uses inspect.signature); call it from dispatch() before invoking the handler. Tolerates **kw-style handlers (passes everything), explicitly-named-kwarg handlers (passes the matching ones, drops the rest), and signature-less callables (falls back to passing all kwargs).
  • tests/tools/test_registry.py: two new tests — test_dispatch_tolerates_handler_without_kwargs and test_dispatch_passes_named_kwargs_when_handler_accepts_them.

Test plan

  • pytest tests/tools/test_registry.py — 33/33 pass (was 31/31, +2 new tests)
  • pytest tests/test_model_tools.py tests/tools/ — 896 pass; 2 unrelated failures (test_custom_cwd_in_command_wrapper in daytona env, test_os_environ_still_wins_over_dotenv in credential pool) confirmed pre-existing on main — neither touches the registry
  • End-to-end: external plugin with def handler(args) (no **kw) registers and dispatches cleanly under hermes chat

The dispatcher injects context kwargs (`task_id`, `user_task`,
`parent_agent`) into every tool handler call. All bundled handlers
accept `**kw` to swallow them, but this convention is undocumented —
third-party plugin authors who write the natural `def handler(args)`
signature get a confusing `TypeError: got an unexpected keyword
argument 'task_id'` at first dispatch.

Make the dispatcher inspect the handler's signature and pass only
kwargs the handler accepts. Backward-compatible: handlers with `**kw`
still receive every kwarg; handlers that explicitly name `task_id`
still get it.

- Add `ToolRegistry._filter_kwargs_for_handler` (signature-aware).
- Update `dispatch()` to filter via the helper.
- Two new tests: a no-`**kw` handler dispatches without TypeError,
  and a handler that names `task_id` still receives it.

Caught while authoring an external plugin (nostrkey for Hermes); fix
helps any third-party plugin written outside this repo.
@vveerrgg vveerrgg merged commit dcc43ef into main May 8, 2026
@vveerrgg vveerrgg deleted the fix/dispatcher-tolerant-handler-kwargs branch May 8, 2026 21:30
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.

1 participant