@keystrokehq/cli 0.1.15 → 0.1.16
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 +7 -4
- package/dist/index.mjs.map +1 -1
- package/dist/skills-bundle/_AGENTS.mcp.md +10 -3
- package/dist/skills-bundle/_AGENTS.md +61 -70
- package/dist/skills-bundle/skills/keystroke-actions/SKILL.md +60 -12
- package/dist/skills-bundle/skills/keystroke-actions/references/catalog-and-imports.md +32 -3
- package/dist/skills-bundle/skills/keystroke-agents/SKILL.md +50 -8
- package/dist/skills-bundle/skills/keystroke-agents/references/models.md +11 -13
- package/dist/skills-bundle/skills/keystroke-agents/references/tools-mcp-codemode.md +45 -3
- package/dist/skills-bundle/skills/keystroke-agents/references/workflows-and-testing.md +1 -1
- package/dist/skills-bundle/skills/keystroke-apps/SKILL.md +26 -13
- package/dist/skills-bundle/skills/keystroke-apps/references/cli-and-catalog.md +47 -16
- package/dist/skills-bundle/skills/keystroke-channels/SKILL.md +66 -0
- package/dist/skills-bundle/skills/keystroke-channels/references/slack-setup.md +41 -0
- package/dist/skills-bundle/skills/keystroke-cli/SKILL.md +41 -93
- package/dist/skills-bundle/skills/keystroke-deploy/SKILL.md +10 -9
- package/dist/skills-bundle/skills/keystroke-deploy/references/build-and-full-deploy.md +3 -1
- package/dist/skills-bundle/skills/keystroke-deploy/references/filtered-deploy.md +3 -2
- package/dist/skills-bundle/skills/keystroke-deploy/references/wip-ignore.md +5 -2
- package/dist/skills-bundle/skills/keystroke-files/SKILL.md +12 -4
- package/dist/skills-bundle/skills/keystroke-skills/SKILL.md +7 -2
- package/dist/skills-bundle/skills/keystroke-triggers/SKILL.md +30 -17
- package/dist/skills-bundle/skills/keystroke-workflows/SKILL.md +27 -12
- package/dist/skills-bundle/skills/keystroke-workflows/references/authoring.md +116 -4
- package/dist/skills-bundle/skills/keystroke-workflows/references/testing.md +17 -9
- package/dist/templates/hello-world/README.md +19 -8
- package/dist/templates/hello-world/src/workflows/greeting.test.ts +1 -1
- package/package.json +2 -2
- package/dist/skills-bundle/skills/keystroke-cli/references/api-targets.md +0 -87
- package/dist/skills-bundle/skills/keystroke-gateways/SKILL.md +0 -43
- package/dist/skills-bundle/skills/keystroke-gateways/references/slack-setup.md +0 -27
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# keystroke (MCP)
|
|
2
2
|
|
|
3
|
-
Keystroke is
|
|
3
|
+
Keystroke is a code-first AI automation platform — build specialized AI agents and workflow automations as real TypeScript, then deploy them to a managed cloud where they run. Everything is actual code (not brittle JSON), so agents can build, test, and maintain it. There are 1,000+ built-in integrations (Slack, Google, Linear, …), and you can build a connection for any HTTP API (including private internal APIs) or MCP server.
|
|
4
4
|
|
|
5
5
|
You are editing a **keystroke project** in a remote workspace via MCP. Author under `src/`, import from `@keystrokehq/*` npm packages. You do not have framework source — only this project and published deps.
|
|
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`. Load authoring guidance with `search_skills` and `get_skill` (see skills map below). The workspace root also has `AGENTS.md` and `.agents/skills/` with the same skill content, readable via `read_file`.
|
|
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.
|
|
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.
|
|
10
10
|
|
|
11
11
|
## What you build
|
|
12
12
|
|
|
@@ -26,6 +26,10 @@ Draft or in-progress modules, full vs filtered deploy, and `@keystroke ignore`:
|
|
|
26
26
|
|
|
27
27
|
**Actions are leaf units.** An action never calls another action (including integration actions like `postMessage`). Compose actions in a workflow, or attach an integration action directly as a workflow step / agent tool. An action may call an agent.
|
|
28
28
|
|
|
29
|
+
**Workflow steps.** Workflows orchestrate actions, agent prompts, and LLM calls (`promptLlm`) as steps. There's no first-class "call another workflow" step — share logic by extracting it into `src/lib/` or an action, or expose a workflow as an agent tool (`defineWorkflowTool`) / over HTTP when you want it as its own tracked run.
|
|
30
|
+
|
|
31
|
+
**Agent tools.** Agents can use actions, subagents (`defineSubagentTool`), workflows (`defineWorkflowTool`), and MCP tools as tools.
|
|
32
|
+
|
|
29
33
|
## Working habits
|
|
30
34
|
|
|
31
35
|
A few things that are easy to skip and cause common failures:
|
|
@@ -46,7 +50,10 @@ keystroke workflow run <workflow-key> --input '{}'
|
|
|
46
50
|
keystroke workflow runs list <workflow-key>
|
|
47
51
|
keystroke workflow runs get <workflow-key> <run-id> --include steps,trace
|
|
48
52
|
keystroke agent sessions list <agent-key>
|
|
53
|
+
keystroke agent sessions get <agent-key> <session-id> --include messages,trace
|
|
49
54
|
keystroke trigger list
|
|
55
|
+
keystroke trigger url <trigger-key>
|
|
56
|
+
keystroke trigger runs list <trigger-key>:<workflow-key>
|
|
50
57
|
keystroke app list
|
|
51
58
|
```
|
|
52
59
|
|
|
@@ -64,7 +71,7 @@ Call `search_skills` then `get_skill` with the key below.
|
|
|
64
71
|
| `keystroke-workflows` | Orchestration, action steps |
|
|
65
72
|
| `keystroke-actions` | Shared steps, integration tools |
|
|
66
73
|
| `keystroke-triggers` | Cron, webhook, poll automation |
|
|
67
|
-
| `keystroke-
|
|
74
|
+
| `keystroke-channels` | Slack / external channel bindings |
|
|
68
75
|
| `keystroke-skills` | `src/skills/` playbooks |
|
|
69
76
|
| `keystroke-files` | Agent workspace files |
|
|
70
77
|
| `keystroke-apps` | Connectable apps, catalog, connect |
|
|
@@ -1,121 +1,112 @@
|
|
|
1
1
|
# keystroke
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This codebase is a Keystroke project.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> Keystroke is a code-first AI automation platform, an n8n alternative built for agents. With it, anyone can build specialized AI agents and workflow automations as real TypeScript, then deploy them to a managed cloud platform where they run. Unlike tools like Zapier and n8n that hide logic behind brittle JSON, everything in Keystroke is actual code that coding agents (Cursor, Claude Code, Codex, etc.) can build, test, and maintain.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **Build agents and workflows:** Build agents and workflows with an open TypeScript framework. Run tests, connect integrations, and maintain what you build over time.
|
|
8
|
+
- **Connect to thousands of integrations:** Keystroke has over 1,000 built-in integrations (Slack, Google, Linear, and hundreds more). You can also 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 inspect runs, manage credentials, and collaborate from a shared web platform.
|
|
8
10
|
|
|
9
|
-
##
|
|
11
|
+
## Keystroke projects
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
In Keystroke, everything you build belongs to a project. A project is a shared space for building and running your agents, workflows, triggers, and actions. Think of a project as the unit you build, deploy, give credentials to, invite teammates into, and inspect run history for.
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
| --------------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
15
|
-
| **Local** (default `:3002`) | **Development and testing** — iterate on `src/`, run workflows/agents on your machine |
|
|
16
|
-
| **Cloud** (`platformUrl` + `activeProjectId`) | **Invoking and listing deployed resources** — production runs, triggers, remote audit after deploy |
|
|
15
|
+
Keystroke projects use two related ideas:
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
keystroke config use local # switch to local (cloud project id is preserved)
|
|
21
|
-
keystroke config use cloud # switch back to deployed project
|
|
22
|
-
keystroke config use project <id> # swap active cloud project
|
|
23
|
-
keystroke --project <id> workflow run foo --input '{}' # one-off cloud target
|
|
24
|
-
keystroke config show # inspect activeProjectId, apiTarget, dev session
|
|
25
|
-
keystroke project list # platform deploy targets in the active org
|
|
26
|
-
keystroke project create --name "My app" # new target (inactive until deploy)
|
|
27
|
-
keystroke deploy --project <id> # build + upload; activates cloud runtime
|
|
28
|
-
```
|
|
17
|
+
- **Local codebase**: a local directory (this codebase) with `keystroke.config.ts` and `src/` (`keystroke init` scaffolds this). Run it locally with `keystroke start` / `keystroke dev`; no platform project required.
|
|
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.
|
|
29
19
|
|
|
30
|
-
`keystroke
|
|
20
|
+
`keystroke deploy --project <id>` links your local codebase to your platform project: it uploads the built local codebase and activates that platform project's server. After the first deploy the project is saved as your active target (in `~/.keystroke`), so later commands — including subsequent deploys — can drop `--project`. Deployed agents and workflows instantly run there with no additional configuration; the web workspace is where users can manage their projects, deployments, logs, credentials, etc.
|
|
31
21
|
|
|
32
|
-
|
|
22
|
+
## How this codebase fits in
|
|
33
23
|
|
|
34
|
-
|
|
24
|
+
This is the local codebase that defines your agents, workflows, triggers, actions, skills, and files.
|
|
35
25
|
|
|
36
|
-
|
|
26
|
+
Projects are scaffolded with an opinionated folder structure (like Next.js for building AI systems):
|
|
37
27
|
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
keystroke
|
|
41
|
-
|
|
42
|
-
|
|
28
|
+
```
|
|
29
|
+
my-app/
|
|
30
|
+
keystroke.config.ts # project configuration
|
|
31
|
+
src/
|
|
32
|
+
agents/ # LLM agents
|
|
33
|
+
actions/ # reusable units of work
|
|
34
|
+
workflows/ # multi-step automations
|
|
35
|
+
triggers/ # schedules, webhooks, app events
|
|
36
|
+
skills/ # project skills for agents
|
|
37
|
+
files/ # context for attaching to agents
|
|
38
|
+
AGENTS.md # this guide
|
|
39
|
+
.agents/skills/ # Keystroke skills and best practices
|
|
43
40
|
```
|
|
44
41
|
|
|
45
|
-
|
|
42
|
+
Keystroke discovers everything under `src/` by convention. Add a file that exports an agent, workflow, trigger, etc, and it becomes part of the project. Because the project is code, agents (Cursor, Claude Code, Codex, etc) can read it, change it, run tests, and maintain it over time.
|
|
46
43
|
|
|
47
|
-
|
|
44
|
+
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.
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
keystroke auth login
|
|
51
|
-
```
|
|
46
|
+
## How you work
|
|
52
47
|
|
|
53
|
-
|
|
48
|
+
You build in `src/`, deploy to your project on the platform, then run and inspect what's deployed with the CLI. The loop is: edit → `keystroke deploy` → run/inspect/test → repeat. You should deploy often.
|
|
54
49
|
|
|
55
|
-
|
|
50
|
+
```bash
|
|
51
|
+
keystroke auth login # once; token is automatically stored and reused
|
|
52
|
+
keystroke project list # your projects on the platform
|
|
53
|
+
keystroke deploy --project <id> # build + ship src/ to the platform
|
|
54
|
+
keystroke workflow run greeting --input '{"name":"Ada"}' # run on your project
|
|
55
|
+
keystroke agent prompt hello --message "Hi"
|
|
56
|
+
```
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
| -------------- | -------------------------------------- | --------------------------------------------------------------------------- |
|
|
59
|
-
| Actions | `src/actions/` | `@keystrokehq/keystroke/action` |
|
|
60
|
-
| Agents | `src/agents/` | `@keystrokehq/keystroke/agent` |
|
|
61
|
-
| Workflows | `src/workflows/` | `@keystrokehq/keystroke/workflow` |
|
|
62
|
-
| Triggers | `src/triggers/` | `@keystrokehq/keystroke/trigger` |
|
|
63
|
-
| Apps | `src/apps/` | `@keystrokehq/keystroke/app`, `keystroke app`, `keystroke connect` |
|
|
64
|
-
| Integrations | npm packages + catalog | `@keystrokehq/exa`, `@keystrokehq/slack`, … — discover with `keystroke app search` |
|
|
65
|
-
| Skills / files | `src/skills/`, `src/files/` | attached on `defineAgent` |
|
|
58
|
+
After a deploy, runtime commands (`workflow`, `agent`, `trigger`, `app`, `connect`) operate on that project automatically — no target to manage.
|
|
66
59
|
|
|
67
|
-
|
|
60
|
+
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. You can use `--filter` deploys and `@keystroke ignore` to keep iterate quickly.
|
|
68
61
|
|
|
69
|
-
|
|
62
|
+
To create a new project: `keystroke init my-app --yes`, then deploy.
|
|
70
63
|
|
|
71
|
-
|
|
64
|
+
Full deploy mechanics: [cli skill](.agents/skills/keystroke-cli/SKILL.md), [deploy skill](.agents/skills/keystroke-deploy/SKILL.md).
|
|
72
65
|
|
|
73
66
|
## Working habits
|
|
74
67
|
|
|
75
68
|
A few things that are easy to skip and cause common failures:
|
|
76
69
|
|
|
77
70
|
- **Research real APIs before mirroring them** — web search and fetch the actual reference & explore relevant docs; don't guess endpoints or payload shapes.
|
|
78
|
-
- **Run before you depend
|
|
71
|
+
- **Run before you depend on it** — run the workflow/agent and read the real output (`keystroke workflow runs get <workflow-slug> <run-id> --include steps,trace`) before wiring dependent steps or claiming you are finished building something.
|
|
79
72
|
- **Cover obvious edge cases** and write simple tests as needed (null field, empty array, a step that throws) — see [workflows skill](.agents/skills/keystroke-workflows/SKILL.md).
|
|
80
|
-
- **Connected apps aren't in `.env`** — `keystroke deploy` never uploads `.env`; connect apps
|
|
81
|
-
- **Shipping to prod** — full vs filtered deploy, WIP ignore directives: [deploy skill](.agents/skills/keystroke-deploy/SKILL.md).
|
|
73
|
+
- **Connected apps aren't in `.env`** — `keystroke deploy` never uploads `.env`; connect apps (aka, integrations) for your project with `keystroke connect <slug>`. See [apps skill](.agents/skills/keystroke-apps/SKILL.md).
|
|
74
|
+
- **Shipping to prod** — determine if you should do a full vs filtered deploy, or use WIP ignore directives: [deploy skill](.agents/skills/keystroke-deploy/SKILL.md).
|
|
75
|
+
- **Actions are leaf units** - An action never calls another action (including integration actions like `slackSendMessage`). Compose actions in a workflow, or attach an integration action directly as a workflow step / agent tool. An action may call an agent.
|
|
76
|
+
- **Workflow steps** - Workflows orchestrate actions, agent prompts, and LLM calls (`promptLlm`) as steps. There's no first-class "call another workflow" step — share logic by extracting it into `src/lib/` or an action, or expose a workflow as an agent tool (`defineWorkflowTool`) / over HTTP when you want it as its own tracked run.
|
|
77
|
+
- **Agent tools** - Agents can use actions, subagents (`defineSubagentTool`), workflows (`defineWorkflowTool`), and MCP tools as tools.
|
|
82
78
|
|
|
83
79
|
## Audit & debug (CLI)
|
|
84
80
|
|
|
85
|
-
Use the CLI
|
|
86
|
-
|
|
87
|
-
**Local** (developing / testing):
|
|
81
|
+
Use the CLI to inspect your deployed project.
|
|
88
82
|
|
|
89
83
|
```bash
|
|
90
|
-
keystroke
|
|
91
|
-
keystroke
|
|
92
|
-
keystroke workflow
|
|
93
|
-
keystroke
|
|
94
|
-
keystroke
|
|
84
|
+
keystroke workflow run <workflow-slug> --input '{}'
|
|
85
|
+
keystroke workflow runs list <workflow-slug>
|
|
86
|
+
keystroke workflow runs get <workflow-slug> <run-id> --include steps,trace
|
|
87
|
+
keystroke agent sessions list <agent-slug>
|
|
88
|
+
keystroke agent sessions get <agent-slug> <session-id> --include messages,trace
|
|
95
89
|
keystroke app list
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
**Cloud** (deployed — `keystroke config use cloud` or after deploy):
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
90
|
keystroke trigger list
|
|
102
|
-
keystroke trigger url <trigger-
|
|
103
|
-
keystroke trigger runs list <trigger-
|
|
91
|
+
keystroke trigger url <trigger-slug>
|
|
92
|
+
keystroke trigger runs list <trigger-slug>:<workflow-slug>
|
|
104
93
|
```
|
|
105
94
|
|
|
106
|
-
Read `src/` first
|
|
95
|
+
Read `src/` first; existing agents, workflows, actions, and triggers are your best map of how this project works.
|
|
96
|
+
|
|
97
|
+
## Skills
|
|
107
98
|
|
|
108
|
-
|
|
99
|
+
Whenever you work with your Keystroke project, you should review relevant skills. Skills can be found in `.agents/skills/` and are folders named with the following format: `keystroke-[name]`.
|
|
109
100
|
|
|
110
101
|
| Skill | Load when |
|
|
111
102
|
| ------------------------------------------------------------ | ---------------------------------- |
|
|
112
|
-
| [cli](.agents/skills/keystroke-cli/SKILL.md) |
|
|
103
|
+
| [cli](.agents/skills/keystroke-cli/SKILL.md) | Deploy, run, inspect; projects & auth |
|
|
113
104
|
| [deploy](.agents/skills/keystroke-deploy/SKILL.md) | Build, full/filtered deploy, WIP ignore |
|
|
114
105
|
| [agents](.agents/skills/keystroke-agents/SKILL.md) | Building or debugging agents |
|
|
115
106
|
| [workflows](.agents/skills/keystroke-workflows/SKILL.md) | Orchestration, action steps |
|
|
116
107
|
| [actions](.agents/skills/keystroke-actions/SKILL.md) | Shared steps, integration tools |
|
|
117
108
|
| [triggers](.agents/skills/keystroke-triggers/SKILL.md) | Cron, webhook, poll automation |
|
|
118
|
-
| [
|
|
109
|
+
| [channels](.agents/skills/keystroke-channels/SKILL.md) | Slack / external channel bindings |
|
|
119
110
|
| [skills](.agents/skills/keystroke-skills/SKILL.md) | `src/skills/` playbooks |
|
|
120
111
|
| [files](.agents/skills/keystroke-files/SKILL.md) | Agent workspace files |
|
|
121
112
|
| [apps](.agents/skills/keystroke-apps/SKILL.md) | Connectable apps, catalog, connect |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: keystroke-actions
|
|
3
|
-
description: Define keystroke actions — workflow steps and agent tools.
|
|
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
4
|
metadata:
|
|
5
5
|
keystroke-domain: actions
|
|
6
6
|
---
|
|
@@ -9,28 +9,54 @@ metadata:
|
|
|
9
9
|
|
|
10
10
|
One **executable unit** used everywhere: workflow steps, agent tools, and codemode host calls.
|
|
11
11
|
|
|
12
|
-
Anything that calls an external API **
|
|
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
13
|
|
|
14
14
|
## Actions are leaf units — never call an action from an action
|
|
15
15
|
|
|
16
|
-
An action's `run` must **not** call another action (yours or an integration action like `
|
|
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
17
|
|
|
18
18
|
```ts
|
|
19
19
|
// ❌ Don't: an action that calls another action
|
|
20
|
-
import {
|
|
20
|
+
import { slackSendMessage } from "@keystrokehq/slack/actions";
|
|
21
21
|
export const notify = defineAction({ slug: "notify",
|
|
22
|
-
run: async (input) =>
|
|
22
|
+
run: async (input) => slackSendMessage.run({ channel: input.channel, markdown_text: input.text }),
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
// ✅ Do: use the integration action directly as a workflow step
|
|
26
26
|
async run(input) {
|
|
27
|
-
return
|
|
27
|
+
return slackSendMessage.run({ channel: input.channel, markdown_text: buildText(input) });
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
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
32
|
|
|
33
|
-
##
|
|
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:
|
|
34
60
|
|
|
35
61
|
1. **App first** — create in the dashboard or `keystroke app create`, then `keystroke app sync <slug>` → `src/apps/<name>/app.ts`
|
|
36
62
|
2. **Connect** — `keystroke connect <slug>` (see [apps skill](.agents/skills/keystroke-apps/SKILL.md))
|
|
@@ -51,14 +77,14 @@ export const kwatchListAlerts = kwatch.action({
|
|
|
51
77
|
});
|
|
52
78
|
```
|
|
53
79
|
|
|
54
|
-
|
|
80
|
+
Use an app wrapper (over a standalone credential) when a family of actions should share one connection definition.
|
|
55
81
|
|
|
56
|
-
## Pure actions (no
|
|
82
|
+
## Pure actions (no credential)
|
|
57
83
|
|
|
58
|
-
Use `defineAction`
|
|
84
|
+
Use `defineAction` with no `credentials` when the step needs no connection at all (pure logic, local transforms):
|
|
59
85
|
|
|
60
86
|
```ts
|
|
61
|
-
import { defineAction } from "@keystrokehq/action";
|
|
87
|
+
import { defineAction } from "@keystrokehq/keystroke/action";
|
|
62
88
|
import { z } from "zod";
|
|
63
89
|
|
|
64
90
|
export const triage = defineAction({
|
|
@@ -77,7 +103,7 @@ Official integrations ship as npm packages with pre-built actions. Discover with
|
|
|
77
103
|
|
|
78
104
|
```ts
|
|
79
105
|
import { exaSearch } from "@keystrokehq/exa/actions";
|
|
80
|
-
import {
|
|
106
|
+
import { slackSendMessage } from "@keystrokehq/slack/actions";
|
|
81
107
|
```
|
|
82
108
|
|
|
83
109
|
Detail: [catalog-and-imports.md](references/catalog-and-imports.md).
|
|
@@ -98,6 +124,28 @@ export const researchSignup = defineAction({
|
|
|
98
124
|
});
|
|
99
125
|
```
|
|
100
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
|
+
|
|
101
149
|
## Where actions run
|
|
102
150
|
|
|
103
151
|
| Consumer | Usage |
|
|
@@ -9,15 +9,44 @@
|
|
|
9
9
|
|
|
10
10
|
```ts
|
|
11
11
|
import { exaSearch, exaAnswer } from "@keystrokehq/exa/actions";
|
|
12
|
-
import {
|
|
12
|
+
import { slackSendMessage } from "@keystrokehq/slack/actions";
|
|
13
13
|
import { googlesuperSendEmail } from "@keystrokehq/googlesuper/actions";
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
Catalog packages ship a pre-built app + actions — you do not author `src/apps/` for these.
|
|
17
17
|
|
|
18
|
-
## Custom integrations
|
|
18
|
+
## Custom integrations
|
|
19
19
|
|
|
20
|
-
|
|
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:
|
|
21
50
|
|
|
22
51
|
1. Create the app (dashboard or `keystroke app create --name ... --field ...`)
|
|
23
52
|
2. Sync: `keystroke app sync <slug>` → `src/apps/<name>/app.ts`
|
|
@@ -14,7 +14,7 @@ Agents are **autonomous LLM runs** with a sandbox, optional skills/files, and **
|
|
|
14
14
|
**Integration tools** — import actions from an integration package:
|
|
15
15
|
|
|
16
16
|
```ts
|
|
17
|
-
import { defineAgent } from "@keystrokehq/agent";
|
|
17
|
+
import { defineAgent } from "@keystrokehq/keystroke/agent";
|
|
18
18
|
import { exaSearch, exaAnswer } from "@keystrokehq/exa/actions";
|
|
19
19
|
|
|
20
20
|
export default defineAgent({
|
|
@@ -28,7 +28,8 @@ export default defineAgent({
|
|
|
28
28
|
**Skills + files** — static playbooks and docs in the workspace:
|
|
29
29
|
|
|
30
30
|
```ts
|
|
31
|
-
import {
|
|
31
|
+
import { defineAgent } from "@keystrokehq/keystroke/agent";
|
|
32
|
+
import { defineSandbox } from "@keystrokehq/keystroke/sandbox";
|
|
32
33
|
|
|
33
34
|
defineAgent({
|
|
34
35
|
slug: "support",
|
|
@@ -40,6 +41,46 @@ defineAgent({
|
|
|
40
41
|
|
|
41
42
|
Import actions from `@keystrokehq/<integration>/actions` (e.g. `@keystrokehq/exa/actions`, `@keystrokehq/googlesuper/actions`).
|
|
42
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 (`defineSubagentTool`) — 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
|
+
|
|
43
84
|
## Run & audit
|
|
44
85
|
|
|
45
86
|
```bash
|
|
@@ -54,19 +95,20 @@ Follow up in the same session: `--session-id <id>`.
|
|
|
54
95
|
|
|
55
96
|
| From | How |
|
|
56
97
|
| --------------- | --------------------------------------------------------- |
|
|
57
|
-
| CLI | `keystroke agent prompt {
|
|
98
|
+
| CLI | `keystroke agent prompt {slug} --message "…"` |
|
|
58
99
|
| Workflow action | `await myAgent.prompt({ message })` inside `defineAction` |
|
|
59
|
-
|
|
|
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.
|
|
60
103
|
|
|
61
104
|
## Workspace
|
|
62
105
|
|
|
63
|
-
- Skills → `/workspace/agent/skills/{
|
|
64
|
-
- Files from `src/files/{
|
|
65
|
-
- Pass `module: import.meta.url` so skills/files resolve in dev without a rebuild
|
|
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`)
|
|
66
108
|
|
|
67
109
|
## Next references
|
|
68
110
|
|
|
69
|
-
- [models.md](references/models.md) — model ids,
|
|
111
|
+
- [models.md](references/models.md) — model ids, platform LLM proxy
|
|
70
112
|
- [tools-mcp-codemode.md](references/tools-mcp-codemode.md) — actions as tools, MCP, codemode
|
|
71
113
|
- [workflows-and-testing.md](references/workflows-and-testing.md) — sessions, workflow handoff
|
|
72
114
|
|
|
@@ -5,21 +5,19 @@ model: "google/gemini-2.5-flash"; // vendor/model-id — any pi-ai or gateway ca
|
|
|
5
5
|
thinkingLevel: "high"; // optional — defaults to "medium"; use "none" to disable reasoning
|
|
6
6
|
```
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
**Local dev (direct)** — set the provider key for each vendor you use (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, …). Only models in the pi-ai direct registry resolve without gateway.
|
|
8
|
+
`thinkingLevel` accepts `off`, `minimal`, `low`, `medium`, `high`, `xhigh` (`off` disables reasoning).
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
Per-prompt override via API: `{ "message": "...", "thinkingLevel": "low" }`.
|
|
13
11
|
|
|
14
|
-
|
|
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**.
|
|
15
13
|
|
|
16
|
-
| Vendor | Example id |
|
|
17
|
-
| --------- | ----------------------------- |
|
|
18
|
-
| Anthropic | `anthropic/claude-sonnet-4.5` |
|
|
19
|
-
| OpenAI | `openai/gpt-5.5` |
|
|
20
|
-
| Google | `google/gemini-3.5-flash` |
|
|
21
|
-
| DeepSeek | `deepseek/deepseek-v3` |
|
|
22
|
-
| Moonshot | `moonshotai/kimi-k2.5` |
|
|
23
|
-
| Zhipu GLM | `zai/glm-4.5` |
|
|
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` |
|
|
24
22
|
|
|
25
23
|
After changing model, smoke-test: `keystroke agent prompt <key> --message "Hi"`.
|
|
@@ -8,7 +8,7 @@ Most agents use imported integration actions:
|
|
|
8
8
|
import { exaSearch, exaAnswer } from "@keystrokehq/exa/actions";
|
|
9
9
|
import { googlesuperFetchEmails, googlesuperSendEmail } from "@keystrokehq/googlesuper/actions";
|
|
10
10
|
|
|
11
|
-
tools: [exaSearch, exaAnswer,
|
|
11
|
+
tools: [exaSearch, exaAnswer, googlesuperFetchEmails, googlesuperSendEmail],
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
See each integration package's `actions` export for available tools.
|
|
@@ -22,10 +22,52 @@ tools: [triage],
|
|
|
22
22
|
|
|
23
23
|
Same action works in workflows and on agents.
|
|
24
24
|
|
|
25
|
+
## Subagents (delegate to another agent)
|
|
26
|
+
|
|
27
|
+
Wrap any agent as a tool with `defineSubagentTool` (from `@keystrokehq/keystroke/agent`) and add it to `tools`. The parent delegates a scoped task to the child agent:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { defineAgent, defineSubagentTool } from "@keystrokehq/keystroke/agent";
|
|
31
|
+
import { z } from "zod";
|
|
32
|
+
import researcher from "./researcher";
|
|
33
|
+
|
|
34
|
+
export default defineAgent({
|
|
35
|
+
slug: "planner",
|
|
36
|
+
systemPrompt: "Plan work. Delegate research to the researcher subagent.",
|
|
37
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
38
|
+
tools: [
|
|
39
|
+
defineSubagentTool({
|
|
40
|
+
agent: researcher,
|
|
41
|
+
name: "research",
|
|
42
|
+
label: "Research a topic",
|
|
43
|
+
parameters: z.object({ message: z.string() }), // default toMessage reads params.message
|
|
44
|
+
}),
|
|
45
|
+
],
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
25
49
|
## MCP
|
|
26
50
|
|
|
27
|
-
|
|
51
|
+
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`).
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { defineAgent, defineMcp } from "@keystrokehq/keystroke/agent";
|
|
55
|
+
|
|
56
|
+
const deepwiki = defineMcp({
|
|
57
|
+
key: "deepwiki",
|
|
58
|
+
transport: { type: "http", url: "https://mcp.deepwiki.com/mcp" },
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export default defineAgent({
|
|
62
|
+
slug: "researcher",
|
|
63
|
+
systemPrompt: "Use the DeepWiki tools to answer questions about repos.",
|
|
64
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
65
|
+
tools: [deepwiki],
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
For servers that require auth, declare credentials on the definition.
|
|
28
70
|
|
|
29
71
|
## Codemode (advanced)
|
|
30
72
|
|
|
31
|
-
Default sandbox has bash. For batch tool calls, agents can run js-exec scripts that call `await tools['action-
|
|
73
|
+
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`).
|
|
@@ -14,7 +14,7 @@ keystroke agent prompt support --message "Summarize that" --session-id <id>
|
|
|
14
14
|
keystroke agent sessions get support <session-id> --include messages,trace
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Use this when an agent misbehaves or a
|
|
17
|
+
Use this when an agent misbehaves or a channel reply looks wrong.
|
|
18
18
|
|
|
19
19
|
## Agent called from a workflow
|
|
20
20
|
|