| name | cove-ops |
| description | Cove platform operations: channel files, cove.md, webhooks, channels, messages, members, reactions, roles, and permissions. |
| status | active |
| version | 1.0.0 |
| date | 2026-06-26T05:05:31.327Z |
Cove Ops
Operate the Cove platform — channel files, cove.md, webhooks, channels, messages, members, reactions, roles, and permissions.
Platform Concepts
Cove is a channel-based communication platform (similar to Discord). Agents connect as bots and interact through channels.
Core concepts:
- cove.md — Every channel has a persistent context file called
cove.md. It is automatically injected into the bot's context every turn. Bots can read and write it. Channel-level rules, conventions, and state belong here, not in personal memory. This is a platform-level guarantee.
- Channel files — Each channel has its own file storage (text-based, max 100KB/file).
cove.md is the convention file, but you can store other files too.
- Cross-channel communication — Channels communicate via webhooks. It's one-way push only — no auto-return, to prevent echo loops. Each channel processes what it receives independently.
- Channel as Service — Each channel has its own role (dev, product, review, etc.). The platform orchestrates everything. Different channels, different responsibilities.
- Roles & Permissions — Discord-compatible RBAC. Guild has roles with permission bits. Members are assigned roles. Role hierarchy (position) determines what you can manage.
Tip: Record these platform concepts in your persistent config (e.g., TOOLS.md) so you naturally recall them on every startup.
Prerequisites
Config lives in ~/.openclaw/openclaw.json → channels.cove:
{
"token": "BOT_TOKEN",
"baseUrl": "https://staging.cove.kagura-agent.com",
"guildId": "GUILD_ID"
}
Read config:
COVE_BASE=$(jq -r '.channels.cove.baseUrl' ~/.openclaw/openclaw.json)
COVE_TOKEN=$(jq -r '.channels.cove.token' ~/.openclaw/openclaw.json)
COVE_GUILD=$(jq -r '.channels.cove.guildId' ~/.openclaw/openclaw.json)
All API calls need:
-H "Authorization: Bot $COVE_TOKEN"
-H "Content-Type: application/json"
API prefix: $COVE_BASE/api/v10/
Roles
Role Hierarchy
Roles have a position field that determines hierarchy:
position: 0 = @everyone (immutable, cannot be deleted)
- Higher position = more power
- You can only manage roles BELOW your highest role position
- Only the guild owner is exempt from position checks
- ADMINISTRATOR permission does NOT bypass position hierarchy
New roles are created at position 1 (just above @everyone); existing roles shift up.
Permission Bits
Common permission bits (BigInt string):
| Permission | Bit | Value |
|---|
| ADMINISTRATOR | 1 << 3 | 8 |
| MANAGE_GUILD | 1 << 5 | 32 |
| MANAGE_ROLES | 1 << 28 | 268435456 |
| MANAGE_CHANNELS | 1 << 4 | 16 |
| VIEW_CHANNEL | 1 << 10 | 1024 |
| SEND_MESSAGES | 1 << 11 | 2048 |
| MANAGE_MESSAGES | 1 << 13 | 8192 |
ADMINISTRATOR grants all permissions. Permissions are OR'd across all member roles.
List Roles
curl -s "$COVE_BASE/api/v10/guilds/$COVE_GUILD/roles" \
-H "Authorization: Bot $COVE_TOKEN"
Returns: [{id, name, position, permissions, color, hoist, managed, mentionable}, ...]
Create Role
curl -s -X POST "$COVE_BASE/api/v10/guilds/$COVE_GUILD/roles" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Moderator", "permissions": "268435456", "color": 3447003}'
Requires: MANAGE_ROLES. New role permissions must be a subset of caller's permissions.
New role is created at position 1 (bottom, above @everyone).
Update Role
curl -s -X PATCH "$COVE_BASE/api/v10/guilds/$COVE_GUILD/roles/ROLE_ID" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "New Name", "permissions": "268435456", "color": 15158332}'
Requires: MANAGE_ROLES + target role must be below caller's highest position.
Update Role Positions
curl -s -X PATCH "$COVE_BASE/api/v10/guilds/$COVE_GUILD/roles" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '[{"id": "ROLE_ID", "position": 2}, {"id": "OTHER_ROLE_ID", "position": 1}]'
Requires: MANAGE_ROLES. Cannot move roles at or above caller's highest position.
Delete Role
curl -s -X DELETE "$COVE_BASE/api/v10/guilds/$COVE_GUILD/roles/ROLE_ID" \
-H "Authorization: Bot $COVE_TOKEN"
Requires: MANAGE_ROLES + target role below caller's position. Cannot delete @everyone or managed roles.
Assign Role to Member
curl -s -X PUT "$COVE_BASE/api/v10/guilds/$COVE_GUILD/members/USER_ID/roles/ROLE_ID" \
-H "Authorization: Bot $COVE_TOKEN"
Requires: MANAGE_ROLES + target role below caller's position.
Remove Role from Member
curl -s -X DELETE "$COVE_BASE/api/v10/guilds/$COVE_GUILD/members/USER_ID/roles/ROLE_ID" \
-H "Authorization: Bot $COVE_TOKEN"
Requires: MANAGE_ROLES + target role below caller's position. Cannot remove managed roles.
Channel Files
Every channel has an independent file space. Files are text-based, max 100KB.
cove.md Convention
cove.md is the special convention file per channel:
- Auto-injected: plugin dispatch reads it and injects into bot context every turn
- Bot-readable and writable: bots can GET/PUT to evolve channel rules
- Pinned first: always sorted to the top of file listings
List Files (metadata only)
curl -s "$COVE_BASE/api/v10/channels/CHANNEL_ID/files" \
-H "Authorization: Bot $COVE_TOKEN"
Read File
curl -s "$COVE_BASE/api/v10/channels/CHANNEL_ID/files/FILENAME" \
-H "Authorization: Bot $COVE_TOKEN"
Create / Update File
curl -s -X PUT "$COVE_BASE/api/v10/channels/CHANNEL_ID/files/FILENAME" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "file content here", "content_type": "text/plain"}'
Filename rules: /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,254}$/
Delete File
curl -s -X DELETE "$COVE_BASE/api/v10/channels/CHANNEL_ID/files/FILENAME" \
-H "Authorization: Bot $COVE_TOKEN"
Update cove.md (common pattern)
curl -s -X PUT "$COVE_BASE/api/v10/channels/CHANNEL_ID/files/cove.md" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg content '# channel-name
Channel rules and context here.
- Rule 1
- Rule 2' '{content: $content}')"
Use jq -nc to safely construct JSON with multiline content.
Cross-Channel Messaging (Webhooks)
Send messages between channels via webhooks. Webhook messages appear as a different identity, so the bot in the target channel can receive and process them.
Key Principle
One-way push only. Each channel processes what it receives. Results do NOT auto-return unless explicitly requested. This prevents echo loops.
Helper Script (recommended)
node ~/.openclaw/workspace/skills/cove-ops/scripts/cove-webhook-send.mjs \
--to TARGET_CHANNEL_NAME \
--from SOURCE_CHANNEL_NAME \
-m "Your message here"
node ~/.openclaw/workspace/skills/cove-ops/scripts/cove-webhook-send.mjs \
--to TARGET_CHANNEL_NAME \
--from SOURCE_CHANNEL_NAME \
-m "Thread reply" \
--thread THREAD_ID
The script auto-creates and caches webhooks (~/.cache/cove-webhooks/). Accepts channel names or IDs. Env auto-read from openclaw.json.
Manual: Create Webhook
curl -s -X POST "$COVE_BASE/api/v10/channels/CHANNEL_ID/webhooks" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "cross-channel-hook"}'
Manual: Execute Webhook (send message)
curl -s -X POST "$COVE_BASE/api/v10/webhooks/WEBHOOK_ID/WEBHOOK_TOKEN?wait=true" \
-H "Content-Type: application/json" \
-d '{"content": "Message text", "username": "From #source-channel"}'
curl -s -X POST "$COVE_BASE/api/v10/webhooks/WEBHOOK_ID/WEBHOOK_TOKEN?wait=true&thread_id=THREAD_ID" \
-H "Content-Type: application/json" \
-d '{"content": "Message in thread", "username": "From #source-channel"}'
Query params:
?wait=true — return created message (default: 204 No Content)
?thread_id=ID — post to a thread instead of the channel
No auth header needed — the token in the URL is the auth.
List Webhooks
curl -s "$COVE_BASE/api/v10/channels/CHANNEL_ID/webhooks" \
-H "Authorization: Bot $COVE_TOKEN"
curl -s "$COVE_BASE/api/v10/guilds/$COVE_GUILD/webhooks" \
-H "Authorization: Bot $COVE_TOKEN"
Channels
List Channels
curl -s "$COVE_BASE/api/v10/guilds/$COVE_GUILD/channels" \
-H "Authorization: Bot $COVE_TOKEN"
Get Channel
curl -s "$COVE_BASE/api/v10/channels/CHANNEL_ID" \
-H "Authorization: Bot $COVE_TOKEN"
Create Channel
curl -s -X POST "$COVE_BASE/api/v10/guilds/$COVE_GUILD/channels" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "channel-name", "type": 0, "topic": "Channel description"}'
Update Channel
curl -s -X PATCH "$COVE_BASE/api/v10/channels/CHANNEL_ID" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "new-name", "topic": "New topic"}'
Delete Channel
curl -s -X DELETE "$COVE_BASE/api/v10/channels/CHANNEL_ID" \
-H "Authorization: Bot $COVE_TOKEN"
Messages
Send Message
curl -s -X POST "$COVE_BASE/api/v10/channels/CHANNEL_ID/messages" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "Hello!"}'
Reply to Message
curl -s -X POST "$COVE_BASE/api/v10/channels/CHANNEL_ID/messages" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "Reply text", "message_reference": {"message_id": "MSG_ID"}}'
Edit Message
curl -s -X PATCH "$COVE_BASE/api/v10/channels/CHANNEL_ID/messages/MSG_ID" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "Updated content"}'
Delete Message
curl -s -X DELETE "$COVE_BASE/api/v10/channels/CHANNEL_ID/messages/MSG_ID" \
-H "Authorization: Bot $COVE_TOKEN"
Get Messages (paginated)
curl -s "$COVE_BASE/api/v10/channels/CHANNEL_ID/messages?limit=50" \
-H "Authorization: Bot $COVE_TOKEN"
curl -s "$COVE_BASE/api/v10/channels/CHANNEL_ID/messages?limit=50&before=MSG_ID" \
-H "Authorization: Bot $COVE_TOKEN"
Typing Indicator
curl -s -X POST "$COVE_BASE/api/v10/channels/CHANNEL_ID/typing" \
-H "Authorization: Bot $COVE_TOKEN"
Bulk Delete
curl -s -X POST "$COVE_BASE/api/v10/channels/CHANNEL_ID/messages/bulk-delete" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"messages": ["MSG_ID_1", "MSG_ID_2"]}'
Members
List Guild Members
curl -s "$COVE_BASE/api/v10/guilds/$COVE_GUILD/members" \
-H "Authorization: Bot $COVE_TOKEN"
Returns: [{user: {id, username, avatar, bot}, nick, roles: [roleId...], joined_at}, ...]
Bot Channel Permissions
Control which channels a bot can access via permission overwrites:
curl -s -X PUT "$COVE_BASE/api/v10/channels/CHANNEL_ID/permissions/BOT_USER_ID" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type": 1, "allow": "1024", "deny": "0"}'
curl -s -X PUT "$COVE_BASE/api/v10/channels/CHANNEL_ID/permissions/BOT_USER_ID" \
-H "Authorization: Bot $COVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type": 1, "allow": "0", "deny": "1024"}'
curl -s -X DELETE "$COVE_BASE/api/v10/channels/CHANNEL_ID/permissions/BOT_USER_ID" \
-H "Authorization: Bot $COVE_TOKEN"
Reactions
Add Reaction
curl -s -X PUT "$COVE_BASE/api/v10/channels/CHANNEL_ID/messages/MSG_ID/reactions/EMOJI/@me" \
-H "Authorization: Bot $COVE_TOKEN"
EMOJI is URL-encoded (e.g. %F0%9F%91%8D for 👍).
Remove Reaction
curl -s -X DELETE "$COVE_BASE/api/v10/channels/CHANNEL_ID/messages/MSG_ID/reactions/EMOJI/@me" \
-H "Authorization: Bot $COVE_TOKEN"
Get Reactions
curl -s "$COVE_BASE/api/v10/channels/CHANNEL_ID/messages/MSG_ID/reactions/EMOJI" \
-H "Authorization: Bot $COVE_TOKEN"
Local Plugin Deployment
When plugin code (packages/plugin) changes, manually build + deploy:
cd ~/cove/packages/plugin && pnpm run build
cp ~/.openclaw/extensions/cove/dist/index.js ~/.openclaw/extensions/cove/dist/index.js.bak
cp dist/index.js ~/.openclaw/extensions/cove/dist/index.js
openclaw gateway restart
Staging CI only updates the Azure Cove server, not the local OpenClaw plugin.
Rules & Gotchas
- Use
jq -nc for JSON construction — shell string interpolation in JSON is error-prone
- Webhook messages don't need auth header — token is in the URL
- Cross-channel: no auto-return — results must be explicitly sent back via webhook
- cove.md is auto-injected — bots see it every turn without manually reading
- cove.md max 8KB for injection — larger files are stored but not injected into context
- File storage max 100KB — per file limit
- Filename regex — must match
/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,254}$/
- Bot permissions — bots need VIEW_CHANNEL permission overwrite to access channel files/messages
- WS events — file changes broadcast CHANNEL_FILE_CREATE/UPDATE/DELETE via WebSocket
- Plugin caches cove.md — 60s TTL, invalidated on WS file events; changes may take up to 60s to take effect
- Role hierarchy is king — even with ADMINISTRATOR, you cannot manage roles above your position. Only guild owner is exempt.
- New role permissions must be subset — cannot create a role with permissions you don't have yourself
- Managed roles — bot-linked roles cannot be manually assigned/removed/deleted