Summary
Notification / delivery targets across NetClaw's automation surfaces — inbound webhook routes and reminders — require a raw platform channel ID (e.g. a Slack channel id like C0XXXXXXXXX). Operators think in channel names (#netclaw-customer-ops), so this is recurring friction: it's easy to paste the wrong ID, and you can't eyeball a route/reminder file and tell where it delivers.
Current state (verified on a live 0.25.0-alpha.onnx.7 instance)
- Webhook route —
netclaw webhooks set … --notification-channel <id> → stored as
notificationTarget: { "kind": "Slack", "channelId": "C0XXXXXXXXX" }.
- Reminder — delivery is stored as
delivery: { "kind": "Channel", "transport": "slack", "address": "C0XXXXXXXXX" }.
- Both take the raw ID only; there's no name-based input, and the ID is what's persisted.
- Aside worth noting: the two features model the same "where to notify" concept in different shapes —
notificationTarget.channelId vs delivery.address + transport. Unifying them would be nice, but the ID friction is the primary ask here.
Proposal
Accept a human-readable channel name as input on both surfaces, resolve it to an ID at set/create time via the transport's API (the daemon already holds the token), and store the resolved ID (stable across renames). Echo the resolution back, e.g. resolved '#netclaw-customer-ops' → C0XXXXXXXXX.
Design nuance — per-transport, with graceful fallback
Name resolution only works cleanly where names are unique/unambiguous:
- Slack — channel names are unique per workspace →
#name resolves to exactly one ID. Clean.
- Discord — allows duplicate channel names, scoped by guild → category, so a bare name is ambiguous; needs guild (and maybe category) context or a qualified form.
- Mattermost — channel slugs are per-team; needs team context.
So the contract should be layered:
- ID is always accepted — the universal, rename-proof input. Unchanged.
- Name is opt-in ergonomic sugar, resolved only when unambiguous; on ambiguity, fail with the candidate list (or require a qualified form like
guild/channel / team/channel).
- Never store a bare name (it breaks on rename) — always persist the resolved ID.
This is "optional per-transport name resolution that falls back to ID," not "names instead of IDs."
Scope
- Webhook
set_webhook tool + netclaw webhooks set CLI (--notification-channel).
- Reminder
set_reminder tool + netclaw reminder create CLI (--address / --transport).
- Resolution is per-transport, Slack first (it's the clean case); other transports keep accepting IDs / qualified forms.
Summary
Notification / delivery targets across NetClaw's automation surfaces — inbound webhook routes and reminders — require a raw platform channel ID (e.g. a Slack channel id like
C0XXXXXXXXX). Operators think in channel names (#netclaw-customer-ops), so this is recurring friction: it's easy to paste the wrong ID, and you can't eyeball a route/reminder file and tell where it delivers.Current state (verified on a live
0.25.0-alpha.onnx.7instance)netclaw webhooks set … --notification-channel <id>→ stored asnotificationTarget: { "kind": "Slack", "channelId": "C0XXXXXXXXX" }.delivery: { "kind": "Channel", "transport": "slack", "address": "C0XXXXXXXXX" }.notificationTarget.channelIdvsdelivery.address+transport. Unifying them would be nice, but the ID friction is the primary ask here.Proposal
Accept a human-readable channel name as input on both surfaces, resolve it to an ID at set/create time via the transport's API (the daemon already holds the token), and store the resolved ID (stable across renames). Echo the resolution back, e.g.
resolved '#netclaw-customer-ops' → C0XXXXXXXXX.Design nuance — per-transport, with graceful fallback
Name resolution only works cleanly where names are unique/unambiguous:
#nameresolves to exactly one ID. Clean.So the contract should be layered:
guild/channel/team/channel).This is "optional per-transport name resolution that falls back to ID," not "names instead of IDs."
Scope
set_webhooktool +netclaw webhooks setCLI (--notification-channel).set_remindertool +netclaw reminder createCLI (--address/--transport).