Conventions
These hold everywhere in the SDK.
Every list* reads all pages
Section titled “Every list* reads all pages”A list* method returns the whole collection, not the server’s first page — it keeps reading
until it has everything, adopting whatever page size the server honoured.
const projects = await aura.listProjects(); // all of themconst files = await aura.listFiles({ source: "workspace", projectId }); // all of themThis avoids a class of silent bug: deploy prunes remote files by diffing a listing, so a short
read would delete files that are still there. The cost is that a large collection takes several
round-trips inside one await.
Types are generated, not hand-written
Section titled “Types are generated, not hand-written”Request and response types come from the backend’s OpenAPI spec, filtered to the public /api/v1
surface, and are re-exported by name:
import type { Project, Execution, Snapshot, FileEntry } from "@strangeworks-inc/strangeworks-aura-sdk";Because they are generated, a response type is exactly what the server sends. The REST reference documents what is inside each one; the API reference documents the methods that return them.
Five error types, one base
Section titled “Five error types, one base”AuraApiError (the call was rejected), AuraConnectionError (nothing answered),
AuraResponseError (the answer was unreadable), AuraTurnCancelledError (a turn stopped early)
and AuraTurnTimeoutError (your wait elapsed) all extend AuraError, so one catch covers
everything and instanceof tells them apart. Errors has the detail.
A deployment is named, a reference is a handle
Section titled “A deployment is named, a reference is a handle”Methods acting on a deployment (getDeployment, listDeploymentSkills, …) take the bare name —
your key already says which company, and the REST path cannot carry a /. Methods pointing at
one from elsewhere (createProject’s fromDeployment, checkout, pullAgentConfig)
take the <company>/<name> handle, and pullAgentConfig accepts either.
A list is filenames, a get is bodies
Section titled “A list is filenames, a get is bodies”listProjectSkills and its deployment twin carry each skill’s name, description and filenames — enough to
say what is in force without shipping every byte of all of them. getProjectSkill returns one
skill’s file contents.
Snapshots are the only container writes can’t reach
Section titled “Snapshots are the only container writes can’t reach”uploadFile / deleteFile write through the same FileContainer you already pass to listFiles
/ readFile: a workspace or deployment container accepts the write, a snapshot container
rejects it — a run’s captured state has to stay retrievable. Prefer asking the agent in a turn to
change a project’s inputs; reach for these methods directly for out-of-band writes, like staging a
dashboard file. See File containers for when to use which
container.
Two things a workspace write asks of you that a deployment write does not. The path must name a
directory (data/orders.csv, not orders.csv), which uploadFile refuses locally rather than
letting the server explain it. And a project has an agent that may already have read the file, so
both methods take an optional conversationId: pass it and the change announces itself, so the
agent re-reads on its next turn; omit it and the write is silent.
await aura.uploadFile( { source: "workspace", projectId }, "data/orders.csv", bytes, contentTypeForPath("data/orders.csv"), conversationId, // omit to write without telling the agent);contentTypeForPath is exported so a single-file upload records the same type deployFromFolder
would; zipUrl(container, path?) returns a single-use URL for the container (or one subtree) as a
zip — fetch it once, without your API key.
The *Instructions and *Skill methods are the one thing that writes without a turn, and they are
not an exception to this: agent config is stored outside the
workspace, which is exactly why the agent cannot edit the rules it operates under.