@codemation/agent-skills 0.4.0 → 0.5.2

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/dist/metadata.json +358 -48
  3. package/package.json +3 -1
  4. package/skills/builder/ai-agent/SKILL.md +314 -0
  5. package/skills/builder/ai-agent/references/anti-patterns.md +24 -0
  6. package/skills/{codemation-cli → builder/cli}/SKILL.md +1 -8
  7. package/skills/builder/connect-external-systems/SKILL.md +191 -0
  8. package/skills/builder/credential-development/SKILL.md +86 -0
  9. package/skills/{codemation-credential-development → builder/credential-development}/references/credential-patterns.md +3 -3
  10. package/skills/builder/custom-node-development/SKILL.md +61 -0
  11. package/skills/builder/custom-node-development/references/credential-aware-nodes.md +52 -0
  12. package/skills/builder/custom-node-development/references/define-batch-node.md +54 -0
  13. package/skills/{codemation-custom-node-development → builder/custom-node-development}/references/define-node-per-item.md +14 -14
  14. package/skills/{codemation-custom-node-development → builder/custom-node-development}/references/node-patterns.md +33 -49
  15. package/skills/builder/document-ai/SKILL.md +167 -0
  16. package/skills/builder/execution-context/SKILL.md +436 -0
  17. package/skills/{codemation-framework-concepts → builder/framework-concepts}/SKILL.md +18 -18
  18. package/skills/builder/gmail/SKILL.md +327 -0
  19. package/skills/builder/human-in-the-loop/SKILL.md +82 -0
  20. package/skills/{codemation-mcp-capabilities → builder/mcp-capabilities}/SKILL.md +5 -12
  21. package/skills/builder/mcp-capabilities/references/agent-with-mcp.ts +24 -0
  22. package/skills/builder/msgraph/SKILL.md +338 -0
  23. package/skills/builder/odoo/SKILL.md +498 -0
  24. package/skills/{codemation-plugin-development → builder/plugin-development}/SKILL.md +4 -7
  25. package/skills/{codemation-plugin-development → builder/plugin-development}/references/plugin-anatomy.md +36 -15
  26. package/skills/{codemation-plugin-development → builder/plugin-development}/references/plugin-structure.md +2 -2
  27. package/skills/builder/rest-node/SKILL.md +148 -0
  28. package/skills/builder/testing/SKILL.md +142 -0
  29. package/skills/builder/workflow-dsl/SKILL.md +492 -0
  30. package/skills/builder/workspace-files/SKILL.md +191 -0
  31. package/skills/concierge/credentials/SKILL.md +91 -0
  32. package/skills/concierge/intake-automation-playbook/SKILL.md +78 -0
  33. package/skills/concierge/scenario-invoice-to-accounting/SKILL.md +48 -0
  34. package/skills/concierge/scenario-procurement-intake/SKILL.md +58 -0
  35. package/skills/codemation-ai-agent-node/SKILL.md +0 -66
  36. package/skills/codemation-ai-agent-node/references/anti-patterns.md +0 -11
  37. package/skills/codemation-credential-development/SKILL.md +0 -57
  38. package/skills/codemation-custom-node-development/SKILL.md +0 -61
  39. package/skills/codemation-custom-node-development/references/credential-aware-nodes.md +0 -38
  40. package/skills/codemation-custom-node-development/references/define-batch-node.md +0 -38
  41. package/skills/codemation-document-scanner/SKILL.md +0 -136
  42. package/skills/codemation-mcp-capabilities/references/agent-with-mcp.ts +0 -44
  43. package/skills/codemation-workflow-dsl/SKILL.md +0 -78
  44. package/skills/codemation-workflow-dsl/references/builder-patterns.md +0 -120
  45. package/skills/codemation-workflow-dsl/references/complete-example.md +0 -263
  46. package/skills/codemation-workflow-dsl/references/workflow-testing.md +0 -194
  47. package/skills/codemation-workspace-files/SKILL.md +0 -142
  48. /package/skills/{codemation-cli → builder/cli}/references/command-map.md +0 -0
  49. /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,44 +0,0 @@
1
- /**
2
- * Reference: using an MCP server in a workflow agent node.
3
- *
4
- * Before writing this, call GET /api/registry/capabilities?query=<name> to confirm
5
- * the server id and credential type. Then list the server id under `mcpServers`.
6
- *
7
- * Cron / webhook workflows use createWorkflowBuilder({id, name}).trigger(new XxxTrigger(...))
8
- * and chain with .then(new SomeNodeConfig(...)). The fluent .map/.if/.agent helpers are
9
- * only available via workflow("id").manualTrigger(...). See codemation-workflow-dsl skill.
10
- *
11
- * `mcpServers` is a plain array of server ids. Each declared server surfaces a credential
12
- * slot on the materialized MCP connection node (same shape as ChatModel/Tool connection
13
- * nodes). The user binds a credential instance via the canvas credential dropdown before
14
- * activation — same flow as trigger credentials.
15
- */
16
-
17
- import { AIAgent, CronTrigger, createWorkflowBuilder } from "@codemation/core-nodes";
18
-
19
- // Example: cron-triggered agent that uses the Gmail MCP server.
20
- // The "gmail" id comes from the registry (acceptedCredentialTypes: ["oauth.google.gmail"]).
21
- // The user must have connected their Google account and bound the credential before this runs.
22
-
23
- export const summariseEmailsWorkflow = createWorkflowBuilder({
24
- id: "wf.summarise-emails",
25
- name: "Summarise unread emails",
26
- })
27
- .trigger(new CronTrigger("Weekdays at 09:00", { schedule: "0 9 * * 1-5", timezone: "UTC" }))
28
- .then(
29
- new AIAgent({
30
- name: "Summarise",
31
- mcpServers: ["gmail"],
32
- messages: [
33
- {
34
- role: "system",
35
- content: [
36
- "You are an email assistant. Read the user's unread Gmail messages from the last 24 hours.",
37
- "Summarise each one in one sentence. Output as a bullet list.",
38
- "Do not draft or send any replies.",
39
- ].join("\n"),
40
- },
41
- ],
42
- }),
43
- )
44
- .build();
@@ -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