Feedback lets the people who use a Host app, your app's development and pre-production deployments, send your team a message without leaving the page. The person who sends one is a Visitor. A Visitor opens the crewkit panel, reads a short notice, and sends a message with their name and email. The report arrives in your organization's Inbox as pending. Nothing reaches your agents until someone on your team reads it and confirms it.
Turning feedback on
Feedback is off by default. An organization owner or admin turns it on in Settings → Organization → Feedback, from an account whose email address is proven. Once crewkit publishes its data processing agreement, turning feedback on accepts it for your organization.
Turning feedback off closes nothing and revokes no key. While it is off, every key answers as if it did not exist, and the keys work again when feedback is turned back on.
The panel
The panel is the @crewkit/feedback package, a React component with no dependencies besides React.
Mount it once in your app's shell:
import { Feedback } from "@crewkit/feedback";
import "@crewkit/feedback/styles.css";
export function AppShell({ children }: { children: React.ReactNode }) {
return (
<>
{children}
<Feedback
feedbackKey={process.env.NEXT_PUBLIC_CREWKIT_FEEDBACK_KEY}
release={process.env.NEXT_PUBLIC_COMMIT_SHA}
/>
</>
);
}The panel renders nothing when feedbackKey is absent or empty, so an environment without the
variable shows no panel. Put the key only in your development and pre-production environments:
crewkit cannot tell a production origin from a staging one, so nothing enforces that for you.
The panel always sends to https://api.crewkit.io. Add that origin to your Content Security
Policy's connect-src. Its requests never carry cookies. The package's README lists every prop,
including visitor to prefill the name and email, route to send a route pattern instead of the
path, and openFeedback() to open the panel from your own button.
Feedback keys
A Feedback key is a project's credential for one environment of a Host app. A developer or above mints one on the project's Settings page, under Feedback keys. crewkit shows the key once, when it is minted, and stores only its SHA-256 digest, so a lost key cannot be recovered: mint another and revoke the old one. A key never expires. Revoking it ends it, and a manager or above, or the person who minted it, can revoke it.
Each key has these settings:
- Environment. A short lower-case label, such as
previeworstaging. It is shown on every report that comes through the key. - Allowed origins. The origins the panel may send from, each exactly
scheme://host[:port].http:is accepted only forlocalhost. One*is allowed, within the leftmost label of anhttps:origin, and it matches part of that label but never a dot. A pattern that would match every host on a public suffix, such ashttps://*.vercel.app, is refused. A pattern whose fixed part ends in a public suffix, such ashttps://myapp-*-myteam.vercel.app, is accepted with a warning, because any account on that provider can register a host it matches. A request from an origin off the list is refused. The origin check is not authentication: rate limits and the project's daily cap are the controls. - Query parameters to keep. At most 10 parameter names. By default none is kept.
- Repository. Optional. When a report's release is a commit SHA, crewkit links that commit in this repository.
- Sentry organization slug. Optional. When it is set, the panel may send the Visitor's Sentry replay and event IDs, and crewkit builds the links to them from this slug.
- Host app privacy policy URL. Optional. The notice links it beside your organization's policy.
- Screenshots. Off by default. When it is on, the panel offers the Visitor a screenshot (see
Screenshots). A developer or above turns it on with Offer screenshots in the
key's Edit dialog, or through the MCP tool
update_feedback_keywithscreenshots_enabled. Turning it on or off changes the notice Visitors read. The switch is disabled, with its reason, when crewkit has turned screenshots off on the platform, when your organization is data-resident, or when crewkit cannot tell whether either applies.
Each project accepts at most 200 reports a day by default, counted per UTC day. A manager can set the cap from 1 to 1,000. One Visitor's network address gets at most 20 reports a project a day, so one sender cannot use up the cap for everyone else.
What a report carries
- The message. The panel caps it at 4,000 characters. crewkit removes anything in it that looks like a secret before it is stored.
- The Visitor's name and email, as typed. crewkit never verifies them, and records whether your app prefilled them. Both are stored encrypted.
- The page. Its path, or the
routeyour app passes. The query string and the fragment are cut, except the values of the parameters the key keeps. Each kept value has anything that looks like a secret removed, and is cut to 200 characters. The origin the request came from is recorded with the page. - The browser and OS family, such as Chrome on macOS. crewkit reads them from the User-Agent header and never stores the header itself, or any version number.
- The viewport, the window's width and height.
- The locale,
enorfr. - The release your app passes, such as a commit SHA, cut to 64 characters. With the key's repository, a commit-shaped release becomes a link to that commit, and to its pull request when crewkit knows one.
- Sentry links, when the key has a Sentry slug and your app passes the IDs. crewkit builds the links from the slug and the IDs. It never stores a URL the panel sends.
- The screenshot, when the key offers one and the Visitor chooses to add it.
- The notice version, the notice's settings digest, and the privacy policy URL the notice linked.
The report does not store the Visitor's network address. It stores a keyed hash of it, bound to the project, for 30 days, to limit abuse.
What the Visitor is told
Before Send, the panel shows a notice that crewkit writes and serves, in English or French. It opens on a one-line summary: who collects the feedback and for whom, that the AI agents your team works with read the reports your organization confirms, that the information may be communicated outside Québec, and that the Visitor can erase what they send. The full notice sits behind How your feedback is used. It says what is recorded, and it names each setting of the key that changes that: the query parameters kept, screenshots, and Sentry. It also says how long reports are kept, how to erase one, and who to write to. That contact is your privacy officer when your organization has set one, and your organization otherwise.
The notice links your organization's privacy policy, and the Host app's when the key has one. While your organization has not set a privacy policy, the notice says so and links crewkit's instead, labelled as crewkit's. Your Host app's own privacy policy must name crewkit as a processor.
Every change to the notice's words is a new notice version, and each report records the version and locale the Visitor read. If the notice, the key's settings or your organization's policy change while a panel is open, the panel's Send is refused, and the panel loads the notice again first.
The Inbox
Pending reports wait in the Inbox, under Feedback, newest first and grouped by project. Developers and above see them. A row shows the message, the environment, the page, the release and the time. A project also shows there when it reached its daily cap today.
Opening a report shows the full message, its context, its screenshot when it has one, and the Visitor's name and email, marked as provided by the app or as typed and not verified. From there you Confirm it or Delete it, and the next report opens.
- Confirm makes the report project context. Outside a data-resident organization it becomes a
feedbackArtifact, which your agents can search. The Artifact holds the message, the environment, the page, the release, the viewport and the browser, and says whether a screenshot exists. It never holds the Visitor's name, email or locale, their hashed address, the Sentry links or the screenshot itself. Confirming cannot be undone, and there is no bulk confirm: each report is read by a person before agents can read it. - Delete removes the report for good. To delete many at once, pick them in the list and choose Delete picked, up to 200 at a time. Each deletion is recorded as a security event.
The project's Feedback tab
A project's Feedback tab lists its confirmed reports under Open, Resolved and All, each with its count. A pending report never appears there. The tab never shows the Visitor's name or email.
Beside each report's message, the context column shows where it came from, which build, which
device, and its Sentry session. The page's address is a link only once the report is confirmed,
through an origin without a *. Otherwise it is text you can copy.
A developer or above resolves an open report, optionally with the commit or pull request that fixed it, and can reopen a resolved one. A manager or above can delete a confirmed report, from the dashboard only. That deletes its Artifact too. Resolving, reopening and deleting are each recorded as a security event.
Your agents work with confirmed reports through the crewkit MCP tools list_feedback,
get_feedback, resolve_feedback and reopen_feedback. They see what the tab sees, never the
Visitor's name or email, and no tool deletes a report. An agent that resolves a report records the
session it resolved from.
Screenshots
Screenshots are off for every key until your team turns them on for that key, and crewkit can turn them off for every key with a platform switch. They are never available to a data-resident organization.
When the key offers screenshots, the notice says so, and the panel offers Add a screenshot.
No screenshot is taken unless the Visitor chooses one. The panel renders the visible page in the
Visitor's browser and shows it before Send, so they can highlight parts, black parts out, or remove
it. Password, card and one-time-code fields are always blank. An element your app marks
data-ckfb-mask is blanked, and one marked data-ckfb-block is left out.
The screenshot is uploaded once the report is sent, within 15 minutes, as a PNG, JPEG or WebP image of at most 10 MB. crewkit scans and re-encodes it, and serves only a clean image.
- Encryption. Every screenshot object is encrypted before it is first written to storage, with its own AES-256-GCM key. That key is wrapped by a Cloud KMS key for the environment, and the ciphertext is bound to its image record. If Cloud KMS fails, crewkit stores nothing and the upload fails; it never falls back to storing an unencrypted image.
- Serving. A screenshot is never at a public or signed URL. The dashboard fetches it from the API with your sign-in, as whoever may read the report's text. Each view is recorded as a security event first, and when that cannot be recorded, the image is not shown. crewkit's MCP tools return no screenshot, and the screenshot route refuses the crewkit CLI.
- Erasure. Deleting or erasing a report deletes its screenshot with it, and a daily job deletes any stored screenshot whose report is gone, once it is more than an hour old. A screenshot still being processed when its report is erased can therefore stay stored for up to about 25 hours, until that job deletes it.
Data-resident organizations
In a data-resident organization, confirming a report creates no Artifact: the report becomes open in the project's Feedback tab, but nothing of it enters project context. Screenshots cannot be turned on. When an organization becomes data-resident, its keys stop offering screenshots and its stored screenshots are deleted.
Retention, erasure and data requests
Retention. A daily job deletes:
- a pending report, 30 days after it arrived;
- a confirmed report, after your organization's feedback retention period, set in Settings → Organization → Feedback from 30 to 365 days, 180 by default, counted from arrival;
- the hashed network address and the Sentry IDs on every report, 30 days after it arrived.
A report always goes with its Artifact and its screenshot. Deleting a project or offboarding an organization deletes its keys and every report, and the delete does not happen if a report cannot be erased.
Visitor erasure. After Send, the panel offers Delete what I sent, which erases the report at once, and gives the Visitor a private link to see or delete it later. Erasing removes the report, its Artifact and its screenshot. It cannot remove what an agent already quoted in a team member's session, and the notice says so.
Data requests. An organization owner or admin answers a Visitor's request from Settings → Organization → Feedback, with Data request. The lookup is by the exact email address, across every project and status, and it can export or erase what it finds. Each lookup, erasure and screenshot view is recorded as a security event that carries a keyed hash of the address, never the address itself. A screenshot link in an export works only for the admin who ran the lookup, for 15 minutes.