Time to plug in the power.
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 lint runs in milliseconds with nothing installed — that’s why it can live in a 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.
(The third layer — do conversations actually go well — has no checker. That one’s on you: talk to your agent, in the Inspector, often.)
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). - When stable Rasa finally ships the engine, one lint check
(
engine-version-pin) becomes obsolete — and its own docstring says to delete it that day. Tooling that documents its own expiry date is tooling you can trust while it lives. - New traps: if you hit a silent failure the lint didn’t catch, you’ve
found something valuable. The check functions in
lint_mantle.pyaverage ~30 lines each — copy the nearest one, encode your failure, 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— fourteen working projects (voice agents, CRM integrations, patterns) to read, run, and steal from. Every one of them passes the same checks Juniper now does.
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. 🛠️
