Documentation / Sui Testnet
Give your agents a budget.
Create a vault, set each agent's limits, and connect through the HTTP API. Praxis checks every payment and records the reasoning alongside its outcome.
- Network
- Sui Testnet, SUI payments
- Authorization
- Owner-approved vault grants
- Evidence
- Public reasoning on Walrus
01 / Owner setup
Create a vault and authorize agents
Your sign-in wallet controls the vault. Agents can spend only the SUI you deposit, within the permissions you approve.
- 01
Create and fund a vault
Sign in with your Sui wallet and create a workspace. In Wallets, create a spending vault, approve the transaction, then deposit Testnet SUI and set the shared limits.
- 02
Set each agent's permissions
Add an agent from the vault. Approve its recipients, per-payment limits, daily and monthly budgets, total allowance and expiry in your wallet.
- 03
Fund gas and enable access
Use the labeled 0.05 Testnet SUI top-up to fund the agent's delegate gas separately. Verify and enable hosted access once the grant and funding are ready.
02 / Agent setup
Issue a credential and check access
On the agent page, issue a credential for its vault assignment. Save it in your agent's secret environment as PRAXIS_TOKEN; the token is shown once. The credential identifies the agent and vault, so requests do not supply those IDs.
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $PRAXIS_TOKEN" \
https://praxis.allensaji.dev/api/v1/agentA successful response identifies the authorized agent, assignment and wallet without making a payment. Claude Code, Codex and other runtimes can call this API through a local tool or script. There is no native MCP connector.
03 / Before spending
Preview a payment
Save the following as payment.json and replace the recipient with an address approved in your grant. Amounts are integer strings in MIST: 1 SUI = 1,000,000,000 MIST.
{
"recipient": "YOUR_APPROVED_SUI_RECIPIENT",
"amountMist": "1000000",
"coinType": "0x2::sui::SUI",
"privacy": "public",
"reasoning": {
"prompt": "Pay the configured service provider",
"decision": "Send 0.001 SUI within the approved allowance",
"model": "my-agent"
}
}curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $PRAXIS_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @payment.json \
https://praxis.allensaji.dev/api/v1/simulationsThe response includes current budgets, policy violations and a simulation report. A policy violation returns recommendation: "abort" and skips simulation. Review the result before submitting.
04 / Payment lifecycle
Submit once. Track the outcome.
After a successful preview, set PRAXIS_IDEMPOTENCY_KEY to a unique request ID (8-128 printable ASCII characters). This call requests a real Testnet payment and publishes the supplied reasoning.
# Set a unique ID for this payment. Keep it for every retry.
curl --fail-with-body --silent --show-error \
-H "Authorization: Bearer $PRAXIS_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $PRAXIS_IDEMPOTENCY_KEY" \
--data-binary @payment.json \
https://praxis.allensaji.dev/api/v1/spend-intentsKeep the same key and identical payload for retries, including after a timeout. A different payload with the same key returns HTTP 409. Save the returned intentId to track the outcome.
| State | What to do |
|---|---|
| confirmed | Read the transaction digest, receipt and Walrus blob ID. |
| blocked / failed / expired | Review the outcome in Activity before making a new request. |
| submission_unknown | Keep the original request ID. Reconciliation must resolve the signed transaction; do not create another payment. |
Other states are still processing. Poll the intent endpoint; polling does not submit a payment. For a complete integration, see the hosted agent example.
Understand the boundaries
- Shared balance, individual limits
- Every payment must satisfy both the vault and agent limits. Individual allowances are ceilings, not reserved balances. Daily and monthly windows use UTC. Pending requests count against available API budgets.
- Owner control
- Use your wallet to change grants, revoke delegates, pause the vault or withdraw remaining funds. An API credential is separate from the on-chain grant; revoking that credential stops its API access.
- Gas and evidence
- Payment limits cover principal. Delegate gas is funded separately and is not part of the vault balance. Published reasoning and Sui transactions are public; never include credentials or private data in reasoning.
- Testnet scope
- Hosted vaults support SUI transfers on Sui Testnet. Mainnet, arbitrary contract calls, other coins and hosted private reasoning are not available.
Alternative integration
Direct SDK quickstart
Use the direct SDK when you operate your own wallet adapter and signing service. This path uses the core receipt package; it does not create a hosted vault or enforce its on-chain grants. Keep the signer isolated from the agent runtime.
Install
pnpm add @allen-saji/praxis @mysten/suiConfigure your adapter
Connect your signing service through the wallet adapter interface.
import { Praxis, GenericAdapter, makeSuiClient } from "@allen-saji/praxis";
// Connect a signer implementing the wallet adapter interface.
// Isolate the signing key from your agent runtime.
const wallet = new GenericAdapter({
address: async () => signerAddress,
client: makeSuiClient("testnet"),
sign: async (bytes) => signer.sign(bytes),
});
const praxis = new Praxis({ wallet, network: "testnet" });Simulate
Dry-run a transfer and inspect the risk report before signing.
// Dry-run and risk-score without signing.
const report = await praxis.simulate({
to: recipient,
amount: 5_000_000_000n,
});
console.log(report.riskScore); // 0..100
console.log(report.recommendation); // "proceed" | "review" | "abort"
console.log(report.risks); // [{ level, code, message }]Spend and gate
Return false from onReport to abort before signing and record the decision.
// Gate the spend on the report. Returning false aborts before signing.
const result = await praxis.spend({
to: recipient,
amount: 5_000_000_000n,
reasoning: { prompt, decision, model },
privacy: "public",
onReport: (r) => r.recommendation === "proceed",
});
if (result.status === "aborted") {
console.log("blocked:", result.abortReason);
}Read the audit trail
Read direct SDK receipts and counters without a wallet. For hosted vault payments, use the intent endpoint and your workspace Activity page.
// Read the audit trail. No wallet required.
const receipts = await praxis.audit.recent(50);
const stats = await praxis.audit.indexStats();
console.log(stats.totalAborts); // recorded blocked or aborted requests