@markusylisiurunen/tau 0.3.93 → 0.3.95

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 (150) hide show
  1. package/dist/code_mode/command.js +3 -1
  2. package/dist/code_mode/command.js.map +1 -1
  3. package/dist/code_mode/output.d.ts +3 -0
  4. package/dist/code_mode/output.js +8 -2
  5. package/dist/code_mode/output.js.map +1 -1
  6. package/dist/code_mode/runtime.d.ts +7 -1
  7. package/dist/code_mode/runtime.js +18 -14
  8. package/dist/code_mode/runtime.js.map +1 -1
  9. package/dist/core/code_mode/agents.js +434 -0
  10. package/dist/core/code_mode/agents.js.map +1 -0
  11. package/dist/core/code_mode/bash.js +14 -17
  12. package/dist/core/code_mode/bash.js.map +1 -1
  13. package/dist/core/code_mode/history.js +1 -0
  14. package/dist/core/code_mode/history.js.map +1 -1
  15. package/dist/core/code_mode/models.js +27 -4
  16. package/dist/core/code_mode/models.js.map +1 -1
  17. package/dist/core/code_mode/sdk.js +6 -0
  18. package/dist/core/code_mode/sdk.js.map +1 -1
  19. package/dist/core/config/content_loader.js +3 -13
  20. package/dist/core/config/content_loader.js.map +1 -1
  21. package/dist/core/config/schema.js.map +1 -1
  22. package/dist/core/debug.js +2 -2
  23. package/dist/core/debug.js.map +1 -1
  24. package/dist/core/history/history_manager.js +7 -4
  25. package/dist/core/history/history_manager.js.map +1 -1
  26. package/dist/core/index.js +0 -4
  27. package/dist/core/index.js.map +1 -1
  28. package/dist/core/mcp/manager.js +7 -0
  29. package/dist/core/mcp/manager.js.map +1 -1
  30. package/dist/core/models/openrouter.js +25 -1
  31. package/dist/core/models/openrouter.js.map +1 -1
  32. package/dist/core/personas.js +3 -11
  33. package/dist/core/personas.js.map +1 -1
  34. package/dist/core/runtime/chat_runtime.js +11 -10
  35. package/dist/core/runtime/chat_runtime.js.map +1 -1
  36. package/dist/core/runtime/session_prompt_composer.js +9 -8
  37. package/dist/core/runtime/session_prompt_composer.js.map +1 -1
  38. package/dist/core/static/code_mode/history/documentation.md +2 -1
  39. package/dist/core/static/code_mode/sandbox_runner.mjs +4 -0
  40. package/dist/core/static/index.js +18 -5
  41. package/dist/core/static/index.js.map +1 -1
  42. package/dist/core/static/prompts/subagent-prefix.md +17 -0
  43. package/dist/core/static/tau_docs/client-tools.md +4 -0
  44. package/dist/core/static/tau_docs/code-mode.md +77 -0
  45. package/dist/core/static/tau_docs/config-reference.md +4 -2
  46. package/dist/core/static/tau_docs/history.md +5 -3
  47. package/dist/core/static/tau_docs/index.md +2 -1
  48. package/dist/core/static/tau_docs/manifest.json +1 -0
  49. package/dist/core/static/tau_docs/node-sdk.md +2 -0
  50. package/dist/core/static/tau_docs/openrouter.md +2 -0
  51. package/dist/core/static/tau_docs/pdf-unpacking.md +1 -1
  52. package/dist/core/static/tau_docs/personas.md +4 -5
  53. package/dist/core/static/tau_docs/prompts-and-project-context.md +1 -1
  54. package/dist/core/static/tau_docs/security.md +1 -1
  55. package/dist/core/static/tau_docs/sessions.md +1 -1
  56. package/dist/core/static/tau_docs/subagents.md +106 -27
  57. package/dist/core/static/tau_docs/telegram.md +20 -2
  58. package/dist/core/static/tau_docs/tools.md +32 -62
  59. package/dist/core/static/tau_docs/troubleshooting.md +2 -2
  60. package/dist/core/subagents/agent_supervisor.js +185 -339
  61. package/dist/core/subagents/agent_supervisor.js.map +1 -1
  62. package/dist/core/subagents/claude_code_protocol.js +4 -0
  63. package/dist/core/subagents/claude_code_protocol.js.map +1 -1
  64. package/dist/core/subagents/claude_code_runner.js +134 -11
  65. package/dist/core/subagents/claude_code_runner.js.map +1 -1
  66. package/dist/core/subagents/claude_code_runner.mjs +80 -77
  67. package/dist/core/subagents/claude_code_runtime.js +250 -9
  68. package/dist/core/subagents/claude_code_runtime.js.map +1 -1
  69. package/dist/core/subagents/errors.js +18 -0
  70. package/dist/core/subagents/errors.js.map +1 -0
  71. package/dist/core/subagents/events.js +25 -0
  72. package/dist/core/subagents/events.js.map +1 -0
  73. package/dist/core/subagents/format.js +2 -98
  74. package/dist/core/subagents/format.js.map +1 -1
  75. package/dist/core/subagents/native_subagent_runtime.js +270 -0
  76. package/dist/core/subagents/native_subagent_runtime.js.map +1 -0
  77. package/dist/core/subagents/prompt.js +3 -5
  78. package/dist/core/subagents/prompt.js.map +1 -1
  79. package/dist/core/subagents/registry.js +5 -3
  80. package/dist/core/subagents/registry.js.map +1 -1
  81. package/dist/core/subagents/runtime.js +13 -0
  82. package/dist/core/subagents/runtime.js.map +1 -0
  83. package/dist/core/subagents/trace.js +149 -0
  84. package/dist/core/subagents/trace.js.map +1 -0
  85. package/dist/core/telegram/adapter.js +40 -6
  86. package/dist/core/telegram/adapter.js.map +1 -1
  87. package/dist/core/telegram/config.js +6 -0
  88. package/dist/core/telegram/config.js.map +1 -1
  89. package/dist/core/telegram/runtime.js +1 -0
  90. package/dist/core/telegram/runtime.js.map +1 -1
  91. package/dist/core/tools/agent_jobs.js +51 -0
  92. package/dist/core/tools/agent_jobs.js.map +1 -0
  93. package/dist/core/tools/background_jobs.js +205 -0
  94. package/dist/core/tools/background_jobs.js.map +1 -0
  95. package/dist/core/tools/bash.js +11 -45
  96. package/dist/core/tools/bash.js.map +1 -1
  97. package/dist/core/tools/bash_jobs.js +44 -238
  98. package/dist/core/tools/bash_jobs.js.map +1 -1
  99. package/dist/core/tools/catalog.js +37 -72
  100. package/dist/core/tools/catalog.js.map +1 -1
  101. package/dist/core/tools/code.js +177 -54
  102. package/dist/core/tools/code.js.map +1 -1
  103. package/dist/core/tools/code_jobs.js +128 -0
  104. package/dist/core/tools/code_jobs.js.map +1 -0
  105. package/dist/core/tools/code_mode.js +88 -101
  106. package/dist/core/tools/code_mode.js.map +1 -1
  107. package/dist/core/tools/code_mode_worker.js +13 -7
  108. package/dist/core/tools/code_mode_worker.js.map +1 -1
  109. package/dist/core/tools/job_output.js +53 -0
  110. package/dist/core/tools/job_output.js.map +1 -0
  111. package/dist/core/tools/output_file.js +38 -0
  112. package/dist/core/tools/output_file.js.map +1 -0
  113. package/dist/core/tools/presentation.js +19 -9
  114. package/dist/core/tools/presentation.js.map +1 -1
  115. package/dist/core/tools/tool_names.js +8 -6
  116. package/dist/core/tools/tool_names.js.map +1 -1
  117. package/dist/core/tools/wait_for_agents.js +41 -33
  118. package/dist/core/tools/wait_for_agents.js.map +1 -1
  119. package/dist/core/version.js +1 -1
  120. package/dist/diff_tool/app/dist/assets/{core-DaUcjNBm.js → core-NkxL1yZC.js} +1 -1
  121. package/dist/diff_tool/app/dist/assets/{github-dark-default-adAWTKmX.js → github-dark-default-CM8LCIj6.js} +1 -1
  122. package/dist/diff_tool/app/dist/assets/highlights-Coi8xHW0.js +3 -0
  123. package/dist/diff_tool/app/dist/assets/index-Jt-l2Q96.js +205 -0
  124. package/dist/diff_tool/app/dist/assets/langs-qJAo26KT.js +1 -0
  125. package/dist/diff_tool/app/dist/assets/{loader-DrMMfKhl.js → loader-DYYMIDWx.js} +1 -1
  126. package/dist/diff_tool/app/dist/assets/{shiki-BDtWTy6K.js → shiki-B8l9Ufae.js} +2 -2
  127. package/dist/diff_tool/app/dist/assets/{stream-tokenizer-Dpnp6Te1.js → stream-tokenizer-h1lwRQEk.js} +1 -1
  128. package/dist/diff_tool/app/dist/assets/{themes-snQUZ0v5.js → themes-D3P9yN9_.js} +2 -2
  129. package/dist/diff_tool/app/dist/index.html +1 -1
  130. package/dist/host/hosted_ephemeral_agent_session.js +13 -3
  131. package/dist/host/hosted_ephemeral_agent_session.js.map +1 -1
  132. package/dist/host/local_session_host.js +5 -5
  133. package/dist/host/local_session_host.js.map +1 -1
  134. package/dist/sdk/code_mode.js +2 -2
  135. package/dist/sdk/code_mode.js.map +1 -1
  136. package/dist/store/session_snapshot_migrations.js +27 -1
  137. package/dist/store/session_snapshot_migrations.js.map +1 -1
  138. package/package.json +6 -6
  139. package/dist/core/static/prompts/subagent-wrapper.md +0 -20
  140. package/dist/core/tools/interrupt_agent.js +0 -142
  141. package/dist/core/tools/interrupt_agent.js.map +0 -1
  142. package/dist/core/tools/list_agents.js +0 -85
  143. package/dist/core/tools/list_agents.js.map +0 -1
  144. package/dist/core/tools/send_input_to_agent.js +0 -177
  145. package/dist/core/tools/send_input_to_agent.js.map +0 -1
  146. package/dist/core/tools/spawn_agent.js +0 -275
  147. package/dist/core/tools/spawn_agent.js.map +0 -1
  148. package/dist/diff_tool/app/dist/assets/highlights-ey_YWY7Q.js +0 -3
  149. package/dist/diff_tool/app/dist/assets/index-B7CqEx6P.js +0 -202
  150. package/dist/diff_tool/app/dist/assets/langs-BAlu0Oiy.js +0 -1
