@stratusagent/agents 0.13.5 → 0.13.6
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/package.json +2 -2
- package/skills/stratus/SKILL.md +17 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratusagent/agents",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"node": ">=22.13 <23 || >=23.4"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@stratusagent/core": "0.13.
|
|
21
|
+
"@stratusagent/core": "0.13.6"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/node": "^24.6.0",
|
package/skills/stratus/SKILL.md
CHANGED
|
@@ -24,6 +24,7 @@ Everything is under `~/.stratus/` on the daemon's machine:
|
|
|
24
24
|
| --- | --- |
|
|
25
25
|
| `config.json` | The global config, and the trusted one (see "Config"). `0600`, because a plugin's config in it can hold secrets such as `tool-shell`'s `env`, and every save keeps it that way; `stratus doctor` flags one other users can read |
|
|
26
26
|
| `credentials.json` | Provider sign-ins (shared, and any agent's own under `agentSignIns.<id>`), channel secrets (Slack's tokens and any channel plugin's, under `channels.<kind>.<agentId>`), and named credentials. `0600`, and kept that way by Stratus, which is why it is edited with `stratus credential set` and `stratus channel set` rather than by hand |
|
|
27
|
+
| `credential-audit.log` | One line per named credential added or replaced from a Slack form or a link: when, which name, whose store, added or replaced, the approver (for a form), and form or link. Names only, never a value. `0600` |
|
|
27
28
|
| `agents/<file>.md` | A soul: one agent's identity and allowlists. The file name is not the id; the id is the soul's `id:`, or derived from its `name:`. Use the id your instructions give |
|
|
28
29
|
| `agents/<id>/` | That agent's state: `sessions.db`, `memory.jsonl`, `whitelist.json` (its standing approvals), and `workspace/` |
|
|
29
30
|
| `agents/<id>/workspace/` | The agent's own working directory, where `shell.run` starts by default |
|
|
@@ -66,22 +67,27 @@ When a setting "isn't taking", these say why:
|
|
|
66
67
|
|
|
67
68
|
## Credentials and API keys
|
|
68
69
|
|
|
69
|
-
This is the question you will be asked most. A secret reaches Stratus in one of
|
|
70
|
+
This is the question you will be asked most. A secret reaches Stratus in one of these ways, and which one depends on what uses it:
|
|
70
71
|
|
|
71
72
|
- **Provider sign-ins** (the model's own key or subscription): `stratus setup` → Providers, or the dashboard. There is no `stratus login`.
|
|
72
73
|
- **One agent on its own Claude subscription**: `stratus signin set anthropic --agent <id>` at the machine, with a token from `claude setup-token` typed at the hidden prompt or piped on stdin. It replaces the shared Anthropic sign-in for that agent only, from its next turn, no restart. `stratus signin remove anthropic --agent <id>` goes back to the shared one, and `stratus signins` lists who has one. It is not a named credential: you cannot request, read, or resolve it, and `credential.request` is the wrong tool for it. If its token is refused, the turn fails with an error naming that agent's sign-in rather than moving onto the shared account.
|
|
73
74
|
- **Channel tokens** (a Slack app's tokens): `stratus setup` → Channels, or the dashboard. No agent can read them, yours included.
|
|
74
|
-
- **Named credentials**, such as `search.apiKey`, are for tools whose plugin declares that name. A web search backend is the common one: its key is always `search.apiKey`, whatever the vendor. These are the only secrets you can ask for yourself.
|
|
75
|
-
- **A shell command's
|
|
76
|
-
-
|
|
77
|
-
-
|
|
75
|
+
- **Named credentials**, such as `search.apiKey` or `github.token`, are for tools whose plugin declares that name, and for shell commands that `credentialsEnv` maps one into (next). A web search backend is the common one: its key is always `search.apiKey`, whatever the vendor. These are the only secrets you can ask for yourself.
|
|
76
|
+
- **A shell command's token** reaches `shell.run` as an environment variable. Your operator sets that up in the trusted config at the machine, and a change there needs a daemon restart:
|
|
77
|
+
- from the credential store, with `@stratusagent/tool-shell`'s `credentialsEnv`: `{ "GH_TOKEN": "github.token" }` gives each of your commands your stored `github.token` in `GH_TOKEN`, so a CLI that reads its token from a variable just works. It is a named credential like any other: your soul must list it, you can ask for it with `credential.request`, and a replaced value reaches the next command with no restart. Fleet-wide, or under `agents.<id>` for one agent;
|
|
78
|
+
- or as a value written into tool-shell's `env`, under `agents.<id>` to keep it to one agent. An agent's `env` is added to the shared one rather than replacing it, its own names win, and a name set to `null` there is withheld from that agent.
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
Either way your commands can read the value (`echo $GH_TOKEN` prints it), so only narrowly scoped tokens belong there.
|
|
81
|
+
- **An MCP server's token** is not a named credential: MCP servers never read the credential store. Your operator puts it in `servers.<name>.headers` (HTTP) or `servers.<name>.env` (stdio) in the trusted config at the machine, which every agent granted `mcp.<name>.*` uses, and the daemon needs a restart. Its replies are labelled `external`, and so is everything you remember after reading them, unless the operator sets `servers.<name>.outputTrust` to `agent` (or `unknown`) for a server they run; never `user`.
|
|
80
82
|
|
|
81
|
-
|
|
83
|
+
`passEnv` beside tool-shell's or a server's `env` forwards variables, values included, from the daemon's own environment, and only ones that are not secret belong on it.
|
|
84
|
+
|
|
85
|
+
For a named credential to reach you, three things must all be true. It is **stored**, your soul's `credentials:` **lists its name**, and a tool you have **declares it** (tool-shell declares the names its `credentialsEnv` maps). Storing grants nothing by itself. Tools use the value on your behalf, and there is no file for you to look in. The one place a value shows up is a `shell.run` command's environment, in the variable `credentialsEnv` maps it to. Stored entries are read before an environment variable of the same name, and your own entry before a shared one.
|
|
82
86
|
|
|
83
87
|
When you need a named credential you do not hold, first make sure a tool you have uses that name. A key no tool reads does nothing once stored; if what you need is a tool, say which plugin or tool is missing instead. Then:
|
|
84
88
|
|
|
89
|
+
**In Slack, the form comes first.** When someone in a Slack conversation asks how to give you a key, or you need one there, put up the form with `credential.request` instead of explaining terminal steps: the value never touches the conversation, and nobody has to be at the machine. Give the `stratus credential set` command only when they ask for it, when the tool says no form can go up here, or when they say they are at the machine. For example, asked in a Slack thread "how do I give you the GitHub token?", call `credential.request` with `name: "github.token"` and a reason, then reply: "I put a secure form in this thread. An approver enters the token there, it goes straight to the store, and I can use it from my next reply." Not a paragraph of `read -rs KEY` steps.
|
|
90
|
+
|
|
85
91
|
1. **Ask with `credential.request`**. Under the daemon every agent has it, whatever its `tools:` says (the built-in `stratus` agent, which has no soul, cannot use it). Give the `name` the tool expects, a one-sentence `reason`, and a `scope`: `agent` (yours alone, the default) or `shared` (one value stored for the whole fleet, but still granted only to you; another agent needs the name in its own soul).
|
|
86
92
|
- **A form**, in Slack, goes up in this conversation when one of `approvals.slackApprovers` can see it: a public channel, a private one with an approver in it, or a direct message with an approver.
|
|
87
93
|
- **A link** comes back otherwise, or when you pass `via: "link"`, but only if your soul's `tools:` lists `credential.request` (or you have no `tools:` key); without that, it is a form or nothing. It needs the control API, and without `api.publicUrl` it opens only on the daemon's machine. Anyone who has the link can set the key, once, within 30 minutes, with no approver involved, and opening it spends nothing. So give it only to your operator. In a shared channel, or a direct message with anyone else, do not post it: ask your operator to message you directly, and ask again there. Pass `via: "form"` to get a form or nothing.
|
|
@@ -94,7 +100,7 @@ When you need a named credential you do not hold, first make sure a tool you hav
|
|
|
94
100
|
|
|
95
101
|
(leave out `--agent` for a shared one), and to add `<name>` to `credentials:` in your soul.
|
|
96
102
|
|
|
97
|
-
Away from the machine,
|
|
103
|
+
Away from the machine, the control API and a link only **add**: they store a name nobody has stored, and refuse one already stored or supplied by the daemon's environment. The Slack form adds too, and it is the one way to **replace** a key from chat. When one you hold is expiring or was revoked, call `credential.request` with `replace: true`. That is always a form an approver answers in this conversation, never a link. It is refused before anyone is asked when you don't hold the key, when it comes from the daemon's environment, or when your `scope` doesn't match where it is stored: a shared key needs `scope: "shared"`, because replacing it changes the key for every agent granted it. The new value is used from the next tool call or command. At the machine, `stratus credential set` replaces as well, and `stratus credential remove` is the only way to remove one. Each add or replace from a form or a link appends a line to `~/.stratus/credential-audit.log`, names only. `stratus credentials` lists the names stored, shared and per agent, never the values.
|
|
98
104
|
|
|
99
105
|
A stored named credential or provider key takes effect on the next turn, with no restart. One that comes from an environment variable is fixed when the daemon starts, and the background service does not read a shell profile.
|
|
100
106
|
|
|
@@ -188,6 +194,7 @@ When a stored key "isn't found", check in this order:
|
|
|
188
194
|
| `stratus restart` | Announced drain-and-restart of the running daemon |
|
|
189
195
|
| `stratus logs` | Read the daemon's log |
|
|
190
196
|
| `stratus health` | Whether the running daemon is serving: exit 0 if so, for a container healthcheck or a probe |
|
|
197
|
+
| `stratus sessions` (also `stratus session list`) | The running daemon's sessions, newest first: status, agent, last update, id. `--agent <id>`, `--status <status>` (`running`, `pending_approval`, `failed`, `completed`, `idle`), `--limit <n>` (default 20), `--format json` |
|
|
191
198
|
| `stratus doctor` | What a run would use, and why |
|
|
192
199
|
| `stratus update` | Update Stratus and its companion packages (`--check` to look first) |
|
|
193
200
|
| `stratus dashboard` | Open the web dashboard with a one-time sign-in link |
|
|
@@ -221,10 +228,10 @@ Only at the machine can someone:
|
|
|
221
228
|
|
|
222
229
|
- enable or configure a plugin (its `env` and `headers` included), or choose an executor or memory store;
|
|
223
230
|
- install or update packages;
|
|
224
|
-
-
|
|
231
|
+
- remove a named credential, or replace one without an approver's form;
|
|
225
232
|
- raise a memory's trust (`stratus memory reassert`).
|
|
226
233
|
|
|
227
|
-
When you need one of those, ask for it precisely, once: the exact command, the file and the line to change, and what it will let you do. For example: "
|
|
234
|
+
When you need one of those, ask for it precisely, once: the exact command, the file and the line to change, and what it will let you do. For example: "In `~/.stratus/config.json`, add `"credentialsEnv": { "GH_TOKEN": "github.token" }` under `agents.kai` in the `@stratusagent/tool-shell` block, then run `stratus restart`. After that, `gh` in my shell uses the `github.token` I already hold." Not a list of possibilities, and not a guess presented as a step.
|
|
228
235
|
|
|
229
236
|
## Going further
|
|
230
237
|
|