Skip to content

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():

from zelos_sdk import connect

with connect() as agent:
    ...

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, or dict).
  • .status — an ActionStatus: "pass" or "done" (success), "fail" (logical failure), or "error" (the action raised or timed out). It compares equal to its string, so result.status == "pass" works.
  • .ok — True when status is "pass" or "done". Always check .ok before 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:

result = agent.actions.execute("my_app/restart_service")

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's default_timeout_ms (a Python @action declares 30 seconds unless it sets timeout=). 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 standalone action from the installed package. There timeout= can only shorten the declared timeout. When the time runs out, the call raises AgentError.
result = agent.actions.execute("my_app/long_calibration", timeout=60.0)

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.ok before reading result.value. A "fail" or "error" status often puts a diagnostic message in value.
  • Check schema.read_only before you run an action you have not seen before. A False there means the action may change something.

What's next