Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion auth/fill-from-managed-auth.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ These examples continue in order, using GitHub as the login destination. Set `KE

<FillManagedAuthCredential />

`completed` means the selected fields were filled, not that login succeeded. If `fill` fails, returns an uncertain outcome, or loses its response, stop and [inspect the outcome](/vaults/fill#handle-the-outcome) rather than retrying automatically.
`completed` means the selected fields were filled, not that login succeeded. If `fill` fails, returns an uncertain outcome, or loses its response, [check the outcome](/vaults/fill#handle-the-outcome) and retry it; `fill` never submits the form.
</Step>
<Step title="Submit and handle the response">
After `fill` completes, your application or agent submits the login form once and verifies the site's response.
Expand Down
2 changes: 1 addition & 1 deletion auth/fill-from-vault.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ these examples continue in order, using hacker news as the login destination. se

<FillBrowserCredentials />

`completed` means the selected fields were filled, not that login succeeded. if `fill` fails, returns an uncertain outcome, or loses its response, stop and [inspect the outcome](/vaults/fill#handle-the-outcome) rather than automatically retrying.
`completed` means the selected fields were filled, not that login succeeded. if `fill` fails, returns an uncertain outcome, or loses its response, [check the outcome](/vaults/fill#handle-the-outcome) and retry it; `fill` never submits the form.
</Step>
<Step title="Submit and Handle the Response">
after `fill` completes, your application or agent submits the login form once and verifies the site's response. `fill` doesn't perform either step. handle any additional authentication prompts before continuing the task.
Expand Down
15 changes: 8 additions & 7 deletions browsers/enable-payments-in-browser-agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ and authorization state. neither item is the user's underlying wallet or card.
<Warning>
- keep wallet enrollment and provider approval outside the agent and its browser. never put action urls, oauth codes, provider responses, api keys, or browser connection urls in model context.
- independently verify purchase details in your controller before creating, updating, or authorizing a card item. user confirmation alone doesn't validate an agent's proposal.
- submit checkout once through the merchant's normal form. don't retry submission, automatically retry `fill`, or fall back from `fill` to aliases after failure or uncertainty.
- submit checkout once through the merchant's normal form. don't retry submission or fall back from `fill` to aliases after failure or uncertainty. `fill` never submits checkout, so it's safe to retry.
- report success only after the merchant's trusted order record confirms the matching paid order. a timeout, missing event, or browser deletion doesn't cancel a payment.
</Warning>

Expand Down Expand Up @@ -291,7 +291,7 @@ const result = await kernel.vaults.items.performOperation(linkCard.key, {
if (result.type !== "fill") throw new Error("unexpected operation response");
console.log(result.status, result.fields);
if (result.status !== "completed") {
throw new Error("stop and reconcile per-field outcomes; do not retry");
throw new Error("fill did not complete; inspect per-field outcomes and retry");
}
```

