ATLAS ://OS / docs
WATCH LIVE
ATLAS://OS — documentation

Everything, in detail.

Atlas Treasury OS is an open-source, off-chain treasury automation framework for Solana: a deterministic agent that sweeps SOL into a USDC reserve, backs a 1:1 pegged token, and records every action as a verifiable receipt. This page documents how every part of it works.

off-chaindeterministicrule-enforced AIMITnode.js ≥18

01Overview

What it is: a Node.js agent that runs on a cadence. Each cycle it reads on-chain balances, decides what fraction of the collector wallet's SOL to sweep, swaps it to USDC through Jupiter, splits the proceeds between a transparent protocol fee and the treasury, mints or burns the pegged token to hold reserve = supply, and writes a signed, append-only JSON receipt.

What it is not: a smart contract. All behavior executes off-chain. Funds are managed exclusively by the keypairs you provide, and behavior is only as immutable as the machine it runs on. If you require trustless guarantees, the logic must be deployed as an on-chain program — that is Phase III of the roadmap, gated on an audit.

design principle

The architecture mirrors early agent systems (ELIZA-style rule mediation): an AI component assists with interpretation, narration, and bounded proposal — while final execution remains deterministic, rule-enforced, and auditable. The AI holds no keys and cannot sign transactions, by construction.

02Architecture

Three wallets, three roles

WalletRole
devThe project wallet — where inflows (e.g. creator fees) originate. Monitored for value-based cadence; an optional top-up routine keeps it funded for fees.
collectorReceives SOL inflows. The agent sweeps from this wallet: it signs the Jupiter swap and the USDC transfers. Keeps a SOL buffer so it can always pay its own transaction fees.
treasuryHolds the USDC reserve and the mint authority for the pegged token ($ATLAS). Signs mint/burn actions only.

The tick

The agent's unit of work is a tick. In continuous mode it loops forever, sleeping the interval the cadence engine returns; with SINGLE_RUN=1 it executes exactly one tick and exits (useful for cron-style scheduling or testing). Every tick ends in a receipt — including no-ops: if the computed sweep is below the minimum chunk, the agent writes a noop receipt with reason below_min_sweep rather than doing nothing silently.

Failure handling

Swaps and transfers run through a retry executor with backoff (default: 3 attempts, 4s apart). RPC reads use the confirmed commitment. If a step ultimately fails, the tick aborts with an error — it never partially applies a decision and pretends it completed.

03The pipeline — seven steps, every cycle

  1. Read. Fetch dev SOL, collector SOL, treasury USDC balance, and the pegged token's total supply from the chain.
  2. Propose (the only AI step). If the LLM proposer is enabled, it receives the state snapshot and returns a suggested sweepPct as JSON. It receives no keys and returns nothing but a number.
  3. Enforce. Whatever was proposed — by the AI or by the built-in rule — is clamped into [policy.minPct, policy.maxPct]. A proposal outside bounds is simply cut to the boundary. This step cannot be skipped.
  4. Swap. The sweep amount of SOL is quoted and swapped to USDC via Jupiter (lite-api, v1 quote + swap, versioned transaction, configurable slippage), signed by the collector keypair, confirmed on-chain.
  5. Split. The resulting USDC is divided: a protocol fee (basis points, disclosed in config), an optional donation, and the remainder transferred to the treasury — batched in one transaction.
  6. Peg. Compute drift = reserve − supply. Positive drift mints that amount of $ATLAS to the treasury; negative drift burns it. Result: reserve = supply, 1:1.
  7. Receipt. Write an append-only JSON receipt containing the inputs, the decision (including what the AI proposed vs. what was executed), the outputs, and every transaction signature.

04Cadence — when the agent acts

Atlas doesn't run on a fixed cron. The interval between sweeps is computed each cycle with a strict precedence:

  1. Launch safety window. For the first launch.safetyHours (default 24h) after launch, the agent uses a fixed, conservative interval (launch.intervalMin, default 60 min). This bounds the blast radius of any early-stage malfunction.
  2. Value-based baseline. After the safety window, the interval scales with the dev wallet's USD value on a log₁₀ smoothstep curve between minIntervalMin (30) and maxIntervalMin (360), pivoting at pivotUsd. Small treasuries sweep often; large ones relax.
  3. Spike modifier. If the dev wallet's value jumped by at least spikeUsd ($10) or spikePct (25%) since the last look, the interval is multiplied by spikeIntervalMult (0.5) — inflow surges make the agent act sooner.
  4. Clamp. The result is always clamped back into [minIntervalMin, maxIntervalMin].
