@codemation/agent-skills 0.4.0 → 0.5.1
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/CHANGELOG.md +165 -0
- package/dist/metadata.json +358 -48
- package/package.json +3 -1
- package/skills/builder/ai-agent/SKILL.md +314 -0
- package/skills/builder/ai-agent/references/anti-patterns.md +24 -0
- package/skills/{codemation-cli → builder/cli}/SKILL.md +1 -8
- package/skills/builder/connect-external-systems/SKILL.md +191 -0
- package/skills/builder/credential-development/SKILL.md +86 -0
- package/skills/{codemation-credential-development → builder/credential-development}/references/credential-patterns.md +3 -3
- package/skills/builder/custom-node-development/SKILL.md +61 -0
- package/skills/builder/custom-node-development/references/credential-aware-nodes.md +52 -0
- package/skills/builder/custom-node-development/references/define-batch-node.md +54 -0
- package/skills/{codemation-custom-node-development → builder/custom-node-development}/references/define-node-per-item.md +14 -14
- package/skills/{codemation-custom-node-development → builder/custom-node-development}/references/node-patterns.md +33 -49
- package/skills/builder/document-ai/SKILL.md +167 -0
- package/skills/builder/execution-context/SKILL.md +436 -0
- package/skills/{codemation-framework-concepts → builder/framework-concepts}/SKILL.md +10 -18
- package/skills/builder/gmail/SKILL.md +327 -0
- package/skills/builder/human-in-the-loop/SKILL.md +82 -0
- package/skills/{codemation-mcp-capabilities → builder/mcp-capabilities}/SKILL.md +4 -11
- package/skills/{codemation-mcp-capabilities → builder/mcp-capabilities}/references/agent-with-mcp.ts +1 -1
- package/skills/builder/msgraph/SKILL.md +338 -0
- package/skills/builder/odoo/SKILL.md +498 -0
- package/skills/{codemation-plugin-development → builder/plugin-development}/SKILL.md +4 -7
- package/skills/{codemation-plugin-development → builder/plugin-development}/references/plugin-anatomy.md +36 -15
- package/skills/{codemation-plugin-development → builder/plugin-development}/references/plugin-structure.md +2 -2
- package/skills/builder/rest-node/SKILL.md +148 -0
- package/skills/builder/testing/SKILL.md +142 -0
- package/skills/builder/workflow-dsl/SKILL.md +493 -0
- package/skills/builder/workspace-files/SKILL.md +191 -0
- package/skills/concierge/credentials/SKILL.md +91 -0
- package/skills/concierge/intake-automation-playbook/SKILL.md +78 -0
- package/skills/concierge/scenario-invoice-to-accounting/SKILL.md +48 -0
- package/skills/concierge/scenario-procurement-intake/SKILL.md +58 -0
- package/skills/codemation-ai-agent-node/SKILL.md +0 -66
- package/skills/codemation-ai-agent-node/references/anti-patterns.md +0 -11
- package/skills/codemation-credential-development/SKILL.md +0 -57
- package/skills/codemation-custom-node-development/SKILL.md +0 -61
- package/skills/codemation-custom-node-development/references/credential-aware-nodes.md +0 -38
- package/skills/codemation-custom-node-development/references/define-batch-node.md +0 -38
- package/skills/codemation-document-scanner/SKILL.md +0 -136
- package/skills/codemation-workflow-dsl/SKILL.md +0 -78
- package/skills/codemation-workflow-dsl/references/builder-patterns.md +0 -120
- package/skills/codemation-workflow-dsl/references/complete-example.md +0 -263
- package/skills/codemation-workflow-dsl/references/workflow-testing.md +0 -194
- package/skills/codemation-workspace-files/SKILL.md +0 -142
- /package/skills/{codemation-cli → builder/cli}/references/command-map.md +0 -0
- /package/skills/{codemation-framework-concepts → builder/framework-concepts}/references/architecture-map.md +0 -0
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: codemation-custom-node-development
|
|
3
|
-
description: Guides Codemation custom node development with `defineNode(...)` (`execute` per item), `defineBatchNode(...)` (batch `run`), reusable node modules, credential-aware nodes, and the class-based node fallback for advanced cases. Use when creating or updating custom nodes for apps or plugin packages.
|
|
4
|
-
compatibility: Designed for Codemation apps and plugin packages that define reusable nodes.
|
|
5
|
-
tags: node, custom, plugin
|
|
6
|
-
uses: "@codemation/core"
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Codemation Custom Node Development
|
|
10
|
-
|
|
11
|
-
## Mental model
|
|
12
|
-
|
|
13
|
-
Custom nodes are the extension point for reusable business logic that doesn't belong inline in a workflow callback. `defineNode(...)` wraps a per-item `execute` function with a typed contract (input schema, credential slots, output shape); the engine calls it once per item. `defineBatchNode(...)` is the batch variant for logic that must see all items at once. Nodes compose into workflows via config class instances — the node definition is separate from the config class used to wire it into a workflow.
|
|
14
|
-
|
|
15
|
-
## Use this skill when
|
|
16
|
-
|
|
17
|
-
Use this skill for reusable custom node work, whether the node lives inside an app or a published plugin package.
|
|
18
|
-
|
|
19
|
-
Do not use this skill for pure workflow chaining questions unless the node implementation itself is changing.
|
|
20
|
-
|
|
21
|
-
## Per-item vs batch
|
|
22
|
-
|
|
23
|
-
**`defineNode(...)` (per-item)** — the engine calls `execute(args, context)` once per item. This is the right default for the vast majority of nodes: straightforward logic, credential slots, input schema, optional fan-out.
|
|
24
|
-
|
|
25
|
-
**`defineBatchNode(...)` (batch)** — the engine calls `run(items, context)` with the full activation batch. Use only when the node genuinely needs to see all items at once (aggregation, bulk API calls, cross-item correlation).
|
|
26
|
-
|
|
27
|
-
When in doubt, start with `defineNode`.
|
|
28
|
-
|
|
29
|
-
## Node rules
|
|
30
|
-
|
|
31
|
-
1. Keep nodes deterministic and focused.
|
|
32
|
-
2. Request credentials through named slots — never hard-code secrets.
|
|
33
|
-
3. Put **static** options (credentials, retry policy, labels) on **config**; put **per-item** behavior in **inputs** / wire JSON and optional `itemExpr` on config fields.
|
|
34
|
-
4. **Emit files with `ctx.binary`, not base64 in `json`** — base64 in `item.json` bloats persisted run data. See `references/node-patterns.md`.
|
|
35
|
-
5. Drop to class-based node APIs only when you need constructor-injected collaborators, decorators, or deeper runtime metadata.
|
|
36
|
-
|
|
37
|
-
## Minimal `defineNode` example
|
|
38
|
-
|
|
39
|
-
```ts
|
|
40
|
-
import { defineNode } from "@codemation/core";
|
|
41
|
-
import { z } from "zod";
|
|
42
|
-
|
|
43
|
-
export const uppercaseNode = defineNode({
|
|
44
|
-
key: "example.uppercase",
|
|
45
|
-
title: "Uppercase field",
|
|
46
|
-
icon: "lucide:languages",
|
|
47
|
-
inputSchema: z.object({ field: z.string() }),
|
|
48
|
-
async execute({ input }) {
|
|
49
|
-
return { ...input, field: input.field.toUpperCase() };
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
For full patterns — credential-slotted nodes, batch nodes, fan-out, binary payloads, and test kit usage — use your harness's example-discovery tool: `find_examples({ query: "defineNode" })` or `find_examples({ query: "defineBatchNode" })`.
|
|
55
|
-
|
|
56
|
-
## Read next
|
|
57
|
-
|
|
58
|
-
- `references/define-node-per-item.md` — full `defineNode(...)` contract, `inputSchema`, `itemExpr`, fan-out, assertion nodes, and `WorkflowTestKit` usage. Load this when writing or debugging a per-item node.
|
|
59
|
-
- `references/define-batch-node.md` — `defineBatchNode(...)` contract and when to choose batch over per-item. Load this when the node must see the entire batch at once.
|
|
60
|
-
- `references/credential-aware-nodes.md` — credential slots, typed sessions, and how to test credential-aware nodes. Load this when your node needs a credential.
|
|
61
|
-
- `references/node-patterns.md` — binary payloads (`ctx.binary`, `attach`, `withAttachment`), fan-out return shapes, polling-trigger binary patterns, MS Graph attachment download, and HTTP binary round-trips. Load this when working with file data or HTTP binaries.
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Credential-Aware Nodes
|
|
2
|
-
|
|
3
|
-
Load this when your node needs a typed credential (OAuth token, API key, or any `defineCredential(...)` type) injected at runtime.
|
|
4
|
-
|
|
5
|
-
## Core rule
|
|
6
|
-
|
|
7
|
-
Request credentials through **named slots** on the node config instead of hard-coding secrets. The framework resolves the slot to a live typed session at execution time.
|
|
8
|
-
|
|
9
|
-
## Adding a credential slot to `defineNode`
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
import { defineNode } from "@codemation/core";
|
|
13
|
-
import { myApiCredentialType } from "./myApiCredential.js";
|
|
14
|
-
|
|
15
|
-
export const callApiNode = defineNode({
|
|
16
|
-
key: "example.call-api",
|
|
17
|
-
title: "Call My API",
|
|
18
|
-
credentials: {
|
|
19
|
-
api: myApiCredentialType, // slot name → credential type
|
|
20
|
-
},
|
|
21
|
-
async execute({ input }, { credentials }) {
|
|
22
|
-
const session = await credentials.api.getSession();
|
|
23
|
-
// session is typed by myApiCredentialType.sessionSchema
|
|
24
|
-
const response = await fetch("https://api.example.com/data", {
|
|
25
|
-
headers: { Authorization: `Bearer ${session.accessToken}` },
|
|
26
|
-
});
|
|
27
|
-
return response.json();
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Typed sessions
|
|
33
|
-
|
|
34
|
-
`credentials.<slot>.getSession()` returns the shape declared in the credential type's `sessionSchema`. The framework handles refresh, storage, and error propagation — your node only consumes the session.
|
|
35
|
-
|
|
36
|
-
## Testing credential-aware nodes
|
|
37
|
-
|
|
38
|
-
Supply a mock credential in `WorkflowTestKit` rather than live credentials. See `codemation-credential-development` for the full `defineCredential(...)` story, typed sessions, and credential testing patterns.
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Define Batch Node
|
|
2
|
-
|
|
3
|
-
Load this when you need to author a `defineBatchNode(...)` node that processes all items in one call.
|
|
4
|
-
|
|
5
|
-
## When to use `defineBatchNode` instead of `defineNode`
|
|
6
|
-
|
|
7
|
-
- The node must see the **entire activation batch** at once (e.g. an aggregation, a bulk API call, or a node that correlates items against each other).
|
|
8
|
-
- Legacy batch semantics are required by the calling workflow.
|
|
9
|
-
- You need the same contract as built-in batch-shaped nodes such as `Aggregate`.
|
|
10
|
-
|
|
11
|
-
For the common case (one-item-at-a-time logic), prefer `defineNode` — the engine handles iteration for you.
|
|
12
|
-
|
|
13
|
-
## Minimal skeleton
|
|
14
|
-
|
|
15
|
-
```ts
|
|
16
|
-
import { defineBatchNode } from "@codemation/core";
|
|
17
|
-
import { z } from "zod";
|
|
18
|
-
|
|
19
|
-
export const sumNode = defineBatchNode({
|
|
20
|
-
key: "example.sum",
|
|
21
|
-
title: "Sum numeric field",
|
|
22
|
-
inputSchema: z.object({ value: z.number() }),
|
|
23
|
-
async run(items, { config }) {
|
|
24
|
-
const total = items.reduce((acc, item) => acc + (item.json as { value: number }).value, 0);
|
|
25
|
-
return [{ json: { total } }];
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Contract
|
|
31
|
-
|
|
32
|
-
- `run(items, context)` receives the **full array** of activation items.
|
|
33
|
-
- Return an array of output items (same length as input is not required — you can fan-in to one, or fan-out to many).
|
|
34
|
-
- The context object exposes `config`, `credentials`, and `execution` (same as `defineNode`).
|
|
35
|
-
|
|
36
|
-
## Advanced fallback
|
|
37
|
-
|
|
38
|
-
Reach for class-based node APIs when constructor-injected collaborators are required, plugin packaging needs the lower-level runtime contract, or decorators/persisted metadata need tighter control.
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: codemation-document-scanner
|
|
3
|
-
description: CodemationDocumentScanner node — managed document/invoice/image extraction via the Codemation doc-scanner service. No Azure credentials required. Read before writing any workflow that scans documents, invoices, or images.
|
|
4
|
-
compatibility: Codemation core-nodes. Requires @codemation/core-nodes import.
|
|
5
|
-
tags: ocr, document, invoice, image, scan, extract, managed, confidence
|
|
6
|
-
uses: "@codemation/core-nodes"
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Codemation Document Scanner Node
|
|
10
|
-
|
|
11
|
-
> **Start here: call `find_examples` before reading further.**
|
|
12
|
-
>
|
|
13
|
-
> - `find_examples({ query: "CodemationDocumentScanner" })` — node-level usage and all analyzerType variants
|
|
14
|
-
> - `find_examples({ query: "invoice scan post accounting" })` — end-to-end invoice extraction scenario
|
|
15
|
-
> - `find_examples({ query: "document scanner confidence fields" })` — how to enable per-field confidence scores
|
|
16
|
-
|
|
17
|
-
## Use this skill when
|
|
18
|
-
|
|
19
|
-
Writing a workflow that extracts text and/or structured fields from documents, invoices, or images
|
|
20
|
-
using the Codemation managed scanning service. No Azure credentials are required — the service is
|
|
21
|
-
pre-wired to the platform.
|
|
22
|
-
|
|
23
|
-
Use `codemation-workflow-dsl` for surrounding workflow structure.
|
|
24
|
-
Use `codemation-ai-agent-node` if you need to pass the extracted markdown to an LLM for further processing.
|
|
25
|
-
|
|
26
|
-
## When to use CodemationDocumentScanner vs the standalone OCR nodes
|
|
27
|
-
|
|
28
|
-
| Situation | Use |
|
|
29
|
-
| ------------------------------------------------ | --------------------------------------------------------------------------------------------------- |
|
|
30
|
-
| Managed platform deployment, no Azure credential | `codemationDocumentScannerNode` (this skill) |
|
|
31
|
-
| Self-hosted / BYOK Azure Content Understanding | `analyzeDocumentNode` / `analyzeInvoiceNode` / `analyzeImageNode` from `@codemation/core-nodes-ocr` |
|
|
32
|
-
|
|
33
|
-
`codemationDocumentScannerNode` calls the internal `doc-scanner` service via HMAC — the workspace holds
|
|
34
|
-
no Azure key. The standalone OCR nodes call Azure directly using a per-workspace credential.
|
|
35
|
-
|
|
36
|
-
## Choosing `analyzerType`
|
|
37
|
-
|
|
38
|
-
| `analyzerType` | When to use | Azure analyzer | Field extraction | Confidence opt-in supported |
|
|
39
|
-
| -------------- | ----------------------------------------------- | ----------------------------------------------------------------------- | ---------------------- | --------------------------------------- |
|
|
40
|
-
| `"document"` | General PDFs, Word docs, HTML, text-heavy files | `prebuilt-document` | Yes | Yes |
|
|
41
|
-
| `"invoice"` | Invoices, receipts — always prebuilt-invoice | `prebuilt-invoice` | Yes | Yes |
|
|
42
|
-
| `"image"` | Photos, screenshots, diagrams | `prebuilt-imageAnalyzer` | No (markdown only) | No — image carries no extraction charge |
|
|
43
|
-
| `"auto"` | Unknown mime type at author time | Routes on `Content-Type`: `image/*` → image, everything else → document | Depends on routed type | Depends on routed type |
|
|
44
|
-
|
|
45
|
-
**Default is `"auto"`.** Set an explicit type whenever you know the content class — it avoids
|
|
46
|
-
unnecessary re-routing and makes the workflow self-documenting.
|
|
47
|
-
|
|
48
|
-
## Output shape
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
{
|
|
52
|
-
markdown: string; // full text content
|
|
53
|
-
fields: Record<
|
|
54
|
-
string,
|
|
55
|
-
{
|
|
56
|
-
value: unknown; // extracted scalar, date ISO string, nested object, or array
|
|
57
|
-
confidence: number | null; // 0–1 when includeConfidence:true; null otherwise
|
|
58
|
-
}
|
|
59
|
-
>;
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
`item.json.markdown` is the Markdown rendering of the document.
|
|
64
|
-
`item.json.fields` is a flat-or-nested map of structured fields found by the analyzer.
|
|
65
|
-
For `analyzerType: "image"`, `fields` is always `{}`.
|
|
66
|
-
Fields may be sparse or absent for generic documents — extraction is best-effort.
|
|
67
|
-
|
|
68
|
-
## WARNING: How to enable per-field confidence scores (LD6)
|
|
69
|
-
|
|
70
|
-
**By default, `confidence` is `null` on every field.** This keeps token cost low for the majority
|
|
71
|
-
of workflows that only need `value`.
|
|
72
|
-
|
|
73
|
-
To get a populated `confidence` (0–1 float) on each field, set `includeConfidence: true`:
|
|
74
|
-
|
|
75
|
-
```ts
|
|
76
|
-
codemationDocumentScannerNode.create(
|
|
77
|
-
{
|
|
78
|
-
binaryField: "data",
|
|
79
|
-
analyzerType: "invoice",
|
|
80
|
-
includeConfidence: true, // ← opt-in: fields carry confidence 0–1
|
|
81
|
-
},
|
|
82
|
-
"Scan invoice",
|
|
83
|
-
"scan-invoice",
|
|
84
|
-
);
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
**Cost implication:** enabling confidence routes the request to a confidence-enabled analyzer variant,
|
|
88
|
-
which roughly doubles the contextualization token count for document/invoice analyzers.
|
|
89
|
-
Only enable it when your downstream logic actually reads `field.confidence`.
|
|
90
|
-
|
|
91
|
-
Images (`analyzerType: "image"`) and auto-routed-to-image requests carry no field-extraction charge
|
|
92
|
-
regardless of this flag — they silently ignore `includeConfidence` (confidence stays `null`, never a 400).
|
|
93
|
-
|
|
94
|
-
## API usage
|
|
95
|
-
|
|
96
|
-
```ts
|
|
97
|
-
import { codemationDocumentScannerNode } from "@codemation/core-nodes";
|
|
98
|
-
|
|
99
|
-
codemationDocumentScannerNode.create(
|
|
100
|
-
{
|
|
101
|
-
binaryField?: string; // key on item.binary — default "data"
|
|
102
|
-
analyzerType?: "document" | "invoice" | "image" | "auto"; // default "auto"
|
|
103
|
-
contentType?: string; // MIME type override — falls back to attachment.mimeType
|
|
104
|
-
includeConfidence?: boolean; // default false — see cost note above
|
|
105
|
-
maxBytes?: number; // size cap before reading; default 50 MiB (LD10)
|
|
106
|
-
},
|
|
107
|
-
label?: string, // node label on the canvas
|
|
108
|
-
nodeId?: string, // explicit stable id — set when output is used downstream
|
|
109
|
-
)
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Set an explicit `nodeId` whenever downstream nodes reference this node's output by id, or when
|
|
113
|
-
the node may be renamed later (avoids credential-binding orphaning).
|
|
114
|
-
|
|
115
|
-
## Consuming fields downstream
|
|
116
|
-
|
|
117
|
-
```ts
|
|
118
|
-
import type { DocScannerOutput, DocScannerField } from "@codemation/core-nodes";
|
|
119
|
-
|
|
120
|
-
// item.json after codemationDocumentScannerNode:
|
|
121
|
-
// DocScannerOutput = { markdown: string; fields: Record<string, DocScannerField> }
|
|
122
|
-
// DocScannerField = { value: unknown; confidence: number | null }
|
|
123
|
-
|
|
124
|
-
new Callback<DocScannerOutput>("Use fields", (items, _ctx) =>
|
|
125
|
-
items.map((item) => {
|
|
126
|
-
const vendorName = item.json.fields["VendorName"]?.value as string | undefined;
|
|
127
|
-
const vendorConf = item.json.fields["VendorName"]?.confidence; // null unless includeConfidence:true
|
|
128
|
-
return { ...item, json: { ...item.json, vendorName, vendorConf } };
|
|
129
|
-
}),
|
|
130
|
-
);
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
## Read next when needed
|
|
134
|
-
|
|
135
|
-
- `codemation-workflow-dsl` — workflow builder, trigger types, fluent vs low-level API.
|
|
136
|
-
- `codemation-ai-agent-node` — pass `item.json.markdown` to an LLM for summarisation or extraction.
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: codemation-workflow-dsl
|
|
3
|
-
description: Guides Codemation workflow authoring. Use when creating or updating workflow definitions in `src/workflows` — manual-trigger flows via `workflow("...").manualTrigger(...)`, or cron/webhook/other triggers via `createWorkflowBuilder({id, name}).trigger(...)`.
|
|
4
|
-
compatibility: Designed for Codemation apps and plugins that author workflows.
|
|
5
|
-
tags: workflow, dsl, authoring
|
|
6
|
-
uses: "@codemation/core-nodes, @codemation/host"
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Codemation Workflow DSL
|
|
10
|
-
|
|
11
|
-
## Mental model
|
|
12
|
-
|
|
13
|
-
A workflow definition describes how items move from a trigger through downstream node steps. Items carry data in `item.json`; earlier outputs are available through `ctx.data`. Activations are batch-shaped but most node steps execute per-item. Every workflow definition finishes with `.build()`, which validates node ids and emits a `WorkflowDefinitionError` on collision or empty id.
|
|
14
|
-
|
|
15
|
-
## When to use / when NOT
|
|
16
|
-
|
|
17
|
-
Use this skill when authoring or reviewing workflow definitions under `src/workflows/`.
|
|
18
|
-
Do not use for CLI-only troubleshooting or deep host architecture questions unless they directly affect workflow authoring.
|
|
19
|
-
|
|
20
|
-
## Quickstart — pick API by trigger type
|
|
21
|
-
|
|
22
|
-
```ts
|
|
23
|
-
// Manual trigger — full fluent sugar (.map, .if, .switch, .agent, .node, .then)
|
|
24
|
-
import { workflow } from "@codemation/host";
|
|
25
|
-
export default workflow("wf.example")
|
|
26
|
-
.manualTrigger("Start", {
|
|
27
|
-
/* seed items */
|
|
28
|
-
})
|
|
29
|
-
.map(/* ... */)
|
|
30
|
-
.build();
|
|
31
|
-
|
|
32
|
-
// Cron / webhook / any other trigger — low-level .then(new NodeConfig(...)) only
|
|
33
|
-
import { createWorkflowBuilder, CronTrigger } from "@codemation/core-nodes";
|
|
34
|
-
export default createWorkflowBuilder({ id: "wf.example", name: "Example" })
|
|
35
|
-
.trigger(new CronTrigger("Daily", { schedule: "0 9 * * *", timezone: "UTC" }))
|
|
36
|
-
.then(/* new SomeNodeConfig(...) */)
|
|
37
|
-
.build();
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
For full patterns — multi-step pipelines, branching, SubWorkflow, binary, agent tools, TestTrigger, and complete working examples — use your harness's example-discovery tool: `find_examples({ query: "..." })`. Useful queries: `"CronTrigger"`, `"if branch"`, `"AIAgent multi-step"`, `"SubWorkflow binary"`, `"TestTrigger assertion"`.
|
|
41
|
-
|
|
42
|
-
## Decision branches & gotchas
|
|
43
|
-
|
|
44
|
-
**Two authoring APIs — pick by trigger type.** `workflow("id").manualTrigger(...)` returns a `WorkflowChain` with full fluent helpers (`.map`, `.if`, `.switch`, `.split`, `.agent`, `.node`). `createWorkflowBuilder({id, name}).trigger(new XxxTrigger(...))` returns a `ChainCursor` whose only chain method is `.then(new NodeConfig(...))`. Do NOT call `.trigger(...)` on the `workflow(...)` builder — it doesn't exist there.
|
|
45
|
-
|
|
46
|
-
**Node ids and stability.** When no explicit `id:` is given, the engine slugifies the node's `name` label (lowercase, non-alphanumeric → `-`). `"Send Email"` → `"send-email"`. Nodes sharing credential bindings use `(workflowId, nodeId, slotKey)` as the binding key — renaming a label orphans the binding. **Set explicit `id:` on every credential-using node.** `.build()` throws `WorkflowDefinitionError` on empty or duplicate ids.
|
|
47
|
-
|
|
48
|
-
**Id collision pitfall.** A manual-trigger label and a downstream agent label that share the same string both slugify to the same id — `.build()` throws. Fix: add `id: "...-agent"` to disambiguate.
|
|
49
|
-
|
|
50
|
-
**Collection nodes** use `.then(node.create(...))` instead of `.node(label, node, opts)` — TypeScript can't infer the `ParamDeep` constraint via the fluent helper. See `find_examples({ query: "collection crud" })`.
|
|
51
|
-
|
|
52
|
-
**Install state in example results.** Every `find_examples` result includes `installed: boolean` and `requiresInstall: string[]`. If `installed` is `false` or `requiresInstall` is non-empty, call `install_package` for each missing package before writing any workflow code that imports them.
|
|
53
|
-
|
|
54
|
-
**When no example matches — self-solving fallback chain.**
|
|
55
|
-
|
|
56
|
-
1. Retry with intent variations (different verb, more generic term).
|
|
57
|
-
2. For HTTP APIs: `find_examples({ query: "defineRestNode" })` — covers basic and credential-slotted REST.
|
|
58
|
-
3. For one-shot inline HTTP: `find_examples({ query: "HttpRequest" })`.
|
|
59
|
-
4. For non-HTTP custom logic: `find_examples({ query: "defineNode template" })`.
|
|
60
|
-
Do NOT ask the user to pick between primitives — they can't help; use the chain. Do NOT grep `node_modules/@codemation/*` for node implementations — examples are authoritative. Surface the technique used in your reply.
|
|
61
|
-
|
|
62
|
-
**Workflow testing.** Three built-in nodes from `@codemation/core-nodes`: `TestTrigger` (yields one item per test case), `IsTestRun` (routes `true`/`false` by `ctx.testContext`), `Assertion` (emits `AssertionResult[]`, sets `emitsAssertions: true`). See `references/workflow-testing.md` for authoring details.
|
|
63
|
-
|
|
64
|
-
**SubWorkflow binary.** `item.binary` slots pass transparently through SubWorkflow boundaries in both directions — no special config needed. Both runs share the same `BinaryStorage` singleton.
|
|
65
|
-
|
|
66
|
-
**Verify your workflow.** Call `verify_workflow({ path: "src/workflows/my-workflow.ts" })` instead of running `pnpm typecheck` yourself. Returns `{ ok, data: { typecheck, lint, build, structure }, hint? }`.
|
|
67
|
-
|
|
68
|
-
## Anti-patterns
|
|
69
|
-
|
|
70
|
-
- Do not call `.trigger(...)` on the `workflow(...)` manual builder — use `createWorkflowBuilder(...)` for non-manual triggers.
|
|
71
|
-
- Do not rely on slug-derived node ids for production workflows with credential bindings — always set an explicit `id:`.
|
|
72
|
-
- Do not improvise from memory when `find_examples` returns zero hits — use the fallback chain above.
|
|
73
|
-
|
|
74
|
-
## Read next when needed
|
|
75
|
-
|
|
76
|
-
- `references/builder-patterns.md` — item-flow rules and fluent authoring patterns.
|
|
77
|
-
- `references/workflow-testing.md` — TestTrigger / IsTestRun / Assertion with full examples.
|
|
78
|
-
- `references/complete-example.md` — dense end-to-end example covering most authoring features.
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
Load this when you need item-flow rules, the two-API decision, and fluent authoring patterns.
|
|
2
|
-
|
|
3
|
-
# Builder Patterns
|
|
4
|
-
|
|
5
|
-
## Manual-trigger workflow (fluent — full sugar available)
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
import { workflow } from "@codemation/host";
|
|
9
|
-
|
|
10
|
-
export default workflow("wf.example.id")
|
|
11
|
-
.name("Example")
|
|
12
|
-
.manualTrigger("Start", { step: "start" })
|
|
13
|
-
.map("Transform", (item, _ctx) => ({
|
|
14
|
-
...item.json,
|
|
15
|
-
transformed: true,
|
|
16
|
-
}))
|
|
17
|
-
.build();
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
The `.map`, `.if`, `.switch`, `.split`, `.agent`, `.node`, `.then` helpers are available because `manualTrigger(...)` returns a `WorkflowChain`.
|
|
21
|
-
|
|
22
|
-
## Cron-triggered workflow (low-level — `.then(new NodeConfig(...))` only)
|
|
23
|
-
|
|
24
|
-
```ts
|
|
25
|
-
import { Callback, CronTrigger, createWorkflowBuilder } from "@codemation/core-nodes";
|
|
26
|
-
|
|
27
|
-
export default createWorkflowBuilder({
|
|
28
|
-
id: "wf.nightly.id",
|
|
29
|
-
name: "Nightly job",
|
|
30
|
-
})
|
|
31
|
-
.trigger(new CronTrigger("Nightly", { schedule: "0 3 * * *", timezone: "Europe/Amsterdam" }))
|
|
32
|
-
.then(
|
|
33
|
-
new Callback("Process tick", (items, _ctx) => {
|
|
34
|
-
// Callback receives the whole batch (Items), not a single item.
|
|
35
|
-
// For a cron trigger the batch is always one item: { firedAt, scheduledFor }.
|
|
36
|
-
return items.map((item) => ({ firedAt: (item.json as { firedAt: string }).firedAt }));
|
|
37
|
-
}),
|
|
38
|
-
)
|
|
39
|
-
.build();
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
The cron expression is validated at workflow build time. Each tick emits one item with `{ firedAt, scheduledFor }` ISO-8601 strings. Always supply `timezone` for DST-sensitive schedules — defaults to UTC.
|
|
43
|
-
|
|
44
|
-
**Note:** non-manual triggers do NOT give you `.map(...)` / `.if(...)` / `.agent(...)` sugar. Compose with `.then(new Callback(...))`, `.then(new If(...))`, `.then(new AIAgent({...}))`, etc.
|
|
45
|
-
|
|
46
|
-
## Webhook-triggered workflow
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
import { WebhookTrigger, createWorkflowBuilder, Callback } from "@codemation/core-nodes";
|
|
50
|
-
|
|
51
|
-
export default createWorkflowBuilder({
|
|
52
|
-
id: "wf.webhook.example",
|
|
53
|
-
name: "Webhook example",
|
|
54
|
-
})
|
|
55
|
-
.trigger(new WebhookTrigger("Incoming", { endpointKey: "inbound", methods: ["POST"] }))
|
|
56
|
-
.then(new Callback("Handle payload", (items) => items.map((it) => ({ received: it.json }))))
|
|
57
|
-
.build();
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Decision rule
|
|
61
|
-
|
|
62
|
-
- **Manual one-shot trigger?** Use `workflow("id").manualTrigger(...)` — short, fluent, full sugar.
|
|
63
|
-
- **Anything else?** Use `createWorkflowBuilder({ id, name }).trigger(new Trigger(...))` — verbose, node-config style.
|
|
64
|
-
|
|
65
|
-
## Imports cheat sheet
|
|
66
|
-
|
|
67
|
-
- `workflow` → `@codemation/host` (re-exports from `@codemation/core-nodes`)
|
|
68
|
-
- `createWorkflowBuilder`, `CronTrigger`, `WebhookTrigger`, `Callback`, `HttpRequest`, `AIAgent`, `If`, `Split`, `Merge`, `SubWorkflow` → `@codemation/core-nodes`
|
|
69
|
-
- `callableTool`, `itemExpr` → `@codemation/core`
|
|
70
|
-
- Workflow file location: `src/workflows/`. Export the built definition as the default export.
|
|
71
|
-
|
|
72
|
-
## Item rules
|
|
73
|
-
|
|
74
|
-
- workflow data flows as items
|
|
75
|
-
- items usually carry `json` data and optional `binary` data (**storage-backed attachments** via node **`ctx.binary.attach`**, not huge base64 strings in **`json`** — base64 in **`json`** inflates the persisted run payload in the DB; binaries stay as **references**)
|
|
76
|
-
- runtime nodes receive batches of items, not just one record
|
|
77
|
-
- author workflow steps with batching in mind
|
|
78
|
-
- fluent `.map(...)`, `.if(...)`, and `.switch({ resolveCaseKey })` callbacks receive `(item, ctx)`
|
|
79
|
-
- read row fields from `item.json` and earlier completed outputs from `ctx.data`
|
|
80
|
-
|
|
81
|
-
## Node id assignment
|
|
82
|
-
|
|
83
|
-
When no `id:` is provided, the builder slugifies the node's `name` label: lowercase, non-alphanumeric runs replaced with `-`, leading/trailing `-` stripped. Two nodes with the same effective label produce the same slug and `.build()` throws `WorkflowDefinitionError`. Fix: provide a unique `id:` on the colliding node configs.
|
|
84
|
-
|
|
85
|
-
Credential bindings are stored as `(workflowId, nodeId, slotKey)`. Changing a node's label changes its slug-derived id and the binding appears unbound. For credential-using nodes, either keep the label stable or set an explicit `id:`:
|
|
86
|
-
|
|
87
|
-
```ts
|
|
88
|
-
.node("Send email", SendEmailNodeConfig, {
|
|
89
|
-
id: "send-email", // stable even after a label rename
|
|
90
|
-
credentials: { smtp: mySmtpCredential },
|
|
91
|
-
})
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## When to move beyond callbacks
|
|
95
|
-
|
|
96
|
-
Promote inline callbacks into custom nodes when:
|
|
97
|
-
|
|
98
|
-
- the logic is reused across workflows
|
|
99
|
-
- the workflow graph needs clearer names
|
|
100
|
-
- credentials or collaborators need explicit boundaries
|
|
101
|
-
- the callback has become hard to test in isolation
|
|
102
|
-
|
|
103
|
-
## Relationship to the engine
|
|
104
|
-
|
|
105
|
-
- the fluent DSL is the friendly authoring surface
|
|
106
|
-
- `@codemation/core` still owns planning, execution, continuation, and runtime contracts
|
|
107
|
-
- host and node packages add the surrounding product capabilities
|
|
108
|
-
|
|
109
|
-
## Inline callable agent tools
|
|
110
|
-
|
|
111
|
-
- import `callableTool` from `@codemation/core`
|
|
112
|
-
- build tools with `callableTool({ name, inputSchema, outputSchema, execute, credentialRequirements? })` (equivalent to `CallableToolFactory.callableTool(...)`)
|
|
113
|
-
- pass the result in `AIAgent` `tools: [...]` alongside other tool configs
|
|
114
|
-
|
|
115
|
-
## Fluent agent steps
|
|
116
|
-
|
|
117
|
-
- use `.agent(...)` for agent steps in fluent workflow definitions
|
|
118
|
-
- define agent prompts with `messages`
|
|
119
|
-
- use `itemExpr(...)` when message content depends on `item.json`
|
|
120
|
-
- use `outputSchema` when the workflow should expose typed structured agent output
|