Skip to main content

PyroMind SDK

Lightweight Python SDK for the PyroMind AI Platform API — manage training workflows, Jupyter instances, inference jobs, EchoMind and more.

Installation

pip install pyromind-sdk

Requires Python >= 3.8.

Quick Start

from pyromind_sdk import PyroMindAPIClient
from pyromind_sdk.client.models import TrainingTaskCreateRequest

client = PyroMindAPIClient(api_key="your-api-key")

# Create and run a studio task
task = client.studio.create(
    TrainingTaskCreateRequest(
        name="my-workflow",
        workflow={"nodes": [...]}
    )
)
print(f"Created task: {task.task_id}")

Docker CLI over Kubernetes (docker-rt)

pyromind_sdk.docker_rt is an embedded Docker Engine API facade: it listens on a Unix socket (or TCP), translates docker commands into Kubernetes Pod operations, and exposes KubeEnvironment as the SDK-side adapter.

pip install -e .

# start the daemon (Docker Desktop / any reachable cluster)
docker-rt
# underscore alias also works
# docker_rt
# same daemon, via the unified SDK CLI
# pyromind docker-rt

# SDK defaults: kube-context=docker-desktop, namespace=default,
# node-selector=disabled. Override any of them with DOCKER_RT_* env vars.

# background daemon
pyromind docker-rt --daemon
# pyromind docker-rt --daemon --log-file /tmp/docker-rt.log --pid-file /tmp/docker-rt.pid

# point the Docker CLI at it
docker-rt-context
# docker-rt backs up the current Docker context, switches to docker-rt, and
# on exit (including kill -9) a watcher restores the backup, then exits
# manual fallback if needed:
docker-rt-context --restore

docker version
docker run -d --name demo busybox:1.36 sleep 300
docker ps
docker exec demo echo hello

Docker CLI is required before starting docker-rt; if it is missing the daemon refuses to start. On Linux you can install the static binary:

curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-27.5.1.tgz \
  | tar -xz -C /tmp
sudo mv /tmp/docker/docker /usr/local/bin/docker
chmod +x /usr/local/bin/docker

For other systems, see: https://docs.docker.com/desktop/

docker-rt checks the local ~/.pyromind/bin/docker wrapper at startup. If it is missing it asks to install it (or installs automatically in non-interactive shells), and it refreshes the wrapper when the SDK version changes. Declining the install stops docker-rt from starting. Run pyromind-docker-uninstall to remove the wrapper and its PATH entry.

pyromind docker-rt parameters

Argument Meaning Default
--sock SOCK Unix socket path exposed to the Docker CLI $DOCKER_RT_SOCK or /tmp/docker-rt.sock
--daemon Start docker-rt in the background and return immediately disabled
--stop Stop a background docker-rt daemon and restore the previous Docker context disabled
--log-file FILE Log file used by --daemon $DOCKER_RT_LOG_FILE or /tmp/docker-rt.log
--pid-file FILE Write/read the daemon PID file $DOCKER_RT_PID_FILE or /tmp/docker-rt-<sock>.pid
--apikey KEY (--api-key KEY) PyroMind API key $PYROMIND_API_KEY
--cluster CLUSTER Target cluster, e.g. us-west-1#pre $PYROMIND_CLUSTER
-h, --help Show help and exit -
pyromind docker-rt \
  --daemon \
  --sock /tmp/docker-rt.sock \
  --log-file /tmp/docker-rt.log \
  --pid-file /tmp/docker-rt.pid

Use environment variables, or pass credentials directly:

export PYROMIND_API_KEY=XXXXXXXXX
export PYROMIND_BASE_URL=https://pre-api.pyromind.ai/api/v1
export PYROMIND_CLUSTER='us-west-1#pre'
pyromind docker-rt --daemon

# or
pyromind docker-rt --daemon --apikey XXXXXXXXX --cluster 'us-west-1#pre'

docker-rt environment variables

