@keystrokehq/cli 0.1.26 → 0.1.27
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.
|
@@ -6,7 +6,7 @@ You are editing a **keystroke project** in a remote workspace via MCP. Author un
|
|
|
6
6
|
|
|
7
7
|
Use MCP tools to work on the project: `read_file`, `write_file`, `edit_file`, `list_files`, `delete_file`, `exec_command`, and `deploy_project`. Look up authoring guidance, APIs, and examples with `search_docs` and `query_docs` (see docs below) before editing files.
|
|
8
8
|
|
|
9
|
-
The **keystroke platform** is the hosted control plane. After you change code, run `deploy_project` to build and upload; that activates the cloud runtime. A project is a single live runtime — a deploy replaces what's running on that project (there's no separate dev and prod within one project), so use filtered deploys and `@keystroke ignore` to iterate quickly.
|
|
9
|
+
The **keystroke platform** is the hosted control plane and the shared web workspace where your user works — viewing workflows on a canvas, chatting with agents, inspecting runs, and managing credentials. After you change code, run `deploy_project` to build and upload; that activates the cloud runtime. A project is a single live runtime — a deploy replaces what's running on that project (there's no separate dev and prod within one project), so use filtered deploys and `@keystroke ignore` to iterate quickly.
|
|
10
10
|
|
|
11
11
|
## What you build
|
|
12
12
|
|
|
@@ -1,148 +1,267 @@
|
|
|
1
1
|
# keystroke
|
|
2
2
|
|
|
3
|
-
This codebase is a Keystroke project.
|
|
3
|
+
This codebase is a Keystroke project. Keystroke is a code-first AI automation platform. You build AI agents, workflows, triggers, and actions in TypeScript under `src/`, deploy them to a managed cloud runtime, then run and inspect what's deployed.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
You are the user's AI automation engineer, the coding agent that builds and maintains this project. Read `src/` first (existing agents, workflows, actions, and triggers). Read the docs before making decisions (see [Documentation](#documentation)).
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Connect to thousands of integrations:** Keystroke has over 1,000 built-in integrations (Slack, Google, Linear, and hundreds more). It is also extremely easy to quickly build a connection for any HTTP API (including private internal APIs) or MCP server.
|
|
9
|
-
- **Deploy what you build:** The Keystroke platform gives teams a managed workspace to run what they build. Deploy agents and workflows from your project. Then, view workflows on an interactive canvas, chat with agents in a chat interface, inspect runs, manage credentials, and collaborate from a shared web platform.
|
|
7
|
+
## Match the user's level
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
Your user may or may not be technical. Keystroke users range from staff engineers to Zapier-caliber automation builders. You are the medium through which they build.
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
- **Mirror their voice.** Only get as technical as the user does. Match their vocabulary.
|
|
12
|
+
- **Narrate in outcomes, not plumbing.** Default to "I'll set this to run every morning and message you a summary", not "deploying the cron trigger to the runtime." Don't surface internal concepts (build artifacts, event logs, correlation IDs, filtered deploys) unless the user has to make a decision about one.
|
|
13
|
+
- **Don't hand them the work.** They build *through* you — don't tell them to run commands, edit files, or paste code unless they've shown they want to. Do it yourself, do it quickly, and report the result.
|
|
14
|
+
- **Simplify the talk, never the work.** Speaking plainly doesn't lower the bar — follow every invariant in this guide regardless of how the user communicates.
|
|
15
|
+
- **If the end-state isn't clear, just ask.** It's okay to clarify how the thing you're building should be built, which integrations to use, etc.
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
## Local codebase vs platform project
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
- **Platform project**: an org-owned cloud record: a deploy target plus a hosted runtime (its own keystroke server, URL, managed credentials). Projects are inactive until their first deploy.
|
|
19
|
+
Keystroke separates *where you write code* from *where it runs*:
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
| | What it is | Lives |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| **Local codebase** | This directory — `keystroke.config.ts` + `src/`. Source of truth. | Your machine / Git |
|
|
24
|
+
| **Platform project** | Org-owned cloud runtime (its own server, URL, credentials, run history). Inactive until first deploy. | Keystroke cloud |
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
`keystroke deploy` builds `src/`, uploads it, and promotes it as the project's single live runtime. A deploy replaces what's running — there is no separate dev and prod within one project.
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
### The web platform
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
Once deployed, your user works in the **web platform** — a shared workspace where they view workflows on an interactive canvas, use agents in a chat interface, inspect runs and traces, manage credentials, and collaborate with teammates. Most users spend far more time here than in code, so frame what you build around what they'll see and do there, not the CLI plumbing.
|
|
31
|
+
|
|
32
|
+
### Project layout
|
|
33
|
+
|
|
34
|
+
Keystroke discovers everything under `src/` by convention.
|
|
27
35
|
|
|
28
36
|
```
|
|
29
37
|
my-app/
|
|
30
|
-
keystroke.config.ts
|
|
38
|
+
keystroke.config.ts # project configuration
|
|
31
39
|
src/
|
|
32
|
-
agents/
|
|
33
|
-
actions/
|
|
34
|
-
workflows/
|
|
35
|
-
triggers/
|
|
36
|
-
skills/
|
|
37
|
-
files/
|
|
38
|
-
AGENTS.md
|
|
40
|
+
agents/ # LLM agents
|
|
41
|
+
actions/ # reusable leaf units of work
|
|
42
|
+
workflows/ # multi-step automations
|
|
43
|
+
triggers/ # schedules, webhooks, app events
|
|
44
|
+
skills/ # runtime playbooks for agents
|
|
45
|
+
files/ # context files attached to agents
|
|
46
|
+
AGENTS.md # this guide
|
|
39
47
|
```
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Each primitive imports from `@keystrokehq/keystroke/<piece>` (`/action`, `/agent`, `/workflow`, `/trigger`, `/app`); integrations are their own `@keystrokehq/<slug>` packages. The example files in `src/` show the exact imports.
|
|
49
|
+
Each primitive imports from `@keystrokehq/keystroke/<piece>` (`/agent`, `/action`, `/workflow`, `/trigger`, `/sandbox`). Integrations are `@keystrokehq/<slug>` packages.
|
|
44
50
|
|
|
45
|
-
##
|
|
51
|
+
## The deploy-first loop
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
Keystroke is deploy-first: build, ship, then run and inspect what's live. Deploy often.
|
|
48
54
|
|
|
49
|
-
|
|
55
|
+
1. **Auth once** — `keystroke auth login` (token is stored and reused).
|
|
56
|
+
2. **Edit** primitives under `src/`.
|
|
57
|
+
3. **Deploy** — `keystroke deploy` (full) or `keystroke deploy --filter agents/support` (one module).
|
|
58
|
+
4. **Run** — `keystroke workflow run <slug> --input '{...}'` / `keystroke agent prompt <slug> --message "..."`.
|
|
59
|
+
5. **Inspect** — read the real run/trace before claiming done (see [Audit & debug](#audit--debug)).
|
|
60
|
+
6. Repeat.
|
|
50
61
|
|
|
51
62
|
```bash
|
|
52
|
-
keystroke auth status
|
|
53
|
-
keystroke
|
|
54
|
-
keystroke
|
|
55
|
-
keystroke
|
|
56
|
-
keystroke
|
|
57
|
-
|
|
63
|
+
keystroke auth status # current user + org
|
|
64
|
+
keystroke project list # your platform projects
|
|
65
|
+
keystroke deploy # build + ship src/ (first deploy must be full)
|
|
66
|
+
keystroke workflow run greeting --input '{"name":"Ada"}' # run a workflow
|
|
67
|
+
keystroke agent prompt hello --message "Hi" # prompt an agent
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
New project: `keystroke init my-app --yes`, then deploy. Join an existing cloud project: `keystroke pull --project <slug>`.
|
|
71
|
+
|
|
72
|
+
## Choosing a primitive
|
|
73
|
+
|
|
74
|
+
| Build a… | When |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| **Agent** | The path isn't fixed — needs judgment, tool use, language, or multi-turn context. Or when a user is explicitly asking you to build an agent (e.g. AI data analyst for use in Slack, support agent, etc) |
|
|
77
|
+
| **Workflow** | You know the order of steps and want durability and predictability. |
|
|
78
|
+
| **Action** | A single reusable capability (an API call, a computation) used by workflows or agents. |
|
|
79
|
+
| **Trigger** | Something should start a workflow/agent automatically — schedule, webhook, or poll. |
|
|
80
|
+
|
|
81
|
+
Generally, prefer a workflow (or a plain action / LLM step) unless the path genuinely varies at runtime. Reach for an agent only when the user is clearly asking you to build one or when the work needs judgment, tool selection, or multi-turn context — not just because it's easier to wire up. Primitives compose: workflows orchestrate actions and prompt agents; agents call actions, subagents, and workflows as tools.
|
|
82
|
+
|
|
83
|
+
## Building blocks
|
|
84
|
+
|
|
85
|
+
### Agent — `defineAgent`
|
|
86
|
+
|
|
87
|
+
Required: `slug`, `systemPrompt`, `model`. Everything else is optional.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { defineAgent } from "@keystrokehq/keystroke/agent";
|
|
91
|
+
|
|
92
|
+
export default defineAgent({
|
|
93
|
+
slug: "support",
|
|
94
|
+
systemPrompt: "You are a helpful support assistant. Answer concisely.",
|
|
95
|
+
model: "anthropic/claude-sonnet-4.6",
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- **Model** — exact catalog id in `vendor/model-id` format from https://keystroke.ai/models.md. Do **not** kebab-case the version (`anthropic/claude-sonnet-4.6` is valid; `...-4-6` fails at deploy).
|
|
100
|
+
- **Tools** — attach actions, subagents, workflows, and MCP tools directly in `tools: [...]`. Do **not** hand-roll a `defineTool` + `executeWorkflow()` wrapper. A subagent's tool name is its `slug` and takes a `message`.
|
|
101
|
+
- **Built in**: isolated `/workspace` with file + `bash` tools, session + persistent memory (`memory: false` to disable), `web_search`/`web_fetch` when configured, self-scheduling tools.
|
|
102
|
+
- **Credentials** are declared on actions, not agents — the agent gets them by calling those actions as tools.
|
|
103
|
+
- **Sandbox** — default in-process bash covers most needs. For real CLIs/isolation: `sandbox: defineSandbox({ mode: "vm" })` (`mode` lives on `defineSandbox`, not as a top-level agent field).
|
|
104
|
+
|
|
105
|
+
### Workflow — `defineWorkflow`
|
|
106
|
+
|
|
107
|
+
Global `slug`, typed Zod `input`/`output`, a normal `async` `run`.
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { defineWorkflow } from "@keystrokehq/keystroke/workflow";
|
|
111
|
+
import { z } from "zod";
|
|
112
|
+
|
|
113
|
+
export default defineWorkflow({
|
|
114
|
+
slug: "signup-pipeline",
|
|
115
|
+
input: z.object({ name: z.string(), email: z.string().email() }),
|
|
116
|
+
output: z.object({ brief: z.string() }),
|
|
117
|
+
async run(input) {
|
|
118
|
+
const { brief } = await researchSignup.run(input);
|
|
119
|
+
await postBrief.run({ text: brief });
|
|
120
|
+
return { brief };
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
| Step | Syntax |
|
|
126
|
+
| --- | --- |
|
|
127
|
+
| Action | `await action.run(input)` |
|
|
128
|
+
| Agent | `await agent.prompt({ message })` |
|
|
129
|
+
| One-shot LLM | `await promptLlm(prompt, { model, outputSchema? })` |
|
|
130
|
+
| Sub-workflow | `await otherWorkflow.run(input)` — never pass `ctx` |
|
|
131
|
+
| Durable sleep | `await ctx.sleep("1h")` |
|
|
132
|
+
| Durable wait | `await ctx.hook<T>()` |
|
|
133
|
+
|
|
134
|
+
`ctx` is the second `run` argument (`async run(input, ctx)`) — add it only when a step needs `ctx.sleep`/`ctx.hook`.
|
|
135
|
+
|
|
136
|
+
Use `promptLlm(...)` (import from `@keystrokehq/keystroke/workflow`) for one-shot generation/classification. Use `agent.prompt(...)` when the step needs tools, memory, or multi-turn reasoning.
|
|
137
|
+
|
|
138
|
+
**Durability** — completed steps replay on retry: keep side effects inside steps; make steps idempotent; keep control flow deterministic (no `Date.now()` / randomness); pin `.stepId()` when the step set can change. `ctx.sleep`/`ctx.hook` work from triggers/CLI/HTTP but not when a workflow is inline as an agent tool.
|
|
139
|
+
|
|
140
|
+
### Action — `defineAction`
|
|
141
|
+
|
|
142
|
+
Leaf unit — **never calls another action** (yours or an integration's). Enforced at runtime and by lint.
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import { defineAction } from "@keystrokehq/keystroke/action";
|
|
146
|
+
import { z } from "zod";
|
|
147
|
+
|
|
148
|
+
export const triage = defineAction({
|
|
149
|
+
slug: "triage",
|
|
150
|
+
input: z.object({ message: z.string() }),
|
|
151
|
+
output: z.object({ priority: z.enum(["low", "normal", "high", "urgent"]) }),
|
|
152
|
+
run: async (input) => ({ priority: /urgent/i.test(input.message) ? "urgent" : "normal" }),
|
|
153
|
+
});
|
|
58
154
|
```
|
|
59
155
|
|
|
60
|
-
|
|
156
|
+
Compose in workflows. Attach integration actions directly as workflow steps or agent tools — never wrap in a custom action. An action *may* call an agent (`await agent.prompt(...)`).
|
|
157
|
+
|
|
158
|
+
### Trigger — source + `.attach()`
|
|
61
159
|
|
|
62
|
-
|
|
160
|
+
Exactly three sources: `defineCronSource`, `defineWebhookSource`, `definePollSource`. Default-export the attached result.
|
|
63
161
|
|
|
64
|
-
|
|
162
|
+
```ts
|
|
163
|
+
import { defineWebhookSource } from "@keystrokehq/keystroke/trigger";
|
|
164
|
+
import { z } from "zod";
|
|
165
|
+
import workflow from "../workflows/signup-pipeline";
|
|
65
166
|
|
|
66
|
-
|
|
167
|
+
export default defineWebhookSource({
|
|
168
|
+
slug: "signup",
|
|
169
|
+
endpoint: "signup",
|
|
170
|
+
request: z.object({ name: z.string(), email: z.string().email() }),
|
|
171
|
+
}).attach({ workflow });
|
|
172
|
+
```
|
|
67
173
|
|
|
68
|
-
|
|
174
|
+
| Source | Use when |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| **Schedule** (`defineCronSource`) | Time alone starts the run (cron is UTC in prod). Passes `{}` — workflow `input` must accept an empty object. |
|
|
177
|
+
| **Webhook** (`defineWebhookSource`) | Another system pushes events. Best option when available. |
|
|
178
|
+
| **Poll** (`definePollSource`) | Keystroke must pull/check an external system on a schedule. |
|
|
69
179
|
|
|
70
|
-
|
|
180
|
+
Filters live on the source; `transform` lives on the workflow attachment. Agents use `.attach({ agent, prompt })` (not `transform`). Attachment id: `{sourceSlug}:{targetSlug}`.
|
|
71
181
|
|
|
72
|
-
|
|
73
|
-
| -------------------- | --------------------------------------------------- |
|
|
74
|
-
| **Instructions** | `systemPrompt` tells the model how to behave |
|
|
75
|
-
| **Models** | `model` uses `vendor/model-id`, with optional `thinkingLevel` |
|
|
76
|
-
| **File system** | Each session gets a `/workspace` with a built-in file system and bash (code execution) tools |
|
|
77
|
-
| **Web search** | Built-in `web_search` and `web_fetch` tools when a web provider is configured |
|
|
78
|
-
| **Tools** | Attach custom tools, MCP tools, subagents, and workflows as tools |
|
|
79
|
-
| **Skills and files** | Attach skills from `src/skills/` and context files from `src/files/` |
|
|
80
|
-
| **Memory** | Sessions and persistent memory are enabled by default unless disabled |
|
|
81
|
-
| **Sandbox** | A built-in sandbox environment for using CLIs and more advanced code execution |
|
|
82
|
-
| **Self-scheduling** | Built-in tools let an agent schedule its own future or recurring runs (ephemeral triggers) |
|
|
182
|
+
## Integrations & credentials
|
|
83
183
|
|
|
84
|
-
|
|
184
|
+
Keystroke has 1,000+ built-in integrations, and it's easy to build a custom one for any HTTP API or MCP server (including private/internal).
|
|
85
185
|
|
|
86
|
-
|
|
186
|
+
Discover apps and actions with the CLI — the docs integration index is **not** reliable for discovery:
|
|
87
187
|
|
|
88
|
-
|
|
188
|
+
```bash
|
|
189
|
+
keystroke app list # all registered apps
|
|
190
|
+
keystroke app search <query> # find an app + slug in the full catalog
|
|
191
|
+
keystroke app actions <slug> --search <q> # actions an app exposes
|
|
192
|
+
keystroke app action <action-slug> # input/output schema for one action
|
|
193
|
+
keystroke connect <slug> # connect an app credential (opens web OAuth/api key flow for the user)
|
|
194
|
+
keystroke credentials list # stored credential instances
|
|
195
|
+
keystroke credentials set <key> --set apiKey=@env:MY_KEY # static API key
|
|
196
|
+
```
|
|
89
197
|
|
|
90
|
-
|
|
198
|
+
`keystroke deploy` **never uploads `.env`** — connect cloud credentials with `keystroke connect` / `keystroke credentials set`. Missing a built-in? Use `defineCredential` + an action, `defineApp`, or `defineMcp`. See `/learn/credentials/custom-integrations`.
|
|
91
199
|
|
|
92
|
-
|
|
93
|
-
| -------------------------- | --------------------------------------------------------------------------------------------- |
|
|
94
|
-
| **Typed input and output** | Zod schemas validate the payload going in and the result coming out |
|
|
95
|
-
| **Action steps** | Call any [action](/learn/actions/overview) with `.run()`, your own or one from an integration |
|
|
96
|
-
| **Agent steps** | Prompt an [agent](/learn/agents/overview) with `.prompt()` when a step needs judgment |
|
|
97
|
-
| **LLM steps** | Use `promptLlm()` for a one-shot model call without defining a full agent |
|
|
98
|
-
| **Durability** | Completed steps are recorded and replayed, so retries resume instead of restarting |
|
|
99
|
-
| **Durable waits** | `ctx.sleep()` and `ctx.hook()` suspend a run for a delay or until it is resumed externally |
|
|
200
|
+
## Skills & files
|
|
100
201
|
|
|
101
|
-
|
|
202
|
+
- **Skills** (`src/skills/<name>/SKILL.md`) — runtime playbooks that teach an agent *how* to do a task. Attach with `skills: ["<name>"]`.
|
|
203
|
+
- **Files** (`src/files/<set>/`) — static context an agent can access. Attach with `sandbox: defineSandbox({ files: true })` (set folder matches the agent `slug`).
|
|
102
204
|
|
|
103
|
-
|
|
104
|
-
- **Run before you claim you are finished** — deploy what you build, run it in the cloud, and read the real output before activating live triggers or claiming you are finished building something. Chat with agents to ensure they behave correctly. Run workflows to ensure they behave correctly.
|
|
105
|
-
- **Cover obvious edge cases** and write simple tests as needed (null field, empty array, a step that throws).
|
|
106
|
-
- **Connected apps aren't in `.env`** — `keystroke deploy` never uploads `.env`; connect apps (aka, integrations) for your project with `keystroke connect <slug>`.
|
|
107
|
-
- **Filtered deploys** — determine if you should do a full vs filtered deploy, or use WIP ignore directives.
|
|
108
|
-
- **Actions are leaf units** - An action never calls another action (including integration actions like `slackSendMessage`). You can compose actions in a workflow, or attach an integration action directly as a workflow step or agent tool. Action can call agents, allowing you to create "subagent tools" or "agent steps".
|
|
205
|
+
Both materialize into the agent's `/workspace/agent/...` environment before each prompt.
|
|
109
206
|
|
|
110
|
-
|
|
207
|
+
## Deploy targets & scope
|
|
111
208
|
|
|
112
|
-
|
|
209
|
+
- **Target**: after the first deploy, CLI commands target the **cloud** project automatically.
|
|
210
|
+
- **Full vs filtered**: first deploy must be full. Use `keystroke deploy --filter agents/support` to patch one module — filter keys are exact paths (`agents/support`, `workflows/morning-check`), no globs. Changing `keystroke.config.ts` or shared skills/files/integrations needs a full deploy.
|
|
211
|
+
- **WIP**: `// @keystroke ignore` skips a file everywhere; `// @keystroke ignore:deploy` keeps it local but out of deploys. A shipped module cannot import an ignored one.
|
|
212
|
+
|
|
213
|
+
## Audit & debug
|
|
214
|
+
|
|
215
|
+
Inspect deployed runs with `--include` to see full traces:
|
|
113
216
|
|
|
114
217
|
```bash
|
|
115
|
-
|
|
116
|
-
keystroke workflow
|
|
117
|
-
|
|
118
|
-
keystroke
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
keystroke
|
|
122
|
-
keystroke
|
|
123
|
-
keystroke
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
keystroke
|
|
127
|
-
keystroke trigger url <trigger-slug> # print a trigger's webhook URL
|
|
128
|
-
keystroke trigger runs list <trigger-slug>:<workflow-slug> # recent runs for a trigger→workflow attachment
|
|
129
|
-
keystroke trigger runs get <trigger-slug>:<workflow-slug> <run-id> --include workflows,trace # one run in full: workflows fired, execution trace
|
|
218
|
+
keystroke workflow runs list <workflow-slug>
|
|
219
|
+
keystroke workflow runs get <workflow-slug> <run-id> --include steps,trace
|
|
220
|
+
|
|
221
|
+
keystroke agent sessions list <agent-slug>
|
|
222
|
+
keystroke agent sessions get <agent-slug> <session-id> --include messages,trace
|
|
223
|
+
|
|
224
|
+
keystroke trigger list
|
|
225
|
+
keystroke trigger url <trigger-slug> # webhook URL (+ ?token= on platform)
|
|
226
|
+
keystroke trigger runs get <trigger-slug>:<workflow-slug> <run-id> --include workflows,trace
|
|
227
|
+
keystroke trigger attachment disable <trigger-slug> <trigger-slug>:<workflow-slug> # pause without redeploy (takes both the trigger slug and the attachment id)
|
|
228
|
+
|
|
229
|
+
keystroke history list --kind workflow --status failed
|
|
130
230
|
```
|
|
131
231
|
|
|
132
|
-
|
|
232
|
+
Invoke/inspect commands print JSON to stdout (exit 0 on success, 1 on failure) — pipe to `jq`. Lifecycle commands (`init`/`dev`/`deploy`) print human status.
|
|
233
|
+
|
|
234
|
+
## Before you claim you're done
|
|
235
|
+
|
|
236
|
+
- [ ] Deployed the change and read the real run output/trace — not just "it should work".
|
|
237
|
+
- [ ] Prompted agents / ran workflows with realistic input and verified behavior.
|
|
238
|
+
- [ ] Researched real APIs before mirroring them in custom integration actions — no guessed endpoints or payloads.
|
|
239
|
+
- [ ] Covered obvious edge cases (null field, empty array, a step that throws) with a simple test where warranted.
|
|
240
|
+
- [ ] Connected any new apps with `keystroke connect` (not `.env`).
|
|
241
|
+
- [ ] Tested manually before deploying attached cron/polling triggers, or used `trigger attachment disable` to pause until ready.
|
|
242
|
+
|
|
243
|
+
## Common gotchas
|
|
244
|
+
|
|
245
|
+
1. **Action calling an action** — throws at runtime and fails lint. Compose in a workflow, or attach the integration action directly.
|
|
246
|
+
2. **Bad model id** — must be exact `vendor/model-id` from the catalog; don't kebab the version. Fails at deploy, not typecheck.
|
|
247
|
+
3. **LLM structured output: use `.nullish()`, not `.optional()`** — models emit `"field": null` for "not applicable" values, and Zod `.optional()` rejects `null` (the step fails). Use `.nullish()` (or `.nullable()`) for any optional field in an `outputSchema`.
|
|
248
|
+
4. **Silent fallbacks hide real failures** — for live config (Sheets, DBs, credentials), don't `catch` and quietly substitute fallback/empty data in production paths. A run that "completes" with empty inputs looks like success in the trace but is a silent failure. Throw when required config is missing or empty, and validate response shape, not just status.
|
|
249
|
+
5. **Side effects outside steps** — they re-run on every replay. Keep them inside `.run()` / `.prompt()`.
|
|
250
|
+
6. **Schedule input** — a cron trigger passes `{}`; give the workflow `input: z.object({})`.
|
|
133
251
|
|
|
134
252
|
## Documentation
|
|
135
253
|
|
|
136
|
-
|
|
254
|
+
Read the docs regularly and prefer them over prior knowledge. Bias **heavily** toward searching and reading documentation before making any decisions or changes. The documentation contains much more important context than this `AGENTS.md` guide.
|
|
137
255
|
|
|
138
|
-
|
|
256
|
+
All documentation is available via the CLI (no auth), cheapest-first:
|
|
139
257
|
|
|
140
|
-
-
|
|
141
|
-
-
|
|
258
|
+
- `keystroke <command> --help` — authoritative, always-current flags for any command.
|
|
259
|
+
- `keystroke docs search "<query>"` — find pages by topic when you don't know the path.
|
|
260
|
+
- `keystroke docs query "<cmd>"` — read/search pages with `cat`/`rg`/`ls`/`tree`/`head` (e.g. `keystroke docs query "cat /learn/agents/build-agents.mdx"`).
|
|
142
261
|
|
|
143
|
-
|
|
262
|
+
`query` is stateless (working dir resets to `/`; use absolute paths or chain with `&&`) and output is capped (~30KB) — prefer targeted `rg -C 3` / `head` over `cat` on large pages.
|
|
144
263
|
|
|
145
|
-
Below is a sample of common documentation pages.
|
|
264
|
+
Below is a sample of some of the most common documentation pages.
|
|
146
265
|
|
|
147
266
|
| Doc path | Read when |
|
|
148
267
|
| -------- | --------- |
|
|
@@ -162,7 +281,6 @@ Below is a sample of common documentation pages. You can read a page with `keyst
|
|
|
162
281
|
| `/learn/actions/workflow-steps` | Wiring actions into workflows |
|
|
163
282
|
| `/learn/actions/agent-tools` | Exposing actions as agent tools |
|
|
164
283
|
| `/learn/triggers/overview` | Choosing a trigger type |
|
|
165
|
-
| `/learn/triggers/app-events` | App-event triggers |
|
|
166
284
|
| `/learn/triggers/webhooks` | Webhook triggers |
|
|
167
285
|
| `/learn/triggers/schedules` | Cron / scheduled triggers |
|
|
168
286
|
| `/learn/triggers/polling` | Polling triggers |
|
|
@@ -170,24 +288,7 @@ Below is a sample of common documentation pages. You can read a page with `keyst
|
|
|
170
288
|
| `/learn/credentials/connect-credentials` | `keystroke connect`, OAuth, project credentials |
|
|
171
289
|
| `/learn/credentials/use-credentials` | Using connected apps in code |
|
|
172
290
|
| `/learn/credentials/custom-integrations` | Building a custom HTTP / MCP / GraphQL integration |
|
|
173
|
-
| `/learn/skills/overview` | `src/skills/`
|
|
291
|
+
| `/learn/skills/overview` | `src/skills/` skills for agents (runtime, not this guide) |
|
|
174
292
|
| `/learn/skills/create-skills` | Authoring an agent skill |
|
|
175
293
|
| `/learn/files/overview` | `src/files/` workspace context |
|
|
176
|
-
| `/learn/logs/overview` | Reading run history, debugging deployed runs |
|
|
177
|
-
|
|
178
|
-
## Integrations and secrets
|
|
179
|
-
|
|
180
|
-
For searching native integrations use the CLI, not docs. The docs contain an index of integrations, but the documentation integration index is not reliable. To discover apps/integrations and their actions, query the live catalog with the CLI:
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
keystroke app list # list all registered/supported apps
|
|
184
|
-
keystroke app search <query> # find an app and its slug in the full catalog
|
|
185
|
-
keystroke app actions <slug> --search <q> # actions an app exposes
|
|
186
|
-
keystroke app action <action-slug> # input/output schema for one action
|
|
187
|
-
keystroke connect <slug> # connect an app credential (web flow)
|
|
188
|
-
keystroke credentials list # List stored/available credential instances
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
You can read `/learn/credentials/use-credentials` for using credentials in code and binding credentials to workflow steps and agent tools.
|
|
192
|
-
|
|
193
|
-
If you ever run into issues with an integration (or a required action isn't supported), it is *extremely* easy to build custom integrations and actions. You can build connections to any HTTP API or MCP server, including internal or private ones. See `/learn/credentials/custom-integrations`.
|
|
294
|
+
| `/learn/logs/overview` | Reading run history, debugging deployed runs |
|