// value-based baseline (simplified)
t = clamp( log10(devValueUSD) / log10(pivotUsd), 0, 1 )
s = t² · (3 − 2t)                     // smoothstep
interval = MIN + s · (MAX − MIN)      // minutes, then spike ×0.5, then clamp

05Sweep policy — how much moves

Two questions are answered by pure functions every tick:

What percentage?

If the collector's SOL balance jumped by at least policy.spikeSol since the last tick, the sweep is the fixed policy.spikePct (20%) — surge in, surge swept. Otherwise the percentage is drawn uniformly from [minPct, maxPct] (1.0%–2.9% by default), which keeps sweeps organic rather than metronomic.

How much SOL?

sweep = collectorSOL × pct
sweep = min(sweep, collectorSOL − collectorSolBuffer)  // never drain the fee buffer
sweep = max(sweep, minSolChunk)                       // too small isn't worth a tx
sweep = min(sweep, maxSolChunk)                       // hard per-sweep ceiling

If the final value still falls below minSolChunk (e.g. the collector is nearly empty), the tick becomes a noop receipt instead of a transaction.

06The peg — reserve = supply

The pegged token ($ATLAS) tracks the treasury's USDC reserve at exactly 1:1. After every sweep settles, the agent measures drift = reserveUSDC − tokenSupply:

  • drift > 0 (reserve grew): mint drift tokens to the treasury's token account.
  • drift < 0 (reserve shrank): burn |drift| tokens from it.
  • |drift| < minDrift: do nothing — dust isn't worth a transaction.

The peg is therefore not an algorithmic promise — it's an accounting identity the agent restores every cycle, and both sides of the identity are independently readable on-chain: the treasury's USDC balance and the token's supply.

note

Mint/burn is disabled by default (mintBurn.enabled: false) and additionally requires mintBurn.minDrift and mintBurn.decimals to be set in config before it activates. Until then the agent sweeps and splits but leaves supply untouched.

07AI guardrails — reason freely, execute deterministically

The LLM integration has two modes, both optional and both powerless over funds:

ModeWhat the AI doesWhat it cannot do
reporter_onlyTurns the tick's numbers into a human-readable, lowercase summary in the configured personality voice. Falls back to a plain template if the API is unavailable.Change any number. The summary is narration of decisions already made.
rules_proposerReceives the state snapshot and the policy bounds, returns {"sweepPct": n} as JSON.Escape the clamp. Its output is forced into [minPct, maxPct] before use; malformed output is ignored entirely.

Structural guarantees, independent of any prompt: the AI client is called with no keypairs in scope, its response is parsed as a single number or plain text, and the transaction-building code paths never branch on anything the model says. A hostile or hallucinating model can, at worst, pick a sweep percentage inside the same range the random rule already uses.

The personality.example.md file defines the reporting voice — lowercase, dry, protocol-centric, with mandatory numerical rules (units, decimals, peg status) so narration never contradicts the receipt.

08Receipts & verification

Every tick writes receipts/receipt-<timestamp>.json — append-only, one file per action:

{
  "ts": "2026-07-02T21:04:11.582Z",
  "action": "sweep",
  "inputs":   { "devSOL": 3.2, "collSOL": 4.5544, "treasUSDC": 656.02, "atlasSupply": 656.02 },
  "decision": { "pct": 0.029, "sweepSOL": 0.1320, "proposedPct": 0.034 },
  "outputs":  { "collectorUsdc": 10.6797, "feeAmount": 0.1068, "toTreasury": 10.5729,
                "reserveNow": 666.59, "supplyNow": 666.59, "pegAction": "mint" },
  "tx": { "swapSig": "5xQm…9c2R", "sendSig": "9mBt…7aQe", "pegSig": "2kLp…x8Wd" },
  "summary": "sweep 2.90% (0.1320 sol) → 10.5729 usdc to treasury. reserve 666.59, supply 666.59 (1:1)."
}

Note decision.proposedPct vs decision.pct: the receipt permanently records what the AI wanted and what the rules actually executed.

Re-checking a receipt

$ npm run verify receipts/receipt-2026-07-02T21-04-11.json
{ "ok": true, "tx": { "5xQm…9c2R": true, "9mBt…7aQe": true, "2kLp…x8Wd": true } }

The verifier fetches every signature in the receipt from the chain and reports whether each transaction exists. Anyone can run it against any published receipt — nothing in a receipt needs to be taken on trust.

