diff --git a/auth/fill-from-managed-auth.mdx b/auth/fill-from-managed-auth.mdx
index a31a0278..649bb109 100644
--- a/auth/fill-from-managed-auth.mdx
+++ b/auth/fill-from-managed-auth.mdx
@@ -73,7 +73,7 @@ These examples continue in order, using GitHub as the login destination. Set `KE
- `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.
After `fill` completes, your application or agent submits the login form once and verifies the site's response.
diff --git a/auth/fill-from-vault.mdx b/auth/fill-from-vault.mdx
index 093472a7..0a5023df 100644
--- a/auth/fill-from-vault.mdx
+++ b/auth/fill-from-vault.mdx
@@ -57,7 +57,7 @@ these examples continue in order, using hacker news as the login destination. se
- `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.
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.
diff --git a/browsers/enable-payments-in-browser-agent.mdx b/browsers/enable-payments-in-browser-agent.mdx
index 92072dc2..1872f128 100644
--- a/browsers/enable-payments-in-browser-agent.mdx
+++ b/browsers/enable-payments-in-browser-agent.mdx
@@ -35,7 +35,7 @@ and authorization state. neither item is the user's underlying wallet or card.
- 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.
@@ -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");
}
```
@@ -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")
```
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.
@@ -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 |
@@ -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
diff --git a/browsers/use-vault-credentials-in-browser-agent.mdx b/browsers/use-vault-credentials-in-browser-agent.mdx
index e1deeee4..c8fe7dfe 100644
--- a/browsers/use-vault-credentials-in-browser-agent.mdx
+++ b/browsers/use-vault-credentials-in-browser-agent.mdx
@@ -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
@@ -97,6 +98,6 @@ retrieve the item after the user confirms collection. `ready` means required val
-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.
diff --git a/integrations/wallets/stripe-link.mdx b/integrations/wallets/stripe-link.mdx
index 69f7347c..4b8cbe8a 100644
--- a/integrations/wallets/stripe-link.mdx
+++ b/integrations/wallets/stripe-link.mdx
@@ -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");
}
```
@@ -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
@@ -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.
diff --git a/snippets/fill-browser-credentials.mdx b/snippets/fill-browser-credentials.mdx
index d6d1bec5..587b2aa5 100644
--- a/snippets/fill-browser-credentials.mdx
+++ b/snippets/fill-browser-credentials.mdx
@@ -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");
}
```
@@ -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
diff --git a/snippets/fill-managed-auth-credential.mdx b/snippets/fill-managed-auth-credential.mdx
index ab05da62..5805d9ab 100644
--- a/snippets/fill-managed-auth-credential.mdx
+++ b/snippets/fill-managed-auth-credential.mdx
@@ -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");
}
```
@@ -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")
```
diff --git a/vaults/fill.mdx b/vaults/fill.mdx
index 8d947fc3..ca2eb50b 100644
--- a/vaults/fill.mdx
+++ b/vaults/fill.mdx
@@ -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.
@@ -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");
}
```
@@ -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")
```
@@ -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.
## Related guides
diff --git a/vaults/overview.mdx b/vaults/overview.mdx
index 1071c22b..8f9459dc 100644
--- a/vaults/overview.mdx
+++ b/vaults/overview.mdx
@@ -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.