---
title: Feedback
description: File a report about the platform from your tool, attach the refusal and its reference, and read the report's status by its id.
slug: /guides/feedback
order: 19
visibility: public
redirects_from: [/guides/feedback-and-ratings]
---

# Feedback

Prompt:

> That refusal made no sense to me. File it with the platform.

Also works:

- "Report that the storage guide never says how big a transfer can be."
- "Tell the platform we had to work around the missing rename."
- "What happened to the report we filed yesterday?"

## What your tool does

Your tool does each of these with no browser approval:

- Files the [report](/concepts/glossary#issue-and-report) with `submit_feedback` as its own filing, or as yours when you dictated it. It attaches the evidence: the action, the [refusal](/concepts/glossary#refusal) name, and the refusal's `reference`.
- Files one whenever something got in its way: an unexpected refusal, a workaround it needed, a missing capability, or a missing page. The platform welcomes these reports.
- Quotes nothing of your own content and puts no personal details in a report. The text says what was attempted and what came back.
- Reads a report's status later with `read_feedback`, by the id the filing returned, and retries the call when the platform says the fix is live.
- Adds to a report you filed, or answers a question the platform asked about it, by calling `submit_feedback` again with the same `problem_key` and the new text. The filing joins the same issue as a further report. A reporter has no comment action on the platform's space, so its reports are the channel.
- Corrects or withdraws a report you filed by calling `submit_feedback` with `amends`, the report's number, and the corrected words, or `withdraws: true` ([step 3](#3-add-to-a-report-correct-or-withdraw-it-or-join-it-to-an-issue)).

## What you need

- The refusal you want to report, exactly as your tool showed it to you. A management action's refusal includes a ten-character reference code. Keep a copy of it.

## Before your AI starts

This section is for your AI coding tool: what it checks and gathers before it begins. You don't need to do these steps yourself.

- A signed-in session in your connected tool, or an account-scoped [minted token](/concepts/glossary#minted-token) ([Connect Claude Code or Codex](/getting-started/connect-your-tool)). A token scoped to one application is refused `token_scope_refused` on every feedback action. That application's backend reaches its own space through the [egress gateway](/concepts/glossary#egress-gateway) instead.
- The refused call's action, refusal name, and `reference`, read from the refusal itself.

## Steps

The platform keeps its feedback in an issue service. An issue records one problem. A report is one filing about an issue, in the filer's own words, and is never edited. Several reports can belong to one issue.

### 1. File a report

A report carries no personal details: no names, email addresses, telephone numbers, or anything else that identifies a person. Leave out of a report anything you do not want us to have, or do not file the report. Your AI coding tools quote nothing of yours in a report of their own. The names of actions, refusals, applications, and files are not personal details.

Call `submit_feedback`. This report is the tool's own, about a refused `deploy`, its evidence copied from the refusal; the reference is an invented example of the form. A test checks these members against the action's request.

```json
{
  "source": "agent",
  "kind": "bug",
  "title": "deploy refused health_path_unserved although server.mjs answers /health",
  "text": "Called deploy for a new application. The refusal said no source file names the health path's last segment, but server.mjs at the zip's root answers GET /health.",
  "impact": "worked_around",
  "workaround": "Moved the health route into a file named health.mjs.",
  "evidence": { "action": "deploy", "refusal": "health_path_unserved", "reference": "3f9c2a7b1d" }
}
```

The members `submit_feedback` takes:

| Member | What it contains |
| --- | --- |
| `source` | Required. `agent` for the tool's own filing, `person` for a report you dictated. |
| `provider`, `session` | Optional, for `agent`: the tool's provider name and its session id, both or neither. |
| `kind` | Required. `bug`, `gap` for a capability you needed and could not find, `docs` for a page that is missing or wrong, `friction` for something that works but is hard, or `praise`. |
| `title` | Required. Up to 200 characters. |
| `text` | Optional. What was attempted and what came back, with no personal details, up to 20,000 characters. |
| `impact` | Optional. What the problem cost you: `blocked`, `worked_around`, `annoyed`, or `none`. |
| `workaround` | Optional. What you did to get past it, up to 4,000 characters. |
| `proposed_resolution` | Optional. The fix you would suggest, up to 4,000 characters. |
| `evidence` | Optional. `action`, `refusal`, `reference`, `code_site`, and a `context` of up to 20 short strings under keys of lowercase letters, digits, and underscores. The older `environment` and `version` give the build you saw. Any other member is refused. The refusal gives the members `evidence` takes or, for a long list, their count and the action's reference page. |
| `labels` | Optional. Up to 20 short lowercase labels. |
| `restricted` | Optional. `true` for a security concern. A read made for a reporter, as `read_feedback` makes on the platform's space, then never returns its issue to another reporter. |
| `problem_key` | Optional. Your own name for the problem. A later filing with the same name adds a report to the same issue. Praise is the exception: praise and a report of another kind under one name go to two separate issues. Without one, the platform derives it from the kind, the title, and the evidence's action and refusal. |
| `files` | Optional. Up to 4 screenshots, each a PNG, JPEG, or WebP file of at most 524,288 bytes that you stored first. Each names its `application`, `area`, and `name`, and its `environment`, the deploy target when you leave it out. |

To attach a screenshot, store it first. Call `mint_upload_grant` for an application of your account and an area bound to it, run the put line it returns, and name the stored file in `files`. The platform reads each file under your own sign-in or token, before it files anything, so a file it cannot find, or one larger than 524,288 bytes, is refused and nothing is filed. The image is stored with your report as you sent it, and no page of the platform shows it.

The request also takes older names for some members and kinds, which [Actions](/reference/action-catalog) lists. A `question` or a `task` from your tool is refused, because only the platform team files those kinds.

The response contains your `report` as filed, the `issue` it belongs to, and an `outcome`:

- `filed`: a new issue was opened for it.
- `linked`: the report joined an existing issue.
- `retried`: the same filing arrived again, and nothing changed.
- `noted`: praise, recorded and closed at once.
- `confirmed`: you called again with `report` and `repeat_of`, and your report now belongs to the issue you named (step 3). On the platform's own space, where that issue was merged as a duplicate, your report belongs to its master instead.
- `amended`: you called with `amends`, and your correction or withdrawal was filed as a further report beside the one it amends (step 3).
- `related`: you sent `repeat_of`, and one of the two is praise and the other is not. Nothing is joined. Your report stays on its own issue, which the response returns as `issue`. The two issues are related, unless either is restricted, and no member of the response names that relation.

On the platform's own space, `candidates` is an empty list: the platform team links your report to any issue it repeats when it triages it. `issue` is null when your report belongs to a restricted issue, including when your own filing set `restricted`; your `report` and the `outcome` are returned as before. `masked` lists the kinds of credential the service found in your text and hid. Rotate each one.

`personal_removed` lists the kinds of personal detail the platform removed from your report before storing it: `email_address`, `telephone_number`, or `card_number`, in that order. Each detail is replaced by a mark, such as `[email address removed]`, and the list is empty when nothing was removed. [What is kept](#what-is-kept) says where each kind is removed.

### 2. Read its status

Call `read_feedback` with `issue` set to the id the filing returned. The id below is an example. A test checks these members against the action's request.

```json
{ "issue": "#4127" }
```

The response shows the issue as a reporter sees it:

- its `state`: `new`, `open` once it has been triaged, `waiting` while it needs something before it can move on, `fixed` once a fix is built and being released, or `closed`;
- its `outcome` once closed, such as `verified`, `done`, `as_designed`, `declined`, or `duplicate`;
- a one-sentence `sentence` that describes the state and outcome in words;
- the `workaround`, when the platform team wrote one;
- the `note`, a message written for everyone who reported the issue, or null. In it the platform team asks a question or gives news on any state. A landed fix writes when its change landed and that it serves from the first release that carries it, shown while the issue is `fixed`, or `closed` `done` or `verified`;
- `live_in`, the build the fix is live in, or null;
- your own reports on it, and never another reporter's words.

A report another account filed is refused `not_found`. So is an issue number someone quotes to you that differs from the identifier `submit_feedback` returned to you. Where one of your own reports joined that issue, the refusal may name your own submission for it, which `read_feedback` with that identifier reads. It only ever names an issue you can read. For another account's issue, a restricted issue, or a number no issue has, it names nothing, so all three look the same.

Call `read_feedback` with no argument to list your own submissions. Add `state` to list only one state, or `query` to search your own submissions for words. Nothing is deleted when the state moves, and a closed issue stays readable.

### 3. Add to a report, correct or withdraw it, or join it to an issue

To add to a report you filed, or to answer a question the platform asked about it, call `submit_feedback` again with the same `problem_key` and the new text. The filing joins the same issue as a further report, since a report is never edited. The platform's question reads in the issue's `note`. Where the platform team is waiting on your answer, the filing returns the issue to its queue. A reporter has no comment action on the platform's space: commenting, updating, and settling are the platform team's to do, so your reports are the channel.

To correct a report you filed, call `submit_feedback` with `amends`, the report's number from the filing's response, never the issue's id, and the corrected `title`, `text`, `impact`, `workaround`, or `proposed_resolution`. To withdraw a report filed in error, send `withdraws: true` with `amends`. The example below withdraws report 57, an invented number. A test checks these members against the action's request.

```json
{ "source": "agent", "amends": 57, "withdraws": true, "text": "Filed against the wrong application." }
```

The correction is filed as a further report beside the one it amends, which stands as you filed it, and the platform team reads the two side by side. It joins every issue the first report belongs to at that moment, and the response's `outcome` reads `amended`. Where you name no `title` or `impact`, the amendment keeps the first report's, except that a withdrawal with no `impact` carries none. A `text`, `workaround`, or `proposed_resolution` you leave out is empty on the amendment, so repeat any words that still stand.

A withdrawal changes nothing on its own: the platform team reads it and settles the issue. Your latest amendment of a report is your standing word, so `withdraws: false` takes a withdrawal back. An amendment takes no `kind`, `evidence`, `problem_key`, `labels`, `restricted`, `report`, `repeat_of`, or `files`, and each is refused `invalid_request`. A report another account filed is refused 404 `not_found`, as a number no report carries is.

When you know the issue your report repeats, such as the issue an earlier report of yours belongs to, call `submit_feedback` again with `report`, your report's number, and `repeat_of`, that issue's id. A new filing can also name `repeat_of` directly, which adds it to that issue as a further report.

A new filing's response then carries `repeat_of` where the platform joined your report to that issue on this call. Where the service's own match had already linked the report there when it was filed, the response carries no `repeat_of`. Where one of the two is praise and the other is not, your report keeps its own issue, the outcome reads `related`, and the response carries no `repeat_of`. On the platform's own space, `repeat_of` names only an issue that holds one of your own reports.

There, an issue merged as a duplicate counts as its master: your report joins the master, and the response's `issue` and any `repeat_of` give the master. A `repeat_of` naming a restricted issue, or an issue that holds none of your reports, is refused 404 `not_found`, as one naming no issue is. The lookup counts against `read_feedback`'s per-minute limit. The report is still filed: send the same call without `repeat_of` to get it back.

### Known issues in a refusal

A refusal can point to a known issue. When the platform team already knows about a refusal you receive, its `detail` ends with a sentence that gives the issue and any workaround. Once the fix is released, that sentence gives the build that includes it.

### What the platform adds to a report

When your evidence quotes the `reference` of one of your own calls, the platform reads its own record of that call. For a `bug` about a call that was refused, it adds the action, the refusal, the place in its code that returned the refusal, and the build that handled the call. The response then contains `stamped: true`, and the report's evidence is marked `stamped`. The platform can match a stamped report to others with the same cause, without anyone reading its text.

Any other report is not stamped: a report about a call that succeeded or was held for your approval, and a report of another kind. The platform still adds the action and the build, but the response says `stamped: false`, the evidence is `claimed`, and any `refusal` or `code_site` you wrote is replaced by the record's action. So the platform never matches such a report to another only because both mention the same call.

The platform can find a call for 25 days after it was made. A reference it cannot find under your account stays as you wrote it, marked `claimed`. The day after you file, the platform checks a claimed reference again. It marks the report `confirmed` when the report names the refusal, the call its `reference` quotes was refused or failed under your account near that time, and the issue is a `bug`. Otherwise the report stays `claimed`, and nothing else about it changes.

A refusal that includes a `reference` also includes `help`, the address of its row in the [refusals reference](/reference/refusals). Read its cause and remedy there before you file. Over MCP, a refused result includes a second content block that gives the refusal and its reference, so your tool can copy them.

### What happens to a report after it is filed

The platform's triage passes read new reports with an AI model every five minutes. They record the issue's kind, the part of the platform it concerns, and its priority, and link a report to an issue it repeats, merging duplicates where the platform's own records back the match. A report whose text reads as an instruction to whoever reads it is left for a person, and neither pass deletes a report or changes its text. The platform team also settles issues by hand. Your report's issue shows what was decided, whether by the passes or by a person.

A fixed issue closes as `verified` once the fix has been used. The platform counts calls of the same action that completed on a build that includes the fix, and your tool's retry is one of them. After a platform incident closes, the next daily pass files an issue for it and links each report made while the incident was open, up to a limit. [What the triage passes do](/guides/keep-your-own-issue-list#what-the-triage-passes-do) describes the passes in full, as they run in your own spaces too.

### What is kept

A report is kept as the platform's own record of the problems builders meet. It identifies the account that filed it. What you file becomes the platform's to keep and use; the [terms of service](https://turnzero.ai/terms) say so.

Before a report is stored, the platform takes reasonable measures to remove confidential details that someone pastes into it: email addresses, telephone numbers in international form, and payment card numbers. It does not guarantee that every such detail is removed. The rest of the text stays as written, including where it identifies you, so keep personal details out of it, as [step 1](#1-file-a-report) asks.

Where each kind is removed:

- An email address and a telephone number are removed from the report's words, its title, text, workaround, and proposed resolution, and from the technical details your tool attaches, each `context` value of the evidence.
- A payment card number is removed from the report's words alone. A `context` value keeps it, because the technical details hold the identifiers a fix needs, and a long number among them can look like a card number.
- The action, the refusal, the reference, and the code site in the evidence are never changed.

An image you attach is stored exactly as you sent it, because the platform cannot find personal details in an image, so crop out or leave out anything you do not want kept.

A report filed before the platform began removing these details stays as written.

When the account is deleted, the account's identity is erased from every report it filed. No report is deleted, and each keeps its text as written.

The platform's triage passes read report text with an AI provider under the platform's own key. The [privacy page](https://turnzero.ai/privacy) lists the recipients and the retention.

## Your own issue spaces

An issue space of your account stores issues and reports in the same way as the platform's own space, for a repository's issue list or a program's test results. Creating one, minting its token, and working it through `relay_issue_act` need Turn Zero Team (tzTeam). [Keep your own issue list](/guides/keep-your-own-issue-list) covers that task: the space, its token's grant levels, the relayed operations, and how its issues get their priority.

## Feedback in your application's space

An application that declares the `issue_tracking` service in its [manifest](/concepts/glossary#manifest) has a space of its own, where its backend files its users' reports through the [Issue Tracking](/backend-packages/tztrack) client. That page describes the space: how reports are stamped with their environment and version, the build records, and what a deletion removes. [Bind an application to the space](/guides/keep-your-own-issue-list#bind-an-application-to-the-space) binds it to a space of your account instead.

Your backend reaches its application's own space at the `report` [grant level](/concepts/glossary#grant-level), so the answers it reads leave out every restricted issue. To read the space's restricted issues whole, call `relay_issue_act` under an `owner` token for that space; no deployment reads them.

The feedback actions reach that space when you name it in `space`, as the response of `submit_manifest` gives it. They also reach one space of an application that kept a space for each environment, and a space of your account's own.

- `submit_feedback` files into that space as your account's own actor.
- `read_feedback` reads the whole space: with no other argument, its issues newest first; with `issue`, any one of its issues; and with `queue: true`, the selected list ([Reading the queue](/guides/keep-your-own-issue-list#reading-the-queue)).
- `settle_feedback` settles one of its issues, or triages one with its kind or component.

None of them needs a grant.

A filing that names a `space` returns up to three existing issues your report may repeat as `candidates`, each with its id, its state, and any workaround a trusted actor wrote. A candidate's `title` is null when a report other than the platform team's own gave it, when the platform team has not yet reviewed the issue, or when a triage pass wrote the title.

Each candidate also carries the issue's `kind` and `component`, and its `summary` where a trusted actor wrote one. Its `matched_evidence` names the members of your `evidence`, such as `action` or `code_site`, that equal those of the standing reports whose evidence chose the issue, and none where only your title's words matched.

A candidate can be an issue closed `declined` or `as_designed`. Its `outcome` and its `sentence`, such as "Not taken.", mean the request was considered and not taken. Filing it again does not reopen it. A candidate's `outcome` is null while its issue is not closed.

A candidate with a null `title` asks nothing of you, because your report is already filed. Confirm a candidate with `repeat_of` only where you know it is the same issue. Otherwise nothing more is needed: the triage passes look for duplicates themselves.

A token scoped to an application is refused all three `token_scope_refused`, and its backend reaches the space through the gateway at its grant level. A request that passes `application` or `environment` is refused `invalid_request`, and the refusal gives `space`: pass the space in `space` instead. A `space` your account does not have is refused `not_found` before any credential is read, whoever has it.

The platform measures each space's stored bytes without reading any record's content, and that measurement counts against no plan quantity. Your account's export includes only your account's own filings in each space, not the records your end users filed there.

To keep those records before you delete the application, export the space with the `export` operation of `relay_issue_act` under an `owner` token for that space ([Keep your own issue list](/guides/keep-your-own-issue-list#6-export-before-anything-deletes-the-space)). That token needs tzTeam. Without it, or where the application kept a space for each environment, read the space with `read_feedback`: its issues page by page, then each issue's reports with `issue`. [Deletion and copies](/backend-packages/tztrack#deletion-and-copies) says what a deletion removes.

## Expected result

`submit_feedback` returns 200 with your `report`, an `issue` whose `state` is `new` or `open`, an `outcome` of `filed`, and a `reference` for the call itself. `read_feedback` with that issue's id returns the same issue with your report on it. Over MCP, `read_feedback`, `submit_feedback`, `settle_feedback`, and `relay_issue_act` each return one block. It opens with an untrusted-content marker and contains the JSON between two delimiter lines, because the text inside is what reporters wrote. Every other call returns a JSON block.

## Refusals

This table lists the refusals these steps most often meet; the [refusals page](/reference/refusals) lists all of the platform's refusals, with the cause and remedy of each. A backend package's own failures are listed on its package page.

A refusal gives the action and its cause in `detail`. It files no report; the platform's record of the call contains the refusal and its reference. [Keep your own issue list](/guides/keep-your-own-issue-list#refusals) lists the refusals of the issue-space actions.

| Refusal | Status | Cause | Remedy |
| --- | --- | --- | --- |
| `invalid_request` | 400 | A member breaks the rules in step 1, a file in `files` holds more than 524,288 bytes, or the request passed `application` or `environment`; `detail` gives the member to correct. | Correct the named member and call again; name a space in `space`. |
| `feedback_rate_limited` | 429 | A limit was passed: the account's share in a minute, a space's limit, the platform's cap, or the issue service's own rate limit. `detail` says which. | Wait for the minute to turn and repeat the call with the same key. |
| `issue_service_unreachable` | 503 | The platform's issue service did not respond; `detail` contains the cause word. `export_account` returns this refusal too, rather than an export without its feedback. | Repeat the call after a short wait with the same `key`. |
| `not_found` | 404 | `read_feedback` named a submission that is not the account's own, or `space` matches no space your account has. A filing's `files` names a file that your call cannot read. | Use the submission `detail` names, where it names one, or an id from `read_feedback` with no argument. For a space, use the identifier that `submit_manifest` or `list_issue_spaces` returns. |
| `grant_required` | 403 | `read_feedback` was called with `queue` on the platform's space, or `settle_feedback` on it, which only platform staff can do, under the `feedback_queue` grant. | Call `read_feedback` without `queue` for your own submissions, or name your space. |
| `token_scope_refused` | 403 | The call came under a token scoped to one application, which no feedback action accepts. | Use the session or an [account-scoped token](/concepts/glossary#account-scoped-token). The application's backend reaches its space through the gateway. |
| `not_yet_provisioned` | 501 | The platform you reached runs no issue service, which every feedback action needs, so the actions are absent from your tool's listing. | Nothing on your side corrects this. Report through your usual channel. |

## Related

- [Keep your own issue list](/guides/keep-your-own-issue-list) creates an issue space of your account and works it through the relay.
- [What happens without asking](/concepts/what-happens-without-asking) explains which actions complete in the call and which a person approves first.
- [Sign-in, sessions, and tokens](/concepts/sign-in-sessions-and-tokens) explains which credentials file feedback.
- [Export or delete your account](/guides/export-or-delete-your-account) covers the export, which includes the account's own reports, and the deletion.
- [Actions](/reference/action-catalog) lists every management action with its payload and refusals.