Variable Default Meaning
DOCKER_RT_SOCK /tmp/docker-rt.sock Unix socket path
DOCKER_RT_HOST / DOCKER_RT_PORT empty / 2375 Listen on TCP instead of Unix socket
DOCKER_RT_LOG_FILE /tmp/docker-rt.log Daemon log file
DOCKER_RT_KUBECONFIG / KUBECONFIG ~/.kube/config or package .kube.yaml kubeconfig path
DOCKER_RT_KUBE_CONTEXT docker-desktop Kubernetes context name
DOCKER_RT_NAMESPACE default Target Kubernetes namespace
DOCKER_RT_NODE_SELECTOR none Pod nodeSelector (key=val,...; none disables)
DOCKER_RT_GPU_CARD empty GPU card name when using docker run --gpus with the k8s-middleware backend
DOCKER_RT_INSPECT_MODE sandbox docker inspect structure: sandbox or standard
DOCKER_RT_DEFAULT_IMAGE SWE-bench default image docker images default entry
DOCKER_RT_PORT_FORWARD_MODE auto -p backend: auto / direct / api
DOCKER_RT_BUILDKIT_ADDR empty buildctl address, e.g. unix:///run/buildkit/buildkitd.sock
DOCKER_RT_BUILD_REGISTRY empty Push prefix for short image tags
DOCKER_RT_BUILD_PUSH true Whether build pushes to the registry
DOCKER_RT_BUILD_TIMEOUT 3600 buildctl timeout in seconds
DOCKER_RT_SERVICE_DNS true Create ClusterIP Service for Compose service DNS
DOCKER_RT_ORPHAN_POLICY adopt adopt restores managed Pods; reap deletes them on startup
DOCKER_RT_CLEANUP_ON_EXIT false Delete managed Pods on SIGINT/SIGTERM when true
DOCKER_RT_CONTEXT_KEEP true Keep Docker context switched to docker-rt while the daemon runs
DOCKER_RT_CONTEXT_KEEP_INTERVAL 5 Seconds between context keeper checks
DOCKER_RT_SHOW_API_KEY false Print the full API key in the connection banner when true
DOCKER_RT_JUICEFS_UID derived from namespace JuiceFS subPath user id
DOCKER_RT_JUICEFS_PVC auto-discovered JuiceFS PVC name
DOCKER_RT_JUICEFS_HOST_PREFIXES empty Extra host path to JuiceFS subPath mappings
DOCKER_RT_CONTEXT docker-rt Docker context name used by docker-rt-context
LOG_LEVEL INFO Log level

For the default k8s-middleware backend, docker-rt checks PYROMIND_API_KEY and PYROMIND_CLUSTER; missing values are prompted one by one. After a successful connection it prints the active parameters in color and syncs the sandbox list once during startup.

Supported Docker commands

Command Description Supported parameters
docker version / docker info Version and daemon info none
docker ps / docker ps -a Container list; CUSTOM only by default -a, --filter name/id/status/ancestor/label, --no-trunc, --format
docker inspect Container details --format, DOCKER_RT_INSPECT_MODE
docker images / docker pull Image list; pull is a stub image reference
docker run Create and start a sandbox -d, -it, --name, --cpus, --memory, --gpus, --gpu-card / --gpu_card, --label docker-rt.gpu-card=, -p / --publish, -v / --volume, -e / --env, -w / --workdir, --tmpfs
docker create Create a local record --name, --cpus, --memory, --gpus, --gpu-card / --gpu_card, --label docker-rt.gpu-card=, -p, -v, -e, -w, --tmpfs
docker start Create/start the Pod none
docker exec Run a command or open a terminal -it, -w / --workdir
docker cp Copy files CONTAINER:PATH <-> LOCAL_PATH
docker stop / docker kill Stop or kill a container none
docker restart Restart a container none
docker rename Rename a container none
docker rm Remove a container -f / --force; wrapper prompts when running without -f
docker port Show port mappings none
docker volume / docker network Volume and network stubs basic create / inspect / ls / rm
docker compose up Limited Compose support basic up / down

docker inspect output

Default DOCKER_RT_INSPECT_MODE=sandbox. docker inspect returns only:

{
  "id": "sb-94d290262ee8",
  "name": "test-for-doc",
  "type": "custom",
  "status": "Stopped",
  "configuration": {},
  "resources": {},
  "created_at": "",
  "updated_at": "",
  "image": "",
  "volume_mounts": [],
  "port_mappings": []
}

Set DOCKER_RT_INSPECT_MODE=standard to keep the standard Docker inspect fields as well.

GPU card via Docker flags

docker run --gpus passes the GPU count. To specify the GPU card model without setting DOCKER_RT_GPU_CARD, use the docker-rt.gpu-card label:

docker create \
  --name gpu-demo \
  --cpus 4 \
  --memory 8g \
  --gpus 1 \
  --label docker-rt.gpu-card=L40S \
  swebench/swesmith.x86_64.oauthlib_1776_oauthlib.1fd52536

