Workspaces
Create, run and manage workspaces: IDEs running in their own containers.
Access it as client.workspaces on a Strongly client, or the same path on AsyncStrongly with await. All methods exist on both with identical signatures.
Quick start
from strongly import Strongly
client = Strongly()
# List (auto-paginates as you iterate) # filters: search, status, project_id, sort
for workspace in client.workspaces.list():
print(workspace.id)
Methods
Core
list
list(*, search: str | None = None, status: str | None = None, project_id: str | None = None, sort: str | None = None, limit: int | None = None) -> SyncPaginator[Workspace]
List the workspaces you can use, newest first.
Parameters
search(str | None, optional): Only workspaces whose name or description contains this text (case insensitive).status(str | None, optional): Only workspaces with this status, such as"running".project_id(str | None, optional): Only the workspaces of this project.sort(str | None, optional): The order, as comma-separated wire field names, each prefixed with-for descending (for example"name"). The API's default is"-createdAt".limit(int | None, optional): The most workspaces to return;Nonereturns every one.
Returns
SyncPaginator[Workspace]: The workspaces, fetched a page at a time.
create
create(*, name: str, description: str, environment_type: str, environment_id: str | None = None, environment_version: int | None = None, custom_resources: Mapping[str, Any] | None = None, workspace_volume_size: str | None = None, project_id: str | None = None, use_spot: bool | None = None, spot_fallback: bool | None = None, environment_variables: Mapping[str, str] | None = None, addons: Sequence[str] | None = None, data_sources: Sequence[str] | None = None, ai_gateways: Sequence[str] | None = None, workflows: Sequence[str] | None = None, skill_ids: Sequence[str] | None = None, shared_volume_ids: Sequence[str] | None = None, coding_assistants: Sequence[str] | None = None, code_session_enabled: bool | None = None, custom_port: int | None = None, proxy_headers: Sequence[Mapping[str, str]] | None = None, cluster: Mapping[str, Any] | None = None) -> Workspace
Create a workspace, stopped. Start it with start.
The workspace runs at exactly the size you set and none is assumed: give
environment_id (a saved environment supplies the image and size) or
custom_resources.
Parameters
name(str): The workspace's name.description(str): What the workspace is for.environment_type(str): The IDE:"jupyter","vscode","rstudio"or"custom"(the environment image runs its own IDE oncustom_port).environment_id(str | None, optional): A saved environment (image and size).environment_version(int | None, optional): A version of that environment. The API's default is the latest.custom_resources(Mapping[str, Any] | None, optional): The size when no environment is chosen, such as{"cpu": "2", "memory": "8GB", "disk": "20GB"}(optionally"gpu"and"gpu_type");diskis scratch space. At least 0.1 CPU and 128MB of memory.workspace_volume_size(str | None, optional): The size of the persistent/workspacevolume, such as"40GB". The API's default is"20GB".project_id(str | None, optional): The project the workspace belongs to; it mounts the project's volume. The API's default creates a project named after the workspace.use_spot(bool | None, optional):Trueruns the workspace on spot capacity (cheaper; it can be reclaimed, and the workspace restarts on a new node with its volumes kept).spot_fallback(bool | None, optional): Withuse_spot:True(the API's default) falls back to on-demand capacity when no spot is available;Falsewaits for spot.environment_variables(Mapping[str, str] | None, optional): Environment variables for the container.addons(Sequence[str] | None, optional): Add-on ids to attach (delivered inSTRONGLY_SERVICES).data_sources(Sequence[str] | None, optional): Data source ids to attach (delivered inSTRONGLY_DATA_SOURCES).ai_gateways(Sequence[str] | None, optional): AI model ids to make available.workflows(Sequence[str] | None, optional): Workflow ids to make available.skill_ids(Sequence[str] | None, optional): Skill ids to install in the workspace.shared_volume_ids(Sequence[str] | None, optional): The shared volumes to mount at/volumes/shared/<name>; none unless listed (the project's volume always mounts). A volume you may not mount is refused, by name.coding_assistants(Sequence[str] | None, optional): The coding assistant to install: at most one of"claude-code","codex"and"opencode"(not for RStudio or a custom IDE).code_session_enabled(bool | None, optional):Trueadds a terminal an agent can drive.custom_port(int | None, optional): For a custom IDE: the port it serves on. The API's default is 8888.proxy_headers(Sequence[Mapping[str, str]] | None, optional): For a custom IDE: headers the proxy forwards to it, each{"name": ..., "value": ...}; values may use${BASE_PATH},${ORIGIN},${PATH}and${REQUEST_URI}.cluster(Mapping[str, Any] | None, optional): A Ray, Dask or Spark cluster to attach, such as{"engine": "ray", "coordinator": {"cpu": "2", "memory": "4GB"}, "worker": {"cpu": "2", "memory": "4GB"}, "workers": 2}.
Returns
Workspace: The new workspace,stopped, asretrieveshows it.
Raises
ValidationError: A required field is missing, or no size was given.NotFoundError: The project or environment does not exist.PermissionDeniedError: You may not add workspaces to the project.ConflictError: Noproject_idwas given and a project or volume already has the workspace's name (error_codeduplicate).
retrieve
retrieve(workspace_id: str) -> Workspace
Retrieve a workspace you can use.
Parameters
workspace_id(str): The workspace's id.
Returns
Workspace: The workspace.
Raises
NotFoundError: There is no such workspace, or you cannot use it.
update
update(workspace_id: str, *, name: str | None = None, description: str | None = None, environment_variables: Mapping[str, str] | None = None, addons: Sequence[str] | None = None, data_sources: Sequence[str] | None = None, ai_gateways: Sequence[str] | None = None, workflows: Sequence[str] | None = None, shared_volume_ids: Sequence[str] | None = None) -> Workspace
Change a workspace's name, description, services or environment variables.
Only the fields you give change; returns the workspace, as
retrieve shows it. The size, image, IDE and environment are fixed at
create. Services apply at the next start or restart.
Parameters
workspace_id(str): The workspace's id.name(str | None, optional): The workspace's name.description(str | None, optional): Its description.environment_variables(Mapping[str, str] | None, optional): Environment variables, replacing the current set. Only before the first start, or while the workspace is inerror.addons(Sequence[str] | None, optional): The add-on ids it selects, replacing the list.data_sources(Sequence[str] | None, optional): The data source ids it selects, replacing the list.ai_gateways(Sequence[str] | None, optional): The AI model ids it selects, replacing the list.workflows(Sequence[str] | None, optional): The workflow ids it selects, replacing the list.shared_volume_ids(Sequence[str] | None, optional): The shared volumes it mounts at/volumes/shared/<name>from its next start or restart, replacing the list ([]for none).
Raises
NotFoundError: There is no such workspace, or you may not change it.ConflictError:environment_variableson a deployed workspace (error_codeinvalid-state).ValidationError: A value is invalid (a blank name, a repeated id).
delete
delete(workspace_id: str) -> None
Delete a workspace.
The workspace moves to pending_delete and is removed once its
container is gone.
Parameters
workspace_id(str): The workspace's id.
Raises
NotFoundError: There is no such workspace.PermissionDeniedError: You may not delete it.
Lifecycle & actions
start
start(workspace_id: str) -> Workspace
Start a workspace.
Returns as soon as the start is accepted; the status moves through
deploying and starting to running (or error). Poll
retrieve or status. Starting a running or starting
workspace changes nothing.
Parameters
workspace_id(str): The workspace's id.
Returns
Workspace: The workspace, asretrieveshows it, with itsstatusnow.
Raises
NotFoundError: There is no such workspace, or you may not start it.PaymentRequiredError: A budget or the organization's credits refuse the start.PermissionDeniedError: A governance policy blocks the workspace.
stop
stop(workspace_id: str) -> Workspace
Stop a workspace. Its volumes keep their data.
Parameters
workspace_id(str): The workspace's id.
Returns
Workspace: The workspace, asretrieveshows it,stopped.
Raises
NotFoundError: There is no such workspace.
restart
restart(workspace_id: str) -> Workspace
Restart a started workspace, redeploying it (its owner only).
Parameters
workspace_id(str): The workspace's id.
Raises
UnprocessableEntityError: The workspace has never been started (usestart).PermissionDeniedError: You are not the workspace's owner.
execute
execute(workspace_id: str, command: str, *, cwd: str | None = None) -> dict[str, Any]
Run a shell command in a running workspace until it exits.
Returns {stdout, stderr, exit_code}.
Parameters
workspace_id(str): The workspace's id.command(str): The command, run by a shell.cwd(str | None, optional): The directory to run it in.
Other
abort_sync
abort_sync(workspace_id: str, *, volume_id: str) -> dict[str, Any]
Cancel a volume's merge in a workspace, keeping its work as it was.
Parameters
workspace_id(str): The workspace's id.volume_id(str): The volume whose merge to cancel.
add_port
add_port(workspace_id: str, port: int, *, label: str | None = None) -> dict[str, Any]
Save a labeled link to a port of the workspace: {port, label, url}.
Parameters
workspace_id(str): The workspace's id.port(int): The port the app listens on (1024 to 65535).label(str | None, optional): The link's label.
deletion_impact
deletion_impact(workspace_id: str) -> dict[str, Any]
Say whether a workspace can be deleted, and what the delete removes.
Parameters
workspace_id(str): The workspace's id.
logs
logs(workspace_id: str, *, type: str | None = None) -> list[WorkspaceLogEntry]
Return a workspace's latest log lines (up to 100).
Parameters
workspace_id(str): The workspace's id.type(str | None, optional): Which logs:"pod"(the IDE's own runtime log, the API's default),"build"or"deploy".
Returns
list[WorkspaceLogEntry]: The log lines.
metrics
metrics(workspace_id: str) -> WorkspaceMetrics
Measure a running workspace now (about 6 seconds).
Parameters
workspace_id(str): The workspace's id.
Returns
WorkspaceMetrics: CPU and memory against its size, disk, network, GPU, IDE response time, and every container's usage.
Raises
ConflictError: The workspace is not running (error_codeinvalid-state).
minimum_size
minimum_size() -> dict[str, Any]
Get the smallest size a workspace (and a cluster coordinator) can have.
planned_volumes
planned_volumes(*, project_id: str, shared_volume_ids: Sequence[str] | None = None) -> dict[str, Any]
List the volumes a new workspace in a project would mount.
Parameters
project_id(str): The project the workspace would be in.shared_volume_ids(Sequence[str] | None, optional): Shared volumes it would mount besides the project's.
remove_port
remove_port(workspace_id: str, port: int) -> None
Remove a saved port link; the app keeps running.
Parameters
workspace_id(str): The workspace's id.port(int): The link's port.
resolve_sync_conflict
resolve_sync_conflict(workspace_id: str, *, volume_id: str, path: str, take: str) -> dict[str, Any]
Decide one conflicted file of a workspace's Sync.
Parameters
workspace_id(str): The workspace's id.volume_id(str): The volume the file is in.path(str): The file's path in the volume.take(str):mine(the workspace's copy) ortheirs(the volume's).
status
status(workspace_id: str) -> WorkspaceStatus
Ask the cluster for a workspace's status now.
Parameters
workspace_id(str): The workspace's id.
Returns
WorkspaceStatus: The status, the IDE's path and any error.
Raises
NotFoundError: There is no such workspace.
sync
sync(workspace_id: str) -> WorkspaceSync
Save a running workspace's work to its volumes (its owner only).
The project volume's code is committed and pushed (a shared volume's code is read-only and never pushed), and each data file changed in a volume the owner may write is saved as a new version of that file. Unsynced work survives stop, start and restart; only deleting the workspace loses it.
Parameters
workspace_id(str): The workspace's id.
Returns
WorkspaceSync: Each volume's sync report.
Raises
PermissionDeniedError: You are not the workspace's owner.
sync_conflicts
sync_conflicts(workspace_id: str) -> dict[str, Any]
List the files a workspace still has to decide after a Sync conflict.
Parameters
workspace_id(str): The workspace's id.
volumes
volumes(workspace_id: str, *, group: str, q: str | None = None, sort: str | None = None) -> SyncPaginator[WorkspaceMount]
List a workspace's mounted volumes.
Parameters
workspace_id(str): The workspace's id.group(str):project(the project's volume) orshared.q(str | None, optional): Only volumes whose name contains this text.sort(str | None, optional):name,createdAtorupdatedAt; a leading-sorts descending.