@evolvingmachines/evolve 0.0.65 → 0.0.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/dist/{chunk-DK2MGUPB.js → chunk-RFLMRPGK.js} +5 -5
  2. package/dist/cli/index.cjs +39 -39
  3. package/dist/cli/index.d.cts +3 -3
  4. package/dist/cli/index.d.ts +3 -3
  5. package/dist/cli/index.js +30 -30
  6. package/dist/index.cjs +1 -1
  7. package/dist/index.d.cts +4 -4
  8. package/dist/index.d.ts +4 -4
  9. package/dist/index.js +1 -1
  10. package/dist/{types-B_qmzlMk.d.cts → types-84M4J_Vm.d.cts} +11 -44
  11. package/dist/{types-B_qmzlMk.d.ts → types-84M4J_Vm.d.ts} +11 -44
  12. package/package.json +4 -4
  13. package/skills/create-adapter/SKILL.md +71 -26
  14. package/skills/create-task/SKILL.md +124 -66
  15. package/skills/evolve/SKILL.md +37 -20
  16. package/skills/evolve-evals/SKILL.md +142 -69
  17. package/skills/evolve-evals/references/cli-reference/agent.md +76 -0
  18. package/skills/evolve-evals/references/cli-reference/analysis.md +78 -0
  19. package/skills/evolve-evals/references/cli-reference/analyze.md +95 -0
  20. package/skills/evolve-evals/references/cli-reference/auth.md +96 -0
  21. package/skills/evolve-evals/references/cli-reference/check.md +156 -0
  22. package/skills/evolve-evals/references/cli-reference/dataset.md +154 -0
  23. package/skills/evolve-evals/references/cli-reference/filesystem.md +168 -0
  24. package/skills/evolve-evals/references/cli-reference/index.md +149 -0
  25. package/skills/evolve-evals/references/cli-reference/job.md +198 -0
  26. package/skills/evolve-evals/references/cli-reference/run.md +187 -0
  27. package/skills/evolve-evals/references/cli-reference/secrets.md +77 -0
  28. package/skills/evolve-evals/references/cli-reference/session.md +56 -0
  29. package/skills/evolve-evals/references/cli-reference/skill.md +52 -0
  30. package/skills/evolve-evals/references/cli-reference/skills.md +85 -0
  31. package/skills/evolve-evals/references/cli-reference/trial.md +115 -0
  32. package/skills/evolve-evals/references/cli-reference/upload.md +72 -0
  33. package/skills/evolve-evals/references/core-concepts/agents.md +96 -0
  34. package/skills/evolve-evals/references/core-concepts/analyze.md +143 -0
  35. package/skills/evolve-evals/references/core-concepts/check.md +116 -0
  36. package/skills/evolve-evals/references/core-concepts/compatibility.md +39 -0
  37. package/skills/evolve-evals/references/core-concepts/compose.md +103 -0
  38. package/skills/evolve-evals/references/core-concepts/datasets.md +234 -0
  39. package/skills/evolve-evals/references/core-concepts/index.md +52 -0
  40. package/skills/evolve-evals/references/core-concepts/jobs.md +223 -0
  41. package/skills/evolve-evals/references/core-concepts/models.md +73 -0
  42. package/skills/evolve-evals/references/core-concepts/multi-step.md +93 -0
  43. package/skills/evolve-evals/references/core-concepts/rewardkit.md +341 -0
  44. package/skills/evolve-evals/references/core-concepts/sandboxes.md +73 -0
  45. package/skills/evolve-evals/references/core-concepts/secrets.md +86 -0
  46. package/skills/evolve-evals/references/core-concepts/sharing.md +81 -0
  47. package/skills/evolve-evals/references/core-concepts/skills.md +100 -0
  48. package/skills/evolve-evals/references/core-concepts/task-config.md +169 -0
  49. package/skills/evolve-evals/references/core-concepts/task-environment.md +127 -0
  50. package/skills/evolve-evals/references/core-concepts/task-reference.md +191 -0
  51. package/skills/evolve-evals/references/core-concepts/task-verifiers.md +209 -0
  52. package/skills/evolve-evals/references/core-concepts/tasks.md +90 -0
  53. package/skills/evolve-evals/references/core-concepts/teams.md +128 -0
  54. package/skills/evolve-evals/references/core-concepts/trial-outputs.md +225 -0
  55. package/skills/evolve-evals/references/core-concepts/trials.md +129 -0
  56. package/skills/evolve-evals/references/core-concepts/upload-sdk-session.md +240 -0
  57. package/skills/evolve-evals/references/core-concepts/upload.md +166 -0
  58. package/skills/evolve-evals/references/dashboard/checks.md +54 -0
  59. package/skills/evolve-evals/references/dashboard/datasets.md +65 -0
  60. package/skills/evolve-evals/references/dashboard/jobs.md +106 -0
  61. package/skills/evolve-evals/references/dashboard/traces.md +54 -0
  62. package/skills/evolve-evals/references/dashboard/trial-viewer.md +77 -0
  63. package/skills/evolve-evals/references/getting-started/first-task.md +228 -0
  64. package/skills/evolve-evals/references/getting-started/installation.md +79 -0
  65. package/skills/evolve-evals/references/getting-started/quick-start.md +100 -0
  66. package/skills/evolve-evals/references/index.md +58 -0
  67. package/skills/evolve-evals/references/sdk/http.md +110 -0
  68. package/skills/evolve-evals/references/sdk/python.md +108 -0
  69. package/skills/evolve-evals/references/sdk/typescript.md +104 -0
  70. package/skills/evolve-evals/references/sdk-reference/agents.md +75 -0
  71. package/skills/evolve-evals/references/sdk-reference/analyses.md +124 -0
  72. package/skills/evolve-evals/references/sdk-reference/auth.md +171 -0
  73. package/skills/evolve-evals/references/sdk-reference/checks.md +145 -0
  74. package/skills/evolve-evals/references/sdk-reference/datasets.md +170 -0
  75. package/skills/evolve-evals/references/sdk-reference/error-codes.md +231 -0
  76. package/skills/evolve-evals/references/sdk-reference/errors.md +98 -0
  77. package/skills/evolve-evals/references/sdk-reference/filesystem.md +166 -0
  78. package/skills/evolve-evals/references/sdk-reference/index.md +161 -0
  79. package/skills/evolve-evals/references/sdk-reference/jobs.md +250 -0
  80. package/skills/evolve-evals/references/sdk-reference/meta.md +54 -0
  81. package/skills/evolve-evals/references/sdk-reference/methods/agents.md +154 -0
  82. package/skills/evolve-evals/references/sdk-reference/methods/analyses.md +211 -0
  83. package/skills/evolve-evals/references/sdk-reference/methods/auth.md +257 -0
  84. package/skills/evolve-evals/references/sdk-reference/methods/checks.md +460 -0
  85. package/skills/evolve-evals/references/sdk-reference/methods/datasets.md +687 -0
  86. package/skills/evolve-evals/references/sdk-reference/methods/filesystem.md +527 -0
  87. package/skills/evolve-evals/references/sdk-reference/methods/jobs.md +1021 -0
  88. package/skills/evolve-evals/references/sdk-reference/methods/meta.md +209 -0
  89. package/skills/evolve-evals/references/sdk-reference/methods/secrets.md +157 -0
  90. package/skills/evolve-evals/references/sdk-reference/methods/skills.md +125 -0
  91. package/skills/evolve-evals/references/sdk-reference/methods/trials.md +371 -0
  92. package/skills/evolve-evals/references/sdk-reference/secrets.md +104 -0
  93. package/skills/evolve-evals/references/sdk-reference/skills.md +66 -0
  94. package/skills/evolve-evals/references/sdk-reference/trials.md +164 -0
  95. package/skills/evolve-evals/references/sdk-reference/types.md +1249 -0
  96. package/skills/publish/SKILL.md +103 -79
  97. package/skills/rewardkit/SKILL.md +78 -23
  98. package/spec/openapi.yaml +19 -74
  99. package/skills/evolve-evals/references/cli-reference/agent.mdx +0 -79
  100. package/skills/evolve-evals/references/cli-reference/analysis.mdx +0 -160
  101. package/skills/evolve-evals/references/cli-reference/analyze.mdx +0 -84
  102. package/skills/evolve-evals/references/cli-reference/auth.mdx +0 -133
  103. package/skills/evolve-evals/references/cli-reference/check.mdx +0 -263
  104. package/skills/evolve-evals/references/cli-reference/dataset.mdx +0 -151
  105. package/skills/evolve-evals/references/cli-reference/index.mdx +0 -108
  106. package/skills/evolve-evals/references/cli-reference/job.mdx +0 -278
  107. package/skills/evolve-evals/references/cli-reference/run.mdx +0 -204
  108. package/skills/evolve-evals/references/cli-reference/secrets.mdx +0 -95
  109. package/skills/evolve-evals/references/cli-reference/skill.mdx +0 -61
  110. package/skills/evolve-evals/references/cli-reference/skills.mdx +0 -81
  111. package/skills/evolve-evals/references/cli-reference/trial.mdx +0 -181
  112. package/skills/evolve-evals/references/cli-reference/upload.mdx +0 -36
  113. package/skills/evolve-evals/references/core-concepts/agents.mdx +0 -106
  114. package/skills/evolve-evals/references/core-concepts/analyze.mdx +0 -86
  115. package/skills/evolve-evals/references/core-concepts/check.mdx +0 -64
  116. package/skills/evolve-evals/references/core-concepts/datasets.mdx +0 -138
  117. package/skills/evolve-evals/references/core-concepts/index.mdx +0 -42
  118. package/skills/evolve-evals/references/core-concepts/jobs.mdx +0 -151
  119. package/skills/evolve-evals/references/core-concepts/models.mdx +0 -68
  120. package/skills/evolve-evals/references/core-concepts/sandboxes.mdx +0 -52
  121. package/skills/evolve-evals/references/core-concepts/secrets.mdx +0 -41
  122. package/skills/evolve-evals/references/core-concepts/sharing.mdx +0 -35
  123. package/skills/evolve-evals/references/core-concepts/skills.mdx +0 -42
  124. package/skills/evolve-evals/references/core-concepts/tasks.mdx +0 -216
  125. package/skills/evolve-evals/references/core-concepts/teams.mdx +0 -36
  126. package/skills/evolve-evals/references/core-concepts/trial-outputs.mdx +0 -117
  127. package/skills/evolve-evals/references/core-concepts/trials.mdx +0 -103
  128. package/skills/evolve-evals/references/core-concepts/upload.mdx +0 -93
  129. package/skills/evolve-evals/references/dashboard/checks.mdx +0 -21
  130. package/skills/evolve-evals/references/dashboard/datasets.mdx +0 -24
  131. package/skills/evolve-evals/references/dashboard/jobs.mdx +0 -65
  132. package/skills/evolve-evals/references/dashboard/traces.mdx +0 -17
  133. package/skills/evolve-evals/references/dashboard/trial-viewer.mdx +0 -30
  134. package/skills/evolve-evals/references/getting-started/installation.mdx +0 -56
  135. package/skills/evolve-evals/references/getting-started/quick-start.mdx +0 -94
  136. package/skills/evolve-evals/references/index.mdx +0 -48
  137. package/skills/evolve-evals/references/sdk/python.mdx +0 -161
  138. package/skills/evolve-evals/references/sdk/typescript.mdx +0 -163
  139. package/skills/evolve-evals/references/sdk-reference/agents.mdx +0 -108
  140. package/skills/evolve-evals/references/sdk-reference/analyses.mdx +0 -222
  141. package/skills/evolve-evals/references/sdk-reference/auth.mdx +0 -116
  142. package/skills/evolve-evals/references/sdk-reference/checks.mdx +0 -300
  143. package/skills/evolve-evals/references/sdk-reference/datasets.mdx +0 -346
  144. package/skills/evolve-evals/references/sdk-reference/errors.mdx +0 -210
  145. package/skills/evolve-evals/references/sdk-reference/index.mdx +0 -60
  146. package/skills/evolve-evals/references/sdk-reference/jobs.mdx +0 -822
  147. package/skills/evolve-evals/references/sdk-reference/meta.mdx +0 -52
  148. package/skills/evolve-evals/references/sdk-reference/skills.mdx +0 -69
  149. package/skills/evolve-evals/references/sdk-reference/trials.mdx +0 -302
  150. package/skills/evolve-evals/references/sdk-reference/types.mdx +0 -274
  151. package/skills/evolve-evals/references/snippets/global-options.mdx +0 -13
  152. package/skills/evolve-evals/references/snippets/list-flags.mdx +0 -23
