tool-schemas.expected.json 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. {
  2. "initial": [
  3. {
  4. "name": "ask_user_question",
  5. "description": "Ask the user a concise question when you need confirmation, a choice, or missing information before proceeding. Send one or more questions, each with a stable id that will be echoed in the answer.",
  6. "parameters": {
  7. "type": "object",
  8. "properties": {
  9. "questions": {
  10. "type": "array",
  11. "description": "Questions to ask the user before continuing.",
  12. "items": {
  13. "type": "object",
  14. "additionalProperties": true,
  15. "properties": {
  16. "id": {
  17. "type": "string",
  18. "description": "Stable id for this question; echoed in the answer."
  19. },
  20. "question": {
  21. "type": "string",
  22. "description": "The specific question to ask the user."
  23. },
  24. "header": {
  25. "type": "string",
  26. "description": "Optional short heading for the question, such as \"Confirm\" or \"Choose Mode\"."
  27. },
  28. "options": {
  29. "type": "array",
  30. "description": "Optional choices to show the user. If you recommend one, put it first and append \"(Recommended)\" to that label.",
  31. "items": {
  32. "type": "object",
  33. "additionalProperties": true,
  34. "properties": {
  35. "label": {
  36. "type": "string",
  37. "description": "Short user-facing option label."
  38. },
  39. "description": {
  40. "type": "string",
  41. "description": "One sentence explaining the tradeoff or impact."
  42. }
  43. },
  44. "required": [
  45. "label"
  46. ]
  47. }
  48. },
  49. "multi_select": {
  50. "type": "boolean",
  51. "description": "Whether the user may select more than one option. Defaults to false."
  52. }
  53. },
  54. "required": [
  55. "id",
  56. "question"
  57. ]
  58. }
  59. }
  60. },
  61. "required": [
  62. "questions"
  63. ]
  64. }
  65. },
  66. {
  67. "name": "bash",
  68. "description": "Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under <mode> mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a task id immediately; read its output with `task_output` and stop it with `task_kill`. Attempting a command the sandbox may deny is safe and expected: run it and read the marker rather than assuming the denial. When a command is denied and a wider mode would let it succeed, escalate immediately in the same turn — the one sanctioned exception to a denial: retry the exact same command once with `sandbox_permissions` (the narrowest wider mode that suffices) plus a one-sentence `justification`. Do not detour through chat to ask permission first — the approval prompt raised by that retry is how the user consents. If the session states approval prompts are disabled, there is no exception: a denial is final — do not set `sandbox_permissions`. Never escalate speculatively: ground the request in a real denial — normally the one this command just hit; escalating up front is fine only when this session already denied the same access. A rejected escalation is final for that command — stop and explain, never work around it — but it does not forbid attempting or escalating other commands later.",
  69. "parameters": {
  70. "type": "object",
  71. "properties": {
  72. "command": {
  73. "type": "string",
  74. "description": "The bash command to execute."
  75. },
  76. "description": {
  77. "type": "string",
  78. "description": "Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\"."
  79. },
  80. "timeoutMs": {
  81. "type": "number",
  82. "description": "Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."
  83. },
  84. "workdir": {
  85. "type": "string",
  86. "description": "Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."
  87. },
  88. "run_in_background": {
  89. "type": "boolean",
  90. "description": "Run in the background and return a task id immediately (collect with task_output, stop with task_kill). No timeout applies."
  91. },
  92. "sandbox_permissions": {
  93. "type": "string",
  94. "description": "The wider sandbox mode this command needs. Only valid as a one-shot retry of a command the sandbox just denied; requires justification and user approval.",
  95. "enum": [
  96. "workspace-write",
  97. "danger-full-access"
  98. ]
  99. },
  100. "justification": {
  101. "type": "string",
  102. "description": "Required with sandbox_permissions: one sentence for the user explaining why this exact command needs the wider access."
  103. }
  104. },
  105. "required": [
  106. "command",
  107. "description"
  108. ]
  109. }
  110. },
  111. {
  112. "name": "create_goal",
  113. "description": "Create one persisted same-session completion goal when the current direct human request is a long-running objective that should continue across autonomous goal rounds. You may infer that intent without requiring the user to say \"create a goal\". Do not use this for trivial single-turn work. Execution rejects non-human and subagent authority.",
  114. "parameters": {
  115. "type": "object",
  116. "properties": {
  117. "objective": {
  118. "type": "string",
  119. "description": "The concrete completion objective inferred from the direct human request."
  120. },
  121. "max_goal_rounds": {
  122. "type": "number",
  123. "description": "Optional positive safe-integer limit on automatic continuation rounds."
  124. }
  125. },
  126. "required": [
  127. "objective"
  128. ]
  129. }
  130. },
  131. {
  132. "name": "edit",
  133. "description": "Edit an existing UTF-8 text file by replacing literal text.",
  134. "parameters": {
  135. "type": "object",
  136. "properties": {
  137. "file_path": {
  138. "type": "string",
  139. "description": "Path to edit, resolved by the filesystem backend."
  140. },
  141. "old_string": {
  142. "type": "string",
  143. "description": "Literal text to replace. Must match exactly."
  144. },
  145. "new_string": {
  146. "type": "string",
  147. "description": "Literal replacement text. Use an empty string to delete the match."
  148. },
  149. "replace_all": {
  150. "type": "boolean",
  151. "description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
  152. },
  153. "sandbox_permissions": {
  154. "type": "string",
  155. "description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
  156. "enum": [
  157. "workspace-write",
  158. "danger-full-access"
  159. ]
  160. },
  161. "justification": {
  162. "type": "string",
  163. "description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
  164. }
  165. },
  166. "required": [
  167. "file_path",
  168. "old_string",
  169. "new_string"
  170. ]
  171. }
  172. },
  173. {
  174. "name": "exit_plan_mode",
  175. "description": "Use only in plan mode. Present your plan for the user's review and, on approval, leave plan mode. Send the COMPLETE plan as markdown, starting with a # heading that names it. The user may approve (carry out the plan from your next step) or keep planning — their feedback comes back in the tool result; revise and present again.",
  176. "parameters": {
  177. "type": "object",
  178. "properties": {
  179. "plan": {
  180. "type": "string",
  181. "description": "The complete plan, as markdown, starting with a # heading that names it."
  182. }
  183. },
  184. "required": [
  185. "plan"
  186. ]
  187. }
  188. },
  189. {
  190. "name": "get_goal",
  191. "description": "Read the current same-session goal, including its exact id/revision, objective, phase, completed continuation rounds, round limit, blocker reason when present, and whether another continuation is armed. Call this before updating a goal.",
  192. "parameters": {
  193. "type": "object",
  194. "properties": {}
  195. }
  196. },
  197. {
  198. "name": "ralph",
  199. "description": "Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools.",
  200. "parameters": {
  201. "type": "object",
  202. "properties": {
  203. "objective": {
  204. "type": "string",
  205. "description": "The immutable completion objective for every fresh Ralph round."
  206. },
  207. "maxRounds": {
  208. "type": "number",
  209. "description": "Optional positive safe-integer round cap, bounded by the deployment ceiling."
  210. }
  211. },
  212. "required": [
  213. "objective"
  214. ]
  215. }
  216. },
  217. {
  218. "name": "read",
  219. "description": "Read a UTF-8 text file and return line-numbered content.",
  220. "parameters": {
  221. "type": "object",
  222. "properties": {
  223. "file_path": {
  224. "type": "string",
  225. "description": "Path to read, resolved by the filesystem backend."
  226. },
  227. "offset": {
  228. "type": "number",
  229. "description": "1-based first line to return. Defaults to 1."
  230. },
  231. "limit": {
  232. "type": "number",
  233. "description": "Maximum number of lines to return. Defaults to 2000."
  234. }
  235. },
  236. "required": [
  237. "file_path"
  238. ]
  239. }
  240. },
  241. {
  242. "name": "skill",
  243. "description": "Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.",
  244. "parameters": {
  245. "type": "object",
  246. "properties": {
  247. "name": {
  248. "type": "string",
  249. "description": "The exact skill name from the available skills list."
  250. }
  251. },
  252. "required": [
  253. "name"
  254. ]
  255. }
  256. },
  257. {
  258. "name": "subagent",
  259. "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) and return its final result. Use this to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent runs to completion and you receive only its final answer, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. Set `run_in_background: true` to return a task id; collect with `task_output` and stop with `task_kill`.",
  260. "parameters": {
  261. "type": "object",
  262. "properties": {
  263. "description": {
  264. "type": "string",
  265. "description": "A short (3-5 word) description of the delegated task, for display."
  266. },
  267. "prompt": {
  268. "type": "string",
  269. "description": "The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."
  270. },
  271. "run_in_background": {
  272. "type": "boolean",
  273. "description": "Run as a background task and return its id; collect with task_output or stop with task_kill."
  274. }
  275. },
  276. "required": [
  277. "description",
  278. "prompt"
  279. ]
  280. }
  281. },
  282. {
  283. "name": "subagent_fork",
  284. "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn), returning only its final result. Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive only its final answer, not its intermediate steps. Set `run_in_background: true` to return a task id; collect with `task_output` and stop with `task_kill`.",
  285. "parameters": {
  286. "type": "object",
  287. "properties": {
  288. "description": {
  289. "type": "string",
  290. "description": "A short (3-5 word) description of the delegated task, for display."
  291. },
  292. "prompt": {
  293. "type": "string",
  294. "description": "The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new."
  295. },
  296. "run_in_background": {
  297. "type": "boolean",
  298. "description": "Run as a background task and return its id; collect with task_output or stop with task_kill."
  299. }
  300. },
  301. "required": [
  302. "description",
  303. "prompt"
  304. ]
  305. }
  306. },
  307. {
  308. "name": "task_kill",
  309. "description": "Request cancellation of a running background task by task id. Returns immediately; the task settles as killed once its work actually stops.",
  310. "parameters": {
  311. "type": "object",
  312. "properties": {
  313. "task_id": {
  314. "type": "string",
  315. "description": "Task id returned by the tool that started the background work."
  316. },
  317. "reason": {
  318. "type": "string",
  319. "description": "Optional short reason, recorded in the log and forwarded to the task."
  320. }
  321. },
  322. "required": [
  323. "task_id"
  324. ]
  325. }
  326. },
  327. {
  328. "name": "task_list",
  329. "description": "List your background tasks (running and finished) with their ids, kinds, and statuses.",
  330. "parameters": {
  331. "type": "object",
  332. "properties": {}
  333. }
  334. },
  335. {
  336. "name": "task_output",
  337. "description": "Read a background task. Stream tasks return only output since the previous read; final-output tasks return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap.",
  338. "parameters": {
  339. "type": "object",
  340. "properties": {
  341. "task_id": {
  342. "type": "string",
  343. "description": "Task id returned by the tool that started the background work."
  344. },
  345. "wait": {
  346. "type": "boolean",
  347. "description": "Block until the task reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the task alive."
  348. },
  349. "timeout_ms": {
  350. "type": "number",
  351. "description": "Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum."
  352. }
  353. },
  354. "required": [
  355. "task_id"
  356. ]
  357. }
  358. },
  359. {
  360. "name": "todo_write",
  361. "description": "Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Keep AT MOST ONE todo `in_progress` at a time; while work remains, exactly one active task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished).",
  362. "parameters": {
  363. "type": "object",
  364. "properties": {
  365. "todos": {
  366. "type": "array",
  367. "description": "The COMPLETE task list, replacing any previous list.",
  368. "items": {
  369. "type": "object",
  370. "additionalProperties": true,
  371. "properties": {
  372. "content": {
  373. "type": "string",
  374. "description": "What the task is — a short imperative line."
  375. },
  376. "status": {
  377. "type": "string",
  378. "description": "pending (not started) | in_progress (now) | completed (done).",
  379. "enum": [
  380. "pending",
  381. "in_progress",
  382. "completed"
  383. ]
  384. }
  385. },
  386. "required": [
  387. "content",
  388. "status"
  389. ]
  390. }
  391. }
  392. },
  393. "required": [
  394. "todos"
  395. ]
  396. }
  397. },
  398. {
  399. "name": "update_goal",
  400. "description": "Update the exact current goal revision. edit, pause, and resume require a direct top-level human request. During an automatic continuation of the current goal, complete and blocked are also allowed. blocked is rejected before the configured minimum round count; the model remains responsible for judging that the same condition persisted across those rounds and must explain it in blocked_reason.",
  401. "parameters": {
  402. "type": "object",
  403. "properties": {
  404. "goal_id": {
  405. "type": "string",
  406. "description": "Exact id returned by get_goal."
  407. },
  408. "revision": {
  409. "type": "number",
  410. "description": "Exact positive revision returned by get_goal."
  411. },
  412. "action": {
  413. "type": "string",
  414. "description": "edit | pause | resume | complete | blocked",
  415. "enum": [
  416. "edit",
  417. "pause",
  418. "resume",
  419. "complete",
  420. "blocked"
  421. ]
  422. },
  423. "objective": {
  424. "type": "string",
  425. "description": "Replacement objective; valid only with action edit."
  426. },
  427. "max_goal_rounds": {
  428. "type": "number",
  429. "description": "Replacement cap; valid only with action edit."
  430. },
  431. "blocked_reason": {
  432. "type": "string",
  433. "description": "Concrete blocking condition; required only with action blocked."
  434. }
  435. },
  436. "required": [
  437. "goal_id",
  438. "revision",
  439. "action"
  440. ]
  441. }
  442. },
  443. {
  444. "name": "workflow",
  445. "description": "Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn.\n\nThe workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return <value>` — the value must be JSON-serializable and is this tool's result.\n\nScript-body hooks:\n- `agent(prompt, opts?): Promise<any>` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly.\n- `pipeline(items, ...stages): Promise<any[]>` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages.\n- `parallel(thunks): Promise<any[]>` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`.\n- `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim.\n\nMisused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`.\n\nConstraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes.",
  446. "parameters": {
  447. "type": "object",
  448. "properties": {
  449. "script": {
  450. "type": "string",
  451. "description": "The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return <json-value>`)."
  452. },
  453. "meta": {
  454. "type": "object",
  455. "description": "The workflow identity block (plain JSON — never code).",
  456. "additionalProperties": true,
  457. "properties": {
  458. "name": {
  459. "type": "string",
  460. "description": "Short kebab-case workflow name."
  461. },
  462. "description": {
  463. "type": "string",
  464. "description": "One-line description of what the workflow does."
  465. },
  466. "whenToUse": {
  467. "type": "string",
  468. "description": "Optional guidance on when this workflow applies."
  469. },
  470. "phases": {
  471. "type": "array",
  472. "description": "Optional phase declarations matched by phase() calls.",
  473. "items": {
  474. "type": "object",
  475. "additionalProperties": true,
  476. "properties": {
  477. "title": {
  478. "type": "string",
  479. "description": "The phase title phase() calls match by exact string."
  480. },
  481. "detail": {
  482. "type": "string",
  483. "description": "Optional one-line description of the phase."
  484. },
  485. "provider": {
  486. "type": "string",
  487. "description": "Optional provider override this phase is expected to use."
  488. },
  489. "model": {
  490. "type": "string",
  491. "description": "Optional model override this phase is expected to use."
  492. }
  493. },
  494. "required": [
  495. "title"
  496. ]
  497. }
  498. }
  499. },
  500. "required": [
  501. "name",
  502. "description"
  503. ]
  504. },
  505. "args": {
  506. "type": "object",
  507. "description": "Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}).",
  508. "additionalProperties": true
  509. }
  510. },
  511. "required": [
  512. "script",
  513. "meta"
  514. ]
  515. }
  516. },
  517. {
  518. "name": "write",
  519. "description": "Create or fully replace a UTF-8 text file.",
  520. "parameters": {
  521. "type": "object",
  522. "properties": {
  523. "file_path": {
  524. "type": "string",
  525. "description": "Path to write, resolved by the filesystem backend."
  526. },
  527. "content": {
  528. "type": "string",
  529. "description": "Full UTF-8 text content to write."
  530. },
  531. "sandbox_permissions": {
  532. "type": "string",
  533. "description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
  534. "enum": [
  535. "workspace-write",
  536. "danger-full-access"
  537. ]
  538. },
  539. "justification": {
  540. "type": "string",
  541. "description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
  542. }
  543. },
  544. "required": [
  545. "file_path",
  546. "content"
  547. ]
  548. }
  549. }
  550. ],
  551. "changes": [
  552. [
  553. {
  554. "name": "ask_user_question",
  555. "description": "Ask the user a concise question when you need confirmation, a choice, or missing information before proceeding. Send one or more questions, each with a stable id that will be echoed in the answer.",
  556. "parameters": {
  557. "type": "object",
  558. "properties": {
  559. "questions": {
  560. "type": "array",
  561. "description": "Questions to ask the user before continuing.",
  562. "items": {
  563. "type": "object",
  564. "additionalProperties": true,
  565. "properties": {
  566. "id": {
  567. "type": "string",
  568. "description": "Stable id for this question; echoed in the answer."
  569. },
  570. "question": {
  571. "type": "string",
  572. "description": "The specific question to ask the user."
  573. },
  574. "header": {
  575. "type": "string",
  576. "description": "Optional short heading for the question, such as \"Confirm\" or \"Choose Mode\"."
  577. },
  578. "options": {
  579. "type": "array",
  580. "description": "Optional choices to show the user. If you recommend one, put it first and append \"(Recommended)\" to that label.",
  581. "items": {
  582. "type": "object",
  583. "additionalProperties": true,
  584. "properties": {
  585. "label": {
  586. "type": "string",
  587. "description": "Short user-facing option label."
  588. },
  589. "description": {
  590. "type": "string",
  591. "description": "One sentence explaining the tradeoff or impact."
  592. }
  593. },
  594. "required": [
  595. "label"
  596. ]
  597. }
  598. },
  599. "multi_select": {
  600. "type": "boolean",
  601. "description": "Whether the user may select more than one option. Defaults to false."
  602. }
  603. },
  604. "required": [
  605. "id",
  606. "question"
  607. ]
  608. }
  609. }
  610. },
  611. "required": [
  612. "questions"
  613. ]
  614. }
  615. },
  616. {
  617. "name": "bash",
  618. "description": "Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under <mode> mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a task id immediately; read its output with `task_output` and stop it with `task_kill`. Attempting a command the sandbox may deny is safe and expected: run it and read the marker rather than assuming the denial. When a command is denied and a wider mode would let it succeed, escalate immediately in the same turn — the one sanctioned exception to a denial: retry the exact same command once with `sandbox_permissions` (the narrowest wider mode that suffices) plus a one-sentence `justification`. Do not detour through chat to ask permission first — the approval prompt raised by that retry is how the user consents. If the session states approval prompts are disabled, there is no exception: a denial is final — do not set `sandbox_permissions`. Never escalate speculatively: ground the request in a real denial — normally the one this command just hit; escalating up front is fine only when this session already denied the same access. A rejected escalation is final for that command — stop and explain, never work around it — but it does not forbid attempting or escalating other commands later.",
  619. "parameters": {
  620. "type": "object",
  621. "properties": {
  622. "command": {
  623. "type": "string",
  624. "description": "The bash command to execute."
  625. },
  626. "description": {
  627. "type": "string",
  628. "description": "Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\"."
  629. },
  630. "timeoutMs": {
  631. "type": "number",
  632. "description": "Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."
  633. },
  634. "workdir": {
  635. "type": "string",
  636. "description": "Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."
  637. },
  638. "run_in_background": {
  639. "type": "boolean",
  640. "description": "Run in the background and return a task id immediately (collect with task_output, stop with task_kill). No timeout applies."
  641. },
  642. "sandbox_permissions": {
  643. "type": "string",
  644. "description": "The wider sandbox mode this command needs. Only valid as a one-shot retry of a command the sandbox just denied; requires justification and user approval.",
  645. "enum": [
  646. "workspace-write",
  647. "danger-full-access"
  648. ]
  649. },
  650. "justification": {
  651. "type": "string",
  652. "description": "Required with sandbox_permissions: one sentence for the user explaining why this exact command needs the wider access."
  653. }
  654. },
  655. "required": [
  656. "command",
  657. "description"
  658. ]
  659. }
  660. },
  661. {
  662. "name": "create_goal",
  663. "description": "Create one persisted same-session completion goal when the current direct human request is a long-running objective that should continue across autonomous goal rounds. You may infer that intent without requiring the user to say \"create a goal\". Do not use this for trivial single-turn work. Execution rejects non-human and subagent authority.",
  664. "parameters": {
  665. "type": "object",
  666. "properties": {
  667. "objective": {
  668. "type": "string",
  669. "description": "The concrete completion objective inferred from the direct human request."
  670. },
  671. "max_goal_rounds": {
  672. "type": "number",
  673. "description": "Optional positive safe-integer limit on automatic continuation rounds."
  674. }
  675. },
  676. "required": [
  677. "objective"
  678. ]
  679. }
  680. },
  681. {
  682. "name": "edit",
  683. "description": "Edit an existing UTF-8 text file by replacing literal text.",
  684. "parameters": {
  685. "type": "object",
  686. "properties": {
  687. "file_path": {
  688. "type": "string",
  689. "description": "Path to edit, resolved by the filesystem backend."
  690. },
  691. "old_string": {
  692. "type": "string",
  693. "description": "Literal text to replace. Must match exactly."
  694. },
  695. "new_string": {
  696. "type": "string",
  697. "description": "Literal replacement text. Use an empty string to delete the match."
  698. },
  699. "replace_all": {
  700. "type": "boolean",
  701. "description": "Replace all matches. Defaults to false; when false, old_string must appear exactly once."
  702. },
  703. "sandbox_permissions": {
  704. "type": "string",
  705. "description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
  706. "enum": [
  707. "workspace-write",
  708. "danger-full-access"
  709. ]
  710. },
  711. "justification": {
  712. "type": "string",
  713. "description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
  714. }
  715. },
  716. "required": [
  717. "file_path",
  718. "old_string",
  719. "new_string"
  720. ]
  721. }
  722. },
  723. {
  724. "name": "exit_plan_mode",
  725. "description": "Use only in plan mode. Present your plan for the user's review and, on approval, leave plan mode. Send the COMPLETE plan as markdown, starting with a # heading that names it. The user may approve (carry out the plan from your next step) or keep planning — their feedback comes back in the tool result; revise and present again.",
  726. "parameters": {
  727. "type": "object",
  728. "properties": {
  729. "plan": {
  730. "type": "string",
  731. "description": "The complete plan, as markdown, starting with a # heading that names it."
  732. }
  733. },
  734. "required": [
  735. "plan"
  736. ]
  737. }
  738. },
  739. {
  740. "name": "get_goal",
  741. "description": "Read the current same-session goal, including its exact id/revision, objective, phase, completed continuation rounds, round limit, blocker reason when present, and whether another continuation is armed. Call this before updating a goal.",
  742. "parameters": {
  743. "type": "object",
  744. "properties": {}
  745. }
  746. },
  747. {
  748. "name": "ralph",
  749. "description": "Run a foreground fresh-agent Ralph loop toward one immutable objective. Use only when the direct human explicitly asks for Ralph or fresh-agent iteration. Each round opens a new child with no parent conversation or prior child session; the shared workspace is long-term memory, and only a bounded structured report crosses rounds. The call returns when a worker reports completion or a concrete blocker, or at the round limit. Ordinary long-running same-session work belongs to goal tools.",
  750. "parameters": {
  751. "type": "object",
  752. "properties": {
  753. "objective": {
  754. "type": "string",
  755. "description": "The immutable completion objective for every fresh Ralph round."
  756. },
  757. "maxRounds": {
  758. "type": "number",
  759. "description": "Optional positive safe-integer round cap, bounded by the deployment ceiling."
  760. }
  761. },
  762. "required": [
  763. "objective"
  764. ]
  765. }
  766. },
  767. {
  768. "name": "read",
  769. "description": "Read a UTF-8 text file and return line-numbered content.",
  770. "parameters": {
  771. "type": "object",
  772. "properties": {
  773. "file_path": {
  774. "type": "string",
  775. "description": "Path to read, resolved by the filesystem backend."
  776. },
  777. "offset": {
  778. "type": "number",
  779. "description": "1-based first line to return. Defaults to 1."
  780. },
  781. "limit": {
  782. "type": "number",
  783. "description": "Maximum number of lines to return. Defaults to 2000."
  784. }
  785. },
  786. "required": [
  787. "file_path"
  788. ]
  789. }
  790. },
  791. {
  792. "name": "skill",
  793. "description": "Load the full instructions for an available skill. Call this with the exact skill name from the session skill catalog before acting on a task that names or clearly matches that skill.",
  794. "parameters": {
  795. "type": "object",
  796. "properties": {
  797. "name": {
  798. "type": "string",
  799. "description": "The exact skill name from the available skills list."
  800. }
  801. },
  802. "required": [
  803. "name"
  804. ]
  805. }
  806. },
  807. {
  808. "name": "subagent",
  809. "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) and return its final result. Use this to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent runs to completion and you receive only its final answer, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation. Set `run_in_background: true` to return a task id; collect with `task_output` and stop with `task_kill`.",
  810. "parameters": {
  811. "type": "object",
  812. "properties": {
  813. "description": {
  814. "type": "string",
  815. "description": "A short (3-5 word) description of the delegated task, for display."
  816. },
  817. "prompt": {
  818. "type": "string",
  819. "description": "The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."
  820. },
  821. "run_in_background": {
  822. "type": "boolean",
  823. "description": "Run as a background task and return its id; collect with task_output or stop with task_kill."
  824. }
  825. },
  826. "required": [
  827. "description",
  828. "prompt"
  829. ]
  830. }
  831. },
  832. {
  833. "name": "subagent_fork",
  834. "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn), returning only its final result. Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive only its final answer, not its intermediate steps. Set `run_in_background: true` to return a task id; collect with `task_output` and stop with `task_kill`.",
  835. "parameters": {
  836. "type": "object",
  837. "properties": {
  838. "description": {
  839. "type": "string",
  840. "description": "A short (3-5 word) description of the delegated task, for display."
  841. },
  842. "prompt": {
  843. "type": "string",
  844. "description": "The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new."
  845. },
  846. "run_in_background": {
  847. "type": "boolean",
  848. "description": "Run as a background task and return its id; collect with task_output or stop with task_kill."
  849. }
  850. },
  851. "required": [
  852. "description",
  853. "prompt"
  854. ]
  855. }
  856. },
  857. {
  858. "name": "task_kill",
  859. "description": "Request cancellation of a running background task by task id. Returns immediately; the task settles as killed once its work actually stops.",
  860. "parameters": {
  861. "type": "object",
  862. "properties": {
  863. "task_id": {
  864. "type": "string",
  865. "description": "Task id returned by the tool that started the background work."
  866. },
  867. "reason": {
  868. "type": "string",
  869. "description": "Optional short reason, recorded in the log and forwarded to the task."
  870. }
  871. },
  872. "required": [
  873. "task_id"
  874. ]
  875. }
  876. },
  877. {
  878. "name": "task_list",
  879. "description": "List your background tasks (running and finished) with their ids, kinds, and statuses.",
  880. "parameters": {
  881. "type": "object",
  882. "properties": {}
  883. }
  884. },
  885. {
  886. "name": "task_output",
  887. "description": "Read a background task. Stream tasks return only output since the previous read; final-output tasks return their result after settlement. Every response ends with `[status: ...]`. Reads are non-blocking unless `wait: true`, which waits up to the configured cap.",
  888. "parameters": {
  889. "type": "object",
  890. "properties": {
  891. "task_id": {
  892. "type": "string",
  893. "description": "Task id returned by the tool that started the background work."
  894. },
  895. "wait": {
  896. "type": "boolean",
  897. "description": "Block until the task reaches a terminal status or the timeout expires. A timed-out wait returns [status: running] and leaves the task alive."
  898. },
  899. "timeout_ms": {
  900. "type": "number",
  901. "description": "Max wait in milliseconds (only meaningful with wait: true). Defaults to the configured wait timeout; capped by the configured maximum."
  902. }
  903. },
  904. "required": [
  905. "task_id"
  906. ]
  907. }
  908. },
  909. {
  910. "name": "todo_write",
  911. "description": "Record and update a structured task list for the current work. Send the ENTIRE list every call — it REPLACES the previous list (there are no partial updates, no per-item edits). Use it to plan multi-step work and show progress: add one todo per concrete step before you start. Keep AT MOST ONE todo `in_progress` at a time; while work remains, exactly one active task should be `in_progress`. Mark a todo `completed` the moment it is done (do not batch completions), and allow no `in_progress` item only once all work is complete. Skip the list for trivial single-step tasks. Statuses: `pending` (not started), `in_progress` (being worked on now), `completed` (finished).",
  912. "parameters": {
  913. "type": "object",
  914. "properties": {
  915. "todos": {
  916. "type": "array",
  917. "description": "The COMPLETE task list, replacing any previous list.",
  918. "items": {
  919. "type": "object",
  920. "additionalProperties": true,
  921. "properties": {
  922. "content": {
  923. "type": "string",
  924. "description": "What the task is — a short imperative line."
  925. },
  926. "status": {
  927. "type": "string",
  928. "description": "pending (not started) | in_progress (now) | completed (done).",
  929. "enum": [
  930. "pending",
  931. "in_progress",
  932. "completed"
  933. ]
  934. }
  935. },
  936. "required": [
  937. "content",
  938. "status"
  939. ]
  940. }
  941. }
  942. },
  943. "required": [
  944. "todos"
  945. ]
  946. }
  947. },
  948. {
  949. "name": "update_goal",
  950. "description": "Update the exact current goal revision. edit, pause, and resume require a direct top-level human request. During an automatic continuation of the current goal, complete and blocked are also allowed. blocked is rejected before the configured minimum round count; the model remains responsible for judging that the same condition persisted across those rounds and must explain it in blocked_reason.",
  951. "parameters": {
  952. "type": "object",
  953. "properties": {
  954. "goal_id": {
  955. "type": "string",
  956. "description": "Exact id returned by get_goal."
  957. },
  958. "revision": {
  959. "type": "number",
  960. "description": "Exact positive revision returned by get_goal."
  961. },
  962. "action": {
  963. "type": "string",
  964. "description": "edit | pause | resume | complete | blocked",
  965. "enum": [
  966. "edit",
  967. "pause",
  968. "resume",
  969. "complete",
  970. "blocked"
  971. ]
  972. },
  973. "objective": {
  974. "type": "string",
  975. "description": "Replacement objective; valid only with action edit."
  976. },
  977. "max_goal_rounds": {
  978. "type": "number",
  979. "description": "Replacement cap; valid only with action edit."
  980. },
  981. "blocked_reason": {
  982. "type": "string",
  983. "description": "Concrete blocking condition; required only with action blocked."
  984. }
  985. },
  986. "required": [
  987. "goal_id",
  988. "revision",
  989. "action"
  990. ]
  991. }
  992. },
  993. {
  994. "name": "workflow",
  995. "description": "Run a JavaScript workflow script that orchestrates subagents at scale. Use this for work that fans out across many independent pieces — an audit over many files, a migration, multi-angle research, adversarial verification of findings — where you write the orchestration as a script instead of delegating turn by turn.\n\nThe workflow's identity rides the `meta` parameter as JSON: required `name` (short kebab-case) and `description` strings, optional `whenToUse` string and `phases` array (`{title, detail?, provider?, model?}`). The `script` parameter is the plain JavaScript body ONLY (NOT TypeScript, and NO `export const meta` statement — meta is a parameter, not code), running with top-level await; end with `return <value>` — the value must be JSON-serializable and is this tool's result.\n\nScript-body hooks:\n- `agent(prompt, opts?): Promise<any>` — run one subagent to completion. Without `opts.schema` it resolves to the child's final text; with `opts.schema` (an object-rooted JSON Schema using ONLY type/properties/required/additionalProperties/items/enum/const/oneOf — no pattern/format/numeric bounds) it resolves to the validated object. Resolves `null` when the child fails (filter with `.filter(Boolean)`). Other opts: `label` (display), `phase` (progress group), and independent `provider`/`model` LLM target overrides (either may be provided alone). Anything else (`effort`/`isolation`/`agentType`) is rejected loudly.\n- `pipeline(items, ...stages): Promise<any[]>` — run each item through the stages independently with NO barrier between stages (prefer this for multi-stage work). Each stage receives `(prev, item, index)`. An ordinary stage throw drops that ITEM to `null` and skips its remaining stages.\n- `parallel(thunks): Promise<any[]>` — run zero-argument functions concurrently and await ALL of them (a barrier; use only when a stage genuinely needs every prior result together). A throwing thunk resolves to `null`.\n- `phase(title)` — start a progress phase; `log(message)` — narrate progress; `args` — the tool call's `args` input, verbatim.\n\nMisused hooks (bad arguments, unknown options, unsupported schemas, tripped caps) throw errors that ALWAYS kill the script — they never dissolve into a per-item `null`.\n\nConstraints: concurrency and total-agent caps apply; no filesystem, network, timers, or Node.js APIs are provided — the agents do the work, the script only coordinates them. The run executes in the foreground: this call returns when the whole script finishes.",
  996. "parameters": {
  997. "type": "object",
  998. "properties": {
  999. "script": {
  1000. "type": "string",
  1001. "description": "The plain-JS workflow script body (top-level await allowed; NO `export const meta` statement; end with `return <json-value>`)."
  1002. },
  1003. "meta": {
  1004. "type": "object",
  1005. "description": "The workflow identity block (plain JSON — never code).",
  1006. "additionalProperties": true,
  1007. "properties": {
  1008. "name": {
  1009. "type": "string",
  1010. "description": "Short kebab-case workflow name."
  1011. },
  1012. "description": {
  1013. "type": "string",
  1014. "description": "One-line description of what the workflow does."
  1015. },
  1016. "whenToUse": {
  1017. "type": "string",
  1018. "description": "Optional guidance on when this workflow applies."
  1019. },
  1020. "phases": {
  1021. "type": "array",
  1022. "description": "Optional phase declarations matched by phase() calls.",
  1023. "items": {
  1024. "type": "object",
  1025. "additionalProperties": true,
  1026. "properties": {
  1027. "title": {
  1028. "type": "string",
  1029. "description": "The phase title phase() calls match by exact string."
  1030. },
  1031. "detail": {
  1032. "type": "string",
  1033. "description": "Optional one-line description of the phase."
  1034. },
  1035. "provider": {
  1036. "type": "string",
  1037. "description": "Optional provider override this phase is expected to use."
  1038. },
  1039. "model": {
  1040. "type": "string",
  1041. "description": "Optional model override this phase is expected to use."
  1042. }
  1043. },
  1044. "required": [
  1045. "title"
  1046. ]
  1047. }
  1048. }
  1049. },
  1050. "required": [
  1051. "name",
  1052. "description"
  1053. ]
  1054. },
  1055. "args": {
  1056. "type": "object",
  1057. "description": "Optional JSON input exposed to the script as the `args` global (wrap a bare list as a field, e.g. {\"files\": [...]}).",
  1058. "additionalProperties": true
  1059. }
  1060. },
  1061. "required": [
  1062. "script",
  1063. "meta"
  1064. ]
  1065. }
  1066. },
  1067. {
  1068. "name": "write",
  1069. "description": "Create or fully replace a UTF-8 text file.",
  1070. "parameters": {
  1071. "type": "object",
  1072. "properties": {
  1073. "file_path": {
  1074. "type": "string",
  1075. "description": "Path to write, resolved by the filesystem backend."
  1076. },
  1077. "content": {
  1078. "type": "string",
  1079. "description": "Full UTF-8 text content to write."
  1080. },
  1081. "sandbox_permissions": {
  1082. "type": "string",
  1083. "description": "The wider sandbox mode this file operation needs. Only valid as a one-shot retry of an operation the sandbox just denied; requires justification and user approval.",
  1084. "enum": [
  1085. "workspace-write",
  1086. "danger-full-access"
  1087. ]
  1088. },
  1089. "justification": {
  1090. "type": "string",
  1091. "description": "Required with sandbox_permissions: one sentence for the user explaining why this exact file operation needs the wider access."
  1092. }
  1093. },
  1094. "required": [
  1095. "file_path",
  1096. "content"
  1097. ]
  1098. }
  1099. }
  1100. ]
  1101. ]
  1102. }