clawaxis 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAWAXIS.md +954 -0
- package/LICENSE +21 -0
- package/README.md +441 -0
- package/index.ts +53 -0
- package/openclaw.plugin.json +86 -0
- package/package.json +33 -0
- package/src/channel.ts +78 -0
- package/src/config.ts +82 -0
- package/src/governance/hooks.ts +92 -0
- package/src/governance/logging.ts +58 -0
- package/src/governance/style-injection.ts +114 -0
- package/src/governance/validation.ts +206 -0
- package/src/message-handler.ts +212 -0
- package/src/runtime.ts +91 -0
- package/src/sync/documents.ts +127 -0
- package/src/sync/routines.ts +56 -0
- package/src/tools/content.ts +64 -0
- package/src/tools/helpers.ts +40 -0
- package/src/tools/index.ts +16 -0
- package/src/tools/logging.ts +33 -0
- package/src/tools/media.ts +21 -0
- package/src/tools/memory.ts +78 -0
- package/src/tools/routines.ts +54 -0
- package/src/tools/sync.ts +36 -0
- package/src/types.ts +64 -0
- package/src/utils.ts +161 -0
- package/src/websocket.ts +294 -0
package/CLAWAXIS.md
ADDED
|
@@ -0,0 +1,954 @@
|
|
|
1
|
+
# CLAWAXIS.md — Agent Instruction Manual
|
|
2
|
+
|
|
3
|
+
> This is the definitive guide for how to use the ClawAxis tools.
|
|
4
|
+
> It ships alongside the plugin and is injected into the agent's context.
|
|
5
|
+
> **Last updated: February 2026**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Philosophy: Transparency
|
|
10
|
+
|
|
11
|
+
**ALWAYS log what you're doing.** Users feel disconnected when they don't know what's happening. Use logs to:
|
|
12
|
+
- Show progress ("Starting competitive analysis research...")
|
|
13
|
+
- Celebrate wins ("Posted daily blog with hero image")
|
|
14
|
+
- Explain setbacks ("API rate limit hit, retrying in 30s...")
|
|
15
|
+
|
|
16
|
+
Think of logs as your way to "show your work" — it builds trust and keeps users engaged.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Content System — The Most Important Section
|
|
21
|
+
|
|
22
|
+
The `content_type` you choose determines **which visual card the iOS app uses to render your content**. Getting this wrong means the content looks broken. Getting the body format wrong means it renders as garbage.
|
|
23
|
+
|
|
24
|
+
### Content Type Reference
|
|
25
|
+
|
|
26
|
+
| `content_type` | Card | Body Format | Char Limit | Title Displayed? | Media? | Tags? |
|
|
27
|
+
|---|---|---|---|---|---|---|
|
|
28
|
+
| `twitter` | Tweet preview | **Plain text** | **280** | No | Up to 4 images (16:9) | No |
|
|
29
|
+
| `instagram` | Caption preview | **Plain text** | **2,200** | No | 1st image (1:1 square) | Yes → #hashtags |
|
|
30
|
+
| `linkedin` | Post preview | **Plain text** | **3,000** | No | No | No |
|
|
31
|
+
| `facebook` | Post preview | **Plain text** | None | No | 1st image | No |
|
|
32
|
+
| `tiktok` | Caption preview | **Plain text** | **4,000** | No | 1st image (9:16 tall) | Yes → #hashtags |
|
|
33
|
+
| `youtube` | Description preview | **Plain text** | **5,000** | **YES — shown as video title** | 1st image (16:9 thumbnail) | Yes (pills) |
|
|
34
|
+
| `website` | Live HTML render | **Raw HTML** | None | No | No (HTML rendered) | Yes (pills) |
|
|
35
|
+
| `blog` | Markdown render | **Markdown** | None | No | No | Yes (pills + SEO keywords) |
|
|
36
|
+
| `report` | Markdown render | **Markdown** | None | No | No | Yes (pills + SEO keywords) |
|
|
37
|
+
| `email` | Markdown render | **Markdown** | None | No | No | Yes (pills) |
|
|
38
|
+
| `ad` | Markdown render | **Markdown** | None | No | No | Yes (pills) |
|
|
39
|
+
| `document` | Markdown render | **Markdown** | None | No | No | Yes (pills) |
|
|
40
|
+
| `other` | Markdown render | **Markdown** | None | No | No | Yes (pills) |
|
|
41
|
+
|
|
42
|
+
### Body Format Rules
|
|
43
|
+
|
|
44
|
+
**Social platforms** (twitter, instagram, linkedin, facebook, tiktok, youtube):
|
|
45
|
+
- **Plain text ONLY** — no Markdown, no HTML, no formatting symbols
|
|
46
|
+
- Respect character limits — the app shows red warnings when exceeded
|
|
47
|
+
- Write conversational, human-readable text
|
|
48
|
+
|
|
49
|
+
**Website**:
|
|
50
|
+
- **Raw HTML** — the body is rendered directly in a WKWebView
|
|
51
|
+
- Include complete HTML structure (`<!DOCTYPE html>` through `</html>`)
|
|
52
|
+
- Include all styling (inline `<style>` or external stylesheet references)
|
|
53
|
+
- Must be valid, well-formed HTML5
|
|
54
|
+
|
|
55
|
+
**Blog, Report, Email, Ad, Document, Other**:
|
|
56
|
+
- **Markdown** — rendered via the MarkdownUI library
|
|
57
|
+
- Full Markdown support: headings, bold, italic, code blocks, links, lists, tables, images
|
|
58
|
+
|
|
59
|
+
### What You Must Always Provide
|
|
60
|
+
|
|
61
|
+
| Field | When | Why |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| `title` | **ALWAYS** | Card list header, search, identification |
|
|
64
|
+
| `body` | **ALWAYS** | The actual content |
|
|
65
|
+
| `content_type` | **ALWAYS** | Determines which card renders. **Never omit.** |
|
|
66
|
+
| `word_count` | For blog, report, email, document | Displayed prominently in card header |
|
|
67
|
+
| `tags` | For instagram, tiktok, blog, report, website | Instagram/TikTok convert to #hashtags; blog/report show as pill badges |
|
|
68
|
+
| `seo_keywords` | For blog, report | Shown as "SEO Keywords" in card footer |
|
|
69
|
+
| `media` | For twitter, instagram, facebook, tiktok, youtube | These platforms expect images. Without them you get a grey placeholder. |
|
|
70
|
+
| `prompt_used` | Recommended | Shown in "Generation Info" section on detail view |
|
|
71
|
+
| `model_used` | Recommended | Shown in "Generation Info" section on detail view |
|
|
72
|
+
|
|
73
|
+
### The #1 Rule
|
|
74
|
+
|
|
75
|
+
**Always set `content_type` to the correct platform value.** If you're writing an Instagram caption, use `instagram`. If you're writing a blog post, use `blog`, not `other`. The wrong type means the wrong card renders and the content looks broken.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Media Format
|
|
80
|
+
|
|
81
|
+
The `media` field MUST be a JSON object with this structure:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"images": [
|
|
86
|
+
{ "url": "https://example.com/image1.jpg", "alt": "Description of image" }
|
|
87
|
+
],
|
|
88
|
+
"videos": [
|
|
89
|
+
{ "url": "https://example.com/video.mp4", "alt": "Video description" }
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Rules:**
|
|
95
|
+
- `url` is **required** — must be a full HTTPS URL
|
|
96
|
+
- `alt` is optional but recommended
|
|
97
|
+
- **Use permanent URLs only** — temporary URLs (DALL-E, etc.) expire. Upload to R2 first with `clawaxis_upload_media`.
|
|
98
|
+
- The app accesses `media.images[0]` for platforms that show a single image (Instagram, Facebook, TikTok, YouTube)
|
|
99
|
+
- Twitter supports up to 4 images (rendered as a grid)
|
|
100
|
+
|
|
101
|
+
**The Swift decoder also accepts a flat array** (legacy format):
|
|
102
|
+
```json
|
|
103
|
+
[{ "url": "...", "alt": "..." }]
|
|
104
|
+
```
|
|
105
|
+
This is treated as `{ images: [...], videos: [] }`. But always prefer the nested format.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Content Examples
|
|
110
|
+
|
|
111
|
+
### Twitter
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"title": "AI Governance Tweet",
|
|
115
|
+
"body": "The future of autonomous vehicles depends on the governance frameworks we build today. Our latest research dives into what this means. 🚗🤖",
|
|
116
|
+
"content_type": "twitter",
|
|
117
|
+
"word_count": 22,
|
|
118
|
+
"media": {
|
|
119
|
+
"images": [
|
|
120
|
+
{ "url": "https://media.example.com/ai-auto.jpg", "alt": "AI governance infographic" }
|
|
121
|
+
],
|
|
122
|
+
"videos": []
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Instagram
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"title": "AI Governance Instagram Post",
|
|
131
|
+
"body": "The future of autonomous vehicles depends on the governance frameworks we build today. Our latest research dives deep into what this means for the automotive industry.",
|
|
132
|
+
"content_type": "instagram",
|
|
133
|
+
"tags": ["AIGovernance", "AutomotiveAI", "AutonomousVehicles", "FutureOfDriving", "TechPolicy"],
|
|
134
|
+
"media": {
|
|
135
|
+
"images": [
|
|
136
|
+
{ "url": "https://media.example.com/ai-auto-square.jpg", "alt": "AI governance visual" }
|
|
137
|
+
],
|
|
138
|
+
"videos": []
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
Note: Don't put `#` in the tags array — the app adds it automatically.
|
|
143
|
+
|
|
144
|
+
### LinkedIn
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"title": "AI Governance LinkedIn Post",
|
|
148
|
+
"body": "The automotive industry stands at a crossroads.\n\nAs AI systems become more autonomous, the frameworks we build today will determine whether these technologies earn public trust — or erode it.\n\nOur latest research explores three critical governance areas...",
|
|
149
|
+
"content_type": "linkedin"
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### YouTube
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"title": "AI Governance in the Automotive Industry",
|
|
157
|
+
"body": "In this video, we explore the critical governance frameworks needed for autonomous vehicles.\n\n00:00 Introduction\n02:15 ISO 26262 Overview\n05:30 SOTIF Framework\n...",
|
|
158
|
+
"content_type": "youtube",
|
|
159
|
+
"tags": ["AI governance", "autonomous vehicles", "ISO 26262"],
|
|
160
|
+
"media": {
|
|
161
|
+
"images": [
|
|
162
|
+
{ "url": "https://media.example.com/yt-thumbnail.jpg", "alt": "Video thumbnail" }
|
|
163
|
+
],
|
|
164
|
+
"videos": []
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
Note: YouTube is the **only** social card that displays the `title` as the video title.
|
|
169
|
+
|
|
170
|
+
### Blog (Markdown)
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"title": "AI Governance in the Automotive Industry",
|
|
174
|
+
"body": "# AI Governance in the Automotive Industry\n\nThe automotive industry stands at a crossroads...\n\n## Key Frameworks\n\n1. **ISO 26262** — Functional safety\n2. **SOTIF** — Safety of the intended functionality\n\n## Conclusion\n\nThe frameworks we build today will shape...",
|
|
175
|
+
"content_type": "blog",
|
|
176
|
+
"word_count": 1250,
|
|
177
|
+
"tags": ["AI", "automotive", "governance", "safety"],
|
|
178
|
+
"seo_keywords": ["AI governance automotive", "autonomous vehicle safety frameworks"],
|
|
179
|
+
"prompt_used": "Write a blog post about AI governance in the automotive industry",
|
|
180
|
+
"model_used": "anthropic/claude-sonnet-4-5"
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Website (HTML)
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"title": "Company Landing Page",
|
|
188
|
+
"body": "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Welcome</title><style>body{font-family:system-ui;margin:0;padding:2rem;max-width:800px;margin:0 auto;}</style></head><body><h1>Welcome to Our Company</h1><p>We build the future of autonomous systems.</p></body></html>",
|
|
189
|
+
"content_type": "website",
|
|
190
|
+
"tags": ["landing-page", "company"]
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Available Tools
|
|
197
|
+
|
|
198
|
+
### clawaxis_post_content
|
|
199
|
+
Post content to the ClawAxis app for user review.
|
|
200
|
+
|
|
201
|
+
**Parameters:**
|
|
202
|
+
| Param | Required | Description |
|
|
203
|
+
|---|---|---|
|
|
204
|
+
| `title` | **YES** | Content title |
|
|
205
|
+
| `body` | **YES** | Full content body (plain text, Markdown, or HTML depending on content_type) |
|
|
206
|
+
| `content_type` | **YES** | Must be one of: `twitter`, `instagram`, `linkedin`, `facebook`, `tiktok`, `youtube`, `website`, `blog`, `report`, `email`, `ad`, `document`, `other` |
|
|
207
|
+
| `tags` | Recommended | Array of strings. Instagram/TikTok auto-prefix with `#`. Blog/report show as pills. |
|
|
208
|
+
| `seo_keywords` | For blog/report | Array of keyword phrases. Shown in card footer. |
|
|
209
|
+
| `word_count` | For long-form | Integer. Shown in card header for blog/report/email. |
|
|
210
|
+
| `prompt_used` | Recommended | The prompt that generated this. Shown in "Generation Info". |
|
|
211
|
+
| `model_used` | Recommended | Model ID (e.g. `anthropic/claude-sonnet-4-5`). Shown in "Generation Info". |
|
|
212
|
+
| `media` | For visual platforms | `{images: [{url, alt?}], videos: [{url, alt?}]}`. Required for twitter/instagram/facebook/tiktok/youtube. |
|
|
213
|
+
| `platform` | Legacy | Don't use. Use `content_type` instead. |
|
|
214
|
+
|
|
215
|
+
### clawaxis_update_content
|
|
216
|
+
Update existing content. The relay auto-increments `edit_count` and preserves `original_body` on first edit.
|
|
217
|
+
|
|
218
|
+
**Parameters:**
|
|
219
|
+
| Param | Required | Description |
|
|
220
|
+
|---|---|---|
|
|
221
|
+
| `content_id` | **YES** | UUID of content to update |
|
|
222
|
+
| `body` | **YES** | Complete updated body. Same format rules apply. |
|
|
223
|
+
| `title` | No | Updated title. Omit to keep existing. |
|
|
224
|
+
| `media` | No | Updated media. Omit to keep existing. |
|
|
225
|
+
|
|
226
|
+
### clawaxis_get_content
|
|
227
|
+
Retrieve content from the queue. Always uses HTTP (needs synchronous response).
|
|
228
|
+
|
|
229
|
+
**Parameters:**
|
|
230
|
+
| Param | Required | Description |
|
|
231
|
+
|---|---|---|
|
|
232
|
+
| `content_id` | No | UUID of specific item. Omit to get recent list. |
|
|
233
|
+
|
|
234
|
+
### clawaxis_post_log
|
|
235
|
+
Log activity to the ClawAxis dashboard. Users see this in the Home screen's "Recent Activity" feed.
|
|
236
|
+
|
|
237
|
+
**Parameters:**
|
|
238
|
+
| Param | Required | Type | Description |
|
|
239
|
+
|---|---|---|---|
|
|
240
|
+
| `action` | **YES** | String (ENUM) | See table below. **Invalid values are rejected by the database.** |
|
|
241
|
+
| `detail` | **YES** | String | Human-readable description. This is the PRIMARY text the user reads. Make it useful. |
|
|
242
|
+
| `level` | **YES** (effectively) | String (ENUM) | See table below. Default: `info`. Controls the colored dot next to the log. |
|
|
243
|
+
| `tokens_used` | No | Number | Token count. Shown as badge if > 0. |
|
|
244
|
+
| `cost` | No | Number | Cost in USD (e.g. 0.015). Shown as badge if > 0. |
|
|
245
|
+
| `duration_ms` | No | Number | How long the action took in ms. Shown as badge. |
|
|
246
|
+
| `metadata` | No | Object | Additional context as JSON. Stored in JSONB column. |
|
|
247
|
+
|
|
248
|
+
### Valid `action` Values (DATABASE ENUM — no other values work)
|
|
249
|
+
|
|
250
|
+
| Value | When to Use |
|
|
251
|
+
|---|---|
|
|
252
|
+
| `chat_message` | Responding to a user message |
|
|
253
|
+
| `content_generate` | Starting to create content (blog, report, tweet, etc.) |
|
|
254
|
+
| `content_post` | Content was posted to the queue (after `clawaxis_post_content`) |
|
|
255
|
+
| `web_search` | Performed a web search |
|
|
256
|
+
| `web_fetch` | Fetched/scraped a webpage |
|
|
257
|
+
| `browser_action` | Browser automation (navigating, clicking, screenshots) |
|
|
258
|
+
| `cron_execute` | Running a scheduled task / cron job |
|
|
259
|
+
| `skill_update` | Updated agent skills or knowledge base |
|
|
260
|
+
| `file_operation` | Read, wrote, or edited a file |
|
|
261
|
+
| `system` | System-level operations (startup, config, etc.) |
|
|
262
|
+
| `error` | An error occurred |
|
|
263
|
+
| `tool_call` | Called an external tool |
|
|
264
|
+
|
|
265
|
+
**Common mistakes:**
|
|
266
|
+
- `"research"` — NOT valid. Use `web_search` or `web_fetch`
|
|
267
|
+
- `"search"` — NOT valid. Use `web_search`
|
|
268
|
+
- `"generate"` — NOT valid. Use `content_generate`
|
|
269
|
+
- `"post"` — NOT valid. Use `content_post`
|
|
270
|
+
- `"install"` — NOT valid. Use `system`
|
|
271
|
+
- `"api_call"` — NOT valid. Use `tool_call`
|
|
272
|
+
- `"log"` — NOT valid. Use `system`
|
|
273
|
+
|
|
274
|
+
### Valid `level` Values (DATABASE ENUM)
|
|
275
|
+
|
|
276
|
+
| Value | Dot Color | When to Use |
|
|
277
|
+
|---|---|---|
|
|
278
|
+
| `info` | Blue | Starting a task, neutral updates, progress notes |
|
|
279
|
+
| `success` | Green | Task completed, content posted, cron set up |
|
|
280
|
+
| `warning` | Yellow | Partial failure, retry needed, rate limit hit |
|
|
281
|
+
| `error` | Red | Something broke, exception caught, tool failed |
|
|
282
|
+
|
|
283
|
+
**Frontend rendering:**
|
|
284
|
+
|
|
285
|
+
The Home screen "Recent Activity" card shows each log as a row:
|
|
286
|
+
```
|
|
287
|
+
[colored dot] detail text (primary, up to 2 lines)
|
|
288
|
+
action_name • 3 min ago [tokens badge]
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
- The **colored dot** comes from `level` (blue/green/yellow/red)
|
|
292
|
+
- The **action** is displayed as text with underscores replaced by spaces (e.g. `content_post` → "content post")
|
|
293
|
+
- The **detail** is the main text the user reads — make it descriptive
|
|
294
|
+
- **tokens_used** shows as a small badge on the right if > 0
|
|
295
|
+
- **cost** shows as a badge if > 0
|
|
296
|
+
|
|
297
|
+
### Log Examples
|
|
298
|
+
|
|
299
|
+
```json
|
|
300
|
+
// Starting research
|
|
301
|
+
{
|
|
302
|
+
"action": "web_search",
|
|
303
|
+
"detail": "Searching for AI governance frameworks in the automotive industry",
|
|
304
|
+
"level": "info"
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Content created
|
|
308
|
+
{
|
|
309
|
+
"action": "content_post",
|
|
310
|
+
"detail": "Posted blog post: AI Governance in the Automotive Industry (1,250 words)",
|
|
311
|
+
"level": "success",
|
|
312
|
+
"tokens_used": 3200,
|
|
313
|
+
"duration_ms": 15000
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Error occurred
|
|
317
|
+
{
|
|
318
|
+
"action": "error",
|
|
319
|
+
"detail": "Failed to generate hero image: API rate limit exceeded, retrying in 30s",
|
|
320
|
+
"level": "error",
|
|
321
|
+
"metadata": { "retry_in": 30, "service": "image_api" }
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Cron job created
|
|
325
|
+
{
|
|
326
|
+
"action": "cron_execute",
|
|
327
|
+
"detail": "Created routine: Daily AI News — runs every day at 8:00 AM ET",
|
|
328
|
+
"level": "success"
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Installing a dependency
|
|
332
|
+
{
|
|
333
|
+
"action": "system",
|
|
334
|
+
"detail": "Installing @sinclair/typebox for plugin schema validation",
|
|
335
|
+
"level": "info"
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Used a tool
|
|
339
|
+
{
|
|
340
|
+
"action": "tool_call",
|
|
341
|
+
"detail": "Called web_fetch on 5 competitor websites for analysis",
|
|
342
|
+
"level": "info",
|
|
343
|
+
"tokens_used": 800,
|
|
344
|
+
"duration_ms": 4500
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**CRITICAL:** `action` and `level` are real Postgres ENUMs. If you send an invalid value, the database INSERT fails silently and the log is **lost forever**. The relay now validates and defaults invalid values to `system`/`info`, but you should always use exact values from the tables above.
|
|
349
|
+
|
|
350
|
+
### clawaxis_upload_media
|
|
351
|
+
Upload images to permanent R2 storage. Always uses HTTP (binary payloads).
|
|
352
|
+
|
|
353
|
+
**Parameters:**
|
|
354
|
+
| Param | Required | Description |
|
|
355
|
+
|---|---|---|
|
|
356
|
+
| `image_url` | **YES** | URL of image to download and re-upload to R2 |
|
|
357
|
+
| `filename` | No | Custom filename without extension. Defaults to timestamp. |
|
|
358
|
+
| `folder` | No | Subfolder in R2 (e.g. `blog`, `social`). Defaults to agent ID. |
|
|
359
|
+
|
|
360
|
+
**Returns:** `{ ok: true, url: "https://...", key: "...", size: 12345 }`
|
|
361
|
+
|
|
362
|
+
**Always upload before posting content.** Temporary URLs (DALL-E, etc.) expire. Use permanent R2 URLs in your media objects.
|
|
363
|
+
|
|
364
|
+
### clawaxis_notify_routine
|
|
365
|
+
Register a new agent-created routine in the app.
|
|
366
|
+
|
|
367
|
+
**Parameters:**
|
|
368
|
+
| Param | Required | Description |
|
|
369
|
+
|---|---|---|
|
|
370
|
+
| `name` | **YES** | Short name (e.g. "Daily AI News") |
|
|
371
|
+
| `cron_expression` | **YES** | Standard cron (e.g. `0 8 * * *`) |
|
|
372
|
+
| `instruction` | **YES** | What the routine does |
|
|
373
|
+
| `openclaw_cron_id` | **YES** | OpenClaw cron job ID |
|
|
374
|
+
| `schedule_human` | Recommended | Human-readable schedule (e.g. "Every day at 8:00 AM") |
|
|
375
|
+
| `next_run_at` | Recommended | ISO 8601 timestamp of next execution |
|
|
376
|
+
| `timezone` | Recommended | IANA timezone (e.g. `America/New_York`). Default: America/New_York |
|
|
377
|
+
| `frequency` | Recommended | Must be: `once`, `hourly`, `daily`, `weekly`, `monthly`, `custom` |
|
|
378
|
+
| `description` | No | Longer description |
|
|
379
|
+
| `status` | No | Must be: `active`, `paused`, `disabled`. Default: active |
|
|
380
|
+
|
|
381
|
+
**Rule:** Every cron job you create MUST be registered with the app. No hidden automation.
|
|
382
|
+
|
|
383
|
+
### clawaxis_update_routine
|
|
384
|
+
Update an existing routine.
|
|
385
|
+
|
|
386
|
+
**Parameters:**
|
|
387
|
+
| Param | Required | Description |
|
|
388
|
+
|---|---|---|
|
|
389
|
+
| `routine_id` | **YES** | UUID of routine to update |
|
|
390
|
+
| `openclaw_cron_id` | No | Updated OpenClaw cron job ID (if the cron job was recreated) |
|
|
391
|
+
| `name` | No | Updated routine name |
|
|
392
|
+
| `cron_expression` | No | Updated cron expression |
|
|
393
|
+
| `schedule_human` | No | Human-readable schedule |
|
|
394
|
+
| `instruction` | No | Updated task instructions |
|
|
395
|
+
| `timezone` | No | IANA timezone string |
|
|
396
|
+
| `next_run_at` | No | ISO 8601 timestamp of next run |
|
|
397
|
+
| `description` | No | Updated description |
|
|
398
|
+
| `status` | No | `active`, `paused`, or `disabled` |
|
|
399
|
+
|
|
400
|
+
**Rule:** Any time you modify a cron job (schedule, name, status), ALWAYS call this so the app stays in sync.
|
|
401
|
+
|
|
402
|
+
### clawaxis_confirm_doc_sync
|
|
403
|
+
Confirm a document uploaded through the app has been received.
|
|
404
|
+
|
|
405
|
+
**Parameters:**
|
|
406
|
+
| Param | Required | Description |
|
|
407
|
+
|---|---|---|
|
|
408
|
+
| `document_id` | **YES** | UUID of the document |
|
|
409
|
+
| `agent_skill_path` | Recommended | Where the document was saved on the agent machine |
|
|
410
|
+
|
|
411
|
+
### clawaxis_confirm_routine_sync
|
|
412
|
+
Confirm a routine created through the app has been set up.
|
|
413
|
+
|
|
414
|
+
**Parameters:**
|
|
415
|
+
| Param | Required | Description |
|
|
416
|
+
|---|---|---|
|
|
417
|
+
| `routine_id` | **YES** | UUID of the routine |
|
|
418
|
+
| `openclaw_cron_id` | Recommended | OpenClaw cron job ID that was created |
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## Message System
|
|
423
|
+
|
|
424
|
+
### Message Types
|
|
425
|
+
|
|
426
|
+
Every message has a `message_type` field. This tells you what kind of message the user sent:
|
|
427
|
+
|
|
428
|
+
| `message_type` | Description | Content Format |
|
|
429
|
+
|---|---|---|
|
|
430
|
+
| `text` | Normal typed message | Plain text |
|
|
431
|
+
| `voice` | Spoken via voice-to-text | `[VOICE_INPUT] {transcribed text}` |
|
|
432
|
+
| `content_edit` | User wants to edit existing content | `@content_edit:{UUID}:{Title}\n{user instructions}` |
|
|
433
|
+
| `image` | Image attachment | Text with attachment metadata |
|
|
434
|
+
| `document` | Document attachment | Text with attachment metadata |
|
|
435
|
+
|
|
436
|
+
### Message Status Lifecycle
|
|
437
|
+
|
|
438
|
+
Every message goes through these statuses. The plugin now sends status updates automatically:
|
|
439
|
+
|
|
440
|
+
```
|
|
441
|
+
User sends message
|
|
442
|
+
↓
|
|
443
|
+
[pending] — Message created, not yet delivered to agent
|
|
444
|
+
↓
|
|
445
|
+
[processing] — Agent received message, thinking/working on it
|
|
446
|
+
↓ ↓
|
|
447
|
+
[complete] — Agent replied [error] — Something broke
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**What the user sees for each status:**
|
|
451
|
+
| Status | UI Indicator |
|
|
452
|
+
|---|---|
|
|
453
|
+
| `pending` | Clock icon + "Sending" (grey) |
|
|
454
|
+
| `processing` | Brain icon + "Thinking..." (accent color, animated) |
|
|
455
|
+
| `complete` | Checkmark + "Delivered" (green) |
|
|
456
|
+
| `error` | Warning triangle + "Failed" (red) |
|
|
457
|
+
|
|
458
|
+
### Content Edit Requests
|
|
459
|
+
|
|
460
|
+
When a user taps "Edit" on a content item in the app, they can type instructions. The app sends a message with:
|
|
461
|
+
- `message_type: "content_edit"`
|
|
462
|
+
- `ref_id: UUID` (the content item's UUID)
|
|
463
|
+
- Content formatted as: `@content_edit:{UUID}:{Title}\n{user instructions}`
|
|
464
|
+
|
|
465
|
+
**Example message you'll receive:**
|
|
466
|
+
```
|
|
467
|
+
@content_edit:908DE83B-3ECB-4866-9981-CEB8300501D1:AI Governance Blog Post
|
|
468
|
+
Make the introduction more concise and add a section about GDPR compliance
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**What to do:**
|
|
472
|
+
1. Parse the `ref_id` (content UUID) from the message or use the `ref_id` field
|
|
473
|
+
2. Fetch the content: `clawaxis_get_content(content_id: "908DE83B-...")`
|
|
474
|
+
3. Make the requested changes to the body/title
|
|
475
|
+
4. Update: `clawaxis_update_content(content_id: "908DE83B-...", body: revised_content)`
|
|
476
|
+
5. Log: `clawaxis_post_log(action: "content_post", detail: "Updated blog post: AI Governance (added GDPR section)", level: "success")`
|
|
477
|
+
6. Reply confirming what you changed
|
|
478
|
+
|
|
479
|
+
**The frontend shows:**
|
|
480
|
+
- A `@ContentEdit — AI Governance Blog Post` badge above the user's message bubble
|
|
481
|
+
- The user's instructions below the badge (the `@content_edit:...` prefix is stripped for display)
|
|
482
|
+
|
|
483
|
+
### Voice Messages
|
|
484
|
+
|
|
485
|
+
Messages prefixed with `[VOICE_INPUT]` were spoken by the user via voice-to-text. The `message_type` will be `voice`.
|
|
486
|
+
|
|
487
|
+
**Example message you'll receive:**
|
|
488
|
+
```
|
|
489
|
+
[VOICE_INPUT] Hey can you write me a blog post about AI governance in the automotive industry
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
**What the user sees:**
|
|
493
|
+
- The bubble shows: "Hey can you write me a blog post about AI governance in the automotive industry" (prefix stripped)
|
|
494
|
+
- A small "Voice transcription" label with mic icon appears below the bubble
|
|
495
|
+
|
|
496
|
+
**How to respond:**
|
|
497
|
+
- Respond conversationally — no code blocks, no Markdown formatting, no structured lists
|
|
498
|
+
- Keep responses natural and readable aloud
|
|
499
|
+
- The app automatically reads your response aloud via text-to-speech when in voice conversation mode
|
|
500
|
+
- The user hears your response through the device speaker
|
|
501
|
+
|
|
502
|
+
### Routine Management Messages
|
|
503
|
+
|
|
504
|
+
When a user creates, pauses, resumes, or deletes a routine in the app, the app inserts a structured message into the `messages` table. You receive it as a regular chat message. These are **system instructions** — act on them immediately.
|
|
505
|
+
|
|
506
|
+
**Message format:** Each message starts with a system tag in brackets:
|
|
507
|
+
|
|
508
|
+
#### `[system:routine_created:<UUID>]`
|
|
509
|
+
The user created a new routine. The message body includes the name, frequency, schedule, and instructions.
|
|
510
|
+
|
|
511
|
+
**Example message you'll receive:**
|
|
512
|
+
```
|
|
513
|
+
[system:routine_created:908DE83B-3ECB-4866-9981-CEB8300501D1]
|
|
514
|
+
New routine created: "Daily AI News"
|
|
515
|
+
Frequency: Daily
|
|
516
|
+
Schedule: Every day at 8:00 AM (0 8 * * *)
|
|
517
|
+
Instructions: Check AI news sources and post a summary blog post
|
|
518
|
+
|
|
519
|
+
Please set up this cron job and confirm when ready by calling clawaxis_confirm_routine_sync with routine_id: 908DE83B-3ECB-4866-9981-CEB8300501D1
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
**What to do:**
|
|
523
|
+
1. Parse the routine details (name, cron expression, instruction)
|
|
524
|
+
2. Create the cron job: `cron({ action: "add", job: { name, schedule: { kind: "cron", expr: "0 8 * * *", tz: "America/New_York" }, payload: { kind: "agentTurn", message: instruction }, sessionTarget: "isolated" } })`
|
|
525
|
+
3. Confirm sync: `clawaxis_confirm_routine_sync(routine_id: "<UUID>", openclaw_cron_id: cronResult.jobId)`
|
|
526
|
+
4. Log it: `clawaxis_post_log(action: "cron_execute", detail: "Created routine: Daily AI News", level: "success")`
|
|
527
|
+
5. Reply confirming setup
|
|
528
|
+
|
|
529
|
+
#### `[system:routine_paused:<UUID>]`
|
|
530
|
+
The user paused a routine. The message includes the routine name and OpenClaw cron ID.
|
|
531
|
+
|
|
532
|
+
**What to do:**
|
|
533
|
+
1. Remove or pause the cron job: `cron({ action: "remove", jobId: "<openclaw_cron_id>" })`
|
|
534
|
+
2. Reply confirming it's paused
|
|
535
|
+
|
|
536
|
+
#### `[system:routine_resumed:<UUID>]`
|
|
537
|
+
The user resumed a paused routine. The message includes the schedule and instructions.
|
|
538
|
+
|
|
539
|
+
**What to do:**
|
|
540
|
+
1. Re-create the cron job with the original schedule
|
|
541
|
+
2. Confirm sync: `clawaxis_confirm_routine_sync(routine_id: "<UUID>", openclaw_cron_id: newCronId)`
|
|
542
|
+
3. Reply confirming it's active again
|
|
543
|
+
|
|
544
|
+
#### `[system:routine_deleted:<UUID>]`
|
|
545
|
+
The user deleted a routine. The message includes the OpenClaw cron ID.
|
|
546
|
+
|
|
547
|
+
**What to do:**
|
|
548
|
+
1. Remove the cron job: `cron({ action: "remove", jobId: "<openclaw_cron_id>" })`
|
|
549
|
+
2. Reply confirming it's deleted
|
|
550
|
+
|
|
551
|
+
### Pending Routines via Sync / Heartbeat
|
|
552
|
+
|
|
553
|
+
Besides chat messages, you also receive pending routines via two WebSocket paths:
|
|
554
|
+
|
|
555
|
+
1. **On connect (`sync` message):** The relay sends all routines where `synced_at IS NULL` — these are routines the user created while you were offline.
|
|
556
|
+
2. **On heartbeat (`heartbeat_ack` message):** The relay periodically sends any unsynced routines — these are routines created mid-session.
|
|
557
|
+
|
|
558
|
+
Both deliver routine objects with all fields: `id`, `name`, `instruction`, `cron_expression`, `status`, `frequency`, `timezone`, `schedule_human`, `description`, `openclaw_cron_id`, `created_by`.
|
|
559
|
+
|
|
560
|
+
**What to do:** Same as `[system:routine_created]` — create or update the cron job and confirm sync. If `openclaw_cron_id` is present, this is an update to an existing routine.
|
|
561
|
+
|
|
562
|
+
### When YOU Create Cron Jobs
|
|
563
|
+
|
|
564
|
+
If you create a cron job independently (not from an app routine message):
|
|
565
|
+
1. Create the cron job as usual
|
|
566
|
+
2. **Immediately call `clawaxis_notify_routine`** to register it in the app
|
|
567
|
+
3. The user should ALWAYS see every cron job you have running
|
|
568
|
+
|
|
569
|
+
**Rule:** Never have a cron job running that isn't visible in the app. Full transparency.
|
|
570
|
+
|
|
571
|
+
---
|
|
572
|
+
|
|
573
|
+
## Document Management
|
|
574
|
+
|
|
575
|
+
Documents are files the user creates and manages in the ClawAxis app (style guides, reference materials, knowledge bases, etc.). They're synced to your workspace and indexed in memory for search.
|
|
576
|
+
|
|
577
|
+
### How Documents Reach You
|
|
578
|
+
|
|
579
|
+
Documents arrive through **two paths**, just like routines:
|
|
580
|
+
|
|
581
|
+
1. **Via sync/heartbeat:** When you connect (or on each heartbeat), the relay sends any documents where `synced_at IS NULL`. Each document includes: `id`, `name`, `content`, `doc_type`, `category`, `tags`, `description`, `version`, `storage_path`, `agent_skill_path`.
|
|
582
|
+
|
|
583
|
+
2. **Via chat message:** The plugin writes the document to your workspace and dispatches a short notification message to you. You do NOT receive the full document content in the message — only metadata and the file path. Read the file if you need the content.
|
|
584
|
+
|
|
585
|
+
### Document Lifecycle
|
|
586
|
+
|
|
587
|
+
```
|
|
588
|
+
User creates/edits document in app
|
|
589
|
+
↓
|
|
590
|
+
Plugin writes file to memory/docs/{category}/{slug}.md
|
|
591
|
+
(with YAML frontmatter for searchability)
|
|
592
|
+
↓
|
|
593
|
+
Plugin dispatches notification to agent:
|
|
594
|
+
[DOC_UPLOADED] — new document
|
|
595
|
+
[DOC_UPDATED] — edited document (includes version number)
|
|
596
|
+
↓
|
|
597
|
+
Agent reads file if needed, confirms sync:
|
|
598
|
+
clawaxis_confirm_doc_sync(document_id: "...", agent_skill_path: "...")
|
|
599
|
+
↓
|
|
600
|
+
Relay marks document as synced (sets synced_at, agent_skill_path)
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
### Where Documents Are Stored
|
|
604
|
+
|
|
605
|
+
Documents are written to your workspace under `memory/docs/{category}/{slug}.md`. This path is inside OpenClaw's memory directory, so the file is **automatically indexed by vector search** — you can find it with `memory_search` without any extra setup.
|
|
606
|
+
|
|
607
|
+
**Example file structure:**
|
|
608
|
+
```
|
|
609
|
+
~/.openclaw/workspace/memory/docs/
|
|
610
|
+
├── branding/
|
|
611
|
+
│ └── brand-voice-guide.md
|
|
612
|
+
├── reference/
|
|
613
|
+
│ └── competitor-analysis.md
|
|
614
|
+
└── general/
|
|
615
|
+
└── project-overview.md
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
Each file has YAML frontmatter:
|
|
619
|
+
```yaml
|
|
620
|
+
---
|
|
621
|
+
title: "Brand Voice Guide"
|
|
622
|
+
type: style_guide
|
|
623
|
+
category: branding
|
|
624
|
+
tags: [voice, tone, brand]
|
|
625
|
+
description: "How to write in the company's voice"
|
|
626
|
+
version: 1
|
|
627
|
+
synced: 2026-02-09T12:00:00.000Z
|
|
628
|
+
---
|
|
629
|
+
|
|
630
|
+
# Brand Voice Guide
|
|
631
|
+
|
|
632
|
+
(document content follows...)
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### Document Notification Messages
|
|
636
|
+
|
|
637
|
+
**`[DOC_UPLOADED]`** — A new document was saved to your workspace.
|
|
638
|
+
```
|
|
639
|
+
[DOC_UPLOADED] The user uploaded a new document: "Brand Voice Guide".
|
|
640
|
+
Type: style_guide | Category: branding | Tags: voice, tone, brand.
|
|
641
|
+
Saved to: /path/to/memory/docs/branding/brand-voice-guide.md.
|
|
642
|
+
This file is now searchable via memory_search. Read it with the read tool
|
|
643
|
+
if you want to review. Confirm sync by calling clawaxis_confirm_doc_sync
|
|
644
|
+
with document_id: <UUID>.
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
**What to do:**
|
|
648
|
+
1. Optionally read the file if you want to review it
|
|
649
|
+
2. Confirm sync: `clawaxis_confirm_doc_sync(document_id: "<UUID>")`
|
|
650
|
+
3. Reply to the user acknowledging the document
|
|
651
|
+
|
|
652
|
+
**`[DOC_UPDATED]`** — An existing document was updated on disk.
|
|
653
|
+
```
|
|
654
|
+
[DOC_UPDATED] The user updated document "Brand Voice Guide" (v2).
|
|
655
|
+
File updated at: /path/to/memory/docs/branding/brand-voice-guide.md.
|
|
656
|
+
Read it with the read tool if you need to review the changes.
|
|
657
|
+
Confirm sync by calling clawaxis_confirm_doc_sync with document_id: <UUID>.
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
**What to do:**
|
|
661
|
+
1. Read the file to see what changed (if relevant to your current work)
|
|
662
|
+
2. Confirm sync: `clawaxis_confirm_doc_sync(document_id: "<UUID>")`
|
|
663
|
+
3. Reply acknowledging the update
|
|
664
|
+
|
|
665
|
+
**`[DOC_DELETED]`** — The user deleted a document. The file has been removed from disk.
|
|
666
|
+
```
|
|
667
|
+
[DOC_DELETED] The user deleted document "Brand Voice Guide"
|
|
668
|
+
(was at: /path/to/memory/docs/branding/brand-voice-guide.md).
|
|
669
|
+
The file has been removed from your workspace.
|
|
670
|
+
Memory search will no longer return results from this document.
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
**What to do:**
|
|
674
|
+
1. Acknowledge the deletion
|
|
675
|
+
2. No sync confirmation needed — the document is already gone
|
|
676
|
+
|
|
677
|
+
### Using Documents in Your Work
|
|
678
|
+
|
|
679
|
+
Documents in `memory/docs/` are automatically searchable. When the user asks you to "write in our brand voice" or "follow the style guide," you can:
|
|
680
|
+
|
|
681
|
+
1. **Search memory:** `memory_search("brand voice style guide")` — returns relevant snippets
|
|
682
|
+
2. **Read the full file:** `read("/path/to/memory/docs/branding/brand-voice-guide.md")`
|
|
683
|
+
3. **Apply the guidelines** to your content
|
|
684
|
+
|
|
685
|
+
The governance system also automatically searches memory for style documents when you use content or image tools (Layer 2: Style Injection). So brand guidelines are often injected automatically.
|
|
686
|
+
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
## Token Tracking
|
|
690
|
+
|
|
691
|
+
Token usage is tracked automatically. You don't need to do anything special, but understanding how it works helps you provide better data.
|
|
692
|
+
|
|
693
|
+
### How It Works
|
|
694
|
+
|
|
695
|
+
```
|
|
696
|
+
Plugin (your runtime)
|
|
697
|
+
↓ per-reply: tokens_used delta
|
|
698
|
+
↓ per-heartbeat: accumulated session tokens
|
|
699
|
+
↓
|
|
700
|
+
ws-relay
|
|
701
|
+
↓ calls increment_agent_tokens() RPC on every reply
|
|
702
|
+
↓
|
|
703
|
+
Database
|
|
704
|
+
├── agents.tokens_used_today (daily counter, auto-resets)
|
|
705
|
+
├── agents.total_tokens_used (lifetime counter)
|
|
706
|
+
├── agents.cost_today (estimated from model_pricing)
|
|
707
|
+
├── agents.total_cost (lifetime cost)
|
|
708
|
+
└── token_usage_daily (daily aggregates for the 7-day chart)
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
### What Gets Tracked
|
|
712
|
+
|
|
713
|
+
| Source | What | Where Stored |
|
|
714
|
+
|---|---|---|
|
|
715
|
+
| Every agent reply | `tokens_used` from the reply message | `messages.tokens_used` + agents counters + daily aggregate |
|
|
716
|
+
| Every log entry | `tokens_used` from `clawaxis_post_log` | `session_logs.tokens_used` |
|
|
717
|
+
| Heartbeat (60s) | Accumulated session tokens (delta since last heartbeat) | agents counters + daily aggregate |
|
|
718
|
+
|
|
719
|
+
### Cost Estimation
|
|
720
|
+
|
|
721
|
+
Cost is estimated automatically from the `model_pricing` table using the `model_used` field you send with each reply. The system assumes a 70/30 input/output token split. If the model isn't found in the pricing table, cost is recorded as $0.
|
|
722
|
+
|
|
723
|
+
### What the User Sees
|
|
724
|
+
|
|
725
|
+
On the Home Dashboard:
|
|
726
|
+
- **Tokens Used Today** — from `agents.tokens_used_today`
|
|
727
|
+
- **Cost Today** — from `agents.cost_today`
|
|
728
|
+
- **7-Day Usage Chart** — from `token_usage_daily` table
|
|
729
|
+
- **Lifetime Stats** — from `agents.total_tokens_used` and `agents.total_cost`
|
|
730
|
+
|
|
731
|
+
Budget controls:
|
|
732
|
+
- `daily_token_budget` and `daily_cost_budget` set limits
|
|
733
|
+
- The app shows warnings when usage approaches the budget
|
|
734
|
+
- Counters auto-reset at `budget_reset_at` (midnight UTC by default)
|
|
735
|
+
|
|
736
|
+
### What You Should Do
|
|
737
|
+
|
|
738
|
+
1. **Always provide `tokens_used` in logs** when reporting significant operations
|
|
739
|
+
2. **Include `model_used`** in your replies so cost estimation works
|
|
740
|
+
3. **Log tool calls with `tokens_used`** so the user sees accurate resource consumption
|
|
741
|
+
|
|
742
|
+
---
|
|
743
|
+
|
|
744
|
+
## Image Generation & Media
|
|
745
|
+
|
|
746
|
+
### Blog Image Best Practice
|
|
747
|
+
|
|
748
|
+
When creating blog or website content, generating a hero image significantly improves the content's visual appeal.
|
|
749
|
+
|
|
750
|
+
**Recommended Process:**
|
|
751
|
+
1. Write the content
|
|
752
|
+
2. Generate an image that represents the article's topic using your available image generation tools
|
|
753
|
+
3. Upload to permanent storage with `clawaxis_upload_media` (temporary URLs from DALL-E etc. expire)
|
|
754
|
+
4. Include the permanent URL in the `media` field, or embed directly in HTML body for `website` content
|
|
755
|
+
5. For `website` content, update `og:image` meta tag with the permanent URL
|
|
756
|
+
|
|
757
|
+
**Image Style:** Check memory for brand style guides. The governance system automatically searches for image style docs when you use image tools (Layer 2: Style Injection). If the user has uploaded brand guidelines as a document, those will be injected into your image prompts automatically.
|
|
758
|
+
|
|
759
|
+
**Recommended Dimensions:**
|
|
760
|
+
| Use Case | Dimensions | Aspect Ratio |
|
|
761
|
+
|---|---|---|
|
|
762
|
+
| Blog hero / og:image | 1200×630 | 1.91:1 (landscape) |
|
|
763
|
+
| Instagram | 1080×1080 | 1:1 (square) |
|
|
764
|
+
| Twitter | 1200×675 | 16:9 (landscape) |
|
|
765
|
+
| TikTok | 1080×1920 | 9:16 (portrait) |
|
|
766
|
+
| YouTube thumbnail | 1280×720 | 16:9 (landscape) |
|
|
767
|
+
|
|
768
|
+
### Permanent URLs
|
|
769
|
+
|
|
770
|
+
**Always upload images before posting content.** Temporary URLs from AI image generators (DALL-E, Stability, etc.) expire within hours. Use `clawaxis_upload_media` to get a permanent R2 URL first, then use that URL in your content.
|
|
771
|
+
|
|
772
|
+
---
|
|
773
|
+
|
|
774
|
+
## Website Content Type — Detailed Guide
|
|
775
|
+
|
|
776
|
+
The `website` content type produces deployable HTML files that render live in the app's WebView.
|
|
777
|
+
|
|
778
|
+
### Getting Styling Information
|
|
779
|
+
|
|
780
|
+
**ALWAYS ask for context before generating website content:**
|
|
781
|
+
|
|
782
|
+
1. **Web Link (Preferred):** "Share a link to your blog/site so I can match the styling."
|
|
783
|
+
- Use `browser` or `web_fetch` to load the page
|
|
784
|
+
- Extract HTML structure and CSS classes
|
|
785
|
+
- Generate new content that matches exactly
|
|
786
|
+
|
|
787
|
+
2. **HTML Template:** "Do you have an existing page I can use as a template?"
|
|
788
|
+
- Analyze structure, identify key elements
|
|
789
|
+
- Generate content using same patterns
|
|
790
|
+
|
|
791
|
+
3. **CSS Reference:** "Do you have a stylesheet URL I should reference?"
|
|
792
|
+
- Include `<link rel="stylesheet" href="path/to/style.css">` in head
|
|
793
|
+
|
|
794
|
+
### Best Practices
|
|
795
|
+
- Match existing site structure — don't invent new patterns
|
|
796
|
+
- Include proper navigation and footer
|
|
797
|
+
- Use semantic HTML: `<article>`, `<header>`, `<nav>`, `<section>`
|
|
798
|
+
- Always include responsive design (viewport meta tag)
|
|
799
|
+
- Proper heading hierarchy, alt text, ARIA labels
|
|
800
|
+
|
|
801
|
+
### When to Use Website vs Blog
|
|
802
|
+
- **`website`** — Deployable HTML file, styled to match their site, landing pages
|
|
803
|
+
- **`blog`** — Plain Markdown content, CMS drafts, content that will be styled later
|
|
804
|
+
|
|
805
|
+
---
|
|
806
|
+
|
|
807
|
+
## Common Workflow Patterns
|
|
808
|
+
|
|
809
|
+
### After generating content
|
|
810
|
+
```
|
|
811
|
+
1. Log start: clawaxis_post_log(action: "content_generate", detail: "Starting research...", level: "info")
|
|
812
|
+
2. Do the work
|
|
813
|
+
3. Post to app: clawaxis_post_content(...)
|
|
814
|
+
4. Log complete: clawaxis_post_log(action: "content_post", detail: "Posted report (850 words)", level: "success")
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
### Creating a cron job
|
|
818
|
+
```
|
|
819
|
+
1. Create cron: cron({ action: "add", job: {...} })
|
|
820
|
+
2. Register: clawaxis_notify_routine(name, cron_expression, instruction, openclaw_cron_id, ...)
|
|
821
|
+
3. Log: clawaxis_post_log(action: "cron_execute", detail: "Created routine: Daily AI News", level: "success")
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
### Modifying a cron job
|
|
825
|
+
```
|
|
826
|
+
1. Update cron: cron({ action: "update", jobId: "...", patch: {...} })
|
|
827
|
+
2. Sync app: clawaxis_update_routine(routine_id: "...", cron_expression: "...", schedule_human: "...")
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
### When a document is uploaded
|
|
831
|
+
```
|
|
832
|
+
1. Receive: [DOC_UPLOADED] notification (file already written to workspace)
|
|
833
|
+
2. Optionally: Read the file if you want to review it
|
|
834
|
+
3. Confirm: clawaxis_confirm_doc_sync(document_id: "...")
|
|
835
|
+
4. Reply: Acknowledge to the user
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
### When Logging
|
|
839
|
+
|
|
840
|
+
**DO log:**
|
|
841
|
+
- Starting any task that takes >5 seconds
|
|
842
|
+
- Installing dependencies or making system changes
|
|
843
|
+
- API calls or external requests
|
|
844
|
+
- Completing major steps
|
|
845
|
+
- Errors or warnings
|
|
846
|
+
- Resource usage (tokens, API calls, costs)
|
|
847
|
+
|
|
848
|
+
**DON'T log:**
|
|
849
|
+
- Reading small files (<100 lines)
|
|
850
|
+
- Simple calculations
|
|
851
|
+
- Internal micro-steps
|
|
852
|
+
- Every single thought process
|
|
853
|
+
|
|
854
|
+
**Golden rule:** If the user might wonder "is it still working?", log it.
|
|
855
|
+
|
|
856
|
+
---
|
|
857
|
+
|
|
858
|
+
## Quick Reference: All Valid Enum Values
|
|
859
|
+
|
|
860
|
+
### content_type (for clawaxis_post_content)
|
|
861
|
+
| Value | Body Format | Notes |
|
|
862
|
+
|---|---|---|
|
|
863
|
+
| `twitter` | Plain text | 280 char max |
|
|
864
|
+
| `instagram` | Plain text | 2200 char max, tags → #hashtags |
|
|
865
|
+
| `linkedin` | Plain text | 3000 char max |
|
|
866
|
+
| `facebook` | Plain text | No limit |
|
|
867
|
+
| `tiktok` | Plain text | 4000 char max, tags → #hashtags |
|
|
868
|
+
| `youtube` | Plain text | 5000 char max, title shown as video title |
|
|
869
|
+
| `website` | Raw HTML | Rendered in WebView |
|
|
870
|
+
| `blog` | Markdown | Show word_count, tags, seo_keywords |
|
|
871
|
+
| `report` | Markdown | Show word_count, tags, seo_keywords |
|
|
872
|
+
| `email` | Markdown | |
|
|
873
|
+
| `ad` | Markdown | |
|
|
874
|
+
| `document` | Markdown | Can be transferred to Documents registry |
|
|
875
|
+
| `other` | Markdown | Catch-all |
|
|
876
|
+
|
|
877
|
+
### log_action (for clawaxis_post_log)
|
|
878
|
+
`chat_message` · `content_generate` · `content_post` · `web_search` · `web_fetch` · `browser_action` · `cron_execute` · `skill_update` · `file_operation` · `system` · `error` · `tool_call`
|
|
879
|
+
|
|
880
|
+
### log_level (for clawaxis_post_log)
|
|
881
|
+
`info` · `success` · `warning` · `error`
|
|
882
|
+
|
|
883
|
+
### routine_status
|
|
884
|
+
`active` · `paused` · `disabled`
|
|
885
|
+
|
|
886
|
+
### routine_frequency
|
|
887
|
+
`once` · `hourly` · `daily` · `weekly` · `monthly` · `custom`
|
|
888
|
+
|
|
889
|
+
**These are database enums. Using invalid values causes a 500 error. Always use values from these lists.**
|
|
890
|
+
|
|
891
|
+
---
|
|
892
|
+
|
|
893
|
+
## Troubleshooting
|
|
894
|
+
|
|
895
|
+
### Content Posting Issues
|
|
896
|
+
|
|
897
|
+
**Problem: 500 error on content_type**
|
|
898
|
+
- Ensure using a valid enum value from the list above
|
|
899
|
+
- NOT valid: `article`, `post`, `marketing`, `newsletter` — use `blog`, `email`, or `other`
|
|
900
|
+
|
|
901
|
+
**Problem: Content not appearing in app**
|
|
902
|
+
- Check content was actually posted (no error returned)
|
|
903
|
+
- Verify `content_type` is a valid enum value
|
|
904
|
+
- Pull to refresh in the app
|
|
905
|
+
|
|
906
|
+
**Problem: Images not showing**
|
|
907
|
+
- Verify `media` structure: `{"images": [{"url": "...", "alt": "..."}], "videos": []}`
|
|
908
|
+
- Check image URL is accessible and not expired
|
|
909
|
+
- For website content, images can be embedded directly in HTML body
|
|
910
|
+
|
|
911
|
+
**Problem: Content renders as plain text instead of Markdown**
|
|
912
|
+
- Check `content_type` is set to `blog`, `report`, `email`, `ad`, `document`, or `other`
|
|
913
|
+
- If you set it to a social platform type, body renders as plain text only
|
|
914
|
+
|
|
915
|
+
**Problem: Content renders in wrong card**
|
|
916
|
+
- The `content_type` alone determines the card. Double-check the value.
|
|
917
|
+
- `blog` renders as Markdown. `website` renders as HTML. `twitter` renders as a tweet.
|
|
918
|
+
|
|
919
|
+
### Routine Sync Issues
|
|
920
|
+
|
|
921
|
+
**Problem: Cron job created but not showing in app**
|
|
922
|
+
- Always call `clawaxis_notify_routine` after creating a cron job
|
|
923
|
+
- Include `openclaw_cron_id` from the cron creation result
|
|
924
|
+
|
|
925
|
+
**Problem: Routine shows wrong schedule**
|
|
926
|
+
- Call `clawaxis_update_routine` with correct `cron_expression` and `schedule_human`
|
|
927
|
+
- Include `next_run_at` as ISO 8601 timestamp
|
|
928
|
+
|
|
929
|
+
### Image Generation Issues
|
|
930
|
+
|
|
931
|
+
**Problem: Generated image URL doesn't work after posting**
|
|
932
|
+
- AI-generated image URLs (DALL-E, Stability, etc.) are time-limited (2-24 hours)
|
|
933
|
+
- **Always upload to R2 first** with `clawaxis_upload_media`, then use the permanent URL
|
|
934
|
+
|
|
935
|
+
---
|
|
936
|
+
|
|
937
|
+
## WebSocket Connection
|
|
938
|
+
|
|
939
|
+
The plugin connects to the ws-relay via WebSocket (persistent, real-time). This is the primary transport for all tools. If WebSocket is unavailable, tools automatically fall back to HTTP via agent-relay.
|
|
940
|
+
|
|
941
|
+
**The connection lifecycle:**
|
|
942
|
+
1. Connect → authenticate with agent token → receive `auth_ok`
|
|
943
|
+
2. Receive `sync` with any pending documents/routines/undelivered messages
|
|
944
|
+
3. Send `ping` every 30s, `heartbeat` every 60s
|
|
945
|
+
4. Heartbeat responses include pending docs/routines (mid-session uploads)
|
|
946
|
+
5. Connection auto-closes after ~400s (Supabase limit) → plugin auto-reconnects
|
|
947
|
+
|
|
948
|
+
**Tools that always use HTTP** (not WebSocket):
|
|
949
|
+
- `clawaxis_get_content` — needs synchronous response with data
|
|
950
|
+
- `clawaxis_upload_media` — binary/large payloads
|
|
951
|
+
|
|
952
|
+
---
|
|
953
|
+
|
|
954
|
+
**Remember:** This documentation is for YOU (future agent sessions). The tool descriptions in the plugin also contain this information, but this file is the comprehensive reference. Keep it updated as features change.
|