Skip to content

AuraClient

Async client for the Strangeworks Aura public /api/v1 surface.

Authenticates with a company API key (sk-aura-…). Every method is a coroutine; there is no synchronous variant. chat follows a turn live over the project WebSocket and falls back to polling when the socket cannot be held open, hiding both behind a single await.

Owns HTTP connections, so use it as an async context manager, or call aclose:

async with AuraClient(api_key=key) as aura:
project = await aura.create_project(name="demo", from_deployment="acme/vrp")
Parameter Type Default Description
api_key str A company API key, minted in Company settings → API keys.
base_url str DEFAULT_BASE_URL Root of the Aura deployment. Defaults to production; point it at http://localhost:3000 for a local just dev stack.
timeout float DEFAULT_TIMEOUT Per-request HTTP timeout in seconds. This bounds one call, not a whole agent turn — see chat’s own timeout.
transport httpx.AsyncBaseTransport | None None Optional httpx transport, for tests that serve responses in-process instead of over the network.
websocket_factory WebSocketFactory default_websocket_factory Opens the project event socket; tests pass a scripted fake.
async def aclose() -> None

Close the underlying HTTP connections.

async def create_deployment(name: str) -> DeploymentResponse

Create an empty deployment for your company.

Parameter Type Default Description
name str Deployment name, unique within the company.

The created deployment.

Exception When
AuraApiError The name is invalid or already taken.
async def list_deployments() -> list[DeploymentResponse]

List every deployment your company owns, following pagination.

All deployments, in server order.

async def get_deployment(name: str) -> DeploymentResponse

Fetch one deployment by name.

Parameter Type Default Description
name str The deployment’s name.

The deployment.

Exception When
AuraApiError No such deployment.
async def delete_deployment(name: str) -> DeploymentDeleteResponse

Delete a deployment: purge its files and free its name for reuse.

Irreversible — there is no undelete, and a new deployment claiming the same name starts empty. Projects already seeded from this deployment keep their own copy of the workspace and are left alone.

Requires an admin, which every API key satisfies.

Parameter Type Default Description
name str The deployment’s name.

The handle, how many files were purged, and how many projects had been seeded from it.

Exception When
AuraApiError No such deployment.
async def check_deployment(name: str) -> DeploymentCheckResponse

Ask the server whether a deployment satisfies the run contract.

Parameter Type Default Description
name str The deployment’s name.

ok, plus the missing paths and warnings behind that verdict.

async def upload_file(container: FileContainer, path: str, body: bytes | str, content_type: str) -> FileEntry

Upload one file to a container.

Three steps behind one await: plan the upload, PUT the bytes to the URL the plan names, then complete it. The byte PUT carries only the plan’s own headers, never your API key.

Parameter Type Default Description
container FileContainer Which files to write to. A SnapshotFiles is rejected server-side; a snapshot is immutable by design.
path str Destination path within the container, e.g. run/solve.py.
body bytes | str File contents. A str is encoded as UTF-8.
content_type str MIME type recorded for the file.

The stored file’s entry.

Exception When
AuraApiError The plan, the byte upload, or the completion failed, or the server planned a multipart upload, which this SDK does not implement.
async def list_files(container: FileContainer, path_prefix: str | None = None) -> list[FileEntry]

List a container’s files, following pagination.

Parameter Type Default Description
container FileContainer Which files to list.
path_prefix str | None None Restrict the listing to paths under this prefix.

All matching file entries.

async def read_file(container: FileContainer, path: str) -> FileContentResponse

Read one file from a container.

Parameter Type Default Description
container FileContainer Which files to read from. SnapshotFiles reads a run’s frozen copy, which later runs cannot have overwritten.
path str The file’s path, e.g. solutions/out.json for a run’s solution.

The file’s contents: text for text files, base64 for binary ones.

Exception When
AuraApiError No such file in that container.
async def delete_file(container: FileContainer, path: str) -> DeleteResponse