Expand Down Expand Up @@ -320,14 +320,15 @@ if result.type != "fill":
raise RuntimeError("unexpected operation response")
print(result.status, result.fields)
if result.status != "completed":
raise RuntimeError("stop and reconcile per-field outcomes; do not retry")
raise RuntimeError("fill did not complete; inspect per-field outcomes and retry")
```

</CodeGroup>

retain each result's zero-based `index`, `status`, and optional `error_code`.
`failed` may leave earlier writes in place; `unknown` or a transport error means
the outcome is uncertain. stop without retrying or switching to aliases. see the
the outcome is uncertain. `fill` never submits checkout, so retry it rather than
switching to aliases. see the
[`fill` outcome contract](/vaults/fill#handle-the-outcome) for details and [link checkout](/integrations/wallets/stripe-link#fill-the-checkout)
for the cli equivalent.

Expand Down Expand Up @@ -617,7 +618,7 @@ is unavailable or the sources disagree, keep the result indeterminate and don't
| `payment_requires_action` | continue the existing merchant flow without resubmitting payment |
| `payment_processing` | wait for the existing payment and inspect the merchant's status |
| `fill` `completed` or `credential_fill_attempted` | inspect per-field outcomes and merchant state; filling alone does not prove submission or payment success |
| `fill` `failed`, `unknown`, or a lost response | preserve partial or uncertain outcomes; stop without automatic retries or alias fallback |
| `fill` `failed`, `unknown`, or a lost response | retry `fill`; it never submits checkout. don't fall back to aliases |
| agentcard `ready` or authorization `approved` | inspect charge, replay, and merchant state; reusable item state does not prove purchase success |
| decline, expiry, rejection, failure, abandonment, or `payment_unknown` | stop and reconcile the existing attempt before deciding whether a new purchase is appropriate |
| `recovery_required` | stop; reconcile the unresolved provider outcome. do not retry or delete the item or its parent wallet/vault |
Expand Down Expand Up @@ -735,8 +736,8 @@ card.
card and billing fields. fill writes actual values into the browser; do not
read them back, expose them in model context, or assume recordings omit them.
10. preserve the value-free fill result and every per-field outcome. continue
only on `completed`; failed or unknown outcomes, transport errors, or missing
required fields mean stop and reconcile. never automatically retry fill or
only on `completed`. fill never submits checkout, so retry it after failed or
unknown outcomes or transport errors; missing required fields mean stop. never
fall back to aliases. supply other customer fields only from approved user
data, complete any agent disclosure truthfully, then submit checkout once.
11. inspect the checkout result, fill outcomes, and item events. report success
Expand Down
9 changes: 5 additions & 4 deletions browsers/use-vault-credentials-in-browser-agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ verify access with `kernel vaults list --limit 1 -o json` and check
don't open it in your browser. i will enter my credentials and tell you when
i'm done. never ask me to paste my password into the conversation.
4. after i confirm, retrieve the item and require ready plus an advertised fill
operation. invoke fill once with the browser session ID, exact login URL,
operation. invoke fill with the browser session ID, exact login URL,
and selectors that uniquely identify the login inputs. don't read, print,
screenshot, or return the filled values. if fill fails, returns unknown, or
loses its response, stop rather than retrying or using another fill path.
screenshot, or return the filled values. fill never submits the form, so if
it fails, returns unknown, or loses its response, retry it. don't use another
fill path.
5. if fill completed, submit login once, verify the site's response, and tell me
my karma. if login fails or needs more interaction, ask me what to do next.
when we're finished, delete the test browser and only the vault created for
Expand Down Expand Up @@ -97,6 +98,6 @@ retrieve the item after the user confirms collection. `ready` means required val

<FillBrowserCredentials />

if the result is `completed`, the agent can submit login once and inspect the site's response. filling doesn't submit the form or confirm authentication. if the operation fails, returns `unknown`, or loses its response, stop instead of retrying. the [fill guide](/vaults/fill#handle-the-outcome) explains partial outcomes.
if the result is `completed`, the agent can submit login once and inspect the site's response. filling doesn't submit the form or confirm authentication. if the operation fails, returns `unknown`, or loses its response, retry it. the [fill guide](/vaults/fill#handle-the-outcome) explains partial outcomes.

when the temporary demo is finished, delete its browser and vault. retain per-user vaults in your application according to your retention policy. for passwords on other sites, repeat the same flow with the fields and selectors you observe there; don't reuse a credential on a different destination without the user's authorization.
8 changes: 4 additions & 4 deletions integrations/wallets/stripe-link.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ const result = await kernel.vaults.items.performOperation(card.key, {
if (result.type !== "fill") throw new Error("unexpected operation response");
console.log(result.status, result.fields);
if (result.status !== "completed") {
throw new Error("stop and reconcile per-field outcomes; do not retry");
throw new Error("fill did not complete; inspect per-field outcomes and retry");
}
```

Expand Down Expand Up @@ -555,7 +555,7 @@ if result.type != "fill":
raise RuntimeError("unexpected operation response")
print(result.status, result.fields)
if result.status != "completed":
raise RuntimeError("stop and reconcile per-field outcomes; do not retry")
raise RuntimeError("fill did not complete; inspect per-field outcomes and retry")
```

```bash CLI
Expand All @@ -578,11 +578,11 @@ jq -n --arg browser "$BROWSER_ID" --arg url "$PAGE_URL" '{

