Run Actions¶
Actions are typed operations the agent serves: a Python function with a JSON Schema for its parameters, exposed under a name. Anything that's been registered — your own @action-decorated functions, an extension's actions — can be listed, inspected, and run from the same agent.
Defining your own actions?
This page covers calling actions. To expose your own Python functions as actions, see How to Create Actions.
The snippets below assume an agent connected via connect():
Examples use placeholder names like "my_app/read_voltage". Substitute your own from agent.actions.list().
List actions¶
for info in agent.actions.list():
print(info.name)
# my_app/read_voltage
# my_app/restart_service
# ...
ActionInfo.name is what you pass to schema() and execute(). Names usually include a namespace prefix, so actions from different sources sit alongside each other.
The list includes the actions of a running extension. It also includes the standalone actions of an installed extension that is stopped. The agent runs those from the installed package, so you call them the same way.
Run an action¶
result = agent.actions.execute("my_app/read_voltage", {"rail": "5v0"})
if result.ok:
print(result.value) # 5.02
else:
print(f"action returned status={result.status!r}: {result.value}")
execute() always returns an ActionResult. A failed run does not raise; it reports through the result:
.value— the return value as native Python (None,bool,int,float,str,list, ordict)..status— anActionStatus:"pass"or"done"(success),"fail"(logical failure), or"error"(the action raised or timed out). It compares equal to its string, soresult.status == "pass"works..ok—Truewhen status is"pass"or"done". Always check.okbefore reading.value.
A result with no status, or a status the SDK does not know, reads as "done".
For no-arg actions, omit params or pass None:
Most actions reject unknown fields with a "fail" status. The schema is the source of truth for what params should contain.
params is a dict, encoded as JSON. A value that JSON has no type for, such as a tuple, a set or a datetime, is sent as its str(). Pass a list where the action expects an array.
Timeouts¶
timeout is a float in seconds and must be positive. Where the action runs decides what it does:
- The extension is running.
timeout=replaces the action's declared timeout, longer or shorter. Without it, the extension applies the action'sdefault_timeout_ms(a Python@actiondeclares 30 seconds unless it setstimeout=). When the time runs out, the result has status"error"and a value like{"error": "Action timed out after 60000ms"}. - The extension is stopped. The agent runs a
standaloneaction from the installed package. Theretimeout=can only shorten the declared timeout. When the time runs out, the call raisesAgentError.
Five minutes per call
The SDK waits at most five minutes for any single call to the agent. An action that runs longer raises AgentCancelled, whatever timeout= you pass.
Inspect a schema¶
agent.actions.schema(name) returns an ActionSchema describing the action's inputs:
| Field | Description |
|---|---|
.action_schema |
A JSON Schema dict — types, required fields, ranges, patterns. |
.ui_schema |
UI hints (widget choices, ordering, the run button's label). Optional; ignore if you're calling directly. |
.default_timeout_ms |
The timeout the action declares, in milliseconds, or None. The extension applies it when you pass no timeout=. |
.read_only |
True when the action declares that it changes nothing. Zelos AI runs a read-only action without asking first. |
schema = agent.actions.schema("my_app/read_voltage")
print(schema.action_schema["required"])
# ['rail']
The schema tells you exactly what params should contain.
Dynamic schemas
For schemas where one field's choices depend on another, pass current_values=
with whatever the user has filled in so far. Same JSON-friendly dict shape as params.
Build a UI from a schema¶
action_schema is standard JSON Schema, so it drops into any form library that consumes it (the Zelos App uses react-jsonschema-form). To inspect fields directly:
schema = agent.actions.schema("my_app/read_voltage")
for name, field in schema.action_schema.get("properties", {}).items():
title = field.get("title") or name
print(name, field.get("type"), "-", title)
Errors¶
from zelos_sdk import AgentError
try:
result = agent.actions.execute("my_app/read_voltage", timeout=5.0)
except AgentError as exc:
print("call failed:", exc, "cause:", exc.cause)
else:
if not result.ok:
print(f"action reported {result.status!r}: {result.value}")
else:
print(result.value)
| Exception | When |
|---|---|
ValueError |
The action name is empty, or timeout is not a positive number. |
TypeError |
params or current_values is not a dict. |
AgentError |
No action has that name; params has a key that is not a string or a NaN value; a stopped extension's action ran out of time. .cause carries the agent's error code and message. |
AgentCancelled |
The call ran longer than five minutes. |
ActionFailed |
The agent's result is not valid JSON, so the SDK cannot decode value. |
Internal |
The agent answered without a result or schema. This is an SDK bug, and except AgentError does not catch it. |
A failing action result (status="fail" or "error") does not raise — check .ok. To turn a failed result into an exception, raise ActionFailed yourself:
from zelos_sdk import ActionFailed
if not result.ok:
raise ActionFailed(f"{result.status}: {result.value}")
Tips¶
- Pass
params=None(or omit it) for no-arg actions. - Always check
result.okbefore readingresult.value. A"fail"or"error"status often puts a diagnostic message invalue. - Check
schema.read_onlybefore you run an action you have not seen before. AFalsethere means the action may change something.
What's next¶
-
Start, stop, and configure the extensions that publish actions and signals.
-
Time-series queries, latest values, and replay windows.
-
Define Python functions as actions and serve them to the agent.