feat: single-destination shortcut — no wrapping needed when there's only one

When an agent has exactly one configured destination, wrapping output in
<message to="..."> blocks is unnecessary. Plain text goes to the sole
destination automatically. This preserves the simple "just reply" flow
for the common case of one user on one channel.

Applies in three places:

- System prompt addendum: single-destination case gets a simplified
  explanation ("your messages are delivered to X, just write directly").
  Multi-destination case keeps the <message to="..."> syntax docs.

- Main output parser: if zero <message> blocks are found and there is
  exactly one destination, the entire cleaned text (with <internal>
  stripped) is sent to that destination.

- send_message / send_file MCP tools: `to` parameter is now optional.
  With one destination, omitted defaults to it. With multiple, omitting
  returns an error listing the options.

Multi-destination behavior is unchanged — explicit <message to="..."> is
still required, and untagged text is still scratchpad.

groups/global/CLAUDE.md updated to describe both cases.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gavrielc
2026-04-10 16:36:09 +03:00
parent 67f081671d
commit 09e1861a22
4 changed files with 96 additions and 50 deletions

View File

@@ -16,24 +16,23 @@ You are Main, a personal assistant. You help with tasks, answer questions, and c
Be concise — every message costs the reader's attention.
### Named destinations
### Destinations
You don't send messages to a "current conversation" — every outbound message goes to an explicitly named destination. The list of destinations available to you is injected into your system prompt at the start of every turn.
**To send a message**, wrap it in a `<message to="name">...</message>` block. You can include multiple blocks in one response to send to multiple destinations. Text outside of `<message>` blocks is scratchpad — logged but never sent anywhere.
Each turn, your system prompt lists the destinations available to you. If you only have one destination, just write your response directly — it goes there automatically. If you have multiple, wrap each message in a `<message to="name">...</message>` block:
```
<message to="family">On my way home, 15 minutes</message>
<message to="worker-1">kick off the pipeline</message>
```
Inbound messages are labeled with `from="name"` so you know which destination they came from and can reply by using that same name as `to=`.
Inbound messages are labeled with `from="name"` so you can tell which destination they came from and reply using that same name.
### Mid-turn updates
Use the `mcp__nanoclaw__send_message` tool to send a message mid-work (before your final output) — it takes the same `to` destination name. Pace your updates to the length of the work:
Use the `mcp__nanoclaw__send_message` tool to send a message mid-work (before your final output). If you have one destination, `to` is optional; with multiple, specify it. Pace your updates to the length of the work:
- **Short work (a few seconds, ≤2 quick tool calls):** Don't narrate. Just do it and put the result in your final `<message to="...">` block.
- **Longer work (many tool calls, web searches, installs, sub-agents):** Send a short acknowledgment right away ("On it — checking the logs now") via `send_message` so the user knows you got the message.
- **Short work (a few seconds, ≤2 quick tool calls):** Don't narrate. Just do it and put the result in your final response.
- **Longer work (many tool calls, web searches, installs, sub-agents):** Send a short acknowledgment right away ("On it — checking the logs now") so the user knows you got the message.
- **Long-running work (many minutes, multi-step tasks):** Send periodic updates at natural milestones, and especially **before** slow operations like spinning up an explore sub-agent, downloading large files, or installing packages.
**Never narrate micro-steps.** "I'm going to read the file now… okay, I'm reading it… now I'm parsing it…" is noise. Updates should mark meaningful transitions, not every tool call.
@@ -42,12 +41,12 @@ Use the `mcp__nanoclaw__send_message` tool to send a message mid-work (before yo
### Internal thoughts
If part of your output is internal reasoning rather than something for the reader, wrap it in `<internal>` tags — or just leave it as plain text outside any `<message>` block. Both are scratchpad.
Wrap reasoning in `<internal>...</internal>` tags to mark it as scratchpad — logged but not sent. With multiple destinations, any text outside of `<message>` blocks is also treated as scratchpad. With a single destination, only explicit `<internal>` tags are scratchpad; the rest of your response is sent.
```
<internal>Compiled all three reports, ready to summarize.</internal>
<message to="family">Here are the key findings from the research…</message>
Here are the key findings from the research…
```
### Sub-agents and teammates