MuseXTDocs
Contents

    Documentation

    How MuseXT works

    MuseXT gives an AI agent a crypto wallet that it can use without being able to exceed the authority its owner has granted. This document describes the system's model, the rules that govern spending, the way transactions are executed, and the interfaces through which agents and developers interact with it.

    It is written for owners who want to understand exactly what their agent can and cannot do, and for developers who integrate an agent or write a skill. Terms defined in section 2 are used with those meanings throughout.

    1Introduction

    1.1The problem

    A language-model agent that can call tools can also be asked to move money. Giving it a private key directly is unsafe, because the agent's behaviour is shaped by whatever text it reads, and a key cannot distinguish a legitimate instruction from a manipulated one. Withholding the key entirely makes the agent useless for any task that involves payment or trading.

    MuseXT resolves this by separating two things that an ordinary wallet combines: custody, meaning possession of the signing key, and authority, meaning the right to decide what gets signed. The server holds custody. The owner defines authority as a written policy. The agent may request any action, but a request becomes a signed transaction only when it satisfies that policy or the owner approves it explicitly.

    1.2Design principles

    Three rules follow from that separation and appear throughout the system.

    1. The agent never holds a key. Agents authenticate with revocable API keys. Wallet keys are encrypted at rest and are decrypted only inside the server, at the moment of signing.
    2. Spending is measured, not declared. When code proposes a transaction, the server simulates it against current chain state and uses the simulated balance changes as the amount spent. A description supplied by the requester has no effect on the policy decision.
    3. The owner has the last word. Anything outside the configured limits is either refused or held until the owner approves it. A kill switch stops all agent spending immediately.

    2Concepts and terminology

    Owner
    The person responsible for an agent wallet, identified by the Solana wallet they sign in with. The owner sets the policy, issues API keys, approves held requests and can withdraw funds at any time.
    Agent wallet
    The wallet the agent spends from. Each owner has one Solana address and one EVM address. Both are created and held by the server, and neither is the owner's personal wallet.
    API key
    A bearer credential beginning with aw_ that an agent presents on every request. Each key belongs to one owner and carries a set of scopes. Keys are stored only as hashes and can be revoked individually.
    Scope
    A named permission such as read, transfer, swap or launch. A key can call a skill only if it holds that skill's scope.
    Skill
    A single operation an agent can perform, for example transfer or get_token_thesis. A skill is defined once and exposed simultaneously as an MCP tool, a REST route and an OpenAPI operation.
    Plugin
    A named, versioned group of related skills. The marketplace lists plugins, and each owner turns them on or off for their own wallet.
    Policy
    The owner's rules for agent spending: dollar limits, approval thresholds, token rules, recipient restrictions and settings for swaps, skills and launches.
    Activity
    The durable record of one request, including its parameters, its status, the resulting transaction signature and any error.
    Approval
    An activity in the pending_approval state. It executes only when the owner approves it from the dashboard.

    3Getting started

    3.1Signing in

    Owners sign in by signing a text message with a Solana wallet such as Phantom or Solflare. The message follows the Sign-In-With-Solana format. It names the site, contains a random nonce, and expires five minutes after it is issued. Signing it costs nothing and cannot authorise a transaction. Each challenge can be used once. A successful sign-in creates a session that lasts seven days.

    The first sign-in creates the owner's agent wallet. The EVM address is created the first time it is needed.

    3.2Issuing an API key

    From Settings, create a key for each agent or application. By default a new key receives every scope. Narrowing the scopes is the most direct way to limit what an integration can do: a research assistant, for instance, needs only read. The full key is shown once, at creation. Revoking a key takes effect on the next request that uses it.

    3.3Connecting Muse

    Muse adds tools through custom connectors, each described by an OpenAPI schema. The connection is made in the Muse chat itself and takes three steps. An API key must exist beforehand (section 3.2).

    1. Send Muse the following message, which names the schema:
      Add a custom connector with this OpenAPI schema: https://musext.xyz/openapi.json
      The message sent in a Muse chat
    2. Muse reads the schema, sees that it requires a bearer token, and opens its secure credentials store. Paste the API key into the empty field and choose Add. The key is held in Muse's vault; the agent itself never receives the value.
      Muse's secure credentials store with a field for the key
    3. Muse builds its tools from the schema and verifies the key with a read-only call. From then on it can use every skill the key's scopes permit.
      Muse confirming the connection

    The key should never be typed into the chat. A key in the conversation becomes part of the chat history, whereas a key in the credentials store is sent only with requests to MuseXT. The schema itself lists operations and contains no credentials. Muse chooses between operations by reading their descriptions, which is why skill descriptions are written as instructions to the agent.

    3.4Connecting MCP clients

    Claude, Cursor and other clients that implement the Model Context Protocol connect to the streamable HTTP endpoint. The server is stateless, so each request carries the key in its Authorization header.

    https://musext.xyz/mcp

    Clients that support only local (stdio) servers can run the bundled proxy, which forwards to the hosted endpoint:

    {
      "mcpServers": {
        "musext": {
          "command": "npx",
          "args": ["tsx", "src/mcp-stdio.ts"],
          "env": {
            "AGENT_WALLET_URL": "https://musext.xyz",
            "AGENT_WALLET_API_KEY": "aw_..."
          }
        }
      }
    }

    The tools an agent sees depend on the plugins the owner has enabled and the scopes of the key in use. A tool whose plugin is turned off does not appear.

    4Wallets and networks

    4.1The Solana wallet

    Solana is the default network. When a request does not name a chain, it refers to Solana. The Solana wallet holds SOL and any SPL token, including Token-2022 tokens, and is the wallet used for swaps, pump.fun launches, token research and all Solana skills.

    4.2The EVM wallet

    Each agent also has one EVM address, and the same address is valid on Ethereum, Base and Robinhood Chain. Because the address is shared, a deposit sent on the wrong one of these networks still reaches the agent, but it stays on the network it was sent on. All three networks use ETH to pay for gas. Requests select a network with the chain parameter, whose values are solana, ethereum, base and robinhood. At present, only ETH can be sent from the EVM wallet.

    4.3Funding and withdrawal

    To fund the agent, send assets to the deposit addresses shown on the Wallet page. It is sensible to keep only what the agent needs for its current tasks, since the agent wallet is a spending account rather than a place for savings.

    Withdrawals are an owner action and are not subject to the policy, because the policy constrains the agent and not the owner. A Solana withdrawal always goes to the owner's own address. An EVM withdrawal goes to an address the owner names, because the owner's sign-in wallet is a Solana wallet. Omitting the amount withdraws the entire balance less the network fee.

    4.4Names for the wallet

    An address is a long string that people cannot remember or check by eye. A name system maps a readable name to an address, so that a payment can be sent to alice.sol instead. The agent can buy such a name for its own wallet from three registries.

    SuffixRegistryNetworkPaymentTermName resolves to
    .solSolana Name ServiceSolanaSOLPermanentThe Solana wallet
    .base.ethBasenamesBaseETH1 to 10 yearsThe EVM wallet, on Ethereum and on Base
    .ethENSEthereumETH1 to 10 yearsThe EVM wallet, which also takes the name as its primary name

    A .sol name is priced by length in US dollars: $20 for five characters or more, and more for shorter names. It is paid once, in SOL converted at the current rate, together with about 0.008 SOL of rent for the account that stores the name's record. The two EVM registries price names in ETH per year, and shorter names again cost more.

    The check_domain skill reports whether a name is free, its price in the paying currency and in dollars, and the address that would own it. The buy_domain skill purchases it. A purchase is a spend like any other: its dollar value is checked against the owner's limits, and a purchase above the approval threshold waits for the owner. For a .sol name the value is measured by simulating the purchase, so the record's rent is included. For the EVM registries the agent pays the quoted price plus 3%, which absorbs any price movement before the transaction is included; the registry refunds whatever it does not charge, but the full amount paid counts against the limits.

    An .eth name is registered in two steps. ENS requires the buyer first to publish a sealed commitment to the name, and to reveal and register it at least one minute later. The commitment prevents another party from observing the request and registering the name first. MuseXT publishes the commitment immediately and completes the registration about seventy seconds afterwards without further action; the activity remains submitted in the meantime. Because this takes two Ethereum transactions, network fees for an .eth name are higher than for the other two, typically a few dollars.

    An approval can arrive hours after the request, so availability and price are checked again at the moment of purchase. If another buyer has registered the name in the interval, the purchase fails and nothing is spent.

    5Spending policy

    The policy is the owner's statement of what the agent may do without asking. Every request that spends, from any skill and on any chain, is evaluated against it before anything is signed.

    5.1Valuation in US dollars

    Limits are expressed in US dollars so that a single set of numbers applies to every asset and every network. When a request arrives, the server prices the amount at the current market rate and records that dollar value on the activity. SOL and SPL tokens are priced from Jupiter's price feed; ETH is priced from its Solana-wrapped equivalent, which tracks it closely.

    An asset with no reliable price cannot be compared against a dollar limit. Such a request is never allowed automatically: it is held for the owner's approval, however small it is.

    5.2Order of evaluation

    A request is checked in the following order. The first rule that denies it ends the evaluation. Rules that call for approval are collected, and if any applies, the request is held with all of the reasons listed.

    1. If agent spending is switched off, the request is denied.
    2. If the request comes from a skill and the owner requires approval for skill transactions, approval is required.
    3. For swaps: if swaps are disabled the request is denied; if the requested slippage exceeds the maximum it is denied; if the token being bought has no configured limits, the unlisted-token rule applies.
    4. For transfers: if a recipient allowlist exists and the recipient is neither on it nor the owner, the request is denied.
    5. If the asset has its own per-token limits, those are applied in the token's own units. Otherwise, a token other than SOL or ETH falls under the unlisted-token rule.
    6. The dollar limits are applied: the per-transaction maximum, then the 24-hour maximum, then the approval threshold.

    5.3Limits and the rolling window

    SettingDefaultEffect
    Per transaction$50A single request worth more is denied outright. It is not offered for approval.
    Per day$200The total value of agent spending over the preceding 24 hours, including this request, may not exceed it.
    Ask above$25A request worth more, but within both limits, waits for approval. Leaving it empty removes the threshold.

    The daily limit is a rolling window rather than a calendar day. At any moment it counts every agent-initiated spend that was submitted or confirmed in the previous 24 hours, across all chains, at the dollar value recorded when each was requested. Failed and rejected requests do not count, and neither do owner withdrawals. Because values are fixed at request time, a later change in price does not alter how much of the day's allowance has been used.

    5.4Token rules and recipients

    An owner may give a specific token its own limits, measured in that token's units. These apply in addition to the dollar limits, so a request must satisfy both. For tokens without their own limits, the unlisted-token rule decides whether spending or buying them is denied, held for approval (the default), or allowed.

    A recipient allowlist, when present, restricts transfers to the listed addresses. The owner's own address is always permitted.

    5.5Swaps, skill transactions and launches

    Swaps are routed through Jupiter. The default slippage is 0.5% and the policy maximum defaults to 1%. An agent may state a swap in dollars, for example "buy $10 of this token", in which case the input amount is derived from the current price.

    Skill transactions are transactions constructed by a skill rather than by the core, such as staking. By default each one waits for approval. An owner who trusts the installed skills can allow them to run automatically within the dollar limits.

    Token launches on pump.fun always require approval, whatever the other settings say, because a launch is public and cannot be undone. Separate settings cap the SOL spent on the creator's initial purchase and the number of launches per day.

    5.6A worked example

    Suppose SOL trades at $150 and the defaults are in force. The agent has already spent $120 today.

    6Activity and approvals

    6.1Status lifecycle

    Every request produces an activity, and every activity is in exactly one of the following states.

    StatusMeaning
    pending_approvalHeld for the owner. Nothing has been signed.
    rejectedDeclined by the owner, or expired before approval. Nothing was signed.
    submittedSigned and sent, but not yet confirmed on-chain.
    confirmedIncluded in a block and successful.
    failedThe transaction failed, or the network dropped it. The error explains which; a dropped transaction spent nothing.

    A request that is denied by the policy does not create an activity. The agent receives an error explaining which rule applied, so that it can report the reason or ask the owner to change the limits.

    6.2Approval expiry

    A held request can be approved for 24 hours. After that it is marked rejected. The limit exists because the circumstances that justified a request, such as a price or a recipient's needs, may no longer hold a day later. A held swap is quoted again when it is approved, so it executes at the market price of that moment rather than the price at the time of the request.

    6.3Idempotency

    Agents retry requests when a response is slow or lost, and a naive retry of a payment pays twice. Every skill that spends accepts an idempotency key: over REST, the Idempotency-Key header; over MCP, an idempotencyKey argument. A request that repeats a key already used by the same owner returns the original activity instead of acting again. Keys may be up to 128 characters, and a new random value should be used for each distinct intended action.

    7Transaction execution

    7.1On Solana

    Every transaction is simulated before it is sent. A transaction that the network would reject is therefore refused without cost. The simulation also measures the compute the transaction needs, and the compute limit is set to that figure with a margin.

    The priority fee is derived from recent fees paid on the accounts the transaction touches: the server takes the 75th percentile, adds a margin, and applies a floor so that transactions are not starved during quiet periods. The total priority fee for one transaction never exceeds 0.002 SOL. Once sent, the transaction is re-broadcast every two seconds until it is confirmed or its blockhash expires. An expired transaction can no longer land, so its failure is final and nothing was spent.

    For holders, when the operator has configured a relayer, the relayer pays the network fee on transfers, so the agent needs no SOL for gas.

    7.2On EVM networks

    EVM transactions are simulated with an eth_call before signing, and gas is estimated from current network conditions. Transactions from one address are sent one at a time, so that concurrent requests cannot collide on the same nonce. The server waits up to a minute for inclusion. Unlike Solana transactions, an EVM transaction does not expire, so one that has not been included stays submitted until the network includes it.

    7.3Reconciliation

    If a request ends before its outcome is known, because confirmation took too long or the server restarted, the activity remains submitted. A background process examines such activities every minute and settles each one according to the chain's record: confirmed, failed, or, for a Solana transaction whose blockhash has expired without inclusion, failed as dropped. The owner and the agent therefore always converge on the chain's actual state.

    8Skills and the marketplace

    8.1The model

    All agent capabilities, including the built-in ones, are skills grouped into plugins. Built-in plugins start enabled. The wallet basics plugin cannot be disabled. Community plugins start disabled, and each owner decides whether to enable them. Plugins are free.

    A skill declares a name, a description written for the agent, an input schema, the scope it requires and a REST route. From that single declaration the server generates the MCP tool, the REST endpoint and the OpenAPI operation, and validates inputs the same way on every interface.

    8.2Why third-party skills cannot overspend

    A skill never receives a private key. It receives an object that exposes the wallet's address and a single method, propose, which accepts instructions and a summary for the owner. The core then processes the proposal in four steps.

    1. It simulates the transaction and measures the change in every balance the wallet controls, including SOL paid as rent for new accounts.
    2. It refuses any transaction that would transfer control rather than funds: approving a token delegate, changing a token account's owner or close authority, or reassigning the wallet itself. Such changes move no value when they happen and would escape a check based only on balances.
    3. It applies the policy to each measured outflow, exactly as for a built-in transfer.
    4. It signs and sends, holds for approval, or refuses, and records the result as an activity.

    The protection has a boundary that should be stated plainly. Plugins run inside the server process, so the operator must install only plugins whose code they trust. The pipeline defends owners against skills that are mistaken or that misdescribe their effects; it does not make arbitrary server-side code safe to run.

    8.3Writing a skill

    The following skill stakes SOL with a validator. It is abbreviated from examples/stake-sol.ts in the source.

    import { Authorized, Keypair, Lockup, PublicKey, StakeProgram } from "@solana/web3.js";
    import { z } from "zod";
    import { definePlugin, defineSkill } from "../src/skills/types.js";
    
    export const stakeSol = defineSkill({
      name: "stake_sol",
      description: "Stake SOL with a validator to earn staking rewards.",
      scope: "stake",
      input: z.object({
        amount: z.string().describe('SOL to stake, e.g. "1.5"'),
        voteAccount: z.string().describe("The validator's vote account"),
      }),
      http: { method: "POST", path: "/v1/stake" },
      annotations: { destructive: true },
      idempotent: true,
    
      async run({ wallet }, { amount, voteAccount }) {
        const me = new PublicKey(wallet.address);
        const stakeAccount = Keypair.generate();
        const instructions = [/* create the stake account, then delegate it */];
        return wallet.propose(instructions, {
          summary: `Stake ${amount} SOL with ${voteAccount}`,
          signers: [stakeAccount],
        });
      },
    });
    
    export default definePlugin({
      id: "stake-sol", title: "SOL staking", author: "you", version: "0.1.0",
      description: "Stake SOL with any validator.", category: "defi",
      skills: [stakeSol],
    });

    The operator installs plugins through the SKILL_PLUGINS setting, which accepts file paths and npm package names. A new scope introduced by a skill appears automatically among the permissions an owner can grant to a key. Skills that only read data need not call propose and may simply return a value.

    8.4Skill reference

    This table is generated from the live marketplace, so it lists exactly the skills this server offers.

    Loading the skill list…

    9HTTP API

    9.1Authentication

    Agent requests carry the key as a bearer token.

    curl https://musext.xyz/v1/balances?chain=all \
      -H "Authorization: Bearer aw_..."

    Routes under /v1/owner/ are for the dashboard and accept only an owner session, never an API key. An agent therefore cannot approve its own requests, change the policy or issue keys.

    9.2Errors

    Errors share one shape. The code is stable and intended for programs; the message is intended for people and may change.

    { "error": { "code": "policy_denied", "message": "Amount ($75) exceeds the per-transaction limit of $50" } }
    StatusCodeMeaning
    400invalid_requestThe input failed validation. The message names the field.
    400invalid_amount, invalid_address, invalid_mint, invalid_chainA specific parameter is malformed or unknown.
    400insufficient_fundsThe wallet cannot cover the amount and fees.
    400simulation_failedThe transaction would fail on-chain, so it was not sent.
    401unauthorizedThe key or session is missing, revoked or expired.
    403policy_deniedThe policy forbids the request. The message states which rule.
    403insufficient_scopeThe key lacks the scope this skill requires.
    403holder_requiredThe feature is reserved for token holders.
    404not_foundNo such activity, or it belongs to another owner.
    409approval_expired, not_pendingThe approval can no longer be acted on.
    409domain_unavailableThe name is already registered.
    429rate_limitedToo many requests from this key in the past minute.
    502swap_failed, price_unavailable, thesis_unavailableAn upstream service failed. Retrying later is appropriate.

    9.3Rate limits

    Each API key may make 120 requests per minute when its owner is a holder and 20 otherwise. The limit applies per key, so separate agents with separate keys do not consume each other's allowance.

    10Holder benefits

    Owners who hold the project token receive additional capabilities. Holder status is determined by the balance of the wallet the owner signs in with, and is re-checked every five minutes.

    CapabilityHoldersOthers
    Transfers and balancesYesYes
    Network fees on Solana transfersPaid by the relayer, when one is configuredPaid by the agent wallet
    Service fee on SOL transfersNone0.25%, when the operator enables it
    SwapsYesNo
    pump.fun launchesYesNo
    Token thesis breakdownsYesNo
    Requests per minute12020

    Until the project token is configured, every owner is treated as a holder.

    11Security model

    11.1Key custody

    Agent wallet keys are generated on the server and encrypted with AES-256-GCM under a master key held only in the server's configuration. They are decrypted in memory at the moment of signing and are never returned by any interface. API keys and session tokens are stored as SHA-256 hashes, so a copy of the database does not yield usable credentials. The database is backed up daily.

    11.2Trust assumptions

    MuseXT is a custodial service, and its guarantees should be read with that in mind. The policy constrains the agent; it does not constrain the server, which holds the keys and could in principle sign anything. An owner is therefore trusting the operator in the same way a user trusts any custodial wallet. The practical consequences are that the agent wallet should hold working balances rather than savings, and that the owner can withdraw everything at any time.

    Within that assumption, the system is designed so that neither a manipulated agent nor a faulty skill can move more than the owner allows. An agent that is persuaded to act against its owner's interests is limited to the dollar limits, cannot reach the owner routes, and cannot alter its own permissions.