@@ -6,7 +6,7 @@ Tau ships built-in personas and loads custom persona files from the execution en
6
6
 
7
7
  ## Built-in and effective personas
8
8
 
9
- Built-in personas are generated from Tau's current model catalog. Most model families have separate chat and coder variants, and some have only the variants Tau supports. Built-ins come with Tau's own prompts, defaults, tool selections, and subagent tools.
9
+ Built-in personas are generated from Tau's current model catalog. Most model families have separate chat and coder variants, and some have only the variants Tau supports. Built-ins come with Tau's own prompts, defaults, tool selections, and subagent access.
10
10
 
11
11
  The Opus 5.5 chat and coder personas are available only when `anthropic/claude-opus-5-5` is present in the effective model catalog. The Sonnet 5.5 variants (`sonnet-5.5-chat` and `sonnet-5.5-coder`) likewise require `anthropic/claude-sonnet-5-5`.
12
12
 
@@ -93,14 +93,13 @@ Each custom persona is complete on its own. It does not inherit a provider, mode
93
93
  | `allowedReasoningLevels` | Array of reasoning efforts offered by the TUI selector. |
94
94
  | `tools` | List of persona-selectable tools. |
95
95
 
96
- Every persona can use all discovered skills. If a custom persona omits `tools`, Tau enables the standard tools and the subagent tools. A `tools` list without `spawn_agent` prevents the agent from starting subagents. See [skills](skills.md) and [subagents](subagents.md) for those contracts.
96
+ Every persona can use all discovered skills. If a custom persona omits `tools`, Tau enables the standard tools and `agents`. A `tools` list without `agents` prevents the agent from starting or managing subagents. See [skills](skills.md) and [subagents](subagents.md) for those contracts.
97
97
 
98
98
  The selectable tool names are:
99
99
 
100
- - `bash`, `write`, `edit`, `view_image`, `web`, `history`, `mcp`, and `models`;
101
- - `spawn_agent`, `send_input_to_agent`, `wait_for_agents`, `list_agents`, and `interrupt_agent`.
100
+ `bash`, `write`, `edit`, `view_image`, `web`, `history`, `mcp`, `models`, and `agents`.
102
101
 
103
- Names such as `web`, `history`, `mcp`, and `models` enable capabilities inside the `code` tool, and `bash` also enables `tau.bash`. Tau builds the `code` tool from whichever of these capabilities are selected and usable.
102
+ Names such as `web`, `history`, `mcp`, and `models` enable capabilities inside the `code` tool, and `bash` also enables `tau.bash`. `agents` enables `tau.agents` inside `code` and the `wait_for_agents` tool. Tau builds the `code` tool from whichever of these capabilities are selected and usable.
104
103
 
105
104
  A `tools` list replaces the defaults. Names are lowercased and duplicates removed. An unknown name makes the persona invalid. `tools: []` gives the persona none of these tools. The built-in `tau_docs` tool is always available, independent of this list. `mcp` works only when the host has enabled MCP servers. [Tools](tools.md) explains eligibility and ownership.
106
105
 
@@ -111,7 +111,7 @@ The option works for local TUI sessions and for hosts started with `tau serve`.
111
111
 
112
112
  ## Alternate subagent working directories
113
113
 
114
- A subagent normally uses the parent session's working directory and context. When `spawn_agent` sets a different `workingDirectory`, Tau rebuilds the parts of the context that depend on the directory:
114
+ A subagent normally uses the parent session's working directory and context. When `tau.agents.spawn` sets a different `workingDirectory`, Tau rebuilds the parts of the context that depend on the directory:
115
115
 
116
116
  - environment and repository details
117
117
  - the applicable `AGENTS.md` files
@@ -104,7 +104,7 @@ The TUI's built-in diff review tool also runs as a process on the client machine
104
104
 
105
105
  ## Use code mode as a capability boundary
106
106
 
107
- JavaScript written by the model for `code` and code-mode client tools runs in a restricted sandbox. It receives only the declared capabilities, `docs`, `printText`, the async `printImage`, the `truncate` and `truncateLines` helpers, the real `Date`, and `Math.random()`. It has no imports, processes, environment variables, credentials, timers, fetch, files, or network access of its own. When Bash is selected, `tau.bash` runs commands with the same permissions as the Bash tool, and the sandbox does not limit what those commands do.
107
+ JavaScript written by the model for `code` and code-mode client tools runs in a restricted sandbox. It receives only the declared capabilities, `docs`, the JSON `input` value, `printText`, the async `printImage`, the `truncate` and `truncateLines` helpers, the real `Date`, and `Math.random()`. It has no imports, processes, environment variables, credentials, timers, fetch, files, or network access of its own. When Bash is selected, `tau.bash` runs commands with the same permissions as the Bash tool, and the sandbox does not limit what those commands do.
108
108
 
109
109
  The API behind each capability runs outside the sandbox, with whatever access the tool gives it. The sandbox limits the model's code to the declared capabilities, but a capability that is too powerful is still dangerous. Tool authors should validate every argument, offer narrow operations, keep credentials outside the sandbox, honor cancellation, and never return secrets.
110
110
 
@@ -25,7 +25,7 @@ Three parts can run on one machine but stay separate:
25
25
 
