Actions¶
Five actions answer inside an automation and return a response variable.
- action: jev.noul
response_variable: laundry
target:
entity_id: sensor.washing_machine_power
data:
instructions: Is the laundry finished but still sitting in the machine?
background: >-
This machine draws under 5 W when idle and over 300 W while a programme runs.
threshold: 0.7
- if: "{{ laundry.is_true }}"
then:
- action: notify.mobile_app
data: { message: The washing is done and still in the machine. }
| Action | You give it | You get back |
|---|---|---|
jev.noul |
a yes/no question | noul 0 to 1, is_true against your threshold |
jev.choice |
options:, 2 to 255 |
choice, probabilities, confidence |
jev.score |
levels:, 2 to 10, lowest first |
score, normalized, nearest_level, legend, probabilities, confidence |
jev.ask |
any mix, under your own keys | the same, under answers |
jev.box |
one camera or image entity, and what to find in it | left, top, right, bottom, confidence, width, height |
Every response also carries usage and latency_ms, so an automation can watch what
it spends.
Point at entities instead of writing a template¶
All four take the normal Home Assistant target picker. Select entities, devices, areas, floors or labels and the state is built for you:
- action: jev.choice
response_variable: room
target:
area_id: kitchen
data:
instructions: What is happening in this room?
options:
cooking: Somebody is preparing food
eating: Somebody is at the table
empty: Nobody is in here
Up to 250 entities. Past that it refuses and tells you your number, because every entity is billed on every evaluation.
The actions send whatever you target, whether or not it is exposed to Assist. An
automation names its entities on purpose, so the Assist exposure list is not
consulted here; it is consulted for the conversation agent.
include_attributes: true never sends access tokens, entity pictures or coordinates,
so a camera or a device_tracker is safe to target.
Show it a camera¶
images: takes camera and image entities, and sends the current picture of each
beside the state:
- action: jev.noul
response_variable: parcel
data:
images: [camera.front_door]
instructions: Is there a parcel on the doorstep?
It works alone or with a target and a state. A picture costs hundreds to thousands
of tokens, and the budget counts it. Cameras and images has the sizes,
the cost, jev.box and what each error means.
Ask another model for one call¶
Every action takes model:, which asks that model instead of the entry's for this
call only. The entry's model, its version sensor and its options stay as they are.
Box questions need it today: a new entry asks jev-latest, which answered as Jev
1.13 on 2026-10-16, and Box needs jev-1.14.0 or jev-preview.
More than one entry¶
Each Jev entry has its own key and budget. With more than one loaded, an action has
to name the one to ask with under API key (config_entry: in YAML). An action
that names none is refused before anything is sent, and the error lists the entries.
Ask several things at once¶
jev.ask takes any mix under your own keys, in one request:
- action: jev.ask
response_variable: jev
data:
state:
transcript: "{{ trigger.payload }}"
questions:
caller:
type: choice
instructions: Who is at the door?
criteria:
delivery: A courier
visitor: Someone we know
urgency:
type: score
instructions: How quickly does this need a person?
criteria: [Never, Whenever, Right now]
answer_now:
type: noul
instructions: Does someone need to go to the door right now?
This is the shape to reach for. Adding a question costs tokens, not time, so asking the five you might need and discarding four is cheaper than two round trips.
Templates and variables¶
state: takes a template, an object or a list, and automation variables reach it:
- variables:
household: "{{ states('input_text.house_notes') }}"
- action: jev.noul
response_variable: answer
data:
state:
note: "{{ household }}"
time: "{{ now().strftime('%H:%M on %A') }}"
instructions: Is this worth waking someone for?
An object arrives as an object, not as a stringified dict. The model reads the field names as labels, so name them for what they hold.
Tune a threshold¶
jev.calibrate is a fifth action that asks nothing. It compares the recorded history
of a noul sensor with an entity that shows what was really true, and returns the
threshold that fits best. It costs no tokens. See tuning a threshold.
Errors name the limit¶
Every budget failure names the budget, the limit and your ask, because an agent
reading the error can fix max 255 options, asked for 300 and cannot fix a blank
window.