Skip to content

feat(agent): add /btw one-off side-question command#2502

Closed
lxowalle wants to merge 15 commits intosipeed:mainfrom
lxowalle:feat/suppoer_btw_command
Closed

feat(agent): add /btw one-off side-question command#2502
lxowalle wants to merge 15 commits intosipeed:mainfrom
lxowalle:feat/suppoer_btw_command

Conversation

@lxowalle
Copy link
Copy Markdown
Collaborator

@lxowalle lxowalle commented Apr 13, 2026

📝 Description

Summary

  • add a new /btw <question> built-in command for one-off side questions
  • route /btw through a priority command path so it can bypass the normal queued turn flow and reply immediately
  • keep /btw requests and replies out of persisted session history while preserving routed agent/session metadata on immediate replies
  • update command runtime/tests and refresh localized chat/configuration docs to include /btw

Why

This adds a lightweight way to ask a quick side question while another turn is busy, without appending the /btw request or reply to the active session history.

Behavior Notes

  • /btw is a temporary side-question message, not part of the main session turn flow.
  • /btw does not persist into the active session history.
  • /btw is independent from /use: pending skill overrides armed by /use <skill> apply to the next regular session message, not to /btw.

Changes

  • register /btw in the built-in command registry
  • add a dedicated /btw command handler and runtime hook
  • implement agent-loop support to:
    • detect /btw as a priority command in the steering path
    • execute /btw immediately instead of enqueueing it behind the current turn
    • keep the /btw exchange out of persisted session history
    • preserve the routed agent/session metadata when publishing immediate /btw replies
  • add tests covering:
    • command execution and usage validation
    • non-persistent history behavior
    • steering tests for priority execution / queue bypass behavior and outbound metadata preservation
  • update documentation and Telegram command-menu references in localized docs

Testing

  • added unit tests for /btw command handling
  • added agent loop tests for no-history persistence behavior
  • added steering tests for priority execution / queue bypass behavior and outbound metadata preservation

🗣️ Type of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📖 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

🔗 Related Issue

📚 Technical Context (Skip for Docs)

  • Reference URL:
  • Reasoning:

🧪 Test Environment

  • Hardware:
  • OS:
  • Model/Provider:
  • Channels:

📸 Evidence (Optional)

Click to view Logs/Screenshots

☑️ Checklist

  • My code/docs follow the style of this project.
  • I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.

@lxowalle lxowalle changed the title feat(agent): add /btw side-question command feat(agent): add /btw one-off side-question command Apr 13, 2026
fix(agent): route /btw replies through the active agent

Reset /btw priority replies against the routed agent instead of the default one so busy-turn responses are not suppressed in multi-agent flows. Also stop onboarding from copying legacy workspace template files so the generated workspace matches the current structured layout and checks stay green.

fix(agent): suppress duplicate replies across agents

fix(agent): isolate /btw replies from busy-turn sends
@sipeed-bot sipeed-bot bot added type: enhancement New feature or request domain: agent labels Apr 13, 2026
Comment thread pkg/agent/loop.go
media = append([]string(nil), opts.Media...)
activeSkills = activeSkillNames(agent, *opts)

if !opts.NoHistory {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/btw loses the live session context.

This implementation only reassembles the session summary and then calls BuildMessages with nil history, so the /btw request does not see the current conversation state unless it has already been compacted into the summary.

That creates a real behavior gap for the feature as described. A side question such as “what did we decide above?” or “can you expand on the previous point?” may fail during an active turn because the recent turns are still in history, not in the summary. In contrast, the normal turn path includes both history and summary, so /btw is now operating on materially less context than the main conversation.

I think /btw needs to preserve the same read context as the active session while only skipping persistence of the /btw exchange itself. Otherwise this will produce inconsistent and confusing answers in exactly the situations where users are most likely to use the command.

Comment thread pkg/agent/loop.go
}
}

callProvider := func(ctx context.Context, provider providers.LLMProvider, model string) (*providers.LLMResponse, error) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/btw bypasses the normal tool and hook pipeline.

This path calls provider.Chat directly with nil tools, which means /btw no longer behaves like a normal agent turn. Side questions cannot use the agent’s configured tools, and any logic enforced in the standard turn pipeline (for example LLM hooks, policy checks, request mutation, or approval gates) is skipped entirely.

That is a much larger semantic change than “do not persist /btw in session history”. It effectively introduces a second execution model for the same agent, with different capabilities and different enforcement points. Even if the no-history behavior is intentional, bypassing tools and hooks is likely to create hard-to-debug inconsistencies between a normal prompt and the same prompt sent through /btw.

Unless /btw is explicitly intended to be a stripped-down raw-model query, I think this should be routed through the normal agent execution path with a “do not persist” option, rather than calling the provider directly.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/btw no need to call the tool; it's currently just for quick Q&A.

Comment thread pkg/agent/loop.go Outdated
// Handle priority commands (e.g. /btw) immediately instead of queueing them.
if handled, response := al.tryHandlePriorityCommand(ctx, msg); handled {
if response != "" {
al.bus.PublishOutbound(ctx, bus.OutboundMessage{
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Immediate /btw replies drop reply metadata.

The fast path publishes an outbound message with only Channel, ChatID, and Content. It does not preserve ReplyToMessageID or the normalized outbound context used by the regular response path.

On reply-capable channels, that can cause the /btw response to be posted as a detached top-level message instead of replying to the triggering message/thread. This looks like a regression in delivery behavior even if the text content itself is correct.

lxowalle

This comment was marked as resolved.

Keep /btw aligned with the standard LLM hook pipeline so side questions do not bypass request and response interception. Clarify across docs that /btw remains an immediate, no-tool query that does not persist session history.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants