Skip to content
3 changes: 1 addition & 2 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,7 @@ from step 4 and @mention the agent:
```bash
export SPROUT_PRIVATE_KEY=$SENDER_SK # the key from step 4
sprout messages send --channel "$CHANNEL" \
--content "Hey agent, reply PONG only." \
--mention "$AGENT_PUBKEY"
--content "Hey agent, reply PONG only."

# Wait 10–90s, then read the channel — the agent's reply is a kind:9 from
# AGENT_PUBKEY. The current ACP build is quiet on stdout during a turn, so
Expand Down
7 changes: 6 additions & 1 deletion crates/sprout-acp/src/base_prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ Run `sprout --help` or `sprout <group> --help` for full usage.
## Communication Patterns

- Address agents and humans with plain `@name` — do NOT bold or italicize mention text (formatting prevents alert delivery).
- Writing `@name` in message content triggers a notification to that person. Only include `@name` when you intend to notify them and need their attention or response. Do not use `@name` in narrative or status updates (e.g., "let me coordinate with @Duncan on this") — save it for the message where you actually need their response.
- Respond promptly to @mentions.
- Be direct. State what you did, what you found, or what you need. No preamble.
- Message content supports GitHub-flavored Markdown. Use fenced code blocks with a language tag (` ```python `, ` ```typescript `, etc.) for syntax-highlighted rendering on desktop and mobile. Omitting the language tag renders monochrome.
- Use `sprout messages thread` when responding in-thread; post new messages for new topics.
- When responding in-thread, use `sprout messages send --reply-to <thread-root-event-id>` to keep replies scoped to the thread. Post new top-level messages for new topics.
- When you are mentioned in multiple threads, prioritize the most recent one chronologically. If someone steers or redirects you in a newer thread while you are working from an older dispatch, reply in the newer thread to acknowledge — do not bury your response in the original thread where it may go unseen.
- When you complete a task (e.g., PR created, implementation finished, research delivered), post a top-level channel message with the result — do not only reply in-thread. Thread notifications are easy to miss; a broadcast message ensures the requester sees the outcome promptly.
- No push notifications — poll with `sprout messages get --channel <UUID> --since <ts>`. When `since` is set without `before`, results are oldest-first (chronological).

## Startup Recovery
Expand Down
5 changes: 2 additions & 3 deletions crates/sprout-cli/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,8 @@ REPLY=$(sprout messages send --channel "$CHANNEL_ID" --content "Reply" \
echo "$REPLY"
REPLY_ID=$(echo "$REPLY" | jq -r '.event_id')

# messages send with mentions
sprout messages send --channel "$CHANNEL_ID" --content "Hey @someone" \
--mention "0000000000000000000000000000000000000000000000000000000000000001" | jq .
# messages send with mentions — @name in content is auto-resolved, no flag needed
sprout messages send --channel "$CHANNEL_ID" --content "Hey @someone" | jq .

# messages send from stdin — safe path for content with shell metacharacters
# (backticks, $vars, code blocks) that would otherwise be expanded by the shell.
Expand Down
19 changes: 3 additions & 16 deletions crates/sprout-cli/src/commands/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ use crate::validate::{
infer_language, parse_event_id, parse_uuid, read_or_stdin, truncate_diff,
validate_content_size, validate_hex64, validate_uuid, MAX_DIFF_BYTES,
};
use sprout_sdk::mentions::{
extract_at_names, match_names_to_profiles, merge_mentions, normalize_mention_pubkeys,
MentionProfile, MENTION_CAP,
};
use sprout_sdk::mentions::{extract_at_names, match_names_to_profiles, MentionProfile};

// ---------------------------------------------------------------------------
// Helpers
Expand Down Expand Up @@ -348,7 +345,6 @@ pub struct SendMessageParams {
pub kind: Option<u16>,
pub reply_to: Option<String>,
pub broadcast: bool,
pub mentions: Vec<String>,
pub files: Vec<String>,
}

Expand All @@ -365,10 +361,6 @@ pub async fn cmd_send_message(
if let Some(ref r) = p.reply_to {
validate_hex64(r)?;
}
for m in &p.mentions {
validate_hex64(m)?;
}

let channel_uuid = parse_uuid(&p.channel_id)?;

// Upload files and build imeta tags
Expand Down Expand Up @@ -402,13 +394,10 @@ pub async fn cmd_send_message(
None
};

// Normalize explicit mentions, then merge auto-resolved up to the SDK mention cap.
// Auto-resolution scans the author-written body only — not the media markdown we
// Resolve @name mentions in the author-written body only — not the media markdown we
// append above, which is derived from upload metadata and can't carry `@names`.
let mut merged: Vec<String> = normalize_mention_pubkeys(&p.mentions, None);
let auto_resolved = resolve_content_mentions(client, &p.channel_id, &p.content).await;
merge_mentions(&mut merged, &auto_resolved, MENTION_CAP);
let mention_refs: Vec<&str> = merged.iter().map(|s| s.as_str()).collect();
let mention_refs: Vec<&str> = auto_resolved.iter().map(|s| s.as_str()).collect();

let builder = match p.kind {
Some(45001) => {
Expand Down Expand Up @@ -630,7 +619,6 @@ pub async fn dispatch(
kind,
reply_to,
broadcast,
mentions,
files,
} => {
cmd_send_message(
Expand All @@ -641,7 +629,6 @@ pub async fn dispatch(
kind,
reply_to,
broadcast,
mentions,
files,
},
)
Expand Down
3 changes: 0 additions & 3 deletions crates/sprout-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,6 @@ pub enum MessagesCmd {
/// Also publish to the Nostr network
#[arg(long, default_value_t = false)]
broadcast: bool,
/// Explicit mention pubkeys (64-char hex)
#[arg(long = "mention")]
mentions: Vec<String>,
/// Attach file(s) — uploads and includes as imeta tags
#[arg(long = "file")]
files: Vec<String>,
Expand Down
13 changes: 4 additions & 9 deletions desktop/src-tauri/src/managed_agents/nest_skill.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,14 @@ Write commands are unaffected. `--format json` (default) returns full fields.

## Communication Patterns

**Mentions that notify:** Always include `--mention <hex_pubkey>` for each person you `@`-mention in content. The `@Name` text is display-only — without the corresponding `--mention` flag, no notification fires. Look up pubkeys with `sprout users get --name <display_name>`.
**Mentions that notify:** Use `@Name` directly in message content — the CLI auto-resolves channel members by name and adds the required p-tags. No `--mention` flag exists or is needed.

```bash
# ✅ Correct — notification delivered
sprout messages send --channel <UUID> --content "@Alice check this" \
--mention deadbeef1234...

# ❌ Wrong — mention is cosmetic only, no notification
# ✅ Correct — notification delivered automatically
sprout messages send --channel <UUID> --content "@Alice check this"

# Multiple mentions
sprout messages send --channel <UUID> --content "@Alice @Bob review please" \
--mention <alice_hex> --mention <bob_hex>
# Multiple mentions — same pattern
sprout messages send --channel <UUID> --content "@Alice @Bob review please"
```

## DM Management
Expand Down