@@ -0,0 +1,145 @@
1
+ ---
2
+ title: "Checks"
3
+ description: "Review task quality before spending a benchmark run."
4
+ ---
5
+
6
+ **Note:**
7
+
8
+ For every method’s inputs, return values, and language differences, see the [checks method reference](/sdk-reference/methods/checks).
9
+
10
+ A check asks an agent to inspect tasks against a quality rubric. It can read a local directory or an existing dataset version.
11
+
12
+ ## Create and wait
13
+
14
+ ```ts TypeScript
15
+ import { checks } from "@evolvingmachines/evolve";
16
+
17
+ const client = checks();
18
+ const check = await client.create({ source: { directory: "./tasks" } });
19
+ const finished = await client.watch(check.id);
20
+ for (const task of finished.results) {
21
+ console.log(task.task_name, task.status, task.checks);
22
+ }
23
+ ```
24
+
25
+ ```python Python
26
+ from evolve import checks
27
+
28
+ client = checks()
29
+ check = await client.create("./tasks")
30
+ finished = await client.watch(check["id"])
31
+ for task in finished["results"]:
32
+ print(task["task_name"], task["status"], task["checks"])
33
+ ```
34
+
35
+ For a published dataset:
36
+
37
+ ```ts TypeScript
38
+ const check = await client.create({
39
+ source: { dataset: "harbor-examples@1.0" },
40
+ include_task_names: ["hello-world"],
41
+ });
42
+ ```
43
+
44
+ ```python Python
45
+ check = await client.create(
46
+ dataset="harbor-examples@1.0",
47
+ include_task_names=["hello-world"],
48
+ )
49
+ ```
50
+
51
+ Choose one source. A local check does not first publish a dataset.
52
+
53
+ ## Configuration
54
+
55
+ | Option | Purpose |
56
+ | --- | --- |
57
+ | `name` | Check label; defaults to an acceptance timestamp |
58
+ | `model_name` | Checker model |
59
+ | `reasoning_effort` | Supported reasoning effort |
60
+ | `sandbox_provider` | Checker sandbox provider |
61
+ | `rubric` | `{criteria: [{name, description, guidance}, ...]}` |
62
+ | `prompt` | Replacement prompt template |
63
+ | `n_concurrent` | Requested parallel task checks; 1–150, bounded by team quota |
64
+ | `include_task_names` | Task-name include globs |
65
+ | `exclude_task_names` | Task-name exclude globs |
66
+ | `n_tasks` | Positive cap after filters |
67
+ | `onUploadProgress` / `on_upload_progress` | Local archive progress callback: sent/total bytes |
68
+
69
+ TypeScript places these alongside `source` in the input object. Python takes keyword arguments.
70
+
71
+ ## Read current defaults
72
+
73
+ ```ts TypeScript
74
+ const defaults = await client.defaults();
75
+ console.log(defaults.rubric, defaults.prompt);
76
+ ```
77
+
78
+ ```python Python
79
+ defaults = await client.defaults()
80
+ print(defaults["rubric"], defaults["prompt"])
81
+ ```
82
+
83
+ Defaults include model, rubric, prompt, effort, and provider. Check prompt tokens are `{task_path}`, `{file_tree}`, and `{criteria_guidance}`. They differ from analysis prompt tokens.
84
+
85
+ ## Understand the result
86
+
87
+ ```text
88
+ Check
89
+ ├── status
90
+ │ queued → running → completed
91
+ └── results[]
92
+ ├── task_name, status
93
+ ├── checks
94
+ │ └── criterion
95
+ │ ├── outcome
96
+ │ ├── explanation
97
+ │ └── evidence
98
+ └── failure, cost_usd
99
+ ```
100
+
101
+ Each task can be `queued`, `running`, `completed`, or `failed`. The check becomes `completed` once every task settles, even if a task failed.
102
+
103
+ | Field | Read it as |
104
+ | --- | --- |
105
+ | `checks` | Criterion outcomes: `pass`, `fail`, `not_applicable`, `unknown` |
106
+ | `failure` | Why that task check could not produce a result |
107
+
108
+ **Note:**
109
+
110
+ Evolve derives no verdict from a result. Read the criterion outcomes and evidence; the default rubric's execution criteria say whether the checker ran the task.
111
+
112
+ ## Read and follow checks
113
+
114
+ | Method | Options/result |
115
+ | --- | --- |
116
+ | `get(id)` | Full check and its task results |
117
+ | `list(...)` | `scope`, `status` list, `dataset`, `limit`, `cursor`; paginated handle |
118
+ | `watch(id, ...)` | Wait until completed; callback on changes |
119
+ | `defaults()` | Current policy and editable prompt |
120
+
121
+ Watch options are `onProgress`, `pollIntervalMs`, `signal` in TypeScript; `on_progress`, `poll_interval_s`, `timeout_s` in Python. Polling starts at 2 seconds and slows to 30 seconds while unchanged.
122
+
123
+ ## Inspect files and transcripts
124
+
125
+ | Need | TypeScript | Python |
126
+ | --- | --- | --- |
127
+ | Download whole check or one task check | `download(id, { to })` | `download(id, to=...)` |
128
+ | Browse a task check's sandbox | `taskFilesystem(checkId, taskCheckId)` | `task_filesystem(check_id, task_check_id)` |
129
+ | Read one task check | `task(taskCheckId)` | Read the entry in `check["results"]` |
130
+ | Read checker transcript | `transcript(taskCheckId, { since })` | Not exposed |
131
+ | Read checker artifact | `artifact(taskCheckId, stream)` | Not exposed |
132
+
133
+ For TypeScript transcripts, `since` is an inclusive nonnegative event index. Artifact selectors are `trace-stdout`, `trace-stderr`, and `agent-home`; the last returns a file map, the others text. Missing content is null.
134
+
135
+ [Filesystem methods](/sdk-reference/filesystem) and [download options](/sdk-reference/filesystem#download-options) are shared with trials and analyses.
136
+
137
+ ## Share a check
138
+
139
+ | Action | TypeScript | Python |
140
+ | --- | --- | --- |
141
+ | Share by link/email | `share(id, { link, emails })` | `share(id, link=..., emails=...)` |
142
+ | Revoke link/email access | `unshare(id, { link, emails })` | `unshare(id, link=..., emails=...)` |
143
+ | Read current shares | `shares(id)` | `shares(id)` |
144
+
145
+ Only the creator can manage shares. Sharing by email can send invitations. See [sharing](/core-concepts/sharing).
@@ -0,0 +1,170 @@
1
+ ---
2
+ title: "Datasets"
3
+ description: "Browse task versions, check a local corpus, and publish it."
4
+ ---
5
+
6
+ [Method reference: calls, parameters, and response fields](/sdk-reference/methods/datasets).
7
+
8
+ A dataset contains versioned tasks. Use a bare name for its active version, or `name@version` to select one explicitly.
9
+
10
+ ## Browse the catalog
11
+
12
+ ```ts TypeScript
13
+ import { datasets } from "@evolvingmachines/evolve";
14
+
15
+ const client = datasets();
16
+ for await (const dataset of client.list({ search: "harbor-examples" })) {
17
+ console.log(dataset.name, dataset.active_version);
18
+ }
19
+ const dataset = await client.get("harbor-examples@1.0");
20
+ console.log(dataset.tasks?.items);
21
+ ```
22
+
23
+ ```python Python
24
+ from evolve import datasets
25
+
26
+ client = datasets()
27
+ async for dataset in client.list(search="harbor-examples"):
28
+ print(dataset.name, dataset.active_version)
29
+ dataset = await client.get("harbor-examples@1.0")
30
+ print(dataset.tasks.items if dataset.tasks else [])
31
+ ```
32
+
33
+ | Method | Options | Returns |
34
+ | --- | --- | --- |
35
+ | `list(...)` | `search`, `limit`, `cursor` | Dataset handle; await one page or iterate all |
36
+ | `get(ref, ...)` | `limit`, `cursor` page the tasks | Dataset detail and one task page |
37
+ | `getActive(name, ...)` / `get_active(name, ...)` | `limit`, `cursor` | Active version and task page; raises `NoActiveVersionError` if none is active |
38
+ | `getTaskBuild(ref, task)` / `get_task_build(ref, task)` | Pinned `name@version` required | One task's build state, failure excerpt, and log reference |
39
+ | `taskFiles(ref, task)` / `task_files(ref, task)` | Pinned `name@version` required | [Package file client](/sdk-reference/filesystem#task-package-files) |
40
+
41
+ ### More catalog filters through HTTP
42
+
43
+ `GET /api/datasets` also accepts these query parameters. The CLI and SDK list methods do not expose them.
44
+
45
+ | Parameter | Values |
46
+ | --- | --- |
47
+ | `org` | Team slug or id; requires membership |
48
+ | `visibility` | `public` or `private` |
49
+ | `sortField` | `name` (default), `updated`, or `tasks` |
50
+ | `sortDirection` | `asc` (default) or `desc` |
51
+
52
+ ```bash
53
+ curl -sS --get https://dashboard.evolvingmachines.ai/api/datasets \
54
+ -H "Authorization: Bearer $EVOLVE_API_KEY" \
55
+ --data-urlencode "org=my-team" \
56
+ --data-urlencode "visibility=private" \
57
+ --data-urlencode "sortField=updated" \
58
+ --data-urlencode "sortDirection=desc"
59
+ ```
60
+
61
+ `org` selects the team's catalog, including public datasets. `visibility` narrows the selected catalog; it does not grant access to other private datasets. `updated` and `tasks` use the active version's creation time and task count. Start from the first page when changing sort order.
62
+
63
+ ## Check before publishing
64
+
65
+ Metadata preflight reads `task.toml` files and an optional `dataset.toml`. It checks their declared requirements without uploading the full corpus or building its images.
66
+
67
+ ```ts TypeScript
68
+ const verdict = await client.preflight({ source: { directory: "./tasks" } });
69
+ console.log(verdict);
70
+ ```
71
+
72
+ ```python Python
73
+ verdict = await client.preflight(directory="./tasks")
74
+ print(verdict)
75
+ ```
76
+
77
+ SDK `publish()` does not run this step automatically. Preflight is also different from an [agent-run quality check](/sdk-reference/checks).
78
+
79
+ ## Publish a version
80
+
81
+ ```text
82
+ 1. Send a source
83
+ └─ DatasetImport id returned
84
+ 2. Import and build tasks
85
+ ├─ At least one task ready
86
+ │ → version READY
87
+ └─ No usable version
88
+ → import FAILED
89
+ 3. Read the settled import and version
90
+ └─ Inspect failed_tasks
91
+ even when the version is READY
92
+ ```
93
+
94
+ ```ts TypeScript
95
+ const pending = await client.publish({
96
+ name: "my-benchmark",
97
+ version: "1.0",
98
+ source: { directory: "./tasks" },
99
+ });
100
+ const result = await client.watchImport(pending.id);
101
+ console.log(result.status, result.failure);
102
+ ```
103
+
104
+ ```python Python
105
+ pending = await client.publish(
106
+ name="my-benchmark",
107
+ version="1.0",
108
+ directory="./tasks",
109
+ )
110
+ result = await client.watch_import(pending.id)
111
+ print(result.status, result.failure)
112
+ ```
113
+
114
+ Choose exactly one source:
115
+
116
+ | Source | TypeScript `source` | Python keyword arguments | Name/version |
117
+ | --- | --- | --- | --- |
118
+ | Local corpus | `{ directory: "./tasks" }` | `directory="./tasks"` | Required unless supplied by `dataset.toml` |
119
+ | Git repository | `{ git_url, git_ref, git_path? }` | `git_url=`, `git_ref=`, optional `git_path=` | Required |
120
+ | Public tarball | `{ archive_url }` | `archive_url=` | Required |
121
+ | Public Harbor Hub package | `{ hub_package: "org/name@ref" }` | `hub_package="org/name@ref"` | May default from the package |
122
+
123
+ `org` selects the owning team, overriding the client default. Git sources need a ref; `git_path` selects a repository subdirectory.
124
+
125
+ ### Follow a publish
126
+
127
+ | Operation | TypeScript | Python |
128
+ | --- | --- | --- |
129
+ | Read one import | `getImport(id)` | `get_import(id)` |
130
+ | List your imports | `listImports({status, dataset, limit, cursor})` | `list_imports(status=..., dataset=..., limit=..., cursor=...)` |
131
+ | Wait for settlement | `watchImport(id, options)` | `watch_import(id, ...)` |
132
+
133
+ ### Upload callbacks
134
+
135
+ Pass these in the second `publish` argument in TypeScript, or as Python keyword arguments.
136
+
137
+ | TypeScript | Python | Receives |
138
+ | --- | --- | --- |
139
+ | `onUploadProgress` | `on_upload_progress` | Sent bytes, total archive bytes |
140
+ | `onRegistered` | `on_registered` | Import id when a resumable upload registers it |
141
+
142
+ Local dataset and job archives larger than 256 MiB use resumable transfer. Remote-source submissions upload no client archive. Python upload callbacks run on the uploader thread and must be thread-safe.
143
+
144
+ ### Watch options
145
+
146
+ | TypeScript | Python | Meaning |
147
+ | --- | --- | --- |
148
+ | `onStatus` | `on_status` | Called when import status/receiving state changes |
149
+ | `onProgress` | `on_progress` | Called with changed progress and the import |
150
+ | `onVersion` | `on_version` | Called with version and dataset during settlement |
151
+ | `pollIntervalMs` | `poll_interval_s` | Default `2000` ms / `2` s |
152
+ | `settleTimeoutMs` | `settle_timeout_s` | Post-import version settlement bound; default 30 minutes |
153
+ | `signal` | `timeout_s` | Stop waiting / bound the overall Python wait |
154
+
155
+ A failed import is returned with `status: FAILED` and a failure object. Dataset completion also confirms that its version settled. Stopping your wait does not cancel the import.
156
+
157
+ ## Download and manage
158
+
159
+ | Action | TypeScript | Python |
160
+ | --- | --- | --- |
161
+ | Download original package | `download(ref, { to: "./packages" })` | `download(ref, to="./packages")` |
162
+ | Select active version | `activate(name, version)` | `activate(name, version)` |
163
+ | Follow upstream changes | `update(name, { upstream_auto_import: true })` | `update(name, upstream_auto_import=True)` |
164
+ | Delete dataset | `delete(name)` | `delete(name)` |
165
+
166
+ Original-package download is owner-only. Platform-curated datasets do not have a downloadable owner package through this method. [Task package files](/sdk-reference/filesystem#task-package-files) are a separate inspection surface.
167
+
168
+ Only a READY version can be activated. Upstream auto-import needs a watchable git source. Deletion is refused while jobs still reference the dataset.
169
+
170
+ Download returns bytes by default; `to` names a directory. TypeScript also supports a raw stream. See [download options](/sdk-reference/filesystem#download-options).
@@ -0,0 +1,231 @@
1
+ ---
2
+ title: "Error codes"
3
+ description: "Every known code, what it means, and what to do next."
4
+ ---
5
+
6
+ Use `code` to identify a failure. Read `param` for the input to fix and `details` for the full context. See [Errors](/sdk-reference/errors) for TypeScript and Python handlers.
7
+
8
+ This catalog covers all 122 codes known to the SDK. A newer server can add codes; [Meta](/sdk-reference/meta) lists the deployment's vocabulary.
9
+
10
+ **Info:**
11
+
12
+ An API refusal raises an SDK exception. An accepted import can fail later and return a `failure` record instead. A skipped trial appears in `skipped_trials`. The [job import section](#job-imports) separates these cases.
13
+
14
+ ## Keys, credits, and quotas
15
+
16
+ | Code | Meaning and next step |
17
+ | --- | --- |
18
+ | `missing_authorization` | The request has no usable authorization. Supply an Evolve API key. |
19
+ | `invalid_api_key` | The key is invalid, or a key lookup found no matching key. Check the key or key ID used by the request. |
20
+ | `read_only_key` | This operation changes data. Use a key with write access. |
21
+ | `credential_service_unavailable` | The credential service could not complete an authentication, key, credit, or organization-budget operation. Retry after the supplied delay. |
22
+ | `rate_limited` | The request rate exceeded its limit. Wait for `retryAfterSec` / `retry_after_sec`. |
23
+ | `insufficient_credits` | The account has no remaining credits. Add credits before starting more work. |
24
+ | `quota_exceeded` | The request would exceed the organization's queued-trial limit. Read `details` for the limit, usage, and requested count. No fixed retry delay is supplied. |
25
+
26
+ ## Request inputs
27
+
28
+ | Code | Meaning and next step |
29
+ | --- | --- |
30
+ | `invalid_json` | The JSON body or JSON form part could not be parsed, or a required object was not an object. Correct its structure. |
31
+ | `invalid_input` | An input failed validation or exceeded a limit. Read `message`, `param`, and `details`; this code covers several input rules. |
32
+ | `invalid_limit` | `limit` is not an integer within the endpoint's allowed range. Use the range named in the message. |
33
+ | `invalid_status` | A status filter is not supported. Choose one of the values named in the response. |
34
+ | `invalid_visibility` | Visibility is neither `public` nor `private`. |
35
+ | `invalid_cursor` | The collection cursor is invalid for this request. Use a `nextCursor` returned by the same collection and sort order. |
36
+ | `invalid_after` | The stream resume position is invalid. Use an event ID from that stream; its format depends on the stream. |
37
+ | `invalid_format` | The requested output format is not supported. Use a format named in the message, or omit it for the default. |
38
+ | `invalid_ids` | A stop request has an invalid trial-ID list: it must contain 1–100 nonempty IDs. |
39
+ | `invalid_multipart` | The upload is not valid `multipart/form-data`. Correct the content type and form parts. |
40
+ | `idempotency_key_reused` | This idempotency key belongs to a different request. Repeat the original request exactly, or use a new key for new work. |
41
+
42
+ ## Datasets and tasks
43
+
44
+ | Code | Meaning and next step |
45
+ | --- | --- |
46
+ | `dataset_not_found` | The dataset does not exist or is not visible to you. Check its name and your access. |
47
+ | `dataset_version_not_found` | The requested dataset version was not found. List the dataset's versions and use an existing one. |
48
+ | `dataset_name_taken` | The dataset name is already in use and unavailable to this publish. Choose another name. |
49
+ | `dataset_in_use` | Jobs still reference the dataset, so it cannot be deleted. Read `details.job_count` and `details.sample_job_ids`. |
50
+ | `dataset_not_owned` | You cannot perform this dataset operation with the current ownership or credentials. Read the message for the required owner or administrator access. |
51
+ | `dataset_import_in_progress` | Visibility cannot change while an import is queued or running. Wait for the import to finish. |
52
+ | `upstream_not_watchable` | Auto-import was requested for a dataset with no moving Git ref to follow. It has no watchable upstream. |
53
+ | `no_active_version` | A dataset was selected without a version, but it has no active version. Pin a ready version or activate one. |
54
+ | `version_not_ready` | The operation requires a `READY` dataset version. Inspect the version's state and import progress. |
55
+ | `version_not_activatable` | A `FAILED` or `ARCHIVED` version cannot become active. Choose a ready version. |
56
+ | `unknown_task_names` | Requested task names are missing from the version. `details.unknown_task_names` contains the complete list. |
57
+ | `no_tasks` | The dataset or selection has no runnable tasks. Check the filters and any failed task builds. |
58
+ | `task_not_found` | The named task or its build record was not found in the version. Check the task name and version. |
59
+ | `task_failed_to_build` | An explicitly selected task failed to build. Read `details.failed_tasks`; fix and publish a new version, or change the selection. |
60
+
61
+ ## Dataset imports and packages
62
+
63
+ | Code | Meaning and next step |
64
+ | --- | --- |
65
+ | `import_not_found` | The dataset import was not found or is not visible to you. Check the import ID and account. |
66
+ | `import_too_large` | The dataset archive exceeds a receiving or storage limit. Read the stated bound and reduce the archive. |
67
+ | `invalid_archive` | The archive cannot be read or contains unsafe entries. Correct the archive before submitting it again. |
68
+ | `unpinned_git_ref` | The Git ref is neither a full 40-character commit SHA nor a remote tag. Pin the full commit or a tag. |
69
+ | `hub_package_not_found` | The Harbor Hub package does not exist or is private. Check the reference; authenticated Hub sources are not supported. |
70
+ | `hub_unreachable` | Evolve could not reach Harbor Hub to resolve the package. Retry the publish when the Hub is reachable. |
71
+ | `package_not_retained` | This version has no retained original package. Import the corpus as a new version to retain one. |
72
+ | `package_corrupt` | The stored package failed its checksum check and was not served. Keep the request ID when reporting it. |
73
+ | `package_missing` | The recorded package is no longer in storage. Import the corpus as a new version to restore a downloadable package. |
74
+
75
+ ## Resumable uploads
76
+
77
+ These codes apply to chunked dataset and job uploads. They describe the transfer, before an accepted import finishes processing.
78
+
79
+ | Code | Meaning and next step |
80
+ | --- | --- |
81
+ | `upload_session_not_found` | The upload session does not exist or belongs to another caller. Check the upload ID and account. |
82
+ | `upload_offset_mismatch` | The chunk offset differs from the session's next byte. Probe the offset with `HEAD` and resume there; complete the session if all bytes arrived. |
83
+ | `upload_chunk_digest_mismatch` | The chunk failed its checksum check; none of that chunk was stored. Send the correct chunk again. |
84
+ | `upload_incomplete` | Completion was requested before all declared bytes arrived. Send the remaining chunks, then complete. |
85
+ | `upload_archive_digest_mismatch` | The assembled archive failed its checksum check. The assembled object was deleted; start a new upload. |
86
+ | `upload_session_failed` | The session already failed. Read `details.failure` and start a new upload after addressing the cause. |
87
+
88
+ ## Harness settings
89
+
90
+ | Code | Meaning and next step |
91
+ | --- | --- |
92
+ | `agent_version_not_found` | The pinned harness version is not published. Choose an available version. |
93
+ | `agent_version_unresolvable` | Evolve could not resolve the latest unpinned harness version. Retry after the supplied delay. |
94
+ | `agent_kwarg_unsupported` | A harness argument is unsupported. Compare `details.unsupported_kwargs` with `details.supported_kwargs`. |
95
+ | `agent_config_unsupported` | This harness does not support a native config. Omit it or choose a harness listed in `details.config_supporting_agents`. |
96
+ | `agent_config_key_refused` | Native config contains settings that Evolve controls, such as routing or credentials. Remove the keys named in `details.refused_keys`. |
97
+ | `agent_preset_unsupported` | This harness cannot apply the requested preset. Choose a supported harness or remove the preset. |
98
+
99
+ ## Registered agents
100
+
101
+ | Code | Meaning and next step |
102
+ | --- | --- |
103
+ | `agent_not_found` | No registered agent with this name is available to you. Check the name and organization. |
104
+ | `agent_name_taken` | You already have an agent registered with this name. Update that registration or choose another name. |
105
+ | `agent_name_reserved` | The name belongs to a built-in harness. Choose another name. |
106
+ | `agent_invalid_name` | The name does not match the allowed pattern or length. Follow the pattern in the message. |
107
+ | `agent_source_required` | Registration has no source. Supply an install script or a source archive. |
108
+ | `agent_source_conflict` | Both source forms were supplied. Choose either an install script or an archive. |
109
+ | `agent_invalid_env` | The environment map is malformed, too large, overrides a reserved variable, or contains a credential-like name. Correct the entry named in the message. |
110
+ | `agent_too_large` | The agent archive exceeds its upload limit. Reduce it to the bound in the response. |
111
+ | `agent_limit_reached` | The account reached its registered-agent limit. Remove an unused registration before adding another. |
112
+
113
+ ## Skills
114
+
115
+ | Code | Meaning and next step |
116
+ | --- | --- |
117
+ | `skill_not_found` | The uploaded skill ID was not found or is unavailable to you. Check the ID and access. |
118
+ | `skill_name_not_found` | `name:<skill-name>` has no current upload for this caller. List your skills and check the name. |
119
+ | `skill_ref_invalid` | The skill reference list is malformed, exceeds its count limit, or contains an unsupported reference. Read the message; local folders must be uploaded first. |
120
+ | `skill_unresolvable` | Evolve could not resolve a skill source to a pinned reference. Read the cause and check that the source can be fetched. |
121
+ | `skill_invalid` | The uploaded archive is not a valid skill. Fix the archive or skill content named in the message. |
122
+ | `skill_in_use` | An unfinished job references this skill upload. Wait for that job before deleting the skill. |
123
+ | `skill_too_large` | The skill archive exceeds its upload limit. Reduce it to the bound in the response. |
124
+ | `skill_limit_reached` | The account reached its uploaded-skill limit. Remove unused uploads before adding another. |
125
+
126
+ ## Job secrets
127
+
128
+ These codes describe secret attachment during job creation. The [managed-secrets client](/sdk-reference/secrets) uses separate error handling.
129
+
130
+ | Code | Meaning and next step |
131
+ | --- | --- |
132
+ | `secret_not_found` | No enabled secret matches the requested name and label. Check the stored secret and its label. |
133
+ | `secret_ambiguous` | Several labels match the name, with no default to select. Supply an explicit label. |
134
+ | `secret_brokered_unsupported` | Jobs cannot attach a secret that uses brokered delivery. Choose a secret intended for direct delivery. |
135
+ | `secret_exists` | An inline secret conflicts with an existing stored identity; Evolve will not overwrite it. Attach the stored secret by reference or choose another label. |
136
+ | `secret_not_attached` | A task requires a secret with no fallback, and the job did not attach it under the required environment name. Add the attachment. |
137
+
138
+ ## Jobs and trials
139
+
140
+ | Code | Meaning and next step |
141
+ | --- | --- |
142
+ | `provider_unsupported` | Selected tasks cannot run on the chosen sandbox provider. Read every reason in `details.refused_tasks` and adjust the provider or selection. |
143
+ | `job_not_found` | The job was not found or is not visible to you. Check its ID and your access. |
144
+ | `job_not_terminal` | The operation requires a finished job. Wait for it to settle; deletion can also be blocked by a running regrade named in `details`. |
145
+ | `no_failed_trials` | Resume or retry found no trials matching its selection. Scored trials, including reward `0`, are not failures. Check the operation's selection rules. |
146
+ | `trial_not_found` | The trial or requested run artifact was not found or is unavailable to you. Check the ID, parent job, and artifact. |
147
+ | `trial_not_settled` | A retry selected a live trial. Wait until it leaves `QUEUED`, `RUNNING`, or `SCORING`. |
148
+ | `concurrent_update` | Cancellation could not be committed because the job changed concurrently. Read the current job state, then retry if needed. |
149
+ | `job_uploaded` | Resume, retry, and regrade require a job Evolve executed. Uploaded jobs can still be analyzed. |
150
+
151
+ ## Regrades
152
+
153
+ | Code | Meaning and next step |
154
+ | --- | --- |
155
+ | `regrade_source_ineligible` | The trial lacks usable verifier inputs or uses an unsupported regrade setup, such as a multi-step task or LLM judge. Read the recorded reason. |
156
+ | `no_regradable_trials` | No selected trial is eligible for regrade. Inspect the original trials and their verifier inputs. |
157
+
158
+ ## Analysis and task checks
159
+
160
+ | Code | Meaning and next step |
161
+ | --- | --- |
162
+ | `invalid_rubric` | The analysis or check configuration is invalid. Correct the unknown keys, criteria, or bounds named in the message. |
163
+ | `analysis_already_running` | The job already has queued or running analysis. Wait for it to finish before another analysis or job deletion. |
164
+ | `analysis_not_found` | The analysis was not found or is not visible to you. Check the analysis ID and access. |
165
+ | `analysis_not_terminal` | The analysis download requires a finished run. Wait for `COMPLETED` or `FAILED`. |
166
+ | `no_analyzable_trials` | No trial matches the analysis selection: it is empty, only cancelled trials remain, or the reward filter excludes every trial. Adjust the selection. |
167
+ | `check_not_found` | The check or task-check ID was not found or is not visible to you. Check the ID and access. |
168
+ | `check_not_terminal` | The check download requires a finished check or task check. Wait for `COMPLETED` or `FAILED`. |
169
+ | `no_checkable_tasks` | No valid task directories were found, or the filters selected none. Check the source task structure and selection. |
170
+
171
+ ## Job imports
172
+
173
+ Job upload returns an import record before validation finishes. A later failure is returned as `status: FAILED` with `failure.code`, `failure.message`, and optional `failure.details`. Reading that record can succeed over HTTP.
174
+
175
+ | Code | Meaning and next step |
176
+ | --- | --- |
177
+ | `not_a_job_dir` | **Import failure.** Root `result.json` or `config.json` is missing, invalid, or too large to parse. Fix the file and limit named in the failure; see the [job directory format](/core-concepts/upload). |
178
+ | `invalid_trial` | **Import failure.** A trial record, lock file, or trace could not be read or accepted. Fix the file and cause named in the failure. |
179
+ | `job_already_uploaded` | **Import failure.** You already uploaded the source job ID in this archive. Use `details.existing_job_id` to open the existing record. |
180
+ | `trial_too_large` | **Skipped trial.** An artifact exceeds a storage or parsing bound. Read `skipped_trials` for the file and limit; other trials can still import. |
181
+ | `upload_too_large` | A job or check upload exceeds a transfer, extraction, or storage bound. It can be an HTTP refusal or a job import failure. Read the file and limit named in the response. |
182
+ | `job_import_not_found` | **API refusal.** The job import does not exist or belongs to another caller. Check the import ID and account. |
183
+
184
+ Job import failures can also use shared codes such as `invalid_archive`, `dataset_not_found`, `dataset_version_not_found`, `no_active_version`, and `version_not_ready`. Preserve an unfamiliar failure code: import failures can include values outside this API vocabulary, such as `import_failed`.
185
+
186
+ ## Filesystems and sessions
187
+
188
+ | Code | Meaning and next step |
189
+ | --- | --- |
190
+ | `not_found` | The filesystem path or capture record was not found. Check the path, source, and capture named in the response. |
191
+ | `not_captured` | The file is listed, but its bytes were not saved: it was unchanged from the image or omitted during capture. Read `details.reason` when present. |
192
+ | `filesystem_state` | The requested live or captured filesystem is unavailable. Read `details.state`; a capture may still be running or no source may remain. |
193
+ | `feature_unsupported` | This provider or run does not support the requested filesystem feature. Read `details.feature` and `details.cause`. |
194
+ | `provider_unreachable` | The sandbox provider did not answer. Retry after the supplied delay. |
195
+ | `task_package_not_retained` | The dataset version has no retained task package, so its task files cannot be served. |
196
+ | `session_not_found` | The managed-agent session was not found or is not visible to you. Check the session ID and access. |
197
+
198
+ ## Organizations and invites
199
+
200
+ | Code | Meaning and next step |
201
+ | --- | --- |
202
+ | `org_not_found` | The organization does not exist or you are not a member. Check the organization and account. |
203
+ | `org_slug_taken` | Another organization already uses this slug. Choose another slug. |
204
+ | `org_forbidden` | Your role or credentials do not allow the operation. The message names the restriction; deleting a job requires its creator. |
205
+ | `org_personal_immutable` | Personal organizations cannot be modified or deleted, and their permanent owner cannot be changed. Use a team organization for membership changes. |
206
+ | `org_last_owner` | This change would remove the organization's last owner. Promote another owner first. |
207
+ | `org_in_use` | The organization still owns jobs or datasets and cannot be deleted. `details` provides the counts. |
208
+ | `org_member_not_found` | The named user is not a member of this organization. Check the user ID. |
209
+ | `invite_not_found` | The invite ID or token was not found. Check the invitation. |
210
+ | `invite_invalid` | The invitation is revoked, expired, or out of uses. Read `details.reason` and request a new invite. |
211
+
212
+ ## Temporary server capacity
213
+
214
+ These are capacity limits, separate from request rate limits. Each response provides `details.max_concurrent`, with no fixed retry delay. Retry after an in-flight operation finishes.
215
+
216
+ | Code | Operation waiting for capacity |
217
+ | --- | --- |
218
+ | `too_many_concurrent_upload_chunks` | Receiving another upload chunk. Retry the same chunk offset. |
219
+ | `too_many_concurrent_imports` | Receiving another dataset archive. |
220
+ | `too_many_concurrent_job_uploads` | Moving another job archive into storage. |
221
+ | `too_many_concurrent_check_uploads` | Receiving another task-check archive. |
222
+ | `too_many_concurrent_skill_uploads` | Receiving and processing another skill archive. |
223
+ | `too_many_concurrent_package_downloads` | Serving another retained package download. |
224
+
225
+ ## Server failures
226
+
227
+ | Code | Meaning and next step |
228
+ | --- | --- |
229
+ | `internal_error` | The server encountered an unexpected failure. Keep the request ID when reporting it. |
230
+
231
+ `unknown_error` is an SDK fallback when a response provides no usable code. It is not one of the 122 codes above. Preserve the status, message, and request ID rather than guessing a cause.
@@ -0,0 +1,98 @@
1
+ ---
2
+ title: "Errors"
3
+ description: "Handle API refusals separately from local, transfer, and wait failures."
4
+ ---
5
+
6
+ For hosted API refusals, branch on the error's stable `code`. Keep `requestId` / `request_id` when reporting a problem.
7
+
8
+ Looking up a specific failure? The [error code reference](/sdk-reference/error-codes) explains every known code and its next step.
9
+
10
+ ## Catch an API refusal
11
+
12
+ ```ts TypeScript
13
+ import { EvolveApiError, jobs } from "@evolvingmachines/evolve";
14
+
15
+ try {
16
+ await jobs().get(jobId);
17
+ } catch (error) {
18
+ if (error instanceof EvolveApiError) {
19
+ console.error(error.status, error.code, error.param, error.requestId);
20
+ console.error(error.details);
21
+ } else {
22
+ throw error;
23
+ }
24
+ }
25
+ ```
26
+
27
+ ```python Python
28
+ from evolve import EvolveAPIError, jobs
29
+
30
+ try:
31
+ await jobs().get(job_id)
32
+ except EvolveAPIError as error:
33
+ print(error.status, error.code, error.param, error.request_id)
34
+ print(error.details)
35
+ ```
36
+
37
+ | Field | Meaning |
38
+ | --- | --- |
39
+ | `status` | HTTP status |
40
+ | `code` | Stable failure identifier; a newer server can add codes |
41
+ | `message` / `str(error)` | Human-readable explanation |
42
+ | `param` | Input field or query parameter to fix, when known |
43
+ | `details` | Structured failure context |
44
+ | `retryAfterSec` / `retry_after_sec` | Server's requested wait, when supplied |
45
+ | `requestId` / `request_id` | Request identifier for diagnosis |
46
+
47
+ `isKnownCode()` / `is_known_code()` checks this SDK's known code list. `HOSTED_ERROR_CODES` and `isHostedErrorCode` / `is_hosted_error_code` are exported. [Meta](/sdk-reference/meta) publishes the deployment's current list.
48
+
49
+ ## Common next actions
50
+
51
+ | Code | Next step |
52
+ | --- | --- |
53
+ | `invalid_input` | Fix the named parameter and read `details` |
54
+ | `provider_unsupported` | Inspect refused task requirements and choose a compatible setup |
55
+ | `job_not_terminal` | Wait for the job to settle before this operation |
56
+ | `no_analyzable_trials` | Check selected ids, reward filters, and trial statuses |
57
+ | `analysis_already_running` | Wait for the existing wave |
58
+ | `filesystem_state` | Read filesystem status and choose an available source |
59
+ | `not_captured` | The file has no saved bytes; inspect capture metadata |
60
+ | `secret_ambiguous` | Choose a label explicitly |
61
+
62
+ An unknown code is still an API error. Do not replace it with a guessed classification.
63
+
64
+ ## Failures outside the API error class
65
+
66
+ | Failure | TypeScript | Python |
67
+ | --- | --- | --- |
68
+ | Dataset has no active version | `NoActiveVersionError` | `NoActiveVersionError` |
69
+ | Dataset version did not settle within watch's bound | `ImportSettleError` | `ImportSettleError` |
70
+ | Download length differs | `EvolveIncompleteDownloadError` | Same name |
71
+ | Download digest differs | `EvolveDigestMismatchError` | Same name |
72
+ | Upload inactivity | `EvolveUploadTimeoutError` | Transport timeout exception |
73
+ | Missing key / invalid local arguments | Usually `Error` | Usually `ValueError` or `TypeError` |
74
+ | Managed secret HTTP failure | `Error` | `RuntimeError` |
75
+
76
+ A failed import is usually a returned import with `status: FAILED` and `failure`. That is different from failing to read the import over HTTP.
77
+
78
+ ## Retry the right thing
79
+
80
+ ```text
81
+ API request refused
82
+ ├─ Ordinary call
83
+ │ → error returned to your code
84
+ ├─ Job event watch
85
+ │ → reconnects on transport errors
86
+ │ and 429/5xx
87
+ ├─ Polling watch
88
+ │ → waits through 429/503
89
+ └─ Resumable upload
90
+ → bounded transport/rate-limit
91
+ retries
92
+
93
+ Trial execution failed
94
+ └─ Job retry policy
95
+ → separate server-side decision
96
+ ```
97
+
98
+ The SDK does not blindly retry every write. Use idempotency keys on [supported job operations](/sdk-reference/jobs). Aborting a watch stops waiting; it does not cancel the remote work.