NERYA recipes

Examples & recipes · copy, paste, run

From a sentence
to a live fill.

Every recipe below is something you can run: the natural-language prompts the agent acts on, and the SDK scripts that ship under sdk/python/examples/. Scripts never touch keys or exchanges; they talk to the local daemon, which enforces every skill permission, Risk Gate, and Approval Gate.

0runnable recipes
0SDK demos
0Risk Gate / order
0keys in your scripts

01 · one sentence to a strategy

Ask the agent for a strategy

One sentence is enough: the strategy_author skill scaffolds a full package, you approve it, and it runs.

youI have $500 in a live account. Make me money on BTC. Don't blow it up.

neryaDrafts a demo_btc_5m_scalper package, wires binance:BTCUSDT candles, binds paper_main, sets a 0.4% max-drawdown guard, schedules the trigger every 5 minutes, and asks you to approve.

Under the hood the skill walks a fixed flow and writes nothing live until you sign:

strategy_author flow
DEFINE    markets, accounts, timeframe, trigger, risk limits, goal
SCAFFOLD  strategy_draft_proposal      → stages files under a proposal
AUTHOR    edit the staged package files at the returned proposal paths
VALIDATE  strategy_validate            → fix blockers until ok = true
SUBMIT    strategy_submit_proposal     → enters the pending-review queue
BACKTEST  strategy_backtest            → evidence over historical candles
Proposal-only

The package is staged under evolution/proposals/<id>/after/strategies/<id>/. The live strategies/<id>/ tree is proposal-only; the workspace guard refuses direct writes. Nothing papers, shadows, or goes live unless you ask for that gate.

02 · teach it a new venue

Add an exchange the agent doesn't know

If your venue isn't in the list, don't wait for a release. Hand the agent the API docs.

youAdd Bitget perpetual futures. Here are the API docs: https://bitgetlimited.github.io/apidoc/en/

The coding skill checks the CCXT bridge first (100+ venues already wired). If your venue is there, it registers an alias and you're done. If not, it drops a provider spec, hot-reloads, and verifies, with no daemon restart and no source-tree commit:

workspace provider (hot-reload)
# workspace/providers/bitget/provider.py
SPEC = {
    "id": "bitget",
    "kind": "cex",
    "markets": ["perp"],
    # endpoints, auth, symbol mapping, order shapes …
}

# then, from the runtime:
ConnectorRegistry.reload_providers()   # picks up the new SPEC live
connector_view("bitget")               # verify capabilities before trading
Promotion path

Once the venue stabilises, a maintainer can lift the workspace file into nerya/connectors/. Until then it lives entirely in your workspace.

03 · a report on a schedule

Schedule a recurring report

For background and recurring work, the tasks skill writes a durable schedule and can route the output to a gateway channel like Telegram.

youEvery morning at 09:00, post a BTC + ETH market summary to my Telegram.

neryaWrites a schedule with session_kind="agent" and a durable generated_prompt spelling out the source checks, output format, language, and delivery target, then confirms next run.

tasks
# the agent runs this for you; you can inspect it too
python scripts/create_task.py \
  --kind agent \
  --schedule "cron:0 9 * * *" \
  --deliver telegram \
  --prompt "Summarise BTC and ETH: price, 24h change, funding, 1 risk note."

python scripts/list_tasks.py        # see schedule, last run, next run

04 · alerts to your channel

Wire a Telegram alert

Channel setup is config-proposal work, so the notify skill lands it as one evolve_core_config_patch against messages/channels.yml. Your token is stored as a vault ref, never plaintext.

messages/channels.yml
channels:
  telegram:
    kind: telegram
    bot_token_ref: vault://telegram/bot_token   # never a plaintext token
    chat_id: 123456789
    topics: [trade_execution, critical_risk]     # which events to push

severity_routes:
  critical_risk: [telegram]
Secrets discipline

Plaintext tokens submitted anywhere are rewritten as vault:// refs on submit. The token never sits in the channel config or reaches an agent prompt.

05 · turn sessions into upgrades

Reflect & evolve between sessions

After a strategy session closes, turn its journal into memory, then into typed upgrade proposals you can sign or reject.

bash
python -m nerya.cli.app reflect        --workspace ~/.nerya   # write memory entries
python -m nerya.cli.app evolve         --workspace ~/.nerya   # produce typed proposals
python -m nerya.cli.app proposals list --workspace ~/.nerya   # review what's pending

Proposals are typed: learning_update, prompt_patch, script_proposal, skill_proposal, trigger_route_patch, strategy_config_patch, and advisory risk_limit_suggestion. You sign the diff; the runtime applies it with a rollback.py snapshot. Protected scopes are never touched.

06 · classify, then trigger

Price-breakout vertical slice

A light-tier LLM decides breakout vs. noise, then emits a trigger to a sub-agent. The main agent picks it up and submits a TradeIntent that flows through the Risk Gate to paper execution.

python · price_tracker.py
from nerya_sdk import connect

client = connect()
tick = {"market": "PAPER:BTCUSDT", "price": 82_140.0, "change_pct": 0.013}

