zillion-agent 0.3.6__tar.gz

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.
@@ -0,0 +1,331 @@
1
+ Metadata-Version: 2.4
2
+ Name: zillion_agent
3
+ Version: 0.3.6
4
+ Summary: Zillion for your agent — API MCP server (VMs, sandboxes, credit, SSH keys), Roka chat MCP server and terminal chat, with browser sign-in.
5
+ Author: Zillion Network
6
+ License: Proprietary
7
+ Project-URL: Homepage, https://app.zillion.network
8
+ Keywords: zillion,mcp,agent,vm,sandbox
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+ Requires-Dist: websockets>=12.0
19
+ Requires-Dist: mcp<2,>=1.21.1
20
+
21
+ # zillion_agent
22
+
23
+ Zillion for your own agent (Codex, Claude Code, Cursor, any MCP host) and your
24
+ terminal. Two interfaces, one browser sign-in:
25
+
26
+ - **API MCP** (`zillion-agent api`) — the portal's functions as tools: buy and
27
+ manage VMs and sandboxes, check credit and usage, manage SSH keys. The tools run
28
+ the portal's own operations, so prices, checks and confirmations are the same as
29
+ on the portal.
30
+ - **Roka** — chat with the Zillion Agent (Roka):
31
+ - **Roka MCP** (`zillion-agent mcp`) — async `zillion_send` / `zillion_poll`
32
+ tools, so a long Roka task never blocks your agent.
33
+ - **Terminal chat** (`zillion-agent chat`) — streams Roka live.
34
+
35
+ Account settings, Telegram linking, access tokens and top-ups are not in the
36
+ adapter; they stay on the portal (`https://app.zillion.network`).
37
+
38
+ ## Prerequisites
39
+
40
+ 1. **Python 3.10+** and a recent pip (`python3 -m pip install -U pip`).
41
+ 2. **A Zillion account** — register on the portal; registration is portal-only.
42
+
43
+ ## Install
44
+
45
+ The package is `zillion-agent` on PyPI. Any of these works; a tool install keeps
46
+ it apart from your other Python packages:
47
+
48
+ ```bash
49
+ uv tool install zillion-agent # or: pipx install zillion-agent
50
+ # or: python3 -m pip install --user zillion-agent
51
+ zillion-agent setup # registers the servers with your agent apps, then signs you in
52
+ ```
53
+
54
+ Check the name: it is `zillion-agent`, from the regular PyPI index, and nothing
55
+ else (not a fork, a similar name or another index).
56
+
57
+ ### Updating
58
+
59
+ ```bash
60
+ zillion-agent update # installs the newest release, then runs setup again
61
+ zillion-agent update --check # only says whether there is one
62
+ zillion-agent --version
63
+ ```
64
+
65
+ `update` reads the newest release from PyPI, checks the downloaded wheel against
66
+ its published sha256, and installs that file the way the adapter was installed
67
+ (uv tool, pip or pipx). On Windows it prints the command to run instead.
68
+
69
+ If you installed a beta from TestPyPI, `zillion-agent update` moves you to the
70
+ PyPI releases; nothing else is needed.
71
+
72
+ Restart the agent apps afterwards: they keep the MCP servers running as
73
+ subprocesses, which run the old code until restarted. Your sign-in is kept.
74
+
75
+ ### After upgrading to 0.3.0
76
+
77
+ - **No more PAT.** `ZILLION_EMAIL` / `ZILLION_PAT` and the `email` / `pat` keys in
78
+ `config.json` are no longer read. Run `zillion-agent setup`: it re-registers the
79
+ servers without them and signs you in. You can delete the PAT on the portal's
80
+ Tokens page.
81
+ - **New API MCP server**, registered by `zillion-agent setup` next to the Roka server.
82
+ - The session token is now sent with every message, as the backend requires.
83
+
84
+ ## Sign in
85
+
86
+ ```bash
87
+ zillion-agent login # opens the sign-in page in your browser
88
+ zillion-agent whoami # which account, and until when
89
+ zillion-agent logout # ends the session and deletes it from this machine
90
+ ```
91
+
92
+ `login` prints a link and a short code (`ABCD-EFGH`). The browser page shows the
93
+ same code, so you can check the link is yours; sign in with your portal email and
94
+ password. On a machine without a browser (SSH, a server), open the printed link
95
+ on any device: when the browser is on a different network from the machine that
96
+ started the sign-in, the page warns about it and asks for the code. Inside an MCP
97
+ host, the agent calls `zillion_login` instead and shows you the same link and code.
98
+
99
+ Only use a sign-in link you started yourself. Whoever started it receives the
100
+ session, so never sign in on a link, or enter a code, that someone sent you.
101
+
102
+ The adapter's session can only do what the adapter does (Roka chat and the tools
103
+ below). Access tokens, password, profile and Telegram stay with a portal session.
104
+
105
+ The portal's **Agent adapter** page lists the machines signed in to your account,
106
+ whether each is connected right now and from which agent apps, and can sign one
107
+ out. For that, the adapter sends the machine's host name, OS, CPU architecture,
108
+ Python and adapter versions when a sign-in starts, and the agent app's name with
109
+ each connection. It keeps a random machine id in `~/.config/zillion/device.json`
110
+ (mode 600), so signing in again on the same machine replaces that machine's
111
+ earlier session.
112
+
113
+ An agent's shell cannot keep a command waiting while you are in the browser, so
114
+ agents use two steps: `zillion-agent login --start` prints the link and code and
115
+ returns, and `zillion-agent login --wait` (up to 30 s, repeat while pending)
116
+ finishes the sign-in. The pending sign-in is kept in
117
+ `~/.config/zillion/pending_sign_in.json` (mode 600) until it completes or the
118
+ link expires.
119
+
120
+ The session is the portal's own: it lasts **24 hours from the last activity**
121
+ (chatting with Roka counts; reading lists does not) and ends early if you change
122
+ your password or sign out. When it ends, the tools answer `not_signed_in`; sign
123
+ in again. The session is stored in `~/.config/zillion/credentials.json` with mode
124
+ 600. Your password never passes through the adapter.
125
+
126
+ A session the backend refuses is deleted at once and never re-sent: repeated
127
+ refused sign-ins from one address get that address blocked for a while.
128
+
129
+ ## Set up your agent apps
130
+
131
+ ```bash
132
+ zillion-agent setup
133
+ ```
134
+
135
+ It registers both servers (`zillion-api` and `zillion`) with every agent app it
136
+ finds — Claude Code, Cursor, Codex, Claude Desktop — using the Python it runs
137
+ with, installs `SKILL.md` where the app reads skills (Claude Code, Cursor, Codex),
138
+ and offers the browser sign-in. Restart the apps afterwards. When an agent runs
139
+ `setup` for you, it starts the sign-in right away (the `login --start` step above)
140
+ and prints what the agent should do next, so you are signed in before the restart.
141
+
142
+ - `--dry-run` shows what would change; `--only cursor,codex` limits the apps;
143
+ `--no-skill` / `--no-login` skip those steps; `--remove` undoes everything.
144
+ - It only touches the entries named `zillion-api` and `zillion`. A config file is
145
+ copied to `<file>.bak-zillion-<timestamp>` before it is changed; Claude Code is
146
+ configured through `claude mcp add --scope user`.
147
+ - Other MCP apps: add a stdio server with command `python -m zillion_agent api`
148
+ (and `mcp`). If no app is found, `setup` prints a config block to paste.
149
+
150
+ The agent learns how to use the tools without any extra files: each server sends
151
+ its usage guide as MCP server instructions when the app connects (the same text
152
+ as `SKILL.md`; print it with `zillion-agent skill`). Rules for a single tool sit
153
+ in that tool's description.
154
+
155
+ Both servers share the sign-in; signing in through either one signs in both.
156
+
157
+ ## API MCP tools
158
+
159
+ | Area | Tools |
160
+ |---|---|
161
+ | Sign-in | `zillion_login`, `zillion_login_status`, `zillion_logout`, `zillion_whoami` |
162
+ | Credit | `zillion_credit` (balance, status, spend, renewals, runway, notices), `zillion_credit_alert`, `zillion_usage(period, start, end)`, `zillion_usage_statements`, `zillion_usage_statement(month)` |
163
+ | SSH keys | `zillion_ssh_keys`, `zillion_ssh_key_add(public_key, name)`, `zillion_ssh_key_delete(key_id)` |
164
+ | VMs | `zillion_vm_catalog(region)`, `zillion_vm_terms(product_id)`, `zillion_vm_quote(...)`, `zillion_vm_purchase(...)`, `zillion_vm_purchases`, `zillion_vm_purchase_status(purchase_id)`, `zillion_vm_cancel_options(purchase_id)`, `zillion_vm_cancel(purchase_id, when)`, `zillion_servers`, `zillion_vm_power_status(server_ip)`, `zillion_vm_power(server_ip, action, user_confirmed)`, `zillion_server_rename(server_ip, new_name)` |
165
+ | Sandboxes | `zillion_sandbox_options`, `zillion_sandbox_create(...)`, `zillion_sandboxes`, `zillion_sandbox_extend(sandbox_id, additional_seconds)`, `zillion_sandbox_suspend`, `zillion_sandbox_resume`, `zillion_sandbox_delete`, `zillion_sandbox_exec(sandbox_id, command, cwd, timeout_seconds)`, `zillion_sandbox_token`, `zillion_sandbox_usage` |
166
+
167
+ Money and machines are guarded the same way as on the portal:
168
+
169
+ - **Buying a VM** takes two steps. `zillion_vm_quote` prices it without charging.
170
+ `zillion_vm_purchase` needs `confirmed_total` copied from the quote (if the
171
+ price moved, the order is refused and nothing is charged) and
172
+ `user_accepted_terms`. If the reply is lost, the tool says so; check
173
+ `zillion_vm_purchases` instead of buying again.
174
+ - **Sandboxes** bill per second while running. A create that is still starting
175
+ answers `pending`; calling again with the same `idempotency_key` picks up the
176
+ same sandbox instead of starting a second one.
177
+ - **stop / shutdown / reboot** need `user_confirmed=true`; one power action per VM
178
+ every 30 seconds.
179
+ - **Credit** can be checked but not added: top up on the portal's Billing & usage
180
+ page.
181
+ - Server passwords are never returned. A sandbox API token is returned only by
182
+ `zillion_sandbox_create` (once) and `zillion_sandbox_token` (which revokes the
183
+ previous one).
184
+
185
+ ## Configure (optional)
186
+
187
+ Nothing is required. Preferences come from environment variables or
188
+ `~/.config/zillion/config.json`:
189
+
190
+ | Variable | Meaning |
191
+ |---|---|
192
+ | `ZILLION_WS_URL` | Backend base URL; defaults to `wss://app-backend.zillion.network` |
193
+ | `ZILLION_WORKFLOW_ID` | Pin a Roka workflow; defaults to the standard workflow |
194
+ | `ZILLION_ZDR` | `1`/`true` starts new Roka conversations in Zero Data Retention mode |
195
+ | `ZILLION_ZDR_ENFORCE` | `1`/`true` refuses to create any persisted Roka conversation |
196
+ | `ZILLION_CONFIG` | Path of `config.json` |
197
+ | `ZILLION_CREDENTIALS` | Path of the sign-in file (default `~/.config/zillion/credentials.json`) |
198
+ | `ZILLION_CA_BUNDLE` | Custom CA bundle (rarely needed; e.g. a TLS-inspecting proxy) |
199
+ | `ZILLION_INSECURE_TLS` | `1`/`true` disables TLS verification — testing only, insecure |
200
+
201
+ ```json
202
+ {
203
+ "ws_url": "wss://app-backend.zillion.network",
204
+ "workflow_id": "1781915952622",
205
+ "zero_data_retention": false
206
+ }
207
+ ```
208
+
209
+ The default endpoint uses a normal, publicly trusted certificate; the session is
210
+ always sent encrypted. A sign-in belongs to the backend it was made against:
211
+ pointing `ZILLION_WS_URL` elsewhere needs a new sign-in.
212
+
213
+ ## Roka: run
214
+
215
+ ```bash
216
+ zillion-agent chat # standard: the conversation is saved
217
+ zillion-agent chat --zdr # Zero Data Retention: nothing is saved
218
+ ```
219
+
220
+ `chat` offers the browser sign-in if you are not signed in yet.
221
+
222
+ ### Switching accounts
223
+
224
+ The account is bound by the authenticated connection, which the Roka MCP server
225
+ holds for its whole lifetime. Signing in as another account (`zillion-agent
226
+ login`, or `zillion_login`) is noticed on the next `zillion_send` /
227
+ `zillion_new_conversation`, which rebinds and reports the switch in the result;
228
+ `zillion_reload` forces it immediately, and `zillion_status` shows
229
+ `config_changed` when the sign-in on disk no longer matches. Rebinding
230
+ **discards conversations started under the previous account**, so any earlier
231
+ `session_id` or `turn_id` is invalid. The API MCP server rebinds on its next call.
232
+
233
+ ## Zero Data Retention (ZDR)
234
+
235
+ A ZDR conversation is **ephemeral**: the backend keeps it in memory for the life
236
+ of the session and then discards it. Nothing is written down.
237
+
238
+ | | Standard conversation | ZDR conversation |
239
+ |---|---|---|
240
+ | Chat history on disk | Saved | Never written |
241
+ | Vector / cross-session memory | Written, and searchable later | Not written; `memory_search` returns nothing |
242
+ | `SOUL.md` / `USER.md` / `BEST_PRACTICES.md` | Roka may update them | Writes refused (reads still work) |
243
+ | Learned skills | Roka may create/update them | Writes refused (reads still work) |
244
+ | Scheduled tasks, alert rules, cross-channel messages | Can be created | Creation refused (listing still works) |
245
+ | Appears in portal history | Yes | No |
246
+ | Infrastructure operations | Full | Full — nothing is restricted here |
247
+
248
+ The distinction is **persistence, not capability**. ZDR applies to Roka
249
+ conversations only; the API MCP tools act on the account directly.
250
+
251
+ ### A conversation's mode is fixed when it starts
252
+
253
+ You cannot flip ZDR on or off mid-conversation; switching always means starting
254
+ a new conversation. Turning it on would leave the turns already written on disk
255
+ stranded, and turning it off would flush the whole supposedly-ephemeral
256
+ conversation to disk on the very next save.
257
+
258
+ ### In the terminal
259
+
260
+ ```bash
261
+ zillion-agent chat --zdr # ephemeral
262
+ zillion-agent chat --no-zdr # persisted, even if ZILLION_ZDR=1
263
+ zillion-agent chat # whatever ZILLION_ZDR says (default: persisted)
264
+ ```
265
+
266
+ The prompt shows the mode: `you (zdr)>` when nothing is saved, `you>` when the
267
+ chat is saved.
268
+
269
+ | Command | Effect |
270
+ |---|---|
271
+ | `/zdr` | Show the current mode and exactly what is and isn't saved |
272
+ | `/zdr on` | Start a **new** ephemeral conversation (the current one ends) |
273
+ | `/zdr off` | Start a **new** persisted conversation (the current one ends) |
274
+ | `/new` | New conversation, keeping the current retention mode |
275
+ | `/status`, `/reload` | Account and mode; re-read the sign-in |
276
+ | `/quit`, `/exit` | Quit, purging the ephemeral session immediately |
277
+
278
+ A ZDR transcript still sits in your terminal scrollback; clear it if that
279
+ matters. Ctrl+C exits without sending the purge; the backend then discards the
280
+ session when its idle grace period expires.
281
+
282
+ ### In the Roka MCP server
283
+
284
+ Strongest first:
285
+
286
+ 1. **Process-level** — register a ZDR server; every conversation it creates is
287
+ ephemeral:
288
+
289
+ ```bash
290
+ claude mcp add zillion-zdr -e ZILLION_ZDR=1 -e ZILLION_ZDR_ENFORCE=1 -- python -m zillion_agent mcp
291
+ ```
292
+
293
+ 2. **Session-level** — `zillion_new_conversation(zero_data_retention=True)`
294
+ returns a permanently ephemeral `session_id`.
295
+ 3. **Per-call** — `zillion_send(message, zero_data_retention=True)` with no
296
+ `session_id`.
297
+
298
+ Every tool result carries `zero_data_retention` plus a plain-language
299
+ `retention` line.
300
+
301
+ ### Limitations
302
+
303
+ - **The backend does not acknowledge the mode**; the adapter asserts ZDR but
304
+ cannot confirm an old backend honored it.
305
+ - **Only one ephemeral conversation per account.** Starting a second ends the
306
+ first, reported as `superseded_session_id`.
307
+ - **A dropped connection can end a ZDR conversation.** The adapter re-asserts it
308
+ on reconnect and warns on the next send if the context may be gone.
309
+
310
+ ## How it works
311
+
312
+ - **Sign-in:** `POST /adapter/login/start` returns the page link, the short code
313
+ and a poll secret only this process holds; the adapter polls
314
+ `/adapter/login/poll` until the user has signed in and receives the session
315
+ once. `zillion-agent logout` calls `/adapter/logout`. The adapter only opens
316
+ https links on zillion.network.
317
+ - **Tool annotations:** every tool is marked read-only, a change, or destructive
318
+ (spends credit, stops or deletes something, runs a command), so agent apps can
319
+ ask before the destructive ones. Keep those on "ask every time".
320
+ - **API MCP:** one connection to the portal socket
321
+ (`/ws/zillion_portal/client_meta_data/<email>`), first frame
322
+ `{"type":"auth","token":...}`, the token on every message, replies matched by
323
+ `request_id` (or by reply type for the few queued actions).
324
+ - **Roka:** one connection to `/ws/zillion_portal/<email>`; frames are routed into
325
+ per-turn buffers behind a non-blocking send/poll API. Retention is attached to
326
+ every outgoing message.
327
+
328
+ ### Docs after install
329
+
330
+ This README is the package page on PyPI. `zillion-agent setup` installs the skill
331
+ into the agent apps it finds, and `zillion-agent skill` prints it.
@@ -0,0 +1,311 @@
1
+ # zillion_agent
2
+
3
+ Zillion for your own agent (Codex, Claude Code, Cursor, any MCP host) and your
4
+ terminal. Two interfaces, one browser sign-in:
5
+
6
+ - **API MCP** (`zillion-agent api`) — the portal's functions as tools: buy and
7
+ manage VMs and sandboxes, check credit and usage, manage SSH keys. The tools run
8
+ the portal's own operations, so prices, checks and confirmations are the same as
9
+ on the portal.
10
+ - **Roka** — chat with the Zillion Agent (Roka):
11
+ - **Roka MCP** (`zillion-agent mcp`) — async `zillion_send` / `zillion_poll`
12
+ tools, so a long Roka task never blocks your agent.
13
+ - **Terminal chat** (`zillion-agent chat`) — streams Roka live.
14
+
15
+ Account settings, Telegram linking, access tokens and top-ups are not in the
16
+ adapter; they stay on the portal (`https://app.zillion.network`).
17
+
18
+ ## Prerequisites
19
+
20
+ 1. **Python 3.10+** and a recent pip (`python3 -m pip install -U pip`).
21
+ 2. **A Zillion account** — register on the portal; registration is portal-only.
22
+
23
+ ## Install
24
+
25
+ The package is `zillion-agent` on PyPI. Any of these works; a tool install keeps
26
+ it apart from your other Python packages:
27
+
28
+ ```bash
29
+ uv tool install zillion-agent # or: pipx install zillion-agent
30
+ # or: python3 -m pip install --user zillion-agent
31
+ zillion-agent setup # registers the servers with your agent apps, then signs you in
32
+ ```
33
+
34
+ Check the name: it is `zillion-agent`, from the regular PyPI index, and nothing
35
+ else (not a fork, a similar name or another index).
36
+
37
+ ### Updating
38
+
39
+ ```bash
40
+ zillion-agent update # installs the newest release, then runs setup again
41
+ zillion-agent update --check # only says whether there is one
42
+ zillion-agent --version
43
+ ```
44
+
45
+ `update` reads the newest release from PyPI, checks the downloaded wheel against
46
+ its published sha256, and installs that file the way the adapter was installed
47
+ (uv tool, pip or pipx). On Windows it prints the command to run instead.
48
+
49
+ If you installed a beta from TestPyPI, `zillion-agent update` moves you to the
50
+ PyPI releases; nothing else is needed.
51
+
52
+ Restart the agent apps afterwards: they keep the MCP servers running as
53
+ subprocesses, which run the old code until restarted. Your sign-in is kept.
54
+
55
+ ### After upgrading to 0.3.0
56
+
57
+ - **No more PAT.** `ZILLION_EMAIL` / `ZILLION_PAT` and the `email` / `pat` keys in
58
+ `config.json` are no longer read. Run `zillion-agent setup`: it re-registers the
59
+ servers without them and signs you in. You can delete the PAT on the portal's
60
+ Tokens page.
61
+ - **New API MCP server**, registered by `zillion-agent setup` next to the Roka server.
62
+ - The session token is now sent with every message, as the backend requires.
63
+
64
+ ## Sign in
65
+
66
+ ```bash
67
+ zillion-agent login # opens the sign-in page in your browser
68
+ zillion-agent whoami # which account, and until when
69
+ zillion-agent logout # ends the session and deletes it from this machine
70
+ ```
71
+
72
+ `login` prints a link and a short code (`ABCD-EFGH`). The browser page shows the
73
+ same code, so you can check the link is yours; sign in with your portal email and
74
+ password. On a machine without a browser (SSH, a server), open the printed link
75
+ on any device: when the browser is on a different network from the machine that
76
+ started the sign-in, the page warns about it and asks for the code. Inside an MCP
77
+ host, the agent calls `zillion_login` instead and shows you the same link and code.
78
+
79
+ Only use a sign-in link you started yourself. Whoever started it receives the
80
+ session, so never sign in on a link, or enter a code, that someone sent you.
81
+
82
+ The adapter's session can only do what the adapter does (Roka chat and the tools
83
+ below). Access tokens, password, profile and Telegram stay with a portal session.
84
+
85
+ The portal's **Agent adapter** page lists the machines signed in to your account,
86
+ whether each is connected right now and from which agent apps, and can sign one
87
+ out. For that, the adapter sends the machine's host name, OS, CPU architecture,
88
+ Python and adapter versions when a sign-in starts, and the agent app's name with
89
+ each connection. It keeps a random machine id in `~/.config/zillion/device.json`
90
+ (mode 600), so signing in again on the same machine replaces that machine's
91
+ earlier session.
92
+
93
+ An agent's shell cannot keep a command waiting while you are in the browser, so
94
+ agents use two steps: `zillion-agent login --start` prints the link and code and
95
+ returns, and `zillion-agent login --wait` (up to 30 s, repeat while pending)
96
+ finishes the sign-in. The pending sign-in is kept in
97
+ `~/.config/zillion/pending_sign_in.json` (mode 600) until it completes or the
98
+ link expires.
99
+
100
+ The session is the portal's own: it lasts **24 hours from the last activity**
101
+ (chatting with Roka counts; reading lists does not) and ends early if you change
102
+ your password or sign out. When it ends, the tools answer `not_signed_in`; sign
103
+ in again. The session is stored in `~/.config/zillion/credentials.json` with mode
104
+ 600. Your password never passes through the adapter.
105
+
106
+ A session the backend refuses is deleted at once and never re-sent: repeated
107
+ refused sign-ins from one address get that address blocked for a while.
108
+
109
+ ## Set up your agent apps
110
+
111
+ ```bash
112
+ zillion-agent setup
113
+ ```
114
+
115
+ It registers both servers (`zillion-api` and `zillion`) with every agent app it
116
+ finds — Claude Code, Cursor, Codex, Claude Desktop — using the Python it runs
117
+ with, installs `SKILL.md` where the app reads skills (Claude Code, Cursor, Codex),
118
+ and offers the browser sign-in. Restart the apps afterwards. When an agent runs
119
+ `setup` for you, it starts the sign-in right away (the `login --start` step above)
120
+ and prints what the agent should do next, so you are signed in before the restart.
121
+
122
+ - `--dry-run` shows what would change; `--only cursor,codex` limits the apps;
123
+ `--no-skill` / `--no-login` skip those steps; `--remove` undoes everything.
124
+ - It only touches the entries named `zillion-api` and `zillion`. A config file is
125
+ copied to `<file>.bak-zillion-<timestamp>` before it is changed; Claude Code is
126
+ configured through `claude mcp add --scope user`.
127
+ - Other MCP apps: add a stdio server with command `python -m zillion_agent api`
128
+ (and `mcp`). If no app is found, `setup` prints a config block to paste.
129
+
130
+ The agent learns how to use the tools without any extra files: each server sends
131
+ its usage guide as MCP server instructions when the app connects (the same text
132
+ as `SKILL.md`; print it with `zillion-agent skill`). Rules for a single tool sit
133
+ in that tool's description.
134
+
135
+ Both servers share the sign-in; signing in through either one signs in both.
136
+
137
+ ## API MCP tools
138
+
139
+ | Area | Tools |
140
+ |---|---|
141
+ | Sign-in | `zillion_login`, `zillion_login_status`, `zillion_logout`, `zillion_whoami` |
142
+ | Credit | `zillion_credit` (balance, status, spend, renewals, runway, notices), `zillion_credit_alert`, `zillion_usage(period, start, end)`, `zillion_usage_statements`, `zillion_usage_statement(month)` |
143
+ | SSH keys | `zillion_ssh_keys`, `zillion_ssh_key_add(public_key, name)`, `zillion_ssh_key_delete(key_id)` |
144
+ | VMs | `zillion_vm_catalog(region)`, `zillion_vm_terms(product_id)`, `zillion_vm_quote(...)`, `zillion_vm_purchase(...)`, `zillion_vm_purchases`, `zillion_vm_purchase_status(purchase_id)`, `zillion_vm_cancel_options(purchase_id)`, `zillion_vm_cancel(purchase_id, when)`, `zillion_servers`, `zillion_vm_power_status(server_ip)`, `zillion_vm_power(server_ip, action, user_confirmed)`, `zillion_server_rename(server_ip, new_name)` |
145
+ | Sandboxes | `zillion_sandbox_options`, `zillion_sandbox_create(...)`, `zillion_sandboxes`, `zillion_sandbox_extend(sandbox_id, additional_seconds)`, `zillion_sandbox_suspend`, `zillion_sandbox_resume`, `zillion_sandbox_delete`, `zillion_sandbox_exec(sandbox_id, command, cwd, timeout_seconds)`, `zillion_sandbox_token`, `zillion_sandbox_usage` |
146
+
147
+ Money and machines are guarded the same way as on the portal:
148
+
149
+ - **Buying a VM** takes two steps. `zillion_vm_quote` prices it without charging.
150
+ `zillion_vm_purchase` needs `confirmed_total` copied from the quote (if the
151
+ price moved, the order is refused and nothing is charged) and
152
+ `user_accepted_terms`. If the reply is lost, the tool says so; check
153
+ `zillion_vm_purchases` instead of buying again.
154
+ - **Sandboxes** bill per second while running. A create that is still starting
155
+ answers `pending`; calling again with the same `idempotency_key` picks up the
156
+ same sandbox instead of starting a second one.
157
+ - **stop / shutdown / reboot** need `user_confirmed=true`; one power action per VM
158
+ every 30 seconds.
159
+ - **Credit** can be checked but not added: top up on the portal's Billing & usage
160
+ page.
161
+ - Server passwords are never returned. A sandbox API token is returned only by
162
+ `zillion_sandbox_create` (once) and `zillion_sandbox_token` (which revokes the
163
+ previous one).
164
+
165
+ ## Configure (optional)
166
+
167
+ Nothing is required. Preferences come from environment variables or
168
+ `~/.config/zillion/config.json`:
169
+
170
+ | Variable | Meaning |
171
+ |---|---|
172
+ | `ZILLION_WS_URL` | Backend base URL; defaults to `wss://app-backend.zillion.network` |
173
+ | `ZILLION_WORKFLOW_ID` | Pin a Roka workflow; defaults to the standard workflow |
174
+ | `ZILLION_ZDR` | `1`/`true` starts new Roka conversations in Zero Data Retention mode |
175
+ | `ZILLION_ZDR_ENFORCE` | `1`/`true` refuses to create any persisted Roka conversation |
176
+ | `ZILLION_CONFIG` | Path of `config.json` |
177
+ | `ZILLION_CREDENTIALS` | Path of the sign-in file (default `~/.config/zillion/credentials.json`) |
178
+ | `ZILLION_CA_BUNDLE` | Custom CA bundle (rarely needed; e.g. a TLS-inspecting proxy) |
179
+ | `ZILLION_INSECURE_TLS` | `1`/`true` disables TLS verification — testing only, insecure |
180
+
181
+ ```json
182
+ {
183
+ "ws_url": "wss://app-backend.zillion.network",
184
+ "workflow_id": "1781915952622",
185
+ "zero_data_retention": false
186
+ }
187
+ ```
188
+
189
+ The default endpoint uses a normal, publicly trusted certificate; the session is
190
+ always sent encrypted. A sign-in belongs to the backend it was made against:
191
+ pointing `ZILLION_WS_URL` elsewhere needs a new sign-in.
192
+
193
+ ## Roka: run
194
+
195
+ ```bash
196
+ zillion-agent chat # standard: the conversation is saved
197
+ zillion-agent chat --zdr # Zero Data Retention: nothing is saved
198
+ ```
199
+
200
+ `chat` offers the browser sign-in if you are not signed in yet.
201
+
202
+ ### Switching accounts
203
+
204
+ The account is bound by the authenticated connection, which the Roka MCP server
205
+ holds for its whole lifetime. Signing in as another account (`zillion-agent
206
+ login`, or `zillion_login`) is noticed on the next `zillion_send` /
207
+ `zillion_new_conversation`, which rebinds and reports the switch in the result;
208
+ `zillion_reload` forces it immediately, and `zillion_status` shows
209
+ `config_changed` when the sign-in on disk no longer matches. Rebinding
210
+ **discards conversations started under the previous account**, so any earlier
211
+ `session_id` or `turn_id` is invalid. The API MCP server rebinds on its next call.
212
+
213
+ ## Zero Data Retention (ZDR)
214
+
215
+ A ZDR conversation is **ephemeral**: the backend keeps it in memory for the life
216
+ of the session and then discards it. Nothing is written down.
217
+
218
+ | | Standard conversation | ZDR conversation |
219
+ |---|---|---|
220
+ | Chat history on disk | Saved | Never written |
221
+ | Vector / cross-session memory | Written, and searchable later | Not written; `memory_search` returns nothing |
222
+ | `SOUL.md` / `USER.md` / `BEST_PRACTICES.md` | Roka may update them | Writes refused (reads still work) |
223
+ | Learned skills | Roka may create/update them | Writes refused (reads still work) |
224
+ | Scheduled tasks, alert rules, cross-channel messages | Can be created | Creation refused (listing still works) |
225
+ | Appears in portal history | Yes | No |
226
+ | Infrastructure operations | Full | Full — nothing is restricted here |
227
+
228
+ The distinction is **persistence, not capability**. ZDR applies to Roka
229
+ conversations only; the API MCP tools act on the account directly.
230
+
231
+ ### A conversation's mode is fixed when it starts
232
+
233
+ You cannot flip ZDR on or off mid-conversation; switching always means starting
234
+ a new conversation. Turning it on would leave the turns already written on disk
235
+ stranded, and turning it off would flush the whole supposedly-ephemeral
236
+ conversation to disk on the very next save.
237
+
238
+ ### In the terminal
239
+
240
+ ```bash
241
+ zillion-agent chat --zdr # ephemeral
242
+ zillion-agent chat --no-zdr # persisted, even if ZILLION_ZDR=1
243
+ zillion-agent chat # whatever ZILLION_ZDR says (default: persisted)
244
+ ```
245
+
246
+ The prompt shows the mode: `you (zdr)>` when nothing is saved, `you>` when the
247
+ chat is saved.
248
+
249
+ | Command | Effect |
250
+ |---|---|
251
+ | `/zdr` | Show the current mode and exactly what is and isn't saved |
252
+ | `/zdr on` | Start a **new** ephemeral conversation (the current one ends) |
253
+ | `/zdr off` | Start a **new** persisted conversation (the current one ends) |
254
+ | `/new` | New conversation, keeping the current retention mode |
255
+ | `/status`, `/reload` | Account and mode; re-read the sign-in |
256
+ | `/quit`, `/exit` | Quit, purging the ephemeral session immediately |
257
+
258
+ A ZDR transcript still sits in your terminal scrollback; clear it if that
259
+ matters. Ctrl+C exits without sending the purge; the backend then discards the
260
+ session when its idle grace period expires.
261
+
262
+ ### In the Roka MCP server
263
+
264
+ Strongest first:
265
+
266
+ 1. **Process-level** — register a ZDR server; every conversation it creates is
267
+ ephemeral:
268
+
269
+ ```bash
270
+ claude mcp add zillion-zdr -e ZILLION_ZDR=1 -e ZILLION_ZDR_ENFORCE=1 -- python -m zillion_agent mcp
271
+ ```
272
+
273
+ 2. **Session-level** — `zillion_new_conversation(zero_data_retention=True)`
274
+ returns a permanently ephemeral `session_id`.
275
+ 3. **Per-call** — `zillion_send(message, zero_data_retention=True)` with no
276
+ `session_id`.
277
+
278
+ Every tool result carries `zero_data_retention` plus a plain-language
279
+ `retention` line.
280
+
281
+ ### Limitations
282
+
283
+ - **The backend does not acknowledge the mode**; the adapter asserts ZDR but
284
+ cannot confirm an old backend honored it.
285
+ - **Only one ephemeral conversation per account.** Starting a second ends the
286
+ first, reported as `superseded_session_id`.
287
+ - **A dropped connection can end a ZDR conversation.** The adapter re-asserts it
288
+ on reconnect and warns on the next send if the context may be gone.
289
+
290
+ ## How it works
291
+
292
+ - **Sign-in:** `POST /adapter/login/start` returns the page link, the short code
293
+ and a poll secret only this process holds; the adapter polls
294
+ `/adapter/login/poll` until the user has signed in and receives the session
295
+ once. `zillion-agent logout` calls `/adapter/logout`. The adapter only opens
296
+ https links on zillion.network.
297
+ - **Tool annotations:** every tool is marked read-only, a change, or destructive
298
+ (spends credit, stops or deletes something, runs a command), so agent apps can
299
+ ask before the destructive ones. Keep those on "ask every time".
300
+ - **API MCP:** one connection to the portal socket
301
+ (`/ws/zillion_portal/client_meta_data/<email>`), first frame
302
+ `{"type":"auth","token":...}`, the token on every message, replies matched by
303
+ `request_id` (or by reply type for the few queued actions).
304
+ - **Roka:** one connection to `/ws/zillion_portal/<email>`; frames are routed into
305
+ per-turn buffers behind a non-blocking send/poll API. Retention is attached to
306
+ every outgoing message.
307
+
308
+ ### Docs after install
309
+
310
+ This README is the package page on PyPI. `zillion-agent setup` installs the skill
311
+ into the agent apps it finds, and `zillion-agent skill` prints it.
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "zillion_agent"
7
+ version = "0.3.6"
8
+ description = "Zillion for your agent — API MCP server (VMs, sandboxes, credit, SSH keys), Roka chat MCP server and terminal chat, with browser sign-in."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "Proprietary" }
12
+ authors = [{ name = "Zillion Network" }]
13
+ keywords = ["zillion", "mcp", "agent", "vm", "sandbox"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
22
+ ]
23
+ dependencies = [
24
+ "websockets>=12.0",
25
+ # Capped below 2.0: mcp 2.x removed `mcp.server.fastmcp` (FastMCP) in favour
26
+ # of a new server API, so an uncapped range installs a release this package
27
+ # cannot import. Lift the cap only together with a port to the 2.x API.
28
+ # 1.3.0 is the first release whose FastMCP takes server instructions.
29
+ "mcp>=1.21.1,<2",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://app.zillion.network"
34
+
35
+ [project.scripts]
36
+ zillion-agent = "zillion_agent.__main__:main"
37
+
38
+ [tool.setuptools.packages.find]
39
+ where = ["."]
40
+ include = ["zillion_agent*"]