@mysten-incubation/sui-agent-pass 0.0.0 → 0.1.1
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/LICENSE +201 -0
- package/README.md +423 -4
- package/deployments/README.md +28 -0
- package/deployments/mainnet.json +65 -0
- package/deployments/testnet.json +69 -0
- package/dist/activation.js +287 -0
- package/dist/agent.js +409 -0
- package/dist/chain.js +763 -0
- package/dist/cli.js +250 -0
- package/dist/describe.js +352 -0
- package/dist/domain.js +393 -0
- package/dist/explorer.js +143 -0
- package/dist/float.js +80 -0
- package/dist/mcp.js +180 -0
- package/dist/navi.js +125 -0
- package/dist/owner.js +410 -0
- package/dist/plugin.js +795 -0
- package/dist/server.js +229 -0
- package/dist/signer.js +40 -0
- package/dist/storage.js +180 -0
- package/docs/AGENT.md +207 -0
- package/docs/PLAYBOOK.md +199 -0
- package/package.json +95 -10
- package/web-dist/assets/index-GamQ8vny.js +844 -0
- package/web-dist/assets/index-IgtbvOwM.css +1 -0
- package/web-dist/assets/mount-B6ddx2sS.js +3842 -0
- package/web-dist/deployments/mainnet.json +65 -0
- package/web-dist/deployments/testnet.json +69 -0
- package/web-dist/favicon.svg +10 -0
- package/web-dist/index.html +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,5 +1,424 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Sui Agent Pass
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
**Your money. Your rules. AI at work.**
|
|
4
|
+
|
|
5
|
+
Sui Agent Pass lets an AI agent run your onchain finance under a policy you write once. The agent
|
|
6
|
+
pays, trades, lends and stakes; Sui checks every transaction against the policy at settlement.
|
|
7
|
+
A policy is more than a spending limit: it names who the agent can pay, which markets it can
|
|
8
|
+
trade on and at what price, how much lending risk it can take, which validators it can stake
|
|
9
|
+
with, and how long its access lasts. Each new protocol plugs in as a new policy module.
|
|
10
|
+
|
|
11
|
+
An owner authorizes a new agent key with Slush. The agent builds its own programmable
|
|
12
|
+
transactions, a local MCP signer holds the agent key on the owner's machine and signs complete
|
|
13
|
+
transaction bytes, and the chain decides what executes. No hosted service ever holds a key.
|
|
14
|
+
|
|
15
|
+
One pass per agent, and the agent never owns anything:
|
|
16
|
+
|
|
17
|
+
- **Your coins stay in your own address.** Setup issues two allowances (`sui::allowance`) bound
|
|
18
|
+
to the pass, one per coin. Every agent action draws from your address balance through an
|
|
19
|
+
allowance, is checked by the pass's policies, and returns its proceeds to your address. The
|
|
20
|
+
pass never holds a coin.
|
|
21
|
+
- **The pass holds the rules and the objects the agent operates.** A NAVI lending position is
|
|
22
|
+
an object that can only be used under its owner's signature, so it sits in the pass where the
|
|
23
|
+
agent can run it. Only you can take it out, and taking it out hands you the position directly.
|
|
24
|
+
- **A receipt in your wallet points at each pass**, so from any device you can find your passes,
|
|
25
|
+
read their positions, and reclaim them. Authority stays with your address, never the receipt.
|
|
26
|
+
|
|
27
|
+
The pass is an account, not a typed container: each action names its coin. The owner installs
|
|
28
|
+
one policy per kind of action and coin. Transfers go to recipients the owner named; the agent
|
|
29
|
+
never supplies an address. Swaps run on the DeepBook and Cetus pools the owner listed, within
|
|
30
|
+
per-trade and daily caps and above a price floor. Lending supplies collateral to NAVI and, if
|
|
31
|
+
enabled, borrows against it while keeping the health factor above the owner's floor. Staking
|
|
32
|
+
puts SUI with the validators the owner listed (or any active one), within per-stake and daily
|
|
33
|
+
caps; the stake object stays in the pass and unstaking returns the SUI to the owner. An action
|
|
34
|
+
with no policy for its coin is refused. Revocation ends the agent's term and deletes the
|
|
35
|
+
allowances. The package references `sui::allowance`, so it needs protocol 137 or later, which
|
|
36
|
+
testnet, devnet and mainnet all run. The demo stays on localnet, testnet and devnet; mainnet
|
|
37
|
+
serves compatibility tests with small sums until launch.
|
|
38
|
+
|
|
39
|
+
The agent pays its own gas from the session address. Setup seeds an initial gas stipend and issues
|
|
40
|
+
a separate small SUI allowance for gas; when the session's balance runs low the agent tops it up
|
|
41
|
+
from that allowance, within its own lifetime cap and daily window, so gas spend is bounded apart
|
|
42
|
+
from the asset rules. Owners cannot bill an agent's transaction gas to the wallet directly yet,
|
|
43
|
+
because gas is authorized by a signature and `sui::allowance` cannot authorize it.
|
|
44
|
+
|
|
45
|
+
Transfers and staking are the real thing on every network. DeepBook, Cetus and NAVI are called
|
|
46
|
+
through their mainnet interfaces; off mainnet the demo publishes local stand-ins with the same
|
|
47
|
+
signatures over small mock markets, and the Move manifest lists the real packages as mainnet
|
|
48
|
+
replacements. See `move/protocols/README.md`.
|
|
49
|
+
|
|
50
|
+
This repository is fully self-contained. There is no broker, authorization database,
|
|
51
|
+
intent adapter, or transaction builder inside MCP.
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
The package is on npm as `@mysten-incubation/sui-agent-pass` (the incubation scope, for the
|
|
56
|
+
dogfood; the launch release will follow). A user needs no clone, no build, and no toolchain. The
|
|
57
|
+
client ships the per-network deployment IDs (`deployments/<network>.json`):
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
npm install -g @mysten-incubation/sui-agent-pass
|
|
61
|
+
agent-pass connect # pick the agents on this machine; nothing stays running
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
That is the only command. Then open the agent and tell it what to do with your money. It
|
|
65
|
+
proposes a pass (`propose_authorization`) and opens the review page with the proposal in its URL.
|
|
66
|
+
Connect a wallet, check the rules the agent quoted to you, and sign once; the session key stays
|
|
67
|
+
local, and the agent sees your signature land on chain and acts within the rules. Claude Code
|
|
68
|
+
starts the signer when it needs it. In production the page is our site at a fixed origin, so the
|
|
69
|
+
agent cannot change what you see or sign; in development the same build is served from the local
|
|
70
|
+
port (see "The site" in `docs/ARCHITECTURE.md`). There is no setup wizard: the agent composes
|
|
71
|
+
the rules from your words and the facts the server gives it (coins, pools, balances, quotes), and
|
|
72
|
+
the review page is where you check them. For a private publish:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
agent-pass connect # asks which agents; or --client <name>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Publishing the Move package and installing the Sui toolchain are maintainer steps, never on a
|
|
79
|
+
user's machine. See the release checklist below.
|
|
80
|
+
|
|
81
|
+
## Use it with your agent
|
|
82
|
+
|
|
83
|
+
The signer speaks MCP, so any agent that can load an MCP server can use it. The protocol is
|
|
84
|
+
the same for every client; where each one keeps its server list is not, so `connect --client`
|
|
85
|
+
writes or prints the entry in the right place:
|
|
86
|
+
|
|
87
|
+
| `--client` | What it does |
|
|
88
|
+
| ---------------- | ---------------------------------------------------------------------- |
|
|
89
|
+
| `claude-code` | `claude mcp add` in user scope |
|
|
90
|
+
| `claude-desktop` | Writes into `claude_desktop_config.json` |
|
|
91
|
+
| `cursor` | Writes into `~/.cursor/mcp.json` |
|
|
92
|
+
| `hermes` | Prints the `mcp_servers` block for `~/.hermes/config.yaml` |
|
|
93
|
+
| `codex` | Prints the `[mcp_servers.agent-pass]` block for `~/.codex/config.toml` |
|
|
94
|
+
| `json` | Prints a generic `mcpServers` entry |
|
|
95
|
+
|
|
96
|
+
The entry is `agent-pass mcp`, a stdio server the client starts when it needs it and stops with
|
|
97
|
+
it. It covers every pass on this machine, exposes `session_info` and `sign_transaction`, and
|
|
98
|
+
adds the owner tools (`list_passes`, `propose_authorization`, `revoke_pass`), so the agent can
|
|
99
|
+
also set a pass up. While it runs it also serves each pass's HTTP signer, which the SDK uses.
|
|
100
|
+
`connect --session <directory>` instead points a client at one session's foreground signer
|
|
101
|
+
(`agent-pass serve`), for agents that cannot start a process themselves.
|
|
102
|
+
|
|
103
|
+
Acting is a Node script against the SDK. `session_info.sdk.install` is the install command
|
|
104
|
+
(`npm install <this checkout>` after `npm run build` while the package is unpublished), then:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { Agent, pickValidator, send, stake, swap } from '@mysten-incubation/sui-agent-pass/agent';
|
|
108
|
+
import { SUI, units } from '@mysten-incubation/sui-agent-pass/domain';
|
|
109
|
+
|
|
110
|
+
const agent = await Agent.open(directory); // from session_info
|
|
111
|
+
const usdc = agent.identity.deployment.coins.find((c) => c.symbol === 'USDC')!;
|
|
112
|
+
const out = await agent.submit(
|
|
113
|
+
swap(agent.identity, { coinIn: SUI, coinOut: usdc.type }, units('0.01', 9), units('0.019', 6)),
|
|
114
|
+
);
|
|
115
|
+
// out.success, out.reason (the owner's rule on a refusal), out.balanceChanges
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`submit` signs through the session signer, submits to Sui and returns the persisted outcome; it
|
|
119
|
+
throws when nothing executed, so a dry-run refusal is never mistaken for enforcement.
|
|
120
|
+
[docs/AGENT.md](docs/AGENT.md) documents the SDK and the contract for hand-built PTBs. Agents
|
|
121
|
+
that do not speak MCP get the same two operations as plain HTTP with the bearer from
|
|
122
|
+
`mcp.token`: `GET /v1/session` and `POST /v1/sign` with `{ "transactionBytes": "<base64>" }`.
|
|
123
|
+
|
|
124
|
+
## Run the rehearsal
|
|
125
|
+
|
|
126
|
+
Clone the repository with your authorized GitHub account:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
gh repo clone MystenLabs/sui-agent-pass ~/github/sui-agent-pass
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Requires Node 22+, npm, and Sui 1.81.1 (`mainnet-v1.81.1`, the release mainnet runs; `npm run
|
|
133
|
+
toolchain` installs it with `mvr`). The project checks `SUI_BIN`, then
|
|
134
|
+
`~/.cache/sui-agent-pass/toolchain/sui`, then `sui` on PATH. Older installations are not used if
|
|
135
|
+
the project toolchain is present. The single Move package references `sui::allowance`, so it
|
|
136
|
+
builds and publishes only with a chain that has it enabled: localnet from this toolchain,
|
|
137
|
+
testnet, devnet, or mainnet (protocol 138).
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
cd ~/github/sui-agent-vault
|
|
141
|
+
npm ci
|
|
142
|
+
npm run toolchain
|
|
143
|
+
npm run build
|
|
144
|
+
npm run demo
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The command starts its own fresh local Sui network, publishes immutable demo contracts,
|
|
148
|
+
creates separate owner/publisher/session identities, authorizes the session, starts MCP,
|
|
149
|
+
and prints an owner dashboard URL and Claude connection command. It keeps the chain and
|
|
150
|
+
signer alive until `quit` or Ctrl-C. Keys stay in ignored private directories.
|
|
151
|
+
|
|
152
|
+
Commands in the rehearsal: `status`, `send` (5 USDC to the recipient named `owner`), `swap`
|
|
153
|
+
(0.01 SUI on DeepBook), `cetus` (0.01 SUI on Cetus), `supply` (0.2 SUI to NAVI), `borrow`
|
|
154
|
+
(0.15 USDC from NAVI), `stake` (1 SUI with the localnet validator), `unstake` (the held
|
|
155
|
+
stake, back to the owner), `over` (11 USDC against a 10 per-transfer limit), `revoke`, `quit`.
|
|
156
|
+
`npm run demo -- --smoke` runs the sequence automatically and exits. After revocation the
|
|
157
|
+
allowance objects no longer exist, so a transaction that names one is refused before execution
|
|
158
|
+
rather than recorded as a chain failure.
|
|
159
|
+
|
|
160
|
+
**The default rehearsal uses a generated test owner, not Slush.** It proves chain execution
|
|
161
|
+
and MCP signing. For the wallet connection/signature flow use the flow below.
|
|
162
|
+
|
|
163
|
+
## Slush + Claude Code
|
|
164
|
+
|
|
165
|
+
Use a deployed configuration, or `npm run devnet -- --owner <address>`, which publishes to
|
|
166
|
+
devnet with a faucet-funded publisher, funds your wallet address from the faucet and writes the
|
|
167
|
+
deployment to `~/.sui-agent-pass/deployment.json` for the Claude Code plugin. Slush offers
|
|
168
|
+
mainnet, testnet and devnet only. `npm run demo -- --wallet` keeps a localnet alive and prints a
|
|
169
|
+
funded throwaway owner key for a wallet that accepts a custom RPC URL; not verified with any.
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
# Prepare valueless testnet contracts using a separate deployment identity (testnet is the
|
|
173
|
+
# default network):
|
|
174
|
+
npm run deploy -- create --directory .local/testnet
|
|
175
|
+
# If the faucet cannot provide enough funds, the command prints the deployment address.
|
|
176
|
+
# Fund it with at least 11 test SUI, then:
|
|
177
|
+
npm run deploy -- resume --directory .local/testnet
|
|
178
|
+
|
|
179
|
+
# A private deployment.json replaces the bundled network for new passes:
|
|
180
|
+
node dist/cli.js connect # then ask the agent; it passes deployment: .local/testnet/deployment.json
|
|
181
|
+
# devnet works the same way:
|
|
182
|
+
npm run deploy -- create --network devnet --directory .local/devnet
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The agent asks what the pass is for and proposes the rules: recipients with per-transfer and
|
|
186
|
+
daily caps for each coin; for each trade direction the pools, per-trade and daily caps and a
|
|
187
|
+
price floor; for each lent coin per-action and daily caps, whether borrowing is allowed and a
|
|
188
|
+
health-factor floor; the validators it may stake with and per-stake and daily caps (a stake is
|
|
189
|
+
at least 1 SUI, the system's minimum); a lifetime cap per coin and the gas terms. It quotes the
|
|
190
|
+
exact rules text the page will show, generates a key and opens the review page. Connect Slush;
|
|
191
|
+
allowances draw only from your address balance, never from coin objects, so the page reads what
|
|
192
|
+
you hold on both sides and shows how much of your coins the signature converts into that balance
|
|
193
|
+
to cover the caps, with a faucet link if your wallet is short. Gas for your own signature comes
|
|
194
|
+
from either side. Sign. One PTB creates the pass and hands you its receipt, converts the coins,
|
|
195
|
+
issues the allowances over your own balance, installs the policies, opens the pass's NAVI
|
|
196
|
+
account when lending is allowed, and sends SUI to the session's **address balance** for gas. The
|
|
197
|
+
service re-reads everything that landed on chain and compares it with what you reviewed before
|
|
198
|
+
the signer serves the key.
|
|
199
|
+
|
|
200
|
+
Register the agents that may use your passes once with `connect` (it asks which ones it finds on
|
|
201
|
+
the machine). Then start Claude anywhere:
|
|
202
|
+
|
|
203
|
+
```sh
|
|
204
|
+
claude
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The registration is `agent-pass mcp` in Claude Code's user scope, a stdio server Claude starts
|
|
208
|
+
when it needs it. It contains no key and no token. If that MCP name already exists, remove the
|
|
209
|
+
old entry with `claude mcp remove agent-pass` before reconnecting.
|
|
210
|
+
|
|
211
|
+
```sh
|
|
212
|
+
node dist/cli.js status --session /absolute/session/directory
|
|
213
|
+
node dist/cli.js serve --session /absolute/session/directory # advanced: a foreground HTTP signer
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Closing Claude does not revoke the chain session;
|
|
217
|
+
the owner page's **Stop the agent now** button does, and **Close the pass** returns everything.
|
|
218
|
+
Your coins never left your address. If the
|
|
219
|
+
agent opened a NAVI position, **Reclaim NAVI position** on the owner page takes the account cap
|
|
220
|
+
into your wallet: the position is then yours to manage on NAVI directly and the agent has
|
|
221
|
+
nothing to lend on. Each stake the agent opened has a **Reclaim** button of its own, which moves
|
|
222
|
+
that `StakedSui` into your wallet. The pass also provides owner-only policy edits, documented in
|
|
223
|
+
the agent API guide.
|
|
224
|
+
|
|
225
|
+
## Claude Code plugin
|
|
226
|
+
|
|
227
|
+
The plugin runs the whole owner flow from inside Claude Code. You describe what the agent may
|
|
228
|
+
do; Claude proposes rules; the plugin renders them, opens the review page, and you sign once in
|
|
229
|
+
Slush. After that Claude acts through the same session, with no `connect` step and no second
|
|
230
|
+
terminal.
|
|
231
|
+
|
|
232
|
+
```sh
|
|
233
|
+
cd ~/github/sui-agent-vault
|
|
234
|
+
npm ci && npm run toolchain && npm run build
|
|
235
|
+
# Publish with a faucet-funded key, fund your Slush address from the faucet, and write
|
|
236
|
+
# ~/.sui-agent-pass/deployment.json:
|
|
237
|
+
npm run devnet -- --owner <your Slush address>
|
|
238
|
+
cd ~/anywhere && claude --plugin-dir ~/github/sui-agent-vault/plugin
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Then, in Claude Code:
|
|
242
|
+
|
|
243
|
+
> Manage 1 SUI and 100 USDC for me. Sell at most 0.1 SUI a day on DeepBook, never below
|
|
244
|
+
> 1.8 USDC. You may pay alice (0x…) up to 10 USDC a time and 20 a day. One week.
|
|
245
|
+
|
|
246
|
+
Claude calls `propose_authorization`, prints the rules text the tool returned, and the review
|
|
247
|
+
page opens. Connect Slush, check that the page shows the same rules, sign. Claude waits on
|
|
248
|
+
`session_info` until the pass is confirmed and its policies match, then works within the rules
|
|
249
|
+
with scripts against the SDK (`@mysten-incubation/sui-agent-pass/agent`), or with its own PTBs and
|
|
250
|
+
`sign_transaction`. `/agent-pass:pass-status` shows balances and today's
|
|
251
|
+
usage; `/agent-pass:pass-revoke` reopens the owner page for the revocation signature. The
|
|
252
|
+
guidance Claude follows is [`docs/PLAYBOOK.md`](docs/PLAYBOOK.md), which the MCP serves to every
|
|
253
|
+
client as the `agent-pass://playbook` resource; the plugin skills only point at it.
|
|
254
|
+
|
|
255
|
+
The MCP is `node dist/cli.js mcp`. It keeps sessions under `~/.sui-agent-pass/sessions/` and
|
|
256
|
+
reads `deployment.json` from that directory; Claude can also pass another deployment path to
|
|
257
|
+
`propose_authorization`. The plugin and Claude Code run as the same OS user: the session key
|
|
258
|
+
is not hidden from Claude by the operating system, and the on-chain rules are the boundary.
|
|
259
|
+
|
|
260
|
+
## The site
|
|
261
|
+
|
|
262
|
+
`npm run build` produces `web-dist/`, one static site that reads the chain directly and needs
|
|
263
|
+
no signer or session. `#/authorize/<proposal>` is the review page `setup` and the plugin open:
|
|
264
|
+
the rules come from the URL, the page builds the authorization against the package IDs it was
|
|
265
|
+
built with, your wallet signs, and the local signer finds the result on chain. Paste a pass id
|
|
266
|
+
or an owner address, or connect a wallet, and see the pass's rules, the owner's balances and
|
|
267
|
+
allowances, what the pass holds, and every transaction the agent sent with the chain's verdict
|
|
268
|
+
and the rule behind each refusal. Owner actions (revoke, reclaim a position or a stake, close
|
|
269
|
+
the pass) are wallet signatures from the same page. Closing deletes the pass, its policies, its
|
|
270
|
+
receipt and any remaining allowances in one transaction and hands back anything it still holds;
|
|
271
|
+
the storage deposits of everything deleted return with that transaction's gas. `#/booth` is the event view: the latest passes on the
|
|
272
|
+
package and a live feed of every call into it, refreshing every four seconds.
|
|
273
|
+
|
|
274
|
+
The pages use the Sui brand fonts, which are licensed and not in git: put the brand kit under
|
|
275
|
+
`.local/brand/` and run `npm run brand` before building, or the pages fall back to system fonts.
|
|
276
|
+
The build bundles `deployments/<network>.json`; `?network=testnet` picks one, otherwise the
|
|
277
|
+
first of testnet, devnet, localnet, mainnet that exists. To host it, serve `web-dist/` as static
|
|
278
|
+
files at a fixed origin and set `siteUrl` in the deployment file. To run it locally against any
|
|
279
|
+
deployment:
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
npm run explorer -- --deployment .local/devnet/deployment.json
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Basecamp film and slides
|
|
286
|
+
|
|
287
|
+
Every word of the film (voiceover and on-screen text) and of the two slides lives in
|
|
288
|
+
[`presentation/copy.md`](presentation/copy.md). Edit it, then run `npm run slides` (seconds) or
|
|
289
|
+
`npm run demo:film` (about six minutes, since the voice paces the recording).
|
|
290
|
+
|
|
291
|
+
`npm run demo:film` records the three-minute cut on a fresh localnet and writes
|
|
292
|
+
`scripts/film/out/basecamp-silent.mp4` (picture only, for the presenter's voiceover),
|
|
293
|
+
`basecamp-scratch-vo.mp4` (the same cut read by a scratch voice, for pacing) and
|
|
294
|
+
`basecamp-script.md` (the voiceover with a timecode per line). The voice paces the recording, and quiet waits on the agent are cut. On a
|
|
295
|
+
published network: `npm run film:record -- --deployment <deployment.json> --funder <key file>`,
|
|
296
|
+
then `npm run film:edit`. There the owner signs in the real Slush extension, copied from the
|
|
297
|
+
local Chrome profile (or `SLUSH_EXTENSION`) into a throwaway browser profile with a fresh key;
|
|
298
|
+
the stage shows Slush's own screens as a docked panel, and what the key has left goes back to
|
|
299
|
+
the funder afterwards. Localnet keeps the page's dev wallet, since Slush has no localnet.
|
|
300
|
+
`node --import tsx scripts/slides/render.ts` renders the two concept
|
|
301
|
+
slides to `.local/basecamp/`. Both need the brand kit (`npm run brand`) and Codex on the PATH.
|
|
302
|
+
Drafts use the free edge-tts voice. `npm run film:final` (with `ELEVENLABS_API_KEY` set) reads the
|
|
303
|
+
lines in the account's ElevenLabs voice (`ELEVENLABS_VOICE`, default `Tech`); clips are cached
|
|
304
|
+
under `.local/tts-cache/`, so an unchanged line costs no credits on a re-recording.
|
|
305
|
+
|
|
306
|
+
### Changing the voice or the words
|
|
307
|
+
|
|
308
|
+
The voice paces the recording, so a new voice or a new line means a new recording. To re-record
|
|
309
|
+
the testnet cut as it was made for Basecamp, with the owner signing in Slush:
|
|
310
|
+
|
|
311
|
+
1. Have Codex (`codex`) on the PATH and Slush installed in Chrome, then `npm install`, `npm run
|
|
312
|
+
brand` and `npx playwright install chromium`.
|
|
313
|
+
2. Put a funded testnet key (the `suiprivkey…` string, a few SUI; each run uses about 2) in a
|
|
314
|
+
file, for example `.local/testnet/funder.key`. Get testnet SUI at <https://faucet.sui.io>.
|
|
315
|
+
3. Change the words in `presentation/copy.md` if you want to. `[tone]` tags and `...` shape the
|
|
316
|
+
ElevenLabs reading; the free draft voice ignores them.
|
|
317
|
+
4. Record with your own ElevenLabs voice:
|
|
318
|
+
|
|
319
|
+
```sh
|
|
320
|
+
export ELEVENLABS_API_KEY=… ELEVENLABS_VOICE="Your voice name"
|
|
321
|
+
npm run film:record -- --final --deployment deployments/testnet.json --funder .local/testnet/funder.key
|
|
322
|
+
npm run film:edit
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Leave out `--final` for a free draft first. The cut lands in `scripts/film/out/`:
|
|
326
|
+
`basecamp-scratch-vo.mp4` is the voiced film and `basecamp-silent.mp4` the same picture with no
|
|
327
|
+
sound, for recording a human voiceover over it with `basecamp-script.md` as the timecoded script.
|
|
328
|
+
|
|
329
|
+
## Show it to someone
|
|
330
|
+
|
|
331
|
+
- [English demo script](docs/DEMO.md): pitch, exact commands, Claude prompts, expected results.
|
|
332
|
+
- [Chinese presenter instructions](docs/DEMO.zh-CN.md): operator notes with English prompts and narration.
|
|
333
|
+
- [Agent transaction guide](docs/AGENT.md): complete interface and agent-side examples.
|
|
334
|
+
- [Architecture and boundaries](docs/ARCHITECTURE.md).
|
|
335
|
+
- [Status: implemented and todo](docs/STATUS.md).
|
|
336
|
+
- [Verification record](docs/VERIFICATION.md) and [generated chain evidence](docs/evidence/localnet.json),
|
|
337
|
+
including the explorer's [pass page](docs/evidence/explorer-pass.png) and
|
|
338
|
+
[booth view](docs/evidence/explorer-booth.png).
|
|
339
|
+
- [Real Claude execution evidence](docs/evidence/claude.json): Claude Code with the plugin,
|
|
340
|
+
from prompt to signed pass to on-chain actions on a localnet.
|
|
341
|
+
|
|
342
|
+
## Checks
|
|
343
|
+
|
|
344
|
+
```sh
|
|
345
|
+
npm run check
|
|
346
|
+
npm test
|
|
347
|
+
npm run test:move
|
|
348
|
+
npm run build
|
|
349
|
+
AGENT_PASS_BROWSER_TEST=1 npm run test:integration
|
|
350
|
+
# Optional live model check, using fresh localnet funds and your Claude login:
|
|
351
|
+
npm run test:claude
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Browser verification uses installed Google Chrome and a wallet-standard **test wallet**.
|
|
355
|
+
It runs with a Chinese browser locale to verify the demo still displays English dates and copy.
|
|
356
|
+
It is not evidence of a live Slush extension signature. Integration tests submit signed
|
|
357
|
+
invalid transactions and inspect persisted failures; ordinary SDK simulations are not
|
|
358
|
+
counted as chain refusals. Each test owns and stops its localnet process.
|
|
359
|
+
|
|
360
|
+
## Release checklist
|
|
361
|
+
|
|
362
|
+
Publishing is a maintainer step, done once per network and once per npm release. None of it runs
|
|
363
|
+
on a user's machine.
|
|
364
|
+
|
|
365
|
+
Publish the contracts to a network:
|
|
366
|
+
|
|
367
|
+
1. `npm run toolchain` and `npm run build`.
|
|
368
|
+
2. `npm run deploy -- create --network testnet --directory .local/testnet`. Testnet is the
|
|
369
|
+
default. Mainnet needs a manually funded publisher (no faucet): `create --network mainnet`
|
|
370
|
+
prints the address, `resume` publishes once it holds 2 SUI.
|
|
371
|
+
3. Commit the resulting `deployment.json` here as `deployments/<network>.json`.
|
|
372
|
+
|
|
373
|
+
Publish the npm client:
|
|
374
|
+
|
|
375
|
+
1. Confirm `npm run check`, `npm test`, `npm run test:move`, `npm run build`, and
|
|
376
|
+
`AGENT_PASS_BROWSER_TEST=1 npm run test:integration` pass.
|
|
377
|
+
2. `npm pack --dry-run` to confirm the tarball holds `dist/`, `web-dist/` and `deployments/`.
|
|
378
|
+
3. Finalize the package name and version, remove `"private": true`, then `npm publish`;
|
|
379
|
+
`prepublishOnly` rebuilds first.
|
|
380
|
+
|
|
381
|
+
## Scope
|
|
382
|
+
|
|
383
|
+
Demo only, localnet/testnet/devnet, SUI and a test **USDC** that the demo faucet mints (not
|
|
384
|
+
Circle's USDC). Off mainnet DeepBook, Cetus and NAVI are exercised through local stand-ins that
|
|
385
|
+
keep the mainnet function signatures over constant-product pools and a principal-only lending
|
|
386
|
+
market. The package also builds against the real protocols (`sui move build -e mainnet`) and
|
|
387
|
+
`npm run deploy -- create --network mainnet` publishes it there with Circle's USDC and the real
|
|
388
|
+
pools, for compatibility tests; no mainnet publication is claimed yet. The demo packages are
|
|
389
|
+
made immutable when published; the mainnet package keeps its upgrade cap.
|
|
390
|
+
|
|
391
|
+
**Policies.** Each rule set is one on-chain policy object for one coin type, installed by the
|
|
392
|
+
owner and metered per UTC calendar day. Transfers reach only named recipients. Swaps run only
|
|
393
|
+
on listed pools, within input caps, above a static price floor and the agent's own `min_out`;
|
|
394
|
+
proceeds return to the owner's address. Lending pins the NAVI pool and asset index, caps each
|
|
395
|
+
action, and refuses a withdraw or borrow that would leave the position below the owner's
|
|
396
|
+
health-factor floor; the floor sits on the collateral policy too, so a withdraw cannot breach
|
|
397
|
+
it. Positions belong to the pass's own NAVI account cap, never to the agent. Owners edit
|
|
398
|
+
policies by removing and reinstalling them, which keeps the meters.
|
|
399
|
+
|
|
400
|
+
**Allowances.** `sui::allowance` draws from address balances only, so setup moves the chosen
|
|
401
|
+
coins from the owner's coin objects into the owner's own address balance. Anything the owner
|
|
402
|
+
spends from that balance later simply reduces what the agent can withdraw; a spend above the
|
|
403
|
+
live balance is refused at signing. A session's allowances, the two asset allowances and the
|
|
404
|
+
separate SUI gas allowance, share one expiry and are deleted together on revocation. The pass
|
|
405
|
+
accepts only allowances funded by its owner for its agent, and only it can spend them. A
|
|
406
|
+
repayment to NAVI is charged to the allowance in full before NAVI runs, so an over-payment
|
|
407
|
+
returns to the owner but still counts against the allowance; the agent should size repayments
|
|
408
|
+
from the live debt.
|
|
409
|
+
|
|
410
|
+
**Staking.** Real on every network. The policy lists validators (empty means any active one)
|
|
411
|
+
and caps each stake and the day. The `StakedSui` the agent opens is held by the pass; the
|
|
412
|
+
agent may unstake it, which sends principal and rewards to the owner's address, and the owner
|
|
413
|
+
may reclaim it as an object. The system's own 1 SUI minimum per stake applies.
|
|
414
|
+
|
|
415
|
+
**Objects.** The pass holds objects under typed keys: a protocol account under its adapter's
|
|
416
|
+
key, a stake under its ID, anything else under its own ID. Only the owner deposits or withdraws
|
|
417
|
+
them. Withdrawing the NAVI account cap moves the position with it, into the owner's wallet,
|
|
418
|
+
where NAVI's own UI shows it; withdrawing a stake makes it an ordinary `StakedSui` there. An
|
|
419
|
+
emptied pass (no policies, no objects) can be destroyed by the owner.
|
|
420
|
+
|
|
421
|
+
The gas stipend belongs to the session address and is freely spendable. A local service and
|
|
422
|
+
Claude running under the same OS user are not a private-key isolation boundary: the chain rules
|
|
423
|
+
survive key theft, while key confidentiality needs a separate identity or container. The private
|
|
424
|
+
owner/publisher fixture keys never enter the signing service.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<!-- Copyright (c) Mysten Labs, Inc. -->
|
|
2
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
+
|
|
4
|
+
# Bundled deployments
|
|
5
|
+
|
|
6
|
+
One `deployment.json` per public network, committed here and shipped in the npm package (see the
|
|
7
|
+
`files` field in `package.json`). Each records the published package and object IDs, the gRPC URL
|
|
8
|
+
and the chain identifier for that network. The stdio server loads one of these when
|
|
9
|
+
the agent names a `network` in `propose_authorization`, so an installed client needs no local
|
|
10
|
+
publish; a private `deployment.json` under `~/.sui-agent-pass` or a `deployment` path overrides.
|
|
11
|
+
|
|
12
|
+
`mainnet.json` is the mainnet test copy of the package (`0x4c9010b0…f403`, upgraded to
|
|
13
|
+
`0x08d82880…f744`, version 2), published for dogfooding and for testing the publish and upgrade
|
|
14
|
+
process with small sums; the real launch will be a fresh publish and a new file here. Add
|
|
15
|
+
`siteUrl` to it once the hosted site has its address, so the plugin sends owners there.
|
|
16
|
+
`testnet.json` is the current package (Sui Agent Pass), published to testnet on 2026-10-20 with
|
|
17
|
+
the version gate and the per-coin deployment shape (`coins`, `pools`, NAVI `reserves`, the demo
|
|
18
|
+
faucet). Any Move change means a new publish and a new file here. `npm run devnet` publishes to devnet and writes its
|
|
19
|
+
`deployment.json` for the plugin; `npm run deploy -- create --network <name>` publishes to
|
|
20
|
+
testnet or devnet. At launch, commit the resulting `deployment.json` here as `<name>.json`.
|
|
21
|
+
|
|
22
|
+
The site build (`npm run build`) copies these files into `web-dist/deployments/`, so the hosted
|
|
23
|
+
site serves whichever networks are committed here. A deployment's `siteUrl` is where the
|
|
24
|
+
plugin sends owners to review and sign; without it the local signer serves the same build.
|
|
25
|
+
|
|
26
|
+
The package references `sui::allowance`, which testnet, devnet and mainnet (protocol 138) all
|
|
27
|
+
have. A mainnet publish needs a manually funded publisher (mainnet has no faucet):
|
|
28
|
+
`npm run deploy -- create --network mainnet`.
|