### Handle the outcome

the cli exits nonzero for `failed` or `unknown`, but retains the value-free result on stdout with `-o json`. preserve that output and its per-field statuses; don't discard it or retry just because the exit code is nonzero. a transport error can leave the outcome uncertain even without a result body.
the cli exits nonzero for `failed` or `unknown`, but retains the value-free result on stdout with `-o json`. use the per-field statuses to decide what to fix before retrying. a transport error can leave the outcome uncertain even without a result body.

see the [shared fill outcome contract](/vaults/fill#handle-the-outcome) for per-field statuses and reconciliation.

`fill` returns value-free per-field outcomes. `completed` means the fields were filled, not that payment succeeded. a `failed` result can leave earlier writes in place; `unknown` or a lost response requires reconciliation. don't automatically retry fill or fall back to aliases. decide whether to submit separately, and never retry checkout automatically.
`fill` returns value-free per-field outcomes. `completed` means the fields were filled, not that payment succeeded. a `failed` result can leave earlier writes in place, and `unknown` or a lost response means the outcome is uncertain. `fill` never submits checkout, so retry it in either case; don't fall back to aliases. decide whether to submit separately, and never retry checkout automatically.

single-use describes the provider-issued card, not one-use alias consumption. `fill` does not consume the item or clear its encrypted material on the first field write. expiry, deletion, and item lifecycle restrictions still apply; a ready item is not evidence that a purchase can safely be repeated.

Expand Down
4 changes: 2 additions & 2 deletions snippets/fill-browser-credentials.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const result = await kernel.vaults.items.performOperation(item.key, {
],
});
if (result.type !== "fill" || result.status !== "completed") {
throw new Error("stop and reconcile the fill outcome");
throw new Error("fill did not complete; inspect per-field outcomes and retry");
}
```

Expand All @@ -43,7 +43,7 @@ result = kernel.vaults.items.perform_operation(
],
)
if result.type != "fill" or result.status != "completed":
raise RuntimeError("stop and reconcile the fill outcome")
raise RuntimeError("fill did not complete; inspect per-field outcomes and retry")
```

```bash CLI
Expand Down
4 changes: 2 additions & 2 deletions snippets/fill-managed-auth-credential.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const result = await kernel.vaults.items.performOperation(item.key, {
],
});
if (result.type !== "fill" || result.status !== "completed") {
throw new Error("stop and reconcile the fill outcome");
throw new Error("fill did not complete; inspect per-field outcomes and retry");
}
```

Expand All @@ -49,7 +49,7 @@ result = kernel.vaults.items.perform_operation(
],
)
if result.type != "fill" or result.status != "completed":
raise RuntimeError("stop and reconcile the fill outcome")
raise RuntimeError("fill did not complete; inspect per-field outcomes and retry")
```

</CodeGroup>
16 changes: 8 additions & 8 deletions vaults/fill.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ the item must be ready and contain a stored value for each requested field. addi

attach the vault when creating the browser. the browser and vault must belong to the same project, and the attachment can't change later. attaching a vault grants access to all its items, including items added later; use separate vaults for tasks that must not share items. use the browser's session id in `browser_id`, not its name. KERNEL rechecks the attachment and item lifecycle before writing.

configure your sdk client with `maxRetries: 0` (typescript) or `max_retries=0` (python) for fill, and don't wrap it in a retry loop. the cli does not automatically retry fill requests.
`fill` is safe to retry. it only writes field values and never submits the form, so default sdk retries and your own retry loops are fine.

<a id="map-credential-fields-to-inputs" />

Expand Down Expand Up @@ -61,7 +61,7 @@ const result = await kernel.vaults.items.performOperation(item.key, {
if (result.type !== "fill") throw new Error("unexpected operation response");
console.log(result.status, result.fields);
if (result.status !== "completed") {
throw new Error("stop and reconcile the fill outcome before continuing");
throw new Error("fill did not complete; inspect per-field outcomes and retry");
}
```

