@kybernesis/create 0.6.0 → 0.7.0
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/doctor.js
CHANGED
|
@@ -242,14 +242,16 @@ export async function doctor() {
|
|
|
242
242
|
const hasLocal = existsSync(join(cwd, "agent/tools/local_shell.ts"));
|
|
243
243
|
const hasManage = existsSync(join(cwd, "agent/channels/kyb.ts"));
|
|
244
244
|
if (hasLocal) {
|
|
245
|
-
// Without
|
|
246
|
-
//
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
|
|
245
|
+
// Without a credential the tools compile, appear in the tool list, and fail
|
|
246
|
+
// at the moment the user asks for something — the worst time to learn a
|
|
247
|
+
// deployment is incomplete. This is NOT a value to go and set by hand: the
|
|
248
|
+
// switch in Studio installs it, and a missing one means nobody has turned
|
|
249
|
+
// local access on yet.
|
|
250
|
+
if (process.env.KYBERNESIS_AGENT_CREDENTIAL) {
|
|
251
|
+
add("pass", "local execution can identify this agent to the control plane");
|
|
250
252
|
}
|
|
251
253
|
else {
|
|
252
|
-
add("
|
|
254
|
+
add("warn", "local execution is installed but this agent has no credential yet", "turn on 'Work on this computer' in the agent's settings in KYBER Studio — it mints and installs one; do not paste a credential by hand");
|
|
253
255
|
}
|
|
254
256
|
}
|
|
255
257
|
if (hasManage) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kybernesis/create",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "The Kybernesis agent scaffolder and FDE toolkit: one command to a governed, remembering, multiplayer, self-testing eve agent — plus doctor and upgrade.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -46,6 +46,32 @@ This exact sequence was verified against production 2026-08-05. The demo
|
|
|
46
46
|
moment for clients is step 3→4 — access appearing and disappearing from the
|
|
47
47
|
admin screen.
|
|
48
48
|
|
|
49
|
+
## It also brokers connectors and the user's own machine
|
|
50
|
+
|
|
51
|
+
Governance was the first job; the plane now also holds the two things an agent
|
|
52
|
+
cannot hold itself.
|
|
53
|
+
|
|
54
|
+
**Connectors** (`/api/connectors`, `link`, `disconnect`, `tools`, `execute`,
|
|
55
|
+
`custom`, `mcp`, `mcp/test`). Each ORG holds its own broker (Composio) API key,
|
|
56
|
+
encrypted at rest with `SECRET_ENCRYPTION_KEY` (AES-256-GCM,
|
|
57
|
+
`v1:<iv>:<tag>:<ct>`), set
|
|
58
|
+
through the admin — never an env var, never our key used for a client. The
|
|
59
|
+
agent asks the plane which services the CURRENT principal has connected;
|
|
60
|
+
`@kybernesis/connectors` turns the answer into tools for that turn only. The
|
|
61
|
+
broker's entity is `<registered-agent-name>:<userId>` — the registered NAME,
|
|
62
|
+
not the agent's UUID.
|
|
63
|
+
|
|
64
|
+
**Local access** (`/api/local-exec/*`). A device enrolls, the user grants it
|
|
65
|
+
once, and that grant is STANDING — no expiry. Requests and responses are relayed
|
|
66
|
+
as frames; the plane never executes anything. See `@kybernesis/local`.
|
|
67
|
+
|
|
68
|
+
**A client must refresh on the earlier of the token and the bundle.** They have
|
|
69
|
+
independent lifetimes: a token with 57 minutes left and a bundle with 12 will
|
|
70
|
+
start returning 401 while every dashboard says the session is fine. This cost a
|
|
71
|
+
full day, presented to the user as "log out and log back in", and the fix is one
|
|
72
|
+
line — `Math.min(tokenExpiry, bundleExpiry)`. On a 401, force a refresh and
|
|
73
|
+
retry ONCE before showing a human anything.
|
|
74
|
+
|
|
49
75
|
## Boundaries to state plainly
|
|
50
76
|
|
|
51
77
|
Control-plane grants govern the HTTP/desktop doors — NOT the Slack door
|
|
@@ -1873,6 +1873,45 @@ client with an existing ChatGPT or Claude subscription pays no incremental
|
|
|
1873
1873
|
inference cost for the pilot. Say the number out loud in the discovery
|
|
1874
1874
|
conversation — it changes the shape of the deal.
|
|
1875
1875
|
|
|
1876
|
+
**Grok, on a SuperGrok or X Premium+ subscription.** Same arrangement, without
|
|
1877
|
+
the broker: xAI's Grok Build CLI does a device login and writes a credential
|
|
1878
|
+
that is a valid bearer for `https://api.x.ai/v1`. Proven in production on Sid —
|
|
1879
|
+
twelve evals, twenty-nine gates, green on the subscription.
|
|
1880
|
+
|
|
1881
|
+
```bash
|
|
1882
|
+
# on the host, as the unix user the agent runs as
|
|
1883
|
+
curl -fsSL https://x.ai/cli/install.sh | bash
|
|
1884
|
+
grok login # device flow → ~/.grok/auth.json
|
|
1885
|
+
```
|
|
1886
|
+
|
|
1887
|
+
```ts title="agent/agent.ts"
|
|
1888
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
1889
|
+
import { grokSubscription } from "@kybernesis/exe";
|
|
1890
|
+
|
|
1891
|
+
export default defineAgent({
|
|
1892
|
+
model: grokSubscription({ model: "grok-4.6", createOpenAI }),
|
|
1893
|
+
modelContextWindowTokens: 400_000,
|
|
1894
|
+
});
|
|
1895
|
+
```
|
|
1896
|
+
|
|
1897
|
+
Three things to know before you promise it to a client:
|
|
1898
|
+
|
|
1899
|
+
- The credential is **per-machine and per-user**. It lives in a home directory.
|
|
1900
|
+
A different unix user cannot see it; a new host needs its own login.
|
|
1901
|
+
- It **expires in six hours** and the CLI refreshes it in place, so the agent
|
|
1902
|
+
must re-read the file per request. `grokSubscription` does this in a `fetch`
|
|
1903
|
+
wrapper. (Do not reach for a Proxy around the model object — the AI SDK's
|
|
1904
|
+
methods depend on their own `this` and every call dies inside the SDK.)
|
|
1905
|
+
- **Unattended refresh over days is unverified.** If nobody runs `grok` on that
|
|
1906
|
+
host for a week, it is an open question, and it would present to the client as
|
|
1907
|
+
the agent breaking for no reason.
|
|
1908
|
+
|
|
1909
|
+
**The model will lie about which model it is.** Sid, running Grok, stated it was
|
|
1910
|
+
"Claude Opus 4.6, Anthropic" and attributed it to an instruction that exists
|
|
1911
|
+
nowhere in its context. Verify from the host — the configured model id and the
|
|
1912
|
+
credential in use — never by asking the agent. Expect a client to ask it in a
|
|
1913
|
+
demo, and have the real answer ready.
|
|
1914
|
+
|
|
1876
1915
|
### 11.5 Third-party APIs: broker the credential, pin the version
|
|
1877
1916
|
|
|
1878
1917
|
Do not put a client's API token on the agent host. Put it in an exe.dev
|
|
@@ -1974,6 +2013,40 @@ Also: a long-lived channel session caches the compiled agent. After changing
|
|
|
1974
2013
|
capabilities, start a **fresh conversation** before deciding the change did not
|
|
1975
2014
|
work.
|
|
1976
2015
|
|
|
2016
|
+
**A restart script must do two more things, and both were learned from a
|
|
2017
|
+
stranded user.**
|
|
2018
|
+
|
|
2019
|
+
*Serialize restarts.* `@kybernesis/manage` fires one 20s after any change, and
|
|
2020
|
+
you will also run one by hand. Two overlapping runs both finish killing before
|
|
2021
|
+
either starts, and you end up with **two supervisors and two servers writing to
|
|
2022
|
+
one durable store** — two executors racing over the same runs. That is not a
|
|
2023
|
+
slow agent, it is a corrupt one. Take a `flock` at the top of the script, and
|
|
2024
|
+
assert exactly one server process at the bottom.
|
|
2025
|
+
|
|
2026
|
+
*Wait for in-flight turns.* eve does **not** resume a step killed mid-flight.
|
|
2027
|
+
Restart into a live turn and that turn never emits another event, the session
|
|
2028
|
+
never parks, and every later message queues behind a turn that will never
|
|
2029
|
+
finish. The user watches a spinner forever, and no further restart fixes it,
|
|
2030
|
+
because the session is stranded rather than stuck. Poll
|
|
2031
|
+
`.eve/.workflow-data/runs/*.json` for a `turnWorkflow` in `running` state and
|
|
2032
|
+
wait for it to clear — with a cap, so a wedged turn cannot block the restart
|
|
2033
|
+
that would clear it.
|
|
2034
|
+
|
|
2035
|
+
*And measure it correctly.* `pgrep -f 'server/index.mjs'` run over ssh matches
|
|
2036
|
+
**the shell running the pgrep** — the pattern is in its own command line — so it
|
|
2037
|
+
reports two servers when there is one. An entire investigation went into hunting
|
|
2038
|
+
a phantom supervisor that a `ps -eo pid,ppid,args` would have dismissed in
|
|
2039
|
+
thirty seconds. Same family as `pkill -f` killing its caller. Inside a script
|
|
2040
|
+
file it is safe (the script's command line is `bash restart.sh`); typed at a
|
|
2041
|
+
shell or sent over ssh it is not. When a process count surprises you, **list the
|
|
2042
|
+
matches before believing the number.**
|
|
2043
|
+
|
|
2044
|
+
The escape from an already-stranded session is a **session reset**
|
|
2045
|
+
(`ClientSession.reset()`, or Reset in Studio's agent settings), which releases
|
|
2046
|
+
the durable owner so the next message starts a fresh conversation. Cancelling
|
|
2047
|
+
often does not help: the executor that would honour the cancel is the one that
|
|
2048
|
+
died.
|
|
2049
|
+
|
|
1977
2050
|
### 11.9 Credential checklist — collect ALL of these from the client
|
|
1978
2051
|
|
|
1979
2052
|
Nothing here can be borrowed from another agent or another account.
|
|
@@ -2047,8 +2120,14 @@ manage, since it cannot check a grant for a name it does not know.
|
|
|
2047
2120
|
rebuilds, so it works on a VM and refuses on a read-only serverless bundle,
|
|
2048
2121
|
with that reason. Set `restartCommand` in `agent/channels/kyb.ts` or an
|
|
2049
2122
|
install completes without taking effect.
|
|
2050
|
-
4. **For `local`:
|
|
2051
|
-
|
|
2123
|
+
4. **For `local`: nothing to configure.** Setup is one switch in Studio — the
|
|
2124
|
+
agent's settings, *Work on this computer*. Behind it, Studio mints the
|
|
2125
|
+
agent's credential from the control plane, installs it over the manage
|
|
2126
|
+
channel, and records a standing grant for that machine; the agent restarts
|
|
2127
|
+
once to load it. Never hand anyone a credential to paste into an env file.
|
|
2128
|
+
The admin UI's "mint agent credential (shown once)" button remains for
|
|
2129
|
+
recovery and is not the path: a setup step that asks someone to carry a
|
|
2130
|
+
secret between two screens gets done wrong or skipped.
|
|
2052
2131
|
|
|
2053
2132
|
### 12.4 What consent looks like for the user
|
|
2054
2133
|
|
|
@@ -2065,11 +2144,23 @@ colleague knows "build me a demo" from "look at my repo".
|
|
|
2065
2144
|
|
|
2066
2145
|
### 12.5 State this plainly to the client
|
|
2067
2146
|
|
|
2068
|
-
- **
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2147
|
+
- **Two things gate a laptop, and they fail differently.** *Identity* is the
|
|
2148
|
+
agent's signed credential — "the local-execution relay rejected my
|
|
2149
|
+
credentials" means that. *Consent* is a standing per-device grant — "you have
|
|
2150
|
+
not allowed this agent to work on this computer" means that. Neither alone
|
|
2151
|
+
reaches anything. The grant is permanent on purpose: "always allow" means
|
|
2152
|
+
always, from a chat window, a schedule, or a message sent from a phone, and it
|
|
2153
|
+
ends on revoke, device removal, or disabling the agent.
|
|
2154
|
+
- **Reaching a desktop is still not its own revocable capability.** "May talk to
|
|
2155
|
+
this agent" and "may run commands on my laptop" remain one decision, taken
|
|
2156
|
+
when the person allows the machine. Say so at a client who would treat it as a
|
|
2157
|
+
surprise.
|
|
2158
|
+
- **Installing the credential restarts the agent**, and a turn in flight during
|
|
2159
|
+
that restart is lost for good — eve does not resume a step killed mid-flight.
|
|
2160
|
+
It reads as a spinner that never resolves, often alongside a "credential is
|
|
2161
|
+
unset" error from the process that was replaced. Send a new message, and reset
|
|
2162
|
+
the conversation if the session itself is stranded. §11.8 is why a restart
|
|
2163
|
+
script must wait for in-flight turns.
|
|
2073
2164
|
- **Reading a file sends it to the model.** Execution is local; the reasoning is
|
|
2074
2165
|
not. Fine for most work, and a conversation to have before a Studio points at
|
|
2075
2166
|
a regulated repository.
|
|
@@ -2077,6 +2168,89 @@ colleague knows "build me a demo" from "look at my repo".
|
|
|
2077
2168
|
means the repository is no longer only yours. Agree who reviews what Studio
|
|
2078
2169
|
writes — routines land as source files, so a normal review works.
|
|
2079
2170
|
|
|
2171
|
+
### 12.7 Connectors — the apps library
|
|
2172
|
+
|
|
2173
|
+
The Apps tab in Studio is a shelf of services a person connects in one click:
|
|
2174
|
+
Gmail, Calendar, Drive, Slack, Notion, Linear, GitHub, Attio, Outlook, HubSpot.
|
|
2175
|
+
Connecting one makes its tools appear in that person's next session.
|
|
2176
|
+
|
|
2177
|
+
**Setup is one field, and it belongs to the client.** The org's own Composio key
|
|
2178
|
+
goes in their control plane at **Settings → Connectors**, set by an owner, the
|
|
2179
|
+
same way SSO is. It is never a deployment env var and never ours: each control
|
|
2180
|
+
plane belongs to one company, and nobody's people connect their mailboxes under
|
|
2181
|
+
another org's account. Direct them to composio.dev → Settings → API Keys.
|
|
2182
|
+
|
|
2183
|
+
**What makes it one click** is that Composio has already registered the OAuth
|
|
2184
|
+
app for each service. Without a broker, every client has to create a developer
|
|
2185
|
+
app per provider — which is exactly the hour lost to Notion on the first
|
|
2186
|
+
deployment, version pin and all.
|
|
2187
|
+
|
|
2188
|
+
**Two things on every card, because both are load-bearing:**
|
|
2189
|
+
|
|
2190
|
+
*Connects as you* versus *for the company*. A user-scoped connection cannot fire
|
|
2191
|
+
from a schedule — a routine at 8am has no signed-in person. Anything a briefing
|
|
2192
|
+
depends on must be the company's connection.
|
|
2193
|
+
|
|
2194
|
+
*An admin must approve*. True for Slack, Notion, and Google Workspace. Say it on
|
|
2195
|
+
the card; a client who discovers it at the end of a redirect chain reads the
|
|
2196
|
+
product as broken.
|
|
2197
|
+
|
|
2198
|
+
**How tools reach the agent.** `@kybernesis/connectors` mounts a dynamic
|
|
2199
|
+
resolver in `agent/tools/connectors.ts`. It resolves per session from the
|
|
2200
|
+
principal on the turn, asks the control plane what that person has connected,
|
|
2201
|
+
and calls back through it to execute. The agent never holds the broker key — it
|
|
2202
|
+
proves which agent it is with its own credential, and the control plane decides
|
|
2203
|
+
whose account the call runs against.
|
|
2204
|
+
|
|
2205
|
+
Resolution is per session, not per turn: a tool set is part of the prompt, and
|
|
2206
|
+
rebuilding it every turn re-ingests the conversation at uncached prices. Pass
|
|
2207
|
+
`perTurn: true` where people connect things mid-conversation and expect them to
|
|
2208
|
+
work immediately.
|
|
2209
|
+
|
|
2210
|
+
**Say this to the client.** Their Composio account holds refresh tokens for
|
|
2211
|
+
their Google Workspace and Slack — a fourth party alongside the model provider,
|
|
2212
|
+
the host, and us. Most will not blink; a regulated one will, and the answer for
|
|
2213
|
+
them is `eve-connect`, native eve connections with no broker. That is why every
|
|
2214
|
+
card carries a `provider`.
|
|
2215
|
+
|
|
2216
|
+
**And watch the bill.** Composio prices per action. An agent in a loop is a very
|
|
2217
|
+
different cost profile from a person clicking, and that belongs in the pricing
|
|
2218
|
+
conversation before the first invoice, not after.
|
|
2219
|
+
|
|
2220
|
+
### 12.8 MCP servers — the client's own tools, local and remote
|
|
2221
|
+
|
|
2222
|
+
The MCP tab is the escape hatch from the shelf: anything with an MCP server
|
|
2223
|
+
becomes agent tools, whether it runs on the person's laptop or on a URL.
|
|
2224
|
+
|
|
2225
|
+
**Local** — a command Studio runs on that machine (`npx -y @acme/mcp`, with env
|
|
2226
|
+
vars if the server needs them). Studio keeps it alive, and the deployed agent
|
|
2227
|
+
reaches it through the same relay as local execution. This is how a client's
|
|
2228
|
+
internal tooling — the CLI nobody will ever expose to the internet — becomes
|
|
2229
|
+
something the agent can use, without opening a port.
|
|
2230
|
+
|
|
2231
|
+
**Remote** — a URL and optional headers. Studio runs the handshake before
|
|
2232
|
+
saving, so a bad URL fails at the moment someone types it rather than in the
|
|
2233
|
+
middle of a demo.
|
|
2234
|
+
|
|
2235
|
+
Consent is **per server**, and approving one does not approve the next. The
|
|
2236
|
+
discovery call (listing what a server offers) is exempt — otherwise a person is
|
|
2237
|
+
asked to approve something before they can see what it is.
|
|
2238
|
+
|
|
2239
|
+
The things that cost real sessions here:
|
|
2240
|
+
|
|
2241
|
+
- **The command in a vendor's README is often the installer**, not the server.
|
|
2242
|
+
Plaud's documented line runs an `install` subcommand and exits; the stdio
|
|
2243
|
+
server is the bare command. If a server "connects" and never answers, check
|
|
2244
|
+
that you are running the server.
|
|
2245
|
+
- **A server declares its arguments and you must honour them.** Studio passes
|
|
2246
|
+
the published `inputSchema` through to the model (`@kybernesis/local` ≥0.5.0).
|
|
2247
|
+
Before that it did not, and watching the result is the best argument for the
|
|
2248
|
+
fix: nine consecutive calls guessing the name of an argument the server had
|
|
2249
|
+
documented, steered only by error strings.
|
|
2250
|
+
- **Discovery must have a deadline.** These resolvers run before a turn and
|
|
2251
|
+
reach across a network to a laptop that might be shut. Budgeted at 6s with a
|
|
2252
|
+
five-minute cache; without that, one closed lid makes every turn hang.
|
|
2253
|
+
|
|
2080
2254
|
## 13. Known gaps — state these plainly, do not sell around them
|
|
2081
2255
|
|
|
2082
2256
|
Being straight about these is a feature. Clients have met vendors who were not.
|
|
@@ -2094,9 +2268,12 @@ Being straight about these is a feature. Clients have met vendors who were not.
|
|
|
2094
2268
|
requester or a `manage`-grant holder may approve — are the planned governance half in
|
|
2095
2269
|
`@kybernesis/enterprise`.
|
|
2096
2270
|
|
|
2097
|
-
3. **
|
|
2098
|
-
|
|
2099
|
-
|
|
2271
|
+
3. **The desktop door is built** — KYBER Studio, signed and notarized, with device-flow
|
|
2272
|
+
sign-in and in-app updates. What is NOT built is a second consent system talking to
|
|
2273
|
+
the first: the control plane holds the standing per-device grant, Studio holds
|
|
2274
|
+
per-effect permissions in a local file, and revoking in one does not revoke the
|
|
2275
|
+
other. An off-boarding story that says "we revoke access centrally" must be qualified
|
|
2276
|
+
at any client that asks the follow-up question.
|
|
2100
2277
|
|
|
2101
2278
|
4. **Off-boarding SLA equals the token TTL** (1h default) for already-minted sessions.
|
|
2102
2279
|
Suspension is immediate; revocation is not. Tune `IDENTITY_TOKEN_TTL_SECONDS` to the
|
|
@@ -2107,9 +2284,20 @@ Being straight about these is a feature. Clients have met vendors who were not.
|
|
|
2107
2284
|
a time per session — simultaneous speakers resolve in arrival order, with mid-turn
|
|
2108
2285
|
messages folded into the next turn best-effort.
|
|
2109
2286
|
|
|
2110
|
-
6. **Per-user OAuth
|
|
2111
|
-
|
|
2112
|
-
|
|
2287
|
+
6. **Per-user OAuth and local-file work are BUILT** — §12.6 and §12.7, both proven end
|
|
2288
|
+
to end. The remaining edge is the one that bites unattended: anything without a
|
|
2289
|
+
signed-in person (a schedule, a subagent) has no user principal, so a user-scoped
|
|
2290
|
+
connection is not available to it. A morning briefing built on someone's personal
|
|
2291
|
+
Gmail connection does not fail loudly — it quietly has no tools. Company-scoped
|
|
2292
|
+
connections are the answer, and that path has not yet been exercised in production.
|
|
2293
|
+
|
|
2294
|
+
Two more, worth saying because a client will meet them:
|
|
2295
|
+
|
|
2296
|
+
- **Tool volume is unmanaged.** Gmail and Calendar alone are 51 tool definitions in
|
|
2297
|
+
every prompt. Real tokens per turn, and measurably worse tool selection as a client
|
|
2298
|
+
connects more. Curation is designed, not shipped — connect what the pilot needs.
|
|
2299
|
+
- **Local MCP servers are per-machine.** A person's second laptop silently has a
|
|
2300
|
+
different set, and nothing in the UI says which machine a server is on.
|
|
2113
2301
|
|
|
2114
2302
|
7. **DM memory is per-workspace, not per-employee, unless you build it.** Splitting DMs
|
|
2115
2303
|
into one Arcana workspace per person needs a Slack-user-id → workspace-slug map in the
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Use when installing, configuring, or debugging any @kybernesis package — arcana (memory), enterprise (governance), multiplayer (Slack), engineer (build+ship), dispatch (agent-to-agent), evals (QA), create (kyb CLI) — or the Kybernesis registry. Includes every production-learned gotcha.
|
|
2
|
+
description: Use when installing, configuring, or debugging any @kybernesis package — arcana (memory), enterprise (governance), multiplayer (Slack), engineer (build+ship), dispatch (agent-to-agent), connectors (Gmail/Calendar/remote MCP), local (the user's own machine), manage (Studio→agent), exe (off-Vercel hosting), evals (QA), create (kyb CLI) — or the Kybernesis registry. Includes every production-learned gotcha.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# The Kybernesis packages
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Eleven packages, npm-public under `@kybernesis`, Apache-2.0, monorepo
|
|
8
8
|
`KybernesisAI/platform`. Registry: `https://registry.kybernesis.ai`
|
|
9
9
|
(`eve registry add @kybernesis=https://registry.kybernesis.ai/r/{name}.json`,
|
|
10
10
|
then `eve add @kybernesis/<item>`). Each covers one axis:
|
|
@@ -60,6 +60,28 @@ then `eve add @kybernesis/<item>`). Each covers one axis:
|
|
|
60
60
|
0.2.1 lesson: eve resolves remote URLs at BOOT — url() must degrade
|
|
61
61
|
(env → discovery-if-credentialed → fallbackUrl), never throw on a missing
|
|
62
62
|
credential, or the whole agent (and its evals) fails to boot.
|
|
63
|
+
- **connectors** — the user's SaaS accounts, brokered. `connectorTools()` is a
|
|
64
|
+
dynamic resolver: at turn start it asks the control plane which services THIS
|
|
65
|
+
principal has connected and returns those tools. Composio is the broker; the
|
|
66
|
+
API key is per-org, held in the control plane (never an env var, never a
|
|
67
|
+
client's key in our account). Tools are named `<toolkit>_<action>`. Also
|
|
68
|
+
exports `toolInputSchema` (broker JSON Schema → zod) and a minimal MCP client
|
|
69
|
+
for `mcp-direct` servers that speaks BOTH JSON and text/event-stream.
|
|
70
|
+
- **local** — the user's own machine, through KYBER Studio. `localShellTool`,
|
|
71
|
+
`localRead/List/Write/Edit/SearchTool`, plus `localMcpTools()` for MCP servers
|
|
72
|
+
running on that machine, relayed. Every effect is consented in Studio; the
|
|
73
|
+
agent never holds a shell. `LOCAL_INSTRUCTIONS` explains the arrangement to
|
|
74
|
+
the model — mount it or the agent will offer to do things it cannot do.
|
|
75
|
+
- **manage** — the other direction: `manageChannel()` lets Studio install
|
|
76
|
+
capabilities and write schedules onto a running agent, and `routineTools()`
|
|
77
|
+
turns "every morning at 8, brief me" into a real schedule file. This is how a
|
|
78
|
+
routine gets created from chat without anyone touching the repo.
|
|
79
|
+
- **exe** — running off Vercel. `exeModel()` for exe.dev's LLM integration,
|
|
80
|
+
`grokSubscription()` / `readGrokCredential()` for a SuperGrok or X Premium+
|
|
81
|
+
login (`grok login` → `~/.grok/auth.json`, a valid bearer for api.x.ai —
|
|
82
|
+
same shape as eve's `experimental_chatgpt()`), `hostPreflight()`, Photon
|
|
83
|
+
iMessage credentials, and a `/preview` tool. Subpaths: `/slack`, `/photon`,
|
|
84
|
+
`/sandbox`, `/preview`. See the `self-hosting` skill.
|
|
63
85
|
- **evals** — QA. `kybernesisBaseline({ agentDisplayName, routing,
|
|
64
86
|
engineer? })` = smoke + 5 memory + routing per dept + optional vision-loop
|
|
65
87
|
eval. Judge model ≠ model under test. Hermetic runs force all workspaces to
|
|
@@ -91,6 +113,36 @@ then `eve add @kybernesis/<item>`). Each covers one axis:
|
|
|
91
113
|
company-general wording (dept-flavored prompts delegate and hide tool
|
|
92
114
|
calls), no security vocabulary ("canary" triggers refusals), long routing
|
|
93
115
|
timeouts. Do not "clean up" the odd-looking patterns.
|
|
116
|
+
- **A per-turn dynamic resolver needs a deadline.** `connectorTools()` and
|
|
117
|
+
`localMcpTools()` run before every turn and reach across a network. Without a
|
|
118
|
+
budget (6s) and a cache (60s connectors, 5min local discovery) one unreachable
|
|
119
|
+
laptop makes every turn hang — the agent looks broken and nothing in the log
|
|
120
|
+
says why.
|
|
121
|
+
- **Composio: one request per toolkit.** Repeating `toolkit_slug` in a single
|
|
122
|
+
`/api/v3/tools` call returns an EMPTY list, so connecting a second service
|
|
123
|
+
silently emptied the first. The logo is at `meta.logo`, not `logo`. A 200 can
|
|
124
|
+
still carry `successful: false` — check the body, not the status.
|
|
125
|
+
- **The broker's entity is the agent's REGISTERED name**, not its UUID.
|
|
126
|
+
`<agent>:<userId>`. Studio knows agents by id; normalize before you ask the
|
|
127
|
+
broker, or a connected account looks unconnected.
|
|
128
|
+
- **MCP requires the handshake.** `initialize` AND `notifications/initialized`
|
|
129
|
+
before `tools/list`, or the server never answers. Spawn through a LOGIN shell
|
|
130
|
+
(a bare spawn misses the user's PATH and node) and always bind
|
|
131
|
+
`child.on("error")` — without it a failed spawn is an unhandled rejection
|
|
132
|
+
that takes the process, not a error message.
|
|
133
|
+
- **Translate the MCP/broker inputSchema — never pass an open object.** A tool
|
|
134
|
+
with no declared arguments makes the model guess: nine calls to find a
|
|
135
|
+
`file_id` the server had documented all along. `mcpInputSchema` (local) and
|
|
136
|
+
`toolInputSchema` (connectors) do this; keep them permissive where the server
|
|
137
|
+
says nothing.
|
|
138
|
+
- **Never wrap a model object in a Proxy.** The AI SDK's model methods depend on
|
|
139
|
+
their own `this`; intercepting them detaches it and every call dies inside the
|
|
140
|
+
SDK on a missing internal. To swap a credential, wrap `fetch` instead — and
|
|
141
|
+
re-read the credential per request: a Grok login expires in six hours and the
|
|
142
|
+
CLI refreshes it in place.
|
|
143
|
+
- **Credentials are never a user's problem.** No client ever puts a key in a
|
|
144
|
+
`.env` — broker keys live per-org in the control plane, encrypted at rest, set
|
|
145
|
+
through an admin screen. A design that ends in "paste this token" is wrong.
|
|
94
146
|
- **npm**: only the `kybernesis` account creates new packages in the scope;
|
|
95
147
|
publishes need the human's browser auth; new versions take 1–3 min to
|
|
96
148
|
propagate to anonymous reads.
|
|
@@ -25,7 +25,7 @@ kyb init <name> --host=exe --channel=<imessage|slack|telegram|none> --engineer
|
|
|
25
25
|
|
|
26
26
|
| Capability | On Vercel | Self-hosted replacement |
|
|
27
27
|
| --- | --- | --- |
|
|
28
|
-
| Model access | AI Gateway | exe.dev LLM integration (`exeModel`) — managed, BYO key, or a **ChatGPT subscription** |
|
|
28
|
+
| Model access | AI Gateway | exe.dev LLM integration (`exeModel`) — managed, BYO key, or a **ChatGPT / Grok subscription** |
|
|
29
29
|
| Slack/Photon/Linear credentials | Vercel Connect | **Portable/static credentials the client issues** |
|
|
30
30
|
| Sandbox | `vercel()` hosted | `docker()` on the host |
|
|
31
31
|
| File delivery | Vercel Blob | Blob **or** `DELIVER_DIR` + `DELIVER_BASE_URL` |
|
|
@@ -38,6 +38,44 @@ Vercel MCP connection, Linear, everything. Each becomes a static credential
|
|
|
38
38
|
someone must issue and rotate. `kyb doctor` fails loudly if a `@vercel/connect`
|
|
39
39
|
import survives into a self-hosted agent.
|
|
40
40
|
|
|
41
|
+
## Running on the client's own subscription
|
|
42
|
+
|
|
43
|
+
A client who already pays for ChatGPT Plus/Pro or SuperGrok / X Premium+ can
|
|
44
|
+
run the agent on it instead of on metered API billing. Both work the same way:
|
|
45
|
+
a CLI performs a device login on the host, writes a credential to the home
|
|
46
|
+
directory, and that credential is a valid bearer for an OpenAI-compatible
|
|
47
|
+
endpoint. eve ships `experimental_chatgpt()` for the first;
|
|
48
|
+
`@kybernesis/exe` ships `grokSubscription()` for the second.
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# on the host, as the user the agent runs as
|
|
52
|
+
curl -fsSL https://x.ai/cli/install.sh | bash
|
|
53
|
+
grok login # device flow → ~/.grok/auth.json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```ts title="agent/agent.ts"
|
|
57
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
58
|
+
import { grokSubscription } from "@kybernesis/exe";
|
|
59
|
+
|
|
60
|
+
export default defineAgent({
|
|
61
|
+
model: grokSubscription({ model: "grok-4.6", createOpenAI }),
|
|
62
|
+
modelContextWindowTokens: 400_000,
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
What this arrangement costs you, and it is worth saying to the client:
|
|
67
|
+
|
|
68
|
+
- **It is per-machine and per-user.** The login belongs to the host's home
|
|
69
|
+
directory. Moving the agent means logging in again; running it as a different
|
|
70
|
+
unix user means it cannot see the credential at all.
|
|
71
|
+
- **The token expires in hours** (Grok: six) and the CLI refreshes it in place.
|
|
72
|
+
Read it per request, never once at boot, or the agent works all afternoon and
|
|
73
|
+
starts failing authentication at dinner for no reason a user can see.
|
|
74
|
+
- **Nobody has proven unattended refresh over days.** If no one runs `grok` on
|
|
75
|
+
that host, whether the refresh keeps happening is an open question — and it
|
|
76
|
+
presents as the agent "breaking".
|
|
77
|
+
- **Ask the vendor's terms question before a client demo**, not after.
|
|
78
|
+
|
|
41
79
|
## The failure modes, each of which cost a real session
|
|
42
80
|
|
|
43
81
|
- **Docker ships disabled on some images.** exe.dev's exeuntu runs
|
|
@@ -144,3 +182,20 @@ yesterday's agent. Assert the process started AFTER the build it should serve
|
|
|
144
182
|
(`scripts/eve-server.sh` and the restart pattern in `@kybernesis/exe` do this).
|
|
145
183
|
Related: a long-lived channel session caches the compiled agent, so start a
|
|
146
184
|
fresh conversation after changing capabilities.
|
|
185
|
+
|
|
186
|
+
A restart script also has to **serialize** (`flock`, released by the child with
|
|
187
|
+
`9>&-`) and **wait for in-flight turns** — eve does not resume a step killed
|
|
188
|
+
mid-flight, and restarting into a live turn strands the session behind a turn
|
|
189
|
+
that will never finish.
|
|
190
|
+
|
|
191
|
+
Run restarts **detached** from your ssh connection —
|
|
192
|
+
`setsid nohup bash restart.sh >/tmp/r.log 2>&1 </dev/null &` — or a dropped
|
|
193
|
+
connection SIGHUPs the script halfway through and leaves exactly the mess it
|
|
194
|
+
exists to prevent.
|
|
195
|
+
|
|
196
|
+
**And measure it correctly.** `pgrep -f 'server/index.mjs'` typed over ssh
|
|
197
|
+
matches the shell running it: the pattern is in that shell's own command line,
|
|
198
|
+
so it reports two servers when there is one. A whole investigation went into a
|
|
199
|
+
phantom "second server" that `ps -eo pid,ppid,args` would have dismissed
|
|
200
|
+
immediately. Inside a script file it is safe; typed at a shell it is not. List
|
|
201
|
+
the matches before you believe the count.
|