evoke

Why reflexes.

Say it, and the right small program runs, only when it is sure enough. The idea in ten minutes: what is new, why it holds, and where it goes.

In one minute

You say what you want. evoke picks the small program that does it, from the ones you installed, and fills in its arguments from your sentence. It never writes a program and never makes up a value: an argument is a choice the author listed, a word you taught it, or a piece of what you typed. Beside every call it shows a number, and that number is a probability. Reading runs at a lower bar than changing something. Anything that cannot be undone asks first.

When it is not sure, it asks you, and you can teach it in one line that no update will touch. The programs are recipes anyone can write, publish with a git tag, and improve. The same decisions run inside an application, through the SDK.

The problem

01

Saying it is easy. Trusting it is the hard part.

Everyone wants to say what they mean and have the computer do it. What nobody gives you is a reason to trust what runs. An action taken on a guess costs more than one that never ran. Trust needs three things.

Reflexes are built for exactly these three. If you answer for what an automation did, you already know why. The rest of this page shows how, with real sessions.

The move

02

Your words pick a program. They never write one.

A reflex is a small program that says what it does, in plain words, and which arguments it takes. Jev, the classifier, reads your sentence and answers closed questions about it. Three kinds of question, every answer a probability.

  1. 01Which reflex?One of the installed reflexes, or none of them.
  2. 02Which values?An option the author listed, one of your own words, or a piece of the sentence, checked.
  3. 03How well does it fit?A number per reflex, so a sentence that asks for two things is noticed.

Every answer is a choice among things that already exist. That is the whole trick, and it is why a sentence can pick a call but never invent a value.

The number

03

A confidence that means what it says.

Jev's probabilities are calibrated: 0.85 means right about 85 times in 100. The weakest answer is the decision's confidence, and every effect has its bar. A read runs at 0.6, a write at 0.8, and a destructive reflex always asks. evoke try shows all of it.

evoke
$ evoke try "kill the lights"
  lights 0.90 · none 0.06 · timer 0.02 · volume 0.02
  room   unstated 0.75 · den 0.20 · office 0.05
  state  off 0.58 · on 0.30 · dim 0.10 · unstated 0.02
  fits   lights 0.70 · timer 0.05 · volume 0.05
  ask room · weakest: state 0.58
$ evoke try "kill the lights in the den"
  lights 0.91 · none 0.06 · timer 0.02 · volume 0.01
  room   den 0.85 · unstated 0.10 · office 0.05
  state  off 0.88 · on 0.05 · dim 0.05 · unstated 0.02
  fits   lights 0.70 · timer 0.05 · volume 0.05
  run · weakest: room 0.85

Three words moved the weakest answer from 0.58 to 0.85. An ask became a run. You can read every judgment, and you can move the bar in a file you own.

It stops

04

When it is not sure, nothing runs.

The value of all this is what it refuses to do, and a refusal only shows when something would have gone wrong. So here is what refusing looks like: three real sessions where nothing ran on a guess.

evoke
$ evoke "restart the computer"
  power action="restart" · destructive · weakest: action 0.97
  Really restart now?  [y]es [n]o [t]each > n
[2]
$ evoke "set the volume to 150 percent"
  How loud, in percent?  150 percent is outside 0–100  > 40
  volume level="40"  0.93
volume set to 40%
$ evoke "make it cosy"
  lights 0.45 · none 0.40 · timer 0.10 · volume 0.05 · route floor 0.50
[2]

Sure at 0.97, and it still asked: a destructive reflex always does. A value outside its range never reached a program, and the range was on the line. A sentence that fits nothing ran nothing, and showed the ranking that says why.

The recipe

05

Written once. Shared. Improved by everyone.

What a reflex says about itself is a file, its manifest: the readable definition of a decision. So it travels. evoke add fetches it from git, checks it, and locks it by content. A collection grows the way packages did, one recipe at a time.

lights/reflex.toml
reflex = 1

description = """
Turn the lights in one room on, off, or dim them.
Ceiling and lamp lights only."""
not_for = ["colour scenes and schedules", "asking whether a light is on"]
tags = ["home", "lighting"]
effect = "write"
confirm = "Set the {room} lights {state}?"
run = "lights.mts"

