Skip to content

[P2-8] Plugin lifecycle hooks: pre/post tool, pre/post LLM, session start/end (Rust HookRegistry + SDK plugins.on) #42

@justrach

Description

@justrach

Parent: #34
Priority: P2 (extensibility — gateway/cron/memd all rely on hooks)
Branch base: release/0.1.53

Why

Hermes' plugin contract registers six lifecycle hooks: pre_tool_call, post_tool_call, pre_llm_call, post_llm_call, on_session_start, on_session_end. graff-agent's gateway uses on_session_start/end for chat mapping; memd uses post_tool_call to detect failure patterns; cron uses on_session_end to log cron-run outcomes.

Scope

Rust side

  • forge_domain::Hook trait + a HookRegistry on ForgeAPI.
  • Six hooks fired from forge_app:
    • pre_tool_call(tool_call) — can mutate or veto (return HookOutcome::Veto(reason)).
    • post_tool_call(tool_call, result).
    • pre_llm_call(request).
    • post_llm_call(response).
    • on_session_start(cid).
    • on_session_end(cid).
  • Hooks are async, invoked sequentially per registration order, errors logged but don't crash the agent.

SDK side

  • graff.plugins.on(event, handler) — typed events.
  • TS:
    graff.plugins.on("preToolCall", async (tc) => { /* ... */ });

Acceptance

  • Each hook fires at the documented point
  • Veto from preToolCall skips the tool and surfaces an error to the agent
  • Multiple handlers registered for one event run in order
  • Crash in a handler logs but doesn't kill the conversation

Metadata

Metadata

Assignees

No one assigned

    Labels

    severity: highSignificant impact; core functionality is impaired.type: featureBrand new functionality, features, pages, workflows, endpoints, etc.work: complicatedThe situation is complicated, good practices used.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions