feat: hook system and plugin support design spec#63
feat: hook system and plugin support design spec#63araujof wants to merge 1 commit intopraxis-proxy:mainfrom
Conversation
Signed-off-by: Ian Molloy <molloyim@us.ibm.com> Signed-off-by: Teryl Taylor <terylt@ibm.com> Signed-off-by: Frederico Araujo <frederico.araujo@ibm.com> Co-authored-by: Ian Molloy <molloyim@us.ibm.com> Co-authored-by: Teryl Taylor <terylt@ibm.com> Co-authored-by: Frederico Araujo <frederico.araujo@ibm.com>
|
@shaneutt Thanks for 0f0f656. It addresses the listener-wide collapse by removing the precedence rung that let one filter promote the whole listener to all-or-nothing buffered mode, and per-request Net: the spec's §4.1 Cost 1 is resolved at the architectural level. I'll update the plugins doc to reference per-request One small thing: the |
Description
A proposal for a second extension surface in Praxis, complementing the existing HttpFilter / TcpFilter surface with typed, lifecycle-anchored hooks backed by the CPEX runtime embedded in-process.
Specification
Closes: #30
What it adds
Hooks sit at well-defined points across the server lifecycle: startup, TLS handshake, TCP accept and session, and the HTTP request and response path. Each has a typed payload and a declared interaction class (observe, mutate, or policy), so plugin authors know what they can touch and the dispatcher knows how to compose results.
Plugins run as native shared libraries or WASM modules; Python is excluded because the latency budget does not accommodate it. A plugin call is an in-process function call, not an IPC hop, and a deployment with no plugins configured pays nothing beyond a single atomic check per call site.
The central structural property is tighten-only composition. Policy hooks can strengthen any of Praxis' built-in security boundaries but never weaken them, and this is enforced by the dispatcher rather than left to plugin discipline.
What it defers
Protocol-semantic concerns, MCP tool invocations, A2A tasks, LLM inputs and outputs, are named and reserved but intentionally unregistered. They probably belong in future protocol-native services that parse bodies once during routing, not in an HTTP filter that would have to buffer speculatively. Hot reload, Python, and sidecar hosts for synchronous paths are also out of scope for v1.
@shaneutt this is a design question we should discuss before committing to protocol-semantic hooks implementation specification. We documented the cost and performance disadvantages of content-based filters for this in the specification linked to this PR.
Operational surface
Configuration is YAML-driven, with per-hook timeouts, error policies, and priorities. Plugins that span multiple hooks, for example deciding at request-time and auditing at session-end, get a typed request-scoped state channel rather than having to smuggle state through headers. Body-handling hooks have cumulative budgets at the chunk, request, and plugin level, and a circuit breaker auto-disables plugins that repeatedly misbehave. Metrics and tracing cover invocations, rejections, short-circuits, and the time the plugin chain contributes to each request.
Rollout
The work is staged so each phase is independently shippable.
cc: @terylt @imolloy