@keystrokehq/skills 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/AGENTS-blurb.md +123 -0
  2. package/LICENSE +21 -0
  3. package/README.md +63 -0
  4. package/keystroke-agent-authoring/SKILL.md +225 -0
  5. package/keystroke-agent-authoring/evals/evals.json +29 -0
  6. package/keystroke-agent-authoring/references/messaging-gateways.md +242 -0
  7. package/keystroke-agent-authoring/references/patterns.md +417 -0
  8. package/keystroke-agent-authoring/references/prebuilt-integrations.md +879 -0
  9. package/keystroke-agent-authoring/references/sandbox-and-mcp.md +214 -0
  10. package/keystroke-agent-authoring/references/source-map.md +182 -0
  11. package/keystroke-agent-authoring/references/testing.md +85 -0
  12. package/keystroke-cli-workspace/SKILL.md +93 -0
  13. package/keystroke-cli-workspace/evals/evals.json +23 -0
  14. package/keystroke-cli-workspace/references/command-map.md +50 -0
  15. package/keystroke-cli-workspace/references/credentials-and-connect.md +79 -0
  16. package/keystroke-cli-workspace/references/project-lifecycle.md +85 -0
  17. package/keystroke-credential-binding/SKILL.md +509 -0
  18. package/keystroke-credential-binding/evals/evals.json +29 -0
  19. package/keystroke-credential-binding/references/cli.md +85 -0
  20. package/keystroke-credential-binding/references/patterns.md +878 -0
  21. package/keystroke-credential-binding/references/source-map.md +69 -0
  22. package/keystroke-data-toolkit/SKILL.md +59 -0
  23. package/keystroke-data-toolkit/evals/evals.json +23 -0
  24. package/keystroke-data-toolkit/references/usage.md +79 -0
  25. package/keystroke-task-authoring/SKILL.md +124 -0
  26. package/keystroke-task-authoring/evals/evals.json +23 -0
  27. package/keystroke-task-authoring/references/patterns.md +132 -0
  28. package/keystroke-task-authoring/references/source-map.md +61 -0
  29. package/keystroke-trigger-authoring/SKILL.md +189 -0
  30. package/keystroke-trigger-authoring/evals/evals.json +29 -0
  31. package/keystroke-trigger-authoring/references/patterns.md +265 -0
  32. package/keystroke-trigger-authoring/references/source-map.md +128 -0
  33. package/keystroke-trigger-authoring/references/testing.md +148 -0
  34. package/keystroke-workflow-as-tool-debugging/SKILL.md +52 -0
  35. package/keystroke-workflow-as-tool-debugging/evals/evals.json +23 -0
  36. package/keystroke-workflow-as-tool-debugging/references/playbook.md +77 -0
  37. package/keystroke-workflow-authoring/SKILL.md +234 -0
  38. package/keystroke-workflow-authoring/evals/evals.json +29 -0
  39. package/keystroke-workflow-authoring/references/patterns.md +265 -0
  40. package/keystroke-workflow-authoring/references/prebuilt-integrations.md +811 -0
  41. package/keystroke-workflow-authoring/references/runtime-helpers.md +264 -0
  42. package/keystroke-workflow-authoring/references/source-map.md +108 -0
  43. package/keystroke-workflow-authoring/references/testing.md +108 -0
  44. package/package.json +26 -0