To use the shorter --gpu-card L40S syntax, run pyromind docker-rt once. Every pyromind docker-rt run asks for confirmation, installs ~/.pyromind/bin/docker, and adds it to your shell PATH. Declining the prompt still starts docker-rt, but --gpu-card shorthand is unavailable; use --label docker-rt.gpu-card=L40S or DOCKER_RT_GPU_CARD instead. You can also install it manually:

pyromind docker-install

Before pip uninstall pyromind-sdk, remove the wrapper manually:

pyromind docker-uninstall
# or
pyromind-docker-uninstall

pip uninstall has no uninstall hook, so this explicit command deletes ~/.pyromind/bin/docker and removes the PATH line from your shell rc file.

After installation, open a new terminal and use:

docker create \
  --name gpu-demo \
  --gpus 1 \
  --gpu-card L40S \
  busybox:1.36 sleep 300

docker ps only shows Running sandboxes by default; use docker ps -a to see Stopped sandboxes too. docker ps shows CUSTOM sandboxes only. To include OSWorld instances, use: docker ps shows CUSTOM sandboxes only. Filter by type using label.type (default CUSTOM, osworld for OSWorld, all for both):

docker ps --filter label.type=osworld
docker ps --filter label.type=custom
docker ps --filter label.type=all

Standard Docker filters are passed to the docker-rt server and applied there:

docker ps --filter name=test-sdk-1
docker ps --filter id=sb-94d290
docker ps --filter status=running
docker ps --filter ancestor=swebench
docker ps --filter label.type=custom

The legacy --filter label=docker-rt.type=<type> syntax is still supported.

This is the correct way to search on the server side. docker ps | grep XXXX is client-side filtering: grep runs after the daemon has returned output, so the docker-rt server never receives XXXX. Standard Docker protocol does not provide a cross-field substring filter; use the explicit filter that matches the field you know (name, id, status, ancestor, or label).

When the docker wrapper is active, docker ps uses the custom header: CONTAINER ID / IMAGE / COMMAND / CREATED / STATUS / PORTS / NAMES, matching standard Docker. Column widths are adaptive to the terminal and long values are truncated; CREATED is computed in standard Docker style (e.g. About a minute ago, 3 days ago). The STATUS column shows only the state keyword (running shows Up, stopped shows Exited, pending shows Created, failed shows Dead, without a duration), while --filter status= still matches the internal state (running / stopped / pending / failed).

Docker command reference

docker run / docker create

docker run creates and starts a sandbox; docker create only creates a local record; docker start actually creates/starts the sandbox (Pending -> Running).

Parameter Description Example
--name sandbox name --name gpu-demo
image container image busybox:1.36
--cpus CPU count (default 1) --cpus 4
--memory memory size (default 2Gi) --memory 8g
--gpus GPU count --gpus 1
--gpu-card / --gpu_card GPU card model, requires wrapper --gpu-card L40S
--label docker-rt.gpu-card=L40S GPU card model, no wrapper needed --label docker-rt.gpu-card=L40S
-p / --publish port mapping -p 8080:80
-v / --volume volume mount -v /workspace:/data
-v ...:ro read-only mount -v /workspace:/data:ro
-e / --env environment variable (not supported by k8s-middleware yet) -e FOO=bar
-w / --workdir working directory (not supported by k8s-middleware yet) -w /workspace
--tmpfs temporary memory disk (not supported by k8s-middleware yet) --tmpfs /tmp:rw

Example:

docker create \
  --name gpu-demo \
  --cpus 4 \
  --memory 8g \
  --gpus 1 \
  --label docker-rt.gpu-card=L40S \
  -p 8080:80 \
  -v /workspace:/data:ro \
  busybox:1.36 sleep 300

docker start gpu-demo

Minimal create / run / remove example:

docker create --name test-sdk-1 swebench/swesmith.x86_64.oauthlib_1776_oauthlib.1fd52536
docker start test-sdk-1
docker ps
docker exec -it test-sdk-1 bash
docker rm -f test-sdk-1

