Skip to main content
Now, let’s see how we can build an agent.
The same crates the CLI uses are available as Rust libraries. Import them from a path or git and build custom agents, batch tools, or test harnesses.

Example - Buy CC

We take a canonical example – buying CantonCoins. The agent lives at examples/buy_cc. It buys CC on CC-USDC. examples/buy_cc/Cargo.toml:
[package]
name = "buy-cc-example"
version = "0.1.0"
edition = "2024"

[dependencies]
cloud-agent = { path = "../../crates/cloud-agent" }
agent-logic = { path = "../../crates/agent-logic" }
orderbook-proto = { path = "../../crates/orderbook-proto" }
tokio = { version = "1", features = ["full"] }
anyhow = "1.0"
clap = { version = "4", features = ["derive"] }
dotenvy = "0.15"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
examples/buy_cc/src/main.rs (abridged):
use std::sync::Arc;
use anyhow::{Context, Result};
use clap::Parser;

use agent_logic::config::BaseConfig;
use agent_logic::confirm::new_confirm_lock;
use agent_logic::liquidity::LiquidityManager;
use cloud_agent::accept_settle::MulticallSettler;
use cloud_agent::backend::CloudSettlementBackend;
use cloud_agent::fill_loop::{self, FillDirection, FillParams};
use cloud_agent::populate_instruments;

#[derive(Parser)]
struct Args {
    #[arg(long)] amount: f64,
    #[arg(long)] max_price: Option<f64>,
    #[arg(long, default_value = "600")] poll_period: u64,
    #[arg(long, default_value = "5.0")] min_settlement: f64,
}

#[tokio::main]
async fn main() -> Result<()> {
    let _ = dotenvy::dotenv();
    let args = Args::parse();
    tracing_subscriber::fmt().with_env_filter("info").init();

    // 1. Load config from .env + agent.toml
    let mut config = BaseConfig::load_or_defaults("agent.toml")?;

    // 2. Fetch instrument registry (CC/USDC/…) from orderbook-rpc
    populate_instruments(&mut config).await?;

    // 3. Create backend (spawns ACS worker to keep amulet cache fresh)
    let confirm_lock = new_confirm_lock();
    let lm = LiquidityManager::new(
        config.fee_reserve_cc, config.liquidity_margin,
        config.flow_ema_window_hours,
        config.depletion_max_hours, config.depletion_min_hours,
    );
    let backend = CloudSettlementBackend::new(
        config.clone(), false, false, false, false, confirm_lock.clone(), lm,
    );

    // 4. Create settler for atomic multicall settlement
    let settler = Arc::new(MulticallSettler {
        config: config.clone(),
        amulet_cache: backend.amulet_cache().clone(),
        verbose: false, dry_run: false, force: false, confirm: false,
        confirm_lock,
    });

    // 5. Run the fill loop
    let params = FillParams {
        direction: FillDirection::Buy,
        market_id: "CC-USDC".to_string(),
        total_amount: args.amount,
        price_limit: args.max_price,
        min_settlement: args.min_settlement,
        max_settlement: args.amount,
        interval_secs: args.poll_period,
    };
    let _backend_guard = backend;
    fill_loop::run_fill_loop(config, settler, params, None, None).await
}
To launch the agent, run this command:
cargo run -p buy-cc-example -- --amount 10.0 --max-price 0.16 --poll-period 600
CC Buying agent is launched! Great job!