Skip to content

Commit a62cf9b

Browse files
committed
Describe vault fill as safe to retry
1 parent 37e9af0 commit a62cf9b

9 files changed

Lines changed: 32 additions & 30 deletions

‎auth/fill-from-managed-auth.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ These examples continue in order, using GitHub as the login destination. Set `KE
7373

7474
<FillManagedAuthCredential />
7575

76-
`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.
76+
`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.
7777
</Step>
7878
<Step title="Submit and handle the response">
7979
After `fill` completes, your application or agent submits the login form once and verifies the site's response.

‎auth/fill-from-vault.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ these examples continue in order, using hacker news as the login destination. se
5757

5858
<FillBrowserCredentials />
5959

60-
`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.
60+
`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.
6161
</Step>
6262
<Step title="Submit and Handle the Response">
6363
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.

‎browsers/enable-payments-in-browser-agent.mdx‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ and authorization state. neither item is the user's underlying wallet or card.
3535
<Warning>
3636
- 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.
3737
- 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.
38-
- 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.
38+
- 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.
3939
- 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.
4040
</Warning>
4141

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

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

326326
</CodeGroup>
327327

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

@@ -617,7 +618,7 @@ is unavailable or the sources disagree, keep the result indeterminate and don't
617618
| `payment_requires_action` | continue the existing merchant flow without resubmitting payment |
618619
| `payment_processing` | wait for the existing payment and inspect the merchant's status |
619620
| `fill` `completed` or `credential_fill_attempted` | inspect per-field outcomes and merchant state; filling alone does not prove submission or payment success |
620-
| `fill` `failed`, `unknown`, or a lost response | preserve partial or uncertain outcomes; stop without automatic retries or alias fallback |
621+
| `fill` `failed`, `unknown`, or a lost response | retry `fill`; it never submits checkout. don't fall back to aliases |
621622
| agentcard `ready` or authorization `approved` | inspect charge, replay, and merchant state; reusable item state does not prove purchase success |
622623
| decline, expiry, rejection, failure, abandonment, or `payment_unknown` | stop and reconcile the existing attempt before deciding whether a new purchase is appropriate |
623624
| `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.
735736
card and billing fields. fill writes actual values into the browser; do not
736737
read them back, expose them in model context, or assume recordings omit them.
737738
10. preserve the value-free fill result and every per-field outcome. continue
738-
only on `completed`; failed or unknown outcomes, transport errors, or missing
739-
required fields mean stop and reconcile. never automatically retry fill or
739+
only on `completed`. fill never submits checkout, so retry it after failed or
740+
unknown outcomes or transport errors; missing required fields mean stop. never
740741
fall back to aliases. supply other customer fields only from approved user
741742
data, complete any agent disclosure truthfully, then submit checkout once.
742743
11. inspect the checkout result, fill outcomes, and item events. report success

‎browsers/use-vault-credentials-in-browser-agent.mdx‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ verify access with `kernel vaults list --limit 1 -o json` and check
5151
don't open it in your browser. i will enter my credentials and tell you when
5252
i'm done. never ask me to paste my password into the conversation.
5353
4. after i confirm, retrieve the item and require ready plus an advertised fill
54-
operation. invoke fill once with the browser session ID, exact login URL,
54+
operation. invoke fill with the browser session ID, exact login URL,
5555
and selectors that uniquely identify the login inputs. don't read, print,
56-
screenshot, or return the filled values. if fill fails, returns unknown, or
57-
loses its response, stop rather than retrying or using another fill path.
56+
screenshot, or return the filled values. fill never submits the form, so if
57+
it fails, returns unknown, or loses its response, retry it. don't use another
58+
fill path.
5859
5. if fill completed, submit login once, verify the site's response, and tell me
5960
my karma. if login fails or needs more interaction, ask me what to do next.
6061
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
9798

9899
<FillBrowserCredentials />
99100

100-
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.
101+
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.
101102

102103
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.

‎integrations/wallets/stripe-link.mdx‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ const result = await kernel.vaults.items.performOperation(card.key, {
526526
if (result.type !== "fill") throw new Error("unexpected operation response");
527527
console.log(result.status, result.fields);
528528
if (result.status !== "completed") {
529-
throw new Error("stop and reconcile per-field outcomes; do not retry");
529+
throw new Error("fill did not complete; inspect per-field outcomes and retry");
530530
}
531531
```
532532

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

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

579579
### Handle the outcome
580580

581-
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.
581+
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.
582582

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

585-
`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.
585+
`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.
586586

587587
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.
588588

‎snippets/fill-browser-credentials.mdx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const result = await kernel.vaults.items.performOperation(item.key, {
2121
],
2222
});
2323
if (result.type !== "fill" || result.status !== "completed") {
24-
throw new Error("stop and reconcile the fill outcome");
24+
throw new Error("fill did not complete; inspect per-field outcomes and retry");
2525
}
2626
```
2727

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

4949
```bash CLI

‎snippets/fill-managed-auth-credential.mdx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const result = await kernel.vaults.items.performOperation(item.key, {
2222
],
2323
});
2424
if (result.type !== "fill" || result.status !== "completed") {
25-
throw new Error("stop and reconcile the fill outcome");
25+
throw new Error("fill did not complete; inspect per-field outcomes and retry");
2626
}
2727
```
2828

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

5555
</CodeGroup>

‎vaults/fill.mdx‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ the item must be ready and contain a stored value for each requested field. addi
2121

2222
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.
2323

24-
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.
24+
`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.
2525

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

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

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

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

104104
## Handle the outcome
105105

106-
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.
106+
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.
107107

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

115115
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`.
116116

117117
`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.
118118

119-
**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.
119+
**`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.
120120

121121
## Related guides
122122

‎vaults/overview.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ availability.
8888

8989
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.
9090

91-
`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.
91+
`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.
9292

9393
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.
9494

0 commit comments

Comments
 (0)