[config]
bridge = "Hue bridge address"

[args.room]
ask   = "Which room?"
vocab = "rooms"

[args.state]
ask         = "What should the lights do?"
options.on  = "Switch on."
options.off = "Switch off."
options.dim = "Lower the brightness without switching off."

[args.brightness]
ask      = "How bright, in percent?"
pick     = "number"
range    = [1, 100]
optional = true

[examples]
"turn on the kitchen lights"   = { state = "on" }
"dim the office to 30 percent" = { state = "dim", brightness = "30 percent" }

[tests]
"make it darker in here" = { state = "dim" }
"light a candle"         = false
  • 1Wording and contract. The description, the examples and the question are wording: you may change them for yourself. The arguments and the effect are the contract: only a new version changes them.
  • 2Tests are held out. The classifier never sees them, so they say how it does on sentences it was not shown.
  • 3A second recipe is checked against the first. At add, every installed example is routed over the new set, and a phrase the newcomer would steal is named, with its one-line fix.
  • 4A recipe can be code. The SDK takes the same manifest as an object with a function, inside your own app.

The manifest, key by key →

Your words

06

It learns your way of saying it.

Type t at a confirm and your sentence becomes an example in your overlay. Your vocabulary is a file you own. The recipe underneath is untouched, so an update never loses your words.

evoke
$ evoke "kill the lights"
  Which room?  [1] den  [2] office  [+] add one  > 1
  lights room="den" state="off" · write · weakest: state 0.58
  Set the den lights off?  [y]es [n]o [t]each > t
+ overlays/lights.toml  [examples] "kill the lights" = { state = "off" }
den lights off

The lesson is one line in a file of yours. The next decision reads it. A team shares its lessons the way it shares its dotfiles.

A weave

07

Two things in one sentence, planned before either runs.

Each part is decided as one sentence would be. The plan is shown first, numbered. A result of one step can feed the next. A part that matches nothing refuses the whole request.

evoke
$ evoke "look up dana's address and email them"
  1  contact name="dana"  0.90
  2  mail · takes email from 1
dana <dana@example.com>
  2  mail to="dana@example.com"  0.88
drafted to dana@example.com
$ evoke "kill the lights in the den and feed the cat"
  1  lights room="den" state="off"  0.85
  2  "feed the cat" · no reflex
[2]

them names the address the first step found. mail needed one, and took it. Nothing was guessed, and nothing was half done. Weaving, in the manual →

Where it goes

08

What software looks like when words select programs.

If the idea holds, the pieces are already in place. Here is the road, one stage at a time. The first three exist today. The rest could follow from them.

  1. 01Your laptop.The collection installed, your key in place. Reflexes for the things you do every day, written by people who do them too.
  2. 02Your apps.The SDK inside an ops bot, an inbox, a payments desk, a runbook. Every sentence decided the same way, checked before it runs.
  3. 03A plan you read before it runs.A request becomes numbered steps that show their confidence and ask when they must. That is how automation earns trust, one line at a time.
  4. 04Every program with a manifest.An application ships its reflexes the way it ships a package. Install it, and the words come with it.
  5. 05Your words, everywhere.Your vocabulary and your lessons are files. They could follow you from the laptop to the phone to the device on the wall.
  6. 06Engines chosen by their numbers.Jev is the first adapter of a design bound to none. The next is chosen by how honest its probabilities are.

Execution

09

Ideas like this live or die in the first year.

A shared recipe is used by everyone who installs it, so a small flaw compounds, and so does care. Four things are held to from the start.

Quality is the strategy, not a finish. A reflex written well once is right for everyone who installs it, for as long as the format lasts.

Start

10

Try it in ten minutes.

One small binary on macOS and Linux. Node next to it, for reflexes written in JavaScript.

The CLI

Fetches the release for your machine, checks its digest, and puts evoke in ~/.local/bin.

curl -fsSL https://evoke.build/install.sh | sh

The SDK

Node 24.5 or newer, ES modules, no dependencies. The core ships inside as WebAssembly.

npm install @evoke-build/evoke

Then the first ten minutes, or seven real sessions where people use it.