Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Bardo Tools – Configuration [SPEC]

Version: 4.0.0 Last Updated: 2026-03-14

Crate: bardo-tools | Prerequisites: 01-architecture.md (ToolDef pattern, trust tiers, capability tokens, safety hooks, and profiles)

Environment variables, config file schema, startup validation, health checks, capability token configuration, and API key tiers.


Reader orientation: This document specifies the configuration system for bardo-tools: environment variables, TOML config file schema, startup validation, health checks, and API key tiers (Read/Feedback/Write). Configuration controls safety policies, wallet settings, chain RPC endpoints, and tool profiles. You should be comfortable with TOML configuration and environment variable precedence patterns. Bardo-specific terms are defined inline on first use; for a full glossary see prd2/shared/glossary.md.

Configuration hierarchy

CLI flags  >  Environment variables  >  Config file  >  Defaults

Environment variables always override config file values. Never put secrets in the config file – use env vars for all credentials.


Environment variables

All environment variables use the BARDO_ prefix.

Core

VariableRequiredDefaultDescription
BARDO_PROFILENodataTool profile: data, trader, lp, vault, intelligence, learning, identity, golem, full, dev
BARDO_LOG_LEVELNoinfoLog level: debug, info, warn, error
BARDO_LOG_FORMATNojsonLog format: json, text

Pi runtime

VariableRequiredDefaultDescription
BARDO_PI_SESSION_TTLNo3600Pi session TTL in seconds (default: 1 hour)
BARDO_PI_MAX_ACTIONSNo1000Max action invocations per session before forced renewal
BARDO_A2A_ENABLEDNofalseEnable A2A endpoint for external agent access
BARDO_A2A_PORTNo3000A2A endpoint port (when A2A is enabled)
BARDO_A2A_HOSTNolocalhostA2A endpoint host

Wallet

VariableRequiredDefaultDescription
BARDO_WALLET_PRIVATE_KEYNoLocal private key (dev only)
BARDO_PRIVY_APP_IDNoPrivy application ID
BARDO_PRIVY_APP_SECRETNoPrivy application secret
BARDO_SAFE_ADDRESSNoSafe smart account address
BARDO_SAFE_SIGNER_KEYNoSafe signer private key
BARDO_ZERODEV_PROJECT_IDNoZeroDev project ID
BARDO_LIT_AUTH_TOKENNoLit Protocol (Vincent) auth token

Capability token limits

Capability tokens gate every write operation. These env vars set the default limits baked into each token. The safety extension reads them once at boot and uses them when minting Capability<T> tokens for write tool handlers.

VariableRequiredDefaultDescription
BARDO_CAP_MAX_VALUE_PER_TXNo10000Max USD authorized per capability token
BARDO_CAP_MAX_VALUE_PER_TICKNo50000Max USD across all capabilities in a single tick
BARDO_CAP_MAX_VALUE_PER_DAYNo100000Daily cumulative capability value cap (USD)
BARDO_CAP_EXPIRY_TICKSNo3Capability token expiry in heartbeat ticks
BARDO_MAX_SLIPPAGE_BPSNo100Maximum slippage tolerance (basis points)
BARDO_MAX_PRICE_IMPACT_BPSNo300Maximum price impact (basis points)
BARDO_TOKEN_ALLOWLIST_MODENostrictToken allowlist mode: strict, warn, off
BARDO_RATE_LIMIT_MAX_OPSNo20Max operations per time window
BARDO_RATE_LIMIT_WINDOWNo3600Rate limit window in seconds

RPC overrides

VariableRequiredDefaultDescription
BARDO_RPC_ETHEREUMNopublicCustom Ethereum RPC URL
BARDO_RPC_BASENopublicCustom Base RPC URL
BARDO_RPC_ARBITRUMNopublicCustom Arbitrum RPC URL
BARDO_RPC_OPTIMISMNopublicCustom Optimism RPC URL
BARDO_RPC_POLYGONNopublicCustom Polygon RPC URL

External APIs and data

VariableRequiredDefaultDescription
BARDO_SUBGRAPH_API_KEYNoThe Graph API key (for higher rate limits)
BARDO_COINGECKO_API_KEYNoCoinGecko API key (fallback; x402 preferred)

Uniswap Trading API

