@sensu-ai/feedback-widget
v0.1.0
Published
Drop-in end-user feedback widget for Sensu β collect π/π + comments under any AI-generated message and forward to the Sensu observability platform.
Maintainers
Readme
@sensu-ai/feedback-widget
Drop-in end-user feedback widget for Sensu. Collects π / π + optional comments under any AI-generated message and forwards to Sensu's POST /api/v1/feedback endpoint.
Two entry points:
- React component β
import { SensuFeedback } from '@sensu-ai/feedback-widget' - Vanilla
<script>embed β<script src="https://cdn.sensu-ai.com/feedback-widget.js">exposingwindow.SensuFeedback.mount(...)
Transport modes
The widget runs in your customer's browser, so it can't carry a secret API key. Pick one:
mode: 'proxy' (default, recommended)
The widget POSTs to your backend, which proxies the payload to Sensu's POST /api/v1/feedback carrying your real (server-side) API key. No credentials in the browser.
<SensuFeedback
runId="run_abc"
mode="proxy"
endpoint="/api/sensu-feedback"
/>Your backend's /api/sensu-feedback handler receives the JSON FeedbackPayload and forwards it.
mode: 'direct'
The widget POSTs directly to Sensu using a public, feedback-only API key. Easier to deploy; the key is visible in browser bundles, so you must use a feedback_only-scoped API key (created via the dashboard's API Keys page or POST /api/v1/auth/api-keys with { scope: "feedback_only" }). That scope can ONLY hit POST /api/v1/feedback β it cannot ingest events, write eval scores, or read any data, so the worst a leaked key can do is spam feedback rows.
<SensuFeedback
runId="run_abc"
mode="direct"
publicKey="pk_public_..." // a feedback_only-scoped key
/>React usage
import { SensuFeedback } from '@sensu-ai/feedback-widget';
export function ChatMessage({ runId }: { runId: string }) {
return (
<div>
<p>{message}</p>
<SensuFeedback
runId={runId}
endUserId={currentUser.id}
mode="proxy"
endpoint="/api/sensu-feedback"
onSubmitted={(id) => console.log('submitted', id)}
/>
</div>
);
}Vanilla embed
<div id="my-feedback"></div>
<script src="https://cdn.sensu-ai.com/feedback-widget.js"></script>
<script>
SensuFeedback.mount('#my-feedback', {
runId: 'run_abc',
mode: 'proxy',
endpoint: '/api/sensu-feedback',
});
</script>Wire format
The widget POSTs the same JSON shape Sensu's REST API accepts:
{
"runId": "run_abc",
"type": "thumbs_up" | "thumbs_down" | "score" | "correction",
"score": 0.0, // optional, [0, 1]
"comment": "string", // optional
"endUserId": "string" // optional
}In proxy mode, your backend should accept the same shape, then call:
POST https://api.sensu-ai.com/api/v1/feedback
X-API-Key: <your server-side key>
Content-Type: application/json
{ ...payload }Status
v0.1 β protocol locked, UI minimal-but-functional, customizable via style / prompt / thanksMessage props.
