The SDK is
@distilled/agent-sdk. It is in private preview and not yet on npm; ask us for access. Everything it does is also available over REST.The client covers phones, control, apps, skills, runs, secrets, usage and egress. Allocating and managing phones, proxies and billing are REST only for now. It retries 429, 502, 503 and 504, waiting as long as Retry-After asks. Every retry of an action on a phone reuses one idempotency key, so the node plays each action at most once. Every POST gets an idempotency key, and keys never appear in its error messages.
first-phone.ts
import { DistilledClient } from "@distilled/agent-sdk"
const distilled = new DistilledClient({ apiKey: process.env.DISTILLED_KEY! })
// Drive a phone yourself.
const [phone] = await distilled.phones.list()
const control = distilled.phones.control(phone.id)
await control.launchApp("com.android.settings")
const screen = await control.screenshot()
// Or hand a task to a run, and wait for it to end.
const run = await distilled.runs.start({ skill: "sk_2hq8", phones: [phone.id] })
const finished = await distilled.runs.wait(run.id)
console.log(finished.state)| Area | Methods |
|---|---|
| Client | me(), usage(range), egress({ period }) |
phones | list(), get(id), control(id) |
control(id) | observe, screenshot, uiTree, waitForIdle, tap, longPress, swipe, type, key, launchApp, openUrl, act, location, setLocation, lease, release |
apps | search(query), get(pkg), install(phoneId, pkg), installs(phoneId) |
skills | list(), get(id), create(definition), update(id, definition), setEnabled(id, enabled), delete(id) |
runs | start, list, get, stop, resume, steps, stepScreenshot, wait, watch |
secrets | list(), put(name, value), delete(name) |
Failures are thrown as DistilledError, with the HTTP status, the error code, its detail and whether it is retryable.