grix-connector
Version:
Connect local AI coding agents (Claude, Codex, Gemini, Qwen, DeepSeek, Cursor, OpenCode, Pi, OpenHuman, Reasonix) to the Grix scheduling platform. Also serves as an OpenClaw plugin for Grix channel transport.
198 lines (141 loc) • 7.41 kB
Markdown
---
name: message-send
description: Send messages. Supports current session replies and cross-session sending. For cross-session, use an exact `session_id` or an existing `route.sessionKey` as the `to` target; do not use the legacy `target=agent:...` format. Trigger words: send DM, DM, send message, notify.
---
# Message Send Skill
This skill is used to send messages through OpenClaw's `message` tool.
## Two Sending Modes
### 1. Current Session Reply
If replying to the current Grix session, send directly without providing an additional target session.
**Parameters**:
- `action`: "send"
- `channel`: "grix"
- `accountId`: current account ID
- `message`: message content
**Example**:
```json
{
"action": "send",
"channel": "grix",
"accountId": "{accountId}",
"message": "Got it, processing now..."
}
```
### 2. Cross-Session Sending
If sending to another private chat or group chat, use `to` to point to the target session.
**Parameters**:
- `action`: "send"
- `channel`: "grix"
- `accountId`: current account ID
- `to`: target session identifier
- `message`: message content
**Example**:
```json
{
"action": "send",
"channel": "grix",
"accountId": "{accountId}",
"to": "{targetSessionId}",
"message": "Need your confirmation on a development decision: ..."
}
```
## Real Format of `to`
The current plugin recognizes these two types of targets:
1. Exact Grix `session_id` (recommended, usually a UUID)
2. An existing `route.sessionKey` in the current runtime
Recommended to pass the bare `session_id` directly:
```text
to=e72ce987-2d2e-40ed-bcc9-b336b4974512
```
In compatible formats, `grix:<session_id>` or `session:<session_id>` can also be parsed, but should not be used as the default format.
Do not use these legacy formats:
1. `target=agent:{agentId}:grix:direct:{sessionId}`
2. Pure numeric user ID / agent ID
3. Non-existent session aliases
## How to Obtain the Target Session
1. If replying to the current session, simply omit `to`
2. If MEMORY.md already records the target `session_id`, reuse it directly
3. If the target session is unknown, first use `grix_query`'s `session_search` to find the exact `session_id`
Example:
```json
{
"action": "send",
"channel": "grix",
"accountId": "{accountId}",
"to": "{groupSessionId}",
"message": "Task completed, please check the results"
}
```
## Key Parameter Reference
| Parameter | Required | Description |
|------|------|------|
| `action` | ✅ | Fixed value `"send"` |
| `channel` | ✅ | Fixed value `"grix"` |
| `accountId` | ✅ | Current Grix account ID |
| `message` | ✅ | Message content |
| `to` | Required for cross-session | Exact `session_id` or resolvable `route.sessionKey` |
## Important Notes
1. Use `to`, not `target`
2. `to` should preferably be an exact `session_id`; do not confuse user ID, agent ID, and session ID
3. Pure numeric targets will fail directly; they will not auto-convert to private chats
4. Before sending cross-session messages, confirm the current account has send permission for the target session
5. Message content supports plain text and markdown
## Conversation Card Message Protocol
When the message content is **reminding the user to open a group chat**, **open a private chat conversation**, or **referencing a specific conversation entry point**, and you already have the exact `session_id`, do not send natural language links or frontend internal JSON; you must send a standalone `grix://card/conversation` Markdown link, which the frontend will uniformly parse and render as a clickable conversation card.
### Standard Format
Group chat:
```text
[Open Group](grix://card/conversation?session_id=<SESSION_ID>&session_type=group&title=<URI_ENCODED_GROUP_TITLE>)
```
Private chat:
```text
[Open Conversation](grix://card/conversation?session_id=<SESSION_ID>&session_type=private&title=<URI_ENCODED_CHAT_TITLE>&peer_id=<URI_ENCODED_PEER_ID>)
```
### Field Rules
- `session_id`: Required. Must be the exact target session ID.
- `session_type`: Required. Can only be `group` or `private`.
- `title`: Required. The group title or private chat title displayed to the user.
- `peer_id`: Optional for private chat only. Used to supplement private chat peer information, but frontend open behavior is still based on `session_id`.
### Encoding Rules
To prevent spaces, newlines, or reserved characters in titles, nicknames, URLs, and other fields from breaking the link, query parameter values should be URI component encoded before being written into the `grix://card` link.
- Recommended: uniformly apply URI component encoding to `title`, `peer_id`, and any future text fields
- `session_id` and `session_type` can be output as-is if they only contain safe characters
- Link text is plain copy for the user to see and does not need URI encoding
Example:
```text
[Open Group](grix://card/conversation?session_id=session-9&session_type=group&title=%E4%BA%A7%E5%93%81%E8%AE%A8%E8%AE%BA%E7%BE%A4%20A)
```
### Usage Requirements
1. Only output a conversation card when the **exact `session_id` is known**
2. If there is no `session_id`, can only send plain text explanation; cannot fabricate a conversation card
3. Do not output `chat://...`, web links, or "click here to open session" style natural language link alternatives
4. Do not construct frontend internal `biz_card` JSON or attempt to send Flutter/frontend private protocol structures
5. The `grix://card/conversation` link must be on a single line and must be sent as a standalone message
6. If additional explanation is needed, send the explanation text and the card as two separate messages; do not mix explanation and card in the same message
7. Do not put multiple cards in the same message; when multiple jump entries are needed, send multiple messages
8. If field values contain special characters, apply URI component encoding first, then assemble into the link
### Examples
Example 1: Remind user to enter a group chat
```text
[Open Product Group](grix://card/conversation?session_id=9d6a4b1d-5d37-4e38-ae6a-0c12a2c4c901&session_type=group&title=%E4%BA%A7%E5%93%81%E7%BE%A4)
```
Example 2: Remind user to enter a private chat
```text
[Open Alice Conversation](grix://card/conversation?session_id=e72ce987-2d2e-40ed-bcc9-b336b4974512&session_type=private&title=Alice&peer_id=1001)
```
Example 3: Send explanation and card as two separate messages
```text
Message 1: The test group has been created. Check the next card to enter directly.
Message 2: [Open Test Group](grix://card/conversation?session_id=0fa947bd-bb4e-46ad-8308-5526bc98e002&session_type=group&title=%E6%B5%8B%E8%AF%95%E7%BE%A4)
```
## Error Handling
- `to` cannot be resolved: confirm whether the `session_id` or `route.sessionKey` is correct
- Insufficient permissions: check whether the current `accountId` has send permission for the target session
- Missing parameters: ensure all required parameters are provided
- Target format error: check whether `to` is an exact `session_id` or valid `route.sessionKey`
## Best Practices
1. For cross-session sending, prefer recording and reusing exact `session_id`
2. When you need to find a session, use `grix_query.session_search` first
3. Keep message content concise and highlight key points
4. Do not abuse proactive messages to avoid disturbing the owner
5. Prefer conversation cards over plain text explanations when navigation is needed