# cheap, light-tier classification first
cls = client.llm.classify(
    prompt=str(tick), labels=["breakout", "noise"],
    caller="script:price_tracker",
)

if (cls.get("result") or {}).get("label") == "breakout":
    client.triggers.emit(
        source="script", kind="price.breakout",
        payload={"symbol": "BTC", **tick},
        target="subagent:market_analyst", strategy_id="btc_momentum",
        idempotency_key=f"btc-bo-{int(time.time())}",
    )
    # main agent → TradeIntent → Risk Gate → PaperExecution
run
python sdk/python/examples/price_tracker.py

07 · gated without an LLM

Direct order, still gated

No LLM involved. The intent still flows through the Risk Gate, the Approval Gate, and paper execution, then triggers an immediate strategy review.

python · direct_order_strategy.py
result = client.trading.submit_intent(
    strategy_id="btc_momentum", account_id="paper_main",
    market="PAPER:BTCUSDT", side="buy",
    size=250, size_unit="usd", order_type="market",
    confidence=0.6, reasoning="direct SDK buy, smoke test", source="sdk",
)

if result.get("status") in ("filled", "partial", "accepted"):
    client.strategy.review(
        "btc_momentum", result["session_id"], stage="immediate",
    )

08 · cheap filter, costly survivors

Tiered news-alpha watcher

Spend cheap tokens to filter, expensive tokens only on the survivors. The light tier classifies; only alpha items pay for the high tier; anything actionable emits a trigger; scripts never trade directly.

python · news_alpha_watcher.py
for headline in headlines:
    # 1. light tier filters noise (cheap)
    cls = client.llm.classify(
        prompt=headline, labels=["alpha", "noise", "risk"], caller=CALLER,
    )
    if (cls.get("result") or {}).get("label") != "alpha":
        continue

    # 2. only alpha pays for the high tier
    analysis = client.llm.analyze_signal(context=headline, caller=CALLER)
    parsed = analysis.get("parsed")

    # 3. emit a trigger, never place trades from a script
    if isinstance(parsed, dict) and parsed.get("recommended_action"):
        client.triggers.emit(
            source="script", kind="news.alpha",
            payload={"headline": headline, "analysis": parsed},
            target="main", strategy_id="btc_momentum",
            idempotency_key=f"news-alpha-{abs(hash(headline))}",
        )
Budget enforced

Every LLM call is checked against the script's llm_policy. If the manifest sets allowed_tiers: [light], the high-tier step is rejected by the gateway before a dollar is spent.

09 · wake on a funding spike

Funding-rate spike trigger

Watch a perp funding feed and wake the agent when funding crosses a threshold. The trigger carries no order; it leaves the call to the risk_critic and execution_planner sub-agents.

python · funding_spike_trigger.py
for row in pull_funding():     # [{market, funding_rate_bps, ts}, …]
    if abs(row["funding_rate_bps"]) < 30:
        continue
    client.triggers.emit(
        source="script", kind="funding.spike",
        payload=row, target="main", strategy_id="btc_momentum",
        idempotency_key=f"fund-{row['market']}-{int(row['ts'])}",
    )

10 · follow the whale wallets

Whale-wallet watcher

Mock a chain watcher and route large transfers to the onchain_watcher sub-agent, which computes cluster heuristics and escalates only when the activity is relevant to an active strategy.

python · whale_wallet_trigger.py
for tx in transfers:          # chain watcher output
    if tx["amount_usd"] < 1_000_000:
        continue
    client.triggers.emit(
        source="script", kind="whale.transfer",
        payload=tx, target="subagent:onchain_watcher",
        strategy_id="btc_momentum",
        idempotency_key=f"whale-{tx['from']}-{int(time.time())}",
    )

11 · the same surface in TypeScript

TypeScript quickstart

Same surface, Node / Bun / Edge friendly. Probe a route with dryRun, emit for real, or submit an intent; every call is forwarded to the local daemon, which enforces the Risk Gate server-side.

bash
npm install @nerya/sdk
typescript
import { connect } from "@nerya/sdk";

const nerya = connect({
  baseUrl: "http://127.0.0.1:18317",
  caller: "script:my_bot",
});

// probe a route without firing it
const dry = await nerya.triggers.dryRun({
  source: "script", kind: "price.breakout",
  payload: { symbol: "BTC", price: 82_000 },
  target: "subagent:market_analyst", strategy_id: "btc_momentum",
});

// emit for real
await nerya.triggers.emit({
  source: "script", kind: "price.breakout",
  payload: { symbol: "BTC", price: 82_000 },
  target: "subagent:market_analyst", strategy_id: "btc_momentum",
  idempotency_key: "btc-" + Date.now(),
});

// direct intent, still passes the Risk Gate server-side
await nerya.trading.submitIntent({
  strategy_id: "btc_momentum", account_id: "paper_main",
  market: "PAPER:BTCUSDT", side: "buy", size: 0.01,
  size_unit: "base", order_type: "market",
  confidence: 0.6, reasoning: "ts-sdk demo",
});

That's the whole loop.

Trigger in, skills decide, the Risk Gate guards, memory and evolution carry the lesson forward. Read the manual for the architecture behind it.