Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
cf5a9ac
feat(cli): submit keyless job feedback
Max17190 Sep 11, 2026
521389c
docs(cli): distinguish keyless and authenticated feedback
Max17190 Sep 11, 2026
cf929f4
fix(cli): forward feedback invitation preferences
Max17190 Sep 11, 2026
02baf67
docs(cli): clarify shared keyless feedback daily limit
Max17190 Sep 11, 2026
2f3855c
fix(cli): preserve keyless feedback and silence opted-out guidance
Max17190 Sep 11, 2026
aec2df9
fix(cli): retain keyless invitations and optional submissions
Max17190 Sep 12, 2026
80a8808
feat(cli): support structured keyless feedback categories
Max17190 Sep 12, 2026
fc5f679
docs(cli): clarify search feedback source attribution
Max17190 Sep 12, 2026
b9a61bb
docs(cli): align keyless feedback evidence guidance
Max17190 Sep 14, 2026
49c4737
docs: clarify keyless feedback limits and failure reasons
Max17190 Sep 17, 2026
328a8b8
merge: synchronize keyless feedback with main
Max17190 Sep 17, 2026
7a0847d
style(test): format CLI terms refusal test
Max17190 Sep 18, 2026
dd0af47
fix(cli): print a short keyless feedback reminder
Max17190 Sep 23, 2026
5062793
merge: synchronize keyless feedback with main
Max17190 Sep 23, 2026
89e878d
feat(feedback): print an optional keyless feedback reminder
Max17190 Sep 28, 2026
9ea44ef
merge: sync main for keyless feedback
Max17190 Oct 1, 2026
8f6ce95
refactor(feedback): simplify and align optional keyless guidance
Max17190 Oct 1, 2026
b0d54d5
fix(search): use web results by default for keyless callers
Max17190 Oct 1, 2026
4cb90b3
fix(feedback): retain auth boundaries and handle keyless failures
Max17190 Oct 1, 2026
66a980f
fix(feedback): expose keyless validation details and retry timing
Max17190 Oct 1, 2026
ba84855
fix(feedback): preserve keyless endpoint aliases and remove redundant…
Max17190 Oct 1, 2026
15c817d
Merge remote-tracking branch 'origin/main' into max/enable-keyless-fe…
Max17190 Oct 3, 2026
713628d
fix: clarify keyless feedback submission requirements
Max17190 Oct 3, 2026
739a19f
fix(skills): clarify keyless feedback guidance and keep search feedba…
Max17190 Oct 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 39 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,9 +466,21 @@ Paper ids accept `pmid:`, `pmcid:`, `doi:`, and `arxiv:` forms, plus canonical `

### `feedback` - Send endpoint job feedback

Send concise feedback for a completed v2 `search`, `scrape`, `parse`, or `map`
job. For search-result quality, `search-feedback` is still the most guided
command; `feedback` is the generic endpoint/job surface.
Send evidence through `/v2/feedback`. Feedback on keyless `search`, `scrape`, and
`parse` jobs is optional. Keyless guidance asks agents to submit concise feedback on observed result quality or missing coverage when the host permits it, especially if a result is wrong, incomplete, blocked, or an error. Feedback does not determine whether a task is complete. Keyless feedback submissions require `--rating`, `--task`, `--assessment`, and 1-20 observations
provided through `--observations` or `--observations-file`. Task, assessment, and each observation detail require 10-2000 characters after trimming whitespace. Keyless Parse also requires `--doc-class born_digital|scanned|mixed|unknown` once per submission. Use the returned job
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
reference and evidence already available; no user interview or additional
investigation is required. Run `firecrawl feedback --help` for category fields.

Each keyless job accepts one submission; retrying returns the original feedback
ID. Submit from the same caller IP before the invitation's `expiresAt` deadline,
which provides a 24-hour feedback window for the job.
Submitting feedback does not consume or restore operation allowance. Invitations
and references appear in metadata or stderr, preserving ordinary stdout.

Authenticated callers retain the existing fields. `search-feedback` remains an
authenticated Search command and cannot submit feedback for keyless jobs. The
following example uses the authenticated endpoint feedback contract:

```bash
firecrawl feedback scrape 0193f6c5-1234-7890-abcd-1234567890ab \
Expand All @@ -483,25 +495,33 @@ firecrawl feedback scrape 0193f6c5-1234-7890-abcd-1234567890ab \
Keep notes and metadata small. Do not send raw scrape or parse outputs as
feedback.

