@keystrokehq/cli 0.1.15 → 0.1.17
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/{dist-BnIugffH.mjs → dist-BRA_tOTT.mjs} +47 -5
- package/dist/{dist-BnIugffH.mjs.map → dist-BRA_tOTT.mjs.map} +1 -1
- package/dist/dist-BZBvPUyu.mjs +3 -0
- package/dist/{dist-PBiyADK0.mjs → dist-C6KqfgGN.mjs} +3 -3
- package/dist/{dist-PBiyADK0.mjs.map → dist-C6KqfgGN.mjs.map} +1 -1
- package/dist/{dist-B4pkCJsM.mjs → dist-DeRE4uJW.mjs} +2 -2
- package/dist/dist-DeRE4uJW.mjs.map +1 -0
- package/dist/{dist-BW3AMCud.mjs → dist-E9nHDRnf.mjs} +3 -3
- package/dist/{dist-BW3AMCud.mjs.map → dist-E9nHDRnf.mjs.map} +1 -1
- package/dist/index.mjs +27 -15
- package/dist/index.mjs.map +1 -1
- package/dist/{maybe-auto-update-BIarxWf3.mjs → maybe-auto-update-douMZFWJ.mjs} +2 -2
- package/dist/{maybe-auto-update-BIarxWf3.mjs.map → maybe-auto-update-douMZFWJ.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/dist/{version-DScIhncv.mjs → version-CJd1mEoq.mjs} +2 -2
- package/dist/{version-DScIhncv.mjs.map → version-CJd1mEoq.mjs.map} +1 -1
- package/package.json +2 -2
- package/dist/dist-B4pkCJsM.mjs.map +0 -1
- package/dist/dist-c4WWC9_F.mjs +0 -3
- 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
|
@@ -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
|
|
|
@@ -9,9 +9,9 @@ metadata:
|
|
|
9
9
|
|
|
10
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
11
|
|
|
12
|
-
Secrets never live in source or `.env`.
|
|
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
13
|
|
|
14
|
-
Custom actions that call external APIs **
|
|
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
15
|
|
|
16
16
|
## Two sources of apps
|
|
17
17
|
|
|
@@ -83,7 +83,7 @@ Auth kinds: `keystroke` (MCP/Composio catalog apps), `api_key` (custom fields),
|
|
|
83
83
|
|
|
84
84
|
## Connect an app
|
|
85
85
|
|
|
86
|
-
`keystroke connect <slug>` opens the
|
|
86
|
+
`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`.
|
|
87
87
|
|
|
88
88
|
**Official integrations** — the cleanest path:
|
|
89
89
|
|
|
@@ -100,34 +100,47 @@ keystroke app sync acme/internal-api
|
|
|
100
100
|
keystroke connect acme/internal-api
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
The web app **Apps** page offers the same flow.
|
|
104
104
|
|
|
105
|
-
Field names in the connect form match the app's synced template.
|
|
105
|
+
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).
|
|
106
106
|
|
|
107
|
-
##
|
|
107
|
+
## Connect what your project needs
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
A new project starts with **no connected apps**. After deploy, connect the apps it uses:
|
|
110
110
|
|
|
111
111
|
```bash
|
|
112
112
|
keystroke deploy --project <id>
|
|
113
|
-
keystroke config use cloud
|
|
114
113
|
keystroke connect google
|
|
115
114
|
keystroke connect exa
|
|
116
115
|
keystroke app list
|
|
117
116
|
```
|
|
118
117
|
|
|
119
|
-
A runtime error about a missing connection almost always means the app
|
|
118
|
+
A runtime error about a missing connection almost always means the app hasn't been connected for this project.
|
|
119
|
+
|
|
120
|
+
## Manage & bind credentials
|
|
121
|
+
|
|
122
|
+
`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:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
keystroke credentials consumers list --workflow sync # step:<slug>#<n>
|
|
126
|
+
keystroke credentials assignments assign --workflow sync --credential org/work --consumer step:fetch-gmail#0
|
|
127
|
+
keystroke credentials assignments assign --agent support --credential vault-prod --consumer vault-lookup # tool slug
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
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).
|
|
120
131
|
|
|
121
132
|
## Audit
|
|
122
133
|
|
|
123
134
|
```bash
|
|
124
|
-
keystroke app list
|
|
135
|
+
keystroke app list # org-registered apps
|
|
136
|
+
keystroke credentials list # connected instances + scope + default
|
|
137
|
+
keystroke credentials assignments list --workflow <slug> # which instance is pinned where
|
|
125
138
|
```
|
|
126
139
|
|
|
127
|
-
Failed integration call → confirm
|
|
140
|
+
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.
|
|
128
141
|
|
|
129
142
|
## Next references
|
|
130
143
|
|
|
131
|
-
- [cli-and-catalog.md](references/cli-and-catalog.md) — `keystroke app` commands, connect, scopes,
|
|
144
|
+
- [cli-and-catalog.md](references/cli-and-catalog.md) — `keystroke app` commands, connect, scopes, credential management & binding
|
|
132
145
|
|
|
133
|
-
Related: [cli](.agents/skills/keystroke-cli/SKILL.md), [actions](.agents/skills/keystroke-actions/SKILL.md), [
|
|
146
|
+
Related: [cli](.agents/skills/keystroke-cli/SKILL.md), [actions](.agents/skills/keystroke-actions/SKILL.md), [channels](.agents/skills/keystroke-channels/SKILL.md).
|
|
@@ -7,7 +7,7 @@ keystroke auth login
|
|
|
7
7
|
keystroke auth status
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
Token is stored in the OS keychain and reused for
|
|
10
|
+
Token is stored in the OS keychain and reused for all CLI commands. See [cli skill](.agents/skills/keystroke-cli/SKILL.md).
|
|
11
11
|
|
|
12
12
|
## keystroke app commands
|
|
13
13
|
|
|
@@ -23,11 +23,11 @@ All org-scoped; output is JSON.
|
|
|
23
23
|
| `app create` | Create custom org `api_key` app (`--name`, `--slug`, `--description`, `--field`) |
|
|
24
24
|
| `app sync <slug>` | Write `src/apps/<name>/app.ts` from platform template (`--dir`) |
|
|
25
25
|
|
|
26
|
-
`--field` syntax: `key`, `key:secret`, `key:optional`, or `key:secret:optional` (repeatable).
|
|
26
|
+
`--field` syntax: `key`, `key:secret`, `key:optional`, `key:public`, or combinations like `key:secret:optional` (repeatable). A bare `key` is **secret by default**; `:public` forces a non-secret field. `app create` requires at least one `--field`, and at least one of them must be required (not `:optional`).
|
|
27
27
|
|
|
28
28
|
## Connect an app
|
|
29
29
|
|
|
30
|
-
`keystroke connect <slug>` attaches secrets to an app via the
|
|
30
|
+
`keystroke connect <slug>` attaches secrets to an app via the web app connect flow:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
33
|
keystroke connect google # official OAuth
|
|
@@ -40,27 +40,58 @@ keystroke connect <slug> --print-url # deeplink without opening browser
|
|
|
40
40
|
- **Official integrations** — always prefer `keystroke connect <slug>`
|
|
41
41
|
- **Custom apps** — `keystroke app sync <slug>` first, then `keystroke connect <slug>`
|
|
42
42
|
- Slug must exist in your org registry (`app list`)
|
|
43
|
-
-
|
|
44
|
-
- Dashboard at `:3000` → **Apps** offers the same flow
|
|
43
|
+
- The web app **Apps** page offers the same flow
|
|
45
44
|
|
|
46
45
|
## Scopes
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
A connection is stored at one scope. `keystroke connect` has **no** `--scope` flag — you choose the scope in the web connect flow. To set scope from the CLI, use `keystroke credentials set <key> --scope <scope> [--project-slug <slug>]` (that command defaults to `org`).
|
|
49
48
|
|
|
50
49
|
| Scope | When |
|
|
51
50
|
| ----- | ---- |
|
|
52
|
-
| `project`
|
|
53
|
-
| `org` | Share with every user and project
|
|
51
|
+
| `project` | Tie to one project |
|
|
52
|
+
| `org` | Share with every user and project |
|
|
54
53
|
| `user` | Single user's personal connection |
|
|
55
54
|
|
|
56
|
-
At runtime resolution
|
|
55
|
+
At runtime resolution prefers the **project default first, then the org default**. Get the active project id from `keystroke config show`.
|
|
57
56
|
|
|
58
|
-
##
|
|
57
|
+
## Manage & bind credentials
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
| ----- | ------ | ------------------------------ |
|
|
62
|
-
| Model keys (`ANTHROPIC_API_KEY`), DB URL, OAuth **provider** config (`SLACK_CLIENT_ID`, `GOOGLE_*`) | yes — local boot only | — |
|
|
63
|
-
| Integration secrets resolved at runtime | — | yes |
|
|
64
|
-
| Reaches the cloud? | no | yes, when connected on cloud target |
|
|
59
|
+
Day-to-day management (output is JSON):
|
|
65
60
|
|
|
66
|
-
|
|
61
|
+
```bash
|
|
62
|
+
keystroke credentials list # every instance + scope + default flag
|
|
63
|
+
keystroke credentials get <credential-id>
|
|
64
|
+
keystroke credentials update <credential-id> --label "Prod" --default
|
|
65
|
+
keystroke credentials rotate-key <credential-id> --set apiKey=@env:ACME_API_KEY
|
|
66
|
+
keystroke credentials delete <credential-id>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`--default` marks one instance as the default for its app + scope. When several instances share a scope and none is the default, a run can't auto-resolve — set a default, or **bind** a specific instance to the step/tool that needs it.
|
|
70
|
+
|
|
71
|
+
### Bind a specific instance to a step or tool
|
|
72
|
+
|
|
73
|
+
An assignment pins an exact credential instance to one consumer. It's the **explicit selection** at the top of the resolution order, so it wins over scope defaults. List the bindable consumers first, then assign:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Workflow consumers are step correlation ids from recent runs (step:<slug>#<n>)
|
|
77
|
+
keystroke credentials consumers list --workflow sync
|
|
78
|
+
keystroke credentials assignments assign --workflow sync --credential org/work --consumer step:fetch-gmail#0
|
|
79
|
+
|
|
80
|
+
# Agent consumers are tool slugs
|
|
81
|
+
keystroke credentials consumers list --agent support
|
|
82
|
+
keystroke credentials assignments assign --agent support --credential vault-prod --consumer vault-lookup
|
|
83
|
+
|
|
84
|
+
# Omit --consumer (or pass "*") to bind every consumer on the target
|
|
85
|
+
keystroke credentials assignments assign --workflow sync --credential work
|
|
86
|
+
|
|
87
|
+
keystroke credentials assignments list --workflow sync # inspect bindings
|
|
88
|
+
keystroke credentials assignments unassign <assignment-id> # remove one
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- Exactly one of `--workflow <slug>` or `--agent <slug>` is required.
|
|
92
|
+
- `--credential` takes an instance slug: `work`, `org/work`, or `<app>/<slug>` (e.g. `linear/work`).
|
|
93
|
+
- Workflow consumer ids only appear after a run has produced `step_completed` events; `consumers list` reads them from recent runs.
|
|
94
|
+
|
|
95
|
+
## Where secrets live
|
|
96
|
+
|
|
97
|
+
App secrets are **not** read from `.env` and are **never** uploaded by `keystroke deploy` — it ships code only. Attach integration secrets by connecting the app with `keystroke connect <slug>`; they're resolved at runtime for your project.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: keystroke-channels
|
|
3
|
+
description: Let people use keystroke agents from Slack (external channels) — connect Slack, bind channels with `keystroke channel bind`, pick a listen mode. Use when setting up messaging for agents.
|
|
4
|
+
metadata:
|
|
5
|
+
keystroke-domain: channels
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# External channels
|
|
9
|
+
|
|
10
|
+
External channels route **Slack (and similar) messages** to an agent — people chat in-channel instead of using the CLI. Slack is the only channel today.
|
|
11
|
+
|
|
12
|
+
## Setup (Slack)
|
|
13
|
+
|
|
14
|
+
1. Deploy the agent you want to chat with (`keystroke deploy`)
|
|
15
|
+
2. Connect Slack once for the org: `keystroke connect slack` (or the web app **Apps** page); complete OAuth
|
|
16
|
+
3. Bind a channel to the agent (CLI below, or the agent's **External Channels** panel in the web app)
|
|
17
|
+
4. Message the bound channel per its listen mode
|
|
18
|
+
|
|
19
|
+
## Bind from the CLI
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
keystroke channel platforms list # supported platforms
|
|
23
|
+
keystroke channel accounts --platform slack # connected workspaces (team ids)
|
|
24
|
+
keystroke channel directory --platform slack --account <team-id> # channels you can bind
|
|
25
|
+
keystroke channel bind \
|
|
26
|
+
--agent support \
|
|
27
|
+
--platform slack \
|
|
28
|
+
--account <team-id> \
|
|
29
|
+
--channel <channel-id> \
|
|
30
|
+
--mode mention
|
|
31
|
+
keystroke channel list --agent support # bindings for an agent
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Listen modes (`--mode`): `mention` (only when @mentioned), `all` (every message), `dm` (direct messages). Update or remove a binding with `keystroke channel update-binding --agent <id> --binding <id> --mode all` / `keystroke channel unbind --agent <id> --binding <id>`.
|
|
35
|
+
|
|
36
|
+
`channel bind` also takes an optional `--channel-name <name>` (defaults to the channel id). Every `keystroke channel` subcommand accepts `--project <slug>` to target a non-active project; otherwise they use the active project.
|
|
37
|
+
|
|
38
|
+
## What happens at runtime
|
|
39
|
+
|
|
40
|
+
Inbound Slack event → lookup channel binding → `runPrompt` for the bound agent → reply in thread.
|
|
41
|
+
|
|
42
|
+
The agent acts **on behalf of the channel**, not the sender: it runs with its own tools, actions, and credentials regardless of who messaged. Only bind agents to channels whose members you trust with everything the agent can do.
|
|
43
|
+
|
|
44
|
+
## Audit channel-driven sessions
|
|
45
|
+
|
|
46
|
+
The CLI session source is still named `gateway`:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
keystroke agent sessions list <agent-key> --source gateway
|
|
50
|
+
keystroke agent sessions get <agent-key> <session-id> --include messages,trace
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Troubleshooting
|
|
54
|
+
|
|
55
|
+
| Issue | Check |
|
|
56
|
+
| ----------- | ------------------------------------------------------------------- |
|
|
57
|
+
| Bot silent | `keystroke agent sessions list` for errors; agent on the binding |
|
|
58
|
+
| "Choose an agent" prompt | The channel has no agent bound — bind one with `keystroke channel bind` |
|
|
59
|
+
| OAuth fails | Slack redirect URLs match your project's web app origin |
|
|
60
|
+
| Wrong agent | Re-bind with `keystroke channel bind` (or the web app panel) |
|
|
61
|
+
|
|
62
|
+
## Next references
|
|
63
|
+
|
|
64
|
+
- [slack-setup.md](references/slack-setup.md) — connect flow, testing against a deployed project
|
|
65
|
+
|
|
66
|
+
Related: [agents](.agents/skills/keystroke-agents/SKILL.md), [apps](.agents/skills/keystroke-apps/SKILL.md).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Slack channel setup
|
|
2
|
+
|
|
3
|
+
## Connect Slack
|
|
4
|
+
|
|
5
|
+
Connect the Slack app once for the org with `keystroke connect slack` — the Slack app credentials are entered in the web connect flow, not in your project's `.env`. The connected workspace stays connected; adding more agents is just a bind step.
|
|
6
|
+
|
|
7
|
+
Slack OAuth and the inbound routes mount automatically on your **deployed** project, so connecting against the cloud target works out of the box — you don't add Slack to `keystroke.config.ts`.
|
|
8
|
+
|
|
9
|
+
## Bind a channel
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
keystroke channel accounts --platform slack # find the team id
|
|
13
|
+
keystroke channel directory --platform slack --account <team-id> # find the channel id
|
|
14
|
+
keystroke channel bind --agent support --platform slack \
|
|
15
|
+
--account <team-id> --channel <channel-id> --mode mention
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`--mode` is `mention`, `all`, or `dm`. Thread follow-up is on by default; toggle it with `keystroke channel update-binding --agent <id> --binding <id> --threads` / `--no-threads`.
|
|
19
|
+
|
|
20
|
+
The web app offers the same flow from each agent's **External Channels** panel.
|
|
21
|
+
|
|
22
|
+
## Testing
|
|
23
|
+
|
|
24
|
+
Slack OAuth and the inbound event routes are handled by your **deployed** project — `keystroke dev` (local watch/rebuild) is not in the Slack delivery path. To test Slack end-to-end: `keystroke deploy`, `keystroke connect slack`, `keystroke channel bind …`, then message the bound channel and inspect the session (below).
|
|
25
|
+
|
|
26
|
+
> Self-hosting the keystroke platform is a separate concern: that setup seeds Slack app credentials via platform env vars (`SLACK_CLIENT_ID/SECRET/SIGNING_SECRET`) and a public origin (`PUBLIC_PLATFORM_PROXY_URL`). Those are **platform** vars, not part of a scaffolded user project, and `keystroke dev` does not read them.
|
|
27
|
+
|
|
28
|
+
## Audit
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
keystroke agent sessions list <agent-key> --source gateway
|
|
32
|
+
keystroke agent sessions get <agent-key> <session-id> --include messages,trace
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Common fixes
|
|
36
|
+
|
|
37
|
+
| Issue | Fix |
|
|
38
|
+
| ------------- | -------------------------------------------------- |
|
|
39
|
+
| 401 on events | Check the signing secret in the Slack connection |
|
|
40
|
+
| No reply | Session errors via `keystroke agent sessions list` |
|
|
41
|
+
| Wrong agent | Re-bind with `keystroke channel bind` |
|