@jr2/orchestrator 0.4.1 → 0.6.0

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 (361) hide show
  1. package/README.md +20 -2
  2. package/console/components/app.ts +2 -0
  3. package/console/components/fleet.ts +14 -1
  4. package/console/components/machine-pane.ts +41 -2
  5. package/console/main.ts +13 -1
  6. package/console/store.ts +102 -6
  7. package/console/style.css +21 -0
  8. package/docs/agents-block.md +5 -0
  9. package/docs/concepts/agents-and-turns.md +478 -0
  10. package/docs/concepts/architecture.md +243 -0
  11. package/docs/concepts/charts.md +146 -0
  12. package/docs/concepts/composition.md +357 -0
  13. package/docs/concepts/converge.md +257 -0
  14. package/docs/concepts/durable-runs.md +189 -0
  15. package/docs/concepts/effects.md +658 -0
  16. package/docs/concepts/gates.md +208 -0
  17. package/docs/concepts/machines-and-workflows.md +298 -0
  18. package/docs/concepts/pools-and-sources.md +230 -0
  19. package/docs/concepts/secrets-and-trust.md +306 -0
  20. package/docs/concepts/the-menu.md +381 -0
  21. package/docs/concepts/workspaces.md +756 -0
  22. package/docs/get-started/a-model-decides.md +563 -0
  23. package/docs/get-started/an-agent-in-a-sandbox.md +383 -0
  24. package/docs/get-started/connect-a-model.md +248 -0
  25. package/docs/get-started/create-an-instance.md +194 -0
  26. package/docs/get-started/have-your-assistant-write-a-machine.md +993 -0
  27. package/docs/get-started/install.md +130 -0
  28. package/docs/guides/add-tools-to-the-sandbox.md +308 -0
  29. package/docs/guides/answer-a-gate.md +304 -0
  30. package/docs/guides/bind-open-parts.md +224 -0
  31. package/docs/guides/cancel-a-run.md +146 -0
  32. package/docs/guides/clean-up.md +206 -0
  33. package/docs/guides/cut-a-worktree.md +560 -0
  34. package/docs/guides/fix-a-failed-converge.md +361 -0
  35. package/docs/guides/give-the-cluster-git-credentials.md +222 -0
  36. package/docs/guides/iterate-on-a-machine-on-kind.md +190 -0
  37. package/docs/guides/let-an-agent-write-a-chart.md +230 -0
  38. package/docs/guides/look-inside-a-sandbox.md +177 -0
  39. package/docs/guides/mirror-the-kit-images.md +176 -0
  40. package/docs/guides/move-from-kind-to-a-shared-cluster.md +318 -0
  41. package/docs/guides/open-the-console.md +91 -0
  42. package/docs/guides/publish-a-machine-as-an-npm-package.md +350 -0
  43. package/docs/guides/push-and-sign-a-branch.md +532 -0
  44. package/docs/guides/run-a-chart-by-name.md +270 -0
  45. package/docs/guides/run-a-command-or-call-a-url.md +587 -0
  46. package/docs/guides/run-one-worker-per-item.md +322 -0
  47. package/docs/guides/set-an-agents-access-and-dials.md +420 -0
  48. package/docs/guides/size-a-workspace.md +217 -0
  49. package/docs/guides/start-a-run-from-a-run.md +237 -0
  50. package/docs/guides/start-a-run.md +207 -0
  51. package/docs/guides/upgrade-the-kit-version.md +240 -0
  52. package/docs/guides/use-a-hosted-provider.md +214 -0
  53. package/docs/guides/use-a-local-model.md +313 -0
  54. package/docs/guides/watch-a-run.md +349 -0
  55. package/docs/guides/write-a-workflow.md +318 -0
  56. package/docs/index.md +44 -0
  57. package/docs/llms.txt +237 -0
  58. package/docs/reference/authoring-surface/agent.md +151 -0
  59. package/docs/reference/authoring-surface/answer.md +156 -0
  60. package/docs/reference/authoring-surface/arg.md +82 -0
  61. package/docs/reference/authoring-surface/basic.md +62 -0
  62. package/docs/reference/authoring-surface/bearer.md +53 -0
  63. package/docs/reference/authoring-surface/branchname.md +15 -0
  64. package/docs/reference/authoring-surface/chartschema.md +23 -0
  65. package/docs/reference/authoring-surface/chartschemafor.md +48 -0
  66. package/docs/reference/authoring-surface/command.md +206 -0
  67. package/docs/reference/authoring-surface/customize.md +64 -0
  68. package/docs/reference/authoring-surface/defineconfig.md +41 -0
  69. package/docs/reference/authoring-surface/defineevent.md +114 -0
  70. package/docs/reference/authoring-surface/dispatch.md +126 -0
  71. package/docs/reference/authoring-surface/fail.md +96 -0
  72. package/docs/reference/authoring-surface/file.md +142 -0
  73. package/docs/reference/authoring-surface/frompick.md +277 -0
  74. package/docs/reference/authoring-surface/http.md +259 -0
  75. package/docs/reference/authoring-surface/isfailure.md +58 -0
  76. package/docs/reference/authoring-surface/isready.md +14 -0
  77. package/docs/reference/authoring-surface/jr2setup.md +237 -0
  78. package/docs/reference/authoring-surface/open.md +105 -0
  79. package/docs/reference/authoring-surface/openbody.md +86 -0
  80. package/docs/reference/authoring-surface/paramsof.md +143 -0
  81. package/docs/reference/authoring-surface/pool.md +186 -0
  82. package/docs/reference/authoring-surface/push.md +130 -0
  83. package/docs/reference/authoring-surface/readyof.md +21 -0
  84. package/docs/reference/authoring-surface/secret.md +139 -0
  85. package/docs/reference/authoring-surface/sentby.md +83 -0
  86. package/docs/reference/authoring-surface/source.md +51 -0
  87. package/docs/reference/authoring-surface/text.md +62 -0
  88. package/docs/reference/authoring-surface/type-agentdeclaration.md +27 -0
  89. package/docs/reference/authoring-surface/type-agentdefinition.md +80 -0
  90. package/docs/reference/authoring-surface/type-agentlogic.md +15 -0
  91. package/docs/reference/authoring-surface/type-agentslots.md +15 -0
  92. package/docs/reference/authoring-surface/type-answeraction.md +12 -0
  93. package/docs/reference/authoring-surface/type-anyframepath.md +14 -0
  94. package/docs/reference/authoring-surface/type-anyworktreepath.md +15 -0
  95. package/docs/reference/authoring-surface/type-arg.md +19 -0
  96. package/docs/reference/authoring-surface/type-argnames.md +12 -0
  97. package/docs/reference/authoring-surface/type-bindactors.md +14 -0
  98. package/docs/reference/authoring-surface/type-binding.md +61 -0
  99. package/docs/reference/authoring-surface/type-bindingof.md +12 -0
  100. package/docs/reference/authoring-surface/type-bodyacceptsdoor.md +15 -0
  101. package/docs/reference/authoring-surface/type-bodyacceptsslots.md +17 -0
  102. package/docs/reference/authoring-surface/type-ceilings.md +41 -0
  103. package/docs/reference/authoring-surface/type-chainlink.md +19 -0
  104. package/docs/reference/authoring-surface/type-chartaction.md +46 -0
  105. package/docs/reference/authoring-surface/type-chartagent.md +28 -0
  106. package/docs/reference/authoring-surface/type-chartevent.md +20 -0
  107. package/docs/reference/authoring-surface/type-chartguard.md +20 -0
  108. package/docs/reference/authoring-surface/type-chartinvoke.md +28 -0
  109. package/docs/reference/authoring-surface/type-chartjson.md +14 -0
  110. package/docs/reference/authoring-surface/type-chartstate.md +46 -0
  111. package/docs/reference/authoring-surface/type-charttext.md +40 -0
  112. package/docs/reference/authoring-surface/type-charttransition.md +22 -0
  113. package/docs/reference/authoring-surface/type-charttransitions.md +14 -0
  114. package/docs/reference/authoring-surface/type-chartvalue.md +15 -0
  115. package/docs/reference/authoring-surface/type-childat.md +12 -0
  116. package/docs/reference/authoring-surface/type-childslots.md +12 -0
  117. package/docs/reference/authoring-surface/type-commandenv.md +15 -0
  118. package/docs/reference/authoring-surface/type-commandinput.md +20 -0
  119. package/docs/reference/authoring-surface/type-commandoptions.md +56 -0
  120. package/docs/reference/authoring-surface/type-commandoutput.md +122 -0
  121. package/docs/reference/authoring-surface/type-customize.md +111 -0
  122. package/docs/reference/authoring-surface/type-dispatchdefinition.md +39 -0
  123. package/docs/reference/authoring-surface/type-dispatchinput.md +14 -0
  124. package/docs/reference/authoring-surface/type-dispatchopenparts.md +14 -0
  125. package/docs/reference/authoring-surface/type-dispatchoutput.md +72 -0
  126. package/docs/reference/authoring-surface/type-doorlessinput.md +19 -0
  127. package/docs/reference/authoring-surface/type-duration.md +15 -0
  128. package/docs/reference/authoring-surface/type-effectbinding.md +93 -0
  129. package/docs/reference/authoring-surface/type-effectlogic.md +12 -0
  130. package/docs/reference/authoring-surface/type-envopenparts.md +14 -0
  131. package/docs/reference/authoring-surface/type-eventaudience.md +27 -0
  132. package/docs/reference/authoring-surface/type-eventdef.md +45 -0
  133. package/docs/reference/authoring-surface/type-eventfrom.md +16 -0
  134. package/docs/reference/authoring-surface/type-eventsemantics.md +26 -0
  135. package/docs/reference/authoring-surface/type-execoutcome.md +34 -0
  136. package/docs/reference/authoring-surface/type-failslot.md +14 -0
  137. package/docs/reference/authoring-surface/type-failure.md +19 -0
  138. package/docs/reference/authoring-surface/type-failureinput.md +20 -0
  139. package/docs/reference/authoring-surface/type-filebody.md +37 -0
  140. package/docs/reference/authoring-surface/type-framepath.md +14 -0
  141. package/docs/reference/authoring-surface/type-frominput.md +14 -0
  142. package/docs/reference/authoring-surface/type-hostinjectedinput.md +56 -0
  143. package/docs/reference/authoring-surface/type-httpdefinition.md +104 -0
  144. package/docs/reference/authoring-surface/type-httpfileinput.md +20 -0
  145. package/docs/reference/authoring-surface/type-httpinput.md +12 -0
  146. package/docs/reference/authoring-surface/type-httpmethod.md +14 -0
  147. package/docs/reference/authoring-surface/type-httpopenparts.md +12 -0
  148. package/docs/reference/authoring-surface/type-httpoutput.md +95 -0
  149. package/docs/reference/authoring-surface/type-httprequestparts.md +33 -0
  150. package/docs/reference/authoring-surface/type-jr2config.md +126 -0
  151. package/docs/reference/authoring-surface/type-lateroutcome.md +21 -0
  152. package/docs/reference/authoring-surface/type-lends.md +38 -0
  153. package/docs/reference/authoring-surface/type-logicat.md +12 -0
  154. package/docs/reference/authoring-surface/type-markedif.md +12 -0
  155. package/docs/reference/authoring-surface/type-mergedactors.md +12 -0
  156. package/docs/reference/authoring-surface/type-namedsecret.md +25 -0
  157. package/docs/reference/authoring-surface/type-namestart.md +77 -0
  158. package/docs/reference/authoring-surface/type-noslotworkspaceoptions.md +27 -0
  159. package/docs/reference/authoring-surface/type-notworktreekeys.md +12 -0
  160. package/docs/reference/authoring-surface/type-openbodydeclaration.md +40 -0
  161. package/docs/reference/authoring-surface/type-openbodylogic.md +14 -0
  162. package/docs/reference/authoring-surface/type-openbodyoutput.md +42 -0
  163. package/docs/reference/authoring-surface/type-openbodyslot.md +18 -0
  164. package/docs/reference/authoring-surface/type-opencommandinput.md +22 -0
  165. package/docs/reference/authoring-surface/type-openeffect.md +12 -0
  166. package/docs/reference/authoring-surface/type-openeffectslots.md +12 -0
  167. package/docs/reference/authoring-surface/type-openof.md +12 -0
  168. package/docs/reference/authoring-surface/type-opensecret.md +23 -0
  169. package/docs/reference/authoring-surface/type-opensecretmark.md +12 -0
  170. package/docs/reference/authoring-surface/type-permissivenoslotworkspaceoptions.md +26 -0
  171. package/docs/reference/authoring-surface/type-permissiveworkspaceoptions.md +27 -0
  172. package/docs/reference/authoring-surface/type-poolmachine.md +28 -0
  173. package/docs/reference/authoring-surface/type-poolnextinput.md +22 -0
  174. package/docs/reference/authoring-surface/type-poolspec.md +60 -0
  175. package/docs/reference/authoring-surface/type-pushinput.md +34 -0
  176. package/docs/reference/authoring-surface/type-pushoptions.md +79 -0
  177. package/docs/reference/authoring-surface/type-pushoutput.md +149 -0
  178. package/docs/reference/authoring-surface/type-pushwireoutput.md +12 -0
  179. package/docs/reference/authoring-surface/type-quantity.md +14 -0
  180. package/docs/reference/authoring-surface/type-reached.md +12 -0
  181. package/docs/reference/authoring-surface/type-reposlot.md +70 -0
  182. package/docs/reference/authoring-surface/type-reposlotsof.md +16 -0
  183. package/docs/reference/authoring-surface/type-sandboxoptions.md +84 -0
  184. package/docs/reference/authoring-surface/type-secret.md +25 -0
  185. package/docs/reference/authoring-surface/type-sender.md +19 -0
  186. package/docs/reference/authoring-surface/type-sentbyguards.md +12 -0
  187. package/docs/reference/authoring-surface/type-size.md +85 -0
  188. package/docs/reference/authoring-surface/type-slothandles.md +24 -0
  189. package/docs/reference/authoring-surface/type-sourcenextresult.md +17 -0
  190. package/docs/reference/authoring-surface/type-sourcespec.md +44 -0
  191. package/docs/reference/authoring-surface/type-syncstate.md +12 -0
  192. package/docs/reference/authoring-surface/type-text.md +19 -0
  193. package/docs/reference/authoring-surface/type-textpart.md +24 -0
  194. package/docs/reference/authoring-surface/type-thinkinglevel.md +39 -0
  195. package/docs/reference/authoring-surface/type-toparameterizedobject.md +14 -0
  196. package/docs/reference/authoring-surface/type-toprovidedactor.md +14 -0
  197. package/docs/reference/authoring-surface/type-unknown.md +21 -0
  198. package/docs/reference/authoring-surface/type-usercontainer.md +77 -0
  199. package/docs/reference/authoring-surface/type-withoutemptyindex.md +20 -0
  200. package/docs/reference/authoring-surface/type-workflowevent.md +46 -0
  201. package/docs/reference/authoring-surface/type-workspaceaccess.md +16 -0
  202. package/docs/reference/authoring-surface/type-workspaced.md +115 -0
  203. package/docs/reference/authoring-surface/type-workspacehandles.md +22 -0
  204. package/docs/reference/authoring-surface/type-workspacemachine.md +29 -0
  205. package/docs/reference/authoring-surface/type-workspaceof.md +13 -0
  206. package/docs/reference/authoring-surface/type-workspaceoptions.md +27 -0
  207. package/docs/reference/authoring-surface/type-worktreefound.md +16 -0
  208. package/docs/reference/authoring-surface/type-worktreeinput.md +56 -0
  209. package/docs/reference/authoring-surface/type-worktreekey.md +14 -0
  210. package/docs/reference/authoring-surface/type-worktreeoptions.md +29 -0
  211. package/docs/reference/authoring-surface/type-worktreeoutput.md +45 -0
  212. package/docs/reference/authoring-surface/type-worktreepath.md +16 -0
  213. package/docs/reference/authoring-surface/type-worktreeready.md +37 -0
  214. package/docs/reference/authoring-surface/type-worktreerefused.md +21 -0
  215. package/docs/reference/authoring-surface/workspace.md +287 -0
  216. package/docs/reference/authoring-surface/worktree.md +71 -0
  217. package/docs/reference/authoring-surface.md +217 -0
  218. package/docs/reference/cli.md +433 -0
  219. package/docs/reference/config.md +765 -0
  220. package/docs/reference/decisions/0001-operator-owned-generic-sandbox.md +114 -0
  221. package/docs/reference/decisions/0002-duplex-streaming-actor.md +117 -0
  222. package/docs/reference/decisions/0004-worktree-provisioning-model.md +130 -0
  223. package/docs/reference/decisions/0005-sandbox-pod-composition.md +240 -0
  224. package/docs/reference/decisions/0006-agent-control-surface.md +50 -0
  225. package/docs/reference/decisions/0007-durable-machine-state.md +109 -0
  226. package/docs/reference/decisions/0008-orchestrator-as-deployed-app.md +60 -0
  227. package/docs/reference/decisions/0009-cli-and-instance-interface.md +275 -0
  228. package/docs/reference/decisions/0010-bdd-acceptance-tests.md +160 -0
  229. package/docs/reference/decisions/0011-workflow-defined-events.md +141 -0
  230. package/docs/reference/decisions/0012-workspace-wrapper-machine.md +103 -0
  231. package/docs/reference/decisions/0013-the-agent-reaches-its-machine-through-a-container-it-cannot-read.md +175 -0
  232. package/docs/reference/decisions/0014-observation-is-open-run-state-is-not.md +95 -0
  233. package/docs/reference/decisions/0015-authoring-surface-absorbs-the-mechanism.md +271 -0
  234. package/docs/reference/decisions/0016-agent-turn-mechanics-are-internal.md +126 -0
  235. package/docs/reference/decisions/0017-pool-over-a-source-port.md +71 -0
  236. package/docs/reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md +111 -0
  237. package/docs/reference/decisions/0019-one-converging-command-against-the-current-context.md +287 -0
  238. package/docs/reference/decisions/0020-private-ca-trust-is-a-named-concept.md +60 -0
  239. package/docs/reference/decisions/0021-workspace-continuity-is-a-lease-that-answers-back.md +101 -0
  240. package/docs/reference/decisions/0022-observation-is-a-level-triggered-feed.md +103 -0
  241. package/docs/reference/decisions/0023-the-harness-prints-the-conversation.md +175 -0
  242. package/docs/reference/decisions/0024-an-agents-turn-ends-with-the-state-that-asked-for-it.md +436 -0
  243. package/docs/reference/decisions/0025-cancel-ends-a-run-stop-parks-it.md +65 -0
  244. package/docs/reference/decisions/0026-a-turn-that-is-over-is-never-prompted.md +62 -0
  245. package/docs/reference/decisions/0027-the-harness-is-jr2s-own-server-flue-retires-the-wire-stays.md +245 -0
  246. package/docs/reference/decisions/0028-what-an-agent-may-do-to-the-workspace-is-part-of-its-definition.md +90 -0
  247. package/docs/reference/decisions/0029-a-menu-is-fixed-for-a-conversation-and-a-turn-is-told-its-allowed-picks.md +154 -0
  248. package/docs/reference/decisions/0030-a-snapshot-names-the-machine-it-was-written-under.md +100 -0
  249. package/docs/reference/decisions/0031-menu-only-agents-run-on-the-instance-harness.md +193 -0
  250. package/docs/reference/decisions/0032-the-console-unlocks-with-the-instance-token.md +61 -0
  251. package/docs/reference/decisions/0033-a-machine-declares-the-input-that-starts-it.md +126 -0
  252. package/docs/reference/decisions/0034-the-console-renders-with-preact-and-the-server-erases-the-types.md +57 -0
  253. package/docs/reference/decisions/0035-a-runaway-turn-is-ended-rerolled-once-then-a-fault.md +92 -0
  254. package/docs/reference/decisions/0036-a-turn-compacts-its-own-context-mid-flight.md +138 -0
  255. package/docs/reference/decisions/0037-an-instance-builds-its-sandbox-images-jr2-injects-the-harness.md +196 -0
  256. package/docs/reference/decisions/0038-jr2-up-builds-every-image-it-deploys.md +170 -0
  257. package/docs/reference/decisions/0039-image-garbage-collects-by-reachability.md +115 -0
  258. package/docs/reference/decisions/0041-a-build-the-host-already-holds-is-not-spent-again.md +64 -0
  259. package/docs/reference/decisions/0042-ready-is-not-routable-an-admission-retries-its-connection.md +142 -0
  260. package/docs/reference/decisions/0043-the-kit-is-tested-as-installed-a-local-registry-stands-in-for-npm.md +170 -0
  261. package/docs/reference/decisions/0044-kit-images-live-at-a-canonical-home-a-self-host-mirrors-it.md +85 -0
  262. package/docs/reference/decisions/0045-the-platform-joins-the-image-address-and-the-cluster-chooses-it.md +82 -0
  263. package/docs/reference/decisions/0046-a-converge-failure-carries-its-diagnosis.md +34 -0
  264. package/docs/reference/decisions/0047-the-git-ssh-key-source-is-the-users-choice.md +47 -0
  265. package/docs/reference/decisions/0048-the-orchestrator-boots-without-its-repos.md +36 -0
  266. package/docs/reference/decisions/0049-a-machine-carries-its-parts-and-composes-by-invoke.md +126 -0
  267. package/docs/reference/decisions/0050-what-code-names-config-declares-what-the-cli-names-discovery-finds.md +73 -0
  268. package/docs/reference/decisions/0051-a-repo-is-a-slot-on-the-workspace-and-a-cache-on-the-node.md +238 -0
  269. package/docs/reference/decisions/0052-a-sandbox-lands-where-an-ordinary-pod-lands-and-the-cache-follows-it.md +86 -0
  270. package/docs/reference/decisions/0053-a-fetch-inside-the-pod-asks-the-node-cache-and-the-cache-asks-the-remote.md +123 -0
  271. package/docs/reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md +126 -0
  272. package/docs/reference/decisions/0055-a-release-is-a-pushed-tag-and-the-publish-guard-is-the-credential.md +107 -0
  273. package/docs/reference/decisions/0056-a-global-jr2-hands-off-to-the-instances-own-and-an-instance-has-one-kit-version.md +62 -0
  274. package/docs/reference/decisions/0057-a-turn-is-its-frame-its-dials-and-whether-it-continues.md +152 -0
  275. package/docs/reference/decisions/0058-a-harness-answers-the-orchestrator-alone.md +108 -0
  276. package/docs/reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md +427 -0
  277. package/docs/reference/decisions/0060-a-workspace-states-its-size-and-jr2-reserves-all-of-it.md +111 -0
  278. package/docs/reference/decisions/0061-a-memory-kill-ends-the-agents-processes-not-the-harness.md +83 -0
  279. package/docs/reference/decisions/0062-jr2-briefs-the-agent-on-its-seat-never-on-its-task.md +239 -0
  280. package/docs/reference/decisions/0063-the-orchestrator-watches-the-cluster.md +82 -0
  281. package/docs/reference/decisions/0064-a-workspace-waits-for-capacity.md +79 -0
  282. package/docs/reference/decisions/0065-a-persist-survives-a-crash-and-history-is-a-week.md +65 -0
  283. package/docs/reference/decisions/0066-a-model-tier-runs-a-real-model-and-a-change-to-what-it-reads-runs-the-tier.md +552 -0
  284. package/docs/reference/decisions/0067-an-effect-is-an-actor-slot-and-runs-at-most-once-unless-marked-idempotent.md +458 -0
  285. package/docs/reference/decisions/0068-an-effector-holds-an-effects-secrets-and-signs-its-wire.md +475 -0
  286. package/docs/reference/decisions/0069-the-orchestrator-is-a-kit-image-and-an-instance-publishes-its-assembly.md +180 -0
  287. package/docs/reference/decisions/0070-a-machine-lends-its-parts-to-a-chart.md +334 -0
  288. package/docs/reference/decisions/0071-a-run-starts-a-run-through-a-dispatch-effect.md +183 -0
  289. package/docs/reference/decisions/0072-the-docs-ship-inside-the-kit-and-an-instances-agents-md-indexes-them.md +144 -0
  290. package/docs/reference/decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md +122 -0
  291. package/docs/reference/decisions/0074-an-unrouted-mechanism-event-is-refused-at-load-and-faults-the-run.md +76 -0
  292. package/docs/reference/decisions/0075-a-machine-cuts-a-worktree-and-the-workspace-only-clones.md +295 -0
  293. package/docs/reference/decisions/0076-an-agents-control-credential-lives-only-where-no-workspace-code-runs.md +320 -0
  294. package/docs/reference/decisions/0077-jr2-requires-landlock-on-every-sandbox-node.md +79 -0
  295. package/docs/reference/decisions.md +86 -0
  296. package/docs/reference/glossary.md +687 -0
  297. package/docs/reference/http-api.md +1386 -0
  298. package/docs/reference/machines.md +189 -0
  299. package/docs/reference/mechanism-events.md +72 -0
  300. package/docs/why.md +207 -0
  301. package/package.json +5 -3
  302. package/src/actor.ts +694 -106
  303. package/src/agent.ts +114 -38
  304. package/src/ambient.ts +3 -4
  305. package/src/assembly-checks.ts +189 -7
  306. package/src/cause.ts +234 -0
  307. package/src/chart.ts +345 -46
  308. package/src/charts.ts +43 -8
  309. package/src/config.ts +440 -178
  310. package/src/custodian.lua +17 -5
  311. package/src/custodian.ts +325 -99
  312. package/src/customize.ts +199 -49
  313. package/src/dispatch-effect.ts +945 -0
  314. package/src/door-compat.ts +217 -0
  315. package/src/durability.ts +11 -4
  316. package/src/effect-checks.ts +50 -3
  317. package/src/effect.ts +641 -128
  318. package/src/effector-wire.ts +165 -13
  319. package/src/fail.ts +222 -0
  320. package/src/harness-client.ts +587 -50
  321. package/src/harness-env.ts +33 -0
  322. package/src/held-secrets.ts +125 -16
  323. package/src/holds.ts +3 -0
  324. package/src/http-effect.ts +556 -58
  325. package/src/http.ts +480 -30
  326. package/src/index.ts +74 -82
  327. package/src/instance.ts +68 -8
  328. package/src/internal.ts +85 -0
  329. package/src/kube-client.ts +6 -3
  330. package/src/machine-doc.ts +24 -7
  331. package/src/mechanism-routes.ts +168 -0
  332. package/src/model-keys.generated.ts +53 -0
  333. package/src/model-keys.ts +42 -58
  334. package/src/names.ts +19 -6
  335. package/src/notices.ts +483 -41
  336. package/src/open-body.ts +242 -40
  337. package/src/open-effect.ts +81 -8
  338. package/src/open.ts +90 -6
  339. package/src/parts.ts +213 -30
  340. package/src/party.ts +101 -2
  341. package/src/pick.ts +497 -11
  342. package/src/pool.ts +282 -50
  343. package/src/registration.ts +133 -12
  344. package/src/repo-identity.ts +7 -3
  345. package/src/repos.ts +22 -3
  346. package/src/run-host.ts +665 -45
  347. package/src/run-output.ts +38 -0
  348. package/src/sandbox-effect.ts +457 -71
  349. package/src/sandbox-kube.ts +66 -17
  350. package/src/secret-placement.ts +59 -17
  351. package/src/server.ts +3 -0
  352. package/src/setup.ts +325 -62
  353. package/src/size.ts +121 -9
  354. package/src/snapshot-store.ts +54 -10
  355. package/src/stub-harness.ts +44 -16
  356. package/src/timers.ts +14 -1
  357. package/src/tokens.ts +107 -32
  358. package/src/vocabulary.ts +88 -14
  359. package/src/wire.ts +100 -26
  360. package/src/workspace.ts +771 -238
  361. package/src/worktree.ts +249 -0
