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.
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:
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
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/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
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.
# 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.
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]
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.
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.
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
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.
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.
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))}",
)
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.
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.
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.
npm install @nerya/sdk
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.