@keystrokehq/cli 0.1.24 → 0.1.25
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/dist/index.mjs +46 -52
- package/dist/index.mjs.map +1 -1
- package/dist/skills-bundle/_AGENTS.md +1 -1
- package/package.json +3 -3
- package/dist/skills-bundle/skills/keystroke-actions/SKILL.md +0 -160
- package/dist/skills-bundle/skills/keystroke-actions/references/catalog-and-imports.md +0 -71
- package/dist/skills-bundle/skills/keystroke-agents/SKILL.md +0 -115
- package/dist/skills-bundle/skills/keystroke-agents/references/models.md +0 -23
- package/dist/skills-bundle/skills/keystroke-agents/references/tools-mcp-codemode.md +0 -85
- package/dist/skills-bundle/skills/keystroke-agents/references/workflows-and-testing.md +0 -26
- package/dist/skills-bundle/skills/keystroke-apps/SKILL.md +0 -151
- package/dist/skills-bundle/skills/keystroke-apps/references/cli-and-catalog.md +0 -104
- package/dist/skills-bundle/skills/keystroke-channels/SKILL.md +0 -66
- package/dist/skills-bundle/skills/keystroke-channels/references/slack-setup.md +0 -41
- package/dist/skills-bundle/skills/keystroke-cli/SKILL.md +0 -93
- package/dist/skills-bundle/skills/keystroke-deploy/SKILL.md +0 -93
- package/dist/skills-bundle/skills/keystroke-deploy/references/build-and-full-deploy.md +0 -30
- package/dist/skills-bundle/skills/keystroke-deploy/references/filtered-deploy.md +0 -50
- package/dist/skills-bundle/skills/keystroke-deploy/references/wip-ignore.md +0 -35
- package/dist/skills-bundle/skills/keystroke-files/SKILL.md +0 -43
- package/dist/skills-bundle/skills/keystroke-skills/SKILL.md +0 -42
- package/dist/skills-bundle/skills/keystroke-triggers/SKILL.md +0 -143
- package/dist/skills-bundle/skills/keystroke-workflows/SKILL.md +0 -78
- package/dist/skills-bundle/skills/keystroke-workflows/references/authoring.md +0 -168
- package/dist/skills-bundle/skills/keystroke-workflows/references/testing.md +0 -138
|
@@ -63,7 +63,7 @@ A project is a single live runtime. A deploy replaces what's running on that pro
|
|
|
63
63
|
|
|
64
64
|
To create a new project: `keystroke init my-app --yes`, then deploy.
|
|
65
65
|
|
|
66
|
-
Look things up cheapest-first: `keystroke <command> --help` for the authoritative flags and usage of any command (local, always current); `keystroke docs search`/`query` for documentation and examples; and
|
|
66
|
+
Look things up cheapest-first: `keystroke <command> --help` for the authoritative flags and usage of any command (local, always current); `keystroke docs search`/`query` for documentation and examples; and `keystroke docs query "cat /cli.mdx"` for the full CLI reference.
|
|
67
67
|
|
|
68
68
|
### Building agents
|
|
69
69
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keystrokehq/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/keystrokehq/keystroke.git",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"vitest": "^4.1.7",
|
|
43
43
|
"@keystrokehq/oxlint-config": "0.0.4",
|
|
44
44
|
"@keystrokehq/tsconfig": "0.0.3",
|
|
45
|
-
"@keystrokehq/
|
|
46
|
-
"@keystrokehq/
|
|
45
|
+
"@keystrokehq/vitest-config": "0.0.6",
|
|
46
|
+
"@keystrokehq/tsdown-config": "0.0.3"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "tsx scripts/generate-catalog-versions.ts && tsdown && node scripts/copy-templates.mjs && node scripts/copy-skills-bundle.mjs",
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: keystroke-actions
|
|
3
|
-
description: Define keystroke actions — workflow steps and agent tools. Custom API actions use a credential (defineCredential) or an app wrapper (app.action); catalog integrations import from npm packages. Use when authoring src/actions/ or wiring integrations.
|
|
4
|
-
metadata:
|
|
5
|
-
keystroke-domain: actions
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Actions
|
|
9
|
-
|
|
10
|
-
One **executable unit** used everywhere: workflow steps, agent tools, and codemode host calls.
|
|
11
|
-
|
|
12
|
-
Anything that calls an external API needs a **credential**. Two paths: declare a standalone `defineCredential` on a `defineAction` (simplest), or use an **app** wrapper (`app.action()`) when several actions share one connection or you've synced a catalog/custom app into `src/apps/`. See [apps skill](.agents/skills/keystroke-apps/SKILL.md).
|
|
13
|
-
|
|
14
|
-
## Actions are leaf units — never call an action from an action
|
|
15
|
-
|
|
16
|
-
An action's `run` must **not** call another action (yours or an integration action like `slackSendMessage`). Composition belongs in a **workflow**; an integration action is used directly as a workflow step or agent tool — not wrapped in a custom action.
|
|
17
|
-
|
|
18
|
-
```ts
|
|
19
|
-
// ❌ Don't: an action that calls another action
|
|
20
|
-
import { slackSendMessage } from "@keystrokehq/slack/actions";
|
|
21
|
-
export const notify = defineAction({ slug: "notify",
|
|
22
|
-
run: async (input) => slackSendMessage.run({ channel: input.channel, markdown_text: input.text }),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
// ✅ Do: use the integration action directly as a workflow step
|
|
26
|
-
async run(input) {
|
|
27
|
-
return slackSendMessage.run({ channel: input.channel, markdown_text: buildText(input) });
|
|
28
|
-
}
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
This is enforced at runtime (calling an action inside an action throws) and by lint (`no-restricted-imports` blocks importing `@keystrokehq/*/actions` inside `src/actions/`). An action **may** call an agent — see below.
|
|
32
|
-
|
|
33
|
-
## Custom API actions (standalone credential)
|
|
34
|
-
|
|
35
|
-
The simplest custom integration: declare a `defineCredential` and consume it from a plain `defineAction`. No app needed.
|
|
36
|
-
|
|
37
|
-
```ts
|
|
38
|
-
import { defineAction } from "@keystrokehq/keystroke/action";
|
|
39
|
-
import { defineCredential } from "@keystrokehq/keystroke/credentials";
|
|
40
|
-
import { z } from "zod";
|
|
41
|
-
|
|
42
|
-
const acme = defineCredential({ key: "acme", fields: { apiKey: z.string() } });
|
|
43
|
-
|
|
44
|
-
export const createAcmeTicket = defineAction({
|
|
45
|
-
slug: "create-acme-ticket",
|
|
46
|
-
input: z.object({ title: z.string() }),
|
|
47
|
-
output: z.object({ id: z.string() }),
|
|
48
|
-
credentials: [acme] as const,
|
|
49
|
-
async run(input, credentials) {
|
|
50
|
-
return createTicket({ apiKey: credentials.acme.apiKey, title: input.title });
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Connect it with `keystroke credentials set acme --set apiKey=@env:ACME_API_KEY --scope org`.
|
|
56
|
-
|
|
57
|
-
## App-backed actions (shared connection / synced apps)
|
|
58
|
-
|
|
59
|
-
Reach for an app when several actions share one connection, or when you've synced a catalog/custom app:
|
|
60
|
-
|
|
61
|
-
1. **App first** — create in the dashboard or `keystroke app create`, then `keystroke app sync <slug>` → `src/apps/<name>/app.ts`
|
|
62
|
-
2. **Connect** — `keystroke connect <slug>` (see [apps skill](.agents/skills/keystroke-apps/SKILL.md))
|
|
63
|
-
3. **Action** — `app.action()` in `src/actions/`, reading `credentials[app.slug]` in `run`
|
|
64
|
-
|
|
65
|
-
```ts
|
|
66
|
-
import { z } from "zod";
|
|
67
|
-
import { kwatch } from "../apps/kwatch/app";
|
|
68
|
-
|
|
69
|
-
export const kwatchListAlerts = kwatch.action({
|
|
70
|
-
slug: "kwatch-list-alerts",
|
|
71
|
-
input: z.object({}),
|
|
72
|
-
output: z.object({ ok: z.boolean(), alertCount: z.number() }),
|
|
73
|
-
async run(_input, credentials) {
|
|
74
|
-
const { apiKey } = credentials["keystroke/kwatch"];
|
|
75
|
-
return { ok: true, alertCount: 0 };
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Use an app wrapper (over a standalone credential) when a family of actions should share one connection definition.
|
|
81
|
-
|
|
82
|
-
## Pure actions (no credential)
|
|
83
|
-
|
|
84
|
-
Use `defineAction` with no `credentials` when the step needs no connection at all (pure logic, local transforms):
|
|
85
|
-
|
|
86
|
-
```ts
|
|
87
|
-
import { defineAction } from "@keystrokehq/keystroke/action";
|
|
88
|
-
import { z } from "zod";
|
|
89
|
-
|
|
90
|
-
export const triage = defineAction({
|
|
91
|
-
slug: "triage",
|
|
92
|
-
name: "Triage",
|
|
93
|
-
description: "Classify an inbound message",
|
|
94
|
-
input: z.object({ message: z.string(), sender: z.string() }),
|
|
95
|
-
output: z.object({ priority: z.enum(["low", "normal", "high", "urgent"]) }),
|
|
96
|
-
run: async (input) => ({ priority: "normal" }),
|
|
97
|
-
});
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Catalog integration actions
|
|
101
|
-
|
|
102
|
-
Official integrations ship as npm packages with pre-built actions. Discover with `keystroke app search`, connect with `keystroke connect <slug>`, then import in workflows or agent tools — not in `src/actions/`:
|
|
103
|
-
|
|
104
|
-
```ts
|
|
105
|
-
import { exaSearch } from "@keystrokehq/exa/actions";
|
|
106
|
-
import { slackSendMessage } from "@keystrokehq/slack/actions";
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Detail: [catalog-and-imports.md](references/catalog-and-imports.md).
|
|
110
|
-
|
|
111
|
-
## Call an agent from an action (allowed)
|
|
112
|
-
|
|
113
|
-
Agents — not other actions — are the one thing an action may invoke:
|
|
114
|
-
|
|
115
|
-
```ts
|
|
116
|
-
import signupResearcher from "../agents/signup-researcher";
|
|
117
|
-
|
|
118
|
-
export const researchSignup = defineAction({
|
|
119
|
-
slug: "research-signup",
|
|
120
|
-
run: async (input) => {
|
|
121
|
-
const result = await signupResearcher.prompt({ message: "…" });
|
|
122
|
-
return { brief: "…" };
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## Credential scope & resolution
|
|
128
|
-
|
|
129
|
-
When a credential's scope isn't pinned, the runtime resolves it **project default first, then org default**. Pin a scope per-use with `.scope()` (the authoring-side counterpart to the CLI `--scope` flag) — it returns a fresh action that still binds like any other step/tool:
|
|
130
|
-
|
|
131
|
-
```ts
|
|
132
|
-
await myAction.scope("user").run(input); // workflow step
|
|
133
|
-
tools: [myAction.scope("user")]; // agent tool
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
When several instances exist for one app + scope and none is the default, pin an exact instance to the consuming step/tool from the CLI: `keystroke credentials assignments assign --workflow <slug> --credential <app>/<slug> --consumer step:<slug>#0` (see [apps skill](.agents/skills/keystroke-apps/SKILL.md)).
|
|
137
|
-
|
|
138
|
-
## Long-running actions: honor the abort signal
|
|
139
|
-
|
|
140
|
-
`run` receives a third `ctx` argument with an `AbortSignal`. Thread it into fetches/SDK calls so the framework can cancel work cleanly:
|
|
141
|
-
|
|
142
|
-
```ts
|
|
143
|
-
async run(input, credentials, ctx) {
|
|
144
|
-
const res = await fetch(url, { signal: ctx?.signal });
|
|
145
|
-
return res.json();
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Where actions run
|
|
150
|
-
|
|
151
|
-
| Consumer | Usage |
|
|
152
|
-
| -------- | ----------------------------------------------- |
|
|
153
|
-
| Workflow | `await myAction.run(input)` in `defineWorkflow` |
|
|
154
|
-
| Agent | `tools: [myAction, exaSearch]` on `defineAgent` |
|
|
155
|
-
|
|
156
|
-
## Next references
|
|
157
|
-
|
|
158
|
-
- [catalog-and-imports.md](references/catalog-and-imports.md) — catalog discovery, npm imports
|
|
159
|
-
|
|
160
|
-
Related: [apps](.agents/skills/keystroke-apps/SKILL.md), [workflows](.agents/skills/keystroke-workflows/SKILL.md), [agents](.agents/skills/keystroke-agents/SKILL.md).
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# Integration actions
|
|
2
|
-
|
|
3
|
-
## Official catalog integrations
|
|
4
|
-
|
|
5
|
-
1. Discover: `keystroke app search <query>` → `app show <slug>` → `app actions <slug>`
|
|
6
|
-
2. Connect: `keystroke connect <slug>`
|
|
7
|
-
3. Add npm package (e.g. `@keystrokehq/exa`, `@keystrokehq/googlesuper`, `@keystrokehq/slack`)
|
|
8
|
-
4. Import in `src/workflows/` or on `defineAgent` `tools` — not in `src/actions/`:
|
|
9
|
-
|
|
10
|
-
```ts
|
|
11
|
-
import { exaSearch, exaAnswer } from "@keystrokehq/exa/actions";
|
|
12
|
-
import { slackSendMessage } from "@keystrokehq/slack/actions";
|
|
13
|
-
import { googlesuperSendEmail } from "@keystrokehq/googlesuper/actions";
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Catalog packages ship a pre-built app + actions — you do not author `src/apps/` for these.
|
|
17
|
-
|
|
18
|
-
## Custom integrations
|
|
19
|
-
|
|
20
|
-
Two supported paths. Pick based on whether actions share a connection.
|
|
21
|
-
|
|
22
|
-
### Standalone credential (simplest)
|
|
23
|
-
|
|
24
|
-
Declare a `defineCredential` and consume it from a plain `defineAction`:
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
import { defineAction } from "@keystrokehq/keystroke/action";
|
|
28
|
-
import { defineCredential } from "@keystrokehq/keystroke/credentials";
|
|
29
|
-
import { z } from "zod";
|
|
30
|
-
|
|
31
|
-
const acme = defineCredential({ key: "acme", fields: { apiKey: z.string() } });
|
|
32
|
-
|
|
33
|
-
export const fetchStatus = defineAction({
|
|
34
|
-
slug: "fetch-status",
|
|
35
|
-
input: z.object({}),
|
|
36
|
-
output: z.object({ ok: z.boolean() }),
|
|
37
|
-
credentials: [acme] as const,
|
|
38
|
-
async run(_input, credentials) {
|
|
39
|
-
const { apiKey } = credentials.acme;
|
|
40
|
-
return { ok: true };
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Connect it with `keystroke credentials set acme --set apiKey=@env:ACME_API_KEY --scope org`.
|
|
46
|
-
|
|
47
|
-
### App wrapper (shared connection / synced apps)
|
|
48
|
-
|
|
49
|
-
Use an app when several actions share one connection, or when you've synced a custom/catalog app:
|
|
50
|
-
|
|
51
|
-
1. Create the app (dashboard or `keystroke app create --name ... --field ...`)
|
|
52
|
-
2. Sync: `keystroke app sync <slug>` → `src/apps/<name>/app.ts`
|
|
53
|
-
3. Connect: `keystroke connect <slug>`
|
|
54
|
-
4. Author actions in `src/actions/` with `app.action()`:
|
|
55
|
-
|
|
56
|
-
```ts
|
|
57
|
-
import { z } from "zod";
|
|
58
|
-
import { internalApi } from "../apps/internal-api/app";
|
|
59
|
-
|
|
60
|
-
export const fetchStatus = internalApi.action({
|
|
61
|
-
slug: "fetch-status",
|
|
62
|
-
input: z.object({}),
|
|
63
|
-
output: z.object({ ok: z.boolean() }),
|
|
64
|
-
async run(_input, credentials) {
|
|
65
|
-
const { apiKey } = credentials["acme/internal-api"];
|
|
66
|
-
return { ok: true };
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Re-run `keystroke app sync <slug>` after template changes on the platform. Full app lifecycle: [apps skill](../../keystroke-apps/SKILL.md).
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: keystroke-agents
|
|
3
|
-
description: Build keystroke agents with defineAgent — models, integration tools (Exa, Google, Slack), skills, files, and sandbox. Use when authoring src/agents/ or debugging agent sessions.
|
|
4
|
-
metadata:
|
|
5
|
-
keystroke-domain: agents
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Agents
|
|
9
|
-
|
|
10
|
-
Agents are **autonomous LLM runs** with a sandbox, optional skills/files, and **tools** (your actions + integration actions).
|
|
11
|
-
|
|
12
|
-
## Typical patterns
|
|
13
|
-
|
|
14
|
-
**Integration tools** — import actions from an integration package:
|
|
15
|
-
|
|
16
|
-
```ts
|
|
17
|
-
import { defineAgent } from "@keystrokehq/keystroke/agent";
|
|
18
|
-
import { exaSearch, exaAnswer } from "@keystrokehq/exa/actions";
|
|
19
|
-
|
|
20
|
-
export default defineAgent({
|
|
21
|
-
slug: "signup-researcher",
|
|
22
|
-
systemPrompt: "Research signups with Exa. Stay concise; cite sources.",
|
|
23
|
-
model: "anthropic/claude-sonnet-4.6",
|
|
24
|
-
tools: [exaSearch, exaAnswer],
|
|
25
|
-
});
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
**Skills + files** — static playbooks and docs in the workspace:
|
|
29
|
-
|
|
30
|
-
```ts
|
|
31
|
-
import { defineAgent } from "@keystrokehq/keystroke/agent";
|
|
32
|
-
import { defineSandbox } from "@keystrokehq/keystroke/sandbox";
|
|
33
|
-
|
|
34
|
-
defineAgent({
|
|
35
|
-
slug: "support",
|
|
36
|
-
systemPrompt: "Read /workspace/agent/product-guide.md before answering.",
|
|
37
|
-
skills: ["support"],
|
|
38
|
-
sandbox: defineSandbox({ files: true }),
|
|
39
|
-
});
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Import actions from `@keystrokehq/<integration>/actions` (e.g. `@keystrokehq/exa/actions`, `@keystrokehq/googlesuper/actions`).
|
|
43
|
-
|
|
44
|
-
## Built-in capabilities (on by default)
|
|
45
|
-
|
|
46
|
-
Two capabilities are enabled automatically — you don't add them to `tools`:
|
|
47
|
-
|
|
48
|
-
- **Memory** — agents persist memory across sessions by default. Disable with `memory: false`.
|
|
49
|
-
- **Web** — built-in `web_search` / `web_fetch` host tools are available by default. Disable with `web: false`.
|
|
50
|
-
|
|
51
|
-
```ts
|
|
52
|
-
defineAgent({
|
|
53
|
-
slug: "researcher",
|
|
54
|
-
systemPrompt: "…",
|
|
55
|
-
model: "anthropic/claude-sonnet-4.6",
|
|
56
|
-
memory: false, // opt out of persistent memory
|
|
57
|
-
web: false, // opt out of built-in web tools
|
|
58
|
-
});
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Delegate to other agents with subagents, or trigger multi-step work with workflows — import them directly into `tools` — see [tools-mcp-codemode.md](references/tools-mcp-codemode.md).
|
|
62
|
-
|
|
63
|
-
## Structured output (`outputSchema`)
|
|
64
|
-
|
|
65
|
-
`outputSchema` is a **per-prompt** option, not a `defineAgent` field — the same agent can return free text on one call and a schema-validated object on the next. Pass a Zod schema to `prompt(...)` and read the parsed result from `result.output` (typed from the schema):
|
|
66
|
-
|
|
67
|
-
```ts
|
|
68
|
-
import { z } from "zod";
|
|
69
|
-
import researcher from "../agents/signup-researcher";
|
|
70
|
-
|
|
71
|
-
const Summary = z.object({ company: z.string(), summary: z.string() });
|
|
72
|
-
|
|
73
|
-
const result = await researcher.prompt({
|
|
74
|
-
message: "Research Acme Corp",
|
|
75
|
-
outputSchema: Summary,
|
|
76
|
-
});
|
|
77
|
-
if (result.error) throw new Error(result.error);
|
|
78
|
-
|
|
79
|
-
const { company, summary } = result.output!; // typed { company: string; summary: string }
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Without `outputSchema`, `result.output` is `undefined` and you read the reply from `result.messages`. This is an in-process TypeScript API (workflows, actions, scripts) — structured output is **not** exposed over the HTTP route or `keystroke agent prompt`.
|
|
83
|
-
|
|
84
|
-
## Run & audit
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
keystroke agent prompt signup-researcher --message "Research Acme Corp"
|
|
88
|
-
keystroke agent sessions list signup-researcher
|
|
89
|
-
keystroke agent sessions get signup-researcher <session-id> --include messages,trace
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Follow up in the same session: `--session-id <id>`.
|
|
93
|
-
|
|
94
|
-
## How agents get invoked
|
|
95
|
-
|
|
96
|
-
| From | How |
|
|
97
|
-
| --------------- | --------------------------------------------------------- |
|
|
98
|
-
| CLI | `keystroke agent prompt {slug} --message "…"` |
|
|
99
|
-
| Workflow action | `await myAgent.prompt({ message })` inside `defineAction` |
|
|
100
|
-
| Channel | Slack message to a bound agent (see channels skill) |
|
|
101
|
-
|
|
102
|
-
The agent's identity field is `slug` — it's also the route id (`POST /agents/{slug}`) and the CLI `<agentId>` argument.
|
|
103
|
-
|
|
104
|
-
## Workspace
|
|
105
|
-
|
|
106
|
-
- Skills → `/workspace/agent/skills/{skill-name}/` (the skill's folder name)
|
|
107
|
-
- Files from `src/files/{slug}/` → `/workspace/agent/` (`{slug}` is the agent slug when `files: true`)
|
|
108
|
-
|
|
109
|
-
## Next references
|
|
110
|
-
|
|
111
|
-
- [models.md](references/models.md) — model ids, platform LLM proxy
|
|
112
|
-
- [tools-mcp-codemode.md](references/tools-mcp-codemode.md) — actions as tools, MCP, codemode
|
|
113
|
-
- [workflows-and-testing.md](references/workflows-and-testing.md) — sessions, workflow handoff
|
|
114
|
-
|
|
115
|
-
Related: [actions](.agents/skills/keystroke-actions/SKILL.md), [workflows](.agents/skills/keystroke-workflows/SKILL.md), [files](.agents/skills/keystroke-files/SKILL.md), [apps](.agents/skills/keystroke-apps/SKILL.md).
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Models
|
|
2
|
-
|
|
3
|
-
```ts
|
|
4
|
-
model: "google/gemini-2.5-flash"; // vendor/model-id — any pi-ai or gateway catalog id
|
|
5
|
-
thinkingLevel: "high"; // optional — defaults to "medium"; use "none" to disable reasoning
|
|
6
|
-
```
|
|
7
|
-
|
|
8
|
-
`thinkingLevel` accepts `off`, `minimal`, `low`, `medium`, `high`, `xhigh` (`off` disables reasoning).
|
|
9
|
-
|
|
10
|
-
Per-prompt override via API: `{ "message": "...", "thinkingLevel": "low" }`.
|
|
11
|
-
|
|
12
|
-
Set `model` to any `vendor/model-id` and deploy — the platform routes agents through its managed LLM proxy automatically, so there are **no provider keys to configure**.
|
|
13
|
-
|
|
14
|
-
| Vendor | Example id |
|
|
15
|
-
| --------- | ----------------------------- |
|
|
16
|
-
| Anthropic | `anthropic/claude-sonnet-4.5` |
|
|
17
|
-
| OpenAI | `openai/gpt-5.5` |
|
|
18
|
-
| Google | `google/gemini-3.5-flash` |
|
|
19
|
-
| DeepSeek | `deepseek/deepseek-v3` |
|
|
20
|
-
| Moonshot | `moonshotai/kimi-k2.5` |
|
|
21
|
-
| Zhipu GLM | `zai/glm-4.5` |
|
|
22
|
-
|
|
23
|
-
After changing model, smoke-test: `keystroke agent prompt <key> --message "Hi"`.
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# Tools, MCP, and codemode
|
|
2
|
-
|
|
3
|
-
## Integration actions as tools
|
|
4
|
-
|
|
5
|
-
Most agents use imported integration actions:
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
import { exaSearch, exaAnswer } from "@keystrokehq/exa/actions";
|
|
9
|
-
import { googlesuperFetchEmails, googlesuperSendEmail } from "@keystrokehq/googlesuper/actions";
|
|
10
|
-
|
|
11
|
-
tools: [exaSearch, exaAnswer, googlesuperFetchEmails, googlesuperSendEmail],
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
See each integration package's `actions` export for available tools.
|
|
15
|
-
|
|
16
|
-
## Your own actions as tools
|
|
17
|
-
|
|
18
|
-
```ts
|
|
19
|
-
import { triage } from "../actions/triage";
|
|
20
|
-
tools: [triage],
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Same action works in workflows and on agents.
|
|
24
|
-
|
|
25
|
-
## Subagents (delegate to another agent)
|
|
26
|
-
|
|
27
|
-
Import another agent into `tools` and the parent delegates a scoped task to the child agent:
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
import { defineAgent } from "@keystrokehq/keystroke/agent";
|
|
31
|
-
import researcher from "./researcher";
|
|
32
|
-
|
|
33
|
-
export default defineAgent({
|
|
34
|
-
slug: "planner",
|
|
35
|
-
systemPrompt: "Plan work. Delegate research to the researcher subagent.",
|
|
36
|
-
model: "anthropic/claude-sonnet-4.6",
|
|
37
|
-
tools: [researcher],
|
|
38
|
-
});
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
The tool name is the subagent's `slug`. The tool expects a `message` string parameter.
|
|
42
|
-
|
|
43
|
-
## Workflows as tools
|
|
44
|
-
|
|
45
|
-
Import a workflow into `tools` when the agent should trigger a fixed multi-step sequence as one durable tool call:
|
|
46
|
-
|
|
47
|
-
```ts
|
|
48
|
-
import { defineAgent } from "@keystrokehq/keystroke/agent";
|
|
49
|
-
import refundOrder from "../workflows/refund-order";
|
|
50
|
-
|
|
51
|
-
export default defineAgent({
|
|
52
|
-
slug: "support",
|
|
53
|
-
systemPrompt: "Help customers. To issue a refund, call the refund-order tool.",
|
|
54
|
-
model: "anthropic/claude-sonnet-4.6",
|
|
55
|
-
tools: [refundOrder],
|
|
56
|
-
});
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
The tool name is the workflow's `slug`; parameters come from the workflow's `input` schema (must be a Zod object). The workflow runs inline as a tool — it cannot use `ctx.sleep()` or `ctx.hook()`. To run a workflow as its own tracked run instead, call it over HTTP or from a trigger; to reuse it inside another workflow, import it and call `await otherWorkflow.run(input)`.
|
|
60
|
-
|
|
61
|
-
## MCP
|
|
62
|
-
|
|
63
|
-
Point an agent at an MCP server with `defineMcp` (from `@keystrokehq/keystroke/agent`) and add the definition to `tools` alongside actions. Each tool the server lists becomes available, prefixed with the server `key` (e.g. `mcp__deepwiki__ask_question`).
|
|
64
|
-
|
|
65
|
-
```ts
|
|
66
|
-
import { defineAgent, defineMcp } from "@keystrokehq/keystroke/agent";
|
|
67
|
-
|
|
68
|
-
const deepwiki = defineMcp({
|
|
69
|
-
key: "deepwiki",
|
|
70
|
-
transport: { type: "http", url: "https://mcp.deepwiki.com/mcp" },
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
export default defineAgent({
|
|
74
|
-
slug: "researcher",
|
|
75
|
-
systemPrompt: "Use the DeepWiki tools to answer questions about repos.",
|
|
76
|
-
model: "anthropic/claude-sonnet-4.6",
|
|
77
|
-
tools: [deepwiki],
|
|
78
|
-
});
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
For servers that require auth, declare credentials on the definition.
|
|
82
|
-
|
|
83
|
-
## Codemode (advanced)
|
|
84
|
-
|
|
85
|
-
Default sandbox has bash. For batch tool calls, agents can run js-exec scripts that call `await tools['action-slug'](args)` (the tool name is the action's slug; MCP tools keep their `mcp__<key>__<tool>` prefix). Optional VM runtime via `sandbox: defineSandbox({ mode: "vm" })` (from `@keystrokehq/keystroke/sandbox`).
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Sessions and workflow handoff
|
|
2
|
-
|
|
3
|
-
## Multi-turn CLI
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
keystroke agent prompt support --message "What is the refund policy?"
|
|
7
|
-
keystroke agent sessions list support
|
|
8
|
-
keystroke agent prompt support --message "Summarize that" --session-id <id>
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Inspect a session
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
keystroke agent sessions get support <session-id> --include messages,trace
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Use this when an agent misbehaves or a channel reply looks wrong.
|
|
18
|
-
|
|
19
|
-
## Agent called from a workflow
|
|
20
|
-
|
|
21
|
-
Actions invoke agents with `.prompt()` inside `defineAction`. Audit the workflow run, not just the agent session:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
keystroke workflow runs list signup-pipeline
|
|
25
|
-
keystroke workflow runs get signup-pipeline <run-id> --include steps,trace
|
|
26
|
-
```
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: keystroke-apps
|
|
3
|
-
description: Connectable apps — defineApp, app.action, catalog discovery via keystroke app search, custom app create/sync, and connect. Use when wiring integrations, OAuth, API keys, or a deployed run fails because an app is not connected.
|
|
4
|
-
metadata:
|
|
5
|
-
keystroke-domain: apps
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Apps
|
|
9
|
-
|
|
10
|
-
An **app** is a connectable integration: a slug, an auth kind, and (for custom apps) a field template. **Connected** = secrets for that app have been uploaded via the connect flow.
|
|
11
|
-
|
|
12
|
-
Secrets never live in source or `.env`. `keystroke deploy` uploads code only, not connections — connect the apps your project needs with the connect flow.
|
|
13
|
-
|
|
14
|
-
Custom actions that call external APIs need a **credential**. The simplest path is a standalone `defineCredential` declared on a `defineAction`. Reach for an **app** (`defineApp` + `app.action()`) when several actions share one connection, or when you've synced a catalog/custom app into `src/apps/`. See [actions skill](.agents/skills/keystroke-actions/SKILL.md).
|
|
15
|
-
|
|
16
|
-
## Two sources of apps
|
|
17
|
-
|
|
18
|
-
| Source | How you get it | Author in code |
|
|
19
|
-
| ------ | -------------- | -------------- |
|
|
20
|
-
| **Catalog** | ~1000 Composio integrations + first-party (`exa`, `slack`, `googlesuper`) | npm package `@keystrokehq/<slug>` — discover via CLI |
|
|
21
|
-
| **Custom** | Dashboard UI or `keystroke app create`, then `keystroke app sync <slug>` | `src/apps/<name>/app.ts` from sync |
|
|
22
|
-
|
|
23
|
-
## Discover catalog integrations
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
keystroke auth login
|
|
27
|
-
keystroke app search github # live Composio catalog
|
|
28
|
-
keystroke app show github
|
|
29
|
-
keystroke app actions github --search issue
|
|
30
|
-
keystroke app action GITHUB_CREATE_ISSUE
|
|
31
|
-
keystroke app list # apps registered in your org
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Discovery is read-only — there is no `app install` yet. To connect an app, its slug must be in your org registry (`app list`).
|
|
35
|
-
|
|
36
|
-
## Create and sync custom apps
|
|
37
|
-
|
|
38
|
-
Create in the dashboard or CLI, then pull the template into your project:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
# Manual custom app (api_key fields)
|
|
42
|
-
keystroke app create \
|
|
43
|
-
--name "Internal API" \
|
|
44
|
-
--description "Our internal service" \
|
|
45
|
-
--field apiKey:secret
|
|
46
|
-
|
|
47
|
-
# Auto-detect from URL (same as dashboard Create custom app)
|
|
48
|
-
keystroke app create --mcp https://mcp.example.com/mcp --preview
|
|
49
|
-
keystroke app create --openapi https://example.com/openapi.yaml --name "Example API"
|
|
50
|
-
|
|
51
|
-
keystroke app sync acme/internal-api # writes src/apps/internal-api/app.ts
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Re-run `sync` after template changes on the platform. Then author actions with `app.action()` in `src/actions/`.
|
|
55
|
-
|
|
56
|
-
## Author with defineApp
|
|
57
|
-
|
|
58
|
-
Synced apps land as `defineApp` in `src/apps/<name>/app.ts`:
|
|
59
|
-
|
|
60
|
-
```ts
|
|
61
|
-
import { defineApp } from "@keystrokehq/keystroke/app";
|
|
62
|
-
import { z } from "zod";
|
|
63
|
-
|
|
64
|
-
export const kwatch = defineApp({
|
|
65
|
-
slug: "keystroke/kwatch",
|
|
66
|
-
auth: "api_key",
|
|
67
|
-
credential: { apiKey: z.string() },
|
|
68
|
-
});
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Actions use `app.action()` — the app binding is automatic:
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
import { kwatch } from "../apps/kwatch/app";
|
|
75
|
-
|
|
76
|
-
export const kwatchListAlerts = kwatch.action({
|
|
77
|
-
slug: "kwatch-list-alerts",
|
|
78
|
-
input: z.object({}),
|
|
79
|
-
output: z.object({ ok: z.boolean(), alertCount: z.number() }),
|
|
80
|
-
async run(_input, credentials) {
|
|
81
|
-
const { apiKey } = credentials["keystroke/kwatch"];
|
|
82
|
-
return { ok: true, alertCount: 0 };
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
Auth kinds: `keystroke` (MCP/Composio catalog apps), `api_key` (custom fields), `oauth` (token resolved at runtime). In `run`, read connected fields as `credentials[app.slug]`.
|
|
88
|
-
|
|
89
|
-
## Connect an app
|
|
90
|
-
|
|
91
|
-
`keystroke connect <slug>` opens the web app connect flow (OAuth or API-key form, depending on the app). This is how secrets get attached to an app — not via `.env`.
|
|
92
|
-
|
|
93
|
-
**Official integrations** — the cleanest path:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
keystroke connect google
|
|
97
|
-
keystroke connect slack
|
|
98
|
-
keystroke connect exa
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
**Custom apps** — sync the template first, then connect:
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
keystroke app sync acme/internal-api
|
|
105
|
-
keystroke connect acme/internal-api
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
The web app **Apps** page offers the same flow.
|
|
109
|
-
|
|
110
|
-
Field names in the connect form match the app's synced template. You pick the scope (project / org / user) in the web connect flow — `keystroke connect` has no `--scope` flag. See [cli-and-catalog.md](references/cli-and-catalog.md).
|
|
111
|
-
|
|
112
|
-
## Connect what your project needs
|
|
113
|
-
|
|
114
|
-
A new project starts with **no connected apps**. After deploy, connect the apps it uses:
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
keystroke deploy --project <id>
|
|
118
|
-
keystroke connect google
|
|
119
|
-
keystroke connect exa
|
|
120
|
-
keystroke app list
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
A runtime error about a missing connection almost always means the app hasn't been connected for this project.
|
|
124
|
-
|
|
125
|
-
## Manage & bind credentials
|
|
126
|
-
|
|
127
|
-
`keystroke credentials list / get / update --default / rotate-key / delete` manage instances. When several instances share a scope and none is the default, a run can't auto-resolve — set a default, or **bind** an exact instance to one step/tool:
|
|
128
|
-
|
|
129
|
-
```bash
|
|
130
|
-
keystroke credentials consumers list --workflow sync # step:<slug>#<n>
|
|
131
|
-
keystroke credentials assignments assign --workflow sync --credential org/work --consumer step:fetch-gmail#0
|
|
132
|
-
keystroke credentials assignments assign --agent support --credential vault-prod --consumer vault-lookup # tool slug
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
An assignment is the explicit selection at the top of the resolution order, so it overrides scope defaults. Full surface: [cli-and-catalog.md](references/cli-and-catalog.md).
|
|
136
|
-
|
|
137
|
-
## Audit
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
keystroke app list # org-registered apps
|
|
141
|
-
keystroke credentials list # connected instances + scope + default
|
|
142
|
-
keystroke credentials assignments list --workflow <slug> # which instance is pinned where
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Failed integration call → confirm the app is connected for your project, the action uses the right slug, and (if multiple instances) a default or assignment resolves the right one.
|
|
146
|
-
|
|
147
|
-
## Next references
|
|
148
|
-
|
|
149
|
-
- [cli-and-catalog.md](references/cli-and-catalog.md) — `keystroke app` commands, connect, scopes, credential management & binding
|
|
150
|
-
|
|
151
|
-
Related: [cli](.agents/skills/keystroke-cli/SKILL.md), [actions](.agents/skills/keystroke-actions/SKILL.md), [channels](.agents/skills/keystroke-channels/SKILL.md).
|