Install
Configure once
Register Epode before the included route handlers:Cached APIs
The defaultcacheMode: "safe" does not silently turn a response with public, max-age, s-maxage,
immutable, or stale-while-revalidate into a private response. It skips those responses and logs one
configuration warning.
If ordinary callers share a CDN response but feedback-aware agent callers can opt in, use request mode:
Agent-Feedback-Request: 1. Only that request receives feedback metadata and
becomes private, no-store; the public response keeps its existing cache policy. Use
cacheMode: "private" only when disabling shared caching on every included response is intentional.
Async jobs
Instrument the result, not every polling response:Server-rendered HTML
Use the same middleware and include the HTML route:<script id="agent-feedback" type="application/json"> contract.
It does not change the visible page.
Verify
never_ask, it submits one synthetic review. In ask modes, it validates consent without claiming approval.
What is not instrumented
Errors, redirects, health and metrics routes, assets, streams, binary responses, and routes outsideinclude remain untouched. JSON arrays and scalar values use response headers instead of being wrapped.
View the runnable Express example
View the cached search API example