@markusylisiurunen/tau 0.3.49 → 0.3.50

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 (57) hide show
  1. package/README.md +22 -908
  2. package/dist/core/commands/registry.js +4 -4
  3. package/dist/core/commands/registry.js.map +1 -1
  4. package/dist/core/personas.js +19 -10
  5. package/dist/core/personas.js.map +1 -1
  6. package/dist/core/runtime/runtime_bootstrap.js +14 -9
  7. package/dist/core/runtime/runtime_bootstrap.js.map +1 -1
  8. package/dist/core/static/tau_docs/client-tools.md +228 -0
  9. package/dist/core/static/tau_docs/config-reference.md +422 -0
  10. package/dist/core/static/tau_docs/configuration.md +210 -0
  11. package/dist/core/static/tau_docs/credentials.md +200 -0
  12. package/dist/core/static/tau_docs/getting-started.md +140 -0
  13. package/dist/core/static/tau_docs/history.md +163 -0
  14. package/dist/core/static/tau_docs/index.md +40 -0
  15. package/dist/core/static/tau_docs/manifest.json +28 -0
  16. package/dist/core/static/tau_docs/models.md +198 -0
  17. package/dist/core/static/tau_docs/node-sdk.md +399 -0
  18. package/dist/core/static/tau_docs/nook.md +264 -0
  19. package/dist/core/static/tau_docs/ownership-and-scope.md +104 -0
  20. package/dist/core/static/tau_docs/personas.md +199 -0
  21. package/dist/core/static/tau_docs/prompts-and-project-context.md +181 -0
  22. package/dist/core/static/tau_docs/remote-sessions.md +274 -0
  23. package/dist/core/static/tau_docs/security.md +188 -0
  24. package/dist/core/static/tau_docs/session-protocol-methods.md +577 -0
  25. package/dist/core/static/tau_docs/session-protocol.md +265 -0
  26. package/dist/core/static/tau_docs/sessions.md +223 -0
  27. package/dist/core/static/tau_docs/skills.md +176 -0
  28. package/dist/core/static/tau_docs/subagents.md +203 -0
  29. package/dist/core/static/tau_docs/telegram.md +342 -0
  30. package/dist/core/static/tau_docs/tools.md +203 -0
  31. package/dist/core/static/tau_docs/troubleshooting.md +292 -0
  32. package/dist/core/static/tau_docs/tui.md +224 -0
  33. package/dist/core/telegram/session_manager.js +4 -3
  34. package/dist/core/telegram/session_manager.js.map +1 -1
  35. package/dist/core/tools/catalog.js +3 -1
  36. package/dist/core/tools/catalog.js.map +1 -1
  37. package/dist/core/tools/presentation.js +12 -1
  38. package/dist/core/tools/presentation.js.map +1 -1
  39. package/dist/core/tools/tau_docs.js +115 -0
  40. package/dist/core/tools/tau_docs.js.map +1 -0
  41. package/dist/core/tools/tool_names.js +8 -0
  42. package/dist/core/tools/tool_names.js.map +1 -1
  43. package/dist/core/utils/repository.js +19 -0
  44. package/dist/core/utils/repository.js.map +1 -1
  45. package/dist/core/version.js +1 -1
  46. package/dist/host/client_tool_broker.js +3 -18
  47. package/dist/host/client_tool_broker.js.map +1 -1
  48. package/dist/protocol/session_protocol.d.ts +1 -0
  49. package/dist/protocol/session_protocol.js +2 -1
  50. package/dist/protocol/session_protocol.js.map +1 -1
  51. package/dist/tui/session_chat_app.js +1 -0
  52. package/dist/tui/session_chat_app.js.map +1 -1
  53. package/dist/tui/session_chat_controller.js +13 -13
  54. package/dist/tui/session_chat_controller.js.map +1 -1
  55. package/dist/tui/session_creation_attributes.js +3 -3
  56. package/dist/tui/session_creation_attributes.js.map +1 -1
  57. package/package.json +2 -2
