Feedback
People using your app can send you a bug report or a suggestion right from the app, and your agent can read it back and turn it into a fix.
What you can do
People report bugs and ideas from inside the app. Every hosted app has a Feedback button in the toolbar Charming puts around it (not something you have to build). Anyone who can use the app, not just the owner, can open it, pick a category (bug, crash, enhancement, praise, or other), write a message, and send it.
A read-only visitor gets a fallback instead. Someone with view-only access can’t submit through the button, since it can’t authenticate on their behalf. A “Copy for agent” button writes a ready-to-paste prompt to the clipboard that names the app and the message, so they can hand it to their own AI assistant instead.
Your agent reads it back and ships changes. Ask your agent to check an app’s feedback; it lists the rows, reads what people said, and can turn that straight into an update. See How Charming works for the update step.
Technical
The Feedback button and its form are part of Charming’s own control-panel chrome, rendered around every app; nothing in the app’s own code has to add a form or an endpoint for it.
Copy this prompt for your agent
Check the feedback for my Charming app and act on it. Read
https://charm.ing/docs/capabilities/feedback.md first. Find the app,
check its feedback, and update the app to address anything
actionable. Ask me before making a change that isn't obvious from
the feedback text.
How an agent performs this job
The control panel’s Feedback button submits to POST /app/{id}/feedback with a category and an optional message; the server stamps that row’s source as user. Your agent reads those rows, and can add its own, with two MCP tools: submit_feedback records agent-authored feedback (an observed bug, a caught crash, a note), and list_feedback reads rows back, newest first, either for one app or across every app the caller owns. The server always stamps a row created through submit_feedback with source: "agent", regardless of what the caller sends, so an agent can’t pass its own note off as one a person wrote. Once your agent has read the feedback and decided what to change, it ships the fix the normal way: update_app (MCP) or PUT /app/<id> (HTTP), covered in How Charming works.
The contract
submit_feedback({ app_id, category, text?, structured_data?, crash_data? });
// category: "bug" | "crash" | "enhancement" | "praise" | "other"
// crash_data required when category is "crash": { message, stack?, url?, userAgent?, traceId? }
list_feedback({ app_id?, category?, since?, limit?, cursor? });
// app_id omitted: every app the caller owns, not apps merely shared with them
// limit: 1-50, default 20
POST /app/{id}/feedback takes the same category / text / structured_data / crash_data body over HTTP. A direct REST call can also tag source as user or auto-crash; the MCP tool always overrides it to agent.
Limits, access, and deletion
- Text and structured data.
textis capped at 16 KiB.structured_data, an optional JSON object for extra context like a route or repro inputs, is capped at 64 KiB serialized. A submission over either cap fails witherror.kind: "text_too_large"or"structured_data_too_large"; the recovery is to shorten it and retry. - REST payload cap and rate limits.
POST /app/{id}/feedbackcaps the request body at 96 KiB and is rate-limited to 30 requests per minute per app per visitor, and 200 per minute per app overall. - Access to send. The control panel’s button only works for someone with run access to the app, because it authenticates with the same render token, the short-lived credential the app’s own page runs on; a read-only viewer sees the “Copy for agent” fallback instead.
submit_feedbackover MCP needs that same run access, the bar for using an app’s own operations. - The raw endpoint.
POST /app/{id}/feedbackitself only checks read access, since a feedback row never touches the app’s own data. Only a run-capable role ever holds the render token needed to reach it, so this never loosens who can submit. - Access to read.
list_feedbackwith anapp_idneeds read access to that app. Without anapp_id, it returns rows only from apps the caller owns outright. - Deletion. Feedback rows belong to the app. Deleting an app is the only way to clear its feedback log; it goes with the app.
Related
- Privacy and sharing: who can run an app decides who can send feedback through its button
- How Charming works: the
update_appstep that turns feedback into a shipped change - Docs home
- llms-full.txt