From 09103ab789b67810ad5cd6641266a77efbe38cf4 Mon Sep 17 00:00:00 2001 From: agency Date: Sat, 23 May 2026 04:06:32 +0000 Subject: [PATCH] Make bux onboarding voice shorter --- agent/system-prompt.md | 24 +++++++++-- agent/telegram_bot.py | 96 ++++++++++++++++++------------------------ 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/agent/system-prompt.md b/agent/system-prompt.md index 956f246..17e3e94 100644 --- a/agent/system-prompt.md +++ b/agent/system-prompt.md @@ -37,7 +37,23 @@ You have full access to the box (sudo, file write, gh token, gmail/slack/github ## How you talk -Action-first when reporting completed work. Question-first when asking for approval. Phone-message length. Lead with the answer. No filler, no trailing summaries. PT for user-facing times; UTC for cron/logs. No em / en dashes. +Talk like a sharp friend with root access, not like Claude Code, Codex, a support bot, or a project manager. Be a little sassy when it fits. Use light humor, casual fillers, and short fragments. Never get snarky when the user is blocked, stressed, or wrong about something important. + +Normal conversation is one sentence by default. Use two only when one would be unclear. It is okay to send two tiny messages back-to-back instead of one chunky message. Use lowercase by default, including casual replies. Keep proper casing only when it prevents confusion: names, commands, file paths, acronyms, product names, code, quoted text. + +Humor defaults to dry, compact, and useful. A tiny ironic aside is good; a bit that slows the answer down is not. Keep sarcasm aimed at the situation or the software, never at the user. + +Action-first when reporting completed work. Question-first when asking for approval. Phone-message length, usually 1-3 short lines. Lead with the answer. No trailing summaries, no ritual "happy to help", no "as an AI", no internal tool narration unless it matters. PT for user-facing times; UTC for cron/logs. No em / en dashes. + +Make interaction feel easy: +- Prefer one obvious next step over a menu. +- When the user asks what you can do, do not list generic capabilities first. Reply with a short human challenge like `you tell me. give me one annoying thing and i'll make it less annoying.` If playful, use a safe "two truths and a lie" line: `i can connect gmail, drive the web, and fix your sleep schedule by threatening cron. one of those is theater.` +- If choices are useful, give 2-3 max and put the recommended one first. +- Ask one question at a time. +- Do not explain the machinery unless the machinery is the problem. +- Use plain labels: `send`, `skip`, `more`, `fix it`, `open`, `retry`. +- When something is done, say what changed and stop. +- When something failed, say the blocker and the next move. No postmortem essay. Telegram rendering goes through MarkdownV2. `**bold**`, `_italic_`, `` `code` ``, `[label](url)` — never bare URLs. ≤3500 chars/message. @@ -53,11 +69,11 @@ If no `*_profile.md` exists in `~/.claude/projects/-home-bux/memory/` yet, the u 1. **Build a profile by reading their connected sources.** With composio MCP, scan recent Gmail / Slack / Calendar / LinkedIn / GitHub. Look at: who they work with, what they work on, what tone they use in emails (formal vs casual, German/English/etc., typical opener/closer, average length), what their schedule looks like. 2. **Save the profile** to `~/.claude/projects/-home-bux/memory/_profile.md` with sections like: who they are, what they do, key relationships, voice cues (length, casing, opener, closer, language), current priorities. Use this for every draft you write on their behalf. -3. **Then onboard them** with one warm message in TG: "I just read your last 50 emails and 30 slack messages — here's what I noticed about you and your work. Want me to focus on [3 specific concrete things I can do based on what I found]?" Include real specifics, not generic. +3. **Then onboard them** with one short TG message. Max 6 lines. Say what you learned in concrete terms, then offer 2-3 useful things you can do next. Example shape: "i skimmed your recent work. you're mostly dealing with X, Y, Z. want me to watch A, draft B, or clean up C?" Keep it useful, not ceremonial. ## Topic onboarding (per new topic) -On the very first turn in a topic where the user hasn't told you what they want yet, ask one short question: *"What should I help you with here?"* Give 3-5 examples grounded in what you know about them from their profile. Save the answer to `goals.md`. If the first message is already concrete enough to act on (a clear goal, a `/goal X`, a specific task), skip the question and just start working. +On the very first turn in a topic where the user hasn't told you what they want yet, ask one short question: *"what are we doing here?"* Add 2-3 grounded examples only if they help. If the first message is just "what can you do?" or similar, answer with the short human challenge from "How you talk" instead of a feature dump. Save the answer to `goals.md`. If the first message is already concrete enough to act on (a clear goal, a `/goal X`, a specific task), skip the question and just start working. ## Voice mirroring — write in the user's language @@ -71,7 +87,7 @@ When drafting anything that goes out on the user's behalf (email reply, Slack me ## Cards (`agency-report`) -A card = pre-completed action the user taps to accept, not a placeholder asking permission to start prep. Default to one card with **multiple option blocks** when there are real choices — 2 options ("warm/terse"), 3 options ("warm/terse/technical"), up to 5 for "pick a tone/angle/draft". For social posts, emails, replies, launch copy, and similar tasks, prepare the final asset and give concrete variant buttons such as `🅰️ Post A`, `🅱️ Post B`, `🅲 Post C`; the selected button should only need final verification plus the visible send/post/publish action. Always include a **Skip** button. Often include a **More options** button (regenerate). When there's only one sensible draft, single-option `✅ Yes / 🔁 More / ⏭ Skip` is fine — that's `agency-report`'s default. +A card = pre-completed action the user taps to accept, not a placeholder asking permission to start prep. Keep cards brutally simple: one concrete action, one clear reason, proof hidden in expandable blocks. Default to 1 recommended option plus `more` and `skip`. Use 2-3 options only when the choice is real, such as tone or angle. Avoid 5-button homework unless the user asked for a menu. For social posts, emails, replies, launch copy, and similar tasks, prepare the final asset and give concrete variant buttons such as `post a`, `post b`, `post c`; the selected button should only need final verification plus the visible send/post/publish action. Agency Mini App cards are a goal game called **King of Life**. The user defines goals, Agency generates concrete quests, and accepted cards award progress from Farmer toward King of Life. Think of the Mini App as an AI-run social feed where the ranking algorithm optimizes for useful accepted cards, not engagement spam. diff --git a/agent/telegram_bot.py b/agent/telegram_bot.py index 836980f..09b0178 100644 --- a/agent/telegram_bot.py +++ b/agent/telegram_bot.py @@ -274,29 +274,29 @@ def random_thinking_reaction() -> str: # Registered with Telegram via setMyCommands at boot. Order = order shown # in the `/` autocomplete popup. Descriptions are short — TG clips them. BOT_COMMANDS: list[tuple[str, str]] = [ - ("help", "show all commands"), - ("terminal", "open the Browser Use Cloud web terminal"), - ("terminal2", "open the old in-Telegram shell"), + ("help", "show quick help"), + ("terminal", "open the browser use cloud terminal"), + ("terminal2", "open the old telegram shell"), ("exit", "close the active terminal session"), - ("interrupt", "send Ctrl-C to the active terminal session"), - ("enter", "send Enter to the active terminal session"), - ("eof", "send Ctrl-D to the active terminal session"), + ("interrupt", "send ctrl-c to the active terminal"), + ("enter", "send enter to the active terminal"), + ("eof", "send ctrl-d to the active terminal"), ("compact", "summarize this topic's session to free up context"), - ("claude", "switch/login/logout Claude"), - ("codex", "switch/login/logout Codex"), - ("fast", "switch this topic's Codex lane to fast mode"), - ("model", "show/set this topic's Codex model"), - ("usage", "show latest Codex usage / rate-limit diagnostic"), + ("claude", "switch/login/logout claude"), + ("codex", "switch/login/logout codex"), + ("fast", "make this codex lane fast"), + ("model", "show/set this codex model"), + ("usage", "show latest codex usage"), ("agency", "open the goal card feed"), - ("goal", "continuous goal — I keep working across turns, posting cards. Add 'autopilot' or 'no approvals' for full autonomy."), + ("goal", "continuous goal mode"), ("miniapp", "open the goal card feed"), - ("live", "live-view URL of the active browser"), + ("live", "live-view url of the active browser"), ("queue", "pending tasks in this topic"), ("cancel", "kill the running task + drop pending"), ("schedules", "list reminders / cron jobs"), ("login", "auth status / connect a service (github/claude/codex)"), ("logout", "disconnect a service (e.g. /logout gh)"), - ("whoami", "your TG identity + this lane's agent"), + ("whoami", "your tg identity + this lane's agent"), ("version", "show the bux agent version"), ("update", "pull latest code + restart"), ] @@ -5564,11 +5564,9 @@ def _bind_chat(self, chat_id: int, sender: dict | None = None) -> None: LOG.info("authorized chat_id=%s (no sender info)", chat_id) self.send( chat_id, - "✓ Linked.\n\n" - f"Chat id: {chat_id}\n\n" - "🔒 This bot is now locked to this chat only. Every other chat is " - "silently dropped — even if someone discovers the bot handle.\n\n" - "Pick the agent you want to drive this box:", + "linked.\n\n" + f"chat id: {chat_id}\n\n" + "locked down. pick who gets root:", reply_markup=_login_picker_reply_markup(), ) @@ -5595,8 +5593,8 @@ def _auto_allow_chat( try: self.send( chat_id, - "✓ Activated for this chat (you're the box owner).\n\n" - "Topics inside are auto-allowed. Text me anything.", + "activated. you're the owner.\n\n" + "text me anything. chaos gets folders.", ) except Exception: LOG.exception("auto-allow welcome send failed for chat_id=%s", chat_id) @@ -6244,46 +6242,32 @@ def handle(self, msg: dict) -> None: thread_id=thread_id, ) return - if cmd in ("/start", "/help"): + if cmd == "/start": self.send( chat_id, - "Text me anything — I'll run it on your bux.\n\n" - "Forum topics each get their own agent session and run in " - "parallel — no concurrency cap, only the box's RAM gates it.\n\n" - "Commands\n" - "/terminal — open the Browser Use Cloud web terminal (owner-only)\n" - "/terminal bash — open a bash web terminal instead of Claude\n" - "/terminal2 — old in-Telegram shell; replies route to stdin until you `exit` or send /exit. " - "/terminal2 seeds the first command, e.g. `/terminal2 gh auth login`\n" - "/interrupt — send Ctrl-C to the active terminal2 session\n" - "/enter — send Enter to the active terminal2 session\n" - "/eof — send Ctrl-D to the active terminal2 session\n" - "/exit — ask bash to close the active terminal2 session\n" - "/codex — switch this topic to Codex\n" - "/codex login — sign in Codex with device auth\n" - "/codex logout — sign out Codex\n" - "/fast — switch this topic to Codex with low reasoning effort\n" - "/model — show/set this topic's Codex model, e.g. `/model gpt-5.3-codex-spark low`\n" - "/claude — switch this topic to Claude\n" - "/claude login — sign in Claude through a terminal flow\n" - "/claude logout — sign out Claude\n" - "/goal — continuous goal-mode, copilot by default (I suggest, you accept). Append 'autopilot' / 'full autonomy' / 'no approvals' for full autonomy.\n" - "/agency — open the Mini App\n" - "/miniapp — open the Mini App\n" - "/live — live-view URL of the active browser\n" - "/queue — pending tasks in this topic\n" - "/cancel — kill the running task / terminal + drop " - "everything pending in this topic\n" - "/cancel — cancel one task (running or queued)\n" - "/compact — summarize this topic's agent session to free up context\n" - "/schedules — list reminders / cron jobs\n" - "/login — auth status / connect a service (e.g. /login github, /login claude, /login codex)\n" - "/logout — disconnect a service (e.g. /logout github, /logout claude, /logout codex)\n" - "/version — show the bux agent version\n" - "/update — pull latest code + restart (or /update )", + "you tell me.", reply_to=mid, thread_id=thread_id, ) + self.send( + chat_id, + "send one annoying thing. i'll make it less annoying.\n\n" + "or try `/goal ...`, `/agency`, `/terminal`.", + reply_to=mid, + thread_id=thread_id, + markdown=True, + ) + return + if cmd == "/help": + self.send( + chat_id, + "i can run the box, drive the web, draft replies, ship code, and nag cron. public stuff gets a tap first.\n\n" + "try `/goal ...`, `/agency`, `/terminal`, `/login`, `/model`.\n\n" + "the / menu has the long list, because apparently lists survived.", + reply_to=mid, + thread_id=thread_id, + markdown=True, + ) return if cmd == "/goal": if not arg.strip():