@codemation/agent-skills 0.1.10 → 0.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # @codemation/agent-skills
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#174](https://github.com/MadeRelevant/codemation/pull/174) [`b2c1855`](https://github.com/MadeRelevant/codemation/commit/b2c185525fdbb903a6ad5e756cd180e249c3d6c3) Thanks [@cblokland90](https://github.com/cblokland90)! - feat(metadata): emit skills[] into package metadata — SkillFrontmatterParser reads YAML-frontmatter SKILL.md files and resolves @codemation/\* uses deps to concrete versions via monorepo walk (D8); PackageMetadataExtractor walks skills/ directory; all 8 agent-skills SKILL.md files updated with tags and version-sensitive uses declarations per D7
8
+
9
+ - [#180](https://github.com/MadeRelevant/codemation/pull/180) [`5f28922`](https://github.com/MadeRelevant/codemation/commit/5f289221b35b165f84beb263f823f223b51b3f66) Thanks [@cblokland90](https://github.com/cblokland90)! - Restructure all 8 agent skills to orient+constrain pattern: keep mental model, when-to-use, decision branches, and anti-patterns in the skill body; replace multi-snippet code dumps with a single quickstart + find_examples() pointer to version-matched examples. Total line count reduced from 788 to ~421 (46%). Adds references/anti-patterns.md to codemation-ai-agent-node for version-specific gotchas (managed model id churn, chatModel string shorthand trap).
10
+
11
+ Product-owner steering applied (PR [#180](https://github.com/MadeRelevant/codemation/issues/180)): plugin-development SKILL.md slimmed with managed-mode non-relevance note; plugin anatomy + full definePlugin code moved to references/plugin-anatomy.md. mcp-capabilities adds managed CP-loaded discovery path and non-managed plugin note. ai-agent-node reframes CodemationChatModelConfig as the managed default (LLM broker auto-authenticates via HMAC pairing; no API key needed) and steers away from BYOK for managed users. credential-development adds conceptual test() explanation (what it does, when called, return shape) with pointer to new defineCredential example.
12
+
13
+ ## 0.2.0
14
+
15
+ ### Minor Changes
16
+
17
+ - 8285ec0: Add `codemation-ai-agent-node` skill teaching the coding agent the `AIAgent` constructor signature, message shape, output contract (`{ output: string }`), and the four managed model IDs currently in the allowlist. Also covers BYOK (`OpenAIChatModelConfig`) and MCP tool attachment.
18
+ - 8285ec0: Add `codemation-mcp-capabilities` skill: documents the control-plane `GET /api/registry/capabilities` endpoint, MCP server credential kinds, and the workflow-author flow for discovering and binding MCP servers. Originally produced under Story 14 in a workspace-local install; relocated here so `pnpm codemation skills sync` picks it up.
19
+
20
+ ### Patch Changes
21
+
22
+ - 8285ec0: docs(codemation-workflow-dsl): add "Verifying your workflow" section pointing agents to use `verify_workflow` MCP tool instead of `pnpm typecheck`.
23
+ - 8285ec0: Reorganize agent skills for faster coding-agent start-up (Story C).
24
+ - `codemation-framework-concepts` promoted to router skill: adds "Where to go next" section mapping tasks to skills, and updated frontmatter describing it as the index to read first.
25
+ - `codemation-custom-node-development` split into a slim TOC (53 lines) plus three new focused refs: `define-node-per-item.md`, `define-batch-node.md`, `credential-aware-nodes.md`. Binary/HTTP/MS-Graph patterns consolidated into the existing `node-patterns.md`.
26
+
27
+ - 8285ec0: Remove dead references to `describe_node` and `list_nodes` from workflow-dsl and ai-agent-node skills; replace with `find_examples` as the discovery surface.
28
+ - 8285ec0: Sprint 11 Story D: deepen `find_examples` as the canonical discovery surface in skills.
29
+ - Expand `codemation-workflow-dsl` "Discovering nodes and patterns" section with why examples are canonical, when to call first, two query patterns, zero-hit response (ask user or adapt with confirmation), and anti-pattern (don't grep node_modules).
30
+ - Strengthen `codemation-ai-agent-node` call-to-action with concrete `find_examples` query suggestions for AIAgent patterns.
31
+
32
+ - 8285ec0: docs(codemation-workflow-dsl): note that search results include install-state fields (`installed`, `requiresInstall`) and how agents should use them to plan `install_package` calls.
33
+ - 8285ec0: Sprint 12 Story C: add self-solving fallback chain to `codemation-workflow-dsl` skill.
34
+ - Add "When no example matches — the self-solving fallback chain" section after "Discovering nodes and patterns".
35
+ - Four-tier chain: retry with intent variations → defineRestNode (HTTP APIs) → HttpRequest (inline one-off) → defineNode (non-HTTP custom logic).
36
+ - Explicit "What NOT to do" and "Surfacing what you did" sub-sections.
37
+ - Agent never asks the non-technical user for fallback choices; picks per the chain and reports what it used.
38
+
39
+ - 8285ec0: Sprint 14 coverage: tests for WhenBuilder DSL helper, InMemoryWorkflowExecutionRepository retention paths, DevTrackedProcessTreeKiller edge cases, ConsumerCliTsconfigPreparation resolution, ListenPortConflictDescriber ss fallback, RedisRunEventBus publish/subscribe/teardown, CodemationChatModelFactory HMAC signing, registerCoreNodes smoke, single-react-component-per-file rule branches, and CodemationAgentSkillsCli error/help paths. No production code changes.
40
+ - 8285ec0: docs(skills): add complete workflow example to workflow-dsl skill
41
+ - 8285ec0: Fix workflow-dsl skill docs: `workflow("id")` is manual-trigger only. Cron, webhook, and other non-manual triggers must use `createWorkflowBuilder({id, name}).trigger(new XxxTrigger(...))` and chain with `.then(new SomeNodeConfig(...))` — the fluent `.map`/`.if`/`.agent`/`.node` sugar is only available via `manualTrigger(...)`.
42
+
43
+ Affected: `codemation-workflow-dsl/SKILL.md`, `codemation-workflow-dsl/references/builder-patterns.md`, `codemation-workflow-dsl/references/complete-example.md`, `codemation-mcp-capabilities/references/agent-with-mcp.ts`.
44
+
3
45
  ## 0.1.10
4
46
 
5
47
  ### Patch Changes
@@ -0,0 +1,110 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "packageName": "@codemation/agent-skills",
4
+ "packageVersion": "0.3.0",
5
+ "description": "Reusable agent skills for Codemation projects and plugin development.",
6
+ "kind": "skills",
7
+ "skills": [
8
+ {
9
+ "name": "codemation-ai-agent-node",
10
+ "description": "AIAgent constructor, message shape, managed and BYOK chatModel configs, outputSchema, mcpServers. Read before writing any workflow step that calls an LLM.",
11
+ "tags": [
12
+ "agent",
13
+ "llm",
14
+ "ai"
15
+ ],
16
+ "sourcePath": "skills/codemation-ai-agent-node/SKILL.md",
17
+ "dependencies": {
18
+ "@codemation/core-nodes": "0.9.0"
19
+ },
20
+ "code": "---\nname: codemation-ai-agent-node\ndescription: AIAgent constructor, message shape, managed and BYOK chatModel configs, outputSchema, mcpServers. Read before writing any workflow step that calls an LLM.\ncompatibility: Codemation core-nodes. Requires @codemation/core-nodes import.\ntags: agent, llm, ai\nuses: \"@codemation/core-nodes\"\n---\n\n# Codemation AI Agent Node\n\n## Mental model\n\n`AIAgent` is the single building block for any LLM step in a workflow. It receives items, runs a chat completion per item using the configured model and messages, and emits `{ output: string }` (or a parsed object when `outputSchema` is set) on its `main` port. The `chatModel` field determines whether the run consumes Codemation-managed quota (no credential needed) or a BYOK key the operator supplies. Every AIAgent emits exactly one output item per input item — it never fans out or filters.\n\n## When to use / when NOT\n\nUse `AIAgent` when a workflow step needs an LLM call: classification, extraction, summarisation, drafting, or decision.\nUse a plain `Callback` instead when the logic is deterministic code — no LLM needed.\nUse `mcpServers` (see `codemation-mcp-capabilities`) when the agent needs tool access to external services.\nRead `codemation-workflow-dsl` for the surrounding workflow structure.\n\n## Quickstart\n\n```ts\nimport { AIAgent, CodemationChatModelConfig } from \"@codemation/core-nodes\";\n\nnew AIAgent({\n name: \"Classify email\",\n messages: [\n { role: \"system\", content: \"Classify the email as spam or not-spam.\" },\n { role: \"user\", content: (args) => args.item.json.body as string },\n ],\n chatModel: new CodemationChatModelConfig(\"Claude Haiku\", \"anthropic/claude-haiku-4-5-20251001\"),\n});\n```\n\nFor full patterns — BYOK (`OpenAIChatModelConfig`), `outputSchema`, tools, multi-step pipelines, and gmail classification — use your harness's example-discovery tool: `find_examples({ query: \"AIAgent\" })`.\n\n## Decision branches & gotchas\n\n**Managed mode (default — no API key needed):** use `CodemationChatModelConfig(label, modelId)`. In managed mode the LLM broker **auto-authenticates via the workspace HMAC pairing** — no API key, no credential slot, no user setup required. This is the correct default for all managed-mode workflows. Do NOT tell managed users to \"get an API key\" — the broker handles authentication transparently.\n\n```ts\nchatModel: new CodemationChatModelConfig(\"Claude Haiku\", \"anthropic/claude-haiku-4-5-20251001\");\n// No credential slot created. Discover live model ids:\n// GET <CONTROL_PLANE_URL>/api/llm/managed-models\n```\n\n**BYOK (self-hosted / non-managed only):** use `OpenAIChatModelConfig(label, modelId, slotKey)` — it creates a credential slot the operator must bind with an API key. Only use this in self-hosted deployments where no managed broker is available.\n\n**Messages:** `content` is a plain string or a function `(args: { item, itemIndex, items, ctx }) => string`. Put instructions in the `system` message, per-item data in the `user` message. Use `\"assistant\"` role only for few-shot examples.\n\n**Structured output:** add `outputSchema: z.object({...})` to validate and parse the response. Without it, `item.json.output` is always a plain string.\n\n**Stable node id:** if the node has a credential binding (BYOK), set an explicit `id:` on the constructor. Without it the id derives from the `name` label — renaming the label orphans the binding. See `codemation-workflow-dsl` for the full id-stability rule.\n\n**Downstream access:** the next node sees `item.json.output` as the agent's text response. Cast it via a typed `Callback<{ output: string }>`.\n\n## Anti-patterns\n\n- Do not tell managed users to get an API key — use `CodemationChatModelConfig`; the broker authenticates automatically.\n- Do not use `OpenAIChatModelConfig` in managed mode — it creates an unnecessary credential slot and will prompt the user to bind a key they don't need.\n- Do not use `AIAgent` for deterministic logic; use `Callback` instead (cheaper, faster, no LLM billing).\n- Do not attempt to return multiple items from a single `AIAgent` step — it emits exactly one output per input.\n\nSee `references/anti-patterns.md` for version-specific gotchas (managed model id churn, chatModel string shorthand trap).\n"
21
+ },
22
+ {
23
+ "name": "codemation-cli",
24
+ "description": "Guides Codemation CLI work for consumer apps and framework-author development. Use when the user asks about `codemation dev`, `build`, `serve web`, `serve worker`, `user create`, `user list`, `--consumer-root`, `.codemation/output`, or consumer versus framework-author mode.",
25
+ "tags": [
26
+ "cli",
27
+ "dev"
28
+ ],
29
+ "sourcePath": "skills/codemation-cli/SKILL.md",
30
+ "dependencies": {},
31
+ "code": "---\nname: codemation-cli\ndescription: Guides Codemation CLI work for consumer apps and framework-author development. Use when the user asks about `codemation dev`, `build`, `serve web`, `serve worker`, `user create`, `user list`, `--consumer-root`, `.codemation/output`, or consumer versus framework-author mode.\ncompatibility: Designed for Codemation repositories and projects that use the Codemation CLI.\ntags: cli, dev\n---\n\n# Codemation CLI\n\n## Mental model\n\nThe CLI is a thin orchestrator: it loads `codemation.config.ts`, delegates to `@codemation/host` (web server) and worker packages, and manages build artifacts in `.codemation/output/`. It owns no workflow logic. There are two modes: **consumer mode** (`codemation dev`) runs a stable packaged UI against the consumer's workflows; **framework-author mode** (`codemation dev --watch-framework`) enables `next-host` HMR for monorepo development.\n\n## When to use / when NOT\n\nUse this skill for command selection, local development flow, and CLI troubleshooting.\nDo not use for workflow graph design, custom node implementation, or credential modeling unless the CLI command is the core question.\n\n## Quickstart\n\n```\ncodemation dev # consumer development (default)\ncodemation dev --watch-framework # framework-author / UI HMR (monorepo)\ncodemation build # emit .codemation/output/build\ncodemation serve web # run packaged web host\ncodemation serve worker # start queue-backed worker\ncodemation user create # bootstrap local-auth user\ncodemation user list # inspect auth users\n```\n\nUse `codemation --help` or `codemation <command> --help` before guessing flags.\n\n## Decision branches & gotchas\n\n**Standalone consumer vs monorepo:** confirm which context the user is in before suggesting commands. In the monorepo, distinguish framework-author mode from consumer mode explicitly.\n\n**Plugin loading:** in consumer mode, plugins are loaded from the built JavaScript path declared in `package.json#codemation.plugin` — not from TypeScript source under `node_modules`. In plugin dev mode, the CLI TypeScript-loads only the current plugin repo through the generated `.codemation/plugin-dev/codemation.config.ts`.\n\n**Redis-backed execution:** when Redis-backed execution is involved, mention the shared PostgreSQL requirement — local SQLite no longer fits.\n\n**Skills sync:** after `@codemation/cli` or `@codemation/agent-skills` package upgrades in monorepo work, run `codemation skills sync` to refresh extracted packaged skills in `.agents/skills/extracted`. Automatic refresh is intentionally disabled in the monorepo worktree to keep it clean.\n\n## Anti-patterns\n\n- Do not guess CLI flags — use `codemation <command> --help`.\n- Do not assume SQLite fits when Redis-backed workers are in play — check for the PostgreSQL requirement.\n\n## Read next when needed\n\n- Read `references/command-map.md` for command responsibilities and development-mode guidance.\n"
32
+ },
33
+ {
34
+ "name": "codemation-credential-development",
35
+ "description": "Guides Codemation custom credential development with `defineCredential(...)`, typed sessions, credential testing, and node credential slots. Use when creating or updating custom credentials, credential registrations, or credential-aware custom nodes.",
36
+ "tags": [
37
+ "credential",
38
+ "oauth",
39
+ "plugin"
40
+ ],
41
+ "sourcePath": "skills/codemation-credential-development/SKILL.md",
42
+ "dependencies": {},
43
+ "code": "---\nname: codemation-credential-development\ndescription: Guides Codemation custom credential development with `defineCredential(...)`, typed sessions, credential testing, and node credential slots. Use when creating or updating custom credentials, credential registrations, or credential-aware custom nodes.\ncompatibility: Designed for Codemation apps and plugins that register typed credentials.\ntags: credential, oauth, plugin\n---\n\n# Codemation Credential Development\n\n## Mental model\n\nA credential type is a schema + runtime adapter: it declares `public` config (e.g. OAuth client id), `secret` material (e.g. tokens), a `createSession(...)` factory that returns the typed object nodes consume, and a `test(...)` function for pre-activation validation. Nodes declare named credential slots; operators bind concrete instances to those slots in the UI. The binding key is `(workflowId, nodeId, slotKey)`.\n\n## When to use / when NOT\n\nUse this skill for defining new credential types, wiring them into apps or plugins, and teaching nodes to request typed credential sessions.\nDo not use for general workflow authoring unless credential slots or runtime sessions are the core problem.\n\n## Quickstart\n\nNo standalone snippet — the full `defineCredential(...)` shape is in `references/credential-patterns.md`. Use your harness's example-discovery tool for runnable examples: `find_examples({ query: \"defineCredential api-key test\" })` or `find_examples({ query: \"credential slot\" })`.\n\n## What `test()` does and why it matters\n\nEvery credential type must implement `test(args)`. It is called:\n\n- When the operator clicks **Connect** in the credential dialog (validates before saving).\n- Before a workflow activates (blocks activation on failing credentials).\n\n`test()` receives the same `{ publicConfig, material }` args as `createSession()`. It must return `{ status: \"healthy\" | \"failing\", message, testedAt }`. A \"failing\" result blocks workflow activation and surfaces the `message` to the operator — use it to give actionable guidance (\"API key is empty\", \"Endpoint returned 401 — key is invalid\").\n\nImplement `test()` as a cheap probe against the real service when possible (e.g. a `/health` or `/me` call). At minimum, validate that required secret fields are non-empty. Do NOT call `createSession()` from inside `test()` — test independently so credential issues are caught before runtime.\n\nSee the `define-credential-api-key` example for a concrete `test()` implementation: `find_examples({ query: \"defineCredential api-key test\" })`.\n\n## Authoring rules\n\n1. Start with `defineCredential(...)`.\n2. Keep `public` versus `secret` fields intentional.\n3. Make `createSession(...)` return the typed runtime object the node actually needs.\n4. Implement `test(...)` so failure states are explicit before workflow activation.\n5. Register credential types at the app or plugin boundary, not inside random workflow files.\n\n## Decision branches & gotchas\n\n**Node integration:** helper-defined nodes declare credentials directly in the `credentials` field; class-based nodes use lower-level credential requirement APIs when needed.\n\n**Binding stability:** the `nodeId` defaults to a slug of the node's `name` label. Renaming a credential-using node's label silently changes its id and orphans the binding in the UI. To prevent this, set an explicit `id:` on credential-using node configs so the id is decoupled from the label.\n\n## Anti-patterns\n\n- Do not hard-code secrets in node implementation — use credential slots.\n- Do not register credential types inside workflow files — use the app or plugin composition root.\n\n## Read next when needed\n\n- Read `references/credential-patterns.md` for schema, registration, and slot guidance.\n"
44
+ },
45
+ {
46
+ "name": "codemation-custom-node-development",
47
+ "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.",
48
+ "tags": [
49
+ "node",
50
+ "custom",
51
+ "plugin"
52
+ ],
53
+ "sourcePath": "skills/codemation-custom-node-development/SKILL.md",
54
+ "dependencies": {
55
+ "@codemation/core": "0.12.0"
56
+ },
57
+ "code": "---\nname: codemation-custom-node-development\ndescription: 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.\ncompatibility: Designed for Codemation apps and plugin packages that define reusable nodes.\ntags: node, custom, plugin\nuses: \"@codemation/core\"\n---\n\n# Codemation Custom Node Development\n\n## Mental model\n\nCustom 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.\n\n## Use this skill when\n\nUse this skill for reusable custom node work, whether the node lives inside an app or a published plugin package.\n\nDo not use this skill for pure workflow chaining questions unless the node implementation itself is changing.\n\n## Per-item vs batch\n\n**`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.\n\n**`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).\n\nWhen in doubt, start with `defineNode`.\n\n## Node rules\n\n1. Keep nodes deterministic and focused.\n2. Request credentials through named slots — never hard-code secrets.\n3. Put **static** options (credentials, retry policy, labels) on **config**; put **per-item** behavior in **inputs** / wire JSON and optional `itemExpr` on config fields.\n4. **Emit files with `ctx.binary`, not base64 in `json`** — base64 in `item.json` bloats persisted run data. See `references/node-patterns.md`.\n5. Drop to class-based node APIs only when you need constructor-injected collaborators, decorators, or deeper runtime metadata.\n\n## Minimal `defineNode` example\n\n```ts\nimport { defineNode } from \"@codemation/core\";\nimport { z } from \"zod\";\n\nexport const uppercaseNode = defineNode({\n key: \"example.uppercase\",\n title: \"Uppercase field\",\n icon: \"lucide:languages\",\n inputSchema: z.object({ field: z.string() }),\n async execute({ input }) {\n return { ...input, field: input.field.toUpperCase() };\n },\n});\n```\n\nFor 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\" })`.\n\n## Read next\n\n- `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.\n- `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.\n- `references/credential-aware-nodes.md` — credential slots, typed sessions, and how to test credential-aware nodes. Load this when your node needs a credential.\n- `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.\n"
58
+ },
59
+ {
60
+ "name": "codemation-framework-concepts",
61
+ "description": "Explains Codemation package boundaries, runtime concepts, observability shape, and the normal consumer mental model. Use when the user asks where code belongs across `@codemation/core`, `@codemation/host`, `@codemation/next-host`, `@codemation/cli`, workflows, plugins, credentials, activation, telemetry, or runtime modes. Read this first when starting any Codemation task — it points at the right skill for the work.",
62
+ "tags": [
63
+ "concepts",
64
+ "architecture"
65
+ ],
66
+ "sourcePath": "skills/codemation-framework-concepts/SKILL.md",
67
+ "dependencies": {},
68
+ "code": "---\nname: codemation-framework-concepts\ndescription: Explains Codemation package boundaries, runtime concepts, observability shape, and the normal consumer mental model. Use when the user asks where code belongs across `@codemation/core`, `@codemation/host`, `@codemation/next-host`, `@codemation/cli`, workflows, plugins, credentials, activation, telemetry, or runtime modes. Read this first when starting any Codemation task — it points at the right skill for the work.\ncompatibility: Designed for Codemation apps, plugins, and framework contributors.\ntags: concepts, architecture\n---\n\n# Codemation Framework Concepts\n\n## Mental model\n\nCodemation is a workflow engine with a layered package structure. `@codemation/core` owns the engine and runtime contracts (must stay pure — no HTTP, UI, or vendor SDKs). `@codemation/host` adds persistence, credentials, APIs, and scheduler wiring. `@codemation/next-host` is the framework UI shell. `@codemation/cli` runs local development, build, and serve. Consumer apps define behavior in `codemation.config.ts` and `src/workflows/` — they never touch core internals.\n\n## When to use / when NOT\n\nUse this skill to orient on package ownership, runtime shape, observability boundaries, and the consumer/framework divide.\nDo not use as a substitute for detailed CLI, workflow DSL, or plugin implementation guidance when you already know which skill you need.\n\n## Core concepts\n\n- **workflows** define behavior; **triggers** start runs; **nodes** process items; **items** carry `item.json` data.\n- **credentials** provide typed runtime resources (bound per operator instance, not per workflow code).\n- **activation** is framework-managed and happens in the UI — consumer code does not call it directly.\n- **telemetry** is observability-first: traces, spans, artifacts, and metric points are framework-owned runtime data.\n- **workflow testing** is a first-class primitive: `TestTrigger` yields one item per test case; `Assertion` nodes record per-run results into `TestAssertion` rows; the canvas exposes a Tests tab.\n- **run retention** and **telemetry retention** can differ — trend data can outlive raw run state.\n\n## Where to go next\n\n| Task | Skill |\n| ------------------------------------- | ------------------------------------ |\n| Authoring workflows | `codemation-workflow-dsl` |\n| Building a reusable node | `codemation-custom-node-development` |\n| Building a credential type | `codemation-credential-development` |\n| Packaging as a plugin | `codemation-plugin-development` |\n| Calling an MCP server from a workflow | `codemation-mcp-capabilities` |\n| CLI commands / dev loop | `codemation-cli` |\n\n## Read next when needed\n\n- Read `references/architecture-map.md` for package ownership and runtime-mode guidance.\n"
69
+ },
70
+ {
71
+ "name": "codemation-mcp-capabilities",
72
+ "description": "Discover MCP servers registered on the Codemation control plane. Use before authoring agent workflows that reference mcpServers to find available server ids and their credential requirements.",
73
+ "tags": [
74
+ "mcp",
75
+ "agent",
76
+ "tool"
77
+ ],
78
+ "sourcePath": "skills/codemation-mcp-capabilities/SKILL.md",
79
+ "dependencies": {},
80
+ "code": "---\nname: codemation-mcp-capabilities\ndescription: Discover MCP servers registered on the Codemation control plane. Use before authoring agent workflows that reference mcpServers to find available server ids and their credential requirements.\ncompatibility: Requires an installation paired with a connected control plane (Sprint 2+).\ntags: mcp, agent, tool\n---\n\n# Codemation MCP Capabilities\n\n## Mental model\n\nMCP servers extend `AIAgent` with tool access to external services (Gmail, Sheets, etc.). Server ids and credential requirements come from the control-plane registry — they are not hard-coded in framework code. The agent's `mcpServers` array contains stable server id slugs; each declared server surfaces a credential slot the operator must bind in the canvas before activation.\n\n## When to use / when NOT\n\nUse this skill before writing `agent({ mcpServers: [\"...\"] })` to discover available server ids and their credential types.\nDo not use for general AIAgent authoring — read `codemation-ai-agent-node` for that.\n\n## Managed mode: CP-loaded MCP servers (default path)\n\nIn **managed mode**, MCP servers are loaded from the **control plane (CP)** — not declared in plugin code. Discover available servers by querying the CP registry:\n\n```\nGET /api/registry/capabilities?query=gmail\n```\n\nResponse contains objects with `{ kind, id, displayName, description, acceptedCredentialTypes }`. Use `id` in the workflow's `mcpServers` array. An empty `query` string returns all registered servers.\n\nFor a full wired example — cron workflow + AIAgent + mcpServers — use your harness's example-discovery tool: `find_examples({ query: \"AIAgent gmail mcpServers\" })` or `find_examples({ query: \"mcp server\" })`.\n\n## Non-managed: plugin-declared MCP servers\n\nIn self-hosted / non-managed deployments, MCP servers can also be declared via `mcpServers: [...]` in a `definePlugin(...)` call. This is a framework-author pattern — do not use it in managed-mode workflows. See `references/plugin-anatomy.md` in the `codemation-plugin-development` skill for the plugin declaration syntax.\n\n## Decision branches & gotchas\n\n**Credential types:** `\"oauth.google.gmail\"` requires the user to connect a Google account via the credential dialog before the workflow runs. The same instance can be shared between a `GmailTrigger` and the Gmail MCP server. An empty `acceptedCredentialTypes` array means no credential is needed.\n\n**Multiple instances:** a user may have multiple instances of the same credential type (personal vs work Gmail). The canvas credential dropdown surfaces all matching instances — the operator picks the one to bind.\n\n**Bind via UI only:** there is no inline credential field on the workflow definition. The operator binds the credential instance via the canvas credential dropdown before activation.\n\n**Typical flow (managed):**\n\n1. `GET /api/registry/capabilities?query=<term>` → find `id` and `acceptedCredentialTypes`.\n2. Add `id` to `mcpServers` in the `AIAgent` config.\n3. Report: \"The user will need to bind a `<type>` credential instance via the canvas before activating.\"\n\n## Anti-patterns\n\n- Do not guess server ids — always query the registry first.\n- Do not add `acceptedCredentialTypes` to the workflow definition — credential binding is UI-driven, not code-driven.\n- Do not declare MCP servers inside plugin code for managed-mode workflows — use the CP registry instead.\n"
81
+ },
82
+ {
83
+ "name": "codemation-plugin-development",
84
+ "description": "Guides Codemation plugin package development, including `definePlugin(...)`, plugin sandboxes, custom nodes, custom credentials, and publishable plugin package structure. Use when building or updating a Codemation plugin package or the plugin starter template.",
85
+ "tags": [
86
+ "plugin",
87
+ "node",
88
+ "package"
89
+ ],
90
+ "sourcePath": "skills/codemation-plugin-development/SKILL.md",
91
+ "dependencies": {},
92
+ "code": "---\nname: codemation-plugin-development\ndescription: Guides Codemation plugin package development, including `definePlugin(...)`, plugin sandboxes, custom nodes, custom credentials, and publishable plugin package structure. Use when building or updating a Codemation plugin package or the plugin starter template.\ncompatibility: Designed for Codemation plugin packages and the Codemation plugin starter template.\ntags: plugin, node, package\n---\n\n# Codemation Plugin Development\n\n## Mental model\n\nA Codemation plugin is an npm package with a `codemation.plugin.ts` composition root that calls `definePlugin(...)`. It registers custom nodes and credential types, optionally declares MCP servers, and ships a sandbox app so the plugin is immediately testable. Consumers load the built JavaScript entry (`package.json#codemation.plugin`) — not TypeScript source. Plugin code follows the same `defineNode` / `defineCredential` patterns as app-level code; the plugin boundary is purely about packaging and distribution.\n\n## When to use / when NOT\n\n**Plugin authoring is a framework-author / non-managed task.** Managed-mode agents work with credential slots and workflow DSL — they do not author or modify plugin packages.\n\nUse this skill for published plugin packages, plugin starter work, and sandbox-driven plugin development. Do not use for ordinary consumer workflow-only changes.\n\n## Decision branches & gotchas\n\n**MCP servers in plugins:** Plugin-declared `mcpServers` is a non-managed pattern for self-hosted / framework-author scenarios. In managed mode, MCP servers are loaded from the control plane — see `codemation-mcp-capabilities` for the managed path.\n\n**Publishing guardrail:** `package.json#codemation.plugin` must point at runnable JavaScript (`./dist/codemation.plugin.js`). Do not rely on consumers TypeScript-loading plugin files from `node_modules`.\n\n## Read next when needed\n\n- Read `references/plugin-anatomy.md` for the full `definePlugin(...)` code, package layout, sandbox setup, MCP server declaration, binary payload rules, and publishing guidance.\n- Read `references/plugin-structure.md` for a concise package layout reference.\n"
93
+ },
94
+ {
95
+ "name": "codemation-workflow-dsl",
96
+ "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(...)`.",
97
+ "tags": [
98
+ "workflow",
99
+ "dsl",
100
+ "authoring"
101
+ ],
102
+ "sourcePath": "skills/codemation-workflow-dsl/SKILL.md",
103
+ "dependencies": {
104
+ "@codemation/core-nodes": "0.9.0",
105
+ "@codemation/host": "0.9.1"
106
+ },
107
+ "code": "---\nname: codemation-workflow-dsl\ndescription: 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(...)`.\ncompatibility: Designed for Codemation apps and plugins that author workflows.\ntags: workflow, dsl, authoring\nuses: \"@codemation/core-nodes, @codemation/host\"\n---\n\n# Codemation Workflow DSL\n\n## Mental model\n\nA 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.\n\n## When to use / when NOT\n\nUse this skill when authoring or reviewing workflow definitions under `src/workflows/`.\nDo not use for CLI-only troubleshooting or deep host architecture questions unless they directly affect workflow authoring.\n\n## Quickstart — pick API by trigger type\n\n```ts\n// Manual trigger — full fluent sugar (.map, .if, .switch, .agent, .node, .then)\nimport { workflow } from \"@codemation/host\";\nexport default workflow(\"wf.example\")\n .manualTrigger(\"Start\", {\n /* seed items */\n })\n .map(/* ... */)\n .build();\n\n// Cron / webhook / any other trigger — low-level .then(new NodeConfig(...)) only\nimport { createWorkflowBuilder, CronTrigger } from \"@codemation/core-nodes\";\nexport default createWorkflowBuilder({ id: \"wf.example\", name: \"Example\" })\n .trigger(new CronTrigger(\"Daily\", { schedule: \"0 9 * * *\", timezone: \"UTC\" }))\n .then(/* new SomeNodeConfig(...) */)\n .build();\n```\n\nFor 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\"`.\n\n## Decision branches & gotchas\n\n**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.\n\n**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.\n\n**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.\n\n**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\" })`.\n\n**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.\n\n**When no example matches — self-solving fallback chain.**\n\n1. Retry with intent variations (different verb, more generic term).\n2. For HTTP APIs: `find_examples({ query: \"defineRestNode\" })` — covers basic and credential-slotted REST.\n3. For one-shot inline HTTP: `find_examples({ query: \"HttpRequest\" })`.\n4. For non-HTTP custom logic: `find_examples({ query: \"defineNode template\" })`.\n 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.\n\n**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.\n\n**SubWorkflow binary.** `item.binary` slots pass transparently through SubWorkflow boundaries in both directions — no special config needed. Both runs share the same `BinaryStorage` singleton.\n\n**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? }`.\n\n## Anti-patterns\n\n- Do not call `.trigger(...)` on the `workflow(...)` manual builder — use `createWorkflowBuilder(...)` for non-manual triggers.\n- Do not rely on slug-derived node ids for production workflows with credential bindings — always set an explicit `id:`.\n- Do not improvise from memory when `find_examples` returns zero hits — use the fallback chain above.\n\n## Read next when needed\n\n- `references/builder-patterns.md` — item-flow rules and fluent authoring patterns.\n- `references/workflow-testing.md` — TestTrigger / IsTestRun / Assertion with full examples.\n- `references/complete-example.md` — dense end-to-end example covering most authoring features.\n"
108
+ }
109
+ ]
110
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemation/agent-skills",
3
- "version": "0.1.10",
3
+ "version": "0.3.0",
4
4
  "description": "Reusable agent skills for Codemation projects and plugin development.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -43,11 +43,14 @@
43
43
  "README.md",
44
44
  "CHANGELOG.md",
45
45
  "bin",
46
+ "dist",
46
47
  "lib",
47
48
  "skills"
48
49
  ],
49
50
  "scripts": {
50
51
  "changeset:verify": "pnpm --workspace-root run changeset:verify",
52
+ "build": "pnpm build:metadata",
53
+ "build:metadata": "tsx ../../tooling/discovery/scripts/extract-metadata.ts",
51
54
  "test": "vitest run",
52
55
  "test:unit": "vitest run"
53
56
  }
@@ -0,0 +1,66 @@
1
+ ---
2
+ name: codemation-ai-agent-node
3
+ description: AIAgent constructor, message shape, managed and BYOK chatModel configs, outputSchema, mcpServers. Read before writing any workflow step that calls an LLM.
4
+ compatibility: Codemation core-nodes. Requires @codemation/core-nodes import.
5
+ tags: agent, llm, ai
6
+ uses: "@codemation/core-nodes"
7
+ ---
8
+
9
+ # Codemation AI Agent Node
10
+
11
+ ## Mental model
12
+
13
+ `AIAgent` is the single building block for any LLM step in a workflow. It receives items, runs a chat completion per item using the configured model and messages, and emits `{ output: string }` (or a parsed object when `outputSchema` is set) on its `main` port. The `chatModel` field determines whether the run consumes Codemation-managed quota (no credential needed) or a BYOK key the operator supplies. Every AIAgent emits exactly one output item per input item — it never fans out or filters.
14
+
15
+ ## When to use / when NOT
16
+
17
+ Use `AIAgent` when a workflow step needs an LLM call: classification, extraction, summarisation, drafting, or decision.
18
+ Use a plain `Callback` instead when the logic is deterministic code — no LLM needed.
19
+ Use `mcpServers` (see `codemation-mcp-capabilities`) when the agent needs tool access to external services.
20
+ Read `codemation-workflow-dsl` for the surrounding workflow structure.
21
+
22
+ ## Quickstart
23
+
24
+ ```ts
25
+ import { AIAgent, CodemationChatModelConfig } from "@codemation/core-nodes";
26
+
27
+ new AIAgent({
28
+ name: "Classify email",
29
+ messages: [
30
+ { role: "system", content: "Classify the email as spam or not-spam." },
31
+ { role: "user", content: (args) => args.item.json.body as string },
32
+ ],
33
+ chatModel: new CodemationChatModelConfig("Claude Haiku", "anthropic/claude-haiku-4-5-20251001"),
34
+ });
35
+ ```
36
+
37
+ For full patterns — BYOK (`OpenAIChatModelConfig`), `outputSchema`, tools, multi-step pipelines, and gmail classification — use your harness's example-discovery tool: `find_examples({ query: "AIAgent" })`.
38
+
39
+ ## Decision branches & gotchas
40
+
41
+ **Managed mode (default — no API key needed):** use `CodemationChatModelConfig(label, modelId)`. In managed mode the LLM broker **auto-authenticates via the workspace HMAC pairing** — no API key, no credential slot, no user setup required. This is the correct default for all managed-mode workflows. Do NOT tell managed users to "get an API key" — the broker handles authentication transparently.
42
+
43
+ ```ts
44
+ chatModel: new CodemationChatModelConfig("Claude Haiku", "anthropic/claude-haiku-4-5-20251001");
45
+ // No credential slot created. Discover live model ids:
46
+ // GET <CONTROL_PLANE_URL>/api/llm/managed-models
47
+ ```
48
+
49
+ **BYOK (self-hosted / non-managed only):** use `OpenAIChatModelConfig(label, modelId, slotKey)` — it creates a credential slot the operator must bind with an API key. Only use this in self-hosted deployments where no managed broker is available.
50
+
51
+ **Messages:** `content` is a plain string or a function `(args: { item, itemIndex, items, ctx }) => string`. Put instructions in the `system` message, per-item data in the `user` message. Use `"assistant"` role only for few-shot examples.
52
+
53
+ **Structured output:** add `outputSchema: z.object({...})` to validate and parse the response. Without it, `item.json.output` is always a plain string.
54
+
55
+ **Stable node id:** if the node has a credential binding (BYOK), set an explicit `id:` on the constructor. Without it the id derives from the `name` label — renaming the label orphans the binding. See `codemation-workflow-dsl` for the full id-stability rule.
56
+
57
+ **Downstream access:** the next node sees `item.json.output` as the agent's text response. Cast it via a typed `Callback<{ output: string }>`.
58
+
59
+ ## Anti-patterns
60
+
61
+ - Do not tell managed users to get an API key — use `CodemationChatModelConfig`; the broker authenticates automatically.
62
+ - Do not use `OpenAIChatModelConfig` in managed mode — it creates an unnecessary credential slot and will prompt the user to bind a key they don't need.
63
+ - Do not use `AIAgent` for deterministic logic; use `Callback` instead (cheaper, faster, no LLM billing).
64
+ - Do not attempt to return multiple items from a single `AIAgent` step — it emits exactly one output per input.
65
+
66
+ See `references/anti-patterns.md` for version-specific gotchas (managed model id churn, chatModel string shorthand trap).
@@ -0,0 +1,11 @@
1
+ # AIAgent anti-patterns (version-specific)
2
+
3
+ ## Managed model ids change between releases
4
+
5
+ Do NOT hard-code managed model ids sourced from training data. The allowlisted set changes with each release.
6
+ Always discover the live list via `GET <CONTROL_PLANE_URL>/api/llm/managed-models` before committing a model id.
7
+
8
+ ## `chatModel` string shorthand is not supported on AIAgent
9
+
10
+ `AIAgent` does not accept a plain string for `chatModel` — only `CodemationChatModelConfig` or `OpenAIChatModelConfig` instances.
11
+ (The string shorthand `model: "openai:gpt-4o-mini"` works on the `.agent(...)` fluent DSL helper only.)
@@ -2,42 +2,48 @@
2
2
  name: codemation-cli
3
3
  description: Guides Codemation CLI work for consumer apps and framework-author development. Use when the user asks about `codemation dev`, `build`, `serve web`, `serve worker`, `user create`, `user list`, `--consumer-root`, `.codemation/output`, or consumer versus framework-author mode.
4
4
  compatibility: Designed for Codemation repositories and projects that use the Codemation CLI.
5
+ tags: cli, dev
5
6
  ---
6
7
 
7
8
  # Codemation CLI
8
9
 
9
- ## Use this skill when
10
+ ## Mental model
10
11
 
11
- Use this skill for command selection, local development flow, and CLI troubleshooting in a Codemation app or monorepo.
12
+ The CLI is a thin orchestrator: it loads `codemation.config.ts`, delegates to `@codemation/host` (web server) and worker packages, and manages build artifacts in `.codemation/output/`. It owns no workflow logic. There are two modes: **consumer mode** (`codemation dev`) runs a stable packaged UI against the consumer's workflows; **framework-author mode** (`codemation dev --watch-framework`) enables `next-host` HMR for monorepo development.
12
13
 
13
- Do not use this skill for workflow graph design, custom node implementation, or credential modeling unless the CLI command flow is the main question.
14
+ ## When to use / when NOT
14
15
 
15
- ## Default approach
16
+ Use this skill for command selection, local development flow, and CLI troubleshooting.
17
+ Do not use for workflow graph design, custom node implementation, or credential modeling unless the CLI command is the core question.
16
18
 
17
- 1. Confirm whether the user is in a standalone consumer project or the Codemation monorepo.
18
- 2. Prefer `codemation --help` or `codemation <command> --help` before guessing flags.
19
- 3. Explain the shortest command path first, then mention framework-author alternatives only if they matter.
20
- 4. Keep the CLI thin in your mental model: it orchestrates host and runtime packages instead of owning workflow logic itself.
19
+ ## Quickstart
21
20
 
22
- ## Command map
21
+ ```
22
+ codemation dev # consumer development (default)
23
+ codemation dev --watch-framework # framework-author / UI HMR (monorepo)
24
+ codemation build # emit .codemation/output/build
25
+ codemation serve web # run packaged web host
26
+ codemation serve worker # start queue-backed worker
27
+ codemation user create # bootstrap local-auth user
28
+ codemation user list # inspect auth users
29
+ ```
23
30
 
24
- - `codemation dev`: default consumer development flow with packaged UI and a stable CLI-owned dev gateway.
25
- - `codemation dev --watch-framework`: framework-author mode for monorepo work and `next-host` UI HMR.
26
- - `codemation build`: emits production-oriented consumer output under `.codemation/output/build`.
27
- - `codemation serve web`: runs the packaged web host for a built or configured consumer app.
28
- - `codemation serve worker`: starts the queue-backed worker runtime when execution is separated.
29
- - `codemation user create` and `codemation user list`: local-auth bootstrap and inspection commands.
31
+ Use `codemation --help` or `codemation <command> --help` before guessing flags.
30
32
 
31
- ## Working rules
33
+ ## Decision branches & gotchas
32
34
 
33
- 1. Treat `codemation.config.ts` as the consumer entrypoint.
34
- 2. Mention `.codemation/output` only when build artifacts or runtime bootstrap details matter.
35
- 3. When the user is in the monorepo, distinguish framework-author mode from normal consumer mode explicitly.
36
- 4. When Redis-backed execution is involved, mention the shared PostgreSQL requirement instead of assuming local SQLite still fits.
37
- 5. In consumer mode, discovered plugins are loaded from the built JavaScript path declared in `package.json#codemation.plugin`, not from TypeScript source under `node_modules`.
38
- 6. In plugin mode, the CLI TypeScript-loads only the current plugin repo through the generated `.codemation/plugin-dev/codemation.config.ts`.
39
- 7. In the Codemation framework monorepo, automatic refresh of `.agents/skills/extracted` is intentionally disabled to keep the worktree clean.
40
- 8. After `@codemation/cli` or `@codemation/agent-skills` package upgrades in monorepo work, remind the user to run `codemation skills sync` if they want the extracted packaged skills refreshed.
35
+ **Standalone consumer vs monorepo:** confirm which context the user is in before suggesting commands. In the monorepo, distinguish framework-author mode from consumer mode explicitly.
36
+
37
+ **Plugin loading:** in consumer mode, plugins are loaded from the built JavaScript path declared in `package.json#codemation.plugin` — not from TypeScript source under `node_modules`. In plugin dev mode, the CLI TypeScript-loads only the current plugin repo through the generated `.codemation/plugin-dev/codemation.config.ts`.
38
+
39
+ **Redis-backed execution:** when Redis-backed execution is involved, mention the shared PostgreSQL requirement local SQLite no longer fits.
40
+
41
+ **Skills sync:** after `@codemation/cli` or `@codemation/agent-skills` package upgrades in monorepo work, run `codemation skills sync` to refresh extracted packaged skills in `.agents/skills/extracted`. Automatic refresh is intentionally disabled in the monorepo worktree to keep it clean.
42
+
43
+ ## Anti-patterns
44
+
45
+ - Do not guess CLI flags — use `codemation <command> --help`.
46
+ - Do not assume SQLite fits when Redis-backed workers are in play — check for the PostgreSQL requirement.
41
47
 
42
48
  ## Read next when needed
43
49
 
@@ -2,27 +2,36 @@
2
2
  name: codemation-credential-development
3
3
  description: Guides Codemation custom credential development with `defineCredential(...)`, typed sessions, credential testing, and node credential slots. Use when creating or updating custom credentials, credential registrations, or credential-aware custom nodes.
4
4
  compatibility: Designed for Codemation apps and plugins that register typed credentials.
5
+ tags: credential, oauth, plugin
5
6
  ---
6
7
 
7
8
  # Codemation Credential Development
8
9
 
9
- ## Use this skill when
10
+ ## Mental model
11
+
12
+ A credential type is a schema + runtime adapter: it declares `public` config (e.g. OAuth client id), `secret` material (e.g. tokens), a `createSession(...)` factory that returns the typed object nodes consume, and a `test(...)` function for pre-activation validation. Nodes declare named credential slots; operators bind concrete instances to those slots in the UI. The binding key is `(workflowId, nodeId, slotKey)`.
13
+
14
+ ## When to use / when NOT
10
15
 
11
16
  Use this skill for defining new credential types, wiring them into apps or plugins, and teaching nodes to request typed credential sessions.
17
+ Do not use for general workflow authoring unless credential slots or runtime sessions are the core problem.
18
+
19
+ ## Quickstart
20
+
21
+ No standalone snippet — the full `defineCredential(...)` shape is in `references/credential-patterns.md`. Use your harness's example-discovery tool for runnable examples: `find_examples({ query: "defineCredential api-key test" })` or `find_examples({ query: "credential slot" })`.
12
22
 
13
- Do not use this skill for general workflow authoring unless credential slots or runtime sessions are the core problem.
23
+ ## What `test()` does and why it matters
14
24
 
15
- ## Credential binding stability
25
+ Every credential type must implement `test(args)`. It is called:
16
26
 
17
- Credentials bind to a node via `(workflowId, nodeId, slotKey)`. The `nodeId` defaults to a slug of the node's `name` label (lowercase, non-alphanumeric runs replaced with `-`). Renaming a credential-using node's label silently changes its id and the binding appears unbound in the UI the operator must re-attach manually.
27
+ - When the operator clicks **Connect** in the credential dialog (validates before saving).
28
+ - Before a workflow activates (blocks activation on failing credentials).
18
29
 
19
- To prevent this: either keep the node's label stable across edits, or set an explicit `id:` on the node config so the id is decoupled from the label.
30
+ `test()` receives the same `{ publicConfig, material }` args as `createSession()`. It must return `{ status: "healthy" | "failing", message, testedAt }`. A "failing" result blocks workflow activation and surfaces the `message` to the operator use it to give actionable guidance ("API key is empty", "Endpoint returned 401 — key is invalid").
20
31
 
21
- ## Core mental model
32
+ Implement `test()` as a cheap probe against the real service when possible (e.g. a `/health` or `/me` call). At minimum, validate that required secret fields are non-empty. Do NOT call `createSession()` from inside `test()` — test independently so credential issues are caught before runtime.
22
33
 
23
- 1. A credential type defines public config, secret material, session creation, and health testing.
24
- 2. Nodes request credentials through named slots instead of hard-coded secrets.
25
- 3. Operators configure concrete credential instances in the UI and bind them to those slots.
34
+ See the `define-credential-api-key` example for a concrete `test()` implementation: `find_examples({ query: "defineCredential api-key test" })`.
26
35
 
27
36
  ## Authoring rules
28
37
 
@@ -32,10 +41,16 @@ To prevent this: either keep the node's label stable across edits, or set an exp
32
41
  4. Implement `test(...)` so failure states are explicit before workflow activation.
33
42
  5. Register credential types at the app or plugin boundary, not inside random workflow files.
34
43
 
35
- ## Node integration
44
+ ## Decision branches & gotchas
45
+
46
+ **Node integration:** helper-defined nodes declare credentials directly in the `credentials` field; class-based nodes use lower-level credential requirement APIs when needed.
47
+
48
+ **Binding stability:** the `nodeId` defaults to a slug of the node's `name` label. Renaming a credential-using node's label silently changes its id and orphans the binding in the UI. To prevent this, set an explicit `id:` on credential-using node configs so the id is decoupled from the label.
49
+
50
+ ## Anti-patterns
36
51
 
37
- - helper-defined nodes can declare credentials directly in `credentials`
38
- - class-based nodes can use lower-level credential requirement APIs when needed
52
+ - Do not hard-code secrets in node implementation use credential slots.
53
+ - Do not register credential types inside workflow files — use the app or plugin composition root.
39
54
 
40
55
  ## Read next when needed
41
56
 
@@ -2,45 +2,60 @@
2
2
  name: codemation-custom-node-development
3
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
4
  compatibility: Designed for Codemation apps and plugin packages that define reusable nodes.
5
+ tags: node, custom, plugin
6
+ uses: "@codemation/core"
5
7
  ---
6
8
 
7
9
  # Codemation Custom Node Development
8
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
+
9
15
  ## Use this skill when
10
16
 
11
17
  Use this skill for reusable custom node work, whether the node lives inside an app or a published plugin package.
12
18
 
13
19
  Do not use this skill for pure workflow chaining questions unless the node implementation itself is changing.
14
20
 
15
- ## Default approach
16
-
17
- 1. Start with `defineNode(...)`.
18
- 2. Implement **`execute(args, context)`** — one mapped **input** in, one output payload per item (activations are still batch-shaped; the engine iterates items for you).
19
- 3. Give the node a stable key and a clear title.
20
- 4. Optionally set **`icon`** on the `defineNode` definition so the workflow canvas shows a proper glyph (same string contract as `NodeConfigBase.icon`).
21
- 5. Use **`defineBatchNode(...)`** with **`run(items, context)`** only when the node must process the **entire batch** at once (legacy batch semantics).
22
- 6. Promote callback-heavy logic into a node when the graph or tests need a stronger boundary.
23
-
24
- ## Node rules
21
+ ## Per-item vs batch
25
22
 
26
- 1. Prefer helper-based nodes first.
27
- 2. Keep nodes deterministic and focused.
28
- 3. Request credentials through named slots instead of hard-coded secrets.
29
- 4. Put **static** options (credentials, retry policy, labels) on **config**; put **per-item** behavior in **inputs** / wire JSON and optional **`itemExpr`** on config fields (consistent with built-in nodes).
30
- 5. **Emit files with `ctx.binary`, not base64 in `json`:** use **`attach`** + **`withAttachment`** on **`args.ctx.binary`** (`defineNode`) or **`ctx.binary`** (class nodes). Base64 in **`item.json`** bloats persisted run JSON in the database; binaries use **storage + references** only. See `references/node-patterns.md` and repo docs **Concepts → Execution model** / **Custom nodes**.
31
- 6. Drop to class-based node APIs only when you need constructor-injected collaborators, decorators, or deeper runtime metadata.
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.
32
24
 
33
- ## Testing with `WorkflowTestKit`
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).
34
26
 
35
- For engine-backed tests without the host, use **`WorkflowTestKit`** from **`@codemation/core/testing`**: **`registerDefinedNodes([...])`**, then **`runNode`** or **`run`**. See the plugin development doc and `@codemation/core` tests for examples.
27
+ When in doubt, start with `defineNode`.
36
28
 
37
- ## Custom assertion + test nodes
38
-
39
- When building **assertion** nodes that should record results into the framework's TestSuiteRun infrastructure, set **`emitsAssertions: true`** on the node config. The host's `TestSuiteRunTracker` listens for `nodeCompleted` events from runs with `ctx.testContext` set and persists each emitted item (matching the `AssertionResult` shape) as a `TestAssertion` row. Drop in a `defineNode` with a per-item `execute` that returns `AssertionResult[]` and you're done — no service injection required.
40
-
41
- Custom **per-item nodes** can also read **`ctx.testContext?.{testSuiteRunId, testCaseIndex}`** to branch on test mode without an `IsTestRun` upstream — useful for synthetic outputs or skipping irreversible side effects when running tests.
42
-
43
- ## Read next when needed
29
+ ## Node rules
44
30
 
45
- - Read `references/node-patterns.md` for `defineNode(...)` patterns and packaging guidance.
46
- - Use the `codemation-workflow-dsl` skill's `references/workflow-testing.md` for the full TestTrigger / IsTestRun / Assertion authoring story.
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.
@@ -0,0 +1,38 @@
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.