vike
Tools

validate_strategy

Compile a Rhai strategy offline — and understand exactly which class of mistake a compile can and cannot catch.

Compiles a Rhai strategy and answers whether it compiled. Compile is validation here: there is no separate linter. Entirely offline — no --addr, no --node, no key, no socket.

Input

FieldTypeRequiredMeaning
scriptstringyesRhai strategy source

The argument is script, matching this server's sibling discover_params. A missing one is the only isError this tool produces, and its message names the argument (validate_strategy_missing_script_arg_is_a_tool_error).

{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"validate_strategy","arguments":{
  "script": "let fast = param(\"fast\", 5.0);\nfn on_bar() {}"
}}}

What comes back

Two shapes, and both are successes:

{ "ok": true }
{ "ok": false, "error": "…the compiler's own message…" }

A bad script is an answer, not a tool failure — the agent reads the error and fixes the script. validate_strategy_answers_ok_and_compile_errors_offline pins both halves, including that ok: false arrives with isError: false.

What the check actually is

tool_validate_strategy goes through vike_script::discover_params, the broker-free public compile path. That function compiles the source and then runs its top level exactly once, which is the same error surface as mounting the strategy for real: RhaiStrategy::compile does the same one-time top-level run, and the top level is where param(name, default) is called. So the check covers the grammar, and it covers everything a script does outside a function.

It cannot see inside fn on_bar() — and that is where the trading is

Rhai resolves a registered function when the line runs, not at compile time, and this path runs only the top level. Every call a strategy makes sits inside fn on_bar() and is therefore unchecked. Three mistakes land in that blind spot: an unbound name (a typo, or any indicator the host does not bind), a wrong arity, and a wrong argument type. Name and arity always raise ErrorFunctionNotFound, and so does a mistyped argument to an order verb — register_verbs binds market as (i64, f64), rhai hashes each argument's TypeId and performs no int-to-float coercion for a registered function, so market(1, 1) misses exactly as hard as a misspelling. An indicator is the exception: register_arity_forms binds every arity with rhai::Dynamic parameters, so sma(5.0) resolves just like sma(5), and only a non-numeric argument (sma("20")) fails — as a named runtime error rather than function-not-found. Each of them errors on every bar, RhaiStrategy's hook runner swallows it fail-safe (zero orders that bar), and after 10 consecutive errors the strategy disables itself. It looks mounted and silently never trades.

That hazard is demonstrated rather than argued in the product tree: an_unbound_call_compiles_and_then_reaches_the_broker_with_nothing takes the shipped SMA-cross template, rewrites its sma( calls to a name nothing binds, and shows that it still compiles, still reports its param() knobs, and reaches the broker with nothing over 80 rising bars.

So what does close the gap

Three things, in order of cost:

  1. Check every indicator name against list_indicators, not against memory. That tool lists the host-bound callable set, which is not the same as the indicator registry.
  2. Read the knobs back with discover_params. It shares this compile path, so it confirms the top level ran and tells you which names a [sweep] may vary. Note the deliberate asymmetry: there, a compile error is a tool error, because there are no parameters to report.
  3. Run it. run_backtest over a short slice, then look at n_trades. Zero trades with a populated zero_trade diagnosis is the shape a self-disabled strategy leaves behind, and that field exists precisely so the answer is not a table of zeros.

The prompt

Does this strategy compile? If not, fix it and try again.

An agent can loop on this tool freely — it opens nothing and costs nothing but its own turn. Scripting is the language surface, the cheatsheet every host function and order verb in one page, and Rhai strategy from scratch the worked build.

On this page