@@ -0,0 +1,69 @@
1
+ # Credential Feature Map
2
+
3
+ Use only the public imports a user repo can rely on:
4
+
5
+ ```ts
6
+ import { CredentialSet } from '@keystrokehq/core';
7
+ ```
8
+
9
+ ## `CredentialSet` fields
10
+
11
+ - `id`
12
+ - `namespace`
13
+ - `resolvedCredentialSetId`
14
+ - `name`
15
+ - `description`
16
+ - `auth`
17
+ - `stored`
18
+ - `resolve`
19
+ - `needsResolve`
20
+
21
+ ### What they are used for
22
+
23
+ - `id`: stable credential set identifier
24
+ - `namespace`: optional namespace used for manifest and storage identity
25
+ - `resolvedCredentialSetId`: computed namespaced id used for manifest and binding infrastructure
26
+ - `name`: human-readable name
27
+ - `description`: short explanation of what the credentials are for
28
+ - `auth`: runtime credential schema
29
+ - `stored`: stored credential schema when the stored shape differs from the runtime shape
30
+ - `resolve`: async conversion from stored values to runtime auth values
31
+ - `needsResolve`: tells you whether the credential set uses the stored-plus-resolve flow
32
+
33
+ ## `CredentialSet` instance methods
34
+
35
+ - `describe()`
36
+ - `toManifest()`
37
+
38
+ ## Where a credential set can be attached
39
+
40
+ - `Operation.credentialSets`
41
+ - `Step.credentialSets`
42
+ - `Tool.credentialSets`
43
+ - `Agent.credentialSets`
44
+ - `CronTrigger.credentialSets`
45
+ - `WebhookTrigger.credentialSets`
46
+ - `PollingTrigger.credentialSets`
47
+ - `MessagingGateway.credentialSet`
48
+ - `McpServer.credentialSets`
49
+
50
+ ## Where credentials can be read
51
+
52
+ - `Operation.run(..., ctx).credentials`
53
+ - `Step.run(..., ctx).credentials`
54
+ - `Tool.run(..., ctx).credentials`
55
+ - trigger `verify` callback and polling trigger `poll` callback (`filter`, `idempotencyKey`, and `transform` do not receive credentials)
56
+ - `McpServer.credentialMapper(credentials)`
57
+
58
+ ## Important rules
59
+
60
+ - `Operation`, `Step`, and `Tool` are aliases for the same class
61
+ - if `stored` is present, `resolve` must also be present
62
+ - if `resolve` is present, `stored` must also be present
63
+ - prefer typed access through runtime context rather than ad hoc env access inside primitives
64
+ - runtime credential context keys use raw `id`, not `resolvedCredentialSetId`
65
+
66
+ ## Where to read next
67
+
68
+ - `patterns.md` for code examples
69
+ - `cli.md` for upload and inspection commands
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: keystroke-data-toolkit
3
+ description: Use Keystroke workflow-tool refs and data companion tools. Use when an agent needs to author, explain, debug, or consume large workflow tool outputs with read_ref, slice_ref, describe_ref, truncation metadata, or deferred reducers.
4
+ ---
5
+
6
+ # Keystroke Data Toolkit
7
+
8
+ Use this skill when working with large workflow-tool outputs, ref envelopes, or auto-injected data companion tools.
9
+
10
+ Keep this skill focused on workflow-tool data handling:
11
+ - use `../keystroke-workflow-authoring/SKILL.md` for workflow code and replay-safe orchestration
12
+ - use `../keystroke-agent-authoring/SKILL.md` for agent and tool registration
13
+ - use `../keystroke-workflow-as-tool-debugging/SKILL.md` for debugging a failed workflow-tool run
14
+
15
+ ## Current Product Behavior
16
+
17
+ Workflow tool outputs are capped before they enter LLM context. A workflow that may produce large output should opt into refs:
18
+
19
+ ```ts
20
+ new Workflow({
21
+ id: 'export-audit-data',
22
+ name: 'Export Audit Data',
23
+ largeResultMode: 'ref',
24
+ // ...
25
+ });
26
+ ```
27
+
28
+ When the output exceeds the cap, the platform stores the result and returns a small ref envelope with `inline: false`, a `ref` URI, `mimeType`, `byteSize`, and a summary.
29
+
30
+ ## Companion Tools
31
+
32
+ Agents with workflow tools get bounded ref inspection tools when eligible:
33
+ - `describe_ref` returns shape, size, summary, and available ranges
34
+ - `read_ref` reads a byte, line, or row range
35
+ - `slice_ref` extracts a JSONPath-addressable subset from JSON refs
36
+
37
+ Reads are bounded. If a requested slice is still too large, the response includes truncation metadata such as `truncated: true` and guidance to request a smaller range.
38
+
39
+ ## Rules
40
+
41
+ - Prefer `describe_ref` before reading unknown large refs.
42
+ - Use narrow `read_ref` ranges; do not ask for the full payload by default.
43
+ - Treat `truncated: true` as a signal to request a smaller or more specific range.
44
+ - Keep refs scoped to the current agent run; cross-run access is not supported.
45
+ - Do not add or teach reducer tools as active behavior. Reducers are deferred; reducer calls return unsupported validation guidance.
46
+ - Do not introduce DuckDB or native reducer dependencies unless the product explicitly reopens reducers.
47
+
48
+ ## Default Process
49
+
50
+ 1. Check whether the workflow should use `largeResultMode: 'ref'`.
51
+ 2. Inspect the ref with `describe_ref`.
52
+ 3. Read only the smallest useful slice with `read_ref` or `slice_ref`.
53
+ 4. If truncated, narrow the request and try again.
54
+ 5. If computation over large tabular refs is needed, explain that reducers are currently deferred and use bounded samples instead.
55
+
56
+ ## References
57
+
58
+ Read these files as needed:
59
+ - `references/usage.md` for examples of ref envelopes and companion tool usage
@@ -0,0 +1,23 @@
1
+ {
2
+ "skill_name": "keystroke-data-toolkit",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "My workflow tool can return a few megabytes of audit rows. How should I configure the workflow and how should the agent inspect the result?",
7
+ "expected_output": "Recommends largeResultMode: 'ref', explains the ref envelope, and uses describe_ref/read_ref/slice_ref with bounded ranges.",
8
+ "files": []
9
+ },
10
+ {
11
+ "id": 2,
12
+ "prompt": "The agent called read_ref and got truncated: true. What should it do next?",
13
+ "expected_output": "Explains that truncation is signaled and the agent should request a narrower range or targeted slice rather than assuming it saw all data.",
14
+ "files": []
15
+ },
16
+ {
17
+ "id": 3,
18
+ "prompt": "Can we add DuckDB reducers for this large CSV workflow output?",
19
+ "expected_output": "States that reducers and DuckDB are deferred in the active product and recommends bounded ref reads or samples instead.",
20
+ "files": []
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,79 @@
1
+ # Data Toolkit Usage
2
+
3
+ Read this file when the user needs concrete patterns for large workflow-tool outputs.
4
+
5
+ ## Ref-Producing Workflow
6
+
7
+ ```ts
8
+ import { Workflow } from '@keystrokehq/core';
9
+ import { z } from 'zod';
10
+
11
+ export const exportAuditData = new Workflow({
12
+ id: 'export-audit-data',
13
+ name: 'Export Audit Data',
14
+ description: 'Exports audit rows for an account.',
15
+ largeResultMode: 'ref',
16
+ input: z.object({
17
+ accountId: z.string(),
18
+ }),
19
+ output: z.array(
20
+ z.object({
21
+ accountId: z.string(),
22
+ eventType: z.string(),
23
+ createdAt: z.string(),
24
+ })
25
+ ),
26
+ run: async () => [],
27
+ });
28
+ ```
29
+
30
+ Use `largeResultMode: 'ref'` when large output is legitimate and useful. Do not use refs to hide unbounded or poorly scoped workflows; prefer narrower workflow inputs when possible.
31
+
32
+ ## Ref Envelope
33
+
34
+ The LLM receives a small envelope instead of the full output:
35
+
36
+ ```json
37
+ {
38
+ "inline": false,
39
+ "ref": "blob://run/wfr_abc/output",
40
+ "mimeType": "application/json",
41
+ "byteSize": 1048576,
42
+ "summary": {
43
+ "kind": "tabular",
44
+ "rows": 10000,
45
+ "columns": [
46
+ { "name": "accountId", "type": "string", "nullPct": 0 },
47
+ { "name": "eventType", "type": "string", "nullPct": 0 }
48
+ ]
49
+ }
50
+ }
51
+ ```
52
+
53
+ ## Recommended Agent Flow
54
+
55
+ 1. Call the workflow tool.
56
+ 2. If the result has `inline: false`, call `describe_ref({ ref })`.
57
+ 3. Read a small sample such as `read_ref({ ref, rowRange: [0, 20] })`.
58
+ 4. Use `slice_ref` for targeted JSONPath extraction from JSON refs.
59
+ 5. If a response is truncated, reduce the requested range.
60
+
61
+ ## Bounded Reads
62
+
63
+ Good requests are specific:
64
+
65
+ ```json
66
+ { "ref": "blob://run/wfr_abc/output", "rowRange": [0, 25] }
67
+ ```
68
+
69
+ Avoid full-payload reads:
70
+
71
+ ```json
72
+ { "ref": "blob://run/wfr_abc/output", "rowRange": [0, 1000000] }
73
+ ```
74
+
75
+ If a read returns `truncated: true`, the agent should not summarize as if it saw all data. It should either request a smaller range or explain that it has inspected only a sample.
76
+
77
+ ## Deferred Reducers
78
+
79
+ Reducer tools are not part of the active product. Do not teach agents to call `reduce_ref`, `query_ref`, SQL-over-ref tools, or DuckDB-backed helpers. If a reducer-shaped payload appears, expect unsupported validation guidance and fall back to bounded reads and samples.
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: keystroke-task-authoring
3
+ description: Build Keystroke tasks with @keystrokehq/core. Use when the user wants to author a trigger-driven agent task, define task prompts with trigger templates, configure task lifecycle, or run focused task deploys instead of full workflows.
4
+ ---
5
+
6
+ # Keystroke Task Authoring
7
+
8
+ Use this skill when an agent needs to write or change Keystroke task code.
9
+
10
+ Keep this skill focused on authored task code:
11
+
12
+ - use `../keystroke-agent-authoring/SKILL.md` for the agent itself
13
+ - use `../keystroke-trigger-authoring/SKILL.md` for trigger authoring details
14
+ - use `../keystroke-workflow-authoring/SKILL.md` when the automation needs durable orchestration
15
+ - use `../keystroke-cli-workspace/SKILL.md` for `deploy --target`, build, and debugging flows
16
+
17
+ ## Quick start
18
+
19
+ ```ts
20
+ import { Task, webhookTrigger } from '@keystrokehq/core';
21
+ import { z } from 'zod';
22
+ import { welcomeAgent } from './welcome.agent';
23
+
24
+ const welcomeWebhookTrigger = webhookTrigger({
25
+ name: 'Welcome Webhook',
26
+ description: 'Receives welcome payloads.',
27
+ source: {
28
+ type: 'custom',
29
+ method: 'POST',
30
+ path: '/welcome',
31
+ },
32
+ payload: z.object({
33
+ name: z.string(),
34
+ }),
35
+ });
36
+
37
+ export const welcomeWebhookTask = new Task({
38
+ id: 'welcome-webhook-task',
39
+ name: 'Welcome Webhook Task',
40
+ description: 'Uses a webhook payload to drive one agent run.',
41
+ agent: welcomeAgent,
42
+ prompt:
43
+ 'Write a greeting for this webhook payload: {{trigger.payload}}. Trigger name: {{trigger.name}}.',
44
+ triggers: [welcomeWebhookTrigger],
45
+ lifecycle: {
46
+ maxExecutions: 1,
47
+ },
48
+ tags: ['welcome', 'webhook', 'task'],
49
+ });
50
+ ```
51
+
52
+ ## Authoring model
53
+
54
+ Teach this mental model clearly:
55
+
56
+ - a task is a trigger-driven agent run
57
+ - a task combines an `agent`, a `prompt`, and one or more `triggers`
58
+ - a task is not a workflow-lite wrapper
59
+ - a task does not replace a workflow when durable orchestration is needed
60
+
61
+ Use a task when the real job is:
62
+
63
+ - external event or schedule arrives
64
+ - prompt is resolved from trigger context
65
+ - agent runs once for that task execution
66
+
67
+ ## Trigger model
68
+
69
+ Task triggers are authored as normal triggers but attached differently than workflow triggers.
70
+
71
+ Teach these rules:
72
+
73
+ - define the trigger normally in `*.trigger.ts`
74
+ - place the trigger in `Task.triggers`
75
+ - do not call `trigger.attach(task, ...)`
76
+ - use workflow attachments only for workflows
77
+
78
+ ## Prompt templating
79
+
80
+ Teach the supported task prompt variables:
81
+
82
+ - `{{trigger.payload}}`
83
+ - `{{trigger.name}}`
84
+ - `{{trigger.type}}`
85
+
86
+ Use prompt templating when the agent prompt should include structured trigger context without inventing a separate payload mapping layer.
87
+
88
+ ## Lifecycle
89
+
90
+ Use task lifecycle when execution limits matter:
91
+
92
+ - `maxExecutions`
93
+ - `expiresAt`
94
+ - `expiresAfter`
95
+
96
+ ## Task vs workflow
97
+
98
+ Choose a task when:
99
+
100
+ - the automation is one agent run driven by triggers
101
+ - the user wants a prompt-first agent execution path
102
+ - durable workflow orchestration is not the main requirement
103
+
104
+ Choose a workflow when:
105
+
106
+ - the automation needs multiple steps
107
+ - the automation needs waits or hooks
108
+ - the automation needs branching or child workflows
109
+ - the automation coordinates multiple agents or agent-plus-step flows
110
+
111
+ ## Task rules
112
+
113
+ - Keep each exported task in its own `*.task.ts` file.
114
+ - Keep the referenced agent in its own `*.agent.ts` file.
115
+ - Keep triggers in their own `*.trigger.ts` files.
116
+ - Use Zod v4 syntax in all examples and authored code. See `../../../.agents/rules/zod-v4-requirements.md`.
117
+ - Keep task prompts explicit about what the agent should do with trigger data.
118
+
119
+ ## References
120
+
121
+ Read these files as needed:
122
+
123
+ - `references/source-map.md` for the public task surface
124
+ - `references/patterns.md` for task examples and the task-vs-workflow decision guide
@@ -0,0 +1,23 @@
1
+ {
2
+ "skill_name": "keystroke-task-authoring",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "I want a Keystroke task that runs an agent every time a webhook fires and includes the webhook payload in the prompt. How should I author that?",
7
+ "expected_output": "Explains Task authoring, inline triggers, prompt templating with trigger context, and keeps workflow attachments out of the task path.",
8
+ "files": []
9
+ },
10
+ {
11
+ "id": 2,
12
+ "prompt": "Should this be a workflow or a task? The job is just: cron fires, agent writes a summary, then stop.",
13
+ "expected_output": "Chooses Task, explains why the task model fits better than workflow orchestration, and mentions deploy --target for focused task deploys.",
14
+ "files": []
15
+ },
16
+ {
17
+ "id": 3,
18
+ "prompt": "How do I limit a Keystroke task to run once and expire after a week?",
19
+ "expected_output": "Explains task lifecycle fields such as maxExecutions and expiresAfter with authored code examples.",
20
+ "files": []
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,132 @@
1
+ # Task Patterns
2
+
3
+ Read this file when the user wants concrete task-authoring examples.
4
+
5
+ ## Webhook-driven task
6
+
7
+ ```ts
8
+ import { Task, webhookTrigger } from '@keystrokehq/core';
9
+ import { z } from 'zod';
10
+ import { triageAgent } from './triage.agent';
11
+
12
+ const inboundWebhook = webhookTrigger({
13
+ name: 'Inbound Webhook',
14
+ description: 'Receives inbound payloads.',
15
+ source: {
16
+ type: 'custom',
17
+ method: 'POST',
18
+ path: '/inbound',
19
+ },
20
+ payload: z.object({
21
+ message: z.string(),
22
+ priority: z.enum(['low', 'high']),
23
+ }),
24
+ });
25
+
26
+ export const inboundTask = new Task({
27
+ id: 'inbound-task',
28
+ name: 'Inbound Task',
29
+ agent: triageAgent,
30
+ prompt:
31
+ 'Triage this inbound payload: {{trigger.payload}}. Trigger type: {{trigger.type}}.',
32
+ triggers: [inboundWebhook],
33
+ });
34
+ ```
35
+
36
+ ## Cron-driven task
37
+
38
+ ```ts
39
+ import { cronTrigger, Task } from '@keystrokehq/core';
40
+ import { z } from 'zod';
41
+ import { reportAgent } from './report.agent';
42
+
43
+ const dailyReportTrigger = cronTrigger({
44
+ name: 'Daily Report Trigger',
45
+ description: 'Runs each morning.',
46
+ input: z.object({
47
+ mode: z.literal('daily'),
48
+ }),
49
+ payload: {
50
+ mode: 'daily',
51
+ },
52
+ schedule: '0 9 * * *',
53
+ });
54
+
55
+ export const dailyReportTask = new Task({
56
+ id: 'daily-report-task',
57
+ name: 'Daily Report Task',
58
+ agent: reportAgent,
59
+ prompt: 'Generate the daily report for {{trigger.name}} using {{trigger.payload}}.',
60
+ triggers: [dailyReportTrigger],
61
+ });
62
+ ```
63
+
64
+ ## Polling-driven task
65
+
66
+ ```ts
67
+ import { pollingTrigger, Task } from '@keystrokehq/core';
68
+ import { z } from 'zod';
69
+ import { followUpAgent } from './follow-up.agent';
70
+
71
+ const staleTicketPolling = pollingTrigger({
72
+ name: 'Stale Ticket Polling',
73
+ description: 'Polls for stale tickets.',
74
+ schedule: '*/15 * * * *',
75
+ response: z.object({
76
+ ticketId: z.string(),
77
+ status: z.string(),
78
+ }),
79
+ poll: async () => ({
80
+ ticketId: 'ticket_123',
81
+ status: 'stale',
82
+ }),
83
+ filter: (payload) => payload.status === 'stale',
84
+ });
85
+
86
+ export const staleTicketTask = new Task({
87
+ id: 'stale-ticket-task',
88
+ name: 'Stale Ticket Task',
89
+ agent: followUpAgent,
90
+ prompt: 'Follow up on stale ticket data: {{trigger.payload}}.',
91
+ triggers: [staleTicketPolling],
92
+ });
93
+ ```
94
+
95
+ ## Lifecycle examples
96
+
97
+ ```ts
98
+ lifecycle: {
99
+ maxExecutions: 1,
100
+ }
101
+ ```
102
+
103
+ ```ts
104
+ lifecycle: {
105
+ expiresAfter: '7d',
106
+ }
107
+ ```
108
+
109
+ ```ts
110
+ lifecycle: {
111
+ expiresAt: new Date('2026-12-31T23:59:59.000Z'),
112
+ }
113
+ ```
114
+
115
+ ## Task vs workflow
116
+
117
+ Choose a task when:
118
+ - the job is one agent run from trigger input
119
+ - prompt templating is the main input mapping layer
120
+ - there is no need for durable orchestration across multiple steps
121
+
122
+ Choose a workflow when:
123
+ - the automation has multiple step boundaries
124
+ - waits or hooks are required
125
+ - orchestration logic is as important as the agent run
126
+ - the automation mixes steps, child workflows, and agents
127
+
128
+ ## Gotchas
129
+
130
+ - Do not use `trigger.attach(...)` for tasks.
131
+ - Do not explain tasks as conversation entrypoints. Messaging gateways handle conversations.
132
+ - Do not move workflow orchestration into the task prompt.
@@ -0,0 +1,61 @@
1
+ # Task Feature Map
2
+
3
+ Use only the public imports a user repo can rely on:
4
+
5
+ ```ts
6
+ import { Task, type TaskConfig, type TaskLifecycle } from '@keystrokehq/core';
7
+ ```
8
+
9
+ ## `Task` fields
10
+
11
+ - `id`
12
+ - `name`
13
+ - `description`
14
+ - `agent`
15
+ - `prompt`
16
+ - `triggers`
17
+ - `lifecycle`
18
+ - `tags`
19
+
20
+ ## `Task` instance methods
21
+
22
+ - `describe()`
23
+ - `toManifest()`
24
+
25
+ ## `TaskLifecycle`
26
+
27
+ - `maxExecutions`
28
+ - `expiresAt`
29
+ - `expiresAfter`
30
+
31
+ ## `TriggerContext`
32
+
33
+ - `payload`
34
+ - `name`
35
+ - `type`
36
+
37
+ The current public trigger context `type` values are:
38
+ - `cron`
39
+ - `polling`
40
+ - `provider`
41
+ - `webhook`
42
+
43
+ ## Prompt template tokens
44
+
45
+ Task prompts support a small set of template tokens that the platform resolves
46
+ at run time (just before the agent is invoked). Authors write the tokens
47
+ directly into the `prompt` string — there is no function to call.
48
+
49
+ Supported tokens:
50
+ - `{{trigger.payload}}` — resolved to `JSON.stringify` of the trigger payload
51
+ - `{{trigger.name}}` — resolved to the trigger name
52
+ - `{{trigger.type}}` — resolved to the trigger type (one of `cron`, `polling`, `provider`, `webhook`)
53
+
54
+ Unknown `{{...}}` tokens are left as-is in the resolved prompt.
55
+
56
+ ## Task notes
57
+
58
+ - tasks reference an agent through `agent`
59
+ - tasks list triggers directly in `triggers`
60
+ - tasks do not use `TriggerAttachment`
61
+ - tasks are deployed through `keystroke deploy` or focused with `keystroke deploy --target <task.task.ts>`