VariableRequiredDefaultDescription
BARDO_UNISWAP_API_KEYNoAPI key from developers.uniswap.org. Required to activate API-backed tools.
BARDO_UNISWAP_API_BASE_URLNohttps://trade-api.gateway.uniswap.org/v1Base URL override
BARDO_UNISWAP_API_RATE_LIMITNo3Requests per second (token bucket refill rate)
BARDO_UNISWAP_API_QUOTE_MAX_AGE_MSNo30000Quote cache TTL in milliseconds
BARDO_UNISWAP_API_GAS_BUFFER_PCTNo20Gas estimate buffer percentage
BARDO_UNISWAP_ROUTER_VERSIONNo2.0Universal Router version (1.2 or 2.0)
BARDO_UNISWAP_PERMIT2_ENABLEDNotrueEnable Permit2 approval optimization
BARDO_UNISWAP_ENABLE_LPNotrueUse API for LP operations (SDK fallback if false)
BARDO_UNISWAP_ENABLE_LIMIT_ORDERSNotrueEnable limit order tools
BARDO_UNISWAP_ENABLE_SMART_WALLETNofalseEnable EIP-5792/7702 tools
BARDO_UNISWAP_CHAIN_IDSNoall supportedComma-separated chain IDs to restrict API usage

Uniswap API config is in the [uniswap_api] section of golem.toml (see full example above).

ERC-8004 identity

VariableRequiredDefaultDescription
BARDO_IPFS_MODENobardoIPFS mode: bardo, pinata, inline
BARDO_PINATA_JWTNoPinata JWT (required when IPFS_MODE=pinata)
BARDO_AGENT_NAMENoHuman-readable agent name
BARDO_AGENT_DESCRIPTIONNoAgent description

Memory (Grimoire)

VariableRequiredDefaultDescription
BARDO_MEMORY_ENABLEDNotrueEnable memory system (when learning profile active)
BARDO_MEMORY_DATA_DIRNo~/.bardo/memoryRoot directory for memory files
BARDO_MEMORY_LANCE_DIRNo$DATA_DIR/lanceLanceDB episodic store directory
BARDO_MEMORY_SQLITE_PATHNo$DATA_DIR/semantic.dbSQLite semantic store path
BARDO_MEMORY_MODELNoXenova/all-MiniLM-L6-v2Embedding model ID
BARDO_MEMORY_DECAY_BASE_STABILITYNo7Ebbinghaus base stability in days
BARDO_MEMORY_CONSOLIDATION_INTERVALNo14400ExpeL consolidation interval (seconds)
BARDO_MEMORY_MAX_EPISODESNo100000Max episodic memory entries
BARDO_MEMORY_MAX_INSIGHTSNo10000Max semantic insights

x402 outbound

VariableRequiredDefaultDescription
BARDO_X402_OUTBOUND_ENABLEDNofalseEnable x402 outbound payments
BARDO_X402_OUTBOUND_KEYNoPrivate key for USDC payments on Base
BARDO_X402_MAX_SPEND_PER_HOURNo1.00Max x402 spend per hour (USD)
BARDO_X402_MAX_SPEND_PER_DAYNo10.00Max x402 spend per day (USD)

Startup validation

On startup, the tool library validates all configuration via serde deserialization with custom validation logic. Invalid or missing required values produce clear error messages with suggested fixes:

Profile "trader" requires a wallet, but none is configured.

Configure one of:
  - BARDO_WALLET_PRIVATE_KEY  (dev only)
  - BARDO_PRIVY_APP_ID + BARDO_PRIVY_APP_SECRET  (production)

Or switch to the data profile: BARDO_PROFILE=data

Cross-field validation: BARDO_IPFS_MODE=pinata requires BARDO_PINATA_JWT.

Structured startup log

Bardo Tools v4.0.0 starting...

   Profile:     trader
   Chains:      ethereum (1), base (8453), arbitrum (42161)
   Wallet:      Privy server wallet (0xAbCd...1234)
   Safety:      max $1,000/tx - $10,000/day - strict token allowlist
   Tools:       27 adapters loaded
   A2A:         disabled

   No custom RPCs configured -- using public endpoints.
   Set BARDO_RPC_ETHEREUM for better reliability.

Ready. Extension registered with Pi session.

When BARDO_LOG_FORMAT=json, a structured JSON line is emitted instead.


--health flag

bardo-tools --health

Checks connectivity to all configured services (RPCs, subgraph, wallet provider). Exit codes:

CodeMeaning
0All services healthy
1Degraded (some services failed, server will still start)
2Critical failure (server cannot start)

Config file schema (golem.toml)

Optional complement to environment variables. Useful for team-shared baseline configs (non-secret settings only). The config file is TOML format (golem.toml).

File locations searched (in order):

  1. Path specified via --config CLI flag
  2. golem.toml in the current directory
  3. ~/.bardo/golem.toml

Full example

# golem.toml -- complete configuration reference

[tools]
profile = "trader"
enable = ["intel_compute_vpin"]
disable = ["uniswap_submit_uniswapx_order"]

[chains]
enabled = [1, 8453, 42161]

[chains.rpc_overrides]
1 = "https://my-rpc.example.com"

[custody]
# One of: "delegation", "embedded", "local_key"
mode = "delegation"