Delete one file from a container.

Not recursive — pass a file path, not a directory.

Parameter Type Default Description
container FileContainer Which files to delete from. A SnapshotFiles is rejected server-side; a snapshot is immutable by design.
path str The file’s path within the container.

What the server deleted.

async def create_project(name: str, *, from_deployment: str | None = None, short_description: str | None = None, description: str | None = None) -> ProjectResponse

Create a project, optionally seeded from a published deployment.

A project seeded from a deployment lands directly in run mode, so the run agent is usable on it immediately.

Parameter Type Default Description
name str Human-readable project name.
from_deployment str | None None A deployment handle, "<company>/<name>". The wire field is from, which is a reserved word in Python.
short_description str | None None One-line summary.
description str | None None Longer description.

The created project.

Exception When
AuraApiError The deployment handle is unknown or fails its run contract.
async def list_projects() -> list[ProjectSummary]

List your projects, following pagination.

A summary of every project you can see.

async def get_project(project_id: str) -> ProjectResponse

Fetch one project.

Parameter Type Default Description
project_id str The project’s id.

The project.

Exception When
AuraApiError No such project, or it is not yours.
async def delete_project(project_id: str) -> None

Delete a project and everything in it.

Parameter Type Default Description
project_id str The project’s id.
Exception When
AuraApiError No such project, or it is not yours.
async def list_conversations(project_id: str) -> list[ConversationResponse]

List a project’s conversations, following pagination.

Parameter Type Default Description
project_id str The project’s id.

All conversations in the project.

async def create_conversation(project_id: str, title: str | None = None) -> ConversationResponse

Start a new conversation in a project.

Parameter Type Default Description
project_id str The project’s id.
title str | None None Optional title; the server names it otherwise.

The created conversation.

async def delete_conversation(project_id: str, conversation_id: str) -> None

Delete one conversation.

Parameter Type Default Description
project_id str The project’s id.
conversation_id str The conversation’s id.
Exception When
AuraApiError No such conversation in that project.
async def send_message(project_id: str, content: str, *, conversation_id: str | None = None, client_msg_id: str | None = None) -> ChatResponse

Dispatch a message without waiting for the agent’s reply.

Use this when you want to poll get_conversation_state yourself; chat is the one-await version.

Parameter Type Default Description
project_id str The project’s id.
content str The message text.
conversation_id str | None None Target conversation. Defaults to the project’s active one.
client_msg_id str | None None Your own idempotency key for the dispatch.

The dispatch result, including the stored user message and its sequence.

async def get_conversation_state(project_id: str, conversation_id: str | None = None) -> ConversationSyncResponse

Read an atomic snapshot of a conversation: its messages plus turn state.

Parameter Type Default Description
project_id str The project’s id.
conversation_id str | None None Which conversation. Defaults to the project’s active one at the time of the call.

The messages the server has stored and whether a turn is in flight.

async def chat(project_id: str, content: str, *, conversation_id: str | None = None, client_msg_id: str | None = None, poll_interval: float = DEFAULT_POLL_INTERVAL, timeout: float = DEFAULT_TURN_TIMEOUT, on_delta: Callable[[str], None] | None = None, on_tool_activity: Callable[[ToolActivityData], None] | None = None) -> ChatMessageResponse

Send a message and wait for the agent’s reply, following the turn live.

The turn is followed over the project WebSocket, so the wait is event-driven — turn-end comes from the authoritative stream_end rather than from polling — and on_delta / on_tool_activity see the turn as it happens. When the socket cannot be opened, or dies mid-turn, this degrades silently to polling /chat/sync: the reply is unaffected, only the callbacks stop.

The returned message always comes from a /chat/sync reconcile, never from the accumulated deltas. Deltas carry no sequence numbers, so a dropped frame is undetectable; the stream is liveness and the stored row is truth.