Expand All @@ -84,7 +84,7 @@ if result.type != "fill":
raise RuntimeError("unexpected operation response")
print(result.status, result.fields)
if result.status != "completed":
raise RuntimeError("stop and reconcile the fill outcome before continuing")
raise RuntimeError("fill did not complete; inspect per-field outcomes and retry")
```

</CodeGroup>
Expand All @@ -103,20 +103,20 @@ KERNEL validates bindings before writing, then fills in request order. if naviga

## Handle the outcome

the cli exits nonzero for `failed` or `unknown`, but retains the value-free result on stdout with `-o json`. preserve that output and its per-field statuses; don't discard it or retry just because the exit code is nonzero. a transport error can leave the outcome uncertain even without a result body.
the cli exits nonzero for `failed` or `unknown`, but retains the value-free result on stdout with `-o json`. use the per-field statuses to decide what to fix before retrying. a transport error can leave the outcome uncertain even without a result body.

| result | next action |
| --- | --- |
| `completed` | all fields were filled; inspect the page and decide whether to submit |
| `failed` | inspect the per-field outcomes; earlier writes aren't rolled back |
| `unknown` | stop and reconcile; at least one field's outcome can't be determined |
| transport error | treat the outcome as uncertain because writes may already have happened |
| `failed` | inspect the per-field outcomes, fix the cause, and retry; earlier writes aren't rolled back |
| `unknown` | retry; at least one field's outcome can't be determined |
| transport error | retry; writes may already have happened |

known execution failures can return http `200` with a `failed` or `unknown` status. inspect the response body, not only the http status. each entry in `fields` identifies its request binding by zero-based `index` and reports `filled`, `failed`, `unknown`, or `not_attempted`. bindings after the first failed or unknown field are `not_attempted`.

`fill` doesn't click buttons or submit forms, but input/change handlers can trigger site behavior. `completed` doesn't mean login succeeded, a form was submitted, or payment succeeded.

**don't automatically retry `fill` after a failure or uncertain outcome.** a lost response can follow successful writes; another request can repeat events, overwrite edits, or generate a different totp code. deliberate recovery starts with inspecting the existing attempt, not replaying it. preserve per-field `index`, `status`, and any `error_code` for reconciliation.
**`fill` is safe to retry after a failure, an `unknown` outcome, or a lost response.** it never submits the form, so a retry only rewrites the same fields, and a `totp` field gets a fresh code. a retry right after an `unknown` result can wait up to 15 seconds for the earlier attempt's browser lock to expire. when a field `failed`, fix its cause, such as a selector that matched nothing, before retrying.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dense fill-retry caveats packed together

Low Severity

The new retry guidance stacks several distinct caveats into one dense paragraph: retry is safe, a retry only rewrites fields, totp gets a fresh code, an unknown retry can wait 15s for the browser lock, and a failed field needs its cause fixed first. The Link outcome paragraph similarly packs completed-versus-paid, leftover writes, retry-versus-aliases, and never-retry-checkout into running prose. A short lead-in plus bullets would keep those points from being skipped.

Additional Locations (1)
Fix in Cursor Fix in Web

Triggered by learned rule: Use bullet lists when covering multiple distinct points in guides

Reviewed by Cursor Bugbot for commit a62cf9b. Configure here.


## Related guides

Expand Down
2 changes: 1 addition & 1 deletion vaults/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ availability.

retrieve the item and require `fill` in `available_operations`. your controller authorizes the destination and supplies field names and selectors, not the stored values. KERNEL checks the browser attachment and item lifecycle, validates the target inputs, and writes values into the attached browser.

`fill` returns value-free per-field outcomes. it doesn't submit a form or establish the site's acceptance. inspect failed or unknown outcomes before taking another action; don't automatically retry. see [fill browser fields](/vaults/fill) for the request and outcome contract.
`fill` returns value-free per-field outcomes. it doesn't submit a form or establish the site's acceptance. because it never submits, `fill` is safe to retry after a failed or unknown outcome. see [fill browser fields](/vaults/fill) for the request and outcome contract.

some integrations use a different operation or handoff. [agentcard](/integrations/wallets/agentcard) uses aliases and provider-executed checkout instead of `fill`; this is not a requirement for other vault items.

Expand Down
Loading