Prerequisites
Install Rust and add the WASM target:1. Create the project structure
Create a new crate with this layout:2. Configure Cargo.toml
Cargo.toml
3. Implement the channel interface
Implement the channel guest interface fromwit/channel.wit:
Required Imports
Implementing the Guest Trait
on_start configures how the channel registers with its platform API. The manifest’s [channel.ingress] controls how the host routes inbound webhooks — they are separate concerns. on_http_request and on_poll ingest external messages; on_respond delivers replies to an existing conversation; on_broadcast sends proactive messages; on_status lets channels surface thinking indicators and other progress updates.4. Preserve routing metadata (critical)
Once your channel can receive messages, keep enough metadata to send responses back to the right chat and sender. Store routing info in message metadata so responses can be delivered to the right chat and sender.response.metadata_json contains the metadata from the original inbound message. Treat it as the source of truth for reply routing.5. Add secure credential placeholders
Now that the message path is set, configure API credentials using placeholders instead of hardcoded tokens.URL Placeholders (Telegram-style)
Header Placeholders (WhatsApp-style)
{SECRET_NAME} where SECRET_NAME matches the credential name in uppercase with underscores (e.g., whatsapp_access_token → {WHATSAPP_ACCESS_TOKEN}).
6. Create the extension manifest
Channels are installed as extensions. The manifest declares the runtime surface and channel configuration in TOML format:my-channel/manifest.toml
7. Build and install
Build the WASM component and place it in the extension asset directory alongside the manifest.crates/extensions/packages/<channel>/ (manifest + schemas + prompts + WASM) with a package module crates/extensions/ironclaw_extension_support/src/packages/<channel>.rs and its row in PACKAGES in .../src/packages/mod.rs — there is no separate registration file.
At runtime every package is discovered at the virtual package root /system/extensions/<extension-id>/manifest.toml. Users install discovered packages by ID: ironclaw extension search lists them, and ironclaw extension install <extension-id> installs one — it takes an extension ID from search results, not a filesystem path. The WebUI Extensions area exposes the same list/install/import/remove lifecycle. For local development, place the extension directory under <reborn-home>/local-dev/system/extensions/<channel>/.
8. Host functions you can call
Core APIs (every channel uses these)
Advanced APIs (pairing, attachments)
Channels that download binary payloads (voice notes, images) or support owner approval for unknown senders can use these:9. Common patterns
Polling with stored offsets
Ignore status-only payloads
Ignore bot senders
10. Testing and troubleshooting
Add tests for message parsing and metadata round-trips. The key assertions are that routing metadata is preserved through serialization:byte index N is not a char boundary, avoid byte slicing and truncate by characters:
- Verify secret names match the declared placeholders in the manifest.
- Confirm the credential handle matches what the channel code expects.
- Check runtime logs for unresolved placeholder warnings.