ghosty-acp 0.0.6 → 0.0.7

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ghosty-acp",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Conecta tu editor a un agente ACP remoto. Puente entre entrada/salida estándar y WebSocket, sin dependencias.",
5
5
  "type": "module",
6
6
  "bin": {
package/skills/README.md CHANGED
@@ -11,7 +11,7 @@ npx skills add https://ghosty.studio
11
11
 
12
12
  | Skill | What for |
13
13
  |---|---|
14
- | `ghosty-agent` | configure a Ghosty Studio agent through its API: identity, model, files, skills, MCP servers |
14
+ | `ghosty-agent` | configure, test and chat with a Ghosty Studio agent with the `ghosty` CLI (its REST API as a fallback): identity, model, files, skills, MCP servers, databases, demos |
15
15
  | `ghosty-docs` | read the Ghosty docs from an agent: markdown pages, `llms.txt`, the docs MCP server |
16
16
  | `ghosty-acp` | connect Zed, VS Code, JetBrains or Neovim to the agent over ACP |
17
17
  | `ghosty-recipe` | write or review an agent recipe (`.recipe.yaml`) to upload in the creator |
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: ghosty-agent
3
- description: Configure a Ghosty Studio agent (identity/system prompt, model, knowledge files in its machine, skills, custom MCP servers) through its REST API using the agent token. Use when the user asks to set up, tune, teach, or connect their Ghosty agent, or mentions ghosty.studio.
3
+ description: Configure, test and chat with a Ghosty Studio agent (identity/system prompt, model, knowledge files in its machine, skills, custom MCP servers) with the `ghosty` CLI, or its REST API as a fallback. Use when the user asks to set up, tune, teach, test or connect their Ghosty agent, or mentions ghosty.studio.
4
4
  license: MIT
5
- compatibility: Needs curl or any HTTP client and network access to https://www.ghosty.studio
5
+ compatibility: Needs Node 22+ (for npx @ghostystudio/cli) or curl, and network access to https://www.ghosty.studio
6
6
  metadata:
7
7
  author: ghosty-studio
8
- version: "1.2"
8
+ version: "1.11"
9
9
  ---
10
10
 
11
11
  # Configure a Ghosty Studio agent
@@ -13,45 +13,103 @@ metadata:
13
13
  A Ghosty Studio agent runs on its own isolated machine (disk, terminal, memory). You configure it
14
14
  over HTTPS with **its own token**; nothing runs on the user's computer.
15
15
 
16
- ## Setup (once)
16
+ ## Setup (once): use the CLI
17
17
 
18
- 1. Ask the user for the agent id and token. Both are in Ghosty Studio → **Agentes → their agent →
19
- Conexión con tu editor → Generar token** (token looks like `gat_…`; id is in the page URL
20
- `/app/agents/<id>`).
21
- 2. Keep them in env vars, never in command arguments or committed files:
18
+ Run it with `npx -y @ghostystudio/cli <command>` (or `ghosty <command>` if installed globally).
19
+ Always pass `--json` and read stdout as JSON; notices go to stderr.
20
+
21
+ **Sign in (the user just opens a link):**
22
22
 
23
23
  ```bash
24
- export GHOSTY_AGENT_ID="<id>"
25
- export GHOSTY_AGENT_TOKEN="gat_…"
24
+ npx -y @ghostystudio/cli login --json
25
+ # first line: {"event":"login_url","url":"…"} → show this link to the user and ask them to open it
26
+ # then: {"event":"logged_in","email":"…"} → done; the session is saved and renews itself
26
27
  ```
27
28
 
28
- Base URL: `https://www.ghosty.studio/api/v2/agents/$GHOSTY_AGENT_ID`. Every call:
29
- `-H "Authorization: Bearer $GHOSTY_AGENT_TOKEN"`. Wrong token or id → `404` (do not retry).
29
+ Run it in the background or with a long timeout: it waits (up to 5 min) for the user to sign in
30
+ in their browser. Any command exiting with code **3** means "not signed in" → run `login` again.
31
+
32
+ **Remote box, SSH or CI?** `login` switches by itself to a device code (`--device` forces it): the
33
+ `login_url` line then carries `"code"` too; pass the link to the user and tell them to check the
34
+ code matches before authorizing.
35
+
36
+ **Several accounts** (the user's and a customer's)? `--profile <name>` (or `GHOSTY_PROFILE`) keeps
37
+ a separate saved session per name: `ghosty --profile cliente login --json`, then the same
38
+ `--profile` on every command.
39
+
40
+ Then `ghosty agents ls --json` gives the agent ids.
41
+
42
+ **No browser available** (CI, remote box)? Ask the user for the agent token (Ghosty Studio →
43
+ **Agentes → their agent → Conexión con tu editor → Generar token**, looks like `gat_…`) and put it
44
+ in the environment, never in arguments or committed files: `export GHOSTY_TOKEN="gat_…"`. It
45
+ reaches only that agent (no `agents ls`, no `chat`).
46
+
47
+ Exit codes: `0` ok · `1` API error (read the message, don't retry blindly) · `2` usage error
48
+ (check `--help`) · `3` not signed in.
49
+
50
+ ### Fallback: raw HTTP
51
+
52
+ If Node is not available, use curl with the agent token. Base URL:
53
+ `https://www.ghosty.studio/api/v2/agents/$GHOSTY_AGENT_ID`, header
54
+ `Authorization: Bearer $GHOSTY_AGENT_TOKEN`. Wrong token or id → `404` (do not retry). Shapes in
55
+ `references/api.md`.
56
+
57
+ **Agent hosted on EasyBits** (`ghosty-lite` / `goose` template)? Same contract for `/prompt`,
58
+ `/files`, `/skills/{slug}`, `/mcp`, `/restart`: base `https://www.easybits.cloud/api/v2/agents/$AGENT_ID`
59
+ with `Authorization: Bearer $EASYBITS_API_KEY` (the owner's key, not an agent token). Identity
60
+ there is `PATCH /` with `{ systemPrompt, systemPromptMode }` (`replace` = only your prompt).
30
61
 
31
62
  ## Know the engine first
32
63
 
33
- `GET …?fields=name,engine,model,hasMachine,prompt` before anything else. `hasMachine` decides
34
- what applies:
64
+ `ghosty agents get <id> --fields name,engine,model,needsRestart,prompt --json` before anything else. Every agent
65
+ has its own machine and disk, so files, skills, MCP and `try` work on all of them. `needsRestart` only
66
+ says how new config gets in:
35
67
 
36
- | `hasMachine` | Engines | You can | Identity (`prompt`) takes effect |
68
+ | `needsRestart` | Engines | Files, skills and MCP take effect | Identity (`prompt`) takes effect |
37
69
  |---|---|---|---|
38
- | `true` | Ghosty · Lite, Goose | everything: files, skills, MCP, `restart`, `try` | on the next conversation, or right away with `POST …/restart` |
39
- | `false` | Claude, Codex, DeepSeek | `GET`, `PATCH` (name, model, prompt, webSearch, channels) and `try` | on the next conversation; **never call `restart`** (it answers `409`) |
70
+ | `true` | Ghosty · Lite, Goose (ACP) | skills after `ghosty agents restart <id>`; MCP restarts by itself; files right away | on the next conversation, or right away with `restart` |
71
+ | `false` | Claude, Codex, DeepSeek, Gemini (pool) | on the next turn, by themselves | on the next turn; **never call `restart`** (it answers `409 restart_no_aplica`) |
40
72
 
41
- The `PATCH` response carries a `nota` saying which case you are in. Files, skills and MCP on a
42
- machine-less engine answer `409 agente_sin_maquina`: tell the user and stop.
73
+ The `PATCH` and skill responses carry a `nota` saying which case you are in. (`hasMachine` is
74
+ legacy and always `true`.)
43
75
 
44
76
  ## What you can do
45
77
 
46
78
  | User asks | Do |
47
79
  |---|---|
48
- | "set its identity / persona / system prompt" | write it with `references/identity.md`, `PATCH` with `{"prompt": "..."}`, then `restart` only if `hasMachine` |
49
- | "change the model" | `GET` first (lists `models`), then `PATCH {"model": "<id>"}` (restarts by itself) |
50
- | "give it these files / documents / knowledge" | `PUT …/files/<name>` with raw bytes, one call per file |
51
- | "install / teach it a skill" | `PUT …/skills/<slug>` with the SKILL.md markdown (+ assets), then `POST …/restart` |
52
- | "connect it to this MCP server" | `PUT …/mcp` with the full list of servers (it replaces; restarts by itself) |
53
- | "what does it have?" | `GET …?full=1` → prompt, model, files, skills, mcp (`?fields=` to read just some) |
54
- | "does it work? / test it" | `POST …/try {"text": "…"}` → the agent's answer (see Verify) |
80
+ | "create a new agent" | `ghosty agents create --name <name> [--engine <engine>] [--model <model-id>] [--prompt-file PROMPT.md] [--env K=V,…] --json` → `id`. A model outside the engine answers 400 with the valid list |
81
+ | "set its identity / persona / system prompt" | write it with `references/identity.md` to a file, `ghosty agents set <id> --prompt-file PROMPT.md`, then `ghosty agents restart <id>` only if `needsRestart` |
82
+ | "let it see my Drive / use my connector" | `ghosty agents set <id> --connect google-drive` (owner only; the account must have it connected first). Files are the ones the owner picked in Conectores → Google Drive |
83
+ | "delete this agent" | confirm with the user first, then `ghosty agents rm <id>` (owner only; `409` names the workspace where it is active) |
84
+ | "switch it to another engine" | `ghosty agents set <id> --engine <engine> [--model <model-id>]` (the model belongs to the NEW engine) |
85
+ | "change the model" | `ghosty agents get <id> --json` (lists `models`), then `ghosty agents set <id> --model <model-id>` (restarts by itself) |
86
+ | "make it think more / less" | Ghosty · Lite: `ghosty agents set <id> --env GHOSTY_THINKING_EFFORT=off\|low\|medium\|high\|max`. Codex: `--env FLEET_EFFORT=none\|minimal\|low\|medium\|high\|xhigh\|max` |
87
+ | "give it these files / documents / knowledge" | `ghosty files put <id> <name> --file <local>`, one per file |
88
+ | "install / teach it a skill" | `ghosty skills add <id> <slug> --file SKILL.md` (or just `<slug>` from the catalog: `ghosty skills ls <id>`), then `ghosty agents restart <id>` only if `needsRestart` |
89
+ | "connect it to this MCP server" | `ghosty mcp get <id> --json > servers.json`, add the server, `ghosty mcp set <id> --file servers.json` (replaces; restarts by itself) |
90
+ | "what does it have?" | `ghosty agents get <id> --json` → prompt, model, files, skills, mcp |
91
+ | "does it work? / test it" | `ghosty try <id> "…" --json` → the agent's answer (see Verify) |
92
+ | "talk to it / ask it something" | `ghosty chat <id> "…" --json` → streams `chunk` lines, ends with `done` |
93
+ | "test it as a WhatsApp customer / with a photo / with earlier context" | `ghosty try <id> "…" --waba --session <made-up phone> [--media FILE] [--history FILE --reset] --json` → `sent[]` (what it would send; nothing leaves) |
94
+ | "replay these real conversations" | `ghosty try <id> --replay sample.json --out ./replay [--max N]`; read `./replay/replay.json`; `--resume` if it was cut |
95
+ | "is it configured right? / why does it answer badly?" | `ghosty agents doctor <id> --json` → `checks[]` with `level` (ok/warn/error) and a `fix` command each; exit 1 = something to fix |
96
+ | "why did it fail? / it didn't answer" | `ghosty turns ls <id> --errors --since 24h --json` → failed turns with their `error` |
97
+ | "give it this database / what can it write" | `ghosty dbs ls <id>`, `ghosty dbs tables <id> <db>`, `ghosty dbs grant <id> <db> [--external-write t1,t2]` (tables it may write from WhatsApp/Messenger) |
98
+ | "copy its data from EasyBits" | `ghosty dbs import <id> <db> --from easybits:<db-id> --dry-run` first (needs `EASYBITS_API_KEY`), show the plan, then run without `--dry-run` (`--yes` if replacing rows) |
99
+ | "let it read / send this document" | `ghosty agents docs ls <id>`, `ghosty agents docs grant <id> "<name>" [--write] [--no-deliver]` |
100
+ | "answer with voice notes" | `ghosty agents set <id> --voice elevenlabs:<voice-id>\|kokoro:em_santa --voice-replies auto` |
101
+ | "answer this WhatsApp number" | confirm with the user (real customers), then `ghosty channels whatsapp enable <id> <number> --yes`; `--dry-run` shows the plan |
102
+ | "save my ElevenLabs / MercadoPago key" | never put the key in a command: ask the user to run `ghosty credentials set <provider>` themselves (hidden prompt), or use `--from-env VAR` |
103
+ | "remove this skill" | `ghosty skills rm <id> <slug> --yes` keeps a local copy and returns `restore`; `ghosty skills get <id> <slug>` to back one up first |
104
+ | "how much have I used? / am I out of usage?" | `ghosty usage --json` → `plan.name`, `week.pct` / `month.pct` (0–1), `exhausted` |
105
+ | "let people try it without an account / share a demo" | `ghosty agents demo <id> --slug <name> --on [--vence "YYYY-MM-DDTHH:MM"] [--welcome T] [--starter T] [--chips "a\|b"] --json` → `url`; no flags = status; `--rotate` if the link leaked, `--off` to stop |
106
+ | "what files are in my account?" | `ghosty me files ls [--kind document] --json`; `me files upload <path>`, `me files rm <file-id>` |
107
+ | "clean up the board / archive test cards" | `ghosty board archive <id> --integration X \| --column X \| --before 30d --dry-run` first, then with `--yes` after the user confirms (reversible) |
108
+ | "which conversations does it have?" | `ghosty conversations ls <id> --json`; continue one with `ghosty chat <id> "…" --conversation <conv-id>` |
109
+ | "what's in its database? / fix this row" | `ghosty dbs query <id> <db> "SELECT …" [--arg V]… --json` (read only); `--write` only for a change the user asked for |
110
+ | "stop giving it this database" | `ghosty dbs revoke <id> <db>` (prints the `grant` that undoes it) |
111
+ | "give an agent to each of MY customers (partner)" | not for a normal owner: see https://www.ghosty.studio/docs/cli/partners.md (`ghosty partner --help`) |
112
+ | "have it do X every day / at 9 / remind me" | `ghosty schedule add <id> "…" --at ISO \| --in 30m [--every 12h --until ISO] [--title T]`; each run notifies the user's phone, an answer of exactly `OK` stays silent. `ghosty schedule ls|rm <id>` |
55
113
 
56
114
  Read `references/api.md` for exact request/response shapes before calling.
57
115
 
@@ -67,10 +125,11 @@ Read `references/api.md` for exact request/response shapes before calling.
67
125
  - **MCP `PUT` replaces the whole list.** `GET …/mcp` first and send back the existing servers plus
68
126
  the new one. Only `https://` URLs for HTTP servers; stdio servers need the binary to exist in the
69
127
  agent's machine (Node and Python are there).
70
- - **Engines without their own machine** (Claude, DeepSeek, Codex) accept `GET`/`PATCH` (identity, model) only; files, skills, MCP and restart answer `409 agente_sin_maquina`. Tell the user and stop; do not retry.
128
+ - **Pool engines** (Claude, Codex, DeepSeek, Gemini) have their own machine too: files, skills and MCP work and enter on the next turn. Only `restart` answers `409 restart_no_aplica` there; skip it.
71
129
  - **Restart is not free**: it cuts a turn in progress. Batch changes, restart once at the end.
72
130
  - Files go to the agent's working directory; tell the user the agent can `ls` them. Max 10 MB each.
73
131
  - Never print the token back to the user or into logs.
132
+ - **Destructive commands need `--yes`** when you run them (no terminal): `agents rm`, `files rm`, `skills rm`, `credentials rm`, `board archive`, `dbs import` over existing rows, `channels whatsapp enable`. Confirm with the user BEFORE adding it; prefer `--dry-run` first where it exists.
74
133
 
75
134
  ## Verify
76
135
 
@@ -86,10 +145,10 @@ exactly what changed, read the answer and tell the user whether it matches:
86
145
  | model | `¿Qué modelo eres?` → the label from `models` |
87
146
 
88
147
  ```bash
89
- curl -s -X POST "$B/try" -H "Authorization: Bearer $GHOSTY_AGENT_TOKEN" \
90
- -H "Content-Type: application/json" -d '{"text":"¿Quién eres y qué haces?","reset":true}'
148
+ npx -y @ghostystudio/cli try <id> --reset --json
149
+ npx -y @ghostystudio/cli try <id> "¿Quién eres y qué haces?" --json
91
150
  ```
92
151
 
93
- `reset: true` starts from a clean memory; use `session` to keep several test threads apart. A
152
+ `--reset` starts from a clean memory; use `--session <name>` to keep several test threads apart. A
94
153
  machine that was asleep takes 5–15 s on the first call. Then tell the user in one line what
95
154
  changed and what the agent answered.
@@ -5,9 +5,9 @@ Base: `https://www.ghosty.studio/api/v2/agents/{id}` · Auth: `Authorization: Be
5
5
  Full spec: https://www.ghosty.studio/openapi.yaml · Docs: https://www.ghosty.studio/docs/configurar
6
6
 
7
7
  ## GET /
8
- Returns `{ id, name, engine, hasMachine, model, models: [{id,label}], prompt, channels, webSearch, mcp }`.
9
- `hasMachine` (bool) says whether files/skills/MCP/restart exist for this engine.
10
- Add `?full=1` to also get `files: [{path,size}]` and `skills: [{slug,description,files}]`
8
+ Returns `{ id, name, engine, hasMachine, needsRestart, model, models: [{id,label}], prompt, channels, webSearch, mcp, messengerPages: [{pageId,pageName}], starters, tools: { gs: {name: bool}, extensions: {name: bool} } }`.
9
+ Every agent has its own machine and disk: files, skills and MCP work on all engines. `needsRestart` (bool) is true for ACP engines (Ghosty · Lite, Goose), where new skills enter after `POST /restart`; on pool engines they enter on the next turn. `hasMachine` is legacy and always `true`.
10
+ Add `?full=1` to also get `files: [{path,size}]`, `skills: [{slug,description,files}]` and `extensions: [{name,enabled}]`
11
11
  (wakes the machine if asleep). Add `?fields=prompt,model` to get only those keys (`id` always).
12
12
 
13
13
  ```bash
@@ -15,7 +15,10 @@ curl -s "$B" -H "Authorization: Bearer $GHOSTY_AGENT_TOKEN"
15
15
  ```
16
16
 
17
17
  ## PATCH /
18
- Body: any of `{ "name", "model", "prompt", "webSearch": bool, "channels": { "teams": bool } }`.
18
+ Body: any of `{ "name", "model", "prompt", "webSearch": bool, "channels": { "teams": bool, "web": bool, "whatsapp": bool, "messenger": bool }, "starters": ["…up to 5, ≤80 chars"], "tools": { "gs": { "<name>": bool }, "extensions": { "<name>": bool } } }`.
19
+ `tools.gs` today: `programar_seguimiento` (schedule a future turn), `archivo_enviar` (send a file the agent produced — an https URL — to the person it is talking to: photo/audio/document on WhatsApp and Messenger, a link elsewhere) and `actualizar_identidad` (the agent rewrites or appends to its own prompt — it only works when the owner talks to it from Studio or the Mac app; from Messenger/WhatsApp/Teams the call is refused).
20
+ `tools.canales` decides per channel: `{ "canales": { "messenger": { "actualizar_identidad": false } } }` (channels: `chat` = Studio/Mac app, `teams`, `whatsapp`, `messenger`, `programado`, `prueba`; the GET returns the effective matrix). By default `actualizar_identidad` is only on in `chat`.
21
+ `tools` turns tools off (`false`) or back on (`true`) by name and merges with what is saved. `tools.gs` are the tools gs lends the agent (the GET lists them all with their state); `tools.extensions` are the machine's `config.yaml` extensions (`developer` = shell + files, `todo`, `analyze`, `easybits`…; `?full=1` returns the real list as `extensions`) and changing them restarts the machine. The veto is enforced: an off tool disappears from the list and is refused when called.
19
22
  Response: the same as GET plus `aplicado: ["set-prompt", …]` and, after a `prompt` change, `nota`
20
23
  telling whether a `restart` applies (machine) or the identity simply enters on the next
21
24
  conversation (no machine). `model` restarts the agent.
@@ -38,6 +41,9 @@ curl -s -X PUT "$B/files/precios-2026.pdf" -H "Authorization: Bearer $GHOSTY_AGE
38
41
  ## PUT /skills/{slug} · DELETE /skills/{slug} · GET /skills
39
42
  Body: `{ "markdown": "<SKILL.md content>", "assets": [{ "name": "scripts/x.py", "contentBase64": "…" }] }`.
40
43
  Max 25 MB total. Then `POST /restart` so the agent loads it.
44
+ `GET /skills` also returns `community: [{slug, description, repo, url, license, installed}]` — a curated
45
+ catalog of open-source skills (grill-me, caveman, ponytail, karpathy-guidelines, frontend-design,
46
+ test-driven-development…). Install one with `PUT /skills/{slug}` and body `{ "fromCatalog": true }` (no markdown needed).
41
47
 
42
48
  ```bash
43
49
  jq -n --rawfile md SKILL.md '{markdown:$md}' | \
@@ -52,9 +58,35 @@ Body: `{ "servers": [ …full list… ] }`. Each server is one of:
52
58
 
53
59
  Names: `a-z 0-9 - _`, max 20 servers. The agent restarts automatically.
54
60
 
61
+ ## GET /whatsapp · PUT /whatsapp
62
+ Which WhatsApp numbers this agent answers. Numbers belong to the workspace and are paired from Sales
63
+ (`salesUrl`); here you only choose who answers. `PUT {"numbers": ["<id>", …]}` leaves the agent
64
+ answering exactly those (one number → one agent; unchecking mutes it, the pairing stays).
65
+
66
+ ```bash
67
+ curl -s "$B/whatsapp" -H "Authorization: Bearer $GHOSTY_AGENT_TOKEN"
68
+ ```
69
+ → `{ numbers: [{id, label, mine, takenByOther}], hasSales, salesUrl }`
70
+
71
+ ## GET /bundle · POST /bundle
72
+ The whole agent as an Eve-style directory (`instructions.md`, `skills/<slug>/SKILL.md`, `knowledge/…`, `mcp.json`),
73
+ as JSON: `{ "layout": "eve", "files": [{ "path", "contentBase64" }] }`. `POST` takes the same shape and imports
74
+ it: `instructions.md` → prompt, `skills/x.md` or `skills/x/SKILL.md` → skills (a frontmatter is added when missing),
75
+ `knowledge/…` → files. Eve's `tools/`, `channels/`, `schedules/` are not executed and come back in `ignorado`.
76
+
77
+ ```bash
78
+ curl -s "$B/bundle" -H "Authorization: Bearer $GHOSTY_AGENT_TOKEN" > agent.json
79
+ ```
80
+
81
+ ## PATCH / — connectors
82
+ `{ "connectors": { "google-drive": {} } }` grants the agent access to that account connector; `null` removes it. Drive also takes `files` (ids) and `clientWrite`. Owner only: `403` with a `gat_` token.
83
+
84
+ ## DELETE /
85
+ Deletes the agent and its machines. Owner only (`403` for an editor or a `gat_` token); `409` if a workspace has it active (the message names it). → `{ deleted: id }`.
86
+
55
87
  ## POST /restart
56
- → `{ reiniciado: true }`. Cuts a running turn; disk survives. Only with `hasMachine: true`;
57
- otherwise `409 agente_sin_maquina`.
88
+ → `{ reiniciado: true }`. Cuts a running turn; disk survives. Only with `needsRestart: true`;
89
+ otherwise `409 restart_no_aplica` (pool engines load new config on the next turn by themselves).
58
90
 
59
91
  ## POST /try
60
92
  Body: `{ "text": "…", "session"?: "a-z0-9_-", "reset"?: bool }`. One full turn to text, no stream,
@@ -70,5 +102,5 @@ curl -s -X POST "$B/try" -H "Authorization: Bearer $GHOSTY_AGENT_TOKEN" \
70
102
 
71
103
  ## Errors
72
104
  `400` invalid body (message in `error`) · `404` unknown id/token · `405` wrong method ·
73
- `409 agente_sin_maquina` files, skills, MCP and restart need an engine with its own machine (Ghosty · Lite or Goose); `GET`/`PATCH` work on every engine ·
105
+ `409 restart_no_aplica` only on `POST /restart` for pool engines (they load new config on the next turn; only Ghosty · Lite and Goose restart). Files, skills, MCP, `GET`/`PATCH` work on every engine: the agent's **bundle** (`instructions.md`, `skills/`, `knowledge/`) lives in Studio (`storage: "bundle"`) and is seeded into the worker's cwd on each turn when it changed; on machines (`storage: "box"`) it is also written to `/data/agent` and `/data/work` ·
74
106
  `413` too big · `502` saved but the machine did not take it (retry `POST /restart`).