amness 0.0.0-stage → 0.1.2

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 (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +237 -2
  3. package/dist/cli/acpcli.d.ts +7 -0
  4. package/dist/cli/acpcli.js +14 -0
  5. package/dist/cli/amness.d.ts +2 -0
  6. package/dist/cli/amness.js +694 -0
  7. package/dist/cli/benchcli.d.ts +5 -0
  8. package/dist/cli/benchcli.js +160 -0
  9. package/dist/cli/config.d.ts +79 -0
  10. package/dist/cli/config.js +111 -0
  11. package/dist/cli/demo.d.ts +13 -0
  12. package/dist/cli/demo.js +44 -0
  13. package/dist/cli/detect.d.ts +2 -0
  14. package/dist/cli/detect.js +20 -0
  15. package/dist/cli/evalcli.d.ts +15 -0
  16. package/dist/cli/evalcli.js +198 -0
  17. package/dist/cli/format.d.ts +5 -0
  18. package/dist/cli/format.js +55 -0
  19. package/dist/cli/headless.d.ts +2 -0
  20. package/dist/cli/headless.js +169 -0
  21. package/dist/cli/keystore.d.ts +9 -0
  22. package/dist/cli/keystore.js +108 -0
  23. package/dist/cli/model.d.ts +11 -0
  24. package/dist/cli/model.js +19 -0
  25. package/dist/cli/plugincli.d.ts +2 -0
  26. package/dist/cli/plugincli.js +176 -0
  27. package/dist/cli/schedulecli.d.ts +2 -0
  28. package/dist/cli/schedulecli.js +66 -0
  29. package/dist/cli/state.d.ts +11 -0
  30. package/dist/cli/state.js +19 -0
  31. package/dist/cli/tui/ansi.d.ts +38 -0
  32. package/dist/cli/tui/ansi.js +142 -0
  33. package/dist/cli/tui/app.d.ts +328 -0
  34. package/dist/cli/tui/app.js +1358 -0
  35. package/dist/cli/tui/blocks.d.ts +151 -0
  36. package/dist/cli/tui/blocks.js +128 -0
  37. package/dist/cli/tui/brand.d.ts +9 -0
  38. package/dist/cli/tui/brand.js +16 -0
  39. package/dist/cli/tui/canvas.d.ts +92 -0
  40. package/dist/cli/tui/canvas.js +199 -0
  41. package/dist/cli/tui/cards.d.ts +44 -0
  42. package/dist/cli/tui/cards.js +215 -0
  43. package/dist/cli/tui/clipboard.d.ts +5 -0
  44. package/dist/cli/tui/clipboard.js +29 -0
  45. package/dist/cli/tui/commands.d.ts +10 -0
  46. package/dist/cli/tui/commands.js +650 -0
  47. package/dist/cli/tui/complete.d.ts +39 -0
  48. package/dist/cli/tui/complete.js +113 -0
  49. package/dist/cli/tui/custom.d.ts +9 -0
  50. package/dist/cli/tui/custom.js +34 -0
  51. package/dist/cli/tui/diffview.d.ts +25 -0
  52. package/dist/cli/tui/diffview.js +130 -0
  53. package/dist/cli/tui/editor.d.ts +60 -0
  54. package/dist/cli/tui/editor.js +230 -0
  55. package/dist/cli/tui/full.d.ts +86 -0
  56. package/dist/cli/tui/full.js +630 -0
  57. package/dist/cli/tui/keys.d.ts +31 -0
  58. package/dist/cli/tui/keys.js +134 -0
  59. package/dist/cli/tui/markdown.d.ts +37 -0
  60. package/dist/cli/tui/markdown.js +155 -0
  61. package/dist/cli/tui/mentions.d.ts +15 -0
  62. package/dist/cli/tui/mentions.js +48 -0
  63. package/dist/cli/tui/modal.d.ts +26 -0
  64. package/dist/cli/tui/modal.js +107 -0
  65. package/dist/cli/tui/overlays.d.ts +98 -0
  66. package/dist/cli/tui/overlays.js +237 -0
  67. package/dist/cli/tui/pager.d.ts +15 -0
  68. package/dist/cli/tui/pager.js +66 -0
  69. package/dist/cli/tui/pricing.d.ts +9 -0
  70. package/dist/cli/tui/pricing.js +23 -0
  71. package/dist/cli/tui/rich.d.ts +16 -0
  72. package/dist/cli/tui/rich.js +72 -0
  73. package/dist/cli/tui/screen.d.ts +30 -0
  74. package/dist/cli/tui/screen.js +62 -0
  75. package/dist/cli/tui/session.d.ts +77 -0
  76. package/dist/cli/tui/session.js +103 -0
  77. package/dist/cli/tui/sidebar.d.ts +84 -0
  78. package/dist/cli/tui/sidebar.js +114 -0
  79. package/dist/cli/tui/text.d.ts +15 -0
  80. package/dist/cli/tui/text.js +94 -0
  81. package/dist/cli/tui/theme.d.ts +59 -0
  82. package/dist/cli/tui/theme.js +148 -0
  83. package/dist/cli/tui/themes.d.ts +56 -0
  84. package/dist/cli/tui/themes.js +80 -0
  85. package/dist/cli/tui/tokens.d.ts +39 -0
  86. package/dist/cli/tui/tokens.js +71 -0
  87. package/dist/cli/tui/view.d.ts +60 -0
  88. package/dist/cli/tui/view.js +178 -0
  89. package/dist/cli/ui.d.ts +34 -0
  90. package/dist/cli/ui.js +224 -0
  91. package/dist/src/acp.d.ts +28 -0
  92. package/dist/src/acp.js +111 -0
  93. package/dist/src/agents.d.ts +23 -0
  94. package/dist/src/agents.js +71 -0
  95. package/dist/src/anthropic.d.ts +30 -0
  96. package/dist/src/anthropic.js +91 -0
  97. package/dist/src/approver.d.ts +15 -0
  98. package/dist/src/approver.js +40 -0
  99. package/dist/src/bench.d.ts +67 -0
  100. package/dist/src/bench.js +201 -0
  101. package/dist/src/bundle.d.ts +36 -0
  102. package/dist/src/bundle.js +55 -0
  103. package/dist/src/chaos.d.ts +15 -0
  104. package/dist/src/chaos.js +26 -0
  105. package/dist/src/code.d.ts +187 -0
  106. package/dist/src/code.js +590 -0
  107. package/dist/src/codeindex.d.ts +65 -0
  108. package/dist/src/codeindex.js +300 -0
  109. package/dist/src/deep.d.ts +62 -0
  110. package/dist/src/deep.js +177 -0
  111. package/dist/src/diff.d.ts +8 -0
  112. package/dist/src/diff.js +74 -0
  113. package/dist/src/dynamic.d.ts +42 -0
  114. package/dist/src/dynamic.js +133 -0
  115. package/dist/src/embed.d.ts +8 -0
  116. package/dist/src/embed.js +25 -0
  117. package/dist/src/evalcases.d.ts +11 -0
  118. package/dist/src/evalcases.js +196 -0
  119. package/dist/src/evals.d.ts +197 -0
  120. package/dist/src/evals.js +340 -0
  121. package/dist/src/gitflow.d.ts +27 -0
  122. package/dist/src/gitflow.js +56 -0
  123. package/dist/src/grade.d.ts +42 -0
  124. package/dist/src/grade.js +96 -0
  125. package/dist/src/guidance.d.ts +15 -0
  126. package/dist/src/guidance.js +68 -0
  127. package/dist/src/hardcases.d.ts +2 -0
  128. package/dist/src/hardcases.js +94 -0
  129. package/dist/src/harness.d.ts +411 -0
  130. package/dist/src/harness.js +725 -0
  131. package/dist/src/hooks.d.ts +44 -0
  132. package/dist/src/hooks.js +116 -0
  133. package/dist/src/images.d.ts +13 -0
  134. package/dist/src/images.js +27 -0
  135. package/dist/src/index.d.ts +57 -0
  136. package/dist/src/index.js +57 -0
  137. package/dist/src/ledger.d.ts +58 -0
  138. package/dist/src/ledger.js +78 -0
  139. package/dist/src/live.d.ts +16 -0
  140. package/dist/src/live.js +80 -0
  141. package/dist/src/lsp.d.ts +31 -0
  142. package/dist/src/lsp.js +147 -0
  143. package/dist/src/memory.d.ts +128 -0
  144. package/dist/src/memory.js +390 -0
  145. package/dist/src/metrics.d.ts +3 -0
  146. package/dist/src/metrics.js +42 -0
  147. package/dist/src/mining.d.ts +49 -0
  148. package/dist/src/mining.js +126 -0
  149. package/dist/src/openai.d.ts +50 -0
  150. package/dist/src/openai.js +307 -0
  151. package/dist/src/parallel.d.ts +66 -0
  152. package/dist/src/parallel.js +135 -0
  153. package/dist/src/patch.d.ts +45 -0
  154. package/dist/src/patch.js +219 -0
  155. package/dist/src/permissions.d.ts +46 -0
  156. package/dist/src/permissions.js +245 -0
  157. package/dist/src/plugins.d.ts +148 -0
  158. package/dist/src/plugins.js +225 -0
  159. package/dist/src/pluginscan.d.ts +8 -0
  160. package/dist/src/pluginscan.js +20 -0
  161. package/dist/src/procs.d.ts +41 -0
  162. package/dist/src/procs.js +94 -0
  163. package/dist/src/profiles.d.ts +36 -0
  164. package/dist/src/profiles.js +61 -0
  165. package/dist/src/progress.d.ts +29 -0
  166. package/dist/src/progress.js +75 -0
  167. package/dist/src/prompts.d.ts +10 -0
  168. package/dist/src/prompts.js +28 -0
  169. package/dist/src/ratelimit.d.ts +34 -0
  170. package/dist/src/ratelimit.js +116 -0
  171. package/dist/src/replay.d.ts +25 -0
  172. package/dist/src/replay.js +99 -0
  173. package/dist/src/review.d.ts +20 -0
  174. package/dist/src/review.js +49 -0
  175. package/dist/src/route.d.ts +9 -0
  176. package/dist/src/route.js +30 -0
  177. package/dist/src/router.d.ts +61 -0
  178. package/dist/src/router.js +126 -0
  179. package/dist/src/sandbox.d.ts +13 -0
  180. package/dist/src/sandbox.js +68 -0
  181. package/dist/src/schedule.d.ts +20 -0
  182. package/dist/src/schedule.js +59 -0
  183. package/dist/src/schema.d.ts +13 -0
  184. package/dist/src/schema.js +36 -0
  185. package/dist/src/secrets.d.ts +10 -0
  186. package/dist/src/secrets.js +41 -0
  187. package/dist/src/shell.d.ts +34 -0
  188. package/dist/src/shell.js +95 -0
  189. package/dist/src/skills.d.ts +20 -0
  190. package/dist/src/skills.js +112 -0
  191. package/dist/src/snapshot.d.ts +20 -0
  192. package/dist/src/snapshot.js +93 -0
  193. package/dist/src/stats.d.ts +24 -0
  194. package/dist/src/stats.js +62 -0
  195. package/dist/src/strategies.d.ts +16 -0
  196. package/dist/src/strategies.js +35 -0
  197. package/dist/src/suites.d.ts +30 -0
  198. package/dist/src/suites.js +112 -0
  199. package/dist/src/trace.d.ts +63 -0
  200. package/dist/src/trace.js +153 -0
  201. package/dist/src/tune.d.ts +38 -0
  202. package/dist/src/tune.js +49 -0
  203. package/dist/src/web.d.ts +19 -0
  204. package/dist/src/web.js +56 -0
  205. package/dist/src/worktree.d.ts +24 -0
  206. package/dist/src/worktree.js +85 -0
  207. package/docs/agent-loop.md +222 -0
  208. package/docs/architecture.md +228 -0
  209. package/docs/bench.md +292 -0
  210. package/docs/budgets.md +185 -0
  211. package/docs/build-your-own-harness.md +424 -0
  212. package/docs/cookbook.md +375 -0
  213. package/docs/development.md +150 -0
  214. package/docs/evaluation.md +450 -0
  215. package/docs/features.md +1320 -0
  216. package/docs/getting-started.md +205 -0
  217. package/docs/headless.md +188 -0
  218. package/docs/images/approval.png +0 -0
  219. package/docs/images/chat.png +0 -0
  220. package/docs/images/daylight.png +0 -0
  221. package/docs/images/loop.png +0 -0
  222. package/docs/images/palette.png +0 -0
  223. package/docs/images/running.png +0 -0
  224. package/docs/images/subagent-done.png +0 -0
  225. package/docs/images/subagent-running.png +0 -0
  226. package/docs/images/welcome.png +0 -0
  227. package/docs/index.md +25 -0
  228. package/docs/library.md +267 -0
  229. package/docs/plugins.md +691 -0
  230. package/docs/providers.md +175 -0
  231. package/docs/safety.md +250 -0
  232. package/docs/usage.md +348 -0
  233. package/docs/why.md +155 -0
  234. package/docs/writing-guide.md +39 -0
  235. package/package.json +66 -4
package/docs/bench.md ADDED
@@ -0,0 +1,292 @@
1
+ # Compare coding agents with `amness bench`
2
+
3
+ `amness bench` runs the same tasks through several coding-agent tools (Amness, Claude Code, Codex, or any command) and grades every result with the same hidden check.
4
+
5
+ In this page you will learn:
6
+
7
+ - what a bake-off can and cannot tell you
8
+ - how to set it up on Windows and run it
9
+ - how to read the result table
10
+ - how to add any other tool as a contestant
11
+
12
+ A *contestant* is one tool in the comparison. A *task* is one job with a start state and a check. A *trial* is one attempt at one task. A *hidden check* is a command or function that decides if the task is solved. The tool never sees it.
13
+
14
+ ## What a bake-off can and cannot tell you
15
+
16
+ **What it is.** A bake-off starts each tool on each task in a fresh folder. Then the same check grades the folder.
17
+
18
+ **Why you would use it.** You get a pass rate with a confidence range, tokens, cost and time for each tool, on tasks that you choose.
19
+
20
+ **What is the same for every contestant:**
21
+
22
+ - the tasks and the hidden check
23
+ - the prompt text (`promptTemplate`)
24
+ - the timeout
25
+ - a fresh temporary folder with a new git repository for each run
26
+
27
+ **What is not the same:**
28
+
29
+ - The model, unless you set one for each contestant. Each tool picks its own default model.
30
+ - The tool's own system prompt, tools and permission settings.
31
+ - How tokens and cost are reported. See "Read the table" below.
32
+
33
+ So the result tells you how the tools behave as a whole, with the settings that you used. It does not tell you which tool is "smarter". Different models can cause a difference, not only the tool. The report prints a list of the settings that were used. Publish that list with your numbers.
34
+
35
+ ## Set up on Windows
36
+
37
+ Do these steps in PowerShell.
38
+
39
+ 1. Install Node.js 22.18 or newer from nodejs.org. Check it:
40
+
41
+ ```powershell
42
+ node --version
43
+ ```
44
+
45
+ 2. Install [Git for Windows](https://git-scm.com/download/win). The bench needs `git` on your PATH. The hidden checks of the built-in tasks use bash tools such as `test`. Amness looks for the `bash.exe` that comes with Git (in `Program Files\Git\bin`) and for any `bash.exe` on PATH. It skips `C:\Windows\System32\bash.exe`, because that is the WSL launcher and it sees other files (see `src/shell.ts`).
46
+
47
+ 3. Install Amness from npm:
48
+
49
+ ```powershell
50
+ npm install -g amness
51
+ amness --version
52
+ ```
53
+
54
+ To bench the latest `main` instead of the release, install from a clone: `git clone https://github.com/amirsdream/Amness.git`, then `cd Amness`, `npm install` and `npm link`.
55
+
56
+ 4. Install and log in to the other tools yourself. Follow their own documentation. This page does not repeat install commands, because they change.
57
+ - Claude Code: <https://docs.claude.com/en/docs/claude-code>
58
+ - Codex: <https://github.com/openai/codex>
59
+
60
+ 5. Open a new terminal, so that the new PATH is read. Make sure `claude` and `codex` run from any folder. Then check:
61
+
62
+ ```powershell
63
+ amness bench --check
64
+ ```
65
+
66
+ You see one line per contestant, `found` or `missing`. The exit code is 1 if one is missing. The check calls no model.
67
+
68
+ 6. Set the API keys that you need in the same terminal. For Amness, see [Getting started](getting-started.md). For `claude-bare` you need `ANTHROPIC_API_KEY`.
69
+
70
+ ```powershell
71
+ $env:ANTHROPIC_API_KEY = "sk-ant-..."
72
+ ```
73
+
74
+ **What was tested on Windows.**
75
+
76
+ - Tested: the bench code and the stdin path (`amness run -`) run in the automated tests on a Windows machine in CI. That CI job is marked informational. It is allowed to fail.
77
+ - Not tested: the `claude` and `codex` presets have not been run on any machine by the author. Their flags come from the vendors' documentation and may differ in your version.
78
+
79
+ **If a flag differs on your version,** run `claude --help` or `codex exec --help`. Then edit `args` for that contestant in `bench.json`. No code change is needed.
80
+
81
+ On Windows, Amness starts each tool through the shell, so `.cmd` shims work. It quotes the arguments for you. The presets send the prompt on standard input, so the prompt text never needs quoting.
82
+
83
+ ## Run your first bake-off
84
+
85
+ 1. Write a starter config. It has four contestants: `amness`, `amness-gate`, `claude` and `codex`.
86
+
87
+ ```bash
88
+ amness bench --init
89
+ ```
90
+
91
+ The command writes `bench.json`. It will not overwrite a file that exists.
92
+
93
+ 2. Edit `bench.json`:
94
+
95
+ | Setting | Meaning |
96
+ |---|---|
97
+ | `contestants` | The list of tools. Delete the ones that you do not have. |
98
+ | `model` (per contestant) | The model for that tool. Set it for all, in the same family if you can. |
99
+ | `trials` | Attempts per task and contestant (starter file: 3). |
100
+ | `jobs` | Runs at the same time (starter file: 2). Use 1 if you see rate-limit errors. |
101
+ | `timeoutSec` | Seconds before a run is killed (starter file: 900). |
102
+ | `promptTemplate` | The prompt for every tool. `{task}` is the task text. `{verify}` is the check command that the task offers. |
103
+ | `gitInit` | Make a git repository in each folder (default true). |
104
+ | `logDir` | Where the raw output of every run is kept (default `.amness/bench/logs`). |
105
+
106
+ 3. Look at the plan. This runs nothing and costs nothing:
107
+
108
+ ```bash
109
+ amness bench --config bench.json --dry-run
110
+ ```
111
+
112
+ You see the number of runs, the prompt for the first task, and the exact command line of every contestant. Models you did not set show as "the tool's default". A line `! codex: "codex" is not on PATH` warns you about a missing tool.
113
+
114
+ 4. Run the probe. It gives one tiny real task to each contestant. It confirms that the tool starts, that the grading works, and that tokens and cost are read. It costs a few cents.
115
+
116
+ ```bash
117
+ amness bench --config bench.json --probe
118
+ ```
119
+
120
+ Read the `PASS` or `FAIL` lines and the notes. Fix problems here, before the big run.
121
+
122
+ 5. Set a spending limit on every account. Then run:
123
+
124
+ ```bash
125
+ amness bench --config bench.json --builtin code
126
+ ```
127
+
128
+ Amness asks you to confirm the cost. Add `--yes` to skip the question. Amness prints one `PASS` or `FAIL` line for each run while it works. At the end it prints the table and saves the raw results in `.amness/bench/<time>.json`. Use `--out <file>` to choose another file.
129
+
130
+ ### Read the table
131
+
132
+ Without `--config`, `amness bench --contestants amness,claude --model <name>` uses presets. `--models amness=<a>,claude=<b>` sets one model for each preset.
133
+
134
+ The first table looks like this. The numbers are an example. They are not a measurement.
135
+
136
+ ```text
137
+ 13 tasks × 3 trials; intervals are 95% bootstrap over tasks; baseline = amness
138
+
139
+ variant pass [95% CI] pass^3 tok/solved cache steps secs pareto
140
+ amness 77% [59-92] 62% 41k 58% 9.0 74.2 ●
141
+ claude 82% [64-95] 69% 55k 71% 7.5 61.0
142
+ codex 69% [49-87] 51% n/a n/a 0.0 88.5
143
+
144
+ vs amness (paired by task)
145
+ variant Δ pass [95% CI] W/L/T p (Holm) Δ tok/solved verdict
146
+ claude +5 [-10, +21] 3/2/8 0.600 +14k inconclusive
147
+
148
+ custom metrics (mean per run; Δ against amness with 95% interval over tasks)
149
+ variant cost-usd secs
150
+ amness n/a 74.20
151
+ claude 0.31 Δ n/a 61.00 Δ -13.20 [-30.10, +3.00]
152
+ ```
153
+
154
+ | Column | Meaning |
155
+ |---|---|
156
+ | `pass [95% CI]` | Share of runs that passed, and the range where the true rate probably lies. |
157
+ | `pass^3` | Chance that 3 attempts at a task all pass. It is low for a tool that only wins sometimes. |
158
+ | `tok/solved` | Tokens used for each solved task. A *token* is a small piece of text that a model reads. It shows `n/a` when the tool does not report tokens. |
159
+ | `cache` | Share of input tokens that came from the cache. |
160
+ | `steps` | Mean turns per run. It is 0 when the tool does not report turns. |
161
+ | `secs` | Mean wall-clock seconds per run. |
162
+ | `pareto` | A dot marks a tool that no other tool beats on both pass rate and cost. |
163
+ | `Δ pass` | Difference in pass rate against the baseline, paired by task. The baseline is the first contestant. |
164
+ | `W/L/T` | Tasks where this tool won, lost or tied against the baseline. |
165
+ | `p (Holm)` | The p-value, adjusted because you compare several tools at once. |
166
+ | `verdict` | `better`, `worse` or `inconclusive`. |
167
+
168
+ The `cost-usd` and `secs` metrics are in the custom metrics table. `cost-usd` is the money that the tool reports for a run. `secs` is the run time in seconds, measured by Amness. Only tools that report a cost have `cost-usd`.
169
+
170
+ **What "inconclusive" means.** The data cannot tell the tools apart. It does not mean that the tools are equal. In the example, the interval for the difference goes from -10 to +21 points. That includes zero.
171
+
172
+ **Why 13 tasks and 3 trials is a minimum.** The report prints a line like "only pass-rate differences above ~55 points can be detected reliably". It comes from `minDetectable` in `src/stats.ts`. It is a rough rule: 80% power, 5% error, worst-case variance. With 13 tasks, it is about 55 points. With 50 tasks, it is about 28. More trials reduce the noise from model sampling. They do not add tasks. Only more tasks make small differences visible. With fewer than 3 trials, the report warns you.
173
+
174
+ If a run cannot be set up, it goes to the "exclusion ledger" and is not counted. After the run, read the logs in `logDir` for any surprise.
175
+
176
+ To read the saved results again:
177
+
178
+ ```bash
179
+ amness eval --report .amness/bench/<run>.json
180
+ ```
181
+
182
+ ## Choose the tasks
183
+
184
+ | Suite | Command | What is in it |
185
+ |---|---|---|
186
+ | `code` (default) | `amness bench --builtin code` | 13 easy tasks |
187
+ | `hard` | `amness bench --builtin hard` | 6 harder tasks |
188
+ | `adversarial` | `amness bench --builtin adversarial` | Tasks that try to trick the tool |
189
+ | Your own | `amness bench --cases ./my-tasks` | A folder of `.json` task files |
190
+ | Your own, with functions | `amness bench --cases my-tasks.ts` | A `.ts` or `.js` module that exports a list of cases |
191
+ | SWE-bench format | see below | A `.jsonl` file |
192
+
193
+ The built-in suites are small and made by us. They are not a public benchmark. Use `--only a,b` to run only some tasks.
194
+
195
+ For your own tasks, use the same file format as `amness eval`. See [Evaluating the harness](evaluation.md) for the fields `files`, `task`, `verify` and `check`, and for a function check. Test them first with `amness eval --cases ./my-tasks --selftest`.
196
+
197
+ For a SWE-bench-format file:
198
+
199
+ ```bash
200
+ amness bench --suite instances.jsonl --test-cmd "python -m pytest -x -q {tests}" --install "pip install -e ." --limit 20
201
+ ```
202
+
203
+ `--test-cmd` is required with `--suite`. Python and the repositories' needs must be installed on your machine. Not verified on Windows.
204
+
205
+ ## Use a subscription or an API key
206
+
207
+ | Preset | Login | What it loads | Note |
208
+ |---|---|---|---|
209
+ | `claude` | Your Claude login | Your own settings, `CLAUDE.md` and hooks | Your configuration mixes into the result. |
210
+ | `claude-bare` | `ANTHROPIC_API_KEY` only | Nothing from your user setup | A clean room. The `--bare` flag never reads OAuth or the keychain, so a subscription login does not work. |
211
+ | `codex` | Your Codex login | Ignores your user config and rules | Runs in a `workspace-write` sandbox. |
212
+ | `amness`, `amness-gate` | Your Amness provider key | Your Amness settings | `amness-gate` also uses `--verify`, so it cannot finish before the check passes. The others only see the check in the prompt. |
213
+
214
+ Cost and tokens:
215
+
216
+ - Claude's JSON output includes `total_cost_usd`, so you see `cost-usd` and tokens.
217
+ - Codex shows tokens only. The token event format is not documented, so the parser reads what is commonly there. The `--probe` run tells you if it worked. Not verified on a real Codex.
218
+ - Amness shows total tokens only (no split of input and output, no cost).
219
+ - To get cost for tools without it, multiply the tokens by the price yourself. The bench does not add prices.
220
+
221
+ ## Add any other tool as a contestant
222
+
223
+ Add an object to `contestants` in `bench.json`:
224
+
225
+ ```json
226
+ {
227
+ "name": "my-tool",
228
+ "command": "my-agent",
229
+ "args": ["--headless", "--model", "{model}"],
230
+ "stdin": true,
231
+ "model": "my-model-1",
232
+ "parse": "none",
233
+ "env": { "MY_AGENT_KEY": "..." },
234
+ "timeoutSec": 600,
235
+ "note": "my agent, default settings"
236
+ }
237
+ ```
238
+
239
+ | Field | Meaning |
240
+ |---|---|
241
+ | `name` | A unique name. It is the row name in the report. |
242
+ | `command` | The program. It is found through PATH. |
243
+ | `args` | Arguments. These placeholders are replaced: `{task}` (task text), `{cwd}` (the run folder), `{model}`, `{verify}` (the task's check command). |
244
+ | `stdin` | `true` sends the prompt on standard input. This is the best choice, because there is no quoting problem. `false` sends no input. Then put `{task}` in `args`. |
245
+ | `model` | The value for `{model}`. Shown in the report. |
246
+ | `parse` | How to read tokens and cost: `claude-json`, `codex-jsonl`, `amness-json` or `none`. With `none`, the report has no tokens or cost for this tool. |
247
+ | `env` | Extra environment variables for this tool only. |
248
+ | `timeoutSec` | A timeout for this tool. The default is the bench timeout. |
249
+ | `note` | A text shown in the report. Say what is special, for example "uses my login". |
250
+
251
+ Names must be different. Every contestant needs a `name` and a `command`. Check the new entry with `--dry-run` and `--probe`.
252
+
253
+ ## Fair-play checklist
254
+
255
+ - Use the same model family for every tool where you can, and set `model` for each.
256
+ - Use the same permission level. The presets allow file edits and shell commands without asking.
257
+ - The run order is task by task, then contestant, then trial. A slow period of the API can still affect one tool more than another. Repeat the bake-off on another day.
258
+ - Do not run it while the machine is busy. Time is measured in wall-clock seconds.
259
+ - `jobs` above 1 runs tools at the same time. Your API rate limits may then cause failures that are not the tool's fault. Use `jobs` 1 for timing.
260
+ - Set a spending limit on every account before you start.
261
+ - Run it in a VM or container. The tools are not sandboxed from your machine, and they can run commands. This matters most for tasks that you did not write.
262
+ - Publish `bench.json` and the raw results file together with your numbers.
263
+ - Do not use `claude` for a fair test unless you accept that your own `CLAUDE.md` and hooks are part of it. Use `claude-bare` or say so in the `note`.
264
+
265
+ ## Limits and common problems
266
+
267
+ | Problem | What to do |
268
+ |---|---|
269
+ | `missing ... (not on PATH)` | Open a new terminal. Run `where claude` or `where codex` (Windows) or `which claude`. Add the folder to PATH. |
270
+ | `could not start <command>: ...` in the note | The program could not run. Run `--check`, and run the command by hand in a terminal. |
271
+ | `timed out after Ns` | Raise `timeoutSec` or `--timeout`. A timed-out run counts as a fail. |
272
+ | `n/a` in `tok/solved` or `cost-usd` | The tool did not report it, or `parse` is wrong. Run `--probe` and open the `.out.txt` file in `logDir`. |
273
+ | Every run of one tool fails with the same note | The flags or the login are wrong. Read the `.err.txt` and `.cmd.json` files in `logDir/<name>/`. Fix `args`. |
274
+ | A tool says an option is unknown | Your version differs. Check `--help` of the tool and edit `args`. |
275
+ | Quoting problems on Windows | Keep `stdin: true`. Avoid `{task}` in `args`. |
276
+ | The check fails on `test` or `bash` not found (Windows) | Install Git for Windows. Make sure its `bin` folder is not blocked, or put a `bash.exe` on PATH. |
277
+ | `none of the contestants can start` | No tool was found. Run `--check`. |
278
+ | `the tool reported an error but the check passed` | Only a note. The run counts as a pass, because the check decides. |
279
+
280
+ Other limits: the bench does not stop a tool from reading your files. Tokens and cost depend on what each tool reports. The `claude` and `codex` presets are not verified on a real machine.
281
+
282
+ ## Related pages
283
+
284
+ - [Evaluating the harness](evaluation.md)
285
+ - [Headless and CI](headless.md)
286
+ - [Getting started](getting-started.md)
287
+
288
+ ## Next steps
289
+
290
+ - Read [Evaluating the harness](evaluation.md) to write your own tasks and understand the statistics.
291
+ - Read [Plugins](plugins.md) to change Amness before you compare it.
292
+ - Read the [Cookbook](cookbook.md) for a short recipe.
@@ -0,0 +1,185 @@
1
+ # Budgets, exploration and subagents
2
+
3
+ This page explains why runs used to end with "token budget exhausted" and no answer, what the vendors and papers advise, and what Amness does now.
4
+
5
+ In this page you will learn:
6
+
7
+ - how to choose a token budget and what you see when a run hits it
8
+ - what the budget notes, the final report and the subagent slices do
9
+ - how Amness stays under the provider's rate limits
10
+ - which sources were read and which were only search snippets
11
+
12
+ A *token* is a small piece of text that a model reads or writes. One token is about four letters. A *budget* is the most tokens a run may use.
13
+
14
+ ## Choose a budget
15
+
16
+ **What it is.** The budget is a cap on the tokens for one turn of the chat, or for one headless run. The default is 300,000 tokens (`maxTokens` in `cli/config.ts`).
17
+
18
+ **Why you would change it.** A small budget stops a run early. A large budget lets a lost agent spend more before it stops.
19
+
20
+ **How the cap counts.** The cap counts cached input at one tenth of its size, because cached input costs about that much and a long session reads its whole history again on every turn (`Budget.effective` in `src/harness.ts`). The token count shown on screen is not changed. Where a server reports no token usage, Amness estimates about 4 characters per token and marks the figure `estimated`.
21
+
22
+ **How to set it.**
23
+
24
+ 1. In the chat, type `/budget` to see the cap and what the last turn used.
25
+ 2. Type `/budget 500k` to change it. You can write `500k`, `1m` or `400000`. The minimum is 10,000.
26
+ 3. In headless mode, add `--max-tokens 500000` to `amness run`.
27
+ 4. To keep the value, set `"maxTokens"` in `~/.amness/config.json`.
28
+
29
+ **Advice.** These values are starting points from how the code behaves. They are not measured on real tasks.
30
+
31
+ | Task | Starting budget | Why |
32
+ |---|---|---|
33
+ | A question about one file or one function | 100,000 to 150,000 | The prompt rules ask for 3 to 10 tool calls for this kind of question. |
34
+ | A bug fix with tests | 300,000 (the default) | One logged run of a broad question on a 300,000 cap used 132,000 (see below). Fixes with test runs cost more per step. |
35
+ | A survey of a large code base, or a refactor over many files | 500,000 to 1,000,000 | Subagents use part of the budget. Their cost counts against yours. |
36
+ | An unattended run in CI | The value you can afford, not more | The agent stops at the cap, so the cap is your worst-case cost. |
37
+
38
+ Rules of thumb:
39
+
40
+ - Start with the default. Look at the budget line in the sidebar or in `/budget` after the first turn. Then raise or lower the cap.
41
+ - Do not set the cap very low. At 50% the model is told to stop broad reading, so a small cap makes the agent give up exploration early.
42
+ - If a big task keeps hitting the cap, split it. Ask for the plan in one turn and for each part in a later turn. Each chat turn gets a fresh budget.
43
+ - Use `/loop` or `/tokens` to see where the tokens went before you raise the cap.
44
+
45
+ **Time limits.** The chat also has a time cap of 60 minutes per turn. `amness run` has no time cap. The classic menu mode uses 30 minutes.
46
+
47
+ ### Example: what you see when the budget stops a run
48
+
49
+ When the cap is reached, or when one more step plus a summary would not fit, the loop makes one last call without tools. It asks the model what it found, the state of the work and what remains. You get that text instead of a bare error.
50
+
51
+ In the chat, a warning line appears with the first line of the result. The result text looks like this (the numbers and the report are an example built from the format in `src/harness.ts`, not a captured run):
52
+
53
+ ```
54
+ stopped: token budget exhausted (301204/300000)
55
+
56
+ I read the router and the rate-limit gate. The retry logic is in
57
+ src/ratelimit.ts. I did not read the OpenAI adapter yet.
58
+ Left to do: check how src/openai.ts handles a 429.
59
+ ```
60
+
61
+ If the loop sees that the next step would not fit, the first line is `stopped: budget nearly exhausted` instead.
62
+
63
+ In headless mode with `--json`, the last line is a result object with `"finished": false` and `"stopped": "budget"`. The exit code is 1. Here `tokens` is the raw count, before the cached-input discount.
64
+
65
+ **What to do next.** Raise the cap with `/budget`, or send a message such as "continue with the OpenAI adapter". The conversation keeps its history, so the agent continues from the report.
66
+
67
+ **Limits and common problems.**
68
+
69
+ - The final report is one more model call. If that call fails, the result has only the `stopped:` line.
70
+ - The run counts as not finished (`finished: false`), even if the report is a good answer.
71
+ - Time budgets give a similar message: `stopped: time budget exhausted (...)`.
72
+
73
+ **Related pages.** [The agent loop](agent-loop.md), [Using the chat](usage.md), [Headless and CI](headless.md).
74
+
75
+ ## Understand why runs ran out of budget
76
+
77
+ A question like "explore the codebase" had no natural end. The model kept reading. It started several deep explorers at once, and one used a wrong agent name, which failed and was retried. Every request sent the whole history again. The 300,000 cap then cut the run off with no answer.
78
+
79
+ ## Read what the sources say
80
+
81
+ Sources marked *read* were fetched and read. *Snippet* means only a search summary was seen.
82
+
83
+ | Source | Finding | Used here |
84
+ |---|---|---|
85
+ | [Claude task budgets](https://platform.claude.com/docs/en/build-with-claude/task-budgets) (*read*) | An advisory token budget for the whole agentic loop. The model sees a running countdown and "finishes gracefully". It counts what the model *sees* (new content), not the history that is sent again. Set it once: changing it on each request breaks the prompt cache. A budget that is too small for the task can make the model refuse or stop early. Minimum 20,000. Beta. Not Claude Code. | Opt-in `taskBudget` for Claude (below). |
86
+ | [BATS, arXiv 2511.17006](https://arxiv.org/abs/2511.17006) (*read*) | A per-turn budget tracker, with behaviour tiers (high, medium, low, critical remaining), improved the accuracy of search agents and cut cost. A tracker at budget 10 matched plain ReAct at budget 100 with about 31% lower cost. The tasks were web search, not coding. | Budget notes at 50%, 75% and 90%. |
87
+ | [Anthropic, multi-agent research system](https://www.anthropic.com/engineering/multi-agent-research-system) (*read*) | Models misjudge effort, so put scaling rules in the prompt (simple fact: 1 agent, 3-10 tool calls; comparison: 2-4 agents, 10-15 calls each). Vague subagent briefs cause duplicated work: give an objective, an output format, tool guidance and boundaries. Token use explains about 80% of performance variance. Multi-agent runs use about 15 times the tokens of chat. They suit parallel, high-value work, and "domains like most coding" less. | Effort rules in the system prompts. Brief requirements in the `task` tool. Subagents are limited. |
88
+ | [Anthropic, context engineering](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents) (*read*) | Fetch what you need when you need it (paths, grep) instead of loading everything. Clear old tool results. Subagents may use tens of thousands of tokens but should return a short result of 1,000 to 2,000 tokens. Accuracy falls as the context grows ("context rot"). | Subagent reports are clipped to 8,000 characters. Old tool results are elided. |
89
+ | [OpenAI Codex subagents](https://learn.chatgpt.com/docs/agent-configuration/subagents) (*read*) | Subagents are for read-heavy parallel work. They cost more tokens than one agent. They return summaries, not raw output. There is a cap on concurrent threads. Be careful with parallel writers. | At most 3 `task` calls run at once. |
90
+ | [OpenAI compaction guide](https://developers.openai.com/api/docs/guides/compaction) (*snippet*) | Server-side compaction through `context_management` with a `compact_threshold`. | Optional `compactAt` (see "Not done, and why"). |
91
+ | Blogs on "exploration burn", for example [First-Touch Tool Burn](https://tianpan.co/blog/2026/04/23/first-touch-tool-burn-agent-exploration-budget) (*snippet*) | A claim that reading uses most of an agent's spend (figures from 47% to 87%), and a proposal to cap reads before the agent must state a plan. The numbers are not verified. | The check for 12 read-only turns is the same idea. |
92
+
93
+ ## Know what Amness does now
94
+
95
+ 1. **Prompt rules, not only limits** (Anthropic). The system prompts say how many tool calls a question deserves and when a subagent is worth its cost.
96
+ 2. **The model sees its budget** (BATS). At 50%, 75% and 90% of the cap, a note is added at the end of the conversation. The cache stays valid, because nothing earlier changes. The 50% note says to stop broad exploration. The 75% note says to produce the result. The 90% note says the next reply must be the result.
97
+ 3. **Never end empty-handed.** At 95% of the cap, when the cap is reached, or when another step plus a summary would not fit, one last call without tools asks what was found, the state of the work and what remains.
98
+ 4. **Exploration check.** After 12 turns in a row that only read, the model is told to answer (if the task is a question) or start (if it is a change), or to name exactly what is still missing. It repeats after another 12.
99
+ 5. **Subagents are bounded** (next section).
100
+ 6. **The cap measures cost.** Cached input counts at a tenth.
101
+ 7. **Claude's own countdown (opt-in).** `"taskBudget": 150000` in the config (at least 20,000) sends `output_config.task_budget` with the `task-budgets-2026-03-13` beta header. It works for the Claude models that the adapter lists as supported: Fable, Mythos, Opus 4.7, 4.8 and 5, Sonnet 5.5 and Haiku 5.5. It does not work for Sonnet 5, Opus 4.6, Sonnet 4.6 or Haiku 4.5 (`src/anthropic.ts`). It is set once and never changed per request. It is advice for the model only: Amness's own cap still applies. Choose the size from your real usage. A budget that is too small makes Claude narrow the task or stop early.
102
+
103
+ All of this is tested with scripted models and fake SDK clients (for example `test/features.test.ts`). None of it is measured on a real model for fewer exhausted runs. The eval runner can measure this once there are exploration-style tasks in the suite.
104
+
105
+ ### Subagent slices
106
+
107
+ **What it is.** A subagent gets a slice of the budget, not the whole budget. `Budget.slice(share, max)` in `src/harness.ts` gives a subagent at most `share` of what is left, and no more than `max` tokens. Everything the subagent spends also counts against the main budget.
108
+
109
+ | Subagent | Share of what is left | Token limit | Other limits |
110
+ |---|---|---|---|
111
+ | Read-only explorer (built in) | 12% | 60,000 | 14 steps. The prompt says it has about 12 tool calls and should answer in under 300 words. |
112
+ | Custom agent (from `.amness/agents/`) | 25% | 120,000 | Its own `maxSteps`. |
113
+
114
+ Other limits (`src/code.ts`):
115
+
116
+ - A request may start at most 6 subagents (`MAX_SUBAGENTS_PER_REQUEST`). More return an error that tells the lead to work with what it has.
117
+ - At most 3 `task` calls run at the same time.
118
+ - Reports are clipped to 8,000 characters.
119
+ - Every report ends with a line such as `[subagent used about 3k tokens; the budget for this request is 40% used]`, so the lead can decide to stop delegating.
120
+ - A `task` call with an agent name that does not exist uses the read-only explorer and says so, instead of failing.
121
+
122
+ Inside its slice, a subagent gets the same budget notes and final report. An explorer that runs out returns what it found, not an error. Tested in `test/agents.test.ts` and `test/features.test.ts`.
123
+
124
+ **Limits.** An older version of this page said 20% and 80,000 tokens for the explorer, and 30% and 150,000 for custom agents. Those numbers were out of date. The values in the table match the code.
125
+
126
+ ## What went wrong in the second report, and the fix
127
+
128
+ A "survey the whole codebase" run stopped at "budget nearly exhausted" while the display said 46% used. There were three bugs.
129
+
130
+ 1. The step-cost estimate behind the early final report was the change in the shared budget. That also contains what the subagents spent in the meantime, so a step that ran three explorers looked very expensive. It now uses the cost of the lead's own last request.
131
+ 2. Subagent budget notes were drawn as red errors, and every nudge was labelled "nudged the model to act instead of describing". Now nudges say what happened, subagent notes are not shown, and the final report is shown as a normal answer.
132
+ 3. Nothing limited how many subagents a request could start. Now a request may start at most 6 subagents, explorers get a smaller slice, and every subagent report ends with what it cost.
133
+
134
+ After the fix, the same kind of request on `gpt-6-luna` (300,000 cap) finished in 83 seconds with a full answer. It used 132,000 of the 300,000 (cached input counted at a tenth; 234,000 raw). Two subagents wrapped up inside their slices. This was one run. It is not a measurement.
135
+
136
+ ## Rate limits (requests and tokens per minute)
137
+
138
+ Several agents that share one API key (the lead, up to three explorers, the reviewer) can go over the per-minute limits. Failed requests count toward the limits too. A *429 error* is the answer a provider sends when you are over a limit.
139
+
140
+ What the vendors say ([OpenAI rate limits](https://developers.openai.com/api/docs/guides/rate-limits), [Claude rate limits](https://platform.claude.com/docs/en/api/rate-limits), both *read*):
141
+
142
+ - Wait at least the time in the `Retry-After` header, plus a small random delay (jitter). When the header is missing, use exponential backoff with jitter. Cap the number of attempts and the total wait. Do not retry quota or spend-cap errors, because they also arrive as 429. If you retry yourself, do not also let an SDK retry.
143
+ - Limits are enforced over short windows. A limit of 60 requests per minute can mean one request per second. A sharp rise in traffic can trigger "acceleration" 429 errors, so ramp up step by step.
144
+ - Claude counts only uncached input toward its input-tokens-per-minute limit, and `max_tokens` does not count toward its output limit. OpenAI counts the larger of `max_tokens` and the estimated request size, so keep `max_tokens` near the output you expect.
145
+
146
+ What Amness does (`src/ratelimit.ts`, for every provider, shared by all agents in the process):
147
+
148
+ 1. One gate for each endpoint and key limits the requests in flight. The ceiling is 4 by default (`maxConcurrent` in the config). The gate starts at 2 and adds one after three successes, so traffic ramps up step by step.
149
+ 2. On a 429 that waiting can fix, every caller pauses for the server's `Retry-After` time (or an exponential backoff of up to 60 seconds, with jitter). The gate halves its concurrency, like TCP congestion control. The chat tells you: `rate limited by the provider: waiting 12s, then retrying (attempt 1); 2 requests at a time for now`.
150
+ 3. These cases are not retried, and the error reaches you: quota, billing and spend-cap errors; an abort; a requested wait longer than two minutes; and more than six retries.
151
+ 4. The OpenAI adapter does not retry 429 by itself when the gate is on (`externalRetry`). It still retries timeouts and 5xx errors, and it honours `Retry-After`.
152
+
153
+ **How to use it.** If you see rate-limit messages often, lower the ceiling in `~/.amness/config.json`:
154
+
155
+ ```json
156
+ { "maxConcurrent": 2 }
157
+ ```
158
+
159
+ **Limits and common problems.** Tested with fake models and clocks, and end to end against a local HTTP server that returns 429 with `Retry-After` (`test/ratelimit.test.ts`). The limit of 3 subagents at once is tested too (`test/agents.test.ts`). Not yet seen with a real provider 429. Evals ran slower than expected when many sessions ran at once. That is the situation this gate exists for.
160
+
161
+ ## See subagents in the UI
162
+
163
+ A subagent's steps used to be drawn as loose lines in the transcript, mixed together when explorers ran in parallel. Now every event carries the id of the `task` call that started it (`parent`).
164
+
165
+ - **Full-screen view.** The steps live inside their card. While the subagent runs, the card shows the newest three steps. When it is done, the card shows a one-line summary such as "12 steps · 7 files read · 4 searches". Open the card to see all steps.
166
+ - **Inline view.** One live line for each subagent shows its newest step and step count.
167
+ - An interrupted or failed turn closes every card that was still running.
168
+
169
+ ## Know that this works with any model
170
+
171
+ Everything except item 7 lives in the harness and works the same for OpenAI, Claude and local models. The notes and the final report are ordinary messages. The subagent limits are Amness's own. The prompt rules are plain text. Where a server reports no token usage, the harness estimates it, so the cap, the notes and the final report still work. Only the opt-in `taskBudget` is specific to Claude. Other providers and unsupported Claude models ignore it.
172
+
173
+ ## Not done, and why
174
+
175
+ - **OpenAI server-side compaction** is an option: set `"compactAt": 150000` in the config. It works on the Responses API on official hosts only. The request carries `context_management` with that threshold, and input before the newest compaction item is no longer sent again. Tested at the wire level only. Not measured: it is unknown whether it beats Amness's own staged trimming. It is off by default.
176
+ - **A hard cap on reads in the tool layer** (stop the read tool after N reads until the agent states a plan): proposed in blogs, not verified, and risky for legitimate large reads. The nudge comes first. Measure before making it a hard stop.
177
+ - **Exploration that returns only file paths and line ranges** (a paper named FastContext is cited in a blog, *snippet*, not verified): not implemented.
178
+
179
+ ## Next steps
180
+
181
+ - [The agent loop](agent-loop.md): see where the budget check sits in each turn.
182
+ - [Using the chat](usage.md): the `/budget`, `/loop` and `/tokens` commands.
183
+ - [Headless and CI](headless.md): `--max-tokens` and exit codes.
184
+ - [Providers and models](providers.md): OpenAI, Claude and local models.
185
+ - [Evaluating the harness](evaluation.md): measure what a guard is worth.