--name is required when you want to use a custom name. Without it, docker create test-sdk-1 IMAGE treats test-sdk-1 as the image name. After creating with --name, docker start test-sdk-1 and docker rm -f test-sdk-1 work by name. Non-running containers can be removed directly with docker rm NAME; running containers need -f / --force. When using the docker-rt wrapper, a running docker rm without -f asks for confirmation first. If you see No such container: NAME, run docker ps -a to check the actual container name — it is only registered when create used --name. With the k8s-middleware backend, docker run IMAGE without -d or -it returns after the sandbox is Running with a hint, because foreground attach is not supported yet. Use docker run -d for a background sandbox or docker run -it IMAGE bash for an interactive terminal.

For the k8s-middleware backend, omitting --cpus, --memory and --gpus uses 1 CPU / 2Gi memory and no GPU.

docker ps / docker ps -a

docker ps      # Running only
docker ps -a   # Running + Stopped

With the wrapper active, the header is:

CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES

Long values are truncated with ...; use docker inspect for full details.

docker inspect

docker inspect gpu-demo
docker inspect gpu-demo --format '{{json .resources}}'

The default response only contains sandbox fields. Set DOCKER_RT_INSPECT_MODE=standard to keep standard Docker inspect fields.

docker exec

docker exec gpu-demo echo hello
docker exec -w /workspace gpu-demo ls -la

Non-interactive exec is supported; docker exec -it <name> reuses the k8s_middleware /sandboxes/{id}/terminal WebSocket and opens an interactive shell. The original pyromind terminal <sandbox-id> subcommand keeps its existing parameters and logic. --cluster and --api-key can be supplied as flags or environment variables, but at least one source for each is required; --base-url is optional.

docker logs

docker logs gpu-demo
docker logs -f gpu-demo

The k8s_middleware backend does not expose /logs yet.

docker cp

docker cp gpu-demo:/etc/os-release /tmp/os-release
docker cp /tmp/file.txt gpu-demo:/workspace/file.txt

docker stop / docker start

docker stop gpu-demo
docker start gpu-demo

With the k8s_middleware backend, stop maps to pause and start maps to resume.

docker restart

docker restart gpu-demo

Maps to pause then resume.

docker rename

docker rename gpu-demo gpu-demo-2

With the k8s_middleware backend, name-only changes skip the StatefulSet rollout.

docker rm

docker rm -f gpu-demo

With the k8s_middleware backend, it pauses before deleting.

docker port

docker port gpu-demo

Ports come from k8s_middleware port_mappings. With the PyromindSDK backend, docker-rt only shows port mappings; local access is not supported yet and would require an adapter to k8s_middleware port-forward / NodePort.

docker events

docker events is not supported by the k8s-middleware backend. Use docker ps and docker inspect to check container state.

Unsupported Docker commands

After starting docker-rt, these commands are not supported:

docker build
docker buildx build
docker compose build
docker compose up --build
docker logs
docker events

They depend on a real Docker daemon / BuildKit container lifecycle. Build the image with normal Docker/BuildKit first and push it to a registry, then use docker run with that image. docker logs is not supported by the k8s-middleware backend; use docker exec -it <container> bash to view logs inside the container.

Chain: Docker CLI -> docker-rt daemon -> KubeEnvironment -> Kubernetes API. The current implementation uses the official Kubernetes Python SDK directly; a future adapter can replace that hop with the k8s_middleware HTTP API.

To run through k8s_middleware OpenAPI instead:

PYROMIND_API_KEY=your-key \
PYROMIND_BASE_URL=https://api.pyromind.ai/api/v1 \
PYROMIND_CLUSTER=us-west-2 \
pyromind docker-rt

In this mode docker-rt uses the PyromindSDK adapter, which reads the current sandbox, merges changed fields, and submits the full sandbox update. The backend is fixed to k8s-middleware. Local port forwarding is not supported for the PyromindSDK backend yet. k8s_middleware skips the StatefulSet rollout when only the sandbox name changes.

Common issues

Symptom Cause Fix
docker ps still shows the standard CONTAINER ID ... header The wrapper is installed but the current shell has an old PATH Run source ~/.bashrc or open a new terminal
docker commands connect to ~/.docker/run/docker.sock Docker context is desktop-linux / default instead of docker-rt Run docker-rt-context, or use DOCKER_HOST=unix:///tmp/docker-rt.sock
docker logs / docker events wait forever or return unsupported These commands are not supported by the k8s-middleware backend Use docker exec -it <container> bash, docker ps, and docker inspect
docker cp finishes but no Successfully copied message An old wrapper redirected Docker output, and Docker CLI suppressed the message when stdout/stderr was not a TTY Update the SDK/wrapper and restart docker-rt
docker rm <sb-...> asks for confirmation but docker rm <local-id> returns an error The wrapper can only inspect IDs that the current daemon still knows Use the sb-... sandbox ID, or restart docker-rt to refresh local records
An API error has no trace_id The operation did not reach k8s-middleware (local validation only) Only backend responses carrying x-trace-id will include trace_id=

