Skip to content

feat(plugins): make pre_api_request hook mutable#11112

Open
hermes-agent-dhabibi wants to merge 1 commit into
NousResearch:mainfrom
hermes-agent-dhabibi:feat/mutable-pre-api-request
Open

feat(plugins): make pre_api_request hook mutable#11112
hermes-agent-dhabibi wants to merge 1 commit into
NousResearch:mainfrom
hermes-agent-dhabibi:feat/mutable-pre-api-request

Conversation

@hermes-agent-dhabibi

Copy link
Copy Markdown
Contributor

Summary

The pre_api_request hook is currently observe-only — plugins receive metadata (model name, token counts, etc.) but cannot modify the actual API request. The return value is discarded.

This PR passes api_kwargs into the hook and allows callbacks to return a modified dict that replaces the original api_kwargs for the API call.

Changes

run_agent.py (~5 lines changed):

  • Pass api_kwargs=api_kwargs as an additional kwarg to the pre_api_request hook
  • Capture the hook's return list; iterate results — last non-None dict becomes the new api_kwargs

Convention

Last non-None dict wins. If multiple plugins return modified kwargs, the last one in registration order takes precedence. Plugins that just observe can continue returning None — fully backward compatible.

Use cases

  • Set tool_choice to force tool calls during specific execution phases
  • Inject or override request parameters based on plugin state
  • Implement request-level middleware (rate shaping, payload transforms, etc.)

Example

def on_pre_api_request(**kwargs):
    api_kwargs = kwargs.get("api_kwargs", {})
    if should_force_tool_call():
        api_kwargs["tool_choice"] = {"type": "function", "function": {"name": "my_tool"}}
        return api_kwargs
    return None  # pass-through

Testing

Existing tests pass — test_tool_calls_then_stop (exercises the hook path) and all 48 plugin tests.

Pass api_kwargs into the pre_api_request hook. If any callback returns
a dict, use the last non-None dict as the replacement api_kwargs for
the API call. This lets plugins set tool_choice, inject parameters, or
modify the request payload before it hits the provider.

Convention: last non-None dict wins (allows layered plugin overrides).

Co-authored-by: dhabibi <9087935+dhabibi@users.noreply.github.com>
@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 Apr 25, 2026
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.

2 participants