@jiggai/recipes 0.4.18 → 0.4.20
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/README.md +4 -1
- package/docs/BUNDLED_RECIPES.md +3 -0
- package/docs/COMMANDS.md +3 -2
- package/docs/MEMORY_SYSTEM.md +304 -0
- package/docs/SWARM_ORCHESTRATOR.md +317 -0
- package/docs/TEAM_WORKFLOW.md +4 -0
- package/docs/WORKFLOW_EXAMPLES.md +292 -0
- package/docs/WORKFLOW_FIXES_2026-03-13.md +23 -0
- package/docs/WORKFLOW_RUNS_FILE_FIRST.md +575 -0
- package/index.ts +130 -29
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/recipes/default/business-team.md +28 -28
- package/recipes/default/customer-support-team.md +26 -26
- package/recipes/default/development-team.md +44 -44
- package/recipes/default/marketing-team.md +76 -88
- package/recipes/default/product-team.md +28 -28
- package/recipes/default/research-team.md +26 -26
- package/recipes/default/social-team.md +44 -44
- package/recipes/default/workflow-runner-addon.md +1 -1
- package/recipes/default/writing-team.md +26 -26
- package/src/lib/workflows/workflow-queue.ts +116 -85
- package/src/lib/workflows/workflow-runner.ts +105 -67
- package/src/lib/workspace.ts +20 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# Workflow examples
|
|
2
|
+
|
|
3
|
+
This document gives you copyable workflow patterns for ClawRecipes.
|
|
4
|
+
|
|
5
|
+
Use it together with:
|
|
6
|
+
- [WORKFLOW_RUNS_FILE_FIRST.md](WORKFLOW_RUNS_FILE_FIRST.md) — concepts, node kinds, triggers, runs, edges
|
|
7
|
+
- [OUTBOUND_POSTING.md](OUTBOUND_POSTING.md) — publishing/posting setup
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Example 1: simplest possible workflow
|
|
12
|
+
|
|
13
|
+
Use this when you just want to prove the runner works.
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"id": "append-demo",
|
|
18
|
+
"name": "Append demo",
|
|
19
|
+
"nodes": [
|
|
20
|
+
{ "id": "start", "kind": "start" },
|
|
21
|
+
{
|
|
22
|
+
"id": "append_log",
|
|
23
|
+
"kind": "tool",
|
|
24
|
+
"assignedTo": { "agentId": "development-team-lead" },
|
|
25
|
+
"action": {
|
|
26
|
+
"tool": "fs.append",
|
|
27
|
+
"args": {
|
|
28
|
+
"path": "shared-context/APPEND_LOG.md",
|
|
29
|
+
"content": "- {{date}} run={{run.id}}\n"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{ "id": "end", "kind": "end" }
|
|
34
|
+
],
|
|
35
|
+
"edges": [
|
|
36
|
+
{ "from": "start", "to": "append_log", "on": "success" },
|
|
37
|
+
{ "from": "append_log", "to": "end", "on": "success" }
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
What it does:
|
|
43
|
+
- starts
|
|
44
|
+
- appends one line to a file
|
|
45
|
+
- ends
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Example 2: LLM draft only
|
|
50
|
+
|
|
51
|
+
Use this when you want the workflow to generate text and stop there.
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"id": "draft-only",
|
|
56
|
+
"name": "Draft only",
|
|
57
|
+
"nodes": [
|
|
58
|
+
{ "id": "start", "kind": "start" },
|
|
59
|
+
{
|
|
60
|
+
"id": "draft_post",
|
|
61
|
+
"kind": "llm",
|
|
62
|
+
"assignedTo": { "agentId": "development-team-lead" },
|
|
63
|
+
"action": {
|
|
64
|
+
"promptTemplate": "Write a short product update for X announcing a new workflow feature."
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{ "id": "end", "kind": "end" }
|
|
68
|
+
],
|
|
69
|
+
"edges": [
|
|
70
|
+
{ "from": "start", "to": "draft_post", "on": "success" },
|
|
71
|
+
{ "from": "draft_post", "to": "end", "on": "success" }
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
What it does:
|
|
77
|
+
- drafts content with an LLM
|
|
78
|
+
- writes the output to `node-outputs/`
|
|
79
|
+
- finishes without posting anything
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Example 3: draft → approve → publish
|
|
84
|
+
|
|
85
|
+
Use this when you want a human review step before external posting.
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"id": "draft-approve-publish",
|
|
90
|
+
"name": "Draft, approve, publish",
|
|
91
|
+
"nodes": [
|
|
92
|
+
{ "id": "start", "kind": "start" },
|
|
93
|
+
{
|
|
94
|
+
"id": "draft_post",
|
|
95
|
+
"kind": "llm",
|
|
96
|
+
"assignedTo": { "agentId": "development-team-lead" },
|
|
97
|
+
"action": {
|
|
98
|
+
"promptTemplate": "Write a short X post announcing our new feature."
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "approval",
|
|
103
|
+
"kind": "human_approval",
|
|
104
|
+
"assignedTo": { "agentId": "development-team-lead" },
|
|
105
|
+
"action": {
|
|
106
|
+
"approvalBindingId": "marketing-approval"
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "publish_x",
|
|
111
|
+
"kind": "tool",
|
|
112
|
+
"assignedTo": { "agentId": "development-team-lead" },
|
|
113
|
+
"action": {
|
|
114
|
+
"tool": "outbound.post",
|
|
115
|
+
"args": {
|
|
116
|
+
"platform": "x",
|
|
117
|
+
"text": "Hello from ClawRecipes",
|
|
118
|
+
"idempotencyKey": "draft-approve-publish:publish_x"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{ "id": "end", "kind": "end" }
|
|
123
|
+
],
|
|
124
|
+
"edges": [
|
|
125
|
+
{ "from": "start", "to": "draft_post", "on": "success" },
|
|
126
|
+
{ "from": "draft_post", "to": "approval", "on": "success" },
|
|
127
|
+
{ "from": "approval", "to": "publish_x", "on": "success" },
|
|
128
|
+
{ "from": "publish_x", "to": "end", "on": "success" }
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
What it does:
|
|
134
|
+
- drafts text
|
|
135
|
+
- pauses for approval
|
|
136
|
+
- publishes only after approval
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Example 4: writeback after work finishes
|
|
141
|
+
|
|
142
|
+
Use this when you want the workflow to leave a durable note in team files.
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"id": "writeback-demo",
|
|
147
|
+
"name": "Writeback demo",
|
|
148
|
+
"nodes": [
|
|
149
|
+
{ "id": "start", "kind": "start" },
|
|
150
|
+
{
|
|
151
|
+
"id": "append_log",
|
|
152
|
+
"kind": "tool",
|
|
153
|
+
"assignedTo": { "agentId": "development-team-lead" },
|
|
154
|
+
"action": {
|
|
155
|
+
"tool": "fs.append",
|
|
156
|
+
"args": {
|
|
157
|
+
"path": "shared-context/APPEND_LOG.md",
|
|
158
|
+
"content": "- workflow ran at {{date}}\n"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"id": "write_summary",
|
|
164
|
+
"kind": "writeback",
|
|
165
|
+
"assignedTo": { "agentId": "development-team-lead" },
|
|
166
|
+
"action": {
|
|
167
|
+
"writebackPaths": ["notes/status.md"]
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
{ "id": "end", "kind": "end" }
|
|
171
|
+
],
|
|
172
|
+
"edges": [
|
|
173
|
+
{ "from": "start", "to": "append_log", "on": "success" },
|
|
174
|
+
{ "from": "append_log", "to": "write_summary", "on": "success" },
|
|
175
|
+
{ "from": "write_summary", "to": "end", "on": "success" }
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Example 5: success path and failure path
|
|
183
|
+
|
|
184
|
+
Use this when you want different behavior after success vs failure.
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"id": "success-error-paths",
|
|
189
|
+
"name": "Success and error branches",
|
|
190
|
+
"nodes": [
|
|
191
|
+
{ "id": "start", "kind": "start" },
|
|
192
|
+
{
|
|
193
|
+
"id": "publish_x",
|
|
194
|
+
"kind": "tool",
|
|
195
|
+
"assignedTo": { "agentId": "development-team-lead" },
|
|
196
|
+
"action": {
|
|
197
|
+
"tool": "outbound.post",
|
|
198
|
+
"args": {
|
|
199
|
+
"platform": "x",
|
|
200
|
+
"text": "Hello from ClawRecipes",
|
|
201
|
+
"idempotencyKey": "success-error-paths:publish_x"
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"id": "notify_failure",
|
|
207
|
+
"kind": "tool",
|
|
208
|
+
"assignedTo": { "agentId": "development-team-lead" },
|
|
209
|
+
"action": {
|
|
210
|
+
"tool": "message",
|
|
211
|
+
"args": {
|
|
212
|
+
"action": "send",
|
|
213
|
+
"channel": "telegram",
|
|
214
|
+
"target": "123456",
|
|
215
|
+
"message": "Workflow publish step failed"
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{ "id": "end", "kind": "end" }
|
|
220
|
+
],
|
|
221
|
+
"edges": [
|
|
222
|
+
{ "from": "start", "to": "publish_x", "on": "success" },
|
|
223
|
+
{ "from": "publish_x", "to": "end", "on": "success" },
|
|
224
|
+
{ "from": "publish_x", "to": "notify_failure", "on": "error" },
|
|
225
|
+
{ "from": "notify_failure", "to": "end", "on": "success" }
|
|
226
|
+
]
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Example 6: cron-triggered workflow skeleton
|
|
233
|
+
|
|
234
|
+
Use this when you want a workflow definition that is meant to run on a schedule.
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"id": "weekday-summary",
|
|
239
|
+
"name": "Weekday summary",
|
|
240
|
+
"triggers": [
|
|
241
|
+
{
|
|
242
|
+
"kind": "cron",
|
|
243
|
+
"cron": "0 14 * * 1-5",
|
|
244
|
+
"tz": "America/New_York"
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
"nodes": [
|
|
248
|
+
{ "id": "start", "kind": "start" },
|
|
249
|
+
{
|
|
250
|
+
"id": "draft_summary",
|
|
251
|
+
"kind": "llm",
|
|
252
|
+
"assignedTo": { "agentId": "development-team-lead" },
|
|
253
|
+
"action": {
|
|
254
|
+
"promptTemplate": "Write a short weekday status summary."
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
{ "id": "end", "kind": "end" }
|
|
258
|
+
],
|
|
259
|
+
"edges": [
|
|
260
|
+
{ "from": "start", "to": "draft_summary", "on": "success" },
|
|
261
|
+
{ "from": "draft_summary", "to": "end", "on": "success" }
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Common mistakes
|
|
269
|
+
|
|
270
|
+
### 1) Expecting `if` or `delay` nodes to work as first-class built-ins
|
|
271
|
+
They are not first-class built-in node kinds today.
|
|
272
|
+
|
|
273
|
+
### 2) Forgetting `assignedTo.agentId`
|
|
274
|
+
Several node kinds require it.
|
|
275
|
+
|
|
276
|
+
### 3) Expecting install to automatically enable posting
|
|
277
|
+
Workflow support and workflow posting are not the same thing.
|
|
278
|
+
|
|
279
|
+
### 4) Using paths outside the team workspace
|
|
280
|
+
`fs.append` is intentionally constrained.
|
|
281
|
+
|
|
282
|
+
### 5) Assuming all incoming edges must succeed
|
|
283
|
+
Current incoming-edge semantics are OR, not AND.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Suggested learning order
|
|
288
|
+
|
|
289
|
+
If you are new to workflows, read in this order:
|
|
290
|
+
1. [WORKFLOW_RUNS_FILE_FIRST.md](WORKFLOW_RUNS_FILE_FIRST.md)
|
|
291
|
+
2. this file
|
|
292
|
+
3. [OUTBOUND_POSTING.md](OUTBOUND_POSTING.md)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Workflow fixes (2026-03-13)
|
|
2
|
+
|
|
3
|
+
This note summarizes the workflow reliability fixes merged on 2026-03-13.
|
|
4
|
+
|
|
5
|
+
## Kitchen (workflow editor)
|
|
6
|
+
- Persist real approval binding ids when saving workflows.
|
|
7
|
+
- Prevents saving synthetic ids like `telegram:dm:<peer>`.
|
|
8
|
+
- Ensures `meta.approvalBindingId` and the `human_approval` node config stay in sync.
|
|
9
|
+
|
|
10
|
+
## Recipes / workflow runner
|
|
11
|
+
### Approval ingestion
|
|
12
|
+
- Robust parsing of approval replies (plain text and formatted/wrapped text).
|
|
13
|
+
- Use the runtime hook name (`message_received`) and scan the canonical workspace root so approval lookup works even when the inbound message is routed to a role workspace (e.g. `workspace-<teamId>/roles/copywriter`).
|
|
14
|
+
|
|
15
|
+
### Queue / worker durability
|
|
16
|
+
- Skip stale recovered tasks so expired claim recovery cannot replay old nodes on runs that already advanced.
|
|
17
|
+
|
|
18
|
+
### Worker cron execution
|
|
19
|
+
- Removed `tools.deny: ["exec"]` from the default `marketing-team` recipe so isolated worker loops can actually execute `worker-tick` commands.
|
|
20
|
+
|
|
21
|
+
## Known remaining issues / follow-ups
|
|
22
|
+
- Completion Telegram notifier is still somewhat intermittent. When it fires, it includes the X URL and runId.
|
|
23
|
+
- If it remains flaky, likely fix is to add a deterministic notification node (workflow-level) or a runner-level `run.completed` notifier that uses the `post_to_platforms` artifact URLs.
|