26
26
  The host saves sessions under `~/.config/tau/sessions` in the host user's home. These are versioned files that Tau manages. Never edit them directly. Use Tau's session operations, project configuration, and recovery instead.
27
27
 
28
- [Background Bash jobs](tools.md#bash) belong to the session. They survive turns, interruption, and clients detaching. A running job keeps a session loaded even when no client is attached, and does not block new turns. Jobs stop when the session is closed normally or the host shuts down, and are not restored after a restart. Cleanup after a crash or forced kill is not guaranteed.
28
+ [Background Bash jobs](tools.md#bash) and [background code jobs](code-mode.md#background-code-jobs) belong to the agent that started them, and other agents in the session cannot see them. They survive turns, interruption, and clients detaching. A running job keeps a session loaded even when no client is attached, and does not block new turns. Every agent's jobs stop when the session is closed normally or the host shuts down, and are not restored after a restart. Cleanup after a crash or forced kill is not guaranteed.
29
29
 
30
30
  ## Submit, queue, and steer
31
31
 
@@ -6,13 +6,13 @@ Subagents are background agents that the main agent starts and the host supervis
6
6
 
7
7
  Subagents are general-purpose workers. There are no named types. Several can run at once, each with its own task and conversation.
8
8
 
9
- A native Tau subagent behaves like the active main persona, wrapped in instructions that Tau maintains. Those instructions and the subagent's description cannot be configured. Put task-specific instructions, including any relevant skill guidance, in the launch prompt.
9
+ A native Tau subagent works like a main agent of the active persona in the subagent's working directory. Its system prompt is the one a main agent would get there, with the same persona prompt, skills, project instructions, and environment context. Tau adds a short section in front that explains the subagent's role: work headless on the part of the main agent's task given in the assignment, treat later messages as coming from the main agent, wait for background work its answer depends on, never start other agents, leave contact with the user to the main agent, and return a self-contained result. The section also gives the parent session's ID. This section cannot be configured. Put task-specific instructions in the launch prompt.
10
10
 
11
- Whether the agent can start subagents depends on the main persona's tool list. Built-in personas, and custom personas that omit `tools`, enable all five subagent tools. A custom persona with a `tools` list that lacks `spawn_agent` cannot start subagents. Leave out all five subagent tools when no subagent interaction is wanted. There is no other setting to turn subagents on or off. See [personas](personas.md).
11
+ Whether the agent can start subagents depends on the main persona's tool list. The `agents` tool name enables `tau.agents` in the `code` tool and the `wait_for_agents` tool. Built-in personas, and custom personas that omit `tools`, include it. A custom persona with a `tools` list that lacks `agents` cannot start or manage subagents. There is no other setting to turn subagents on or off. See [personas](personas.md).
12
12
 
13
13
  ## Trigger sensitivity
14
14
 
15
- The main agent starts subagents only when the user or active instructions explicitly ask for delegation. Ask in ordinary language; no special tag is needed. The request itself does not create a subagent: the main agent still has to call `spawn_agent`.
15
+ The main agent starts subagents only when the user or active instructions explicitly ask for delegation. Ask in ordinary language; no special tag is needed. The request itself does not create a subagent: the main agent still has to call `tau.agents.spawn`.
16
16
 
17
17
  The agent follows this rule itself. Tau checks that a launch is valid, but it does not judge whether the request really asked for delegation.
18
18
 
@@ -29,9 +29,11 @@ A native Tau subagent can receive these tools. [Claude Code subagents](#claude-c
29
29
  - `mcp`, when the host has enabled MCP servers
30
30
  - `models`
31
31
 
32
- A subagent gets each of these that the main persona also has. For example, a main persona with `bash`, `edit`, `history`, and `spawn_agent` gives its subagents `bash`, `edit`, and `history`. Names such as `web` and `history` enable the matching capability in the subagent's `code` tool. MCP uses the host's existing connections, whatever the subagent's working directory. There is no separate tool list for subagents.
32
+ A subagent gets each of these that the main persona also has. For example, a main persona with `bash`, `edit`, `history`, and `agents` gives its subagents `bash`, `edit`, and `history`. Names such as `web` and `history` enable the matching capability in the subagent's `code` tool. MCP uses the host's existing connections, whatever the subagent's working directory. There is no separate tool list for subagents.
33
33
 
34
- Every native Tau subagent also gets the built-in `tau_docs` tool, and a persona's `tools` list cannot remove it. Subagents never get the subagent tools, client tools, or TUI tools, so a subagent cannot start subagents of its own. See [tools](tools.md) for how tool availability works in general.
34
+ Every native Tau subagent also gets the built-in `tau_docs` tool, and a persona's `tools` list cannot remove it. Subagents never get `agents`: their `code` tool has no `tau.agents`, and they have no `wait_for_agents`. A subagent cannot start or manage other agents.
35
+
36
+ Subagents also never get [client tools](client-tools.md), such as the TUI's tools or a Telegram runner's file delivery tools. Only the main agent uses tools that attached clients offer. See [tools](tools.md) for how tool availability works in general.
35
37
 
36
38
  ## Models and settings
37
39
 
@@ -45,7 +47,7 @@ A model override uses this exact form:
45
47
 
46
48
  The provider is lowercased. The model ID is kept exactly as written and is case-sensitive. Effort is one of `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max`.
47
49
 
48
- The configured list of launch models is an allowlist. It does not choose a default. The main agent should normally omit the `model` argument to `spawn_agent`, and the subagent then uses the active persona's model and reasoning. When `model` is given, it must exactly match an allowlist entry after normalization. For native Tau subagents, the override changes the provider, model, and reasoning, and keeps the other settings.
50
+ The configured list of launch models is an allowlist. It does not choose a default. The main agent should normally omit the `model` option of `tau.agents.spawn`, and the subagent then uses the active persona's model and reasoning. When `model` is given, it must exactly match an allowlist entry after normalization. For native Tau subagents, the override changes the provider, model, and reasoning, and keeps the other settings.
49
51
 
50
52
  A model ID may be missing from the catalog if its provider is known (see [models](models.md)). An entry with an invalid provider, model, effort, or format makes the configuration field invalid. Duplicate entries are removed.
51
53
 
@@ -64,13 +66,13 @@ Configure the allowlist with `subagents.launchModels` in `config.json`:
64
66
  }
65
67
  ```
66
68
 
67
- The nearest `launchModels` list replaces broader ones; lists are not combined. The resulting list applies to every persona that has `spawn_agent`.
69
+ The nearest `launchModels` list replaces broader ones; lists are not combined. The resulting list applies to every persona that has `agents`.
68
70
 
69
71
  ## Claude Code subagents
70
72
 
71
- The `claude-code` launch provider runs Claude Code through Anthropic's Agent SDK. The main agent uses the usual spawn, list, wait, follow-up, and interrupt tools to manage these workers. Claude Code models are available only as explicit subagent launch overrides.
73
+ The `claude-code` launch provider runs Claude Code through Anthropic's Agent SDK. The main agent manages these workers with the same `tau.agents` methods and `wait_for_agents` tool as native Tau subagents. Claude Code models are available only as explicit subagent launch overrides.
72
74
 
73
- Install Claude Code on the session's execution environment, put `claude` on its login-shell `PATH`, and sign in there with a Claude subscription. A login on the host or attached laptop does not reach a separate execution environment. Tau includes Agent SDK 0.3.308, so no separate SDK installation is needed.
75
+ Install Claude Code on the session's execution environment, put `claude` on its login-shell `PATH`, and sign in there with a Claude subscription. A login on the host or attached laptop does not reach a separate execution environment. Tau includes Agent SDK 0.3.312, so no separate SDK installation is needed.
74
76
 
75
77
  Add the desired model/effort combinations to the launch allowlist:
76
78
 
@@ -90,7 +92,7 @@ These are the three supported model IDs. Effort may be `low`, `medium`, `high`,
90
92
 
91
93
  Claude Code manages its conversation, retries, and compaction. Each run allows up to 1,024 agentic turns. Tau passes the selected model, effort, working directory, and task. Other Tau model settings, such as service tier, do not apply. Follow-ups resume the same Claude session.
92
94
 
93
- The worker uses Claude Code's native system prompt with a short addition: complete the task autonomously, preserve other agents' work, and return a self-contained result. It cannot ask the parent or user for clarification. Tau does not copy the parent conversation, persona prompt, project instructions, or skill descriptions. The worker is instructed to follow applicable project instructions itself.
95
+ The worker uses Claude Code's native system prompt with a short addition: complete the task autonomously, treat later messages as coming from the parent agent, preserve other agents' work, and return a self-contained result. It cannot ask the parent or user for clarification. Tau does not copy the parent conversation, persona prompt, project instructions, or skill descriptions. The worker is instructed to follow applicable project instructions itself.
94
96
 
95
97
  Claude Code loads its user, project, and local settings and discovers its own instructions and skills. The `Skill` tool is always available. Other native tools follow the parent persona's selection:
96
98
 
@@ -106,15 +108,17 @@ Workers receive no Tau `code` capabilities, host MCP connections, `tau_docs`, or
106
108
 
107
109
  Selected tools use `bypassPermissions`, with Claude Code's sandbox disabled. They run with the execution environment's operating-system authority, like Tau's tools. Review the local Claude settings, skills, and MCP configuration before enabling these workers.
108
110
 
109
- Tau displays short assistant updates and tool completion summaries. Full tool output stays in Claude Code's conversation files. Tau records SDK-reported assistant token usage as it arrives, so interruption preserves counts already received. Repeated message blocks and resumed messages are counted once. Final SDK totals reconcile these counts and supply cost estimates, including earlier usage when a session resumes. Cost from an interrupted run remains unavailable until the SDK reports it. The latest assistant usage supplies a context-token estimate; after a successful run, the SDK's context summary supplies the window size and a fuller measurement.
111
+ Tau displays short assistant updates and tool completion summaries. It also records the worker's assistant text, tool calls, and tool results in the worker's [trace](#conversation-traces), using Claude Code's own tool names, such as `Bash` and `Read`. Tau records SDK-reported assistant token usage as it arrives, so interruption preserves counts already received. Repeated message blocks and resumed messages are counted once. Final SDK totals reconcile these counts and supply cost estimates, including earlier usage when a session resumes. Cost from an interrupted run remains unavailable until the SDK reports it. The latest assistant usage supplies a context-token estimate; after a successful run, the SDK's context summary supplies the window size and a fuller measurement.
110
112
 
111
113
  Before sending the task, Tau checks that the SDK reports a subscription login without API-key authentication. Claude Code keeps its own credentials. Tau removes API and cloud-provider routing overrides from the child environment and provides no API fallback. Fast mode is disabled. Account-level extra usage can still incur charges; disable it in Claude to use only the included subscription allowance. The SDK's dollar estimates do not report subscription charges.
112
114
 
115
+ Steering messages go to Claude Code through the Agent SDK's streaming input while the worker is busy. Claude Code decides when to read them, typically between tool rounds, and a tool that is already running may continue. A steering message that Claude Code has not read when its turn ends is handled in another turn. Queued messages wait until Claude Code reports that its turn is finished.
116
+
113
117
  Claude workers share the eight-worker limit and the usual subagent lifetime. Interrupting a worker terminates its process group. A follow-up can resume its Claude session while the parent session remains alive. Host restart, session disposal, and rewind remove workers under the same rules as native Tau subagents. Claude's transcript files remain on disk, but Tau does not use them to restore workers after a restart.
114
118
 
115
119
  ## Working directory
116
120
 
117
- `spawn_agent` normally runs the subagent in the main session's `cwd`. The optional `workingDirectory` may be absolute or relative to that `cwd`. Tau resolves it to an absolute path on the execution environment.
121
+ `tau.agents.spawn` normally runs the subagent in the main session's `cwd`. The optional `workingDirectory` may be absolute or relative to that `cwd`. Tau resolves it to an absolute path on the execution environment.
118
122
 
119
123
  For native Tau subagents, when that path differs from the parent's `cwd`, Tau rebuilds the subagent's context for the new directory. It detects the platform and repository there, reads the applicable `AGENTS.md` files, and discovers that directory's skills.
120
124
 
@@ -124,43 +128,118 @@ For native Tau subagents, the new directory does not change the persona, model c
124
128
 
125
129
  A native Tau launch fails if Tau cannot build context for the directory, if the directory is invalid for the environment, or if the environment cannot resolve working directories. A path that resolves to the parent's `cwd`, such as `.`, reuses the parent's context. Claude Code workers load context themselves in the selected directory; an invalid directory fails when the worker starts.
126
130
 
127
- ## Lifecycle and subagent tools
131
+ ## Managing subagents
132
+
133
+ The main agent manages subagents with `tau.agents` inside the [`code` tool](code-mode.md), and waits for them with the `wait_for_agents` tool. Each subagent has an ID that the host generates, and one conversation that grows with each input.
128
134
 
129
- Each subagent has an ID that the host generates.
135
+ | Method | Purpose |
136
+ | --- | --- |
137
+ | `spawn({ title, prompt, model?, workingDirectory? })` | Start a subagent. |
138
+ | `list()` | State of every subagent, plus the number running and the limit. |
139
+ | `read({ id })` | State of one subagent. |
140
+ | `sendInput({ id, message, mode })` | Queue or steer more input. |
141
+ | `interrupt({ id, wait? })` | Stop the current turn and discard pending input. |
142
+ | `waitUntilIdle({ id })` | Wait inside a program until the subagent is idle. |
143
+ | `trace({ id, kinds?, toolName?, limit?, cursor? })` | Read a page of the subagent's conversation. |
144
+ | `readText({ id, seq, maxChars? })` | Read the text of one assistant message or tool result. |
145
+ | `readContent({ id, ref, cursor? })` | Page through large or non-text content. |
146
+
147
+ The agent reads the complete reference, with types and examples, by printing `await tau.docs("agents")` in `code`. A program reads conversation data into JavaScript variables. Only what the program prints reaches the main agent's conversation, so the agent can select the part of a long trace it needs.
130
148
 
131
149
  ### Spawn
132
150
 
133
- `spawn_agent` takes a title, a prompt, an optional model, and an optional working directory. The prompt is the subagent's only initial input, so it should be self-contained. The call returns right away with the new ID, and the subagent keeps working in the background.
151
+ `spawn` takes a single-line title of at most 512 characters, a prompt of at most 262,144 characters, an optional model, and an optional working directory. The prompt is the subagent's first message, and the subagent does not see the parent conversation, so the prompt should be self-contained. The call returns right away with the subagent's state, and the subagent keeps working in the background.
152
+
153
+ When the main persona has `history`, a native Tau subagent may read the parent session's transcript as a last resort, when missing context would stop the work or force an important assumption. It reads with `tau.history.read` and `source: "local"`, so the read uses the host's local history even when a remote collection is configured. Local recording is best-effort, so the newest parent entries can occasionally be missing.
154
+
155
+ At most eight subagents can be working at once in one main session. Idle subagents do not count toward this limit.
156
+
157
+ ### State and waiting
158
+
159
+ A subagent's state has its ID, title, model and reasoning, working directory, status, counts of pending queued and steering input, token usage, context size, and cost. The status is one of:
160
+
161
+ - `working`: the subagent is handling input.
162
+ - `stopping`: an interrupt was requested and the turn has not ended yet.
163
+ - `idle`: no turn is running and no input is pending. `reason` tells how the latest turn ended: `completed`, `interrupted`, or `failed`, with an error code and message for a failure.
164
+
165
+ `completed` means the turn ended normally. It does not mean the task succeeded, so the main agent reads the subagent's answer before relying on it. Background Bash and code jobs that a subagent started do not keep it working. A subagent that needs a job's result must wait for the job before it answers.
166
+
167
+ `wait_for_agents` takes one or more IDs. It returns as soon as at least one of them is idle, with a text block for every requested subagent:
168
+
169
+ ```
170
+ id: 0b6c2f1e-7d4a-4c1b-9a53-2e8f0d9c4b71
171
+ title: "review authentication"
172
+ status: idle
173
+ reason: completed
174
+ pending: queue=0 steer=0
175
+ response_seq: 42
176
+ response_complete: true
177
+ response_partial: false
178
+
179
+ --- response ---
180
+ No problems found in the session expiry checks.
181
+ ```
182
+
183
+ A subagent that is still working or stopping gets only its ID, title, status, and pending counts. An idle subagent also gets `reason`, an `error` line with the code and message after a failed turn, and the last assistant message from its latest turn:
134
184
 
135
- At most eight subagents can be running at once in one main session. Subagents that have finished or been interrupted do not count toward this limit.
185
+ - `response_seq` is the message's `seq` in the trace. `readText({ id, seq, maxChars })` in `code` reads more retained text. For messages beyond its limit, use `trace` to get the content reference and page through it with `readContent`.
186
+ - `response_complete` is `false` when the text was shortened to fit the budget, or when some of it is unavailable or was removed from the trace. Shortened text keeps its beginning and end, with a marker in the middle.
187
+ - `response_partial` is `true` when the turn failed or was interrupted, so the message may be an unfinished answer.
188
+ - `response: none` replaces these lines when the latest turn produced no assistant message. A message from an earlier turn is never returned.
136
189
 
137
- ### Observe and wait
190
+ The response text of all requested subagents shares a budget of 8,192 estimated tokens, split evenly between them, working ones included. The optional `maxOutputTokens` sets a different budget, from 1 to 65,536.
138
191
 
139
- `list_agents` returns every subagent with its ID, name, title, model and reasoning, working directory, run state, context usage, cost, and whether a response is ready. Use it to find an ID again or to check progress.
192
+ Inside a program, `waitUntilIdle` waits for one subagent with the same meaning of idle and returns its state without the response. Neither wait returns until queued input has been handled too. Cancelling a wait, or stopping the program that waits, does not interrupt the subagent.
140
193
 
141
- `wait_for_agents` takes one or more IDs. It returns as soon as at least one of them finishes, with the current state of all of them. A finished response stays readable through later waits until a follow-up run replaces it.
194
+ The host also sends live subagent activity to attached clients for display. It is a summary for display. The subagent's messages and tool results are in its trace.
142
195
 
143
- The host also sends live subagent activity to attached clients for display. It is a summary for display, and the final response from these tools remains the real result.
196
+ ### Send more input
144
197
 
145
- ### Follow up
198
+ `sendInput` requires a `mode`:
146
199
 
147
- `send_input_to_agent` starts another run on an idle subagent. The subagent keeps its conversation, model, settings, tools, and working directory. It must finish or be interrupted before it accepts more input.
200
+ - `queue`: the subagent finishes its current work, then handles the message as a separate turn. Queued messages run in the order they were sent.
201
+ - `steer`: the subagent takes the message into account as soon as possible during its current turn. A native Tau subagent applies it at the next safe point, never in the middle of a model response or tool call, as in the [main session](sessions.md#submit-queue-and-steer). [Claude Code subagents](#claude-code-subagents) follow Claude Code's own streaming-input behavior.
148
202
 
149
- A follow-up replaces the subagent's previous response, so read anything you need first. Follow-ups do not pick up a changed persona definition or a reloaded allowlist.
203
+ Either mode starts a new turn right away on an idle subagent. The call returns once the input is accepted, before the subagent reads it. The subagent keeps its conversation, model, settings, tools, and working directory. Earlier messages stay readable in its trace.
204
+
205
+ Sending input fails while the subagent is stopping, when 64 inputs are already pending, or when the subagent is idle and eight subagents are already working. Follow-up input does not pick up a changed persona definition or a reloaded allowlist.
150
206
 
151
207
  ### Interrupt
152
208
 
153
- `interrupt_agent` asks the current run to stop and waits for the subagent's latest state. The subagent stays available for follow-up input. On an idle subagent, the call just returns its state.
209
+ `interrupt` stops the current turn and discards all pending input, so the subagent does not continue with queued work. By default the call waits until the turn has ended. With `wait: false` it returns right away, and the status may still be `stopping`. Interrupting an idle subagent only returns its state. Background jobs that the subagent started keep running, and the subagent stays available for more input.
154
210
 
155
211
  In the TUI, `Ctrl+G` interrupts the selected running subagent. Interrupting the main session does not interrupt subagents, and interrupting a subagent does not interrupt the main session.
156
212
 
213
+ ### Conversation traces
214
+
215
+ Each subagent has a trace: an ordered record of what it was told, what it said, and what its tools returned. Native Tau and Claude Code subagents produce the same kinds of entries:
216
+
217
+ | Kind | Contents |
218
+ | --- | --- |
219
+ | `input` | Each message the subagent was sent, with its mode: `initial`, `queue`, or `steer`. Recorded when the message is accepted. |
220
+ | `assistant` | The subagent's message text. |
221
+ | `tool_call` | The tool name, call ID, and arguments as JSON. |
222
+ | `tool_result` | The tool name, call ID, outcome, and the result exactly as the subagent received it. |
223
+ | `notice` | An event with a machine-readable code, such as `input.discarded` after an interrupt or `compaction.compacted`. A failed turn adds a notice with the failure code. |
224
+ | `status` | The subagent started working, began stopping, or became idle. |
225
+
226
+ Traces do not contain reasoning or system prompts. A tool result that the tool itself shortened stays shortened, and the trace cannot recover the missing output.
227
+
228
+ Each entry has a sequence number `seq` and a timestamp. A `trace` call returns the newest matching entries in chronological order, 20 by default and at most 50. It can filter by entry kinds and by tool name. Its `nextCursor` leads to older entries. A cursor keeps its starting point, so new activity does not shift the pages.
229
+
230
+ Content of at most 4,096 bytes as JSON, without images, is inline in the entry. Larger content and all images are references. `readText` returns the text of one assistant message or tool result, up to 30,000 UTF-16 code units by default and at most 100,000. Its `complete` field is `false` when the text was cut or some content is unavailable. It does not detect output that the tool itself shortened. Content with JSON or images needs `readContent`, which returns one block per page. Text arrives in chunks of at most 16,384 UTF-16 code units that join to the exact text.
231
+
232
+ A trace keeps the newest 4,096 entries, up to 64 MiB, for each subagent. When older entries are removed, trace pages report `historyEvicted: true`, and reading a removed entry or reference fails. A single content value larger than 6 MiB is replaced by a block that marks it unavailable. Traces last as long as the subagent and do not survive a host restart.
233
+
234
+ A failed call throws an error with a `code` and a `message`. The codes are `invalid_arguments`, `unknown_agent`, `invalid_cursor`, `expired_content`, `content_type`, `operation_failed`, and `cancelled`. A subagent's own failure is part of its state and trace, not a failed call.
235
+
157
236
  ## Detach, rewind, and recovery
158
237
 
159
238
  Subagents belong to the running session on the host, not to an attached TUI. Detaching a client, or losing the connection, does not stop them while the session stays alive. Another client can attach to the session and see their current state.
160
239
 
161
240
  Subagents do not survive the end of a session on the host or a host restart. Their status may be saved while the session is live, but recovery removes those records, because their runtimes no longer exist. A recovered session cannot send input to an old subagent ID.
162
241
 
163
- Rewind also removes subagents that were started by an assistant message the rewind removed. Host shutdown or session disposal interrupts and removes all subagents.
242
+ Rewind also removes subagents that were started by an assistant message the rewind removed. A subagent started from a `code` program belongs to the assistant message that ran the program, including a program running as a background job. Host shutdown or session disposal interrupts and removes all subagents.
164
243
 
165
244
  Plan long work with this in mind. Important results should reach the main agent and end up in the session history or in project files before the session on the host goes away. [Sessions](sessions.md) covers saving and recovery in general.
166
245
 
@@ -170,6 +249,6 @@ Changes to persona tools or to the launch allowlist apply after `/reload` in an
170
249
 
171
250
  `subagents.launchModels` must be an array of valid `<provider>/<model>:<effort>` strings. Unknown providers, invalid efforts, and malformed entries produce configuration warnings.
172
251
 
173
- A launch can fail because of invalid arguments, a model outside the allowlist, the concurrency limit, a prompt that cannot be built, or a working directory whose context cannot be built. Follow-up, wait, and interrupt calls reject unknown IDs. A follow-up also fails while the subagent is still running.
252
+ A launch can fail because of invalid arguments, a model outside the allowlist, the concurrency limit, a prompt that cannot be built, or a working directory whose context cannot be built. Calls with an unknown subagent ID fail. Sending input also fails under the conditions in [send more input](#send-more-input).
174
253
 
175
- Before starting a local TUI, `tau --debug --persona <id>` shows which tools are available, the model and settings subagents inherit, and the subagents' tool list. In a running session, `/reload` reports file warnings and `list_agents` shows live subagent state.
254
+ Before starting a local TUI, `tau --debug --persona <id>` shows which tools are available, the model and settings subagents inherit, and the subagents' tool list. In a running session, `/reload` reports file warnings and `tau.agents.list()` shows live subagent state.
@@ -46,7 +46,7 @@ A useful configuration defines at least one bot and one project:
46
46
 
47
47
  The bot token must be written in the file; it cannot come from an environment variable. Protect the file, never commit it, and rotate an exposed token through BotFather. Never print the config into a session or shared log.
48
48
 
49
- Unknown fields are removed, so a misspelled field silently has no effect.
49
+ Unknown fields are removed, so a misspelled field silently has no effect. The exception is a `personaMenu` entry, where an unknown field makes the config invalid.
50
50
 
51
51
  ## Top-level fields
52
52
 
@@ -69,6 +69,7 @@ Each `bots.<id>` object supports:
69
69
  | --- | --- | --- |
70
70
  | `botToken` | Yes | Telegram Bot API token. |
71
71
  | `allowedProjectIds` | No | Non-empty unique subset of configured project IDs; omission exposes all projects. |
72
+ | `personaMenu` | No | Ordered list of personas offered by `/persona`; omission offers every persona. See [persona menu](#persona-menu). |
72
73
  | `allowedUserIds` | No | Integer user IDs allowed to trigger turns, commands, and callbacks. |
73
74
  | `allowedChatIds` | No | Integer chat IDs allowed to interact with the bot; also opts groups in. |
74
75
  | `defaultProjectId` | No | Initial project preference, and must be allowed for this bot. |
@@ -143,6 +144,23 @@ In groups, commands must explicitly mention the bot. Accepted forms include:
143
144
 
144
145
  Commands addressed to other bots are ignored.
145
146
 
147
+ ### Persona menu
148
+
149
+ By default, `/persona` offers every persona in the session. A bot's `personaMenu` replaces that list with the personas you name, in the order you list them, and can give each one a shorter label:
150
+
151
+ ```json
152
+ "personaMenu": [
153
+ { "id": "gpt-6.1-sol-coder", "label": "sol" },
154
+ { "id": "sonnet-5.5-coder" }
155
+ ]
156
+ ```
157
+
158
+ Each entry has a required `id`, the exact persona ID, and an optional `label`. Both must be non-empty after surrounding whitespace is trimmed, IDs must be unique, and no other fields are allowed. Without a label, the picker shows the persona's own label, or its ID if it has none. The label appears in the picker and in the switch confirmation. It changes nothing else, so the persona keeps its ID, prompt, model, tools, and reasoning settings, and the TUI still shows its normal name.
159
+
160
+ The menu is matched against each session's personas when `/persona` runs, because different projects can define different personas. Listed personas that the session lacks are named in the picker message, and the rest of the menu still works. An empty list, `[]`, offers no personas.
161
+
162
+ The menu only changes what the picker offers. It does not restrict which personas a session may use, and it does not change defaults. A project's `persona` still applies to new sessions even if the menu omits it. When the session's current persona is not in the menu, the picker message names it, but it is not added as a choice.
163
+
146
164
  ## DMs, groups, and active work
147
165
 
148
166
  In a DM, ordinary text goes to the active session. If none is selected but the chat has exactly one session, Tau selects it. Otherwise the bot asks for `/new`.
@@ -202,7 +220,7 @@ Do not verify bot tokens, provider keys, Access secrets, transcript contents, or
202
220
 
203
221
  ## Troubleshooting
204
222
 
205
- **The runner rejects its config.** Startup errors name every invalid bot or project field. Check the required `bots` and `projects` objects, exact project IDs, positive numbers, allowed project IDs, persona suffixes, and that each project defines exactly one of `repo`, `directory`, or `projectIds`. Check the JSON syntax without printing the file, which contains bot tokens, and restart the runner after fixing it. Relative paths in the file resolve from its directory.
223
+ **The runner rejects its config.** Startup errors name every invalid bot or project field. Check the required `bots` and `projects` objects, exact project IDs, positive numbers, allowed project IDs, persona suffixes, `personaMenu` entries, and that each project defines exactly one of `repo`, `directory`, or `projectIds`. Check the JSON syntax without printing the file, which contains bot tokens, and restart the runner after fixing it. Relative paths in the file resolve from its directory.
206
224
 
207
225
  **The bot ignores a DM.** If `allowedChatIds` is set, the DM's chat ID must be listed. If `allowedUserIds` is set, the sender's user ID must be listed too.
208
226
 
@@ -40,16 +40,12 @@ web
40
40
  history
41
41
  mcp
42
42
  models
43
- spawn_agent
44
- send_input_to_agent
45
- wait_for_agents
46
- list_agents
47
- interrupt_agent
43
+ agents
48
44
  ```
49
45
 
50
- A custom persona that omits `tools` gets `bash`, `write`, `edit`, `view_image`, `web`, `history`, `mcp`, and `models`, plus the five subagent tools. Built-in personas get the same set.
46
+ A custom persona that omits `tools` gets all of these names. Built-in personas get the same set.
51
47
 
52
- `web`, `history`, `mcp`, and `models` are not separate tools. Each enables a namespace inside the single `code` tool. `bash` enables both the Bash tools and `tau.bash` inside `code`. Tau adds `code` whenever at least one usable capability is selected; `code` itself cannot be listed. A namespace the persona does not select is missing from the `code` API and its documentation.
48
+ `web`, `history`, `mcp`, and `models` are not separate tools. Each enables a namespace inside the single `code` tool. `bash` enables both the Bash tools and `tau.bash` inside `code`. `agents` enables `tau.agents` inside `code` and the `wait_for_agents` tool, which together start and manage [subagents](subagents.md). Tau adds `code` and its [job tools](code-mode.md#background-code-jobs) whenever at least one usable capability is selected; `code` itself cannot be listed. A namespace the persona does not select is missing from the `code` API and its documentation.
53
49
 
54
50
  An empty list turns off every selectable tool:
55
51
 
@@ -89,7 +85,7 @@ Agents are told to choose the mode that avoids needless waiting. Background mode
89
85
 
90
86
  Background mode also fits a service that must keep running, or work that must survive turns and interruptions. Starting several independent jobs and then waiting for them is a valid way to run work in parallel. This is guidance for the agent; Tau does not enforce it.
91
87
 
92
- The default foreground timeout is 60 seconds. Tau captures at most 1 MiB of combined stdout and stderr, and keeps the end when there is more. By default the result the model sees is limited to about 8,192 estimated tokens. Longer output is replaced by a preview of about 2,048 tokens from the middle, with a notice. The command has still run in full, with all its side effects.
88
+ The default foreground timeout is 60 seconds. Tau captures at most 24 MiB of combined stdout and stderr, and keeps the end when there is more. By default the result the model sees is limited to about 8,192 estimated tokens. Longer output is replaced by a preview of about 2,048 tokens that keeps the beginning and end, with a notice. The command has still run in full, with all its side effects.
93
89
 
94
90
  A narrower command is better than a higher limit. When more output is really needed, the agent can set `maxOutputTokens` between 8,192 and 16,384 on its own. Values above 16,384, up to 65,536, require an explicit user request. When output is truncated, Tau may save it to a temporary file in the execution environment and report the path.
95
91
 
@@ -97,21 +93,40 @@ In a local execution environment, Tau removes inherited environment variables wh
97
93
 
98
94
  The TUI commands `!<command>` and `!!<command>` run the same way, in a fresh login shell. `!` adds the result to the model's context and `!!` does not. They allow more output into context than an agent's tool call, but capture is still limited.
99
95
 
100
- With `background: true`, `bash` starts the command and returns a job ID for the session right away, without waiting for it to exit. A started job is not necessarily ready to use. Background jobs have no time limit, and combining `background: true` with `timeout` is invalid. Jobs keep running across turns and interruptions. Main agents, subagents, and ephemeral threads share the session's jobs.
96
+ With `background: true`, `bash` starts the command and returns a job ID right away, without waiting for it to exit. Background jobs have no time limit, and combining `background: true` with `timeout` or `maxOutputTokens` is invalid. Jobs keep running across turns and interruptions.
101
97
 
102
- Enabling `bash` also enables `list_bash_jobs`, `read_bash_job`, `stop_bash_job`, and `wait_for_bash_jobs`. These cannot be listed separately in a persona. List returns short ID and status blocks. Read returns the same blocks with the end of the job's output. Stop terminates the job's process group, and kills it if it has not exited after a grace period. Tau keeps up to 64 job records and drops the oldest finished one when needed. Starting a job fails if all 64 are still running. Each job keeps 64 KiB of combined output. At most 2,048 estimated tokens are returned per job, and 8,192 in total when several jobs are observed at once. Background output ignores `maxOutputTokens` and is never saved to an overflow file.
98
+ Each job belongs to the agent that started it, and only that agent can list, read, wait for, or stop it. The main agent, each subagent, and each ephemeral thread have separate jobs. A subagent keeps its jobs across follow-up messages. An ephemeral thread, including a fork, starts with no jobs.
103
99
 
104
- `read_bash_job`, `stop_bash_job`, and `wait_for_bash_jobs` accept `includeOutput`, which defaults to `true`. With `false`, the result leaves out stdout, stderr, and truncation notices, but still has the job ID, command, cwd, status, exit code once finished, termination reason, and errors. List never includes output.
100
+ Enabling `bash` also enables `list_bash_jobs`, `read_bash_job`, `stop_bash_job`, and `wait_for_bash_jobs`. These cannot be listed separately in a persona. Each job appears as a block of labeled lines: `id`, `status`, `command`, `cwd`, and, once the command has exited, `exit_code` and any terminating `signal`. Read, stop, and wait add the job's output after an `--- output ---` line. List never includes output. For example:
105
101
 
106
- In the TUI, job tool cards have headings such as `reading bash <id>` and `listed bash jobs`, and show a seven-line preview from the middle of the result. A background start shows `started background <command>`, which means only that the command started.
102
+ ```text
103
+ id: <job id>
104
+ status: running
105
+ command: "npm test"
106
+ cwd: "/work/app"
107
+ output: truncated; showing beginning and end
108
+
109
+ --- output ---
110
+ <beginning and end of output>
111
+ ```
112
+
113
+ Stop terminates the job's process group, kills it if it has not exited after a grace period, and waits until it has stopped. Tau keeps up to 64 job records for each agent and drops the oldest finished one when needed. Starting a job fails if all 64 are still running.
114
+
115
+ Each job keeps the last 24 MiB of combined output. Read, stop, and wait return that output within a budget of 8,192 estimated tokens for the whole response by default, divided evenly among the requested jobs. `maxOutputTokens` sets this budget, from 1 to 65,536. When a job's output exceeds its share, the result shows the beginning and the end. The `output: truncated` line means only that this response shows part of the output. A separate `capture: truncated` line means the job produced more than 24 MiB, so its earliest output is lost.
116
+
117
+ When a job with output finishes, Tau writes all of its retained text to a temporary file in the execution environment. Later results that include output give the file's path as `text_log`, so the agent can read or search it instead of raising the budget or running the command again. A running job has no text log. If the file cannot be written, the result shows `text_log: unavailable`.
118
+
119
+ `read_bash_job`, `stop_bash_job`, and `wait_for_bash_jobs` accept `includeOutput`, which defaults to `true`. With `false`, the result has only the labeled job lines. It leaves out output, truncation lines, the text log, and execution error messages.
120
+
121
+ In the TUI, job tool cards have headings such as `reading bash <id>` and `listed bash jobs`, and show a seven-line preview from the middle of the result. A background start shows `started background <command>`.
107
122
 
108
123
  Background launch and job-tool footers show the tool call's duration, estimated tokens, and line count. Counts cover the exact text returned to the model after output limits, before the card preview is shortened. With `includeOutput: false`, only returned job information counts. The launch footer also includes the working directory. A `◆` marker means included command output was truncated; shortening the card preview alone does not add it. A wait that reaches its timeout appends `timed out` without making the card an error. Durations measure the tool call, not the job's lifetime, and cards remain snapshots of that call.
109
124
 
110
125
  When a job tool call is invalid or fails, the TUI card shows a short diagnostic as well as the model's result. A normal cancellation shows no details.
111
126
 
112
- `wait_for_bash_jobs({ids, timeout?, includeOutput?})` returns when any of the jobs exits or the wait times out. Jobs that already finished return immediately. The timeout is a positive integer in milliseconds, defaults to 60,000, and can be at most 300,000. A timeout counts as a successful result and does not stop the jobs. Interrupting the wait leaves them running too. The tool waits for a job to exit, not to become ready, so check a server's logs or readiness instead. A job finishing never starts an agent turn by itself.
127
+ `wait_for_bash_jobs({ids, timeout?, includeOutput?, maxOutputTokens?})` returns when any of the jobs exits or the wait times out. Jobs that already finished return immediately. The timeout is a positive integer in milliseconds, defaults to 60,000, and can be at most 300,000. A timeout counts as a successful result. It starts with a note that the jobs are still running, followed by their current blocks, and does not stop the jobs. Interrupting the wait leaves them running too. A job finishing never starts an agent turn by itself.
113
128
 
114
- Jobs survive client disconnects while the host is running, and keep an idle session from being unloaded until they finish. Closing the session normally or shutting down the host stops them. Job IDs and logs are not saved or recovered, and an old ID fails with a clear error. An unknown ID does not mean the command never ran, that its side effects were undone, or that it has stopped. Agents are told to check running processes and output before starting such a command again. Cleanup does not cover processes that daemonize themselves, tmux sessions, or processes left behind by a host crash or forced kill.
129
+ Jobs survive client disconnects while the host is running, and keep an idle session from being unloaded until they finish. Closing the session normally or shutting down the host stops the jobs of every agent in the session. Job records are not saved or recovered, and an old ID fails with a clear error. An unknown ID does not mean the command never ran, that its side effects were undone, or that it has stopped. Agents are told to check running processes and output before starting such a command again. Cleanup does not cover processes that daemonize themselves, tmux sessions, or processes left behind by a host crash or forced kill.
115
130
 
116
131
  ### Write and edit
117
132
 
@@ -142,56 +157,11 @@ Each guide covers setup, input, examples, outputs, and failures. Run `tau tool -
142
157
 
143
158
  ## Code-mode composition
144
159
 
145
- `code` runs a one-off JavaScript program that combines the enabled capabilities: `tau.web`, `tau.history`, `tau.mcp`, `tau.bash`, and `tau.models`. The Bash, write, edit, and image tools stay available as separate tools.
146
-
147
- ### Documentation and output
148
-
149
- If the agent has not yet seen the runtime guide, it first runs a program that only prints it:
150
-
151
- ```js
152
- printText(docs);
153
- ```
154
-
155
- The guide covers runtime rules, capabilities, and examples. The agent reads each capability's reference it has not seen yet in a separate call that only prints documentation:
156
-
157
- ```js
158
- printText(await tau.docs("web"));
159
- ```
160
-
161
- The agent does not re-read documentation it has already seen. MCP tool descriptions are read separately. Programs do not need to print intermediate results.
162
-
163
- `printText` accepts only strings; objects and arrays throw a `TypeError`. The agent selects relevant fields and explicitly formats concise plain text to save tokens. `JSON.stringify` is reserved for cases where the structure matters or machine-readable JSON is requested, with fields selected first instead of dumping whole responses.
164
-
165
- Only `printText(string)` and awaited `printImage({ data, mimeType })` produce output, in the order they are called. Return values are ignored. Text is truncated in the middle to `maxOutputTokens` (default 8,192; range 1–65,536). The agent leaves it unset unless needed, and may raise it to 16,384 on its own. Higher values require an explicit user request. When text from the built-in `code` tool is truncated, Tau saves it to a temporary file in the execution environment when possible and reports the path. The agent reads that file instead of running the program again with its side effects. The file does not contain images or text lost to capture limits.
166
-
167
- JPEG, PNG, and WebP images are validated outside the sandbox and fitted to 4,096 pixels per dimension and 3.5 MiB each. Source images can be at most 40 megapixels, and a program can emit at most 16 images. Valid images are kept even if the built-in `code` program fails.
168
-
169
- The helper functions `truncate(text, { maxChars, position? })` and `truncateLines(text, { maxLines, position? })` return shortened strings with a marker where text was removed. `position` defaults to `middle`; `start` and `end` keep that end of the text. They do not print anything.
170
-
171
- ```js
172
- const result = await tau.bash.run({ command: "npm test" });
173
- printText(truncate(result.stdout, { maxChars: 4000 }));
174
- ```
175
-
176
- ### Execution and limits
177
-
178
- Programs have no direct access to files, processes, environment variables, credentials, imports, timers, or the network. They can act only through the capabilities. Keep data in variables, and use `tau.bash` for files. There is no scratch-file API.
179
-
180
- `code` times out after 5 minutes by default. `timeout` accepts 1–900,000 ms (15 minutes). `tau.bash.run` times out after 60 seconds by default, and at most after 5 minutes or the program's own deadline, whichever comes first. A program can make 128 API requests, eight at a time. Each serialized request and response can be at most 64 MiB. Object properties set to `undefined` are dropped, while `undefined` arguments and array entries are rejected. Programs are never retried, and failure or cancellation does not undo actions already taken.
181
-
182
- ### Capabilities
183
-
184
- - `tau.web`: metadata discovery, Exa search, and fetching page content. Search uses Auto with Dynamic Highlights to select evidence across results. An optional `objective` (1–4,096 nonblank characters) describes the broader task and facts to extract. Results include a `notices` array with retrieval qualifications such as relaxed query restrictions; each notice retains its `code`, `path`, `message`, and optional `details`. The agent prints notices alongside selected search results. The agent prefers local data, dedicated CLIs, first-party APIs, and structured sources over scraping web pages. For GitHub it uses `gh` or a Git checkout where suitable. Metadata discovery works without an Exa key; search and content fetching need one.
185
- - `tau.history`: read-only search and paginated transcripts. The agent uses it only when explicitly told to look at past sessions. It treats past content as data and never follows instructions in it. See [history](history.md).
186
- - `tau.mcp`: finding and calling tools and resources on configured MCP servers. When the persona allows MCP, enabled server names and optional configured descriptions are visible in the initial tool definition, before any tool call. Disabled servers and connection settings are omitted. These summaries guide discovery and do not grant permission to act. The agent reads each tool's description and schema before calling it. Connections are shared and opened on first use, and calls that change data are never retried. An `isError` result is returned as data, while protocol failures throw. MCP server configuration and trust rules apply. See [configuration reference](config-reference.md#mcpservers) and [security](security.md#trust-mcp-servers).
187
- - `tau.bash`: `run`, `start`, `list`, `read`, `wait`, and `stop`. `run` returns stdout, stderr, and exit and termination fields, capturing up to 24 MiB. Beyond that it keeps the end, so check `truncated` before parsing. Optional UTF-8 `stdin` is limited to 16 MiB and closed after writing. Without `stdin` the command has no stdin at all, while `""` gives it an empty one. `start` takes no stdin. Background jobs are the same jobs as the Bash tools', with the same output limits. Jobs survive the program ending and interruption, while foreground commands are cancelled. The shell rules above apply.
188
- - `tau.models`: lists a fixed set of OpenRouter models and runs standalone chats or typed decisions with them. These calls do not see the session's conversation or tools. Chat media can be paths on the agent's machine or inline padded base64 with a matching MIME type. Credentials stay on the host. Provider usage data is returned, but these charges are not included in the session's cost or usage logs. Requests can be cancelled and are never retried automatically. Limits on input, models, media, responses, and requests are the same as in [OpenRouter](openrouter.md). Check whether a response completed or was refused instead of assuming it is a full answer.
189
-
190
- SDK and command client tools built on code mode use the same sandbox functions and output rules, with their own declared APIs. Their programs time out after 60 seconds unless configured otherwise.
160
+ `code` runs a JavaScript program, inline or from a saved file, that combines the enabled capabilities. It can also run the program as a background job. See [code mode](code-mode.md) for input, output, limits, background code jobs, and each capability.
191
161
 
192
162
  ## Subagent tools
193
163
 
194
- A subagent gets each of `bash`, `write`, `edit`, `view_image`, `web`, `history`, `mcp`, and `models` that the main persona also has, plus `tau_docs`. It never gets the subagent tools or client tools. Its Bash and file tools start in the subagent's working directory. [Subagents](subagents.md#tools) has the details.
164
+ A subagent gets each of `bash`, `write`, `edit`, `view_image`, `web`, `history`, `mcp`, and `models` that the main persona also has, plus `tau_docs`. It never gets `agents` or client tools. Its Bash and file tools start in the subagent's working directory. [Subagents](subagents.md#tools) has the details.
195
165
 
196
166
  ## Client-owned tools
197
167
 
@@ -223,7 +193,7 @@ The runner holds the upload credentials, and the recipient is always the session
223
193
  First work out where the tool should come from:
224
194
 
225
195
  - For a host tool, check the active persona's `tools`, the host configuration, and service credentials.
226
- - For a subagent tool, check the main persona's `tools` against the list of tools subagents can receive.
196
+ - For a tool inside a subagent, check the main persona's `tools` against the list of tools subagents can receive.
227
197
  - For a client tool, confirm that an attached, observing client offers it and that client tools are not disabled.
228
198
  - If `tau_docs` is missing, something is wrong with the Tau installation or version; no persona setting removes it.
229
199
 
@@ -117,11 +117,11 @@ For a host tool, check the active persona's `tools` list. A list replaces the de
117
117
 
118
118
  For subagents, check three things:
119
119
 
120
- 1. The main persona has `spawn_agent` and any other subagent tools needed.
120
+ 1. The main persona has `agents`.
121
121
  2. A requested model exactly matches an entry in the launch allowlist.
122
122
  3. Fewer than eight subagents are running.
123
123
 
124
- A running subagent keeps its model, tools, and working directory after a reload. Recovery does not restore subagents, so old IDs cannot receive follow-ups after a host restart. Use `list_agents` to see live subagents. See [subagents](subagents.md).
124
+ A running subagent keeps its model, tools, and working directory after a reload. Recovery does not restore subagents, so old IDs cannot receive follow-ups after a host restart. Use `tau.agents.list()` in `code` to see live subagents. See [subagents](subagents.md).
125
125
 
126
126
  If `tau_docs` is missing, the problem is the host's installation or version, not a persona. Check the host package and restart it.
127
127