@@ -0,0 +1,383 @@
1
+ ---
2
+ title: An Agent in a Sandbox
3
+ description: A coder Agent fixes a bug in your fork of jr2, in a Sandbox. You push its branch, and approve.
4
+ ---
5
+
6
+ # An Agent in a Sandbox
7
+
8
+ At the end of this page, a coder [Agent](../reference/glossary.md#agent) has fixed a bug in your fork of jr2. The Agent
9
+ works in a [Sandbox](../reference/glossary.md#sandbox): a pod of its own, with a git checkout of your fork. You go into
10
+ the Sandbox and read the work. You ask for one more change, push the branch by hand, and approve the work.
11
+
12
+ ## Before you start
13
+
14
+ - Do [A model decides](a-model-decides.md) first. Your [Instance](../reference/glossary.md#instance) `my-instance` has
15
+ the model of your tab, and `kind-jr2` is the current kubectl context.
16
+ - You need a GitHub account.
17
+ - Open two terminals in `my-instance`. The first terminal shows the run. The second terminal sends commands to it.
18
+
19
+ ## Fork jr2
20
+
21
+ The Agent works on a [Repo](../reference/glossary.md#repo) that you can push to, so you fork jr2. Your fork holds the
22
+ tutorial fixture, `docs/site/tutorial/greet/`. It is a small Node CLI with one bug, and its test `trims the name` fails.
23
+
24
+ 1. Open `https://github.com/snapwich/jr2`.
25
+ 2. Click **Fork**.
26
+ 3. Clear **Copy the main branch only**, so that the fork gets the release tags.
27
+ 4. Click **Create fork**.
28
+
29
+ Make sure that the fork has the release tag of your Kit. `<you>` is your GitHub user name. `<version>` is the
30
+ [Kit version](../reference/glossary.md#kit-version): the version of `@jr2/orchestrator` in `package.json`, such as
31
+ `0.4.1`.
32
+
33
+ 1. Open `https://github.com/<you>/jr2/tags`.
34
+ 2. Find the tag `v<version>`, such as `v0.4.1`.
35
+
36
+ If the page shows no tags, delete the fork. Fork again with **Copy the main branch only** cleared.
37
+
38
+ ## Make a token for the fork
39
+
40
+ The Agent cannot push. You push its branch by hand, so you need a token for your fork. On GitHub, make a fine-grained
41
+ personal access token:
42
+
43
+ 1. Click your profile picture, then **Settings**.
44
+ 2. Click **Developer settings**, then **Personal access tokens**, then **Fine-grained tokens**.
45
+ 3. Click **Generate new token**.
46
+ 4. In **Repository access**, select **Only select repositories**.
47
+ 5. Select `<you>/jr2`.
48
+ 6. In **Permissions**, set **Contents** to **Read and write**.
49
+ 7. Click **Generate token**.
50
+ 8. Copy the token.
51
+
52
+ Keep the token in a safe place. You use it on this page and on the next page.
53
+
54
+ ## Install @jr2/machines
55
+
56
+ The Kit ships [Machines](../reference/glossary.md#machine) in the package `@jr2/machines`. Install it at the Kit
57
+ version:
58
+
59
+ ```sh
60
+ npm install --save-exact @jr2/machines@<version>
61
+ ```
62
+
63
+ ```text
64
+
65
+ added 1 package, and audited 15 packages in 266ms
66
+
67
+ 3 packages are looking for funding
68
+ run `npm fund` for details
69
+
70
+ found 0 vulnerabilities
71
+ ```
72
+
73
+ Your numbers can be different.
74
+
75
+ ## Write the Workflow
76
+
77
+ The shipped Machine [`task`](../reference/machines.md#task) gives one prompt to a coder Agent in a
78
+ [Workspace](../reference/glossary.md#workspace). Then the run waits at a [Gate](../reference/glossary.md#gate) named
79
+ `review`, until you approve the work. `task` puts the `review` Gate in its body, so the id of the Gate is `body.review`.
80
+
81
+ `task` cannot know your Repo, and it cannot pay for your model. Thus it leaves two parts
82
+ [Open](../reference/glossary.md#open): its [Repo Slots](../reference/glossary.md#repo-slot) and the model of its coder.
83
+ You bind the two with [`customize()`](../reference/authoring-surface/customize.md).
84
+
85
+ Make the file `workflows/task.ts`. Replace `<you>` and `<version>` in it:
86
+
87
+ **Anthropic**
88
+
89
+ ```ts
90
+ import { customize } from "@jr2/orchestrator";
91
+ import { task } from "@jr2/machines";
92
+
93
+ // `task` leaves two parts Open: its Repo Slots and the model of its coder. This file binds the two.
94
+ // The file name gives the Workflow its name: task.
95
+ export const machine = customize(task, {
96
+ // One Repo Slot, target: your fork, from the release tag of the Kit that you installed.
97
+ // Replace <you> with your GitHub user name. Replace <version> with the Kit version.
98
+ repos: { target: { url: "https://github.com/<you>/jr2.git", ref: "v<version>" } },
99
+ // The model that the coder Agent uses.
100
+ agents: { coder: { model: "anthropic/claude-haiku-5-5" } },
101
+ });
102
+ ```
103
+
104
+ **Local**
105
+
106
+ ```ts
107
+ import { customize } from "@jr2/orchestrator";
108
+ import { task } from "@jr2/machines";
109
+
110
+ // `task` leaves two parts Open: its Repo Slots and the model of its coder. This file binds the two.
111
+ // The file name gives the Workflow its name: task.
112
+ export const machine = customize(task, {
113
+ // One Repo Slot, target: your fork, from the release tag of the Kit that you installed.
114
+ // Replace <you> with your GitHub user name. Replace <version> with the Kit version.
115
+ repos: { target: { url: "https://github.com/<you>/jr2.git", ref: "v<version>" } },
116
+ // The model that the coder Agent uses.
117
+ agents: { coder: { model: "local/qwen3.6-35b-a3b" } },
118
+ });
119
+ ```
120
+
121
+ - `target` is the name of the Repo Slot. The coder works in the first Repo Slot.
122
+ - `ref` is the release tag. The branch of the Agent starts from it, so each reader of a release starts from the same
123
+ fixture.
124
+ - The file name gives the [Workflow](../reference/glossary.md#workflow) its name: `task`.
125
+
126
+ ## Converge the Instance
127
+
128
+ [`jr2 up`](../reference/cli.md#up) converges the Instance with the new Workflow:
129
+
130
+ ```sh
131
+ jr2 up
132
+ ```
133
+
134
+ ```text
135
+ …
136
+ seats: workflow "task" — who may send what, per state (ADR-0015)
137
+ task.working agent:coder: [finish]
138
+ task.review gate: [approve, request_changes]
139
+ …
140
+ sandbox image "default": building jr2-sandbox-my-instance-default:6389bdf72d50-amd64
141
+ no USER declared — the pod's uid-1000 fallback applies
142
+ kind load → cluster "jr2"
143
+ …
144
+ repos: 1 bound Repo(s) — the Orchestrator creates their Repo resources at boot and at each publish (ADR-0069); the cache agent clones on first need (`jr2 status` reports sync state)
145
+ converged — `jr2 run <workflow>` when ready
146
+ ```
147
+
148
+ `task` is the first Workflow of the Instance that has a Workspace. Thus this `jr2 up` also builds the
149
+ [Sandbox Image](../reference/glossary.md#sandbox-image) from `images/default/Dockerfile`, and loads it into the kind
150
+ cluster. If you did not bind an Open part, `jr2 up` stops and prints the `customize()` line that binds it.
151
+
152
+ ## Start the run
153
+
154
+ In the first terminal, start a run of `task` with [`jr2 run`](../reference/cli.md#run). The prompt tells the Agent what
155
+ to fix and how to check the fix:
156
+
157
+ ```sh
158
+ jr2 run task --input '{"prompt":"In docs/site/tutorial/greet, one test fails. Fix the bug in docs/site/tutorial/greet/src/greet.js. To check your fix, run node --test in docs/site/tutorial/greet. Do not change files outside that folder. Do not run the tests of the repo root."}'
159
+ ```
160
+
161
+ ```text
162
+ …
163
+ → context kind-jr2 / namespace my-instance
164
+ run 290b4be9-1e24-46a2-8cb5-27fabb3bbd3c (task) — attached
165
+ → active "placing"
166
+ → active "provisioning"
167
+ → active "attaching"
168
+ → active "running"
169
+ …
170
+ ```
171
+
172
+ The line `run <run id> (task) — attached` gives the run id. Your run id is different. As on the last page, the first
173
+ line of the output, `→ .env:`, shows as `…`. Keep this terminal open. The run does not end until you approve the work.
174
+
175
+ ## Wait for the review Gate
176
+
177
+ The Sandbox starts, and the coder works. When the coder finishes, the run waits at the `review` Gate. In the second
178
+ terminal, read the status of the run with [`jr2 status`](../reference/cli.md#status). `<run id>` is the run id, or its
179
+ first 4 characters or more:
180
+
181
+ ```sh
182
+ jr2 status <run id>
183
+ ```
184
+
185
+ The status is one line of JSON. While the coder works, `gates` is `[]`. When the run waits at `review`, `gates` holds
186
+ the Gate. Its `gate` is `body.review`, and the line ends with its `meta`. After the JSON, `jr2 status` prints one line
187
+ for each Worktree that the run cut:
188
+
189
+ ```text
190
+ …"gate":"body.review",…,"meta":{"summary":"Fixed a bug in docs/site/tutorial/greet/src/greet.js where the name argument wasn't being trimmed. The test \"trims the name\" failed because input like \" ada \" produced \"hello, ada \" instead of \"hello, ada\". Added `.trim()` to the name extraction so whitespace is stripped before constructing the greeting. All 6 tests now pass.","branch":"jr2/task-1f34eef3-5749-4d7c-a16b-488c56ec88cd","worktree":"/work/target/task"}}]}
191
+ worktree: /work/target/task (target), branch jr2/task-1f34eef3-5749-4d7c-a16b-488c56ec88cd
192
+ ```
193
+
194
+ Run the command again until `gates` holds the Gate.
195
+
196
+ - `summary` is what the coder says that it did, in the words of the model. Your summary is different.
197
+ - `branch` is the branch that the coder commits on.
198
+ - `worktree` is the folder in the Sandbox that holds the branch. It is
199
+ [the Worktree](../reference/glossary.md#worktree).
200
+
201
+ Copy `branch` and `worktree` from your output. The part after `jr2/task-`, here `1f34eef3-5749-4d7c-a16b-488c56ec88cd`,
202
+ is the [Instance ID](../reference/glossary.md#instance-id) of the run. `jr2 status` prints it as `instanceId`. It is not
203
+ the run id. Do not make the branch name from the run id. With the Instance token, the drawer of the
204
+ [Console](../reference/glossary.md#console) shows the same `meta`.
205
+
206
+ If `meta` has a `reason` and no `summary`, the [Turn](../reference/glossary.md#turn) of the coder failed. Send
207
+ `request_changes`, as in [Ask for a change](#ask-for-a-change), and the coder tries again.
208
+
209
+ ## Find the Sandbox
210
+
211
+ The label `jr2.dev/run` on the Sandbox holds the full run id. A prefix does not work here. Copy the full run id from the
212
+ line `run <run id> (task) — attached` in the first terminal:
213
+
214
+ ```sh
215
+ kubectl -n my-instance get sandboxes -l jr2.dev/run=<run id>
216
+ ```
217
+
218
+ ```text
219
+ NAME PHASE ENDPOINT AGE
220
+ ws-290b4be9-x-0-19gh8ze Ready http://ws-290b4be9-x-0-19gh8ze.my-instance.svc:8080 5m25s
221
+ ```
222
+
223
+ `ws-290b4be9-x-0-19gh8ze` is the name of the Sandbox. Your Sandbox has a different name. It starts with `ws-` and the
224
+ first 8 characters of the run id. The pod of the Sandbox has the same name. The commands below write it as `<sandbox>`.
225
+
226
+ ## Look inside the Sandbox
227
+
228
+ Go into the `harness` container of the pod. The Agent's tools run in this container:
229
+
230
+ ```sh
231
+ kubectl -n my-instance exec -it <sandbox> -c harness -- bash
232
+ ```
233
+
234
+ In the Sandbox, go to the fixture in the Worktree. Then run its tests. `<worktree>` is the `worktree` that you copied:
235
+
236
+ ```sh
237
+ cd <worktree>/docs/site/tutorial/greet
238
+ node --test
239
+ ```
240
+
241
+ ```text
242
+ ✔ greets the world by default (1.0597ms)
243
+ ✔ greets a name (0.162102ms)
244
+ ✔ shouts (0.08266ms)
245
+ ✔ trims the name (0.057171ms)
246
+ ✔ prints help (3.806196ms)
247
+ ✔ refuses an unknown flag (0.222015ms)
248
+ ℹ tests 6
249
+ ℹ suites 0
250
+ ℹ pass 6
251
+ ℹ fail 0
252
+ ℹ cancelled 0
253
+ ℹ skipped 0
254
+ ℹ todo 0
255
+ ℹ duration_ms 53.312932
256
+ ```
257
+
258
+ Your times are different. Read the commits of the coder. The branch starts at the release tag, so the commits after the
259
+ tag are the commits of the coder:
260
+
261
+ ```sh
262
+ git log --oneline v<version>..HEAD
263
+ ```
264
+
265
+ ```text
266
+ e467788 fix: trim name in greet.js to handle leading/trailing whitespace
267
+ ```
268
+
269
+ Each line is one commit. The commit ids and the messages come from the model. The author of each commit is
270
+ `jr2 Agent <agent@jr2.invalid>`, the default git author that jr2 gives a Sandbox. Then leave the Sandbox:
271
+
272
+ ```sh
273
+ exit
274
+ ```
275
+
276
+ ## Ask for a change
277
+
278
+ In the second terminal, send `request_changes` to the `review` Gate with [`jr2 send`](../reference/cli.md#send).
279
+ `--gate` takes the `gate` value from `jr2 status`. Put your notes in the input:
280
+
281
+ ```sh
282
+ jr2 send <run id> --gate body.review --event request_changes --input '{"notes":"Also add a test that trims the name when you pass --shout."}'
283
+ ```
284
+
285
+ ```text
286
+ …
287
+ → context kind-jr2 / namespace my-instance
288
+ delivered request_changes to gate "body.review" on 290b4be9-1e24-46a2-8cb5-27fabb3bbd3c
289
+ ```
290
+
291
+ The coder continues the same conversation, with your notes as its next prompt. The Sandbox and the branch stay. Run
292
+ `jr2 status <run id>` again until `gates` holds the `review` Gate. The new `summary` tells what the coder changed.
293
+
294
+ ## Push the branch
295
+
296
+ `task` does not push, and the Agent has no credential to push with. While the run waits at `review`, you push the branch
297
+ from the Sandbox. Go into the Sandbox again:
298
+
299
+ ```sh
300
+ kubectl -n my-instance exec -it <sandbox> -c harness -- bash
301
+ ```
302
+
303
+ In the Sandbox, go to the Worktree. Then push the branch. `<branch>` is the `branch` that you copied:
304
+
305
+ ```sh
306
+ cd <worktree>
307
+ git push origin <branch>
308
+ ```
309
+
310
+ `git push` asks for a user name and a password. Give `<you>` as the user name. Give the token as the password.
311
+
312
+ ```text
313
+ Username for 'https://github.com': <you>
314
+ Password for 'https://<you>@github.com':
315
+ …
316
+ To https://github.com/<you>/jr2.git
317
+ * [new branch] jr2/task-1f34eef3-5749-4d7c-a16b-488c56ec88cd -> jr2/task-1f34eef3-5749-4d7c-a16b-488c56ec88cd
318
+ ```
319
+
320
+ `origin` fetches through the Repo cache of the node, and pushes to your fork. Open your fork on GitHub to see the
321
+ branch. Then leave the Sandbox:
322
+
323
+ ```sh
324
+ exit
325
+ ```
326
+
327
+ ## Approve the work
328
+
329
+ > **Caution**
330
+ >
331
+ > `approve` ends the run and removes the Sandbox. A commit that you did not push is lost.
332
+
333
+ In the second terminal, send `approve` to the `review` Gate. `approve` takes no input:
334
+
335
+ ```sh
336
+ jr2 send <run id> --gate body.review --event approve
337
+ ```
338
+
339
+ ```text
340
+ …
341
+ → context kind-jr2 / namespace my-instance
342
+ delivered approve to gate "body.review" on 290b4be9-1e24-46a2-8cb5-27fabb3bbd3c
343
+ ```
344
+
345
+ In the first terminal, `jr2 run` prints the end of the run, then the final status as one line of JSON, and stops:
346
+
347
+ ```text
348
+ …
349
+ → active "teardown"
350
+ → done "done"
351
+ {"runId":"290b4be9-1e24-46a2-8cb5-27fabb3bbd3c","workflow":"task",…,"output":{"branch":"jr2/task-1f34eef3-5749-4d7c-a16b-488c56ec88cd"},"worktrees":[{"slot":"target","path":"/work/target/task","branch":"jr2/task-1f34eef3-5749-4d7c-a16b-488c56ec88cd"}]}
352
+ ```
353
+
354
+ ## Make sure that the Sandbox is gone
355
+
356
+ Use the full run id again:
357
+
358
+ ```sh
359
+ kubectl -n my-instance get sandboxes -l jr2.dev/run=<run id>
360
+ ```
361
+
362
+ ```text
363
+ No resources found in my-instance namespace.
364
+ ```
365
+
366
+ ## What happened
367
+
368
+ - `task` is a Machine in a Workspace. The run made a Sandbox for the Workspace and cloned your fork into it. It cut the
369
+ branch from the release tag, in the Worktree `/work/target/task`. See [Workspaces](../concepts/workspaces.md).
370
+ - `task` left its Repo Slots and the model of its coder Open. `customize()` bound them where you registered the
371
+ Workflow, and `jr2 up` refuses a Workflow with an Open part. See [Composition](../concepts/composition.md) and
372
+ [ADR-0054](../reference/decisions/0054-the-kit-ships-machines-and-a-shipped-machine-leaves-its-parts-open.md).
373
+ - The `review` Gate kept the Sandbox while the run waited. `request_changes` sent the coder back to the same
374
+ conversation. `approve` ended the run, and the end of the Workspace removed the Sandbox. See
375
+ [Gates](../concepts/gates.md) and [ADR-0012](../reference/decisions/0012-workspace-wrapper-machine.md).
376
+ - You used `kubectl exec` to go into the Sandbox. The guide [Look inside a Sandbox](../guides/look-inside-a-sandbox.md)
377
+ gives the same commands.
378
+ - You pushed by hand, because `task` does not push. On the next page, a Machine pushes the branch with an
379
+ [Effect](../reference/glossary.md#effect).
380
+
381
+ ## Next
382
+
383
+ [Have your Assistant write a Machine](have-your-assistant-write-a-machine.md)
@@ -0,0 +1,248 @@
1
+ ---
2
+ title: Connect a model
3
+ description: Add a model to the Instance, with its key or its address in .env, and converge the Instance again.
4
+ ---
5
+
6
+ # Connect a model
7
+
8
+ At the end of this page, the config of your [Instance](../reference/glossary.md#instance) names a model. `jr2.config.ts`
9
+ names its key or its endpoint, `.env` holds the value, and the cluster has the new config. The next page gives the model
10
+ its first task.
11
+
12
+ ## Before you start
13
+
14
+ Do [Create an Instance](create-an-instance.md) first. The Instance `my-instance` must be in the kind cluster.
15
+
16
+ Choose a tab. Choose Anthropic for a model of the Anthropic API. Choose Local for a model that you serve on a computer
17
+ on your network. Each page after this one uses the model of the tab that you choose.
18
+
19
+ **Anthropic**
20
+
21
+ You need an Anthropic API key. Make one on the [Anthropic website](https://console.anthropic.com/).
22
+
23
+ **Local**
24
+
25
+ You need a computer that can serve Qwen3.6-35B-A3B with a context window of 65536 tokens. It can be the computer that
26
+ runs kind, or a different one on your network. Install one of these two servers on it:
27
+
28
+ - [vLLM](https://docs.vllm.ai/en/latest/getting_started/installation/)
29
+ - [llama.cpp](https://github.com/ggml-org/llama.cpp/blob/master/docs/install.md)
30
+
31
+ ## Add the model to jr2.config.ts
32
+
33
+ **Anthropic**
34
+
35
+ Open `jr2.config.ts`. Find the line that starts with `// secrets:`. Remove the `//`. Keep the other lines and their
36
+ comments. This is the result. Its comments are shorter than the comments in your file:
37
+
38
+ ```ts
39
+ import { defineConfig } from "@jr2/orchestrator";
40
+
41
+ export default defineConfig({
42
+ git: {
43
+ // The credentials that the cluster uses to clone and push. The token comes from JR2_GIT_TOKEN in .env.
44
+ credentials: [{ match: "*", token: "JR2_GIT_TOKEN", sshKey: "jr2-git-ssh" }],
45
+ },
46
+ // The model key. jr2 up gives it only to the Custodian of each pod whose Agents use Anthropic.
47
+ secrets: [{ name: "ANTHROPIC_API_KEY", value: process.env.ANTHROPIC_API_KEY }],
48
+ });
49
+ ```
50
+
51
+ The `secrets` line gives jr2 the value of `ANTHROPIC_API_KEY` from `.env`. An [Agent](../reference/glossary.md#agent)
52
+ that names an `anthropic/` model uses this key.
53
+
54
+ **Local**
55
+
56
+ Open `jr2.config.ts`. Add the `harness` entry after the `git` entry. Keep the other lines and their comments. This is
57
+ the result. Its comments are shorter than the comments in your file:
58
+
59
+ ```ts
60
+ import { defineConfig } from "@jr2/orchestrator";
61
+
62
+ export default defineConfig({
63
+ git: {
64
+ // The credentials that the cluster uses to clone and push. The token comes from JR2_GIT_TOKEN in .env.
65
+ credentials: [{ match: "*", token: "JR2_GIT_TOKEN", sshKey: "jr2-git-ssh" }],
66
+ },
67
+ harness: {
68
+ // An OpenAI-compatible endpoint, such as vLLM or llama.cpp. An Agent names its model as local/<model>.
69
+ provider: {
70
+ id: "local",
71
+ api: "openai-completions",
72
+ // An address that a pod can reach, from .env. With no apiKey, plain http:// is permitted.
73
+ baseUrl: process.env.LOCAL_MODEL_URL ?? "",
74
+ // The key is the name that the endpoint gives for GET /v1/models. The limits agree with the server.
75
+ models: { "qwen3.6-35b-a3b": { contextWindow: 65536, maxTokens: 8192 } },
76
+ },
77
+ },
78
+ });
79
+ ```
80
+
81
+ The entry adds a custom provider with the id `local`. An [Agent](../reference/glossary.md#agent) names a model of this
82
+ provider as `local/<model>`, such as `local/qwen3.6-35b-a3b`. `<model>` is the name that the endpoint gives for
83
+ `GET /v1/models`.
84
+
85
+ The [config reference](../reference/config.md#secrets) gives each field of `secrets` and of
86
+ [`harness.provider`](../reference/config.md#harness-provider).
87
+
88
+ ## Put the value in .env
89
+
90
+ **Anthropic**
91
+
92
+ Make the file `.env` in `my-instance`. Put this line in it, with your key in place of `<your key>`:
93
+
94
+ ```text
95
+ ANTHROPIC_API_KEY=<your key>
96
+ ```
97
+
98
+ **Local**
99
+
100
+ Make the file `.env` in `my-instance`. Put this line in it:
101
+
102
+ ```text
103
+ LOCAL_MODEL_URL=http://<address>:8000/v1
104
+ ```
105
+
106
+ `<address>` is an address of the server computer that a pod can reach, such as its LAN address. Do not use `localhost`.
107
+ In a pod, `localhost` is the pod itself.
108
+
109
+ The jr2 CLI reads `.env` before each command, and names each key that it takes from `.env`. A variable that you set in
110
+ your shell has priority over `.env`. Do not put `.env` in git: the `.gitignore` that `jr2 init` wrote keeps it out.
111
+
112
+ ## Start the model server
113
+
114
+ **Anthropic**
115
+
116
+ There is no server to start. Go to the next step.
117
+
118
+ **Local**
119
+
120
+ On the server computer, start one of the two servers. Each command serves the model as `qwen3.6-35b-a3b`, on port 8000,
121
+ on all addresses (`0.0.0.0`). The pods cannot reach a server that listens only on its loopback address.
122
+
123
+ To start llama.cpp, run:
124
+
125
+ ```sh
126
+ llama-server -hf unsloth/Qwen3.6-35B-A3B-GGUF:UD-Q6_K_XL --alias qwen3.6-35b-a3b --no-mmproj \
127
+ --host 0.0.0.0 --port 8000 --jinja -c 65536 \
128
+ --temp 0.6 --presence-penalty 1.0 -ctk q8_0 -ctv q8_0 -fa on
129
+ ```
130
+
131
+ `--jinja` lets the model call tools. `--temp 0.6` and `--presence-penalty 1.0` are the sampling settings for Qwen.
132
+ `-ctk q8_0 -ctv q8_0 -fa on` make the KV cache smaller, so that 65536 tokens fit in memory.
133
+
134
+ To start vLLM, run:
135
+
136
+ ```sh
137
+ vllm serve Qwen/Qwen3.6-35B-A3B --served-model-name qwen3.6-35b-a3b \
138
+ --host 0.0.0.0 --port 8000 --max-model-len 65536 \
139
+ --enable-auto-tool-choice --tool-call-parser qwen3_coder
140
+ ```
141
+
142
+ `--enable-auto-tool-choice` and `--tool-call-parser` let the model call tools.
143
+
144
+ With each of the two servers, the model must make tool calls. `jr2 up` asks the model for one tool call before it
145
+ converges, and stops when the model does not make one.
146
+
147
+ ## Check the model server
148
+
149
+ **Anthropic**
150
+
151
+ There is no server to check. Go to the next step.
152
+
153
+ **Local**
154
+
155
+ From the computer that runs kind, run:
156
+
157
+ ```sh
158
+ curl http://<address>:8000/v1/models
159
+ ```
160
+
161
+ The server sends a JSON object. This object is from vLLM. llama.cpp sends different fields:
162
+
163
+ ```text
164
+ {"object":"list","data":[{"id":"qwen3.6-35b-a3b","object":"model","created":1792819567,"owned_by":"vllm",…,"max_model_len":65536,…}]}
165
+ ```
166
+
167
+ The `data` list in the JSON that the server sends has the id `qwen3.6-35b-a3b`. If `curl` cannot connect, make sure that
168
+ the server listens on `0.0.0.0`. Also make sure that no firewall stops port 8000.
169
+
170
+ ## Converge the Instance again
171
+
172
+ Run:
173
+
174
+ ```sh
175
+ jr2 up
176
+ ```
177
+
178
+ `jr2 up` reads the new config and converges the cluster again. The namespace is there, so it does not ask this time.
179
+
180
+ **Anthropic**
181
+
182
+ ```text
183
+ → .env: ANTHROPIC_API_KEY
184
+ jr2 up — instance "my-instance" → context kind-jr2 / namespace my-instance
185
+ …
186
+ warning: secrets[0] (ANTHROPIC_API_KEY) is named by nothing; goes nowhere — no workspace() lists it, no Agent's provider reads it, and no Effect names it (ADR-0059, ADR-0068)
187
+ …
188
+ converged — `jr2 run <workflow>` when ready
189
+ ```
190
+
191
+ The warning is correct for now. No [Workflow](../reference/glossary.md#workflow) has an Agent that names an `anthropic/`
192
+ model, so no pod gets the key.
193
+
194
+ The next page adds a Workflow with an Agent that names the model. On the next page, `jr2 up` gives the key to the
195
+ [Custodian](../reference/glossary.md#custodian) of the pod where the Agent works. Then it asks the model for one tool
196
+ call through a Custodian that holds the key, before it converges. It is the first `jr2 up` that reaches the model.
197
+
198
+ **Local**
199
+
200
+ ```text
201
+ → .env: LOCAL_MODEL_URL
202
+ jr2 up — instance "my-instance" → context kind-jr2 / namespace my-instance
203
+ …
204
+ provider: http://<address>:8000/v1 configured, but no carried Agent names a "local/…" model — skipped
205
+ …
206
+ converged — `jr2 run <workflow>` when ready
207
+ ```
208
+
209
+ `jr2 up` skips the check of the provider for now. No [Workflow](../reference/glossary.md#workflow) has an Agent that
210
+ names a `local/` model, so there is no model to check.
211
+
212
+ The next page adds a Workflow with an Agent that names the model. On the next page, `jr2 up` checks the endpoint before
213
+ it converges. It is the first `jr2 up` that reaches the model.
214
+
215
+ `jr2 up` published the new `jr2.config.ts` to the [Orchestrator](../reference/glossary.md#orchestrator) in the
216
+ [Assembly](../reference/glossary.md#assembly). The Orchestrator loaded it with no restart, so the port forward of
217
+ [Create an Instance](create-an-instance.md) stays open.
218
+
219
+ ## What happened
220
+
221
+ **Anthropic**
222
+
223
+ The API key is a [Held secret](../reference/glossary.md#held-secret). In this Instance, `jr2 up` gives its value only to
224
+ the Custodian of each pod whose Agents use an `anthropic/` model. The Custodian is a container next to the
225
+ [Harness](../reference/glossary.md#harness) container, where the Agent works. The Harness container holds only a
226
+ [Stand-in](../reference/glossary.md#stand-in): a value that is worth nothing outside the pod. The Custodian puts the
227
+ real key into each request to the Anthropic API. Thus the Agent never holds the key
228
+ ([ADR-0059](../reference/decisions/0059-a-harness-holds-stand-ins-and-the-custodian-holds-the-keys.md)).
229
+
230
+ To use a gateway or a different hosted provider, read
231
+ [Use a hosted provider or a gateway](../guides/use-a-hosted-provider.md).
232
+
233
+ **Local**
234
+
235
+ `harness.provider` adds a custom provider to the [Harness](../reference/glossary.md#harness). The Harness speaks to it
236
+ over the OpenAI chat completions API
237
+ ([ADR-0018](../reference/decisions/0018-instance-agents-are-definitions-jr2-assembles-the-harness.md)). When an Agent
238
+ names a `local/` model, `jr2 up` checks the endpoint from a pod in the cluster before it converges. It asks for the list
239
+ of models, and then for one tool call. If the check fails, `jr2 up` stops and says why.
240
+
241
+ This endpoint has no key, so jr2 permits plain `http://`. To add TLS and a key, read
242
+ [Use a local model](../guides/use-a-local-model.md).
243
+
244
+ [Secrets and trust](../concepts/secrets-and-trust.md) explains where each secret goes, and who can use it.
245
+
246
+ ## Next
247
+
248
+ [A model decides](a-model-decides.md).