09Configuration reference

All behavior is driven by config.json (copy config.example.json) plus a few environment variables. The execution path never changes between deployments — only the parameters do.

config.json

KeyDefaultMeaning
rpcUrlmainnet-betaSolana RPC endpoint (overridable via RPC_URL).
launch.safetyHours24Fixed-cadence safety window after launch.
launch.intervalMin60Interval used inside the safety window (minutes).
cadence.minIntervalMin / maxIntervalMin30 / 360Bounds of the adaptive interval.
cadence.pivotUsd20Dev-wallet USD value where the baseline curve pivots.
cadence.spikeUsd / spikePct10 / 0.25Absolute / relative inflow jump that counts as a spike.
cadence.spikeIntervalMult0.5Interval multiplier during a spike (shorter = sooner).
policy.minPct / maxPct0.01 / 0.029Sweep percentage bounds — also the AI's hard clamp.
policy.spikePct / spikeSol0.2 / 0.1Sweep % used when collector SOL jumps by ≥ spikeSol.
limits.slippageBps50Max slippage for the Jupiter swap.
limits.minSolChunk / maxSolChunk0.008 / 0.010Floor / ceiling for a single sweep, in SOL.
limits.collectorSolBuffer0.01SOL always left behind for transaction fees.
retries.jupiter / backoffMs3 / 4000Swap retry policy.
protocolFee.enabled / bps / recipientUsdcAtatrue / 100 / —Client-side protocol fee (1%), fully disclosed, routed to a USDC token account you set.
donation.enabled / bpsfalse / 0Optional second split for donations.
mintBurn.enabled (+ minDrift, decimals)falsePeg mint/burn switch — see §06.
llm.enabled / mode / modelfalse / reporter_only / gpt-4o-miniAI integration — see §07.
reporting.siteWebhook""URL that receives every receipt as JSON — the live site's /webhook.
addresses.*Public keys and token accounts: dev, collector, treasury, USDC mint, the $ATLAS mint, and their ATAs.
jupiter.base / apiKeylite-api.jup.ag / ""Jupiter endpoint; API key optional.

Environment (.env)

VariableMeaning
RPC_URLOverrides config rpcUrl.
DEV_KEYFILE / COLLECTOR_KEYFILE / TREASURY_KEYFILEPaths to keypair files (JSON array or base58 secret). The only things that can ever sign.
OPENAI_API_KEYEnables the LLM reporter/proposer when llm.enabled is true.
X_APP_KEY / X_APP_SECRET / X_ACCESS_TOKEN / X_ACCESS_SECRETOptional X (Twitter) reporting credentials.
SINGLE_RUNSet to 1 to execute one tick and exit.

10Quickstart

$ git clone https://github.com/AtlasTreasuryOS/atlas
$ cd atlas && npm install
$ cp config.example.json config.json   # set addresses + fee recipient
$ cp .env.example .env                 # point at your keyfiles + RPC
$ npm run single                       # one tick, then exit
$ npm start                            # continuous agent loop
$ npm run verify receipts/<file>.json  # re-check any receipt on-chain
before running with real funds

Set protocolFee.recipientUsdcAta to your USDC token account, fill in all addresses.*, fund the collector above collectorSolBuffer, and start with npm run single on small limits. The defaults ship with placeholder addresses on purpose.

11The live site

The dashboard on this site streams the treasury in real time over WebSocket: the peg gauge, reserve and supply, protocol fees, the receipt tape, and the next-sweep countdown. SOL is priced on the live Pyth oracle feed — the same numbers anyone can query from Hermes.

Disclosure: until mainnet wallets are wired, the dashboard runs a faithful simulation of the agent — the same sweep, cadence, and peg math as the code documented above, executing against the real Pyth SOL price. When the real agent runs with reporting.siteWebhook pointed at this site's /webhook endpoint, its actual receipts take over the tape and the source badge flips from SIM to AGENT.

12Important truths

  • This is not a smart contract; all behavior is implemented off-chain.
  • Funds are managed only by the keypairs you provide.
  • The AI cannot sign transactions or move funds outside predefined constraints — proposals are enforced deterministically.
  • This repository provides infrastructure, not a strategy — and nothing here is financial advice.
  • If you require immutable behavior, deploy the logic as an on-chain program (roadmap Phase III, audited first).
  • Atlas Treasury OS is MIT-licensed and is a fork of keystoneOS; the original license and copyright are preserved in the repo.

READ THE SOURCE  WATCH THE TREASURY