Set `FIRECRAWL_NO_ENDPOINT_FEEDBACK=1` to make `firecrawl feedback` skip
endpoint feedback calls silently.
Search observations identify delivered result positions or missing information. Scrape and Parse observations describe the requested output formats. Failed jobs use a `failure` observation based on the returned error.

Run `firecrawl feedback --help` for endpoint-specific categories, fields and reason codes. Stored keyless feedback must fit within 8 KiB, including server defaults and verification flags. Submit from the same caller IP; attempts are rate limited. See the [API feedback contract](https://docs.firecrawl.dev/api-reference/endpoint/feedback) for examples, format constraints, and Parse retention behavior.

Set `FIRECRAWL_NO_ENDPOINT_FEEDBACK=1` or `FIRECRAWL_DISABLE_ENDPOINT_FEEDBACK=1` to skip authenticated endpoint feedback calls. These flags do not suppress keyless invitations or submissions. The API includes a pointer on every eligible keyless job response. Feedback is optional and helps improve Firecrawl when a result is wrong, incomplete, blocked, or an error; keyless access does not depend on it.

#### Feedback Options

| Option | Description |
| -------------------------------- | -------------------------------------------- |
| `--rating <rating>` | Required: `good`, `partial`, or `bad` |
| `--issues <codesOrJson>` | Comma-separated issue codes or JSON array |
| `--tags <codesOrJson>` | Comma-separated tags or JSON array |
| `--note <text>` | Short human-readable feedback |
| `--valuable-sources <json>` | JSON array of `{url, reason}` entries |
| `--missing-content <json>` | JSON array of `{topic, description}` entries |
| `--query-suggestions <text>` | Search/query improvement notes |
| `--url <url>` | Relevant URL for scrape or parse feedback |
| `--page-numbers <numbersOrJson>` | Comma-separated page numbers or JSON array |
| `--metadata <json>` | Small JSON object with extra context |
| `--metadata-file <path>` | Path to small metadata JSON object |
| `--silent` | Suppress output for background agent calls |
| Option | Description |
| -------------------------------- | ---------------------------------------------------- |
| `--rating <rating>` | Required: `good`, `partial`, or `bad` |
| `--task <text>` | Task intent, required for keyless feedback |
| `--doc-class <class>` | Document class, required for keyless Parse |
| `--assessment <text>` | Assessment, required for keyless feedback |
| `--observations <json>` | JSON array of category-specific keyless observations |
| `--observations-file <path>` | File containing the observations JSON array |
| `--issues <codesOrJson>` | Comma-separated issue codes or JSON array |
| `--tags <codesOrJson>` | Comma-separated tags or JSON array |
| `--note <text>` | Short human-readable feedback |
| `--valuable-sources <json>` | JSON array of `{url, reason}` entries |
| `--missing-content <json>` | JSON array of `{topic, description}` entries |
| `--query-suggestions <text>` | Search/query improvement notes |
| `--url <url>` | Relevant URL for scrape or parse feedback |
| `--page-numbers <numbersOrJson>` | Comma-separated page numbers or JSON array |
| `--metadata <json>` | Small JSON object with extra context |
| `--metadata-file <path>` | Path to small metadata JSON object |
| `--silent` | Suppress output for background agent calls |

---

Expand Down
27 changes: 25 additions & 2 deletions skills/firecrawl-search/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Use `firecrawl search --help` for search options, `firecrawl list --help` for co

`--categories developer` searches an index of public repositories, GitHub issues, merged pull requests, repository READMEs, and curated documentation sites. `--categories research` is a website filter, not the paper index. Dedicated skills: [firecrawl-developer-index](../firecrawl-developer-index/SKILL.md) and [firecrawl-research-index](../firecrawl-research-index/SKILL.md).

**Done when:** relevant results have been inspected, per-call errors and empty results have been checked, the request has been answered with source links, and feedback is sent within the time window unless opted out.
**Done when:** relevant results have been inspected, per-call errors and empty results have been checked, and the request has been answered with source links.

## Go beyond page content with Alexandria

Expand Down Expand Up @@ -86,7 +86,30 @@ Keep large search responses in `--json -o` output and select the relevant result
- Use `jq` to extract URLs or titles: `jq -r '.data.web[].url' .firecrawl/search.json`
- Naming convention: `.firecrawl/search-{query}.json` or `.firecrawl/search-{query}-scraped.json`

## Send feedback after every search (refunds 1 credit)
## Feedback

Choose the feedback contract that matches the search job's authentication. A returned `metadata.feedback` invitation identifies the keyless submission endpoint and job ID. Do not send the keyless fields to the authenticated Search feedback route, or add credentials to submit feedback for a keyless job.

Keyless feedback is available for successful and failed jobs when the response includes a job reference. For an explicitly failed job, use observation `kind: "failure"` and `reason: "timeout"`, `"transport_error"`, `"proxy_error"`, or `"other"`; report only the error already returned. Keep the submission under 8 KiB including server defaults. Run `firecrawl feedback --help` for reason definitions and the complete contract.

### Keyless Search

Submit concise feedback on observed result quality or missing coverage when a keyless search result includes a feedback invitation and the host permits it, especially if the result is wrong, incomplete, blocked, or an error. Feedback does not determine whether the task is complete. If it is unavailable, declined, or rejected, continue without retries.

Use `firecrawl feedback search <jobId>` with `--rating`, `--task`, `--assessment`, and `--observations-file`. The task describes what the search needed to answer; the assessment describes how well it answered that task. Supply 1-20 observations:

- Useful or irrelevant results: `kind` and one-based `position` within the delivered group. `source` (`web`, `images`, or `news`) is required for multi-source jobs and for images-only or news-only jobs. Only web-only jobs can omit it, defaulting to `web`. Irrelevant results also require `reason`; see command help for allowed values.
- Missing information: `kind: "missing"` and `vertical`; `topic` is optional. `vertical` is optional on useful and irrelevant results. See command help for allowed verticals.
- Missing and irrelevant observations may include `knownSources`: up to 20 HTTP(S) URLs, only when already known. These identify absent content or the source that should have ranked instead. Unmentioned results are unassessed; a full ranking is not required.
- Every observation requires `detail` and `basis`: `output`, `source_comparison`, or `expectation`. A source comparison also requires `comparison: {reference, detail}`, with the correct content in `comparison.detail`. Use expectations for gaps that have not been verified against a source.

Task, assessment, and observation detail each require 10-2000 characters. Use only evidence already available. Do not ask the user to complete an interview, investigate further, guess missing content, or diagnose causes merely to submit feedback. An empty result set can support a missing-information observation if the response includes an eligible job reference.

Each job accepts one submission, and retrying returns the original feedback ID. Submit from the same caller IP before the invitation's `expiresAt` deadline, which provides a 24-hour feedback window for the job. Feedback does not consume or restore operation allowance. Omit sensitive information, and do not retry a rate-limit rejection in a loop. Client feedback flags do not suppress keyless invitations or submissions.

Run `firecrawl feedback --help` for the full evidence contract. Old instructions using `firecrawl search-feedback` require authentication and do not work for keyless jobs.

### Authenticated Search: send feedback after every search (refunds 1 credit)

Search costs 2 credits. After you've actually used the results (or decided they were useless), send structured feedback with `firecrawl search-feedback <id>`. The first feedback per search refunds 1 credit and helps us improve search quality. **Do this once per search**, in the background, after you finish processing the results — it does not block your main task.

Expand Down
14 changes: 11 additions & 3 deletions skills/firecrawl/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,17 @@ Single format outputs raw content. Multiple formats (e.g., `--format markdown,li

## Feedback

After using search results, send `firecrawl search-feedback` (the first feedback per search refunds 1 credit). The full pattern, guard, and rules live in [firecrawl-search](../firecrawl-search/SKILL.md).
**Authenticated:** After using search results, send `firecrawl search-feedback` (the first feedback per search refunds 1 credit). The full pattern, guard, and rules live in [firecrawl-search](../firecrawl-search/SKILL.md).

**Keyless:** Submit concise feedback on observed result quality or missing coverage when a keyless Search, Scrape, or Parse result includes a feedback invitation and the host permits it, especially if the result is wrong, incomplete, blocked, or an error. Submit it with `firecrawl feedback <endpoint> <jobId>` with `--rating`, `--task`, `--assessment`, and `--observations-file`, using the job reference and invitation returned in metadata or stderr. Feedback does not determine whether the task is complete. If it is unavailable, declined, or rejected, continue without retries. Run `firecrawl feedback --help` for category-specific observations.

@cubic-dev-ai cubic-dev-ai Bot Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The keyless requirement list omits --doc-class, which executeEndpointFeedback enforces for keyless Parse: it requires task, assessment, observations, and --doc-class when endpoint === 'parse', throwing Keyless feedback requires --doc-class. when missing (src/commands/feedback.ts, required map). README.md also states "Keyless Parse also requires --doc-class born_digital|scanned|mixed|unknown." This sentence claims to cover keyless Search, Scrape, and Parse, so an agent following it for a Parse job is rejected by the CLI. Add the Parse-only requirement to the flag list.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At skills/firecrawl/SKILL.md, line 120:

<comment>The keyless requirement list omits `--doc-class`, which `executeEndpointFeedback` enforces for keyless Parse: it requires task, assessment, observations, and `--doc-class` when `endpoint === 'parse'`, throwing `Keyless feedback requires --doc-class.` when missing (src/commands/feedback.ts, required map). README.md also states "Keyless Parse also requires `--doc-class born_digital|scanned|mixed|unknown`." This sentence claims to cover keyless Search, Scrape, and Parse, so an agent following it for a Parse job is rejected by the CLI. Add the Parse-only requirement to the flag list.</comment>

<file context>
@@ -115,15 +115,17 @@ Single format outputs raw content. Multiple formats (e.g., `--format markdown,li
-Consider submitting feedback, especially if a keyless Search, Scrape, or Parse result is wrong, incomplete, blocked, or an error. Include specific evidence to help improve Firecrawl. Submit it with `firecrawl feedback <endpoint> <jobId>` with `--rating`, `--task`, `--assessment`, and `--observations-file`. Use the job reference and invitation returned in metadata or stderr. Run `firecrawl feedback --help` for category-specific observations.
+**Authenticated:** After using search results, send `firecrawl search-feedback` (the first feedback per search refunds 1 credit). The full pattern, guard, and rules live in [firecrawl-search](../firecrawl-search/SKILL.md).
+
+**Keyless:** Submit concise feedback on observed result quality or missing coverage when a keyless Search, Scrape, or Parse result includes a feedback invitation and the host permits it, especially if the result is wrong, incomplete, blocked, or an error. Submit it with `firecrawl feedback <endpoint> <jobId>` with `--rating`, `--task`, `--assessment`, and `--observations-file`, using the job reference and invitation returned in metadata or stderr. Feedback does not determine whether the task is complete. If it is unavailable, declined, or rejected, continue without retries. Run `firecrawl feedback --help` for category-specific observations.
 
 For Alexandria feedback about a provider result or coverage gap, see [firecrawl-alexandria](../firecrawl-alexandria/SKILL.md).
</file context>
Fix with cubic


For Alexandria feedback about a provider result or coverage gap, see [firecrawl-alexandria](../firecrawl-alexandria/SKILL.md).

For non-search endpoint jobs, use `firecrawl feedback <endpoint> <jobId>` to send concise job-level feedback through `/v2/feedback`. Supported endpoints are `search`, `scrape`, `parse`, and `map`.
Use only evidence already available, without interviewing the user or doing extra investigation, and omit sensitive information. Each keyless job accepts one submission. Submit from the same caller IP before the invitation's `expiresAt` deadline, which provides a 24-hour feedback window for the job. Feedback does not consume or restore operation allowance. Do not send legacy issue/note fields as a substitute for keyless observations.

The two authentication modes use different request contracts; do not add credentials to submit feedback for a keyless job.

For non-search endpoint jobs, use `firecrawl feedback <endpoint> <jobId>` to send concise job-level feedback through `/v2/feedback`. Supported endpoints are `search`, `scrape`, `parse`, and `map`. The following example is for authenticated feedback:

@cubic-dev-ai cubic-dev-ai Bot Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This sentence is self-contradictory: it says "For non-search endpoint jobs" but then lists search among the supported endpoints. An agent will be unable to tell whether firecrawl feedback search <id> is valid. The prior wording described feedback <endpoint> without the "non-search" qualifier; spell out the scrape/parse/map scoping explicitly, or drop "non-search" and keep the endpoint list.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At skills/firecrawl/SKILL.md, line 128:

<comment>This sentence is self-contradictory: it says "For non-search endpoint jobs" but then lists `search` among the supported endpoints. An agent will be unable to tell whether `firecrawl feedback search <id>` is valid. The prior wording described `feedback <endpoint>` without the "non-search" qualifier; spell out the scrape/parse/map scoping explicitly, or drop "non-search" and keep the endpoint list.</comment>

<file context>
@@ -115,15 +115,17 @@ Single format outputs raw content. Multiple formats (e.g., `--format markdown,li
+The two authentication modes use different request contracts; do not add credentials to submit feedback for a keyless job.
 
-Authenticated callers can use `firecrawl feedback <endpoint> <jobId>` with the existing issue/note fields for `search`, `scrape`, `parse`, and `map`. The following example is for authenticated feedback:
+For non-search endpoint jobs, use `firecrawl feedback <endpoint> <jobId>` to send concise job-level feedback through `/v2/feedback`. Supported endpoints are `search`, `scrape`, `parse`, and `map`. The following example is for authenticated feedback:
 
 ```bash
</file context>
Suggested change
For non-search endpoint jobs, use `firecrawl feedback <endpoint> <jobId>` to send concise job-level feedback through `/v2/feedback`. Supported endpoints are `search`, `scrape`, `parse`, and `map`. The following example is for authenticated feedback:
For endpoint jobs, use `firecrawl feedback <endpoint> <jobId>` to send concise job-level feedback through `/v2/feedback`. Supported endpoints are `search`, `scrape`, `parse`, and `map`. The following example is for authenticated feedback:
Fix with cubic


```bash
firecrawl feedback scrape "$SCRAPE_ID" \
Expand All @@ -134,7 +140,9 @@ firecrawl feedback scrape "$SCRAPE_ID" \

Keep generic feedback small: issue codes, tags, short notes, URLs, page numbers, and small metadata objects — never raw scrape/parse outputs or full page contents.

**Opt out:** `export FIRECRAWL_NO_ENDPOINT_FEEDBACK=1` makes the CLI skip every endpoint feedback call silently. Respect that flag — do not try to work around it.
Keyless feedback is available for successful and failed jobs when the response includes a job reference. For an explicitly failed job, use observation `kind: "failure"` and `reason: "timeout"`, `"transport_error"`, `"proxy_error"`, or `"other"`; report only the error already returned. Keep the submission under 8 KiB including server defaults. Run `firecrawl feedback --help` for reason definitions and the complete contract.

**Authenticated feedback preference:** `FIRECRAWL_NO_ENDPOINT_FEEDBACK=1` or `FIRECRAWL_DISABLE_ENDPOINT_FEEDBACK=1` skips authenticated endpoint feedback calls. Respect these flags for authenticated jobs. Keyless jobs retain server-issued invitations and optional submissions regardless of these flags.

## Parallelization

Expand Down
40 changes: 40 additions & 0 deletions src/__tests__/cli-aliases.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ describe('CLI compatibility aliases', { timeout: 30000 }, () => {
scrape.handleScrapeCommand = print;
scrape.handleAllScrapeCommand = (_url, options) => print(options);
require('./dist/commands/parse').handleParseCommand = print;
require('./dist/commands/search').handleSearchCommand = print;
require('./dist/commands/feedback').handleEndpointFeedbackCommand = print;
require('./dist/commands/crawl').handleCrawlCommand = print;
require('./dist/commands/agent').handleAgentCommand = print;
process.argv = [process.execPath, ${JSON.stringify(cliPath)}, ...${JSON.stringify(args)}];
Expand All @@ -33,11 +35,49 @@ describe('CLI compatibility aliases', { timeout: 30000 }, () => {
env: {
...process.env,
FIRECRAWL_API_KEY: '',
FIRECRAWL_API_URL: '',
FIRECRAWL_NO_UPDATE_CHECK: '1',
},
});
}

testWithBuiltCli.each([
{ flags: [], sources: ['web'] },
{ flags: ['--api-key', 'fc-test-key'], sources: ['web', 'alexandria'] },
{ flags: ['--sources', 'news'], sources: ['news'] },
])('selects usable Search sources with $flags', ({ flags, sources }) => {
const result = run(['search', 'retry reference', ...flags]);
expect(result.status, result.stderr).toBe(0);
expect(JSON.parse(result.stdout).sources).toEqual(sources);
expect(result.stdout).not.toContain('AUTH_CHECK');
});

testWithBuiltCli.each([
'search',
'scrape',
'parse',
'map',
'Search',
'Scrape',
'Parse',
'Map',
])(
'retains the authentication gate only for Map feedback: %s',
(endpoint) => {
const result = run([
'feedback',
endpoint,
'00000000-0000-4000-8000-000000000001',
'--rating',
'good',
]);
expect(result.status, result.stderr).toBe(0);
expect(result.stdout.includes('AUTH_CHECK')).toBe(
endpoint.toLowerCase() === 'map'
);
}
);

testWithBuiltCli(
'sql preserves experimental aliases and execution options',
() => {
Expand Down
26 changes: 26 additions & 0 deletions src/__tests__/cli-argv.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ describe('CLI argv parsing', () => {
const cliPath = resolve(process.cwd(), 'dist/index.js');
const testWithBuiltCli = existsSync(cliPath) ? it : it.skip;

testWithBuiltCli(
'describes substantive keyless evidence in feedback help',
() => {
const result = spawnSync(
process.execPath,
[cliPath, 'feedback', '--help'],
{
cwd: process.cwd(),
encoding: 'utf8',
}
);
expect(result.status).toBe(0);
for (const field of [
'--task',
'--assessment',
'--observations-file',
'one-based position',
'source_comparison',
'one submission',
]) {
expect(result.stdout).toContain(field);
}
expect(result.stdout).not.toContain('UTC day');
}
);

testWithBuiltCli('rejects invalid PDF page caps before scraping', () => {
for (const value of ['0', '10001', '2.5', '3pages']) {
const result = spawnSync(
Expand Down
Loading
Loading