Skip to content

tutorial

Chapter 4 of 4

Chapter 4 — Run It, Review It, Repeat

by Rod Rivera Published

Bring Juniper to life, adopt the everyday workflow, learn the review role, and know exactly what your green checkmarks do and do not prove.

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:

VariableWhere it comes from
RASA_LICENSEFree Developer Edition key — a long one-line JWT
OPENAI_API_KEYYour 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”:

LayerCommandProvesDoesn’t prove
Lintpython3 scripts/lint_mantle.pyInternally consistent; no known trapsThat the engine accepts it
Enginemake trainThe installed engine accepts and builds itThat 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 → X upgrade 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.yml keys appear in dev releases; tool_timeout arrived 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.py average ~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. 🛠️