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_instances: 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) -> CreatedWorkspace
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_instances(bool | None, optional):Trueruns the workspace on spot capacity (cheaper, may be reclaimed).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
CreatedWorkspace: The new workspace's id; read it withretrieve.
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) -> None
Change a workspace's name, description, services or environment variables.
Only the fields you give change; read the result back with
retrieve. 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) -> WorkspaceAction
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
WorkspaceAction: What happened, inmessage.
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) -> WorkspaceAction
Stop a workspace. Its volumes keep their data.
Parameters
workspace_id(str): The workspace's id.
Returns
WorkspaceAction: What happened, inmessage; the status is thenstopped.
Raises
NotFoundError: There is no such workspace.
restart
restart(workspace_id: str) -> None
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.
Other
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).
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.