[custody.delegation]
smart_account = "0x..."
caveat_enforcers = ["GolemPhase", "MortalityTimeWindow", "DailySpendLimit"]

[custody.embedded]
privy_app_id = "..."
server_wallet_id = "..."

[custody.local_key]
private_key_path = ".bardo/session-key.json"
max_daily_spend_usd = 100.0
expires_days = 30

[safety]
token_allowlist_mode = "strict"
token_allowlist_source = "uniswap-default"

[safety.capability_limits]
max_value_per_tx_usd = 10000
max_value_per_day_usd = 100000
expiry_ticks = 3

[safety.slippage]
max_slippage_bps = 100
max_price_impact_bps = 300

[safety.rate_limit]
max_operations_per_window = 20
window_seconds = 3600

[safety.simulation]
enabled = true
divergence_tolerance_bps = 200

[trading]
default_deadline_seconds = 300
default_slippage_bps = 50
prefer_trading_api = true
enable_uniswapx = true
enable_cross_chain = true
confirmations = 1

[uniswap_api]
api_key = "your-key"
enable_lp = true
enable_limit_orders = true
enable_smart_wallet = false
universal_router_version = "2.0"
permit2_enabled = true
chain_ids = [1, 8453, 42161, 10, 137]

[a2a]
enabled = false
port = 3000

[logging]
level = "info"
format = "json"

Rust config struct

The config file deserializes into a ToolConfig struct:

#![allow(unused)]
fn main() {
use serde::Deserialize;

#[derive(Debug, Deserialize)]
pub struct ToolConfig {
    #[serde(default)]
    pub tools: ToolsConfig,
    #[serde(default)]
    pub chains: ChainsConfig,
    #[serde(default)]
    pub custody: CustodyConfig,
    #[serde(default)]
    pub safety: SafetyConfig,
    #[serde(default)]
    pub trading: TradingConfig,
    #[serde(default)]
    pub a2a: A2aConfig,
    #[serde(default)]
    pub logging: LoggingConfig,
}

#[derive(Debug, Deserialize)]
#[serde(tag = "mode")]
pub enum CustodyConfig {
    #[serde(rename = "delegation")]
    Delegation {
        smart_account: String,
        caveat_enforcers: Vec<String>,
    },
    #[serde(rename = "embedded")]
    Embedded {
        privy_app_id: String,
        server_wallet_id: String,
    },
    #[serde(rename = "local_key")]
    LocalKey {
        private_key_path: String,
        max_daily_spend_usd: f64,
        expires_days: u32,
    },
}

#[derive(Debug, Deserialize)]
pub struct SafetyConfig {
    pub token_allowlist_mode: AllowlistMode,
    pub capability_limits: CapabilityLimits,
    pub slippage: SlippageConfig,
    pub rate_limit: RateLimitConfig,
    pub simulation: SimulationConfig,
}

#[derive(Debug, Deserialize)]
pub struct CapabilityLimits {
    /// Max USD value a single Capability<T> token authorizes.
    pub max_value_per_tx_usd: f64,
    /// Max cumulative USD value per day across all capability tokens.
    pub max_value_per_day_usd: f64,
    /// Capability tokens expire after this many heartbeat ticks.
    pub expiry_ticks: u64,
}
}

Configuration loading merges env vars over file values over defaults. The merge follows serde’s #[serde(default)] pattern – env var overrides are applied after deserialization via a merge_env_overrides() pass.


Three-tier API key model

Tiered access control for A2A endpoint connections. Governs what any external agent can do based on key scope.

Key tiers

TierPrefixScope
Readbardo_read_All get_*, search_*, list_*, retrieve_*, query_*, compute_*, check_* tools. No state modifications.
Feedbackbardo_feedback_Read + manage_insight, update_memory_confidence. Steering without transaction authority.
Writebardo_write_Full access including execute_swap, vault_deposit, proxy_announce, all execution tools.

Key generation

Keys are generated at first boot (if none exist) or via the CLI:

bardo-tools setup

Keys are cryptographically random, 256-bit, base64url-encoded. Total key length including prefix: ~55 characters.

Enforcement middleware

#![allow(unused)]
fn main() {
fn authorize_tool_call(api_key: &str, tool_name: &str) -> bool {
    let tier = get_key_tier(api_key);
    match tier {
        KeyTier::Write => true,
        KeyTier::Feedback => is_read_tool(tool_name) || is_feedback_tool(tool_name),
        KeyTier::Read => is_read_tool(tool_name),
    }
}
}

Rejection response

When a tool call is rejected due to insufficient key tier:

{
  "isError": true,
  "content": [
    {
      "type": "text",
      "text": "{\"error\":\"INSUFFICIENT_KEY_TIER\",\"message\":\"Tool 'execute_swap' requires Write key. Current key tier: Read.\",\"requiredTier\":\"write\",\"currentTier\":\"read\"}"
    }
  ]
}