Configuration

Client parameters

Param Required Type Default Description
api_key Yes* str PYROMIND_API_KEY env Bearer token for API auth
cluster No str PYROMIND_CLUSTER env or "us-west-2" Target cluster (X-Cluster header)
timeout No int 30 Request timeout in seconds
max_retries No int 3 Max retries for failed requests

* api_key can be provided as a parameter or via PYROMIND_API_KEY environment variable.

Environment variables

Variable Required Default Description
PYROMIND_API_KEY Yes API bearer token
PYROMIND_CLUSTER No us-west-2 Target cluster identifier
PYROMIND_STORAGE_ENDPOINT No https://storage.pyromind.ai Storage endpoint URL
PYROMIND_STORAGE_SECRET_KEY No Storage secret key
PYROMIND_STORAGE_BUCKET No Default storage bucket name

Project Structure

pyromind_sdk/
├── client/                          # API clients
│   ├── base.py                      # Base HTTP client
│   ├── client.py                    # PyroMindAPIClient (unified entry)
│   ├── async_client.py              # PyroMindAsyncAPIClient (async entry)
│   ├── studio.py / async_studio.py  # Studio / Training tasks
│   ├── jupyterLab.py / async_jupyterlab.py  # Jupyter instances
│   ├── inference.py / async_inference.py    # Inference jobs
│   ├── echomind.py / async_echomind.py      # EchoMind instances
│   ├── storage.py                   # File storage
│   ├── profile.py                   # User profile & SSH keys
│   ├── models.py                    # Pydantic models
│   └── workflow/                    # Workflow validation & conversion
├── nodes/                           # Custom node SDK
│   ├── function_call_wrapper.py     # Python function → node
│   ├── python_function_executor.py  # Python node executor
│   ├── python_to_yaml.py            # Convert Python to YAML
│   └── yaml_loader.py               # YAML node loader
├── common/                          # Shared utilities
│   ├── constants.py
│   └── node_sdk.py
├── cli.py                           # CLI entry points
├── python_function_to_yaml_cli.py   # Python → YAML CLI tool
├── examples/                        # Usage examples
│   └── openapi/                     # API usage examples
└── tests/                           # Test suite

Services

Studio (client.studio)

Training workflow management — create, monitor, and manage workflow tasks.

Method Input Output Description
list() List[TrainingTaskResponse] List all studio tasks
create(request) TrainingTaskCreateRequest TrainingTaskCreateResponse Create a new training task
get_job(task_id) / get_task(task_id) str TrainingTaskResponse Get task details
delete(task_id, force=False) str, bool None Delete a task
stop(task_id) str TrainingTaskResponse Stop a running task
get_node_output(task_id, node_id) str, str Optional[Dict] Get node-level output
get_node_info(names=None) Optional[str] Dict[str, Any] Get node definition info
reload_nodes(node_name=None) Optional[str] Dict[str, Any] Reload node YAML definitions
create_node(...) yaml_path/yaml_content + opts Dict[str, Any] Register a custom node
delete_node_by_name(node_name) str Dict[str, Any] Delete a custom node
move_node(node_name, source_file_path) str, str Dict[str, Any] Move node source
run_with_params(request) WorkflowRunRequest TrainingTaskCreateResponse Run stored workflow with params
export_node_outputs(task_id, nodes_info, ...) str, List, Optional[List] List[Dict] Export all node outputs
wait_for_task_completion(task_id, ...) str + opts str (status) Poll until terminal status
create_and_wait(request, ...) TrainingTaskCreateRequest + opts Dict[str, Any] Create + poll + optionally export outputs

TrainingTaskCreateRequest parameters:

Param Required Type Description
name Yes str Task name
workflow Yes Dict[str, Any] Workflow JSON structure with node definitions

WorkflowRunRequest parameters:

Param Required Type Description
workflow_name Yes str Name of the stored workflow
primitive_node_map No Dict[str, Any] Injected primitive node values (default: {})

Example:

from pyromind_sdk.client.models import TrainingTaskCreateRequest, WorkflowRunRequest

