Adding a Scenario
Step-by-step guide to adding a new L0.5 scenario with conventions and methodology extraction
Scenarios map user intent to procedural playbooks. Adding a scenario means giving the agent a new "flow" for a class of questions. This page walks through writing one from scratch, the conventions that must be followed, and how scenarios connect to the methodology learning pipeline.
For the mechanism overview, see Scenario Classifier. For the full catalog of existing scenarios, see the scenario tables on that page.
Step 1: create the definition file
Create apps/agent/src/skills/scenarios/defs/scenario-<id-lowercase>.ts.
Use SCENARIO_ prefix for primary intents, SCENE_ for
composable sub-scenarios.
import type { Scenario } from "../types.js";
export const SCENARIO_NFT_VALUATION: Scenario = {
id: "SCENARIO_NFT_VALUATION",
description:
"Evaluate NFT collections or individual NFTs: floor price, volume, holder distribution, rarity analysis.",
keywords: [
// EN
"nft", "nft valuation", "floor price", "collection",
"rarity", "nft analysis", "opensea",
// ZH
"NFT估值", "地板价", "稀有度",
],
suggestedSkillIds: [
"minara.core",
"research.web",
"analysis.spot_market",
],
fewShotExamples: [
{
message: "What's the floor price of Pudgy Penguins?",
scenarios: ["SCENARIO_NFT_VALUATION"],
},
{
message: "Analyze the BAYC collection — is it worth buying now?",
scenarios: ["SCENARIO_NFT_VALUATION"],
},
],
metaPlan: `1. [Collection Lookup] Identify the collection and chain.
2. [Floor & Volume] Fetch current floor price, 24h volume, listed ratio.
3. [Holder Distribution] Check whale concentration and unique holder count.
4. [Rarity Check] If a specific NFT id is mentioned, fetch its rarity rank.
5. [Comparable Analysis] Compare against 2-3 similar collections on the same chain.`,
analyze: `1. Floor trend: rising/falling/flat over 7d and 30d.
2. Volume sustainability: is volume driven by wash trading or real activity?
3. Holder health: top-10 holder percentage, new holder growth rate.
4. Risk factors: low liquidity, concentrated ownership, unlockable metadata.
5. Actionable view: buy/hold/avoid with reasoning and entry range if applicable.`,
};Field conventions
| Field | Rule |
|---|---|
id | Uppercase ASCII, snake_case. SCENARIO_ for primary, SCENE_ for composable. |
description | ≤100 chars. "Pushy" about when this scenario should trigger. |
keywords | Bilingual (EN + ZH). Lowercased substring match for ASCII keywords; non-ASCII keywords fall back to plain includes so CJK strings still match. The list is consumed only when SCENARIO_CLASSIFIER=keyword-only; in llm mode the LLM classifier sees description + fewShotExamples instead. Keep specific to avoid false positives. |
suggestedSkillIds | Must reference real skill ids. Grep apps/agent/src/skills/builtin/ for the literal id: field. ScenarioRegistry.validate() hard-fails at boot on any typo. |
fewShotExamples | Optional. At least one message that should hit and one that should not. |
metaPlan | Data-gathering steps. Numbered list. |
analyze | Synthesis rules. How to combine the gathered data into an answer. |
assetClasses | Optional. Soft routing hint. |
lifecycleStages | Optional. Soft routing hint. |
Length guidance: there is no per-scenario char cap — the
overall KNOWLEDGE_BUDGET_TOKENS negotiator (default 15000) bounds
the combined system-prompt surface. Still, keep playbooks focused:
every numbered step runs through the LLM on matching turns.
Step 2: register in the catalog
Open
apps/agent/src/skills/scenarios/catalog.ts
and add one import plus one array push:
// At the import section:
import { SCENARIO_NFT_VALUATION } from "./defs/scenario-nft-valuation.js";
// In the SCENARIOS array:
export const SCENARIOS: Scenario[] = [
// ... existing scenarios
SCENARIO_NFT_VALUATION,
// ...
];Do not inline playbook text into catalog.ts. The catalog
is just the aggregation point; all content stays in the
defs/*.ts file.
Step 3: add classifier test examples
Open tests/unit/skills/scenario-classifier.test.ts and add
at least:
- One message that should activate the new scenario.
- One message that should NOT activate it (to verify keyword specificity).
it("classifies NFT floor price query", () => {
const result = classifyKeywords("What's the BAYC floor price?");
expect(result).toContain("SCENARIO_NFT_VALUATION");
});
it("does not trigger NFT scenario on generic price query", () => {
const result = classifyKeywords("What's the price of ETH?");
expect(result).not.toContain("SCENARIO_NFT_VALUATION");
});Run the tests:
npm run test:unit -- tests/unit/skills/scenario-classifier.test.tsStep 4: verify at boot
Start the REPL and confirm the scenario registers:
npm run devIf suggestedSkillIds contains a typo,
ScenarioRegistry.validate() will throw a hard error at boot
with a clear message naming the bad id. Fix the id by grepping:
grep -rnE '^\s*id:\s*"' src/skills/builtin/ | grep -i "the-id-you-want"Step 5: test the classifier live
In the REPL:
› What's the floor price of Pudgy Penguins?Check structured logs to see which scenario fired:
/logs 20 --level debugLook for scenarios_classified with
SCENARIO_NFT_VALUATION in the result.
What NOT to edit
Adding a scenario should touch exactly two files plus a test:
apps/agent/src/skills/scenarios/defs/<id>.ts(new)apps/agent/src/skills/scenarios/catalog.ts(import + push)tests/unit/skills/scenario-classifier.test.ts(test cases)
Do not edit classifier.ts, session.ts, registry.ts,
prompt-builder.ts, agent-loop.ts, or app.ts. If you feel
the need to touch framework code, the scenario's requirements
are out of band and belong in a separate framework PR.
How scenarios feed methodology extraction
Scenarios and methodologies are separate systems that interact indirectly:
scenario playbook (metaPlan + analyze)
│
▼
agent follows the playbook, makes tool calls,
produces analysis + recommendation
│
▼
user acts on recommendation (trade / skip)
│
▼
EvaluationLoop runs post-trade
│
▼
LLM judge extracts a StructuredMethodology:
{ direction, primary_signal, timeframe, indicators }
│
▼
MethodologyStore.create() — quarantined, confidence 0.1
│
▼
BootstrapEngine retrospectively validates against
last 10 trades in the same asset class
│
▼
methodology graduates when Wilson LB ≥ 0.55
with ≥ 5 correct out of ≥ 10 usesThe key insight: scenarios provide the flow, methodologies
capture the signal. A well-written analyze section in a
scenario playbook makes it more likely that the evaluation loop
extracts a useful methodology, because the analysis is
structured and testable. A vague analyze section produces
vague methodologies that don't pass graduation.
Writing scenarios that produce good methodologies
- Be specific about indicators. "Use RSI and MACD" is
better than "use technical analysis." The structured
methodology extractor can map "RSI" to
primary_signal: technicalandindicators: ["rsi"]cleanly. - State direction criteria explicitly. "If RSI < 30 and
MACD crosses up, signal is bullish" gives the judge enough
structure to extract
direction: bullishwith a clearprimary_signal. - Include a timeframe. "This is a 1-week swing trade
setup" lets the extractor set
timeframe: shortwithout guessing. - Keep the analyze section testable. "The recommendation is valid if the price moves >3% in the predicted direction within the stated timeframe" gives the evaluation loop a concrete pass/fail criterion.
Phase 2: self-learning scenarios
When SCENARIO_LEARNING=1 is set in .env, the agent can
autonomously propose new scenarios from classifier misses.
These learned scenarios use the SCENARIO_LEARNED_* id prefix
and live in the learned_scenarios SQLite table, never in
source files.
The operator flow:
minara scenarios pending # show graduation queue
minara scenarios show <id> # inspect a proposed scenario
minara scenarios approve <id> # graduate → active in classifier
minara scenarios reject <id> # reject with reasonLearned scenarios go through the same Wilson confidence gate as methodologies: they need enough successful classification hits (the user's query matched and the agent produced a good result) before graduation is offered.
You should not use self-learning for scenarios that need hand-tuned playbooks. The autonomously proposed playbooks are generic. For production-quality flows, write them by hand following this guide.