# Deploy an AMAHub agent in a TEE

For a CLI agent (Claude Code, Codex…) deploying an agent for a person, inside an
AMD SEV-SNP confidential VM, and checking its attestation.

Rules:
- Use only the commands below: web calls plus the official Amadeus SDK for the
  key. Do not clone or open any repository.
- Never print, log or send the mnemonic.
- Ask before deploying and before stopping.

Needs `curl`, `jq` and Node.js 18+.

## The mnemonic

Ask the person for the path of their mnemonic file: its first line is their
Amadeus Wallet recovery phrase. It holds everything: their public key and API
token are derived from it, locally, with the official SDK
(`@amadeus-protocol/sdk`, `@amadeus-protocol/wallet-sdk`).

No wallet yet? They install the Amadeus Wallet
(https://chromewebstore.google.com/detail/amadeus-wallet/gigmkdnbhopbandngplohmilogilbkjn),
create a wallet, and save the recovery phrase as the first line of a file, anywhere.

```sh
M=~/path/to/their/mnemonic        # the path they gave you
npm i -s --prefix /tmp/ama @amadeus-protocol/sdk @amadeus-protocol/wallet-sdk >/dev/null
keys() { (cd /tmp/ama && node --input-type=module -e '
import { readFileSync } from "node:fs"
import { mnemonicToCandidateKeypairs } from "@amadeus-protocol/sdk"
import { generateApiKey } from "@amadeus-protocol/wallet-sdk"
const k = mnemonicToCandidateKeypairs(readFileSync(process.argv[1], "utf8").split("\n")[0].trim()).find((c) => c.derivation === "eip2333")
console.log(k.publicKey, generateApiKey({ seed: k.seed, aud: "amadeus", expIn: 3 * 3600 }).apiKey)' "$M"); }
read PK TOKEN < <(keys)           # their public key (the wallet shows the same) and a 3-hour API token
API=https://api-hub.ama.one
```

## 1. Deploy

Default agent: perpbot (or ask which TEE agent; see the list at `$API/v1/agent/published`).

```sh
read AUTHOR AGENT < <(curl -fsS $API/v1/agent/published |
  jq -r '[.. | objects | select(.tee? == true and .name_display? == "perpbot")][0] | "\(.pk) \(.name)"')
R=$(jq -n --arg pk "$AUTHOR" --arg n "$AGENT" '{agent_pk: $pk, agent_name: $n}' |
  curl -fsS -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' --data-binary @- $API/v1/agent/create)
UUID=$(echo "$R" | jq -r .uid); IP6=$(echo "$R" | jq -r .ip6)
until S=$(curl -fsS -H "Authorization: Bearer $TOKEN" $API/v1/agent/my |
          jq -r --arg u "$UUID" '.running[] | select(.uuid == $u) | .status') &&
      [ "$S" = running -o "$S" = failed ]; do sleep 10; done; echo "$S"
```

`failed` means it did not boot or attest; tell the person and stop here.

## 2. Check the attestation

```sh
for i in $(seq 30); do A=$(curl -fs https://kbsv2.ama.one/v1/tee/attestation/$IP6) && break; sleep 2; done
echo "$A" | jq '{ok: .verdict.ok, checks: (.verdict.checks | length),
  agent: .verdict.spawn.agent, owner: .verdict.spawn.launcher_pk, author: .verdict.spawn.agent_pk}'
```

Tell the person it is good only if `ok` is `true`, `agent` is `$AGENT`, `author`
is `$AUTHOR` and `owner` is `$PK`. They can check it themselves at
https://kbsv2.ama.one/verify: paste the IPv6 address into **Check a deployment**.

## 3. Reach it

```sh
echo "http://[$IP6]/"
echo "https://$(echo $IP6 | sed 's/:/-/g')-80.ama.gpux.ai/"   # over IPv4
```

The web panel can take a minute after `running`. The deployment has its own
wallet, made inside the VM; nobody, not even the person, can read it.

## Stop

Deletes the deployment for good, wallet included: move funds out first.

```sh
jq -n --arg u "$UUID" '{uuid: $u}' | curl -fsS -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' --data-binary @- $API/v1/agent/stop
```

## Errors

- HTTP 401 or 520: the token expired; run `read PK TOKEN < <(keys)` again.
- `tee_capacity`: no free TEE machine; try later.
- `concurrent_limit`: the account runs as many VMs as it may; stop one.
