lua-cli 3.30.0 โ 3.31.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/dist/api-exports.d.ts +1020 -41
- package/dist/api-exports.js +4984 -137
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +25539 -14391
- package/dist/index.js.map +1 -1
- package/dist/voice/test/index.d.ts +4 -4
- package/dist/workflow-builder.d.ts +766 -0
- package/dist/workflow-builder.js +5732 -0
- package/dist/workflow-builder.js.map +1 -0
- package/docs/API_INDEX.md +2 -0
- package/docs/README.md +27 -9
- package/docs/api/Jobs.md +10 -10
- package/docs/api/LuaWorkflow.md +73 -0
- package/docs/api/Workflows.md +110 -0
- package/docs/workflows/approvals.md +28 -0
- package/docs/workflows/artefacts-and-datasets.md +19 -0
- package/docs/workflows/coding-harness.md +12 -0
- package/docs/workflows/compliance-gates.md +16 -0
- package/docs/workflows/connections-in-coding-turns.md +9 -0
- package/docs/workflows/correlation-keys.md +11 -0
- package/docs/workflows/env-overlays.md +12 -0
- package/docs/workflows/evidence-bundles.md +11 -0
- package/docs/workflows/exports.md +5 -0
- package/docs/workflows/external-content-and-toolscope.md +11 -0
- package/docs/workflows/git-credentials.md +11 -0
- package/docs/workflows/knowledge-bindings.md +13 -0
- package/docs/workflows/limits.md +11 -0
- package/docs/workflows/long-steps-and-checkpoints.md +13 -0
- package/docs/workflows/migrating-cloud-tasks.md +9 -0
- package/docs/workflows/migrating-runs.md +13 -0
- package/docs/workflows/output-visibility.md +9 -0
- package/docs/workflows/per-item-approvals.md +9 -0
- package/docs/workflows/private-network-sources.md +12 -0
- package/docs/workflows/recovery.md +28 -0
- package/docs/workflows/replay-local.md +35 -0
- package/docs/workflows/reply-channels.md +11 -0
- package/docs/workflows/retention-and-archival.md +82 -0
- package/docs/workflows/roles.md +12 -0
- package/docs/workflows/schedules.md +11 -0
- package/docs/workflows/script-form.md +50 -0
- package/docs/workflows/testing-offline.md +46 -0
- package/docs/workflows/workspace-backends.md +11 -0
- package/docs/workflows/workspaces-and-long-steps.md +27 -0
- package/package.json +8 -3
- package/scripts/run-api-extractor.mjs +1 -1
- package/template/.gitignore +2 -0
- package/template/examples/workflows/CLAUDE.md +24 -0
- package/template/examples/workflows/adversarial-verify.workflow.script.js +48 -0
- package/template/examples/workflows/github-review.webhook.ts +19 -0
- package/template/examples/workflows/linear-ready.trigger.ts +21 -0
- package/template/examples/workflows/outreach.ts +55 -0
- package/template/examples/workflows/pr-review-round.ts +38 -0
- package/template/examples/workflows/provision-tenant.ts +18 -0
- package/template/examples/workflows/refund-approval.ts +44 -0
- package/template/examples/workflows/research-brief.ts +42 -0
- package/template/examples/workflows/reviewed-brief.ts +19 -0
- package/template/examples/workflows/support-triage.ts +44 -0
- package/template/examples/workflows/ticket-to-pr.ts +65 -0
- package/template/examples/workflows/vendor-invoices.ts +30 -0
- package/template/lua.skill.yaml +1 -0
- package/template/package.json +1 -1
package/docs/API_INDEX.md
CHANGED
|
@@ -11,6 +11,7 @@ Quick reference for all lua-cli APIs and exports.
|
|
|
11
11
|
| [LuaTool](./api/LuaTool.md) | Individual tool interface | `import { LuaTool } from 'lua-cli/skill'` |
|
|
12
12
|
| [LuaWebhook](./api/LuaWebhook.md) | HTTP webhook handler | `import { LuaWebhook } from 'lua-cli'` |
|
|
13
13
|
| [LuaJob](./api/LuaJob.md) | Scheduled task | `import { LuaJob } from 'lua-cli'` |
|
|
14
|
+
| [LuaWorkflow](./api/LuaWorkflow.md) | Durable multi-step workflow (`createStep`/`createWorkflow`) | `import { createWorkflow } from 'lua-cli'` |
|
|
14
15
|
| [PreProcessor](./api/PreProcessor.md) | Message preprocessor | `import { PreProcessor } from 'lua-cli'` |
|
|
15
16
|
| [PostProcessor](./api/PostProcessor.md) | Response postprocessor | `import { PostProcessor } from 'lua-cli'` |
|
|
16
17
|
| LuaMCPServer | MCP server integration | `import { LuaMCPServer } from 'lua-cli'` |
|
|
@@ -20,6 +21,7 @@ Quick reference for all lua-cli APIs and exports.
|
|
|
20
21
|
| API | Purpose | Methods |
|
|
21
22
|
|-----|---------|---------|
|
|
22
23
|
| [AI](./api/AI.md) | AI text generation | `generate()` |
|
|
24
|
+
| [Workflows](./api/Workflows.md) | Workflow runs | `start()`, `get()`, `list()`, `cancel()`, `resume()`, `signal()` |
|
|
23
25
|
| [User](./api/User.md) | User data management | `get()`, `getChatHistory()` |
|
|
24
26
|
| [Products](./api/Products.md) | Product catalog | `get()`, `search()`, `getById()`, `create()`, `update()`, `delete()` |
|
|
25
27
|
| [Baskets](./api/Baskets.md) | Shopping carts | `get()`, `create()`, `getById()`, `addItem()`, `clear()`, `placeOrder()` |
|
package/docs/README.md
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
# lua-cli v3.
|
|
1
|
+
# lua-cli v3.31.0
|
|
2
2
|
|
|
3
|
-
Welcome to the comprehensive API documentation for lua-cli v3.
|
|
3
|
+
Welcome to the comprehensive API documentation for lua-cli v3.31.0. This guide covers every API, class, and function exported by the package.
|
|
4
4
|
|
|
5
5
|
## ๐ Documentation Index
|
|
6
6
|
|
|
7
7
|
### Core Primitives
|
|
8
|
+
|
|
8
9
|
- [LuaAgent](./api/LuaAgent.md) - Unified agent configuration
|
|
9
10
|
- [LuaSkill](./api/LuaSkill.md) - Tool collections
|
|
10
11
|
- [LuaTool](./api/LuaTool.md) - Individual tools
|
|
@@ -16,6 +17,7 @@ Welcome to the comprehensive API documentation for lua-cli v3.30.0. This guide c
|
|
|
16
17
|
- LuaDevice - Bidirectional device communication (send commands, receive triggers)
|
|
17
18
|
|
|
18
19
|
### Runtime APIs
|
|
20
|
+
|
|
19
21
|
- [User API](./api/User.md) - User data management
|
|
20
22
|
- [Products API](./api/Products.md) - Product catalog (with filter support)
|
|
21
23
|
- [Data API](./api/Data.md) - Custom data storage with vector search
|
|
@@ -29,6 +31,7 @@ Welcome to the comprehensive API documentation for lua-cli v3.30.0. This guide c
|
|
|
29
31
|
- Lua Runtime - Channel detection (`import { Lua } from 'lua-cli'`)
|
|
30
32
|
|
|
31
33
|
### Utilities
|
|
34
|
+
|
|
32
35
|
- `env()` - Environment variable access (`import { env } from 'lua-cli'`)
|
|
33
36
|
- `BasketStatus` - Basket state enum
|
|
34
37
|
- `OrderStatus` - Order state enum
|
|
@@ -49,7 +52,7 @@ import {
|
|
|
49
52
|
LuaJob,
|
|
50
53
|
PreProcessor,
|
|
51
54
|
PostProcessor,
|
|
52
|
-
|
|
55
|
+
|
|
53
56
|
// Runtime APIs
|
|
54
57
|
User,
|
|
55
58
|
Products,
|
|
@@ -58,7 +61,7 @@ import {
|
|
|
58
61
|
Data,
|
|
59
62
|
Jobs,
|
|
60
63
|
Webhooks,
|
|
61
|
-
|
|
64
|
+
|
|
62
65
|
// Instances
|
|
63
66
|
UserDataInstance,
|
|
64
67
|
ProductInstance,
|
|
@@ -66,19 +69,20 @@ import {
|
|
|
66
69
|
OrderInstance,
|
|
67
70
|
DataEntryInstance,
|
|
68
71
|
JobInstance,
|
|
69
|
-
|
|
72
|
+
|
|
70
73
|
// Enums
|
|
71
74
|
BasketStatus,
|
|
72
75
|
OrderStatus,
|
|
73
|
-
|
|
76
|
+
|
|
74
77
|
// Utilities
|
|
75
|
-
env
|
|
78
|
+
env,
|
|
76
79
|
} from 'lua-cli';
|
|
77
80
|
```
|
|
78
81
|
|
|
79
82
|
### Common Patterns
|
|
80
83
|
|
|
81
84
|
#### Create a Tool
|
|
85
|
+
|
|
82
86
|
```typescript
|
|
83
87
|
import { LuaTool } from 'lua-cli/skill';
|
|
84
88
|
import { z } from 'zod';
|
|
@@ -87,7 +91,7 @@ export default class MyTool implements LuaTool {
|
|
|
87
91
|
name = 'my_tool';
|
|
88
92
|
description = 'Tool description';
|
|
89
93
|
inputSchema = z.object({ param: z.string() });
|
|
90
|
-
|
|
94
|
+
|
|
91
95
|
async execute(input: z.infer<typeof this.inputSchema>) {
|
|
92
96
|
return { result: 'success' };
|
|
93
97
|
}
|
|
@@ -95,17 +99,19 @@ export default class MyTool implements LuaTool {
|
|
|
95
99
|
```
|
|
96
100
|
|
|
97
101
|
#### Create an Agent
|
|
102
|
+
|
|
98
103
|
```typescript
|
|
99
104
|
import { LuaAgent, LuaSkill } from 'lua-cli';
|
|
100
105
|
|
|
101
106
|
export const agent = new LuaAgent({
|
|
102
107
|
name: 'my-agent',
|
|
103
108
|
persona: 'Agent personality...',
|
|
104
|
-
skills: [skill1, skill2]
|
|
109
|
+
skills: [skill1, skill2],
|
|
105
110
|
});
|
|
106
111
|
```
|
|
107
112
|
|
|
108
113
|
#### Use Runtime APIs
|
|
114
|
+
|
|
109
115
|
```typescript
|
|
110
116
|
import { User, Products, Data } from 'lua-cli';
|
|
111
117
|
|
|
@@ -119,6 +125,7 @@ await Data.create('notes', { text: 'Hello' });
|
|
|
119
125
|
## ๐ By Category
|
|
120
126
|
|
|
121
127
|
### For Building Agents
|
|
128
|
+
|
|
122
129
|
- Start with [LuaAgent](./api/LuaAgent.md)
|
|
123
130
|
- Learn about [LuaSkill](./api/LuaSkill.md)
|
|
124
131
|
- Create [LuaTool](./api/LuaTool.md)
|
|
@@ -126,25 +133,30 @@ await Data.create('notes', { text: 'Hello' });
|
|
|
126
133
|
- Schedule [LuaJob](./api/LuaJob.md) tasks
|
|
127
134
|
|
|
128
135
|
### For Data Management
|
|
136
|
+
|
|
129
137
|
- [User API](./api/User.md) - User profiles
|
|
130
138
|
- [Data API](./api/Data.md) - Custom collections
|
|
131
139
|
- [Products API](./api/Products.md) - Product catalog
|
|
132
140
|
|
|
133
141
|
### For E-commerce
|
|
142
|
+
|
|
134
143
|
- [Products API](./api/Products.md) - Product catalog
|
|
135
144
|
- [Baskets API](./api/Baskets.md) - Shopping carts
|
|
136
145
|
- [Orders API](./api/Orders.md) - Order fulfillment
|
|
137
146
|
|
|
138
147
|
### For Automation
|
|
148
|
+
|
|
139
149
|
- [LuaJob](./api/LuaJob.md) - Scheduled tasks (cron, intervals)
|
|
140
150
|
- [Jobs API](./api/Jobs.md) - Dynamic job creation from tools
|
|
141
151
|
- [LuaWebhook](./api/LuaWebhook.md) - HTTP endpoints for external triggers
|
|
142
152
|
|
|
143
153
|
### For Message Processing
|
|
154
|
+
|
|
144
155
|
- [PreProcessor](./api/PreProcessor.md) - Filter/modify incoming messages
|
|
145
156
|
- [PostProcessor](./api/PostProcessor.md) - Format/enhance agent responses
|
|
146
157
|
|
|
147
158
|
### For Third-Party Integrations
|
|
159
|
+
|
|
148
160
|
- `lua integrations` command - Connect accounts (Linear, Discord, Google Calendar, etc.)
|
|
149
161
|
- Auto-creates MCP servers for connected integrations
|
|
150
162
|
|
|
@@ -153,16 +165,19 @@ await Data.create('notes', { text: 'Hello' });
|
|
|
153
165
|
## ๐ฏ Learning Path
|
|
154
166
|
|
|
155
167
|
### Beginner
|
|
168
|
+
|
|
156
169
|
1. Read [LuaAgent](./api/LuaAgent.md) - Understand agent configuration
|
|
157
170
|
2. Read [LuaTool](./api/LuaTool.md) - Learn to create tools
|
|
158
171
|
3. Read [LuaSkill](./api/LuaSkill.md) - Organize tools into skills
|
|
159
172
|
|
|
160
173
|
### Intermediate
|
|
174
|
+
|
|
161
175
|
1. [User API](./api/User.md) - Work with user data
|
|
162
176
|
2. [Products API](./api/Products.md) - Manage products
|
|
163
177
|
3. [Data API](./api/Data.md) - Use custom storage
|
|
164
178
|
|
|
165
179
|
### Advanced
|
|
180
|
+
|
|
166
181
|
1. [LuaJob](./api/LuaJob.md) - Schedule automated tasks
|
|
167
182
|
2. [Jobs API](./api/Jobs.md) - Create jobs dynamically
|
|
168
183
|
3. [LuaWebhook](./api/LuaWebhook.md) - Build integrations
|
|
@@ -218,6 +233,7 @@ await Data.create('notes', { text: 'Hello' });
|
|
|
218
233
|
## ๐ Documentation Standards
|
|
219
234
|
|
|
220
235
|
Each API doc includes:
|
|
236
|
+
|
|
221
237
|
- โ
Overview and purpose
|
|
222
238
|
- โ
Type definitions
|
|
223
239
|
- โ
Complete method reference
|
|
@@ -255,6 +271,7 @@ Each API doc includes:
|
|
|
255
271
|
## Additional Utilities
|
|
256
272
|
|
|
257
273
|
### Lua Runtime
|
|
274
|
+
|
|
258
275
|
```typescript
|
|
259
276
|
import { Lua } from 'lua-cli';
|
|
260
277
|
|
|
@@ -264,6 +281,7 @@ if (Lua.request.channel === 'whatsapp') {
|
|
|
264
281
|
```
|
|
265
282
|
|
|
266
283
|
### env() Utility
|
|
284
|
+
|
|
267
285
|
```typescript
|
|
268
286
|
import { env } from 'lua-cli';
|
|
269
287
|
|
package/docs/api/Jobs.md
CHANGED
|
@@ -53,7 +53,7 @@ const job = await Jobs.create({
|
|
|
53
53
|
console.log('Job created:', job.id);
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
### `Jobs.
|
|
56
|
+
### `Jobs.getJob(jobId)`
|
|
57
57
|
|
|
58
58
|
Retrieves a job by ID.
|
|
59
59
|
|
|
@@ -64,7 +64,7 @@ Retrieves a job by ID.
|
|
|
64
64
|
|
|
65
65
|
**Example:**
|
|
66
66
|
```typescript
|
|
67
|
-
const job = await Jobs.
|
|
67
|
+
const job = await Jobs.getJob('job_123');
|
|
68
68
|
console.log(job.name);
|
|
69
69
|
console.log(job.schedule);
|
|
70
70
|
```
|
|
@@ -85,7 +85,7 @@ interface JobConfig {
|
|
|
85
85
|
/** When/how often to run */
|
|
86
86
|
schedule: JobSchedule;
|
|
87
87
|
|
|
88
|
-
/** Maximum execution time in
|
|
88
|
+
/** Maximum execution time in seconds (default 300, supported range: 1-600) */
|
|
89
89
|
timeout?: number;
|
|
90
90
|
|
|
91
91
|
/** Retry configuration */
|
|
@@ -133,7 +133,7 @@ schedule: {
|
|
|
133
133
|
```typescript
|
|
134
134
|
schedule: {
|
|
135
135
|
type: 'interval',
|
|
136
|
-
|
|
136
|
+
seconds: number // Seconds between executions
|
|
137
137
|
}
|
|
138
138
|
```
|
|
139
139
|
|
|
@@ -142,13 +142,13 @@ schedule: {
|
|
|
142
142
|
// Run every 5 minutes
|
|
143
143
|
schedule: {
|
|
144
144
|
type: 'interval',
|
|
145
|
-
|
|
145
|
+
seconds: 300
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
// Run every hour
|
|
149
149
|
schedule: {
|
|
150
150
|
type: 'interval',
|
|
151
|
-
|
|
151
|
+
seconds: 3600
|
|
152
152
|
}
|
|
153
153
|
```
|
|
154
154
|
|
|
@@ -157,7 +157,7 @@ schedule: {
|
|
|
157
157
|
```typescript
|
|
158
158
|
schedule: {
|
|
159
159
|
type: 'cron',
|
|
160
|
-
|
|
160
|
+
expression: string // Cron expression
|
|
161
161
|
}
|
|
162
162
|
```
|
|
163
163
|
|
|
@@ -166,19 +166,19 @@ schedule: {
|
|
|
166
166
|
// Every day at 9 AM
|
|
167
167
|
schedule: {
|
|
168
168
|
type: 'cron',
|
|
169
|
-
|
|
169
|
+
expression: '0 9 * * *'
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
// Every Monday at 8 AM
|
|
173
173
|
schedule: {
|
|
174
174
|
type: 'cron',
|
|
175
|
-
|
|
175
|
+
expression: '0 8 * * 1'
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
// Every 15 minutes
|
|
179
179
|
schedule: {
|
|
180
180
|
type: 'cron',
|
|
181
|
-
|
|
181
|
+
expression: '*/15 * * * *'
|
|
182
182
|
}
|
|
183
183
|
```
|
|
184
184
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# LuaWorkflow โ `createStep` / `createWorkflow`
|
|
2
|
+
|
|
3
|
+
The workflow primitive: a **durable, multi-step program** you author in TypeScript, compile with `lua compile`, and push with `lua push workflow`. The engine executes the compiled graph server-side โ steps survive restarts, waits hold no compute, and approvals/signals park the run until a person or a webhook answers.
|
|
4
|
+
|
|
5
|
+
> **Execution model โ read this first.** *`execute` re-runs from the top after resume; execution is at-least-once โ dedupe on `occurrenceId`.* `occurrenceId` is `${lineageId}:${stepId}` โ the same key on retry, resume, `retry-step` and a repair run; an effect that must be unique across independent runs needs your own business key (`refund:${ticketId}`). Wrap external effects in `ctx.once(key, fn)`.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { createStep, createWorkflow, defineWorkflow, step, stepOf, eq, gt, gte, lit, template, fromInit, fromStep, fromKnowledge, rows, env } from 'lua-cli';
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## `createStep(config)`
|
|
14
|
+
|
|
15
|
+
A typed code step. `inputSchema` / `outputSchema` / `resumeSchema` are zod schemas; the compiler serializes them to JSON Schema.
|
|
16
|
+
|
|
17
|
+
| Field | Meaning |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `id` | Unique step id (referenced by `then`, containers, `fromStep`) |
|
|
20
|
+
| `inputSchema` / `outputSchema` | zod; outputs are validated after every attempt |
|
|
21
|
+
| `timeoutSeconds` | Per-attempt wall (worker tier โค 600; `tier:'job'` up to 86 400) |
|
|
22
|
+
| `retry` | `{ maxAttempts, backoffSeconds?, backoff?: 'fixed'\|'exponential', maxBackoffSeconds? }` โ waits `backoffSeconds ยท 2^(attempt-1)` capped at `maxBackoffSeconds` |
|
|
23
|
+
| `sideEffects` | `'external'` โ never auto-retried on a platform-fault reclaim โ the step **parks** instead (see [When a step parks](../workflows/recovery.md)) |
|
|
24
|
+
| `onError` | `'fail'` (default) ยท `'continue'` ยท `'park'` |
|
|
25
|
+
| `requiredConnections` | Connection ids that must mount before `execute` runs |
|
|
26
|
+
| `tier` / `workspace` / `jobResources` / `jobTools` | Job-tier fields โ see [Workspaces and long steps](../workflows/workspaces-and-long-steps.md) |
|
|
27
|
+
| `execute(ctx)` | `ctx`: `inputData`, `resumeData`, `getInitData()`, `getStepResult(id)`, `state`, `suspend()`, `bail()`, `bailRun()`, `once()`, `log()`, `env`, `artefacts`, `occurrenceId`, `workspace?` |
|
|
28
|
+
|
|
29
|
+
`ctx.suspend(payload)` parks the step for `Workflows.resume(runId, stepId, resumeData)`; on resume **`execute` re-runs from the top** with `ctx.resumeData` set.
|
|
30
|
+
|
|
31
|
+
## `createWorkflow(config)โฆcommit()`
|
|
32
|
+
|
|
33
|
+
`createWorkflow(cfg)` opens a fluent builder; `.commit()` freezes it into the compiled graph. `defineWorkflow(cfg, (wf) => โฆ)` is sugar for the same thing.
|
|
34
|
+
|
|
35
|
+
Config: `name`, `description?`, `inputSchema`, `outputSchema?`, `budget?` (`maxCredits`, `maxDurationSeconds`, `maxJobSeconds?`), `schedule?` (`{ type:'cron', expression, timezone }`), `scheduleInput?`, `concurrencyPolicy?` (`'allow'|'forbid'`), `workspace?`, `outputVisibility?` (see [Output visibility](../workflows/output-visibility.md)), `env.template()` overlays (see [Env overlays](../workflows/env-overlays.md)).
|
|
36
|
+
|
|
37
|
+
### Builder verbs and the placement rule
|
|
38
|
+
|
|
39
|
+
**The call site places.** Every builder call โ `then`, `agentStep`, `specialistStep`, `toolStep`, `map`, `approval`, `waitForSignal`, `sleep`, `sleepUntil`, `foreach`, `parallel`, `branch`, `switch`, `dowhile`, `dountil`, `workflow` โ appends **exactly one** entry to the chain where it is called. Containers take `StepRef`s: an inline step object, or a **string** naming an `agentStep`/`specialistStep`/`toolStep` declared elsewhere in the same chain โ a string ref inside a container means "declare here, inside me" and does not append a second top-level entry. An id declared but never placed is `WORKFLOW_UNPLACED_STEP` (warning locally, error at push); referenced but never declared is `unknown-step-ref` at `.commit()`.
|
|
40
|
+
|
|
41
|
+
| Verb | Entry |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `.then(step, input?)` | Sequential step |
|
|
44
|
+
| `.agentStep(id, { agentId, prompt, outputSchema?, toolScope?, tier?, โฆ })` | Agent turn (`prompt` is a `template(...)`) |
|
|
45
|
+
| `.specialistStep(id, { role, prompt, โฆ })` | Ephemeral role on the owning agent (D25) |
|
|
46
|
+
| `.toolStep(id, { toolId, input? })` | One tool call |
|
|
47
|
+
| `.map(descriptors, { id })` | Data reshaping โ `id` is **required** once the workflow has โฅ 2 maps (`map-id-required`) |
|
|
48
|
+
| `.parallel([...arms], { merge? })` | Concurrent arms; a `[map, step]` pair is a legal arm (lowered to an implicit subrun) |
|
|
49
|
+
| `.switch([[predicate, armRef]...], otherwise?)` / `.branch(...)` | Conditional (exclusive / inclusive) |
|
|
50
|
+
| `.foreach(step, { concurrency?, maxItems?, chunk?, rateLimit? })` / `.foreach({ items })` | Fan-out over an upstream array |
|
|
51
|
+
| `.dowhile(ref, predicate, { maxIterations, intervalSeconds? })` / `.dountil(...)` | Loop |
|
|
52
|
+
| `.sleep(ms)` / `.sleepUntil(template)` | Engine-side waits โ `sleepUntil` lowers to an `<id>_at` mapping + `sleepUntil{dateFrom}` (D6-r1) |
|
|
53
|
+
| `.approval(id, { title, approver, timeoutHours, onTimeout, editable?, editablePaths?, itemsPath?, โฆ })` | Human gate โ see [Approvals](../workflows/approvals.md) |
|
|
54
|
+
| `.waitForSignal(id, { signal, schema?, timeoutHours, acceptedSources? })` | External event via `Workflows.signal` |
|
|
55
|
+
| `.workflow(id, ref, input?, { workspace? })` | Child run the parent waits for |
|
|
56
|
+
|
|
57
|
+
### Typed predicates
|
|
58
|
+
|
|
59
|
+
`step(x).path('confidence')` / `stepOf<typeof schema>('id').path('confidence')` yield a `TypedRef<T>`; `eq`, `gt`, `gte`, `inSet` type-check against `lit(...)` literals โ `gt(number, lit('a'))` does not compile.
|
|
60
|
+
|
|
61
|
+
### Bindings
|
|
62
|
+
|
|
63
|
+
`fromInit(path)` ยท `fromStep(id, path?)` ยท `template('${initData.x} ${stepResults.id.y}')` ยท `fromKnowledge({ source, query, maxChars })` ยท `rows(id, path, { offset, limit })` (paged dataset rows) ยท `env(key)` (run-time secret) vs `env.template(key)` (push-time overlay).
|
|
64
|
+
|
|
65
|
+
## Testing and pushing
|
|
66
|
+
|
|
67
|
+
- Offline: `lua test workflow <name>` โ the local reference driver ([Testing locally](./Workflows.md#testing-locally), full flags in [Testing offline](../workflows/testing-offline.md)).
|
|
68
|
+
- `lua push workflow` compiles, validates (placement, schema flow, caps preflight) and creates a sandbox version; `lua workflows deploy` / `activate` manage the lifecycle.
|
|
69
|
+
|
|
70
|
+
## Related
|
|
71
|
+
|
|
72
|
+
- [Workflows](./Workflows.md) โ the runtime API (`Workflows.start/get/list/cancel/resume/signal`)
|
|
73
|
+
- [When a step parks](../workflows/recovery.md) ยท [Approvals](../workflows/approvals.md) ยท [Script form](../workflows/script-form.md)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Workflows API
|
|
2
|
+
|
|
3
|
+
The Workflows API lets your tools, jobs, webhooks, triggers and other workflows start, inspect and steer **workflow runs** โ durable, multi-step programs you author with `createWorkflow(...)` and push with `lua push workflow`.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { Workflows } from 'lua-cli';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Inside a sandbox (tools, jobs, webhooks, workflow code steps) `Workflows` is also available as a global.
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
- `start` **never awaits execution** โ it returns `{ runId, status }` immediately. `waitSeconds` (โค 55) asks the server to hold the response for early terminal state; it changes the response, never the execution model.
|
|
16
|
+
- Runs are idempotent on `idempotencyKey` โ re-sending the same key returns the existing run instead of a duplicate.
|
|
17
|
+
- A workflow with `concurrencyPolicy: 'forbid'` refuses a second start while one is in flight with a thrown `WorkflowApiError { code: 'RUNS_IN_FLIGHT', blockingRunId }` โ never a 429, never a gate.
|
|
18
|
+
- `status: 'gated'` means the run is parked (quota, billing or consent) and holds no slot. Consent gates are cleared from the desktop or with `lua workflows approve`.
|
|
19
|
+
- `nameOrId` resolves the workflow **name on the calling agent first**, then a workflow id.
|
|
20
|
+
- `get` / `list` honour output visibility: a restricted run comes back with `restricted: true` and no `output` โ never an error.
|
|
21
|
+
- From a workflow code step, `Workflows.start` creates a **detached** run (no parent link). Use the `.workflow(...)` builder node when the parent should wait.
|
|
22
|
+
|
|
23
|
+
## Methods
|
|
24
|
+
|
|
25
|
+
### `Workflows.start(nameOrId, input?, opts?)`
|
|
26
|
+
|
|
27
|
+
Starts a run.
|
|
28
|
+
|
|
29
|
+
**Parameters:**
|
|
30
|
+
|
|
31
|
+
- `nameOrId` (string) โ workflow name (agent-local) or id
|
|
32
|
+
- `input` (unknown) โ validated against the workflow's `inputSchema`
|
|
33
|
+
- `opts` (object, optional)
|
|
34
|
+
- `idempotencyKey` (string) โ dedup key (โค 128 chars)
|
|
35
|
+
- `budget` (`{ maxCredits?, maxSteps?, maxDurationSeconds? }`)
|
|
36
|
+
- `waitSeconds` (number โค 55) โ server long-poll
|
|
37
|
+
- `initialState` (object โค 64 KB) โ seeds `ctx.state`
|
|
38
|
+
- `correlationKey` (string), `tags` (string[] โค 10)
|
|
39
|
+
- `replyTo` (`{ channel, threadId }`) โ customer-channel continuation
|
|
40
|
+
- `workflowVersionId` (string) โ pin a version (default: the active one)
|
|
41
|
+
|
|
42
|
+
**Returns:** `Promise<{ runId, status: 'queued' | 'gated' | 'running' | 'completed' | 'failed', output? }>`
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
const { runId, status } = await Workflows.start(
|
|
46
|
+
'outreach',
|
|
47
|
+
{ leads },
|
|
48
|
+
{ idempotencyKey: `outreach:${batchId}`, tags: ['crm'] }
|
|
49
|
+
);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### `Workflows.get(runId)`
|
|
53
|
+
|
|
54
|
+
Returns the run summary (status, counts, gate, lineage, `output` when readable).
|
|
55
|
+
|
|
56
|
+
### `Workflows.list(opts?)`
|
|
57
|
+
|
|
58
|
+
`opts`: `{ limit?, status?, workflow?, correlationKey?, tags?, sort? }` โ `tags` are AND-ed; `sort` is one of `-createdAt | createdAt | -durationMs | durationMs`.
|
|
59
|
+
|
|
60
|
+
### `Workflows.cancel(runId, opts?)`
|
|
61
|
+
|
|
62
|
+
`opts.mode` is `'request'` (default, two-stage) or `'force'` (after `forceAvailableAt`). Returns `{ status, nextAction: 'cancel_again' | 'force' | 'none', forceAvailableAt? }`. A running code step is killed within seconds; if the runner cannot be reached the step ends at its next boundary (โค 10 min) โ cancellation is never lost either way.
|
|
63
|
+
|
|
64
|
+
### `Workflows.resume(runId, stepId, resumeData)`
|
|
65
|
+
|
|
66
|
+
Resumes a step suspended with `ctx.suspend(...)`. The loser of a resume race receives `{ resumed: false, reason: 'already_resumed', recorded }` โ never an error. Approvals resolve through `lua workflows approve` (human-only); signals through `Workflows.signal`.
|
|
67
|
+
|
|
68
|
+
### `Workflows.signal(runId, name, payload?, opts?)`
|
|
69
|
+
|
|
70
|
+
Delivers a named signal to a run waiting on `waitForSignal(name)`. `opts.dedupeKey` makes a re-send a no-op (`{ accepted: true, duplicate: true }`). Returns `{ accepted, reason?: 'source_not_accepted' | 'duplicate' | 'parked' }`.
|
|
71
|
+
|
|
72
|
+
### Reserved members
|
|
73
|
+
|
|
74
|
+
`startBatch`, `signalByKey`, `raiseBudget`, `setGoal` and `goals.{list,get,pause,resume,close}` are part of the API surface (the member list is frozen) and throw `WorkflowApiError { code: 'WORKFLOWS_API_UNAVAILABLE' }` until their server routes ship. For `startBatch`: from an agent turn, prefer the `startWorkflowRunBatch` tool (one consent card for the whole batch, D23-r5).
|
|
75
|
+
|
|
76
|
+
## Errors
|
|
77
|
+
|
|
78
|
+
All failures throw `WorkflowApiError` with `code` (the server discriminator โ `RUNS_IN_FLIGHT`, `SUSPENDED_CAP`, `WORKFLOW_NOT_FOUND`, `CONTROL_UNAVAILABLE`, โฆ), `statusCode`, and any extra fields the server returned (for example `blockingRunId`).
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
try {
|
|
82
|
+
await Workflows.start('nightly-sync', {});
|
|
83
|
+
} catch (e) {
|
|
84
|
+
if (e.code === 'RUNS_IN_FLIGHT') return `Already running: ${e.blockingRunId}`;
|
|
85
|
+
throw e;
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Testing locally
|
|
90
|
+
|
|
91
|
+
`lua test workflow <name>` runs a compiled workflow **offline** through the local reference driver โ no engine, no cluster:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
lua test workflow outreach --input @leads.json \
|
|
95
|
+
--step-output draftEmail=@fixtures/draft.json \
|
|
96
|
+
--approve reviewDrafts=@edited.json \
|
|
97
|
+
--ledger-out out.json
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
- `--step-output <id>=@file|<json>` completes a step without running it (validated against its `outputSchema`) โ this is how a predicate over an agent output gets both truth values under the default `--agents fake`.
|
|
101
|
+
- `--approve <id>[=@payload]` / `--deny <id>[=@reason]` pre-answer approvals; `--signal <name>=<json>` pre-supplies `waitForSignal` payloads in order.
|
|
102
|
+
- `--fixtures <dir>` replays recorded agent/tool outputs (`--record <dir>` writes them); a missing fixture exits **5** โ never a silent fake.
|
|
103
|
+
- `--from-run <runId>` seeds every completed step from a real run and restarts at the first non-completed one.
|
|
104
|
+
- `--ledger-out <file>` writes the in-memory ledger; `lua workflows replay <runId> --local` re-evaluates a real run's predicates and mappings against your compiled artifact and reports `LEDGER_DIVERGENCE`.
|
|
105
|
+
- `--park <id>` simulates a platform-fault park of a `sideEffects:'external'` step (retry / skip / complete / fail, same verbs as production); `--fast-retries` collapses retry backoff to 0; `--real-time` actually waits instead of fast-forwarding the virtual clock; `--artefacts-dir <dir>` backs `ctx.artefacts.*` on disk.
|
|
106
|
+
|
|
107
|
+
## Related
|
|
108
|
+
|
|
109
|
+
- `lua workflows` โ list, start, runs, status, watch, attach, cancel, resume, approve, signal, replay, logs, delete โ `attach` re-attaches to a running run's event stream (the same stream your chat card re-attaches to)
|
|
110
|
+
- [LuaWorkflow](./LuaWorkflow.md) โ the builder primitive
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Approvals
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec 06 ยง6.4. This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
`.approval(id, cfg)` parks the run until a person decides. The node completes with `{ approved, payload?, edited?, timedOut?, escalations? }` โ branchable data, never an exception.
|
|
6
|
+
|
|
7
|
+
## Approver specs
|
|
8
|
+
|
|
9
|
+
`approver:` takes `'creator' | 'org-admins' | { users: [...] } | { role: '<org-role>' } | { group: '<group>' }`. Role/group specs are org data and template-portable; user lists are not. Approvers are re-resolved **at suspend and at decision** โ a role change mid-wait applies.
|
|
10
|
+
|
|
11
|
+
- **Maker-checker**: `excludeInitiator: true` โ whoever started the run can never approve it. On a customer-channel run (`principalKind:'customer'`) an approval resolving to `'creator'` fails `approver-is-run-principal`.
|
|
12
|
+
- **Four-eyes**: `fourEyes: { edit: <spec>, approve: <spec> }` โ whoever edits the payload cannot be the one who approves it.
|
|
13
|
+
|
|
14
|
+
## Deadlines and escalation chains
|
|
15
|
+
|
|
16
|
+
`timeoutHours` runs on **business time** when `businessHours: { tz, calendar }` is set. `onTimeout` is a chain: each `{ escalateTo, timeoutHours }` hop re-prompts the next audience; the terminal `'deny'` (or `'cancel-run'`/`'continue'`) completes the node โ e.g. `{approved:false, timedOut:true, escalations:2}`.
|
|
17
|
+
|
|
18
|
+
## Edited payloads
|
|
19
|
+
|
|
20
|
+
`editable: true` + `editablePaths: ['amount', 'drafts[*].body']` (the `a.b[0].c` / `[*]` grammar) lets the approver patch the payload. The sequence is **fetch โ patch โ approve-with-fingerprint**: the approve call echoes the fingerprint of the revision the approver saw, so a concurrent edit forces a re-read. Out-of-grammar paths are refused; `editedPayloadSchema` validates the result.
|
|
21
|
+
|
|
22
|
+
## Where approvals surface
|
|
23
|
+
|
|
24
|
+
The desktop inbox and run detail carry the full card (per-item rows, edits, escalation state). **Text channels (WhatsApp/SMS/email) approve or deny the whole batch only** โ no per-item decisions, no edits.
|
|
25
|
+
|
|
26
|
+
Per-item approvals (`itemsPath` / `itemApprover` / `itemTimeout`) fan one node out to one decision per item โ see [Per-item approvals](./per-item-approvals.md).
|
|
27
|
+
|
|
28
|
+
Offline: `--approve <id>[=@payload]` / `--deny <id>[=@reason]` pre-answer the prompt; an edited payload is checked with the same `matchesEditablePath` + `editedPayloadSchema` the server uses.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Artefacts and datasets
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec (P1-8; Cluster K B40). This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
`ctx.artefacts.put(name, data, { contentType?, kind?, datasetSchema?, title?, source? })` stores a file on the run (โค 50 per step) and returns `{ artefactId }`; `get(id)` / `list()` read back. Steps pass **references**, not bytes.
|
|
6
|
+
|
|
7
|
+
## Datasets โ `{__datasetRef}`
|
|
8
|
+
|
|
9
|
+
An array-typed step output over **8 MB** becomes a `{__datasetRef}` (NDJSON on the CDN) instead of `OUTPUT_TOO_LARGE`. Bind pages with `rows(stepId, path, { offset, limit })` โ the bare ref renders as the ref object. `--input` values may carry `{"__artefactRef": "<id>"}` to hand a run an existing artefact.
|
|
10
|
+
|
|
11
|
+
## Streaming and datasets
|
|
12
|
+
|
|
13
|
+
`get(id).stream({ range })` reads large artefacts without buffering; `get(id).rows({ offset, limit })` pages NDJSON/parquet datasets (parquet row groups pass through untranscoded). Ceilings: 256 MB inline, 4 GiB streamed.
|
|
14
|
+
|
|
15
|
+
## Titles and sources
|
|
16
|
+
|
|
17
|
+
`title` and `source` metadata surface in the desktop artefact pane and in exports; `lua workflows artefact <runId> <artefactId>` fetches one from the CLI (presigned).
|
|
18
|
+
|
|
19
|
+
Offline: `--artefacts-dir <dir>` backs `ctx.artefacts.*` on disk (`<dir>/<artefactId>` + `<artefactId>.meta.json`, ids `local-<n>`); without it every call fails loudly (`ARTEFACTS_NOT_AVAILABLE_OFFLINE`) โ never a silent fake. Dataset-ref paging is engine-side.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Coding harness โ `claude-code` vs `generic`
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec 05 ยง5.17.6 (D27). This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
`harness:'claude-code'` runs Claude Code against Anthropic-class models; `harness:'generic'` runs Lua's own agent loop with the **same nine workspace tools** against any provider your org is allowed โ the tool ids, the budget, the secret scan and the turn limit are identical.
|
|
6
|
+
|
|
7
|
+
- Absent `harness`, the platform derives one from the step's model; the local driver prints the derived value so you see what the server will stamp.
|
|
8
|
+
- `LUA_WF_JOB_PROVIDERS` gates providers per org; an out-of-list model is `job-tier-provider-unsupported`.
|
|
9
|
+
- **Org BYOK keys go through the sidecar proxy โ your key never enters the agent container.**
|
|
10
|
+
- Billing rows carry `model` + `harness` (seat multiplier per provider).
|
|
11
|
+
|
|
12
|
+
Offline: `--agents live` with `harness:'generic'` runs the generic provider in-process against **your own** key from the environment (`OPENAI_API_KEY` / `GOOGLE_API_KEY` / `ANTHROPIC_API_KEY`) โ billing and governance are server-side only.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Compliance gates โ EXT-* features shipped dark
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec ยง15 gates. This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
Several enterprise surfaces are **specified and shipped dark; each flips on its own gate** โ the code is in the release, inert until the platform opens the gate for your org:
|
|
6
|
+
|
|
7
|
+
| Gate | Surface | Dark behaviour |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `EXT-REGION` | Region-pinned Job workspaces / data residency | `region-unavailable` at push |
|
|
10
|
+
| `EXT-KMS` | BYOK key-alias on workspaces + artefacts (B38) | alias refused at push |
|
|
11
|
+
| `EXT-AUDIT-API` | SIEM pull / `lua workflows audit-search` (B39, R72) | the verb answers **501** |
|
|
12
|
+
| `EXT-EFS` | `workspace.backend: 'efs' \| 's3'` | `workspace-backend-unavailable` (refused, not downgraded) |
|
|
13
|
+
| `EXT-GOVERNANCE` | Signed external governance review (`routeReview`) | policy verdicts stay platform-internal |
|
|
14
|
+
| `EXT-APPROVALS` / `EXT-SCIM` | External approval systems / SCIM approver sync | approver specs resolve org-locally |
|
|
15
|
+
|
|
16
|
+
Asking for a gate is an org-admin โ platform request; nothing in your workflow file changes when it opens.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Connections in coding turns
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec 05 ยง5.17.6 / 11 ยง11.5. This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
`toolScope.connectionIds` on a Job-tier agent step mounts MCP connections into the coding turn **through a local proxy**: the model calls `tools/list` / `tools/call`; the proxy holds the token โ the model never sees it.
|
|
6
|
+
|
|
7
|
+
- A tool that needs approval is **refused inside the turn** (`mcp_call_denied`) โ hand it to a worker-tier step where the approval card can park the run.
|
|
8
|
+
- Calls are capped per segment; the cap and usage appear in the step detail.
|
|
9
|
+
- Offline: connections are **not mounted** (no proxy, no token mint) โ `--mcp <connectionId>=@fixture.json` stubs `tools/list` / `tools/call` from a `{ tools:[โฆ], calls:{ [tool]: result } }` fixture; an unstubbed call returns the production `mcp_call_denied{reason:'not_in_scope'}` shape.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Correlation keys
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec (P1-3 / P1-14). This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
`correlationKey` stamps a run with YOUR business identity (`ticket-4711`, `order-โฆ`): pass it at `Workflows.start(..., { correlationKey })`, from a trigger's `correlationKeyTemplate`, or `lua workflows start --correlation-key`.
|
|
6
|
+
|
|
7
|
+
- `Workflows.signalByKey(nameOrId, correlationKey, name, payload?)` delivers a signal **by business key** โ no runId bookkeeping in your webhook; `allowMultiple` fans out when several runs share the key.
|
|
8
|
+
- `Workflows.list({ correlationKey })` / `lua workflows runs --correlation-key` find the run(s).
|
|
9
|
+
- `tags` are free-form labels (AND-ed in list filters); `replyTo: { channel, threadId }` routes the terminal reply back to the originating conversation.
|
|
10
|
+
|
|
11
|
+
Offline: `--correlation-key`, `--tag`, `--reply-to <channel>:<threadId>` and `--on-behalf-of` stamp `ctx.runtime.*`; the would-be reply prints on the terminal instead of sending.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Env overlays โ `env.template()` vs `env()`
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec (Cluster K B33, WF-543). This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
**`env.template('KEY')` = a graph literal resolved at push**, visible in `lua workflows env-overlay <name>` (a presence table โ values are never printed). **`env('KEY')` = a run-time secret read inside `execute`.** One file, per-env values: staging and prod resolve different overlays over the **same `graphHash`** (the hash covers placeholders only; `envOverlayHash` sits outside the consent fingerprint).
|
|
6
|
+
|
|
7
|
+
- A missing key at push is ERROR `env-template-missing` (exit 1; the version is never sent).
|
|
8
|
+
- Keys matching `/(SECRET|TOKEN|KEY|PASSWORD)$/` are refused at compile (`env-template-secret-key`) โ secrets belong in `env()`.
|
|
9
|
+
- Caps: โค 64 keys, values โค 4 KB (`invalid-envelope`).
|
|
10
|
+
- Installing a template re-resolves the overlay against the installing org's values.
|
|
11
|
+
|
|
12
|
+
Offline: `lua test workflow --env KEY=value` (repeatable; then the project's `.env`) โ a missing key is exit 2, and values never reach `--ledger-out`.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Evidence bundles and run exports
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec (Cluster E R53โR56 / D24). This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
`lua workflows export-run <runId> --out <dir>` writes one run's evidence bundle: the run doc, per-step rows (inputs/outputs/attempts), events, approvals with decision fingerprints, and artefact manifests. `export-runs --full --since โฆ --until โฆ` bulk-exports a window โ the DSAR and audit path (`archive-runs` adds zip-per-run + an `archive-index.ndjson`).
|
|
6
|
+
|
|
7
|
+
- Output visibility applies: restricted payloads export as `restricted: true` unless the caller's roles pass (owner bypass is audited).
|
|
8
|
+
- Very large originals are referenced, not inlined (a 413 `PAYLOAD_PAGE_REQUIRED` answer means: page the artefact endpoint).
|
|
9
|
+
- `--no-inputs` / `--no-artefacts` trim bundles for privacy-sensitive hand-offs.
|
|
10
|
+
|
|
11
|
+
See also [Exports](./exports.md) for policy-driven terminal exports.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Exports on terminal state
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec (Cluster K B45). This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
`workflowPolicy.export.onTerminal` (org policy) writes an evidence bundle for every terminal run to the configured destination โ the always-on sibling of the manual [evidence bundles](./evidence-bundles.md). `lua workflows exports` lists what was written (destination, run, status); failures surface in the org inbox, and the run itself is never blocked by an export failure.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# External content and `toolScope` โ the taint rule
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec (Cluster E, P1-16). This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
A step is **external-content tainted** when anything untrusted can reach its prompt: customer-channel input (`${initData.message}` on a customer-started run), `{knowledge}` bindings, or output flowing from a tool of the external kinds (`web-search`, `web-fetch`, `email-read`, `http`, `scrape`). Taint **propagates along bindings** โ a step consuming a tainted step's output is tainted too (`computeExternalContentTaint` walks the plan).
|
|
6
|
+
|
|
7
|
+
**A tainted `agentStep` must declare `toolScope`** โ `{}` means "no tools" (and `defaultToolScopeMode:'deny'` implies it when absent). The point: prompt-injected content must not be able to steer an agent that holds tools.
|
|
8
|
+
|
|
9
|
+
Walk-through โ `support-triage` (ยง3.2 (g)): `classify` renders the customer message AND a knowledge binding โ tainted โ `toolScope: {}`; the downstream `refundGate` approval routes to `org-admins` (never `'creator'` โ on a customer-channel run that is `approver-is-run-principal`).
|
|
10
|
+
|
|
11
|
+
Push refuses a tainted step without `toolScope` (`external-content-needs-toolscope`); the desktop run detail marks tainted steps with the provenance chain (`via`).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Git credentials in workflows
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec 11 ยง11.5.6 / 05 ยง5.17.3. This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
`workspace.credentialsRef` names a **git-host connection** (e.g. your org's GitHub App install). Per Job, the platform mints a **short-lived token held by a sidecar** โ git operations in the step go through the credential proxy; the token never enters the agent container and never appears in `env`.
|
|
6
|
+
|
|
7
|
+
> **Never put a PAT in `env`.** Rotation or revocation of the underlying connection makes the next mint fail: the step fails `credentials_revoked{git_token_mint_failed}` and โ with `onError:'park'` โ enters the park/`retry-step` loop, so a re-grant resumes the run without losing work.
|
|
8
|
+
|
|
9
|
+
- `jobTools:['gh']` is what mints `GH_TOKEN` for a code step (`pull_requests:write` + `contents:write` + `issues:read`, repo-scoped). Merge is a contents write โ human-only-merge orgs keep `contents:write` off the App.
|
|
10
|
+
- Templates never hardcode a connection id: they use `connections[].key`, resolved at install.
|
|
11
|
+
- Offline, `credentialsRef` is printed and **not** resolved (no token mint) โ `--credentials-ref-ok` suppresses the notice; the local driver uses your own git credentials.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Knowledge bindings
|
|
2
|
+
|
|
3
|
+
_Source of truth: workflows-spec (P1-11; Cluster K B41). This page is the developer summary; the spec is normative._
|
|
4
|
+
|
|
5
|
+
`fromKnowledge({ source, query, maxChars?, topK? })` as a map descriptor retrieves at render time (S2): each chunk arrives under a **provenance header** โ `[knowledge source=<source> doc=<doc> chunk=<n> score=<s>]` โ so the model can cite and the audit trail can trace. `maxChars` caps the rendered block; a retrieval timeout renders the EMPTY block plus a `knowledge: empty` warning (the run continues).
|
|
6
|
+
|
|
7
|
+
## Connection sources (B41)
|
|
8
|
+
|
|
9
|
+
`source:'connection'` with `connectionId` retrieves from Drive / Notion / Confluence through the org's connection. Requirements: the step must carry `toolScope` (connection knowledge is external content โ see [External content](./external-content-and-toolscope.md)); the compiler's overlay pass adds the knowledge connection to the step's mounted set.
|
|
10
|
+
|
|
11
|
+
Any knowledge binding taints the step (P1-16).
|
|
12
|
+
|
|
13
|
+
Offline: knowledge retrieval is not emulated โ a knowledge binding fails closed (`binding_unresolved`) unless you `--step-output` the consuming step. (`--knowledge <key>=@file` substitution is specified in 03 ยง3.9 step 7 and not yet wired in this build.)
|