circuit.toml, DESCRIPTION.md, AGENTS.md, index.ts exporting run(agent), package.json, and the generated circuit-sdk.d.ts and circuit-settings.d.ts.
DESCRIPTION.md
Users review this description before Start;circuit new writes a starter whose every line says what belongs there. It has three sections, and upload rejects any other shape:
## Thesis: one sentence of at most 160 characters on what the agent trades and how it makes money.## Strategy: up to three- **Title:** rulelines on what makes it act, when it exits and how it sizes. Titles are at most 32 characters; each rule is one sentence of at most 160.## Exposure: the same six- **Label:** answer — detaillines for every agent, in this order: Holds, Venue, Leverage, Costs, Data, On unwind. Answers are at most 24 characters and details at most 240. Data is Circuit, or names each outside host the agent calls.
circuit.toml
Account readiness
Circuit infers startup account requirements fromstartingAsset: HyperCore assets require an existing Hyperliquid account; Polygon pUSD, USDC.e and outcome tokens require an account Polymarket accepts orders from: a Deposit Wallet, or an EOA with Polymarket trading history. Controlled Deposit Wallets require deployment regardless of starting asset. Circuit configures every wallet’s accounts itself. No additional configuration declaration is needed.
Starts check readiness. The heuristic does not predict a different venue chosen later by the strategy; transaction preparation checks every actual action, configures what it can and otherwise returns ACCOUNT_SETUP_REQUIRED, or ACCOUNT_FUNDING_REQUIRED for an account its first deposit opens, before submission. Failed reads block execution, and setup never grants signing authority.
[[triggers]] Section
Set continuous = true for a continuous agent; it declares no schedule and may declare no triggers at all. Each schedule has type = "schedule", an everyMs duration in integer milliseconds divisible by 60000 (one minute), and align = "rolling" or "fixed". rolling starts after the last run; fixed aligns to clock boundaries and must divide one hour. A price trigger uses venue hyperliquid, an exact canonical perp asset, and condition cross, abs_move, or pct_move. Position triggers name their asset (a Hyperliquid perp or a Polymarket outcome token id); fill triggers name a perp venue or Polymarket and may omit it to match any fill. A resolution trigger with venue polymarket names no asset and fires once per resolved market the session holds, carrying one held outcome asset; redeeming it redeems the whole market. A news trigger names a natural-language prompt (for example "Donald Trump posts about Iran") and fires once for each matching news item. A webhook trigger names a trusted webhook provider as provider (polysights) and fires once for each event the provider pushes; the run checks the event’s own fields to decide whether it cares, and backtests never fire it. A walletTrade trigger names only a watched wallet, an EVM or Solana address (a continuous agent may omit it to watch the up to 100 wallets it sets with agent.watchedWallets.set, with no cooldownMs), and fires once for each trade the wallet makes, seconds after it lands: a transaction on any EVM network or Solana in which the wallet paid with some assets and got others, a Relay cross-chain buy it paid for, and each fill of its Hyperliquid (every perp DEX, Trade[XYZ] included), Lighter and Lighter Robinhood main-account and Derive perp and option trades, and each Papertrade position it opens or closes. Assets it only receives (deposits, airdrops, dust) or only sends never fire it, and a transaction counts only when the wallet signed it or paid the native coin or a listed token, so a scam token’s made-up transfer never does. The run receives the trade and names its copy’s once after the trade’s transaction or id. With many watched wallets, a venue fill can arrive up to a minute late while the venue is at Circuit’s read capacity. Builder turns a FOMO username or leaderboard into triggers on the traders’ wallets. The cross and abs_move conditions require a positive decimal thresholdUsd (USD mark price or USD price movement). pct_move requires positive decimal thresholdPercent: "0.5" means 0.5%, with no % or bps suffix. cooldownMs is the minimum interval between reactive firings, default zero, at most 2147483647 milliseconds (the stored integer range).
[startingAsset] Section
network is solana, ethereum:<chainId>, or hypercore. asset identifies the contract or native token: EVM 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee, Solana 11111111111111111111111111111111, or HyperCore index 0 for Core USDC. minimumAmount is the smallest allocation Start accepts and its default, a decimal string of whole tokens such as "10" for ten USDC. Derive it from the strategy: the least allocation at which its sizing places every order it holds at once at or above each venue minimum, plus the fees and gas it pays from the allocation. Top-ups have no minimum. Arc (ethereum:5042) starting USDC uses the native EVM sentinel; the ERC-20 interface is the same balance and is rejected as starting inventory. For an existing HyperCore perpetual, set asset to its exact coin (for example "BTC" or "xyz:GOLD") and expectedSide to "long" or "short"; the session’s holding keeps the position’s direction and venue entry price, and its collateral is assigned separately. For an existing Polymarket outcome, use network = "ethereum:137", asset set to the market’s share contract (Conditional Tokens 0x4d97dcd97ec945f40cf65f87097ace5ea0476045 for markets Polymarket lists as protocol v1, PositionManager 0x006f54f7f9a22e0000cc2ab60031000000ae9fef for v2 markets), and the decimal outcome tokenId. Start assigns only the selected unallocated quantity. Kraken trade agents use "0" because their funds are allocated on the Kraken account. An agent with a position, fill or resolution trigger on a venue starts on that venue’s network (hypercore for Hyperliquid, ethereum:137 for Polymarket), because Paper and new sessions fund only the starting asset; uploads reject any other start.
[settings] Section
Each key defines one setting (maximum 3). Types are text, boolean, single_select, integer, number, percentage, and address. Every setting carries a same-type default; users override it when they start a session. single_select alone requires up to 20 unique options, including its default. Percentages range from 0 through 100. integer, number and percentage alone may declare an inclusive min, max, or both, where min must not exceed max; the default and every session override must satisfy them. Addresses must match walletVmFamily. At runtime agent.settings merges every setting’s default with the session’s overrides, so each declared key always has a value: a string for text and address, a union of its options for single_select, a boolean for boolean, and a number for integer, number and percentage.
circuit check regenerates circuit-settings.d.ts from your [settings] tables, so agent.settings carries exactly the keys you declared. Reading a key circuit.toml does not define is a compiler error. circuit run --setting KEY=VALUE overrides a default for one local invocation.
[exchangeCredentials] Section
One venue may be declared, with access = "read" or access = "trade". Trading also declares a positive minimumAllocation in the exchange’s asset code, for example access = "trade" and minimumAllocation = { asset = "USD", amount = "25" } on Kraken, or { asset = "USDT", amount = "25" } on Binance. Circuit asks the user to pick the credential and allocation, scopes the runtime permit to them, and never exposes the secret or credential id to agent code. Private exchange methods use the attachment automatically.
circuit.toml has no version field, and Circuit rejects unknown fields. Upload content is hashed and versioned by Circuit. Keep runtime assets inside the agent directory; share code through a multi-agent workspace. Circuit applies one fixed source exclusion policy to checks, local runs, uploads and Builder saves. .circuit is reserved for CLI state.
Multi-agent workspace
The CLI detects standalone projects and Bun workspaces. Each shared package owns its dependencies; agents import packages by name. Upload sends the workspace source and lockfile. Circuit installs the agent’s production dependencies into one code artifact. Keep the rootpackage.json and bun.lock at the top, each agent in agents/<name>/ with its index.ts, circuit.toml, DESCRIPTION.md and package.json, and each shared package in shared/<name>/, and declare the workspace in the root package.json:
package.json with a name and main, depend on it from the agent with "@lib/polymarket": "workspace:*", and import it as import { getPositions } from "@lib/polymarket", without TypeScript path aliases. Run bun install at the root and commit bun.lock.
Editing an uploaded workspace agent copies its uploaded workspace config, lockfile, agent directory and shared packages into the builder. Bun links the packages as in the source monorepo. The builder copy is a snapshot, not a live link to the original repository.