feat: auto-onboarding when a channel is registered

After wiring a channel to an agent group, register.ts writes a task
message to the session that triggers the /welcome container skill.
The agent introduces itself immediately — the user sees typing and
then a greeting without having to send a message first.

Uses kind 'task' (not 'system') so the poll loop picks it up normally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gavrielc
2026-04-09 13:48:56 +03:00
parent a2badbd525
commit 4a999ec973
2 changed files with 42 additions and 2 deletions

View File

@@ -0,0 +1,25 @@
---
name: welcome
description: Introduce yourself to a newly connected channel. Triggered automatically when a channel is first wired. Send a friendly greeting and brief overview of what you can do.
---
# /welcome — Channel Onboarding
You've just been connected to a new messaging channel. Introduce yourself to the user.
## What to do
1. Send a short, friendly greeting using `send_message`
2. Mention your name (from your CLAUDE.md)
3. Briefly describe 2-3 things you can help with based on your configured skills and tools
4. Keep it to 2-4 sentences — don't overwhelm
## Tone
Warm but concise. This is a first impression — be helpful, not verbose. Match the channel's vibe (casual for Telegram/Discord, slightly more professional for Slack/Teams/email).
## Example
> Hey! I'm Andy, your assistant. I can help with coding tasks, answer questions, manage scheduled reminders, and work with files. Just send me a message anytime.
Adapt based on your actual name and capabilities. Don't list every tool — pick the most useful ones.

View File

@@ -19,6 +19,7 @@ import {
} from '../src/db/messaging-groups.js';
import { isValidGroupFolder } from '../src/group-folder.js';
import { log } from '../src/log.js';
import { resolveSession, writeSessionMessage } from '../src/session-manager.js';
import { emitStatus } from './status.js';
interface RegisterArgs {
@@ -190,7 +191,21 @@ export async function run(args: string[]): Promise<void> {
log.info('Wired agent to messaging group', { mgaId, agentGroup: agentGroup.id, messagingGroup: messagingGroup.id });
}
// 4. Create group folders
// 4. Send onboarding message — triggers the /welcome skill in the container
const { session } = resolveSession(agentGroup.id, messagingGroup.id, null, parsed.sessionMode as 'shared' | 'per-thread' | 'agent-shared');
writeSessionMessage(agentGroup.id, session.id, {
id: generateId('onboard'),
kind: 'task',
timestamp: new Date().toISOString(),
platformId: parsed.platformId,
channelType: parsed.channel,
content: JSON.stringify({
prompt: `A new ${parsed.channel} channel has been connected. Run /welcome to introduce yourself to the user.`,
}),
});
log.info('Onboarding message written', { sessionId: session.id, channel: parsed.channel });
// 5. Create group folders
fs.mkdirSync(path.join(projectRoot, 'groups', parsed.folder, 'logs'), { recursive: true });
// Create CLAUDE.md from template if it doesn't exist
@@ -205,7 +220,7 @@ export async function run(args: string[]): Promise<void> {
}
}
// 5. Update assistant name in CLAUDE.md files if different from default
// 6. Update assistant name in CLAUDE.md files if different from default
let nameUpdated = false;
if (parsed.assistantName !== 'Andy') {
log.info('Updating assistant name', { from: 'Andy', to: parsed.assistantName });