# Create a training task
task = client.studio.create(
    TrainingTaskCreateRequest(
        name="my-workflow",
        workflow={"nodes": [...]}
    )
)
print(f"Task ID: {task.task_id}")

# List tasks
tasks = client.studio.list()

# Run workflow with params
result = client.studio.run_with_params(
    WorkflowRunRequest(workflow_name="my-workflow", primitive_node_map={"key": "value"})
)

# Wait for completion
status = client.studio.wait_for_task_completion(task.task_id, timeout=600)
print(f"Final status: {status}")

Jupyter (client.jupyter)

Jupyter instance management.

Method Input Output Description
list() List[JupyterResponse] List all Jupyter instances
create(request) JupyterRequest JupyterResponse Create new instance
get_instance(jupyter_id) str JupyterResponse Get instance details
update(jupyter_id, request) str, JupyterRequest JupyterResponse Update instance config
delete(jupyter_id) str None Delete an instance
pause(jupyter_id) / resume(jupyter_id) str JupyterResponse Pause/resume

JupyterRequest parameters:

Param Required Type Description
name No str Instance display name
resources No ResourceConfig CPU/memory/gpu config

Example:

from pyromind_sdk.client.models import JupyterRequest, ResourceConfig

# Create Jupyter instance
jupyter = client.jupyter.create(
    JupyterRequest(
        name="my-notebook",
        resources=ResourceConfig(cpu="4", memory="16Gi", gpu="1")
    )
)
print(f"Jupyter ID: {jupyter.id}, URL: {jupyter.url}")

Inference (client.inference)

Inference job management.

Method Input Output Description
list() List[InferenceJobResponse] List all inference jobs
create(request) InferenceJobRequest str (job_id) Create inference job
get_job(job_id) str InferenceJobResponse Get job details
update(job_id, request) str, InferenceJobRequest InferenceJobResponse Update job config
delete(job_id) str None Delete a job
pause(job_id) / resume(job_id) str InferenceJobResponse Pause/resume job
get_framework() List[str] List available frameworks
get_inf_image(framework) str List[str] List inference images

InferenceJobRequest parameters:

Param Required Type Description
model_path Yes str Path to the model
inference_framework No str Framework name (get via get_framework())
resources No ResourceConfig CPU/memory/gpu config
name No str Job display name
inf_image No str Inference image (get via get_inf_image())
model_name No str Model name override
model_length No int Model context length
startup_args No List[dict] or List[str] Custom inference server startup args. Prefer [{"--arg": value}]; include the leading - or -- yourself. Duplicate default options are overridden by user args

Example:

from pyromind_sdk.client.models import InferenceJobRequest, ResourceConfig

# List available frameworks and images
frameworks = client.inference.get_framework()
images = client.inference.get_inf_image(frameworks[0])

# Create inference job
job_id = client.inference.create(
    InferenceJobRequest(
        model_path="/path/to/model",
        inference_framework=frameworks[0],
        resources=ResourceConfig(cpu="8", memory="32Gi", gpu="1", gpu_card="H100"),
        startup_args=[{"--trust-remote-code": None}],
        name="my-inference"
    )
)
print(f"Job ID: {job_id}")

# Get job details
job = client.inference.get_job(job_id)
print(f"Status: {job.status}")

EchoMind (client.echomind)

EchoMind instance lifecycle management.

Method Input Output Description
list() List[EchoMindJobResponse] List all EchoMind instances
create(request) EchoMindJobRequest str (job_id) Create EchoMind instance
get_job(job_id) str EchoMindJobResponse Get instance details
update(job_id, request) str, EchoMindJobRequest EchoMindJobResponse Update instance config
delete(job_id) str None Delete an instance
pause(job_id) / resume(job_id) str EchoMindJobResponse Pause/resume

EchoMindJobRequest parameters:

Param Required Type Description
name No str Instance display name
resources No ResourceConfig CPU/memory/gpu config

Example:

from pyromind_sdk.client.models import EchoMindJobRequest, ResourceConfig

# Create EchoMind instance
job_id = client.echomind.create(
    EchoMindJobRequest(
        name="my-echomind",
        resources=ResourceConfig(cpu="4", memory="16Gi")
    )
)
print(f"EchoMind ID: {job_id}")

# List instances
instances = client.echomind.list()

# Cleanup
client.echomind.delete(job_id)

Storage (client.storage)

MinIO/S3-compatible file storage. Requires minio package (pip install minio).