On the polling path the reply is the first assistant message whose sequence exceeds the dispatched one, accepted only once the turn reads idle and the message is unchanged across two reads. Comparing sequences rather than counting messages is what makes the wait attributable to this caller, and immune to the newest-N window /chat/sync returns.

The wait is pinned to the conversation the dispatch resolved to, so creating or activating another conversation mid-turn cannot redirect it.

Cancelling the task awaiting this coroutine raises asyncio.CancelledError as usual and stops only the waiting — the turn keeps running server-side. Call cancel to stop the turn itself.

Parameter Type Default Description
project_id str The project’s id.
content str The message text.
conversation_id str | None None Target conversation. Defaults to the project’s active one.
client_msg_id str | None None Your own idempotency key for the dispatch.
poll_interval float DEFAULT_POLL_INTERVAL Seconds between polls, on the fallback path.
timeout float DEFAULT_TURN_TIMEOUT Seconds to wait before giving up.
on_delta Callable[[str], None] | None None Called with each chunk of assistant text, in order.
on_tool_activity Callable[[ToolActivityData], None] | None None Called for each tool start, completion, or failure.

The agent’s completed reply.

Exception When
AuraTurnCancelledError The turn stopped before finishing, so the reply is partial. partial_content carries what the agent managed.
AuraTurnTimeoutError timeout elapsed. The turn is still running server-side; conversation_id is what to pass to cancel.
AuraApiError A call failed, or the turn died before streaming.
AuraResponseError The turn finished but its reply was not in the sync window.
async def cancel(project_id: str, conversation_id: str | None = None) -> bool

Stop a running agent turn.

Parameter Type Default Description
project_id str The project’s id.
conversation_id str | None None Restrict cancellation to this conversation. Without it, any running turn in the project is cancelled.

Whether anything was actually cancelled.

async def get_agent_status(project_id: str) -> AgentStatusResponse

Report whether a turn is in flight, without inferring it from messages.

Parameter Type Default Description
project_id str The project’s id.

The project’s current agent status.

async def list_executions(project_id: str) -> list[ExecutionResponse]

List the project’s solve executions, most recent first.

Parameter Type Default Description
project_id str The project’s id.

Every execution, following pagination.

async def get_execution(project_id: str, execution_id: str) -> ExecutionResponse

Fetch one solve execution.

Parameter Type Default Description
project_id str The project’s id.
execution_id str The execution’s id.

The execution, including its status and timing.

async def list_snapshots(project_id: str) -> list[SnapshotResponse]

List a project’s snapshots, following pagination.

Parameter Type Default Description
project_id str The project’s id.

Every snapshot taken in the project.

async def get_snapshot(project_id: str, ref: str) -> SnapshotDetailResponse

Fetch one snapshot, including its file list.

Parameter Type Default Description
project_id str The project’s id.
ref str A snapshot id or a tag name.

The snapshot and its files.

async def list_tags(project_id: str) -> list[SnapshotTagResponse]

List a project’s snapshot tags, following pagination.

Parameter Type Default Description
project_id str The project’s id.

Every tag and the snapshot it points at.

async def set_tag(project_id: str, name: str, snapshot_id: str) -> SnapshotTagResponse

Point a tag at a snapshot, creating or moving it.

Parameter Type Default Description
project_id str The project’s id.
name str The tag name.
snapshot_id str The snapshot the tag should name.

The tag as stored.

async def checkout(project_id: str, source: str, conversation_id: str | None = None) -> WorkspaceBasisResponse

Reset the project’s workspace to a deployment or snapshot.

The server dispatches on source’s segment count: one segment is a snapshot id or tag name, two is a <group>/<name> deployment handle, three is a <group>/<project>/<name> in-project snapshot tag.

Parameter Type Default Description
project_id str The project’s id.
source str What to check out, as described above.
conversation_id str | None None Conversation to attribute the checkout to.

The workspace’s new basis.

Exception When
AuraApiError source does not resolve to anything checkout-able.