Key rotation

bardo-tools setup --rotate-keys              # Rotate all keys
bardo-tools setup --rotate-keys --grace-period 15  # 15-min grace period
bardo-tools setup --rotate-key read           # Rotate one tier only

Transport security

  • HTTPS required for remote connections (non-localhost)
  • HTTP allowed for localhost only
  • Keys transmitted as Authorization: Bearer headers
  • Keys never logged, never in URLs, never in error responses

Data sources

Primary data source matrix

Data NeedPrimary SourceFallbackLatency
Token pricePool slot0 via RPCTrading API quote< 500ms
Pool TVL/volumeThe Graph subgraphRPC multi-call< 2s
Swap quotesTrading APIsmart-order-router< 2s
LP position stateDirect RPCSubgraph< 500ms
Token metadataOn-chain ERC-20 + token listCoinGecko< 500ms
Historical OHLCVSubgraph Swap eventsRPC event logs< 3s
TokenJar balancesMulti-call batch readsSubgraph< 1s
ERC-8004 identityThe Graph subgraphsDirect contract reads< 2s
External token dataCoinGecko x402On-chain reads< 1s
Multi-chain portfolioElsa x402Multi-chain RPC reads< 2s

Caching strategy

Cache TierTTLExamples
Short-lived15sToken prices, gas prices, pool state
Medium5 minPool metadata, token list
Long24hToken metadata, contract addresses
Pre-computed1hOHLCV candlesticks for popular pairs
ImmutableForeverCompleted candles, IPFS content (CID-addressed)
Never cachedSimulation results, nonce state, streaming data

The caching layer uses moka (a Rust concurrent cache) with per-tier TTL configuration. Circuit breaker logic wraps each external dependency with a 50% error threshold and 30s reset timeout. Fallback returns cached data with staleness indicators.


Error taxonomy

CategoryPrefixDescriptionExamples
safetySAFETY_Blocked by safety middlewareSAFETY_TOKEN_NOT_ALLOWED, SAFETY_SPENDING_LIMIT_EXCEEDED
validationVALIDATION_Invalid input parametersVALIDATION_INVALID_ADDRESS, VALIDATION_CHAIN_NOT_SUPPORTED
executionEXECUTION_Transaction execution failedEXECUTION_TX_REVERTED, EXECUTION_TX_TIMEOUT
dataDATA_Data source errorsDATA_SUBGRAPH_ERROR, DATA_RPC_ERROR
walletWALLET_Wallet/signing errorsWALLET_NOT_CONFIGURED, WALLET_SIGNING_FAILED
routingROUTING_Route finding errorsROUTING_NO_ROUTE, ROUTING_INSUFFICIENT_LIQUIDITY
configCONFIG_Configuration errorsCONFIG_MISSING_ENV, CONFIG_INVALID_VALUE
capabilityCAP_Capability token errorsCAP_EXPIRED, CAP_VALUE_EXCEEDED, CAP_NOT_MINTED

Performance requirements

OperationTargetMaximum
Read (prices, pool info)< 500ms< 2s
Quote< 1s< 3s
Write (swap + simulation)< 5s< 15s
Token search< 1s< 3s
Cold start< 3s
Warm start< 1s

Throughput: 1 write/s sustained, 5 reads/s sustained. Single-agent use (one wallet, sequential operations). Cold start targets are lower than the TypeScript predecessor because binary startup eliminates JIT warmup.


Dependencies

Core

CratePurpose
alloyEVM interaction, providers, signers
alloy-sol-typesABI encoding/decoding via sol! macro
serde / serde_jsonSerialization, parameter parsing
tokioAsync runtime
reqwestHTTP client (Trading API, Privy, subgraph)
mokaConcurrent caching
tracingStructured logging
thiserrorError type definitions
tomlConfig file parsing

TypeScript sidecar

Uniswap’s official SDKs (@uniswap/sdk-core, @uniswap/v3-sdk, @uniswap/v4-sdk, @uniswap/universal-router-sdk, @uniswap/permit2-sdk, @uniswap/uniswapx-sdk) are TypeScript-only. A thin Node.js sidecar process exposes SDK math and calldata encoding over local IPC. The sidecar is started lazily when a tool first needs SDK computation. Tools that only do RPC reads or subgraph queries never start the sidecar.

Runtime

  • Target: x86_64-unknown-linux-gnu, aarch64-apple-darwin
  • Rust edition: 2024
  • MSRV: 1.80
  • No external services required for basic operation (all data from RPC + subgraph)
  • Optional: Uniswap Trading API key, The Graph API key, TypeScript sidecar (for SDK-dependent tools)