Method Input Output Description
list_files(folder_path, ...) str + opts List[Dict] List files in a directory
file_exists(file_path) str bool Check file existence
upload_file(file_path, object_name, ...) str/Path/BinaryIO + opts Dict[str, Any] Upload file (multipart support)
upload_folder(folder_path, ...) str/Path + opts List[Dict] Upload entire folder
download_file(object_name, ...) str + opts Union[bytes, Path] Download file
download_folder(folder_path, local_path) str, str/Path + opts List[Dict] Download folder
delete_file(object_name) str None Delete a file
delete_folder(folder_path) str + opts Dict Delete a folder

Storage init parameters:

Param Required Type Description
endpoint No str Storage endpoint (env: PYROMIND_STORAGE_ENDPOINT, default: https://storage.pyromind.ai)
access_key No str Access key (env: PYROMIND_API_KEY)
secret_key No str Secret key (env: PYROMIND_STORAGE_SECRET_KEY)
bucket_name No str Default bucket (env: PYROMIND_STORAGE_BUCKET)
secure No bool Use HTTPS (auto-detected from endpoint URL)
region No str Storage region (default: us-east-1)

Example:

from pyromind_sdk.client.storage import StorageClient

storage = StorageClient()

# List files
files = storage.list_files(folder_path="documents/")
for f in files:
    print(f"{f['object_name']} ({f['size']} bytes)")

# Upload file
storage.upload_file("local/file.txt", "remote/file.txt")

# Download file
storage.download_file("remote/file.txt", "downloaded/file.txt")

# Check existence
if storage.file_exists("remote/file.txt"):
    print("File exists")

Profile (client.profile)

User profile and SSH keys.

Method Input Output Description
get_user_info(credit_info=False) bool ProfileUserInfoResponse Get user info
get_access_key() str Get access key
get_storage_info() ProfileStorageInfoResponse Get storage credentials
add_key(request) UserPubKeyRequest bool Add SSH public key
list_keys() List[UserPubKey] List SSH public keys

Example:

# Get user info
user = client.profile.get_user_info()
print(f"User: {user.username}")

# Get storage info
storage_info = client.profile.get_storage_info()
print(f"Used: {storage_info.human_used_size} / Total: {storage_info.human_total_size}")

# SSH key management
from pyromind_sdk.client.models import UserPubKeyRequest

client.profile.add_key(UserPubKeyRequest(key="ssh-ed25519 AAAA..."))
keys = client.profile.list_keys()

Async Support

All services have async counterparts via PyroMindAsyncAPIClient:

from pyromind_sdk import PyroMindAsyncAPIClient

async with PyroMindAsyncAPIClient(api_key="your-api-key") as client:
    tasks = await client.studio.list()
    task = await client.studio.create(request)

Async clients (same method set as sync):

  • client.studioAsyncStudioClient
  • client.instancesAsyncJupyterLabClient
  • client.inferenceAsyncInferenceClient
  • client.echomindAsyncEchoMindClient

Error Handling

All API calls raise PyroMindAPIError (sync) or PyroMindAsyncAPIError (async) on failure:

from pyromind_sdk.client.base import PyroMindAPIError

try:
    task = client.studio.get_task("invalid-id")
except PyroMindAPIError as e:
    print(f"Error {e.status_code}: {e.message}")
    if e.response:
        print(f"Response: {e.response}")
Attribute Type Description
message str Error description
status_code Optional[int] HTTP status code
response Optional[Dict] API error response body

Key Response Models

Each service returns structured Pydantic model objects. Key fields:

TrainingTaskResponse (Studio)

Field Type Description
task_id str Task unique ID
name str Task name
status str Current status (running, completed, failed, etc.)
workflow Dict Workflow configuration
nodes List[TrainingTaskNodeInfo] Node execution details
error_message Optional[str] Error info if failed
created_at datetime Creation timestamp

JupyterResponse (Jupyter)

Field Type Description
id str Instance ID
name str Instance name
status str Current status
url Optional[str] Jupyter URL
password Optional[str] Access password

InferenceJobResponse (Inference)

Field Type Description
id str Job ID
name str Job name
model_path str Model path
status str Current status
endpoint_url Optional[str] Inference endpoint
resources Optional[ResourceConfig] Allocated resources

EchoMindJobResponse (EchoMind)

Field Type Description
id str Instance ID
name str Instance name
status str Current status

Workflow Validation & Conversion

The client/workflow/ module provides workflow validation and format conversion:

from pyromind_sdk.client import validate_workflow, ValidationError

# Validate a workflow structure
try:
    validate_workflow(workflow_dict)
    print("Workflow is valid")
except ValidationError as e:
    print(f"Invalid workflow: {e}")
Tool Description
validate_workflow(workflow) Validate workflow JSON structure
ValidationError Raised on invalid workflow
converter.py Convert between workflow formats

CLI Tools

Command Description
python -m pyromind_sdk.cli SDK CLI (various utilities)
python -m pyromind_sdk.python_function_to_yaml_cli Convert Python function → YAML node definition

Custom Node SDK

Beyond YAML definitions, the SDK provides programmatic node creation tools:

Wrap a Python function as a custom node:

from pyromind_sdk.nodes.function_call_wrapper import create_node_from_function

# Decorate any function to become a node definition
@create_node_from_function(
    name="my_custom_node",
    description="Processes input data",
    category="data-processing"
)
def process_data(input_text: str, threshold: float = 0.5) -> dict:
    # Your logic here
    return {"result": "processed", "value": len(input_text)}

Execute Python functions as nodes at runtime:

from pyromind_sdk.nodes.python_function_executor import execute_python_node

result = execute_python_node(
    source_code="print('hello')",
    node_type="python"
)

Convert Python functions to YAML config:

from pyromind_sdk.nodes.python_to_yaml import python_function_to_yaml_config

def my_func(input: str) -> str:
    return input.upper()

yaml_config = python_function_to_yaml_config(my_func)
# yaml_config can be saved to a .yaml file and registered via studio.create_node()

Validate and load YAML node definitions:

from pyromind_sdk.nodes.yaml_loader import load_yaml_node
from pyromind_sdk.nodes.node_validator import validate_node_config

node_config = load_yaml_node("path/to/node.yaml")
validate_node_config(node_config)

Testing

pytest

Examples

Example Description
api_client_basic.py Basic client setup
studio_example.py Studio task CRUD + node output
studio_monitor.py Monitor task status in a loop
workflow_cli.py CLI tool for workflow management
complete_workflow_example.py End-to-end workflow demo
jupyter_instance_example.py Jupyter instance CRUD
inference_example.py Inference job management
echomind_example.py EchoMind lifecycle
storage_example.py File upload/download
release_all_instance.py Bulk release resources
async_training_example.py Async studio training
async_inference_example.py Async inference
async_echomind_example.py Async EchoMind
async_jupyter_instance_example.py Async Jupyter

Development

Install from source

git clone https://github.com/pyromind/pyromind-sdk.git
cd pyromind-sdk
pip install -e .

Download files

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

Source Distribution

pyromind_sdk-0.1.10.tar.gz (290.0 kB view details)

Uploaded Source

Built Distribution

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

pyromind_sdk-0.1.10-py3-none-any.whl (315.0 kB view details)

Uploaded Python 3

File details

Details for the file pyromind_sdk-0.1.10.tar.gz.

File metadata

  • Download URL: pyromind_sdk-0.1.10.tar.gz
  • Upload date:
  • Size: 290.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for pyromind_sdk-0.1.10.tar.gz
Algorithm Hash digest
SHA256 6c6686ec578f2d06c9c640eaef38d06c1d55efdc9c11be8ee094e2adb762e1fd
MD5 5e39f7731da7b8ec78b9cfa8a208d539
BLAKE2b-256 0dbb08c2ab31d709c3bda1e951dd1ce5a9cc824f74009c1a68e0d240c0dc499d

See more details on using hashes here.

File details

Details for the file pyromind_sdk-0.1.10-py3-none-any.whl.

File metadata

  • Download URL: pyromind_sdk-0.1.10-py3-none-any.whl
  • Upload date:
  • Size: 315.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for pyromind_sdk-0.1.10-py3-none-any.whl
Algorithm Hash digest
SHA256 952ee6c19fcf0e90095e57c99f0d9e5e20b01914f15d4b3d3c1a5c7491cd1a75
MD5 09b9cba0c3209e521cd55a2d0bef2fae
BLAKE2b-256 1bf5c067f5a83aecdc3fc53e8f9c2daceeff6b9d9b6e3b2ee9c9edee35ebe2c9

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.10 This release

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.0.26

2 files

0.0.25

2 files

0.0.24

1 file

0.0.21

1 file

0.0.17

1 file

0.0.16

1 file

0.0.12

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page