@@ -0,0 +1,342 @@
1
+ # Telegram
2
+
3
+ Tau's Telegram runner turns one or more bots into clients of local, in-process Tau sessions. It owns Telegram polling, chat routing, attachments, project selection, and workspace preparation on the runner machine. Each prepared workspace then becomes an ordinary local execution environment with normal Tau configuration, personas, tools, project context, session snapshots, and history.
4
+
5
+ Bot access can lead to model calls, filesystem changes, and repository mutations. Configure chat, user, and project boundaries before inviting a bot into a group.
6
+
7
+ ## Start the runner
8
+
9
+ Run the standalone process with one dedicated JSON file:
10
+
11
+ ```sh
12
+ tau telegram --config-file /etc/tau/telegram.json
13
+ ```
14
+
15
+ The process stays in the foreground until `SIGINT` or `SIGTERM`. Relative `--config-file` paths resolve from the process working directory. Paths inside that file resolve as described below, usually from the config file's directory.
16
+
17
+ The Telegram file is **not** a Tau `config.json` level. It controls runner concerns such as bot tokens, project definitions, workspace roots, and routing. Tau still loads normal configuration from the runner's startup working directory and from each prepared session workspace. See [configuration](configuration.md) and [ownership and scope](ownership-and-scope.md).
18
+
19
+ Run at most one Telegram runner for a given configuration and workspace root. Concurrent runners are unsupported and can race Telegram updates, persisted runner state, and workspace cleanup.
20
+
21
+ ## Minimal configuration
22
+
23
+ A useful configuration defines at least one bot and one project:
24
+
25
+ ```json
26
+ {
27
+ "workspaceRoot": "/var/lib/tau/telegram-workspaces",
28
+ "bots": {
29
+ "engineering": {
30
+ "botToken": "<telegram-bot-token>",
31
+ "allowedProjectIds": ["ledger"],
32
+ "allowedUserIds": [18422031],
33
+ "allowedChatIds": [18422031],
34
+ "defaultProjectId": "ledger"
35
+ }
36
+ },
37
+ "projects": {
38
+ "ledger": {
39
+ "repo": "acme/ledger",
40
+ "ref": "main",
41
+ "persona": "gpt-5.6-sol-coder:high"
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ The bot token is a required literal string; Telegram config has no token environment indirection. Protect the file, never commit it, and rotate an exposed token through BotFather. Do not print the config into a session or shared log.
48
+
49
+ Unknown object fields are stripped, so a misspelled field can have no effect without making the JSON invalid.
50
+
51
+ ## Top-level contract
52
+
53
+ | Field | Required | Behavior |
54
+ | --- | --- | --- |
55
+ | `bots` | Yes | Non-empty object keyed by operator-chosen bot ID. |
56
+ | `projects` | Yes | Object keyed by project ID. Bots select from these definitions. |
57
+ | `workspaceRoot` | No | Base for managed workspaces; defaults to `.tau/telegram-workspaces` beside the Telegram config file. |
58
+ | `maxSessions` | No | Positive integer cap on active sessions across the whole runner. |
59
+ | `systemMessage` | No | Non-empty model-facing instruction prepended to every Telegram turn. |
60
+
61
+ A relative top-level `workspaceRoot` resolves from the Telegram config file's directory. Tau persists runner session records at `<workspaceRoot>-sessions.json` and per-chat project preferences at `<workspaceRoot>-project-preferences.json`. These are runner-owned state files, not operator editing surfaces. Session snapshots remain in the normal host store under the runner user's Tau home.
62
+
63
+ `maxSessions` counts queued, preparing, running, and waiting sessions across all configured bots. Failed records do not consume the active cap, but they remain visible to their owning chat until replaced or closed.
64
+
65
+ ## Bot contract and access control
66
+
67
+ Each `bots.<id>` object supports:
68
+
69
+ | Field | Required | Behavior |
70
+ | --- | --- | --- |
71
+ | `botToken` | Yes | Telegram Bot API token. |
72
+ | `allowedProjectIds` | No | Non-empty unique subset of configured project IDs; omission exposes all projects. |
73
+ | `allowedUserIds` | No | Integer user IDs allowed to trigger turns, commands, and callbacks. |
74
+ | `allowedChatIds` | No | Integer chat IDs allowed to interact with the bot; also opts groups in. |
75
+ | `defaultProjectId` | No | Initial project preference, and must be allowed for this bot. |
76
+ | `systemMessage` | No | Additional instruction for turns from this bot. |
77
+ | `pollIntervalMs` | No | Positive polling retry interval, default 1,000 ms. |
78
+ | `requestTimeoutSeconds` | No | Positive Telegram long-poll timeout, default 30 seconds. |
79
+
80
+ An absent or empty `allowedUserIds` means no user restriction. An absent or empty `allowedChatIds` allows DMs but allows no groups. When `allowedChatIds` is non-empty, it restricts DMs to listed chat IDs and enables only listed groups. Group IDs are usually negative integers.
81
+
82
+ Use both lists for a private bot. `allowedUserIds` controls who can trigger work, but messages from other users in an allowed group can still enter the sender-attributed pending group context. Only add the bot to groups whose conversation is suitable for model input.
83
+
84
+ A bot sees only `allowedProjectIds`. If that field is omitted, it sees every configured project. A sole allowed project is selected automatically; otherwise a chat needs `defaultProjectId` or an explicit `/use_<project>` preference before `/new`.
85
+
86
+ Tau registers eight built-in commands plus one `/use_<projectId>` command per visible project. A bot may expose at most 92 projects under Telegram's 100-command limit.
87
+
88
+ ## Project IDs and common fields
89
+
90
+ Project IDs become Telegram command suffixes. They must contain only lowercase letters, digits, and underscores, and may be at most 28 characters:
91
+
92
+ ```text
93
+ ledger
94
+ platform_api
95
+ release2026
96
+ ```
97
+
98
+ Every project can have an optional non-empty `description`. Repository and persistent-directory projects can select `persona` as `<id>` or `<id>:<reasoning>`, and can set `noAgentContextFiles` to disable `AGENTS.md` injection for that session. Composite projects require their own persona and do not support `noAgentContextFiles`.
99
+
100
+ Each project must define exactly one workspace source: `repo`, `directory`, or `projectIds`.
101
+
102
+ ## Repository projects
103
+
104
+ A repository project clones one GitHub repository into a session-specific managed workspace:
105
+
106
+ ```json
107
+ {
108
+ "projects": {
109
+ "ledger": {
110
+ "repo": "acme/ledger",
111
+ "ref": "main",
112
+ "workingDirectory": "packages/api",
113
+ "workspaceRoot": "/var/lib/tau/ledger-workspaces",
114
+ "persona": "gpt-5.6-sol-coder",
115
+ "noAgentContextFiles": false
116
+ }
117
+ }
118
+ }
119
+ ```
120
+
121
+ `repo` must use GitHub `owner/repo` syntax. Arbitrary Git URLs are not accepted. The runner needs `gh` and `git` on its login-shell `PATH`, and `gh` must already be authenticated for the repository.
122
+
123
+ A relative project `workspaceRoot` resolves from the Telegram config file's directory and replaces the top-level root for that project's managed workspaces. A session workspace is:
124
+
125
+ ```text
126
+ <effective-workspace-root>/<project-id>/<telegram-session-id>
127
+ ```
128
+
129
+ `workingDirectory` is optional and must be a relative directory inside the clone. Tau validates that it exists and does not escape the repository, then uses it as the session `cwd`. Without it, the repository root is the `cwd`.
130
+
131
+ `ref` is optional and is passed to `git checkout` after cloning. Without it, the clone's default branch remains checked out. Configure a ref when sessions must begin from a predictable branch or commit.
132
+
133
+ ### Repository caches
134
+
135
+ Tau keeps a persistent bare cache at:
136
+
137
+ ```text
138
+ <effective-workspace-root>-repo-cache/<project-id>.git
139
+ ```
140
+
141
+ The first preparation uses `gh repo clone <owner/repo> <cache> -- --bare`. Later preparations fetch and prune the cache, then create the session workspace with a shared local clone. If the repository configured for the same project ID changes, Tau discards and recreates that cache.
142
+
143
+ Caches are not session workspaces. Tau does not commit, push, or preserve uncommitted changes automatically. Managed workspaces survive a normal restart, but `/new` removes the active session's workspace.
144
+
145
+ ## Persistent-directory projects
146
+
147
+ A persistent-directory project reuses one existing directory instead of creating a managed clone:
148
+
149
+ ```json
150
+ {
151
+ "projects": {
152
+ "notes": {
153
+ "directory": "/srv/tau/notes",
154
+ "persona": "gpt-5.6-sol-coder"
155
+ }
156
+ }
157
+ }
158
+ ```
159
+
160
+ Relative `directory` paths resolve from the Telegram config file's directory. JSON does not expand `~`, so use an absolute path when referring to a home directory.
161
+
162
+ The directory must already exist. Tau never creates, replaces, provisions, or removes it. `/new`, session close, runner shutdown, and startup cleanup all preserve it.
163
+
164
+ Every session for this project uses the same directory as its execution-environment `cwd`, including sessions owned by different chats or bots. Tau does not serialize their filesystem work. Use `maxSessions`, bot project scoping, and access allowlists to prevent unsafe concurrent edits when the directory is not designed for them.
165
+
166
+ Persistent-directory sessions omit the conventional history `repository` attribute. On recovery, Tau requires the configured directory to match the directory stored in the Tau session snapshot. Changing `directory` does not migrate existing sessions and causes those recoveries to fail.
167
+
168
+ ## Composite projects
169
+
170
+ A composite project creates one generated root with multiple repository projects as children:
171
+
172
+ ```json
173
+ {
174
+ "projects": {
175
+ "web": { "repo": "acme/web", "ref": "main" },
176
+ "api": { "repo": "acme/api", "workingDirectory": "services/http" },
177
+ "platform": {
178
+ "projectIds": ["web", "api"],
179
+ "persona": "gpt-5.6-sol-coder:high",
180
+ "instructions": "Keep shared contracts synchronized."
181
+ }
182
+ }
183
+ }
184
+ ```
185
+
186
+ `projectIds` must contain at least two unique repository project IDs. A composite cannot contain persistent-directory projects or another composite. Member order is retained for workspace context and the comma-delimited history `repository` attribute.
187
+
188
+ Tau creates each member under `<composite-root>/<member-project-id>`, using that member's repository cache, ref, and working directory. The session `cwd` is the generated composite root. Tau writes a root `AGENTS.md` describing the members and optional `instructions`, plus a root `.tau/config.json` that adds discovered member `AGENTS.md` files along the configured working-directory paths.
189
+
190
+ The parent composite session remains authoritative for the persona, subagent definition, model catalog, runtime config, settings, and tools. Child `.tau/config.json` files are not merged into the main composite session. A subagent launched in a member directory rebuilds only target-dependent prompt context there: environment and repository metadata, applicable `AGENTS.md` and target `agentContextFiles`, and target-discovered skills filtered by the parent persona.
191
+
192
+ Composite preparation is all-or-nothing. If one member cannot be prepared, Tau removes the generated composite workspace. The composite's optional `workspaceRoot` controls the generated root; member repository caches continue to use each member's configured root or the top-level default.
193
+
194
+ ## Managed workspace safety
195
+
196
+ **Important:** runner startup removes entries under configured managed workspace roots when they are not referenced by persisted sessions. Dedicate these roots to Tau Telegram workspaces. Do not point `workspaceRoot` at a home directory, repository collection, or any directory containing unrelated files.
197
+
198
+ Tau preserves managed workspaces referenced by active or failed persisted records and always preserves configured persistent directories. It also preserves repository caches, which live beside the workspace root under the `-repo-cache` suffix rather than inside the pruned root.
199
+
200
+ `/new` closes the chat's current active session before creating its replacement. For repository and composite projects, closing interrupts work and recursively removes that session's managed workspace. Uncommitted changes are lost unless the agent or operator saved them elsewhere. For persistent-directory projects, the shared directory remains untouched.
201
+
202
+ ## Provision hooks
203
+
204
+ A repository may provide an optional setup script at its repository root:
205
+
206
+ ```text
207
+ .tau/scripts/provision
208
+ ```
209
+
210
+ Tau runs it through `session.exec` with the project's configured working directory as `cwd`. The path must be a regular executable file, not a symlink, and must begin with a shebang. A missing hook is a successful no-op.
211
+
212
+ Provisioning starts after the session becomes available and does not block chat input. A failure is reported to linked chats, but the session remains usable. Composite sessions run each member hook in member order and continue after a member failure. Persistent-directory projects are never provisioned.
213
+
214
+ A newly created workspace runs its hook. A preserved workspace skips it during normal restart recovery. If recovery must reconstruct a missing repository or composite workspace from cache, the reconstructed repositories run provisioning again. Keep hooks repeatable and non-interactive.
215
+
216
+ ## Normal Tau configuration inside workspaces
217
+
218
+ After preparation, Tau creates an ordinary local session at the workspace `cwd`. Runtime discovery reads normal `~/.config/tau` and ancestor `.tau` content visible from that path: models, personas, prompts, skills, project context, host tools, and other session settings work as they do in the TUI.
219
+
220
+ A project `persona` overrides the normal default for that session. `noAgentContextFiles: true` suppresses `AGENTS.md` injection for repository or persistent-directory sessions. Composite root context is generated deliberately and uses its required persona.
221
+
222
+ The top-level and per-bot `systemMessage` values are different from project context. Tau prepends them as a hidden `<system>` block to every Telegram-submitted turn, with the top-level message first and the bot message second. They are persisted as part of the user turn and can appear in history, so never put credentials in them.
223
+
224
+ The runner's speech-to-text provider is loaded from normal Tau config at runner startup, based on the runner process's startup `cwd`. Restart the runner after changing that provider or its environment.
225
+
226
+ ## Chat commands
227
+
228
+ | Command | Behavior |
229
+ | --- | --- |
230
+ | `/use_<projectId>` | Saves the project preference for future `/new` sessions; does not change the active session. |
231
+ | `/new` | Closes the current active session, then creates one from the current project preference. |
232
+ | `/status` | Reports session state, project, model, reasoning, context usage, cost, and goal state when available. |
233
+ | `/effort_low` | Selects low reasoning for later independent turns. |
234
+ | `/effort_medium` | Selects medium reasoning for later independent turns. |
235
+ | `/effort_high` | Selects high reasoning for later independent turns. |
236
+ | `/effort_xhigh` | Selects xhigh reasoning for later independent turns. |
237
+ | `/compact` | Runs summary-only manual compaction while the session is idle. |
238
+ | `/interrupt` | Interrupts the active Tau turn. |
239
+
240
+ Project preferences are scoped to one bot and chat and survive restarts. A changed preference does not switch the active session; `/status` reports the difference.
241
+
242
+ In groups, commands must explicitly mention the bot. Accepted forms include:
243
+
244
+ ```text
245
+ /status@tau_engineering_bot
246
+ /status @tau_engineering_bot
247
+ @tau_engineering_bot /status
248
+ ```
249
+
250
+ A command addressed to another bot does not trigger this one.
251
+
252
+ ## DMs, groups, and active work
253
+
254
+ In a DM, ordinary text goes to the active session. If no session is selected but the chat owns exactly one session, Tau selects it automatically. Otherwise the bot asks for `/new`.
255
+
256
+ In an allowed group, ordinary messages trigger Tau only when they explicitly mention the bot username. Non-triggering text and captions are buffered as sender-attributed background context. On the next valid mention, Tau includes up to the most recent 50 buffered messages since the previous bot-triggering turn, then clears that buffer after successful submission.
257
+
258
+ Pending group context can include attachment paths, audio transcripts, and processing errors. It is untrusted model input. `allowedUserIds` prevents an unlisted sender from triggering work, but their message can still become context in an allowed group.
259
+
260
+ Telegram text and transcribed audio use automatic submit-or-steer behavior. When the session is idle, the input starts a normal turn. When Tau is already working, it becomes steering input that stops the active turn at its next safe boundary and continues with the new message. Additional steering follows Tau's normal batching behavior. Telegram does not expose a separate queued-turn command. Use `/interrupt` when the desired action is to stop rather than steer.
261
+
262
+ Tau keeps tool and lifecycle chatter quiet. It sends committed assistant text, including multiple messages from one run, and refreshes the typing indicator during work. Oversized replies are split into bounded chunks. Durable failed, blocked, and confirmed-unaccepted turn notifications remain pending until Telegram acknowledges delivery.
263
+
264
+ ## Attachments and audio
265
+
266
+ Telegram accepts photos and documents identified as images, PDF, `.txt`, `.md`, `.json`, `.csv`, `.yaml`, or `.yml`. It downloads supported attachments immediately to a runner temporary directory and gives the agent the local path, MIME type, byte size, and caption.
267
+
268
+ Limits are:
269
+
270
+ - at most 10 attachments per turn
271
+ - at most 20 MiB per file
272
+ - at most 50 MiB total per turn
273
+
274
+ An attachment-only DM queues files for the next text or voice/audio turn; it does not run the agent by itself. Unsupported, oversized, or failed downloads are skipped with a warning. Treat every attachment as untrusted input even though its path is local.
275
+
276
+ The local execution environment can access these runner temporary paths. Pending attachments and group context are not snapshot data. Shutdown clears their queues, and startup removes stale `tau-telegram-attachments-*` directories.
277
+
278
+ Telegram `voice` and `audio` messages are downloaded and transcribed. Direct DM turns and bot-triggering group turns echo the transcript to the chat before submission so the sender can verify it.
279
+
280
+ Mistral is the default provider. Configure credentials in the runner's normal Tau config or environment:
281
+
282
+ - Mistral: `MISTRAL_API_KEY`, then `apiKeys.mistral`
283
+ - Gemini: set `speechToText.provider` to `gemini`, then use `GEMINI_API_KEY`, falling back to `apiKeys.google`
284
+
285
+ The environment variable wins for each speech provider. Audio without a usable key produces a user-facing error instead of entering a turn. See [credentials](credentials.md).
286
+
287
+ ## Command client tools
288
+
289
+ Each Telegram session advertises the configured command client tools selected by normal Tau configuration for its prepared workspace. Global `clientTools` definitions provide executable behavior, while the workspace's most-specific `enabledClientTools` value selects an exact subset. An empty list disables all configured client tools for that workspace.
290
+
291
+ These command processes run on the Telegram runner machine with the runner process environment. They can reach the session workspace only through their explicit execution-environment facade, despite physical co-location. Telegram does not advertise TUI-only `diff_review` or `prefill_input` tools.
292
+
293
+ Tool selection occurs when the session client is created or reconnected. `/reload` does not rebuild the Telegram client advertisement. Restart the runner or create a new session client after changing command client-tool selection. See [client tools](client-tools.md).
294
+
295
+ ## Persistence and restart behavior
296
+
297
+ Normal shutdown interrupts live work, waits for active work to settle, disconnects sessions, and preserves repository and composite workspaces rather than deleting them. Sessions that finished creation reconnect on restart and retain their conversation. A session interrupted while its workspace or Tau session was still being prepared starts preparation again.
298
+
299
+ If a referenced repository workspace is missing, Tau reconstructs it from the cache and reconnects the same session. A persistent-directory workspace is never reconstructed; its configured directory must still exist at the original path.
300
+
301
+ If the connection is lost after Telegram submits a message, startup checks whether Tau accepted and completed it. Running work remains interruptible until it settles. A confirmed unaccepted message prompts the user to resend it; failed or blocked outcomes remain queued until delivery succeeds.
302
+
303
+ Tau does not resend earlier assistant messages, notices, or unrelated old outcomes just because the runner restarted. New warning and error notices are delivered after recovery. A restart clears short-lived network retries, but notifications waiting to be delivered remain pending.
304
+
305
+ If a failed session still has unresolved submitted work, Tau can reconnect to determine the outcome. Other failed sessions remain visible with their original diagnostic until the owning chat replaces or closes them. Do not edit runner state files to force recovery.
306
+
307
+ ## Verify a runner safely
308
+
309
+ 1. Validate that the Telegram file is parseable JSON without displaying it in a shared terminal transcript.
310
+ 2. Confirm the runner user can execute `tau`, `git`, and `gh`, and that `gh` can access each repository.
311
+ 3. Start the runner and watch for config, polling, command-sync, cache, checkout, and recovery errors. Successful startup prints `tau telegram running`.
312
+ 4. In an allowed DM, run `/status`, select a project if needed, then run `/new`.
313
+ 5. Submit a small nonsensitive prompt and confirm an assistant response.
314
+ 6. If groups are enabled, verify that an unmentioned message stays quiet and an explicitly mentioned command works.
315
+ 7. If a provision hook exists, confirm its completion or reported failure before relying on its dependencies.
316
+ 8. Restart the runner normally and use `/status` to confirm the session recovered without replaying old replies.
317
+
318
+ Do not verify bot tokens, provider keys, Access secrets, transcript contents, or runner state by printing them.
319
+
320
+ ## Common failures
321
+
322
+ **The runner rejects its config.** Check required `bots` and `projects` objects, exact project IDs, positive numeric fields, known allowed projects, and that each project defines exactly one of `repo`, `directory`, or `projectIds`.
323
+
324
+ **The bot ignores a DM.** If `allowedChatIds` is set, the DM chat ID must be listed. If `allowedUserIds` is set, the sender's user ID must also be listed.
325
+
326
+ **The bot ignores a group.** Groups require an explicit `allowedChatIds` entry and a direct `@botusername` mention. Commands also need the mention in one of the accepted command forms.
327
+
328
+ **`/new` asks for a project.** Configure `defaultProjectId`, expose only one project, or run the matching `/use_<projectId>` command first.
329
+
330
+ **Repository preparation fails.** Verify runner-side `gh` authentication, `git` availability, repository access, configured `ref`, and that `workingDirectory` exists in the checked-out tree. A changed repository under an existing project ID causes cache reinitialization.
331
+
332
+ **Startup removed unexpected files.** The configured workspace root was not dedicated to Tau. Stop the runner and move `workspaceRoot` to an isolated directory before restarting. Recovery data does not make unrelated deleted files restorable.
333
+
334
+ **Provisioning fails but chat still works.** This is expected isolation. Fix the executable bit, shebang, script behavior, or dependencies, then create a new managed workspace if the hook needs to run again.
335
+
336
+ **A persistent-directory session fails recovery.** Restore the configured directory and its original path, or return the project config to the snapshot's durable `cwd`. Tau does not migrate an existing session to a new persistent directory.
337
+
338
+ **Audio reports a missing key.** Set the credential for the configured speech provider in the runner process and restart it. A workspace-only environment change does not update the runner's startup speech configuration.
339
+
340
+ **A message sent during active work changes direction.** Telegram uses steering, not ordinary queueing, while a turn is running. Wait for completion before sending an independent next task, or use `/interrupt` to stop the current run first.
341
+
342
+ **A command client tool is absent.** Check global `clientTools`, the prepared workspace's `enabledClientTools`, and whether the session client was created after the change. Telegram never provides TUI-only tools.
@@ -0,0 +1,203 @@
1
+ # Tools
2
+
3
+ Tools let an agent act beyond plain model output, but not every tool comes from the same machine or policy. Tau binds host tools to a session, accepts selected tools from an attached client, and always supplies a small set of intrinsic capabilities. Understanding that ownership explains why a tool can be available in one session and absent in another.
4
+
5
+ Tool availability is captured when a logical turn starts. Persona changes, configuration reloads, and client attachment changes apply to the next independently started turn rather than changing the tool set halfway through an active turn.
6
+
7
+ ## Tool categories
8
+
9
+ Tau uses four distinct categories:
10
+
11
+ | Category | Owner and availability |
12
+ | --- | --- |
13
+ | Persona-controlled host tools | The host binds implementations that operate against the session execution environment or host services. The active persona's `tools` list selects them. |
14
+ | Intrinsic tools | Tau binds these outside persona allowlists. `tau_docs` is available to main agents and subagents. |
15
+ | Main-session goal tools | `get_goal`, `create_goal`, and `update_goal` are always available to the main session, independently of the persona. They are not subagent tools. |
16
+ | Client-provided tools | An attached client advertises and executes these. TUI-owned `diff_review` and `prefill_input` are examples. Configured command client tools use the same boundary. |
17
+
18
+ A tool schema tells the model how to call a tool. It does not grant operating-system permissions. Host tools execute with the authority of the execution environment or the configured host service. Client tools execute with the authority of their owning client and may separately request commands in the execution environment. See [ownership and scope](ownership-and-scope.md) and [client tools](client-tools.md).
19
+
20
+ ## Persona tool selection
21
+
22
+ A custom persona can set an exact list of persona-controlled tools:
23
+
24
+ ```yaml
25
+ tools:
26
+ - bash
27
+ - write
28
+ - edit
29
+ - view_image
30
+ - web
31
+ ```
32
+
33
+ The supported persona-controlled names are:
34
+
35
+ ```text
36
+ bash
37
+ write
38
+ edit
39
+ view_image
40
+ web
41
+ nook
42
+ history
43
+ spawn_agent
44
+ send_input_to_agent
45
+ wait_for_agents
46
+ list_agents
47
+ interrupt_agent
48
+ ```
49
+
50
+ When a custom persona extends another persona and omits `tools`, it inherits the base persona's list. A non-extending custom persona that omits `tools` enables `bash`, `write`, `edit`, `view_image`, `web`, `nook`, and `history`. If that persona has any enabled subagents, Tau also enables the five subagent-management tools. Built-in personas enable the same base and subagent tool sets.
51
+
52
+ An empty list disables every persona-controlled host tool:
53
+
54
+ ```yaml
55
+ tools: []
56
+ ```
57
+
58
+ It does not remove intrinsic `tau_docs` or the main-session goal tools. It also does not select client-provided tools, which are advertised independently by an observing client.
59
+
60
+ The `nook` name has an additional eligibility check: the effective host configuration must contain a Nook target. Without one, Tau does not register the tool even if the persona lists it. Other credentials and service configuration can affect what an enabled tool can do, but not whether its schema is selected. Persona configuration is covered in [personas](personas.md).
61
+
62
+ ## Intrinsic Tau documentation
63
+
64
+ `tau_docs` reads the exact version-matched documentation shipped with the running Tau package. It is intrinsic, so a persona cannot disable it, and Tau also includes it in every subagent registry.
65
+
66
+ The tool accepts one exact flat Markdown path. It has no search or list operation. Start with:
67
+
68
+ ```text
69
+ index.md
70
+ ```
71
+
72
+ Then follow paths linked by that page. Unknown paths are rejected. The corpus describes supported Tau contracts, not the current effective configuration of a particular session, so use configuration inspection or debug output when the answer depends on local state.
73
+
74
+ ## Main-session goal tools
75
+
76
+ The main agent always receives:
77
+
78
+ - `get_goal`, which reads the persisted session goal or returns no goal.
79
+ - `create_goal`, which creates an active goal only when the user or an active instruction explicitly requests one.
80
+ - `update_goal`, which changes, completes, or blocks the current goal.
81
+
82
+ These tools are outside persona allowlists because goal lifecycle is a session capability. They are not included in subagent registries or advertised by clients. Goal behavior is described in [sessions](sessions.md).
83
+
84
+ ## Execution-environment tools
85
+
86
+ ### Bash
87
+
88
+ `bash` runs a command in a fresh non-interactive login Bash in the execution environment. Each call starts a new shell, so shell variables, aliases, functions, `cd`, and other shell state do not carry into the next call. Files and process side effects do persist.
89
+
90
+ Tau starts Bash with `-lc` and the execution environment's `HOME`. A login shell can read `/etc/profile` and then the first available `~/.bash_profile`, `~/.bash_login`, or `~/.profile`. It reads `BASH_ENV` when set. `.bashrc` is otherwise loaded only when a login file sources it. Startup files must not print output, read stdin, require a terminal, or terminate the shell unexpectedly because Tau does not suppress their effects.
91
+
92
+ There is no TTY and assistant `bash` calls have no stdin. Commands that prompt, open an interactive editor, or require terminal control will hang until timeout or fail. Use non-interactive flags and pass a `workingDirectory` rather than relying on a previous `cd`.
93
+
94
+ Tau forces Git into non-interactive mode: terminal prompts and askpass interaction are disabled, editors are replaced, pagers are disabled, and SSH uses batch mode. Authentication therefore needs to be available non-interactively.
95
+
96
+ The default timeout is 60 seconds. Tau captures at most 1 MiB of merged stdout and stderr, preserving the tail when raw capture overflows. The default model-facing result limit is roughly 8,192 estimated tokens. When output exceeds it, Tau returns a roughly 2,048-token middle preview and a gating notice. The command has already run and its side effects have already happened.
97
+
98
+ Prefer a narrower command over raising the result limit. When more output is genuinely needed, `maxOutputTokens` can request 8,192 through 16,384 tokens autonomously. Values above 16,384, up to 65,536, are reserved for an explicit user request. Tau may save captured output to a temporary execution-environment file when model-context truncation occurs; the result reports that path when available.
99
+
100
+ On a local execution backend, Tau removes inherited environment variables whose names end in `_KEY`, `_SECRET`, `_TOKEN`, or `_PASSWORD`, plus `API_KEY`, before running execution-environment commands. Hosted backends begin from their own target environment. Explicit execution-environment overrides still apply. Do not print credentials or broad environment dumps.
101
+
102
+ Direct TUI commands, `!<command>` and `!!<command>`, use the same fresh login-shell execution boundary. `!` adds the result to model context; `!!` does not. Their user-facing context limit is larger than an ordinary assistant tool result, but raw process capture is still bounded.
103
+
104
+ ### Write and edit
105
+
106
+ `write` creates or overwrites a UTF-8 file and creates missing parent directories. Relative paths resolve from the execution environment's current working directory. Because it replaces the complete file, it is best for new files or intentional full rewrites.
107
+
108
+ `edit` performs one exact textual replacement in an existing UTF-8 file. `oldText` must be non-empty and match exactly once, including whitespace and newlines. Zero matches and multiple matches are rejected without changing the file. Read the current section first and make `oldText` more specific when necessary.
109
+
110
+ Neither tool provides a general read operation. Use a scoped non-interactive Bash command such as `sed`, `cat`, or a language-specific utility to inspect text. Both tools can accept absolute paths, subject to the execution environment's filesystem permissions. They are not confined to the repository root by Tau.
111
+
112
+ ### View image
113
+
114
+ `view_image` reads an image from the execution environment and returns it to a multimodal model. Tau's built-in instruction limits use to cases where the user explicitly asks to view or analyze an image.
115
+
116
+ The supported formats are JPEG, PNG, and WebP. Source reads are capped at 50 MiB. Images larger than 2,000 pixels in either dimension or 2.5 MiB of model payload are resized or re-encoded while preserving aspect ratio. If Tau cannot reduce a valid image below the model payload limit, the call fails. Relative paths resolve from the execution-environment working directory.
117
+
118
+ ## Unpack a PDF from the command line
119
+
120
+ `tau tool pdf-unpack` is a standalone utility for turning a PDF into OCR Markdown and page-image patches. It is not an agent-callable host tool. Run it from the machine that owns the input file:
121
+
122
+ ```bash
123
+ tau tool pdf-unpack ./docs/architecture.pdf
124
+ ```
125
+
126
+ The path is resolved from the command's current working directory and must name a readable file. The command requires `pdftoppm` from Poppler on `PATH`. On macOS, install it with `brew install poppler`; Debian-based Linux distributions provide it through `apt install poppler-utils`.
127
+
128
+ PDF OCR requires `MISTRAL_API_KEY` or `apiKeys.mistral`, with the environment variable taking precedence. Tau loads configuration for the command's current working directory. The credential and local executable therefore belong to the process running `tau tool`, not to an attached TUI, remote host, or session execution environment unless that is where the command itself runs. See [credentials](credentials.md) for credential ownership.
129
+
130
+ On success, Tau prints the persistent temporary output directory and a complete artifact list. The directory contains:
131
+
132
+ - `document.md`, the complete OCR document with recognized tables inlined;
133
+ - `pages/page-0001.md` and later numbered files, one Markdown file per PDF page; and
134
+ - `images/page-0001/patch-0001.png` and later numbered patches for visual verification.
135
+
136
+ OCR text can contain recognition mistakes. Embedded visuals that are not represented in Markdown are marked with placeholders pointing to the corresponding page patches. Read `document.md` for the whole document, use `pages/` for page-level work, and inspect `images/` before trusting or correcting uncertain OCR.
137
+
138
+ The command uploads the PDF to Mistral and attempts to delete the remote upload after OCR. A deletion failure is reported in the command output. Successful local artifacts remain on disk for follow-up use; delete them when they are no longer needed. If processing fails, Tau attempts to remove the partial local output directory. Do not use the command for a sensitive document unless sending it to Mistral and retaining derived local artifacts are both permitted.
139
+
140
+ ## Code-mode service tools
141
+
142
+ `web`, `history`, and `nook` each run a one-shot JavaScript program in Tau's restricted code-mode runtime. They intentionally disclose their exact API at use time rather than embedding signatures in this page.
143
+
144
+ The first useful call must only print the tool's documentation:
145
+
146
+ ```js
147
+ console.log(docs);
148
+ ```
149
+
150
+ Read that result before making a later call that uses the documented API. Do not guess signatures or copy signatures from another code-mode tool. Program return values are ignored; print only the information needed for the task.
151
+
152
+ Code-mode programs have no direct process, environment, credential, import, timer, network, or `fetch` access. They can call only the named API and use agent-scoped scratch files exposed by the runtime. Calls default to a 60-second deadline, allow at most 128 API requests with no more than eight unresolved at once, and limit each serialized request or response to 1 MiB. Console output is middle-truncated above roughly 8,192 estimated tokens.
153
+
154
+ Scratch files are real UTF-8 files in an execution-environment temporary directory shared by code-mode tools for the same agent. Writes are limited to 128 regular files and 64 MiB total. Scratch state is not stored in the session snapshot. The progressively disclosed documentation gives the exact file API.
155
+
156
+ ### Web
157
+
158
+ `web` is for open-web search and webpage extraction when repository data, a purpose-built CLI, a first-party API or SDK, or another structured source cannot answer the task. For GitHub issues, pull requests, releases, and repository metadata, use `gh`; for checked-out source and history, use Git.
159
+
160
+ Web discovery can inspect an ordinary URL through the execution environment without an Exa credential. Search and content extraction require an effective Exa API key. The tool's documentation explains the discovery-first flow and when to retrieve advertised agent-friendly resources with Bash instead of webpage extraction. See [credentials](credentials.md) for key resolution.
161
+
162
+ ### History
163
+
164
+ `history` searches and reads durable Tau transcripts. It is read-only and can have visibility across repositories and execution environments, so use it only when the user or another active instruction directly asks to consult prior sessions. Do not invoke it merely because old context might be useful.
165
+
166
+ The effective history query may be machine-local or backed by a configured remote collection. See [history](history.md) for storage, replication, and access scope.
167
+
168
+ ### Nook
169
+
170
+ `nook` manages the configured Nook static mini-app platform. It is available only to a main-session persona that lists `nook` and only when Nook is configured. Subagents cannot receive it.
171
+
172
+ Use it when the user asks to inspect or manage Nook, publish a static artifact or mini-app, or work with Nook KV. After the initial `docs` call, app-authoring work requires a second separate documentation-only call that prints the Nook authoring skill. Read that guide before creating or modifying app files. Nook setup and platform behavior are covered in [Nook](nook.md).
173
+
174
+ ## Subagent tool eligibility
175
+
176
+ A subagent can receive only:
177
+
178
+ ```text
179
+ bash write edit view_image web history
180
+ ```
181
+
182
+ A subagent definition may list an exact subset. If it omits `tools`, Tau inherits the intersection of the main persona's tools and those six eligible names. Duplicate names are normalized. `tau_docs` is then added intrinsically regardless of the subset.
183
+
184
+ Subagents do not receive Nook, goal tools, subagent-management tools, or client-provided tools. Their Bash and file tools are scoped to the subagent working directory, including an alternate directory selected at launch. See [subagents](subagents.md) for configuration and working-directory context rebuilding.
185
+
186
+ ## Client-owned tools
187
+
188
+ The TUI advertises `diff_review` and `prefill_input` unless client tools are disabled. `diff_review` captures repository state through session execution and runs the review interface on the TUI machine. `prefill_input` places a draft in an empty TUI editor; it does not submit text and refuses to overwrite an existing draft.
189
+
190
+ Configured command client tools are also client-owned. They can run local client processes and use a bounded execution-environment facade when work belongs on the session machine. Remote attachment makes this distinction visible: the TUI process and its tools may be on a laptop while the host and execution environment are elsewhere. See [client tools](client-tools.md) for configuration, protocol helpers, and limits, and [TUI](tui.md) for diff-tool configuration.
191
+
192
+ ## When a tool is missing or fails
193
+
194
+ First identify which owner should provide it:
195
+
196
+ - For a host tool, inspect the active persona's `tools`, effective host configuration, and service credentials.
197
+ - For a subagent tool, inspect both the subagent's explicit list and the eligible inherited set.
198
+ - For a client tool, confirm that an observing client advertises it and that client tools were not disabled.
199
+ - For `tau_docs` or main-session goal tools, a missing schema indicates a runtime or version problem rather than a persona setting.
200
+
201
+ Then check the execution boundary named in the error. A path that exists on the TUI client may not exist in the execution environment. A command available in the host's `PATH` may not be available in the execution environment's login shell. Client process errors belong to the client machine, while `executionEnvironment.exec` errors belong to the session machine.
202
+
203
+ Use `tau --debug --persona <id>` for the host-tool schemas of a new local TUI session. `/reload` refreshes host configuration and persona content for an idle session, but it does not restart or re-advertise tools owned by an attached client. See [troubleshooting](troubleshooting.md) and [security](security.md) for boundary-specific checks.