@keystrokehq/skills 0.0.3 → 0.0.6
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 +39 -0
- package/README.md +24 -15
- package/package.json +3 -10
- package/{AGENTS-blurb.md → src/_AGENTS.md} +1 -1
- package/{keystroke-agent-authoring → src/keystroke-agent-authoring}/SKILL.md +1 -1
- package/{keystroke-agent-authoring → src/keystroke-agent-authoring}/references/source-map.md +1 -1
- package/{keystroke-agent-authoring → src/keystroke-agent-authoring}/references/testing.md +1 -1
- package/{keystroke-cli-workspace → src/keystroke-cli-workspace}/SKILL.md +1 -1
- package/{keystroke-cli-workspace → src/keystroke-cli-workspace}/references/command-map.md +3 -3
- package/{keystroke-cli-workspace → src/keystroke-cli-workspace}/references/project-lifecycle.md +1 -1
- package/{keystroke-credential-binding → src/keystroke-credential-binding}/SKILL.md +4 -3
- package/{keystroke-credential-binding → src/keystroke-credential-binding}/references/patterns.md +14 -15
- package/{keystroke-credential-binding → src/keystroke-credential-binding}/references/source-map.md +2 -1
- package/{keystroke-task-authoring → src/keystroke-task-authoring}/SKILL.md +4 -6
- package/{keystroke-task-authoring → src/keystroke-task-authoring}/references/patterns.md +7 -7
- package/{keystroke-task-authoring → src/keystroke-task-authoring}/references/source-map.md +4 -5
- package/{keystroke-trigger-authoring → src/keystroke-trigger-authoring}/SKILL.md +26 -20
- package/{keystroke-trigger-authoring → src/keystroke-trigger-authoring}/references/patterns.md +62 -66
- package/src/keystroke-trigger-authoring/references/source-map.md +166 -0
- package/{keystroke-trigger-authoring → src/keystroke-trigger-authoring}/references/testing.md +30 -27
- package/{keystroke-workflow-authoring → src/keystroke-workflow-authoring}/SKILL.md +4 -3
- package/{keystroke-workflow-authoring → src/keystroke-workflow-authoring}/references/patterns.md +6 -6
- package/{keystroke-workflow-authoring → src/keystroke-workflow-authoring}/references/prebuilt-integrations.md +1 -1
- package/{keystroke-workflow-authoring → src/keystroke-workflow-authoring}/references/runtime-helpers.md +2 -2
- package/{keystroke-workflow-authoring → src/keystroke-workflow-authoring}/references/source-map.md +1 -1
- package/{keystroke-workflow-authoring → src/keystroke-workflow-authoring}/references/testing.md +2 -2
- package/keystroke-agent-authoring/evals/evals.json +0 -29
- package/keystroke-cli-workspace/evals/evals.json +0 -23
- package/keystroke-credential-binding/evals/evals.json +0 -29
- package/keystroke-data-toolkit/evals/evals.json +0 -23
- package/keystroke-task-authoring/evals/evals.json +0 -23
- package/keystroke-trigger-authoring/evals/evals.json +0 -29
- package/keystroke-trigger-authoring/references/source-map.md +0 -128
- package/keystroke-workflow-as-tool-debugging/evals/evals.json +0 -23
- package/keystroke-workflow-authoring/evals/evals.json +0 -29
- /package/{keystroke-agent-authoring → src/keystroke-agent-authoring}/references/messaging-gateways.md +0 -0
- /package/{keystroke-agent-authoring → src/keystroke-agent-authoring}/references/patterns.md +0 -0
- /package/{keystroke-agent-authoring → src/keystroke-agent-authoring}/references/prebuilt-integrations.md +0 -0
- /package/{keystroke-agent-authoring → src/keystroke-agent-authoring}/references/sandbox-and-mcp.md +0 -0
- /package/{keystroke-cli-workspace → src/keystroke-cli-workspace}/references/credentials-and-connect.md +0 -0
- /package/{keystroke-credential-binding → src/keystroke-credential-binding}/references/cli.md +0 -0
- /package/{keystroke-data-toolkit → src/keystroke-data-toolkit}/SKILL.md +0 -0
- /package/{keystroke-data-toolkit → src/keystroke-data-toolkit}/references/usage.md +0 -0
- /package/{keystroke-workflow-as-tool-debugging → src/keystroke-workflow-as-tool-debugging}/SKILL.md +0 -0
- /package/{keystroke-workflow-as-tool-debugging → src/keystroke-workflow-as-tool-debugging}/references/playbook.md +0 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# @keystrokehq/skills
|
|
2
|
+
|
|
3
|
+
## 0.0.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a1488f8: Update trigger authoring skills for declarative webhook and polling trigger APIs.
|
|
8
|
+
|
|
9
|
+
## 0.0.5
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- a94a8e3: Rename the packaged Keystroke project context artifact to `_AGENTS.md` while preserving `AGENTS.md` as the destination filename during CLI init and skills sync.
|
|
14
|
+
|
|
15
|
+
## 0.0.4
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- bb9fea0: Fix: Removing callbacks from triggers (except polling)
|
|
20
|
+
|
|
21
|
+
## 0.0.3
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- c4870ce: Update public package references and authoring guidance for the provider-name integration packages.
|
|
26
|
+
|
|
27
|
+
## 0.0.2
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- 761d44e: Add `keystroke workflows run` for manually invoking workflows from a project's current deployment, including input and workflow globals parsing plus wait/follow support.
|
|
32
|
+
|
|
33
|
+
Update Keystroke CLI and workflow authoring skills with guidance for deployed workflow manual runs.
|
|
34
|
+
|
|
35
|
+
## 0.0.1
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- 2ff9004: Publish Keystroke skills as an npm package and let the CLI use its installed skills package as a fallback when syncing skills into projects.
|
package/README.md
CHANGED
|
@@ -19,34 +19,43 @@ The packaged skills are:
|
|
|
19
19
|
|
|
20
20
|
## Editing
|
|
21
21
|
|
|
22
|
-
Edit
|
|
22
|
+
Edit shipped skill content in `packages/skills/src/`.
|
|
23
23
|
|
|
24
|
-
Do not treat local editor skill directories as the source of truth for these packaged skills. Edit the canonical files in `packages/skills/` first, then use the Keystroke CLI skill sync flow when
|
|
24
|
+
Do not treat local editor skill directories as the source of truth for these packaged skills. Edit the canonical files in `packages/skills/src/` first, then use the Keystroke CLI skill sync flow when project-installed skill copies need to be refreshed.
|
|
25
|
+
|
|
26
|
+
Evaluation prompts and notes live in `packages/skills/evals/`. They are repo-only authoring assets and are not published to npm or copied into user projects.
|
|
25
27
|
|
|
26
28
|
## Structure
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
The publishable package content follows this structure:
|
|
29
31
|
|
|
30
32
|
```text
|
|
31
|
-
|
|
32
|
-
├──
|
|
33
|
-
├──
|
|
34
|
-
│ ├──
|
|
35
|
-
│ └──
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
src/
|
|
34
|
+
├── _AGENTS.md
|
|
35
|
+
├── <skill-name>/
|
|
36
|
+
│ ├── SKILL.md
|
|
37
|
+
│ └── references/
|
|
38
|
+
│ ├── source-map.md
|
|
39
|
+
│ └── ...
|
|
40
|
+
└── ...
|
|
38
41
|
```
|
|
39
42
|
|
|
43
|
+
- `src/_AGENTS.md` is the Keystroke project context written or appended to project-root `AGENTS.md` by `keystroke init` and `keystroke skills sync`.
|
|
44
|
+
- The leading underscore keeps the package source artifact from being loaded as repository-local editor context while preserving the destination filename.
|
|
40
45
|
- `SKILL.md` stays concise and procedural.
|
|
41
46
|
- `references/` holds longer examples, source maps, and gotchas.
|
|
42
|
-
- `evals
|
|
47
|
+
- `evals/<skill-name>/evals.json` stores the initial evaluation prompts used with `.agents/skills/skill-creator/`.
|
|
43
48
|
|
|
44
49
|
## Wiring
|
|
45
50
|
|
|
46
|
-
These packaged skills are
|
|
51
|
+
These packaged skills are installed into project agent skill directories through the Keystroke CLI:
|
|
47
52
|
|
|
48
|
-
- packaged skills are authored
|
|
49
|
-
- `keystroke
|
|
53
|
+
- packaged skills are authored in `src/`
|
|
54
|
+
- `keystroke init` always copies them into the canonical project path `.agents/skills`
|
|
55
|
+
- `keystroke init --agent <agent> --method symlink` provisions selected agent-specific paths by linking back to `.agents/skills`
|
|
56
|
+
- `keystroke init --agent <agent> --method copy` provisions selected agent-specific paths with independent copies
|
|
57
|
+
- `keystroke skills sync` refreshes an existing project using the same `--agent` and `--method` flags
|
|
58
|
+
- eval assets stay in `evals/` and are excluded from published packages and synced project skills
|
|
50
59
|
|
|
51
60
|
If the discovery story changes later, update this package and the sync flow together. Until then, edit the packaged skills here first.
|
|
52
61
|
|
|
@@ -57,7 +66,7 @@ Because these are repo-authored local skills rather than externally installed sk
|
|
|
57
66
|
Draft and refine these skills with the existing `.agents/skills/skill-creator/` workflow:
|
|
58
67
|
|
|
59
68
|
1. Draft the skill
|
|
60
|
-
2. Add realistic eval prompts to `evals
|
|
69
|
+
2. Add realistic eval prompts to `evals/<skill-name>/evals.json`
|
|
61
70
|
3. Run at least one evaluation pass
|
|
62
71
|
4. Revise the skill based on results
|
|
63
72
|
5. Improve the `description` once the body is stable
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keystrokehq/skills",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -9,15 +9,8 @@
|
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"README.md",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"keystroke-agent-authoring",
|
|
15
|
-
"keystroke-data-toolkit",
|
|
16
|
-
"keystroke-workflow-as-tool-debugging",
|
|
17
|
-
"keystroke-credential-binding",
|
|
18
|
-
"keystroke-trigger-authoring",
|
|
19
|
-
"keystroke-task-authoring",
|
|
20
|
-
"keystroke-cli-workspace"
|
|
12
|
+
"CHANGELOG.md",
|
|
13
|
+
"src"
|
|
21
14
|
],
|
|
22
15
|
"scripts": {
|
|
23
16
|
"build": "node -e \"process.exit(0)\"",
|
|
@@ -103,7 +103,7 @@ Required structure:
|
|
|
103
103
|
|
|
104
104
|
- exported primitives should be top-level and statically visible
|
|
105
105
|
- helper files such as `schemas.ts`, `utils.ts`, or `prompts.ts` should not export primitives
|
|
106
|
-
- a `*.trigger.ts` file may also export
|
|
106
|
+
- a `*.trigger.ts` file may also export narrowed trigger variants or bound trigger helpers
|
|
107
107
|
- tests are exempt, but authored project code should follow the typed-file convention everywhere
|
|
108
108
|
|
|
109
109
|
Example layout:
|
|
@@ -172,7 +172,7 @@ Teach these rules explicitly:
|
|
|
172
172
|
- Do not use `process.env` in authored agent or tool code.
|
|
173
173
|
- Expect the default agent sandbox to be persistent.
|
|
174
174
|
- Create a custom `Sandbox` only when the default sandbox needs customization.
|
|
175
|
-
- Follow Zod v4 syntax in examples and authored code. See `../../../.agents/
|
|
175
|
+
- Follow Zod v4 syntax in examples and authored code. See `../../../.agents/skills/zod-4/SKILL.md` for deep schema guidance.
|
|
176
176
|
|
|
177
177
|
## Agent Guidelines for Custom Tools & Operations
|
|
178
178
|
|
package/{keystroke-agent-authoring → src/keystroke-agent-authoring}/references/source-map.md
RENAMED
|
@@ -88,7 +88,7 @@ import {
|
|
|
88
88
|
### What they are used for
|
|
89
89
|
|
|
90
90
|
- `credentialSets`: credentials attached directly to the agent
|
|
91
|
-
- `allCredentialSets`: combined credential
|
|
91
|
+
- `allCredentialSets`: combined credential requirements from the agent, its tools, its MCP servers, and its messaging gateways
|
|
92
92
|
- `messaging`: `MessagingGateway[]` conversational entry configuration
|
|
93
93
|
- `runtimeKind`: whether the agent is declarative-only or has `run` / `stream` implementations
|
|
94
94
|
- `workflowSafeReference`: stable reference shape used by other primitives such as `Task`
|
|
@@ -17,7 +17,7 @@ Default testing targets:
|
|
|
17
17
|
|
|
18
18
|
```ts
|
|
19
19
|
import { defineConfig } from 'vitest/config';
|
|
20
|
-
import { keystrokeTestPlugin } from '@keystrokehq/testing
|
|
20
|
+
import { keystrokeTestPlugin } from '@keystrokehq/testing';
|
|
21
21
|
|
|
22
22
|
export default defineConfig({
|
|
23
23
|
plugins: [keystrokeTestPlugin()],
|
|
@@ -87,7 +87,7 @@ Important distinctions:
|
|
|
87
87
|
- Use `keystroke connect <integration>` for official integration connection flows.
|
|
88
88
|
- Use `keystroke credentials ...` for credential inspection and upload flows.
|
|
89
89
|
- Use `keystroke skills sync` to copy `@keystrokehq/skills` into local editor skill directories.
|
|
90
|
-
- Use `keystroke workflows run <authoredWorkflowId>` for deployed-workflow manual invocation; use `
|
|
90
|
+
- Use `keystroke workflows run <authoredWorkflowId>` for deployed-workflow manual invocation; use `keystroke workflows test <workflow>` when testing a temporary build artifact.
|
|
91
91
|
|
|
92
92
|
## References
|
|
93
93
|
|
|
@@ -36,8 +36,8 @@ Root help shows these directly. Subcommand help focuses on the local flags for t
|
|
|
36
36
|
- `projects`: inspect cached project state
|
|
37
37
|
- `connect`: connect official integrations through OAuth
|
|
38
38
|
- `credentials`: list requirements and upload credentials
|
|
39
|
-
- `workflows`: build, validate, inspect, diff, env, logs, paused,
|
|
40
|
-
- `test`: test
|
|
39
|
+
- `workflows`: build, validate, inspect, diff, env, logs, paused, test, run
|
|
40
|
+
- `test`: test agent-callable tools
|
|
41
41
|
- `deploy`: deploy workflows, agents, tasks, or focused targets via `--target <file>`
|
|
42
42
|
- `sync`: local sync operations
|
|
43
43
|
- `skills`: Keystroke skills sync flows
|
|
@@ -47,7 +47,7 @@ Root help shows these directly. Subcommand help focuses on the local flags for t
|
|
|
47
47
|
|
|
48
48
|
- `keystroke workflows logs` is different from `keystroke logs`
|
|
49
49
|
- `keystroke workflows run <authoredWorkflowId>` executes the current deployed workflow snapshot via the workflow execute API; it does not build or upload local code
|
|
50
|
-
- `keystroke workflows
|
|
50
|
+
- `keystroke workflows test <workflow>` builds local code, uploads or references a test bundle, and runs that temporary artifact
|
|
51
51
|
- `keystroke deploy --target <file>` is the focused deploy path
|
|
52
52
|
- many commands support `--json`
|
|
53
53
|
|
package/{keystroke-cli-workspace → src/keystroke-cli-workspace}/references/project-lifecycle.md
RENAMED
|
@@ -77,7 +77,7 @@ keystroke workflows run wf_onboard_user --input '{"email":"user@example.com"}'
|
|
|
77
77
|
|
|
78
78
|
Notes:
|
|
79
79
|
- `workflows run` executes the current deployed snapshot through `client.workflows.execute()` / `POST /api/v1/workflows/execute`
|
|
80
|
-
- it does not build or upload local source; use `workflows
|
|
80
|
+
- it does not build or upload local source; use `workflows test` for temporary local artifact testing
|
|
81
81
|
- pass `--project-id <uuid>` outside a project checkout, otherwise the CLI resolves `projectId` from `keystroke.config.ts`
|
|
82
82
|
- pass `--workflow-globals` or `--workflow-globals-file` when the deployed manifest declares required workflow globals without defaults
|
|
83
83
|
- use `--wait` to poll to a terminal status and `--follow` to poll logs/events while waiting
|
|
@@ -87,7 +87,8 @@ Do not assume one credential location covers every layer. An agent can need prov
|
|
|
87
87
|
|
|
88
88
|
Teach these rules:
|
|
89
89
|
- steps and tools read credentials from `ctx.credentials`
|
|
90
|
-
-
|
|
90
|
+
- polling triggers read credentials from `poll(ctx).credentials` when they attach credential sets
|
|
91
|
+
- webhook filters, webhook idempotency, and workflow trigger transforms are declarative or mapping-only paths and do not receive credentials
|
|
91
92
|
- MCP servers map credentials through `credentialMapper`
|
|
92
93
|
- authored code should not read secrets from `process.env`
|
|
93
94
|
|
|
@@ -117,7 +118,7 @@ This matters for integration authors and when explaining `createOperationFactory
|
|
|
117
118
|
- If `stored` is present, `resolve` must also be present.
|
|
118
119
|
- If `resolve` is present, `stored` must also be present.
|
|
119
120
|
- Use `CredentialSet` instead of env-based secret handling inside authored primitives.
|
|
120
|
-
- Follow Zod v4 syntax in examples and authored code. See `../../../.agents/
|
|
121
|
+
- Follow Zod v4 syntax in examples and authored code. See `../../../.agents/skills/zod-4/SKILL.md` for deep schema guidance.
|
|
121
122
|
- The drawer-label rule is enforced at three layers today: compile-time on a single primitive (`AssertUniqueCredentialSetIds`), build-time across the project (`assertUniqueCredentialDefinitionIds`), and deploy-time schema-drift detection (`detectSchemaDrifts`). Cluster 07 of the reconciled credential plan adds two more layers: construction-time identity registry and vault-row schema fingerprint. You do not need to do anything special in authored code beyond following the rule above.
|
|
122
123
|
|
|
123
124
|
### Vault-row schema mismatch
|
|
@@ -439,6 +440,6 @@ For wider command usage, cross-link to `../keystroke-cli-workspace/SKILL.md`.
|
|
|
439
440
|
## References
|
|
440
441
|
|
|
441
442
|
Read these files as needed:
|
|
442
|
-
- `references/source-map.md` for
|
|
443
|
+
- `references/source-map.md` for public credential APIs
|
|
443
444
|
- `references/cli.md` for the current credential command cookbook
|
|
444
445
|
- `references/patterns.md` for field-by-field code examples
|
package/{keystroke-credential-binding → src/keystroke-credential-binding}/references/patterns.md
RENAMED
|
@@ -410,7 +410,7 @@ drop it from `stored` and have `rotate` return `'needs-reinput'` instead.
|
|
|
410
410
|
- Example: HubSpot's auth-modality normalization — `stored` accepts
|
|
411
411
|
either `ACCESS_TOKEN` (OAuth) or `API_KEY` (private app); `resolve`
|
|
412
412
|
picks whichever is populated and returns `{ HUBSPOT_ACCESS_TOKEN }`.
|
|
413
|
-
Throws when neither is present so a missing credential
|
|
413
|
+
Throws when neither is present so a missing credential becomes
|
|
414
414
|
an actionable resolver error rather than a provider 401. One
|
|
415
415
|
credential set covers both authorization paths; splitting into two
|
|
416
416
|
sets would force every consumer to branch on modality.
|
|
@@ -640,28 +640,27 @@ This attaches credentials directly to the agent and also allows tools on the age
|
|
|
640
640
|
## Trigger usage
|
|
641
641
|
|
|
642
642
|
```ts
|
|
643
|
-
import {
|
|
643
|
+
import { pollingTrigger } from '@keystrokehq/core';
|
|
644
644
|
import { z } from 'zod';
|
|
645
645
|
|
|
646
|
-
export const
|
|
647
|
-
|
|
648
|
-
description: '
|
|
649
|
-
path: '/signed',
|
|
650
|
-
method: 'POST',
|
|
646
|
+
export const crmPolling = pollingTrigger({
|
|
647
|
+
id: 'crm-polling',
|
|
648
|
+
description: 'Polls CRM records with credential-backed API access.',
|
|
651
649
|
credentialSets: [crmCredentials],
|
|
652
|
-
|
|
653
|
-
|
|
650
|
+
schedule: '5m',
|
|
651
|
+
response: z.object({
|
|
652
|
+
records: z.array(z.object({ id: z.string() })),
|
|
654
653
|
}),
|
|
655
|
-
|
|
656
|
-
const
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
}
|
|
654
|
+
poll: async (ctx) => {
|
|
655
|
+
const apiKey = ctx.credentials.crmApi.apiKey;
|
|
656
|
+
return {
|
|
657
|
+
records: [{ id: `record-for-${apiKey}` }],
|
|
658
|
+
};
|
|
660
659
|
},
|
|
661
660
|
});
|
|
662
661
|
```
|
|
663
662
|
|
|
664
|
-
This pattern is useful when
|
|
663
|
+
This pattern is useful when polling logic needs credentials. Webhook triggers do not attach per-trigger credential sets in the current custom/app source model.
|
|
665
664
|
|
|
666
665
|
## MCP server usage
|
|
667
666
|
|
package/{keystroke-credential-binding → src/keystroke-credential-binding}/references/source-map.md
RENAMED
|
@@ -52,7 +52,8 @@ import { CredentialSet } from '@keystrokehq/core';
|
|
|
52
52
|
- `Operation.run(..., ctx).credentials`
|
|
53
53
|
- `Step.run(..., ctx).credentials`
|
|
54
54
|
- `Tool.run(..., ctx).credentials`
|
|
55
|
-
-
|
|
55
|
+
- polling trigger `poll(ctx).credentials`
|
|
56
|
+
- not webhook `filter`, webhook `idempotencyKey`, or workflow trigger `transform`
|
|
56
57
|
- `McpServer.credentialMapper(credentials)`
|
|
57
58
|
|
|
58
59
|
## Important rules
|
|
@@ -22,12 +22,10 @@ import { z } from 'zod';
|
|
|
22
22
|
import { welcomeAgent } from './welcome.agent';
|
|
23
23
|
|
|
24
24
|
const welcomeWebhookTrigger = webhookTrigger({
|
|
25
|
-
|
|
25
|
+
id: 'welcome-webhook',
|
|
26
26
|
description: 'Receives welcome payloads.',
|
|
27
27
|
source: {
|
|
28
28
|
type: 'custom',
|
|
29
|
-
method: 'POST',
|
|
30
|
-
path: '/welcome',
|
|
31
29
|
},
|
|
32
30
|
payload: z.object({
|
|
33
31
|
name: z.string(),
|
|
@@ -40,7 +38,7 @@ export const welcomeWebhookTask = new Task({
|
|
|
40
38
|
description: 'Uses a webhook payload to drive one agent run.',
|
|
41
39
|
agent: welcomeAgent,
|
|
42
40
|
prompt:
|
|
43
|
-
'Write a greeting for this webhook payload: {{trigger.payload}}. Trigger
|
|
41
|
+
'Write a greeting for this webhook payload: {{trigger.payload}}. Trigger id: {{trigger.id}}.',
|
|
44
42
|
triggers: [welcomeWebhookTrigger],
|
|
45
43
|
lifecycle: {
|
|
46
44
|
maxExecutions: 1,
|
|
@@ -80,7 +78,7 @@ Teach these rules:
|
|
|
80
78
|
Teach the supported task prompt variables:
|
|
81
79
|
|
|
82
80
|
- `{{trigger.payload}}`
|
|
83
|
-
- `{{trigger.
|
|
81
|
+
- `{{trigger.id}}`
|
|
84
82
|
- `{{trigger.type}}`
|
|
85
83
|
|
|
86
84
|
Use prompt templating when the agent prompt should include structured trigger context without inventing a separate payload mapping layer.
|
|
@@ -113,7 +111,7 @@ Choose a workflow when:
|
|
|
113
111
|
- Keep each exported task in its own `*.task.ts` file.
|
|
114
112
|
- Keep the referenced agent in its own `*.agent.ts` file.
|
|
115
113
|
- Keep triggers in their own `*.trigger.ts` files.
|
|
116
|
-
- Use Zod v4 syntax in all examples and authored code. See `../../../.agents/
|
|
114
|
+
- Use Zod v4 syntax in all examples and authored code. See `../../../.agents/skills/zod-4/SKILL.md` for deep schema guidance.
|
|
117
115
|
- Keep task prompts explicit about what the agent should do with trigger data.
|
|
118
116
|
|
|
119
117
|
## References
|
|
@@ -10,12 +10,10 @@ import { z } from 'zod';
|
|
|
10
10
|
import { triageAgent } from './triage.agent';
|
|
11
11
|
|
|
12
12
|
const inboundWebhook = webhookTrigger({
|
|
13
|
-
|
|
13
|
+
id: 'inbound-webhook',
|
|
14
14
|
description: 'Receives inbound payloads.',
|
|
15
15
|
source: {
|
|
16
16
|
type: 'custom',
|
|
17
|
-
method: 'POST',
|
|
18
|
-
path: '/inbound',
|
|
19
17
|
},
|
|
20
18
|
payload: z.object({
|
|
21
19
|
message: z.string(),
|
|
@@ -41,7 +39,7 @@ import { z } from 'zod';
|
|
|
41
39
|
import { reportAgent } from './report.agent';
|
|
42
40
|
|
|
43
41
|
const dailyReportTrigger = cronTrigger({
|
|
44
|
-
|
|
42
|
+
id: 'daily-report-trigger',
|
|
45
43
|
description: 'Runs each morning.',
|
|
46
44
|
input: z.object({
|
|
47
45
|
mode: z.literal('daily'),
|
|
@@ -56,7 +54,7 @@ export const dailyReportTask = new Task({
|
|
|
56
54
|
id: 'daily-report-task',
|
|
57
55
|
name: 'Daily Report Task',
|
|
58
56
|
agent: reportAgent,
|
|
59
|
-
prompt: 'Generate the daily report for {{trigger.
|
|
57
|
+
prompt: 'Generate the daily report for {{trigger.id}} using {{trigger.payload}}.',
|
|
60
58
|
triggers: [dailyReportTrigger],
|
|
61
59
|
});
|
|
62
60
|
```
|
|
@@ -69,7 +67,7 @@ import { z } from 'zod';
|
|
|
69
67
|
import { followUpAgent } from './follow-up.agent';
|
|
70
68
|
|
|
71
69
|
const staleTicketPolling = pollingTrigger({
|
|
72
|
-
|
|
70
|
+
id: 'stale-ticket-polling',
|
|
73
71
|
description: 'Polls for stale tickets.',
|
|
74
72
|
schedule: '*/15 * * * *',
|
|
75
73
|
response: z.object({
|
|
@@ -80,7 +78,9 @@ const staleTicketPolling = pollingTrigger({
|
|
|
80
78
|
ticketId: 'ticket_123',
|
|
81
79
|
status: 'stale',
|
|
82
80
|
}),
|
|
83
|
-
filter: (
|
|
81
|
+
filter: z.object({
|
|
82
|
+
status: z.literal('stale'),
|
|
83
|
+
}),
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
export const staleTicketTask = new Task({
|
|
@@ -31,13 +31,12 @@ import { Task, type TaskConfig, type TaskLifecycle } from '@keystrokehq/core';
|
|
|
31
31
|
## `TriggerContext`
|
|
32
32
|
|
|
33
33
|
- `payload`
|
|
34
|
-
- `
|
|
34
|
+
- `id`
|
|
35
35
|
- `type`
|
|
36
36
|
|
|
37
37
|
The current public trigger context `type` values are:
|
|
38
38
|
- `cron`
|
|
39
39
|
- `polling`
|
|
40
|
-
- `provider`
|
|
41
40
|
- `webhook`
|
|
42
41
|
|
|
43
42
|
## Prompt template tokens
|
|
@@ -48,8 +47,8 @@ directly into the `prompt` string — there is no function to call.
|
|
|
48
47
|
|
|
49
48
|
Supported tokens:
|
|
50
49
|
- `{{trigger.payload}}` — resolved to `JSON.stringify` of the trigger payload
|
|
51
|
-
- `{{trigger.
|
|
52
|
-
- `{{trigger.type}}` — resolved to the trigger type (one of `cron`, `polling`, `
|
|
50
|
+
- `{{trigger.id}}` — resolved to the trigger id
|
|
51
|
+
- `{{trigger.type}}` — resolved to the trigger type (one of `cron`, `polling`, `webhook`)
|
|
53
52
|
|
|
54
53
|
Unknown `{{...}}` tokens are left as-is in the resolved prompt.
|
|
55
54
|
|
|
@@ -57,5 +56,5 @@ Unknown `{{...}}` tokens are left as-is in the resolved prompt.
|
|
|
57
56
|
|
|
58
57
|
- tasks reference an agent through `agent`
|
|
59
58
|
- tasks list triggers directly in `triggers`
|
|
60
|
-
- tasks do not
|
|
59
|
+
- tasks do not bind triggers with workflow-style `{ transform }`
|
|
61
60
|
- tasks are deployed through `keystroke deploy` or focused with `keystroke deploy --target <task.task.ts>`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: keystroke-trigger-authoring
|
|
3
|
-
description: Build Keystroke cron, webhook,
|
|
3
|
+
description: Build Keystroke cron, webhook, and polling triggers with @keystrokehq/core. Use when the user wants to author, test, or explain trigger code, including webhook app/custom sources, declarative filter schemas, webhook idempotency config, polling schedules, trigger narrowing, and mapping trigger input into workflows or task-driven agent runs.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Keystroke Trigger Authoring
|
|
@@ -22,12 +22,10 @@ import { webhookTrigger, Workflow } from '@keystrokehq/core';
|
|
|
22
22
|
import { z } from 'zod';
|
|
23
23
|
|
|
24
24
|
export const paymentWebhook = webhookTrigger({
|
|
25
|
-
|
|
25
|
+
id: 'payment-webhook',
|
|
26
26
|
description: 'Receives payment events from an external provider.',
|
|
27
27
|
source: {
|
|
28
28
|
type: 'custom',
|
|
29
|
-
method: 'POST',
|
|
30
|
-
path: '/payments',
|
|
31
29
|
},
|
|
32
30
|
payload: z.object({
|
|
33
31
|
id: z.string(),
|
|
@@ -36,8 +34,13 @@ export const paymentWebhook = webhookTrigger({
|
|
|
36
34
|
amount: z.number(),
|
|
37
35
|
}),
|
|
38
36
|
}),
|
|
39
|
-
filter: (
|
|
40
|
-
|
|
37
|
+
filter: z.object({
|
|
38
|
+
type: z.literal('payment.completed'),
|
|
39
|
+
}),
|
|
40
|
+
idempotencyKey: {
|
|
41
|
+
from: 'payload',
|
|
42
|
+
path: 'id',
|
|
43
|
+
},
|
|
41
44
|
});
|
|
42
45
|
```
|
|
43
46
|
|
|
@@ -69,7 +72,7 @@ import { z } from 'zod';
|
|
|
69
72
|
import { reminderAgent } from './reminder.agent';
|
|
70
73
|
|
|
71
74
|
const dailyReminderTrigger = cronTrigger({
|
|
72
|
-
|
|
75
|
+
id: 'daily-reminder-trigger',
|
|
73
76
|
description: 'Runs every morning.',
|
|
74
77
|
input: z.object({
|
|
75
78
|
mode: z.literal('daily'),
|
|
@@ -84,7 +87,7 @@ export const dailyReminderTask = new Task({
|
|
|
84
87
|
id: 'daily-reminder-task',
|
|
85
88
|
name: 'Daily Reminder Task',
|
|
86
89
|
agent: reminderAgent,
|
|
87
|
-
prompt: 'Send the daily reminder for trigger {{trigger.
|
|
90
|
+
prompt: 'Send the daily reminder for trigger {{trigger.id}}.',
|
|
88
91
|
triggers: [dailyReminderTrigger],
|
|
89
92
|
});
|
|
90
93
|
```
|
|
@@ -97,6 +100,8 @@ Teach this mental model clearly:
|
|
|
97
100
|
- workflow triggers are listed in `Workflow({ triggers: [...] })`
|
|
98
101
|
- a bare trigger in the array means the trigger payload passes through directly as workflow input
|
|
99
102
|
- calling the trigger as a function with `{ transform }` creates a bound trigger for payload-to-input mapping
|
|
103
|
+
- filtering lives on the trigger as a pure Zod schema, or on a narrowed child trigger with `.narrow({ id, filter })`
|
|
104
|
+
- webhook idempotency is declarative config, not a callback
|
|
100
105
|
- task triggers are listed inline in `Task.triggers`
|
|
101
106
|
- a `MessagingGateway` is not a trigger
|
|
102
107
|
|
|
@@ -106,11 +111,10 @@ Teach these public trigger factory functions from `@keystrokehq/core`:
|
|
|
106
111
|
- `cronTrigger`
|
|
107
112
|
- `webhookTrigger`
|
|
108
113
|
- `pollingTrigger`
|
|
109
|
-
- `providerTrigger`
|
|
110
114
|
|
|
111
|
-
|
|
115
|
+
Use webhook triggers with `source: { type: 'app', appRef }` when events are fanned out by a Keystroke-managed provider app. Use `source: { type: 'custom' }` when the platform should create a Keystroke-owned custom webhook surface.
|
|
112
116
|
|
|
113
|
-
The factories return a `CallableTrigger` — an object with trigger properties (`.
|
|
117
|
+
The factories return a `CallableTrigger` — an object with trigger properties (`.id`, `.toManifest()`, etc.) that is also callable as a function to create a bound trigger with optional `transform`. Bindings carry only `transform`; they do not carry filter or idempotency callbacks.
|
|
114
118
|
|
|
115
119
|
## Manual API Execution
|
|
116
120
|
|
|
@@ -140,6 +144,7 @@ Workflow trigger rules:
|
|
|
140
144
|
- list it in `Workflow({ triggers: [...] })`
|
|
141
145
|
- for a bare trigger (no transform), place it directly: `triggers: [myTrigger]`
|
|
142
146
|
- for a bound trigger with transform, call it: `triggers: [myTrigger({ transform: (payload) => ({...}) })]`
|
|
147
|
+
- for per-workflow filtering, attach a narrowed trigger: `triggers: [myTrigger.narrow({ id: '...', filter: z.object({...}) })({ transform })]`
|
|
143
148
|
- test the mapping by creating a bound trigger and calling `bound.transform?.(payload)`
|
|
144
149
|
|
|
145
150
|
## Task triggers
|
|
@@ -156,12 +161,13 @@ Task trigger rules:
|
|
|
156
161
|
## Trigger rules
|
|
157
162
|
|
|
158
163
|
- Keep each exported trigger in its own `*.trigger.ts` file.
|
|
159
|
-
- Use `
|
|
160
|
-
- Use `filter` for event gating
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
-
|
|
164
|
+
- Use `id`, not `name`, as the stable authored trigger identity.
|
|
165
|
+
- Use `filter` for event gating on webhook and polling triggers. It must be a pure Zod schema that can be converted to JSON Schema; do not use `.refine()`, `.superRefine()`, `.transform()`, `.preprocess()`, `.pipe()`, or `z.custom()`.
|
|
166
|
+
- Put conditional logic that cannot be expressed as a pure Zod schema at the start of the workflow body, or behind an integration `mapPayload` helper that throws when the declarative filter was too broad.
|
|
167
|
+
- Use `idempotencyKey` only on webhook triggers. It is declarative config such as `{ from: 'payload', path: 'id' }`, `{ from: 'payload', strategy: 'hash' }`, `{ from: 'header', name: 'x-event-id' }`, or `{ from: 'header', strategy: 'hash' }`.
|
|
168
|
+
- Polling triggers do not support idempotency config.
|
|
169
|
+
- `source: { type: 'custom' }` means the platform owns the HTTP surface and authenticates with a Keystroke-issued secret. Do not add `method`, `path`, `verify`, or `response`.
|
|
170
|
+
- `source: { type: 'app', appRef }` means a Keystroke-managed provider app fans out events centrally.
|
|
165
171
|
|
|
166
172
|
## Agent Guidelines for Custom Triggers
|
|
167
173
|
|
|
@@ -169,13 +175,13 @@ When an agent needs to write custom triggers, it must follow these rules:
|
|
|
169
175
|
1. **Always use prebuilt triggers** if they exist before writing custom ones.
|
|
170
176
|
2. **Collect context first**: Do you have all the information you need from the user to build the trigger? If not, ask the user to clarify what they are looking for. **Do Not Guess**.
|
|
171
177
|
3. **Understand API payloads**: If the trigger handles webhooks or fetches from an API endpoint, search the provider's docs to understand the payloads. If possible, hit available endpoints to inspect the actual payloads.
|
|
172
|
-
4. **Always write and run tests**: You must always write tests for custom triggers that handle non-trivial
|
|
178
|
+
4. **Always write and run tests**: You must always write tests for custom triggers that handle polling logic, payload mapping, or non-trivial filter schemas. Always run the tests to verify that the new triggers run (see `references/testing.md`).
|
|
173
179
|
5. **Handle missing credentials**: If you cannot run tests because of missing credentials, ask the user to configure them following the `../keystroke-credential-binding/SKILL.md` skill. The user will need to upload credentials before deploying anyway.
|
|
174
180
|
|
|
175
181
|
## Testing path
|
|
176
182
|
|
|
177
183
|
Default trigger testing guidance:
|
|
178
|
-
- test
|
|
184
|
+
- test declarative filter and idempotency metadata through `trigger.toManifest().runtime`
|
|
179
185
|
- test webhook parsing with `trigger.payload.parse(JSON.parse(request.rawBody))`
|
|
180
186
|
- test polling validation with `trigger.parseResponse(response)`
|
|
181
187
|
- test workflow input mapping by creating a bound trigger and calling `bound.transform?.(payload)`
|
|
@@ -185,5 +191,5 @@ Default trigger testing guidance:
|
|
|
185
191
|
|
|
186
192
|
Read these files as needed:
|
|
187
193
|
- `references/source-map.md` for the public trigger surface
|
|
188
|
-
- `references/patterns.md` for field-by-field examples, including
|
|
194
|
+
- `references/patterns.md` for field-by-field examples, including webhook app sources
|
|
189
195
|
- `references/testing.md` for trigger and bound trigger tests
|