Skip to main content

Airalogy protocol execute sandbox

Project description

airalogy-engine (Python)

PyPI version Python versions

Airalogy protocol execution sandbox for Python. Run protocol packages (parse, assign, validate) inside a secure BoxLite sandbox, and execute AIMD workflow transition assignments across protocol Records.

Installation

pip install airalogy-engine

Sandbox Image

The engine runs protocol code in a BoxLite sandbox. You can use either a remote Docker image or a local OCI rootfs directory.

Remote Image

from airalogy_engine import AiralogyEngine

engine = AiralogyEngine(
    protocol_path="/path/to/your/protocol",
    image="numbcoder/airalogy-engine:latest",
)
result = await engine.parse_protocol()

Local OCI Rootfs (Recommended)

Build and export the image locally for faster, offline execution:

cd packages/runtime/airalogy-engine-image
docker build -t airalogy-engine:latest .
docker save airalogy-engine:latest -o airalogy-engine-image.tar
mkdir airalogy-engine-image
tar -xf airalogy-engine-image.tar -C airalogy-engine-image

Then use rootfs_path:

from airalogy_engine import AiralogyEngine

engine = AiralogyEngine(
    protocol_path="/path/to/your/protocol",
    rootfs_path="./airalogy-engine-image",
)
result = await engine.parse_protocol()

If neither image nor rootfs_path is provided, the engine falls back to the default remote image numbcoder/airalogy-engine:latest.

Usage

import asyncio
from airalogy_engine import AiralogyEngine

async def main():
    protocol_path = "/path/to/your/protocol"
    rootfs_path = "/path/to/airalogy-engine-image"  # or use image="..." instead
    engine = AiralogyEngine(
        protocol_path=protocol_path,
        rootfs_path=rootfs_path,
        boxlite_home="/tmp/airalogy-engine-worker-1",
    )

    # 1. Parse the protocol
    result = await engine.parse_protocol(env_vars={"API_KEY": "xxx"})
    print(result["data"]["meta_data"])
    print(result["data"]["json_schema"])

    # 2. Assign a variable
    result = await engine.assign_variable(
        var_name="duration",
        dependent_data={"seconds": 3600},
        env_vars={"API_KEY": "xxx"},
    )
    print(result["data"])

    # 3. Validate variables
    result = await engine.validate_variables(
        variables={"seconds": 60, "duration": "PT1M"},
    )
    print(result["data"])

    # 4. Import records from a file inside the protocol directory
    result = await engine.import_records(input_filename="records.json")
    print(result["data"]["records"])

    await engine.close()

asyncio.run(main())

You can also use the engine as an async context manager:

async with AiralogyEngine(
    protocol_path=protocol_path,
    rootfs_path=rootfs_path,
    boxlite_home="/tmp/worker-1",
) as engine:
    result = await engine.parse_protocol()

Workflow Usage

AiralogyWorkflowEngine executes fenced workflow definitions from a workflow.aimd file. It resolves transition.inputs, runs workflow-level Python assigners, exposes outputs under ${transition_id.outputs.key}, and applies transition.assign into target Record drafts. It does not persist Records or create Record versions; callers should save returned Record drafts through their platform or database layer.

import asyncio
from airalogy_engine import AiralogyWorkflowEngine

async def main():
    engine = AiralogyWorkflowEngine(
        workflow_path="/path/to/workflow.aimd",
        rootfs_path="/path/to/airalogy-engine-image",
    )
    result = await engine.run(
        records={
            "measurement": {"data": {"var": {"raw_data": [1, 2, 3]}}},
            "literature_review": {"data": {"var": {"summary": "known background"}}},
        },
    )
    print(result["data"]["records"]["analysis"])
    print(result["data"]["transition_outputs"])
    await engine.close()

asyncio.run(main())

For local tests or trusted scripts, pass assigner_runtime="local" to execute workflow assigners in the host Python process instead of BoxLite.

API

