# lyra โ€” full machine-readable docs > A Sui-native, policy-aware AI treasury assistant. The AI advises; deterministic code enforces the fund controls. This file inlines every documentation page plus the repo README. Sections separated by horizontal rules. Each doc body is preceded by a source pointer when frontmatter declares one. > Setup: Lyra is a Bun + Biome monorepo. Run `bun install`, set `OPENAI_API_KEY` (the brain is any OpenAI-compatible model, default `gpt-4o-mini`), then `bun run lyra init` and `bun run lyra chat`. The identity is a Sui address from a local Ed25519 keypair; no on-chain mint is required to start. > Safety model: every value-moving action runs through policy (pure, unit-tested) -> simulate (dry-run) -> approval (material-risk prompts a human even under YOLO) -> execute (broadcast + receipt). The fund-control policy lives in `LYRA_POLICY_*` environment variables, not in the prompt; the model cannot override it. Binary name: `lyra` (run via `bun run lyra`). Engine: Bun. --- ## README > Source: https://github.com/rifkyeasy/lyra/blob/main/README.md # Lyra **A Sui-native, policy-bound, non-custodial AI finance agent.** You state a goal in plain language; the AI proposes the action; **deterministic Move code on Sui enforces the limits** โ€” budget, per-tx cap, allowed coins/protocols/recipients, expiry โ€” and moves funds from an on-chain **vault**, not the agent's wallet. The AI advises; the chain is the source of truth. - ๐ŸŒ **Live web console:** https://lyraai.space - ๐Ÿ“ฆ **npm (CLI):** [`lyra-ai-agent`](https://www.npmjs.com/package/lyra-ai-agent) - โ›“๏ธ **Mainnet package:** `0x8e984145d636037cebf5c402ac4b338567411ba6dd275948d7ff593b1ed01a04` --- ## Why it's non-custodial Funds live in an on-chain `Vault`, owned by **you**. The agent can only draw from it through `vault_spend`, which re-runs the full policy gate in Move on every action. So: - A compromised agent key โ€” or a leaked server โ€” is **bounded by the policy** and **revocable** by you at any time (`owner_withdraw`). - The agent is a **delegate, not a custodian**. It never holds your treasury. Each owner wallet maps deterministically to **one agent + one vault**, identical across the CLI, web, and Telegram. --- ## Quick start (CLI โ€” self-hosted, you hold your keys) ### 1. Prerequisites - [**Bun**](https://bun.sh) โ‰ฅ 1.1 โ€” `curl -fsSL https://bun.sh/install | bash` - A **Sui keypair** for the agent (a `suiprivkey1โ€ฆ` key) and a little **SUI** for gas - An **OpenAI-compatible API key** for the brain ### 2. Install ```bash bun install -g lyra-ai-agent ``` ### 3. Configure Set the agent + guardrails (e.g. in your shell profile or a `.env`): ```bash export LYRA_AGENT_KEY=suiprivkey1... # the agent that signs + pays gas export LYRA_NETWORK=mainnet export LYRA_PACKAGE_ID=0x8e984145d636037cebf5c402ac4b338567411ba6dd275948d7ff593b1ed01a04 export OPENAI_API_KEY=sk-... # any OpenAI-compatible key export LYRA_LLM_BASE_URL=https://api.openai.com/v1 export LYRA_LLM_MODEL=gpt-4o-mini # deterministic guardrails (the whole point) export LYRA_POLICY_MAX_PER_TX_SUI=1.0 # hard per-action cap export LYRA_POLICY_AUTO_MAX_SUI=0.1 # auto-execute at/under this; above โ†’ approval export LYRA_POLICY_MAX_SLIPPAGE_BPS=100 # block swaps over 1% slippage export LYRA_POLICY_ALLOWED_COINS=0x2::sui::SUI export LYRA_POLICY_ALLOWED_PROTOCOLS=transfer,swap,scallop,navi,walrus,deepbook ``` ### 4. Initialize + fund ```bash lyra init # derives the agent's Sui address + writes ~/.lyra/config.ts lyra status # shows the address, network, balance, and the enforced policy ``` Send a little **SUI** to the address shown by `init` (for gas). ### 5. Use it ```bash lyra # interactive chat with your agent lyra demo # guarded-pipeline demo (policy โ†’ blocked over-cap โ†’ send โ†’ Walrus) lyra logs # tail the activity log ``` > Ask it things like *"what's my balance and limits?"*, *"send 0.01 SUI to 0xโ€ฆ"*, > *"swap 1 SUI to USDC"*, *"best stablecoin yield on Sui?"* โ€” every value-moving action > is policy-checked, simulated, then executed, with an on-chain `ActionReceipt`. --- ## The four interfaces โ€” same agent, same policy | Interface | Run it | Identity | | --- | --- | --- | | **CLI** | `lyra` | local config (you hold the key) | | **Web** | https://lyraai.space, or self-host (`apps/web`) | Sign-In-with-Sui | | **Gateway** | `lyra gateway start` (always-on HTTP/socket daemon) | local | | **Telegram** | `lyra telegram setup` โ†’ `lyra gateway start` | `/link` (sign a challenge) | Each user can run their **own** bot + agent from the CLI โ€” their token, their keys, their machine. Fully sovereign. --- ## How it works ``` You (natural language) โ”‚ AI proposes an action โ–ผ Off-chain policy engine โ”€โ”€โ–บ simulate (dry-run) โ”€โ”€โ–บ execute โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ lyra::vault::vault_spend โ—„โ”€โ”€โ”€โ”€โ”€โ”˜ re-runs lyra::policy in Move: agent? budget? per-tx? coin? protocol? recipient? expiry? revoked? โ””โ–บ releases Coin from the on-chain Vault + mints ActionReceipt ``` - **`lyra::policy`** โ€” the `AgentPolicy` shared object: budget, caps, allowlists, recipient allowlist (anti prompt-injection), expiry, revoke. - **`lyra::vault`** โ€” the treasury `Vault`; `vault_spend` / `vault_transfer` enforce the policy on-chain; `owner_withdraw` is your escape hatch. - **Walrus** โ€” durable, verifiable receipts/memory. - **Aggregated execution** โ€” swaps route across Cetus / FlowX / Bluefin / DeepBook (7k). --- ## Develop ```bash git clone https://github.com/rifkyeasy/lyra.git && cd lyra bun install bun test # 930 TS tests sui move test --path move/lyra # 21 Move tests cd apps/web && bun run dev # web console on :3210 ``` Monorepo layout: ``` move/lyra on-chain policy + vault (Move) packages/core agent runtime / brain (tool loop) packages/plugin-onchain Sui tools: send, swap, lend, walrus, vault, policy packages/plugin-telegram Telegram interface (/link, listener) packages/gateway always-on daemon packages/cli the `lyra` CLI apps/web Next.js web console (dapp-kit + SIWS) ``` ## Deploy (web) The web console auto-deploys on push to `main` via GitHub Actions (`.github/workflows/deploy.yml`) โ†’ SSH to the host โ†’ `scripts/deploy-vps.sh` (build โ†’ atomic swap โ†’ `pm2 reload`). See the script for the self-host recipe (nginx reverse proxy + certbot TLS). ## Security Non-custodial by design โ€” funds are in the on-chain vault, bounded by policy, revocable by you. Honest production boundaries (see `DEMO.md`): a **contract audit** and a real **KMS/MPC signer** (the `AgentSigner` abstraction is ready) are recommended before managing significant or third-party funds. Never commit `.env` / keys. ## License MIT --- ## For Agents > Source: https://github.com/rifkyeasy/lyra/blob/main/apps/web/content/docs/11-agents.md # An honest guide for AI agents. You are an LLM. A human asked you to set up Lyra. This page tells you what you can do for them, what you must hand back, and what you should never claim. The goal is fewer hallucinated steps and fewer hung scripts. If you only read one line: **Bun is required, the brain is any OpenAI-compatible model (set `OPENAI_API_KEY`), and the fund-control policy lives in `LYRA_POLICY_*` environment variables, not in the prompt.** ## Install Lyra is a Bun + Biome monorepo. Bun runs the install and the CLI. ```bash bun install export OPENAI_API_KEY=sk-... bun run lyra init bun run lyra chat ``` `init` generates a fresh agent wallet โ€” a Sui address from a locally-stored Ed25519 keypair โ€” and a local encrypted keystore. There is no on-chain mint, no NFT, and no operator signature required to get started. ## What you can do for the user - Install dependencies (`bun install`) and confirm Bun is present. - Configure the brain: set `OPENAI_API_KEY`, optionally `LYRA_LLM_BASE_URL` and `LYRA_LLM_MODEL` (default `gpt-4o-mini`). - Set the fund-control policy via `LYRA_POLICY_*` (caps, allowlists, slippage, autonomy tier, read-only). See [Configuration](/docs/configuration). - Explain commands. The five the user runs most: `bun run lyra init`, `bun run lyra chat`, `bun run lyra telegram setup`, plus the gateway. See [CLI](/docs/cli). - Help them ask the agent to read or act: balances, yield discovery, transfers, Cetus / DeepBook swaps, NAVI / Scallop supply/withdraw. See [Tools](/docs/tools). ## How the safety model works (so you do not fight it) Every value-moving action runs through a four-gate pipeline: policy (pure, unit-tested), simulation (dry-run before gas), an approval floor (material-risk actions prompt a human even under YOLO), and execution (broadcast plus receipt). The model proposes; deterministic code disposes. You cannot raise a limit, skip a simulation, or grant approval from the model. Those decisions live in code. Do not write scripts that try to route around them. ## Anti-patterns to avoid - **Do NOT** tell the user the model can override a policy limit. It cannot. The limits are in code. - **Do NOT** invent on-chain identity ceremonies. The identity is just a Sui address from a local Ed25519 keypair; there is no mint, no NFT, no registry, no naming claim required to start. - **Do NOT** default to mainnet for exploratory work. Use Sui testnet first, then move to Sui mainnet once the policy is set. - **Do NOT** script destructive actions (large transfers, withdrawals) without having the user confirm. Material-risk actions will pause for approval anyway; respect that. ## Networks | Network | RPC | Explorer | |---|---|---| | Sui mainnet | `https://fullnode.mainnet.sui.io:443` | `https://suiscan.xyz` | | Sui testnet | `https://fullnode.testnet.sui.io:443` | `https://suiscan.xyz/testnet` | Gas token is SUI (9 decimals; smallest unit is MIST, 1 SUI = 1e9 MIST). Sui does not use numeric Sui chain IDs. ## Machine-readable surfaces - [/llms.txt](/llms.txt): index with one bullet per doc. Fetch this first. - [/llms-full.txt](/llms-full.txt): a single-file dump of every doc plus the repo README. - [/docs/.md](/docs/agents.md): raw markdown per page (for example `/docs/quickstart.md`, `/docs/cli.md`). Always re-fetch before relying on cached prior advice. --- ## Quickstart > Source: https://github.com/rifkyeasy/lyra/blob/main/README.md # Run your first policy-gated agent. There are two ways in. **Try it in 30 seconds** in the browser, or **run your own agent** from the command line. ## Fastest: the hosted console (no setup) Open the [console](/console) and start typing. Asking about balances, yields, prices, or swap quotes needs **no wallet, no key, no install** โ€” the brain and the Sui connection are already wired. Want it personal? **Connect your wallet** so "my balance / my portfolio" answers for your address, and **sign in** (one signature) to save your chat history across devices and to authorize transfers (owner-only, simulated, policy-capped). That's the whole setup. See [Console](/docs/console). The rest of this page is for running your **own** agent โ€” your keys, your limits, on your machine or server. ## Prerequisites (self-hosted) [Bun](https://bun.sh). The monorepo and CLI run on Bun. An OpenAI-compatible LLM key. The brain is any OpenAI-compatible model; the default is `gpt-4o-mini`. You can point it at any base URL and model via environment variables. A little SUI to pay gas for the actions you ask the agent to take. ## Install and configure ```bash bun install # Configure the brain (OpenAI-compatible; any base URL / model works) export OPENAI_API_KEY=sk-... # optional overrides: # export LYRA_LLM_BASE_URL=https://api.openai.com/v1 # export LYRA_LLM_MODEL=gpt-4o-mini ``` ## Init ```bash bun run lyra init ``` `init` generates an agent wallet โ€” a Sui address derived from a locally-stored Ed25519 keypair โ€” and writes a local encrypted keystore. There is no on-chain mint, no NFT, and no operator signature required to get started. ## Set the policy Configure the boundary entirely from the environment. These limits live in deterministic, unit-tested code; the model cannot raise them at runtime. ```bash LYRA_POLICY_MAX_NATIVE_SUI=2.0 # hard cap: block sends over 2 SUI LYRA_POLICY_AUTO_MAX_NATIVE_SUI=0.1 # auto-execute up to 0.1 SUI; above this requires approval LYRA_POLICY_MAX_SLIPPAGE_BPS=100 # block swaps over 1% slippage LYRA_POLICY_AUTONOMY=auto # auto | confirm | readonly LYRA_POLICY_RECIPIENT_ALLOWLIST=0xabc...,0xdef... # Sui addresses (0x + 64 hex) LYRA_POLICY_TOKEN_ALLOWLIST=0x...::usdc::USDC,... # Sui coin types LYRA_POLICY_READONLY=1 # reject all writes ``` ## Chat ```bash bun run lyra chat ``` Fund the agent wallet with a little SUI for gas, set your `LYRA_POLICY_*` limits, and ask it to do things: "what's my balance?", "best stablecoin yield on Sui?", "swap 1 SUI for USDC", "supply 5 USDC to NAVI". Reads run freely. Every value-moving action runs the four-gate pipeline (policy, simulate, approval, execute) before it broadcasts as a PTB, and material-risk actions pause for your approval. ## Telegram Run the same agent, with the same approval gates, from your phone: ```bash bun run lyra telegram setup ``` Approval prompts arrive as inline-keyboard buttons. Read [Architecture](/docs/architecture) next to understand how the pipeline fits together. Source: [`README.md`](https://github.com/rifkyeasy/lyra/blob/main/README.md). --- ## Configuration > Source: https://github.com/rifkyeasy/lyra/blob/main/README.md # Configured from the environment. The brain and the entire fund-control policy are configured from environment variables. No code changes are needed to change a limit, and nothing the model outputs can override them, because the policy is enforced in deterministic, unit-tested code. ## Brain ```bash export OPENAI_API_KEY=sk-... # optional overrides: export LYRA_LLM_BASE_URL=https://api.openai.com/v1 # any OpenAI-compatible endpoint export LYRA_LLM_MODEL=gpt-4o-mini # default model ``` Any OpenAI-compatible model works. Swapping the model has no effect on the safety boundary. ## Policy ```bash LYRA_POLICY_MAX_NATIVE_SUI=2.0 # hard cap: block sends over 2 SUI LYRA_POLICY_AUTO_MAX_NATIVE_SUI=0.1 # auto-execute up to 0.1 SUI; above this requires approval LYRA_POLICY_MAX_SLIPPAGE_BPS=100 # block swaps over 1% slippage LYRA_POLICY_AUTONOMY=auto # auto | confirm | readonly LYRA_POLICY_RECIPIENT_ALLOWLIST=0xabc...,0xdef... # Sui addresses (0x + 64 hex) LYRA_POLICY_TOKEN_ALLOWLIST=0x...::usdc::USDC,... # Sui coin types LYRA_POLICY_READONLY=1 # reject all writes ``` | Variable | Controls | |---|---| | `LYRA_POLICY_MAX_NATIVE_SUI` | Hard cap on native SUI per action. A value above this blocks. | | `LYRA_POLICY_AUTO_MAX_NATIVE_SUI` | The amount the agent may move without prompting. Above it, approval is required. | | `LYRA_POLICY_MAX_SLIPPAGE_BPS` | Maximum allowed swap slippage, in basis points. | | `LYRA_POLICY_AUTONOMY` | `auto` (act within tier), `confirm` (prompt on writes), `readonly` (no writes). | | `LYRA_POLICY_RECIPIENT_ALLOWLIST` | Comma-separated recipient Sui addresses the agent may send to. | | `LYRA_POLICY_TOKEN_ALLOWLIST` | Comma-separated Sui coin types the agent may touch. | | `LYRA_POLICY_READONLY` | When set, all writes are rejected outright. | The approval floor sits beneath the autonomy tier: a material-risk action prompts for a human even under `auto` / YOLO, and is denied under `readonly` / strict. ## Networks | Network | RPC | Explorer | |---|---|---| | Sui mainnet | `https://fullnode.mainnet.sui.io:443` | `https://suiscan.xyz` | | Sui testnet | `https://fullnode.testnet.sui.io:443` | `https://suiscan.xyz/testnet` | Gas token is SUI (9 decimals; smallest unit is MIST, 1 SUI = 1e9 MIST). Sui does not use numeric Sui chain IDs. Start on Sui testnet for exploratory work, then move to mainnet once your policy is set. Read [Console](/docs/console) next. Source: [`README.md`](https://github.com/rifkyeasy/lyra/blob/main/README.md). --- ## CLI > Source: https://github.com/rifkyeasy/lyra/blob/main/packages/cli # The lyra command. The `lyra` binary owns onboarding, chat, the Telegram bridge, and the gateway daemon. Run it through Bun from the repo (`bun run lyra `). ## Init ```bash bun run lyra init ``` Generates a fresh agent wallet โ€” a Sui address from a locally-stored Ed25519 keypair โ€” and writes a local encrypted keystore. There is no on-chain mint, no NFT, and no operator signature required. Set your `OPENAI_API_KEY` (and any `LYRA_LLM_*` overrides) before you start so the brain is configured. ## Chat ```bash bun run lyra chat ``` Drops into the interactive terminal session. Ask the agent to read or act: "what's my balance?", "best stablecoin yield on Sui?", "swap 1 SUI for USDC", "supply 5 USDC to NAVI". Reads return directly. Every value-moving action runs the four-gate pipeline, and material-risk actions pause for your approval inline. ## Telegram ```bash bun run lyra telegram setup ``` Pairs a Telegram bot so you can drive the same agent from your phone, with the same approval gates. Approval prompts arrive as inline-keyboard buttons. ## Gateway The gateway is a long-running daemon that keeps Telegram online and routes approval prompts even when you do not have an interactive session open. It is the process that lets the agent stay reachable between chats. ## Setting the policy The CLI reads the boundary from the environment. Set the `LYRA_POLICY_*` variables (caps, allowlists, slippage, autonomy tier, read-only) before launching; see [Configuration](/docs/configuration) for the full list. The limits are enforced in deterministic code, so the agent cannot raise them at runtime. Read [Configuration](/docs/configuration) next. Source: [`packages/cli`](https://github.com/rifkyeasy/lyra/tree/main/packages/cli). --- ## Brain > Source: https://github.com/rifkyeasy/lyra/blob/main/README.md # An advisory brain you can swap. The brain is any OpenAI-compatible model. The default is `gpt-4o-mini`. Point it at a different base URL or model with environment variables and nothing else changes, because the model never gets to be the safety boundary. ```bash export OPENAI_API_KEY=sk-... # optional overrides: export LYRA_LLM_BASE_URL=https://api.openai.com/v1 export LYRA_LLM_MODEL=gpt-4o-mini ``` ## What the brain does The brain is the advisory layer. It reads the operator's intent, picks tools, explains tradeoffs, and discovers opportunities. It proposes actions; it does not authorize them. ## What the brain cannot do It cannot raise a policy limit, skip a simulation, or grant its own approval. Those decisions are made by deterministic code in the control layer, which sits beneath the model and is unaffected by anything the model outputs. A jailbreak or a confused tool call still hits a hard cap, a simulation, and an approval floor before any value moves. See [Architecture](/docs/architecture) for the four-gate pipeline. ## How a turn happens 1. The brain receives the operator's message plus the relevant memory index. 2. It decides whether to read (free) or to propose a value-moving action. 3. Reads return results directly. A proposed write is handed to the policy engine, simulated, and (if material-risk) held for approval before execution. 4. Cleared writes broadcast on Sui as a PTB and return a decision record (policy verdict, simulated gas, and tx digest) the brain can report back. Because the boundary lives in code, swapping the model is a one-line change with no impact on safety. A worse model can be wrong about what to do, but it cannot get past the gates. Read [Tools](/docs/tools) next. Source: [`README.md`](https://github.com/rifkyeasy/lyra/blob/main/README.md). --- ## Tools > Source: https://github.com/rifkyeasy/lyra/blob/main/packages/plugin-onchain # Limbs that do, gates that decide. Tools do literal work, never safety logic. The brain decides which tool to call; the deterministic control layer decides whether a value-moving call is allowed. Reads are free. Every write (`sui.send`, `cetus.swap`, `navi.supply` / `withdraw`, `scallop.*`, `walrus.store`) goes through policy, simulation, and approval first. ## On-chain tools (plugin-onchain) | Area | Tools | Notes | |---|---|---| | Wallet / account | `account.info`, `sui.balance` | Identity plus coin snapshot plus activity; native SUI (MIST) position. | | Balances / coins | `sui.balance`, `tokens.info` | Coin-type discovery across owned objects (no curated list). | | Transfers | `sui.send` | Native SUI and any Sui coin type; recipients are Sui addresses (0x + 64 hex). | | Trading | `cetus.quote`, `cetus.swap`, `deepbook.markets` | Cetus and Turbos (concentrated-liquidity AMMs) plus DeepBook's native CLOB. Quotes compare venues and route to the better one. | | Lending | `navi.*`, `scallop.*` | NAVI, Suilend, and Scallop: live supply / borrow rates, supply / withdraw collateral, borrow / repay; receipts report the health factor. | | Staking | `haedal.stake`, `springsui.stake` | Liquid staking of SUI via Haedal and SpringSui. | | Discovery | `defi.yields` | DeFiLlama analytics: Sui pools ranked by APY / TVL with risk and RWA flags (read-only). | | Risk | `risk.token` | Pre-trade vet: can you exit it (live Cetus / DeepBook quote), liquidity depth, restricted-RWA flag, real-package check, into a low / elevated / high verdict. | | Controls | `policy.show`, `policy.create`, `tx.simulate` | Report or set the active fund-control policy; dry-run any PTB (would-succeed plus gas, or decoded failure) without broadcasting. | | Receipts | `walrus.store` | Persist auditable memory and execution receipts to Walrus, addressed by root hash. | | Analysis | `sui.tx`, `sui.object`, `sui.activity` | Decode tx, introspect objects and Move packages, recent transfers. | | Blockchain | `sui.checkpoint`, `sui.gas` | Latest checkpoint, timestamp, reference gas price plus estimated SUI cost of common ops. | | Generic | `sui.read`, `move.call` | Any Move function by package / module / function plus `args`. | Source: [`packages/plugin-onchain`](https://github.com/rifkyeasy/lyra/tree/main/packages/plugin-onchain). ## RWA and restricted awareness `defi.yields` surfaces every Sui pool but flags restricted RWA and tokenized yield products (for example Ondo's offerings) so the agent only proposes entering them with explicit eligibility confirmation. DeFiLlama is used for discovery and analytics only, never execution. ## Host harness (plugin-system) The agent also has a general-purpose toolkit for the work around the chain: OS-sandboxed shell and code execution, file operations, web fetch, and a headless browser. These run on the operator's machine under the OS sandbox. Source: [`packages/plugin-system`](https://github.com/rifkyeasy/lyra/tree/main/packages/plugin-system). ## Telegram (plugin-telegram) A Telegram listener turns inbound DMs into agent events. Approval prompts arrive as inline-keyboard buttons, so the same boundary applies whether you drive the agent from the terminal or your phone. Source: [`packages/plugin-telegram`](https://github.com/rifkyeasy/lyra/tree/main/packages/plugin-telegram). ## Approval modes The session permission mode controls how much the agent does without prompting, but the approval floor sits beneath it. A material-risk action prompts for a human even when the session is in `auto` / YOLO, and is denied outright under `strict` and read-only. Configure it with `LYRA_POLICY_AUTONOMY` and the rest of the `LYRA_POLICY_*` variables. See [Configuration](/docs/configuration). Read [CLI](/docs/cli) next. Source: [`packages/plugin-onchain`](https://github.com/rifkyeasy/lyra/tree/main/packages/plugin-onchain). --- ## Memory > Source: https://github.com/rifkyeasy/lyra/blob/main/README.md # A local, content-addressed memory. Lyra keeps a persistent memory on the operator's machine. It is just files โ€” typed markdown notes plus an index โ€” written next to the agent the CLI created. There is no database and no remote storage layer; nothing is uploaded. ## What it stores The agent writes typed markdown notes plus an index of them. The index is the canonical entry point; the agent reads it to decide which notes to open in full. This keeps the model's working context small while still letting it recall facts it has learned across sessions. Practical examples of what lands in memory: - Operator preferences and instructions worth keeping between sessions. - Facts the agent has confirmed about your treasury or the protocols it works with. - References to external systems it has been pointed at. ## Why local Memory is observability and recall, not a safety boundary. Keeping it local keeps the data on your machine and keeps the design honest: nothing about memory can move funds. The thing that can move funds is the policy-gated write pipeline, and that is governed entirely by the deterministic control layer described in [Architecture](/docs/architecture). ## Reading it back Because memory is plain files on your machine, you can open or edit it directly โ€” what the agent stored is exactly what you see, no special viewer required. The agent reads the index first, then opens only the notes it needs, keeping its working context small. Read [Brain](/docs/brain) next. Source: [`README.md`](https://github.com/rifkyeasy/lyra/blob/main/README.md). --- ## Architecture > Source: https://github.com/rifkyeasy/lyra/blob/main/README.md # An advisory brain, a deterministic boundary. Lyra splits an agent into two layers that never trade places. The advisory layer (the AI) decides what to do. The control layer (deterministic code) decides whether it is allowed to happen. Every value-moving action crosses the same four gates before it touches the chain. ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” intent โ†’โ”‚ POLICY โ”‚ โ”€โ”€โ–ถ โ”‚ SIMULATE โ”‚ โ”€โ”€โ–ถ โ”‚ APPROVAL โ”‚ โ”€โ”€โ–ถ โ”‚ EXECUTE โ”‚ โ†’ receipt โ”‚ (pure fn) โ”‚ โ”‚ (dry-run) โ”‚ โ”‚ (if risky) โ”‚ โ”‚ + verify โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ hard caps, dryRunTx / material-risk broadcast PTB + allowlists, devInspect actions prompt wait for autonomy tier aborts doomed tx EVEN IN yolo on-chain effects ``` ## The four gates Every value-moving tool call (`sui.send`, `cetus.swap`, `navi.supply` / `withdraw`, `scallop.*`, `walrus.store`) goes through the same pipeline: 1. **Policy** (`evaluatePolicy`, pure and unit-tested): hard caps on native and coin amounts, recipient and coin-type allowlists, slippage caps, and an autonomy tier. A violation blocks the action; an in-cap but material-risk action is flagged for approval. No network, no model, fully auditable. The on-chain `lyra::policy` Move package, deployed on Sui mainnet, anchors these controls. 2. **Simulate**: the PTB is dry-run with `dryRunTransactionBlock` / `devInspect` before any gas is spent; a failure aborts with a decoded reason. 3. **Approval floor**: the policy verdict sits beneath the session permission mode, so a material-risk action prompts for human approval even under YOLO / auto, and is denied outright under `strict`. Fund controls in code, not in the model. 4. **Execute**: broadcast on Sui as a PTB, wait for the effects, return a decision record (policy verdict plus simulated gas plus tx digest). ## The monorepo A Bun + Biome monorepo: ``` packages/ core brain (OpenAI-compatible), local file memory + index, permission service + approval floor, plugin host, identity plugin-onchain the Sui limbs: policy engine, simulation, transfers, DeepBook / Cetus / Turbos swaps (best-route), NAVI / Suilend / Scallop lending, Walrus receipts, DeFiLlama discovery, object/Move-call read/analysis plugin-system OS-sandboxed shell / code / file / web / browser tools plugin-telegram Telegram listener + inline-keyboard approvals gateway long-running daemon (keeps Telegram online, routes approvals) cli the `lyra` binary (init, chat, telegram, gateway, ...) apps/ web Next.js console + docs site ``` ## The runtime - **Brain**: any OpenAI-compatible model (default `gpt-4o-mini`), swappable via environment variable. - **Storage**: local files โ€” the agent's memory notes plus an index, on the operator's machine. - **Chain I/O**: [`@mysten/sui`](https://sdk.mystenlabs.com/typescript) (the Sui TypeScript SDK) for every read and write; [zod](https://zod.dev) tool schemas. - **Surfaces**: a terminal TUI, a Telegram bridge, and the web console. A request from any surface runs the identical pipeline. The policy engine, approval floor, simulation guards, and the DeFiLlama discovery logic are covered by deterministic unit tests (no network, injected fetch), so the safety boundary is verifiable in CI. ## Sui specifics - **Sui mainnet** ยท RPC `https://fullnode.mainnet.sui.io:443` ยท explorer `https://suiscan.xyz` - **Sui testnet** ยท RPC `https://fullnode.testnet.sui.io:443` ยท explorer `https://suiscan.xyz/testnet` - Native SUI has 9 decimals; the smallest unit is MIST (1 SUI = 1e9 MIST). Sui uses object identifiers, not numeric Sui chain IDs. - Gas token: SUI. Execution and settlement happen on Sui; official Move packages, object types, and RPC data are used for all writes, and the `lyra::policy` package is deployed on Sui mainnet. Read [Identity](/docs/identity) next. Source: [`README.md`](https://github.com/rifkyeasy/lyra/blob/main/README.md). --- ## Identity > Source: https://github.com/rifkyeasy/lyra/blob/main/README.md # A plain wallet, an enforced boundary. The agent's identity is just a Sui address, derived from a locally-stored Ed25519 keypair. `lyra init` generates a fresh agent wallet and writes a local encrypted keystore. There is no on-chain mint, no NFT, and no operator signature required to get started; the identity is just an address that holds SUI and signs the transactions the agent is allowed to send. ## The agent wallet The agent wallet is the Sui address that pays gas and is the sender of every write the agent executes. Fund it with a little SUI and the agent can transact within the limits you set. The private key is stored locally in an encrypted keystore, never sent to the model and never required to live anywhere but the operator's machine. ## What actually constrains the agent The identity is deliberately boring. The interesting part is the boundary around it: the policy engine. What the agent can do with its wallet is decided entirely by deterministic configuration, not by the address itself. | Control | Configured by | Effect | |---|---|---| | Hard caps | `LYRA_POLICY_MAX_NATIVE_SUI`, slippage caps | Block any action over the limit. | | Allowlists | `LYRA_POLICY_RECIPIENT_ALLOWLIST`, `LYRA_POLICY_TOKEN_ALLOWLIST` | Restrict recipients and tokens. | | Autonomy tier | `LYRA_POLICY_AUTONOMY` (`auto` / `confirm` / `readonly`) | How much the agent may do without a prompt. | | Read-only | `LYRA_POLICY_READONLY` | Reject all writes outright. | These live in code and environment, so the boundary is the same whether the request arrives from the terminal, Telegram, or the web console. ## Sui networks - Sui mainnet, RPC `https://fullnode.mainnet.sui.io:443`, explorer `https://suiscan.xyz`. - Sui testnet, RPC `https://fullnode.testnet.sui.io:443`, explorer `https://suiscan.xyz/testnet`. Start on Sui testnet for exploratory work, then move to mainnet once your policy is set the way you want it. Read [Memory](/docs/memory) next. Source: [`README.md`](https://github.com/rifkyeasy/lyra/blob/main/README.md). --- ## Console > Source: https://github.com/rifkyeasy/lyra/blob/main/apps/web/app/console # Chat with your treasury, in the browser. The console at [/console](/console) is lyra as a chat. Ask plain-English questions about your money on Sui and it answers with **live on-chain data** โ€” and when you ask it to move funds, deterministic code (not the AI) enforces the limits. ## What you need to set up Almost nothing to start. 1. **Open [/console](/console) and type.** Reads โ€” balances, gas, yields, prices, swap quotes โ€” work with **no wallet and no sign-in**. The brain and the on-chain connection are already wired for you. 2. **Connect your wallet** (top-right) when you want lyra to know which wallet is "yours". Now "what's my balance / my portfolio" just answers for your address โ€” no pasting addresses. 3. **Sign in** (one signature) when you want to: - **save your chat history** to your wallet and sync it across devices, and - **authorize transfers** โ€” only the signed-in owner can move funds, and only within policy. No API key, no install. (Want to run it yourself with your own keys and limits? See the [Quickstart](/docs/quickstart) and [CLI](/docs/cli).) Reads need nothing. Anything that moves funds is **prepared by lyra, then signed by your own connected wallet** โ€” you see a "Confirm in wallet" button and your wallet pops up to approve. The server never holds your key. A policy cap is enforced before anything can be prepared. - **Portfolio & positions** โ€” "what's my portfolio worth?", "what does `0xโ€ฆ` hold?" - **Yields** โ€” "best stablecoin yield on Sui right now?" - **Swap** โ€” "swap 0.01 SUI to USDC" โ€” routed across Sui venues (Cetus, Turbos, DeepBook) with slippage protection, then you sign it. - **Transfer & stake** โ€” "send 0.01 SUI to `0xโ€ฆ`", "send 5 USDC to `0xโ€ฆ`", "liquid-stake 0.1 SUI via Haedal" (Sui addresses are 0x + 64 hex). - **Lend & borrow** โ€” "supply 5 USDC to NAVI", "withdraw all my USDC", "borrow 2 USDC", "repay all my debt" (NAVI / Suilend / Scallop). - **Receipts** โ€” "store this decision record to Walrus" New here? Tap the **template menu** (the โ˜ฐ left of the input) for one-tap starters, grouped by activity: Yields, Swap, Transfer & stake, Lend & borrow, Portfolio & positions. ## Your chats are saved Every conversation is kept. **Signed in**, your history lives on the server keyed to your wallet, so it follows you across devices and browsers. **Signed out**, it's saved in this browser. The sidebar lists past chats โ€” switch between them, or delete one. "New chat" starts fresh. Disconnecting your wallet simply hides that wallet's chats; they come back when you reconnect. ## Is it safe? The AI only **advises**. Every value-moving action goes through deterministic, policy-checked code, is **capped** by a hard per-transaction limit the model can't raise, and is then **signed by your own wallet** โ€” lyra prepares the transaction, but nothing moves until you approve it in your wallet, and the server never holds your key. Reads can never move funds. So you can explore freely and stay fully in control of anything that touches money. ## Your agents [/console/agents](/console/agents) lists the agent wallets tied to your account โ€” each is just a Sui address derived from a local Ed25519 keypair, with its balances, recent activity, and active policy. There is no registry, no NFT, and no mint; connect and sign in to load them. Read the [Quickstart](/docs/quickstart) to run your own agent, or [Introduction](/docs/introduction) for the bigger picture. Source: [`apps/web/app/console`](https://github.com/rifkyeasy/lyra/tree/main/apps/web/app/console). --- ## Introduction > Source: https://github.com/rifkyeasy/lyra/blob/main/README.md # An AI agent you can trust with a wallet. Lyra is an AI agent that does real on-chain work on Sui, check balances, transfer, swap, lend, stake, and discover yield, from your terminal, Telegram, or a web console. What makes it more than a chatbot with a wallet is the part the AI cannot override: every value-moving action is checked against a deterministic policy, dry-run simulated, and (when material-risk) held for human approval before it is broadcast as a PTB. The model proposes; code disposes. The pitch in one line: an AI treasury operator you can actually trust with a wallet, because the spending limits, allowlists, and approval gates live in auditable code, not in a prompt the model could rationalize its way around. ## Why this design LLMs are good at deciding what to do and bad at being a safety boundary. A jailbreak, a confused tool call, or a hallucinated "the user said it was fine" should never be the only thing standing between an agent and your treasury. So Lyra splits the two. | Layer | Who | What it owns | |---|---|---| | Advisory | The AI | Understands intent, picks tools, explains tradeoffs, discovers opportunities. | | Control | Deterministic code | A pure policy engine, pre-flight simulation, and an approval floor the model has no way to bypass. | This is the defensible core: unified risk analysis, RWA-eligibility awareness, transaction simulation, enforceable policy controls, approvals, and auditable execution. It is not a generic chatbot and not an APY-ranking bot. ## What it does today Balances and tokens, transfers (native SUI and any Sui coin type), trading via Cetus and Turbos plus DeepBook's native CLOB (best-route comparison), lending via NAVI, Suilend, and Scallop, liquid staking via Haedal and SpringSui, yield discovery via DeFiLlama (read-only analytics with risk signals and RWA-eligibility flags for restricted RWA and tokenized yield products), and on-chain analysis with arbitrary object and Move call inspection. The brain is any OpenAI-compatible model (default `gpt-4o-mini`), swappable by environment variable. Memory is plain files on the operator's machine. Chain I/O goes through `@mysten/sui` (the Sui TypeScript SDK). Execution and settlement happen on Sui. ## Who this is for If you want an autonomous agent that can operate a treasury, propose and execute on-chain actions, and surface opportunities, but whose spending boundary you can read, test, and enforce in code, Lyra is the path. Read [Quickstart](/docs/quickstart) next. ## How the docs are organized Four groups. Get started covers install and a first chat. Concepts walks the four-gate write pipeline and the tool model. Reference is the CLI surface and the config shape. Operate covers the operator console at `/console`. Source for everything in this section: [`README.md`](https://github.com/rifkyeasy/lyra/blob/main/README.md).