You have built Juniper, the fictional plant-shop assistant, and checked its configuration. Now you will add your local credentials, train it and try a conversation.
A successful configuration check and a successful training run answer different questions. This chapter shows how to review both before deciding whether the assistant handles a customer’s request correctly.
Credentials, then life
make env
That copies .env.example to .env. Open .env in any editor and fill in:
| Variable | Where it comes from |
|---|---|
RASA_LICENSE | Free Developer Edition key — a long one-line JWT |
OPENAI_API_KEY | Your OpenAI account |
Remember Chapter 3, break #7: this file is gitignored, the hook scans for keys everywhere else, and that combination is what makes this step safe.
make install # uv downloads rasa-pro (a few minutes, first time only)
make train # validate + teach the engine your agent
make chat # 🎉
you do you have anything that survives a dark bathroom?
bot Yes — a ZZ plant or a snake plant would be happy there.
Want me to check what's in stock?
If anything failed instead, don’t debug from scratch — the mantle-upgrade-and-debug skill opens with a failure→cause table: eleven real error messages mapped to their actual causes and fixes. Mantle symptoms often point far from their causes; the table is the shortcut across that gap. It’s also just Markdown — keep it open in a tab.
An honest word about your green checkmarks
You now have two layers of verification, and knowing the difference is what separates “it’s green” from “it works”:
| Layer | Command | Proves | Doesn’t prove |
|---|---|---|---|
| Lint | python3 scripts/lint_mantle.py | Internally consistent; no known traps | That the engine accepts it |
| Engine | make train | The installed engine accepts and builds it | That conversations go well |
The checker runs locally without installing Rasa or calling a model, so it can run in a commit hook. The engine check needs a real install and a licence — that’s why it can’t. A green lint is necessary, not sufficient, and the pack’s own docs say so in exactly those words. When you tell a teammate “Juniper is green”, say which green you mean.
Conversation quality needs separate checks. Try the assistant in the Inspector, then use the evaluation harness to inspect recorded actions and model-judged answers. Passing the configuration checker alone cannot establish that the conversation handles the task correctly.
The everyday loop
From here on, building Juniper looks like this:
1. Ask Claude Code for a change
"Use the mantle-skill-authoring skill to add a care_tips skill"
2. It builds against the playbook, runs the lint, shows you the result
3. You read the diff ← do not skip this step
4. git commit → the hook runs the lint one more time
5. Occasionally: make train && make chat to feel the change
Step 3 deserves its sentence in bold: read the diff. The skills make correct-shaped files, the lint catches known traps — but “known traps” is a finite list and your judgment is not. The tooling removes the silent failure modes so your attention is free for the interesting question: is this agent actually behaving well?
The reviewer role — a second pair of eyes, on demand
The pack ships a second role for exactly that judgment work. When a change matters — before merging anything, in a team setting — say:
Review this change as mantle-reviewer.
The reviewer role is deliberately paranoid, and its habits are worth stealing for your own reviews:
- It re-runs the lint itself rather than trusting a reported green.
- It re-checks the five silent traps by hand, even though the lint covers them — belt and braces, because these produce zero runtime errors.
- It gives version bumps extra teeth (does the target wheel actually ship
the engine? did a careless find-and-replace produce a nonsense
X → Xupgrade line in the docs? — yes, that has really shipped). - And it names what it did not check. An honest partial review beats a confident-sounding complete one. If it had no licence to train with, it says so instead of implying it verified everything.
That last habit is the deepest lesson in the pack, and it applies to humans too.
Keeping Juniper healthy over time
- Upgrades: the engine line moves fast. When you bump the pin, follow
the upgrade section of the
mantle-upgrade-and-debug skill —
it includes the check most people skip (does the target version actually
contain the engine?) and the one nobody expects (new top-level
agent.ymlkeys appear in dev releases;tool_timeoutarrived that way, unannounced). - Review release-specific checks: the current compatibility report already records Mantle in a stable release. Revisit
engine-version-pinwhen upgrading so its allowed versions match the runtime you actually tested. - New traps: if you hit a silent failure the lint didn’t catch, you’ve
found something valuable. The check functions in
lint_mantle.pyprovide examples of how to encode a failure; read the nearest check and consider contributing it back to the community resources repo. That’s how every existing check got there.
Where to go next
- Tool Scope and Memory Scope — the natural sequel: Juniper’s memory is simple; this builds a bank agent where memory architecture is the product.
- The catalog itself:
RasaHQ/rasa-community-resources— contains voice agents, CRM integrations and patterns to study. Check each project’s README and the compatibility report for its tested scope.
You built an agent, broke it seven ways, caught every break, brought it to life, and know exactly what your tools do and don’t prove. That’s not a beginner’s setup anymore. That’s a workshop. 🛠️