API Description
AiralogyEngine(protocol_path, boxlite_home=None, image=None, rootfs_path=None, timeout=300, memory_mib=512, cpus=1, auto_stop=True) Create an engine bound to one protocol path, BoxLite runtime home, and sandbox configuration
AiralogyWorkflowEngine(workflow_path, workflow_id=None, assigner_runtime="sandbox", boxlite_home=None, image=None, rootfs_path=None, timeout=300, memory_mib=512, cpus=1, auto_stop=True) Create an engine bound to one workflow.aimd file or directory and sandbox configuration for workflow-level assigners
engine.parse_protocol(env_vars=None, timeout=None, debug=False, log_file="protocol_debug.log") Parse the engine protocol and return schema, metadata, fields
engine.assign_variable(var_name, dependent_data, env_vars=None, timeout=None, debug=False, log_file="protocol_debug.log") Assign a variable using assigner functions
engine.validate_variables(variables, env_vars=None, timeout=None, debug=False, log_file="protocol_debug.log") Validate variable values against the protocol model
engine.import_records(input_filename, input_format="auto", allow_extra_var_fields=False, require_complete_quiz=False, include_template_defaults=True, validate_model_sync=True, env_vars=None, timeout=None, debug=False, log_file="protocol_debug.log") Import a protocol-local JSON/JSONL/CSV/TSV file into Airalogy record JSON objects
workflow_engine.run(records, transition_ids=None, transition_outputs=None, node_iterations=None, max_passes=1, env_vars=None, timeout=None, debug=False, log_file="workflow_debug.log") Execute workflow transitions in declaration order and return Record drafts, transition outputs, skipped transitions, attempts, and node iteration counters
workflow_engine.run_transition(transition_id, records, transition_outputs=None, node_iterations=None, env_vars=None, timeout=None, debug=False, log_file="workflow_debug.log") Execute one workflow transition and return updated Record drafts
engine.box_status() Return the current BoxLite BoxStateInfo, or None when the engine has no current box
await engine.stop() Stop this engine's current box without closing the engine
await engine.close() Stop this engine's current box and release its BoxLite runtime reference

All engine methods are async and return a dict with success, message, and data keys.

Engine parameters:

  • protocol_path: Protocol package directory. It must contain protocol.aimd and is mounted writable at /home/airalogy/protocols/protocol inside the sandbox.
  • boxlite_home: BoxLite runtime home directory. Use a distinct value for each OS process when running multiple workers.
  • image: Remote Docker image name (e.g., "numbcoder/airalogy-engine:0.1").
  • rootfs_path: Path to a local OCI rootfs directory (overrides image).
  • timeout: Execution timeout in seconds (default: 300). The sandboxed process will be killed once it times out.
  • memory_mib: Memory limit in MiB (default: 512).
  • cpus: CPU limit (default: 1).
  • auto_stop: Stop the box after each command when True (default). Set to False to keep one running box until stop() or close().

Concurrency

Use one AiralogyEngine instance per protocol and worker process. Concurrent async operations through one engine run on its current box:

engine = AiralogyEngine(
    protocol_path=protocol_path,
    rootfs_path=rootfs_path,
    boxlite_home="/tmp/worker-1",
    auto_stop=False,
)

results = await asyncio.gather(
    engine.parse_protocol(),
    engine.validate_variables({"seconds": 60, "duration": "PT1M"}),
)

await engine.stop()

BoxLite locks each runtime home per OS process. Two independent processes must not share the same boxlite_home or default ~/.boxlite; give each process a distinct directory, for example /tmp/airalogy-worker-1 and /tmp/airalogy-worker-2.

Testing

cd python
uv sync

# Default: local OCI rootfs mode
uv run pytest tests/ -v

# Custom rootfs path
uv run pytest tests/ -v --sandbox-mode=rootfs --rootfs-path=../../runtime/airalogy-engine-image/airalogy-engine-image

# Remote image mode
uv run pytest tests/ -v --sandbox-mode=image --sandbox-image=numbcoder/airalogy-engine:latest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

airalogy_engine-0.0.6.tar.gz (18.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

airalogy_engine-0.0.6-py3-none-any.whl (21.8 kB view details)

Uploaded Python 3

File details

Details for the file airalogy_engine-0.0.6.tar.gz.

File metadata

  • Download URL: airalogy_engine-0.0.6.tar.gz
  • Upload date:
  • Size: 18.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for airalogy_engine-0.0.6.tar.gz
Algorithm Hash digest
SHA256 06ec6dce88de5a627316736d88deec08ab22987abaf0e1df000a6874dd9c8d04
MD5 28203e5f0807e538f0655618320489d6
BLAKE2b-256 406c3a8c501fcab0296d42d00cf557848fc64a31a32e6a04e254ca395f66f7cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for airalogy_engine-0.0.6.tar.gz:

Publisher: release.yml on airalogy/airalogy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file airalogy_engine-0.0.6-py3-none-any.whl.

File metadata

File hashes

Hashes for airalogy_engine-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 8397b73524f2fb2d3c42afee46afa0d57e20b13e9342f105cde8708dee72c87d
MD5 bb4b3d3d1bc20399b53d14f68cb4900a
BLAKE2b-256 0a406ecc9098912cee83cf186e0d5d285a8cd66d60037e3ec0913f06b6eceb7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for airalogy_engine-0.0.6-py3-none-any.whl:

Publisher: release.yml on airalogy/airalogy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page