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.
- zillion_agent-0.3.6/PKG-INFO +331 -0
- zillion_agent-0.3.6/README.md +311 -0
- zillion_agent-0.3.6/pyproject.toml +40 -0
- zillion_agent-0.3.6/setup.cfg +4 -0
- zillion_agent-0.3.6/zillion_agent/__init__.py +31 -0
- zillion_agent-0.3.6/zillion_agent/__main__.py +100 -0
- zillion_agent-0.3.6/zillion_agent/api_mcp.py +521 -0
- zillion_agent-0.3.6/zillion_agent/auth.py +340 -0
- zillion_agent-0.3.6/zillion_agent/cli.py +419 -0
- zillion_agent-0.3.6/zillion_agent/client.py +696 -0
- zillion_agent-0.3.6/zillion_agent/config.py +366 -0
- zillion_agent-0.3.6/zillion_agent/device.py +95 -0
- zillion_agent-0.3.6/zillion_agent/guide.py +186 -0
- zillion_agent-0.3.6/zillion_agent/hosts.py +345 -0
- zillion_agent-0.3.6/zillion_agent/mcp_server.py +308 -0
- zillion_agent-0.3.6/zillion_agent/portal.py +240 -0
- zillion_agent-0.3.6/zillion_agent/raw_api.py +33 -0
- zillion_agent-0.3.6/zillion_agent/tool_hints.py +21 -0
- zillion_agent-0.3.6/zillion_agent/update.py +190 -0
- zillion_agent-0.3.6/zillion_agent.egg-info/PKG-INFO +331 -0
- zillion_agent-0.3.6/zillion_agent.egg-info/SOURCES.txt +23 -0
- zillion_agent-0.3.6/zillion_agent.egg-info/dependency_links.txt +1 -0
- zillion_agent-0.3.6/zillion_agent.egg-info/entry_points.txt +2 -0
- zillion_agent-0.3.6/zillion_agent.egg-info/requires.txt +2 -0
- zillion_agent-0.3.6/zillion_agent.egg-info/top_level.txt +1 -0
|
@@ -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*"]
|