diff --git a/docs/docs.json b/docs/docs.json index bbb0664b..53dff4c4 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -118,7 +118,7 @@ ] }, { - "tab": "Python SDK", + "tab": "SDKs", "groups": [ { "group": "Python SDK", @@ -133,6 +133,21 @@ "sdk-reference/error-handling", "sdk-reference/complete-reference" ] + }, + { + "group": "TypeScript SDK", + "pages": [ + "ts-sdk-reference/overview", + "ts-sdk-reference/tasks", + "ts-sdk-reference/workflows", + "ts-sdk-reference/browser-sessions", + "ts-sdk-reference/browser-profiles", + "ts-sdk-reference/credentials", + "ts-sdk-reference/helpers", + "ts-sdk-reference/browser-automation", + "ts-sdk-reference/error-handling", + "ts-sdk-reference/complete-reference" + ] } ] }, diff --git a/docs/ts-sdk-reference/browser-automation.mdx b/docs/ts-sdk-reference/browser-automation.mdx new file mode 100644 index 00000000..23c75078 --- /dev/null +++ b/docs/ts-sdk-reference/browser-automation.mdx @@ -0,0 +1,403 @@ +--- +title: Browser Automation +subtitle: Control cloud browsers with Playwright + AI +slug: ts-sdk-reference/browser-automation +--- + +The TypeScript SDK extends Playwright with AI-powered browser automation. Launch a cloud browser, get a page that works like a normal Playwright `Page`, then use `.agent` for full-task AI execution or AI-enhanced versions of `click`, `fill`, and `selectOption` that fall back to natural language when selectors fail. + +--- + +## Launch a cloud browser + +### `launchCloudBrowser` + +Create a new cloud-hosted browser session and connect to it. + +```typescript +const browser = await skyvern.launchCloudBrowser(); +const page = await browser.getWorkingPage(); + +// Use Playwright methods +await page.goto("https://example.com"); + +// Or use AI +await page.agent.runTask("Fill out the contact form and submit it"); + +await browser.close(); +``` + +#### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `timeout` | `number` | No | `60` | Session timeout in minutes (5–1440). | +| `proxyLocation` | `ProxyLocation` | No | `undefined` | Geographic proxy location for browser traffic. | + +#### Returns `SkyvernBrowser` + + +Cloud browser sessions are only available with `SkyvernEnvironment.Cloud` or `SkyvernEnvironment.Staging`. + + +--- + +### `useCloudBrowser` + +Get or create a cloud browser session. Reuses the most recent available session if one exists, otherwise creates a new one. + +```typescript +const browser = await skyvern.useCloudBrowser(); +const page = await browser.getWorkingPage(); +``` + +#### Parameters + +Same as `launchCloudBrowser`. Options are only used when creating a new session. + +#### Returns `SkyvernBrowser` + +--- + +### `connectToCloudBrowserSession` + +Connect to an existing cloud browser session by ID. + +```typescript +const browser = await skyvern.connectToCloudBrowserSession("pbs_abc123"); +const page = await browser.getWorkingPage(); +``` + +#### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `browserSessionId` | `string` | Yes | The ID of the cloud browser session. | + +#### Returns `SkyvernBrowser` + +--- + +### `connectToBrowserOverCdp` + +Connect to any browser running with Chrome DevTools Protocol (CDP) enabled, whether local or remote. + +```typescript +const browser = await skyvern.connectToBrowserOverCdp("http://localhost:9222"); +const page = await browser.getWorkingPage(); +``` + +#### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `cdpUrl` | `string` | Yes | The CDP WebSocket URL (e.g., `"http://localhost:9222"`). | + +#### Returns `SkyvernBrowser` + +--- + +## SkyvernBrowser + +A browser context wrapper that provides Skyvern-enabled pages. + +### `getWorkingPage()` + +Get the most recent page or create a new one if none exists. + +```typescript +const page = await browser.getWorkingPage(); +``` + +### `newPage()` + +Create a new page (tab) in the browser context. + +```typescript +const page = await browser.newPage(); +``` + +### `close()` + +Close the browser and release resources. If connected to a cloud session, also closes the session. + +```typescript +await browser.close(); +``` + +--- + +## SkyvernBrowserPage + +A `SkyvernBrowserPage` extends Playwright's `Page` with AI capabilities. Every standard Playwright method (`goto`, `click`, `fill`, `waitForSelector`, etc.) works as-is. Additionally, it provides: + +- **`page.agent`** — AI-powered task execution (full automations) +- **AI-enhanced `click`, `fill`, `selectOption`** — try selectors first, fall back to AI +- **`page.act`, `page.extract`, `page.validate`, `page.prompt`** — single AI actions + +--- + +### AI-enhanced Playwright methods + +These methods extend the standard Playwright API with AI fallback. Pass a CSS selector and it works like normal Playwright. Add a `prompt` option and if the selector fails, AI takes over. + +#### `click` + +```typescript +// Standard Playwright click +await page.click("#submit-button"); + +// AI-powered click (no selector needed) +await page.click({ prompt: "Click the 'Submit' button" }); + +// Selector with AI fallback +await page.click("#submit-button", { prompt: "Click the 'Submit' button" }); +``` + +#### `fill` + +```typescript +// Standard Playwright fill +await page.fill("#email", "user@example.com"); + +// AI-powered fill +await page.fill({ prompt: "Fill 'user@example.com' in the email field" }); + +// Selector with AI fallback +await page.fill("#email", "user@example.com", { + prompt: "Fill the email address field", +}); +``` + +#### `selectOption` + +```typescript +// Standard Playwright select +await page.selectOption("#country", "us"); + +// AI-powered select +await page.selectOption({ prompt: "Select 'United States' from the country dropdown" }); + +// Selector with AI fallback +await page.selectOption("#country", "us", { + prompt: "Select United States from country", +}); +``` + +--- + +### `page.agent` — Full task execution + +The `agent` property provides methods for running complete AI-powered automations within the browser page context. These always wait for completion. + +#### `agent.runTask` + +Run a complete AI task in the context of the current page. + +```typescript +const result = await page.agent.runTask("Fill out the contact form and submit it", { + dataExtractionSchema: { + type: "object", + properties: { + confirmation_number: { type: "string" }, + }, + }, +}); +console.log(result.output); +``` + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `prompt` | `string` | Yes | Natural language task description. | +| `options.engine` | `RunEngine` | No | AI engine to use. | +| `options.url` | `string` | No | URL to navigate to. Defaults to current page URL. | +| `options.dataExtractionSchema` | `Record \| string` | No | JSON schema for output. | +| `options.maxSteps` | `number` | No | Maximum AI steps. | +| `options.timeout` | `number` | No | Max wait time in seconds. Default: `1800`. | +| `options.webhookUrl` | `string` | No | Webhook URL for notifications. | +| `options.totpIdentifier` | `string` | No | TOTP identifier. | +| `options.totpUrl` | `string` | No | TOTP URL. | +| `options.title` | `string` | No | Run display name. | +| `options.errorCodeMapping` | `Record` | No | Custom error code mapping. | +| `options.model` | `Record` | No | LLM model configuration. | + +Returns `TaskRunResponse`. + +#### `agent.login` + +Run a login workflow in the context of the current page. Supports multiple credential providers via overloaded signatures. + +```typescript +// Skyvern credentials +await page.agent.login("skyvern", { + credentialId: "cred_123", +}); + +// Bitwarden +await page.agent.login("bitwarden", { + bitwardenItemId: "item_id", + bitwardenCollectionId: "collection_id", +}); + +// 1Password +await page.agent.login("1password", { + onepasswordVaultId: "vault_id", + onepasswordItemId: "item_id", +}); + +// Azure Vault +await page.agent.login("azure_vault", { + azureVaultName: "vault_name", + azureVaultUsernameKey: "username_key", + azureVaultPasswordKey: "password_key", +}); +``` + +Returns `WorkflowRunResponse`. + +#### `agent.downloadFiles` + +Download files in the context of the current page. + +```typescript +const result = await page.agent.downloadFiles("Download the latest invoice PDF", { + downloadSuffix: ".pdf", + downloadTimeout: 30, +}); +``` + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `prompt` | `string` | Yes | What to download. | +| `options.url` | `string` | No | URL to navigate to. Defaults to current page URL. | +| `options.downloadSuffix` | `string` | No | Expected file extension. | +| `options.downloadTimeout` | `number` | No | Download timeout in seconds. | +| `options.maxStepsPerRun` | `number` | No | Max AI steps. | +| `options.timeout` | `number` | No | Max wait time in seconds. Default: `1800`. | + +Returns `WorkflowRunResponse`. + +#### `agent.runWorkflow` + +Run a pre-defined workflow in the context of the current page. + +```typescript +const result = await page.agent.runWorkflow("wpid_abc123", { + parameters: { company_name: "Acme Corp" }, +}); +console.log(result.output); +``` + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `workflowId` | `string` | Yes | The workflow permanent ID. | +| `options.parameters` | `Record` | No | Workflow input parameters. | +| `options.template` | `boolean` | No | Whether it's a template. | +| `options.title` | `string` | No | Run display name. | +| `options.timeout` | `number` | No | Max wait time in seconds. Default: `1800`. | + +Returns `WorkflowRunResponse`. + +--- + +### Single AI actions + +#### `act` + +Perform a single AI action on the page. + +```typescript +await page.act("Scroll down and click the 'Load More' button"); +``` + +#### `extract` + +Extract structured data from the current page. + +```typescript +const data = await page.extract({ + prompt: "Extract all product names and prices", + schema: { + type: "array", + items: { + type: "object", + properties: { + name: { type: "string" }, + price: { type: "string" }, + }, + }, + }, +}); +console.log(data); +``` + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `prompt` | `string` | Yes | What to extract. | +| `schema` | `Record \| unknown[] \| string` | No | JSON schema for output. | +| `errorCodeMapping` | `Record` | No | Custom error codes. | + +Returns `Record | unknown[] | string | null`. + +#### `validate` + +Validate the current page state with AI. + +```typescript +const isLoggedIn = await page.validate("Check if the user is logged in"); +console.log(isLoggedIn); // true or false +``` + +Returns `boolean`. + +#### `prompt` + +Send a prompt to the LLM and get a structured response. + +```typescript +const result = await page.prompt( + "What is the main heading on this page?", + { heading: { type: "string" } }, +); +console.log(result); +``` + +Returns `Record | unknown[] | string | null`. + +--- + +## Complete example + +```typescript +import { Skyvern } from "@skyvern/client"; + +const skyvern = new Skyvern({ apiKey: "YOUR_API_KEY" }); +const browser = await skyvern.launchCloudBrowser(); +const page = await browser.getWorkingPage(); + +// Navigate with Playwright +await page.goto("https://app.example.com"); + +// Login with AI +await page.agent.login("skyvern", { credentialId: "cred_abc123" }); + +// Extract data with AI +const data = await page.extract({ + prompt: "Extract all invoice numbers and amounts from the billing page", + schema: { + type: "array", + items: { + type: "object", + properties: { + invoice_number: { type: "string" }, + amount: { type: "string" }, + }, + }, + }, +}); +console.log(data); + +// Clean up +await browser.close(); +await skyvern.close(); +``` diff --git a/docs/ts-sdk-reference/browser-profiles.mdx b/docs/ts-sdk-reference/browser-profiles.mdx new file mode 100644 index 00000000..1655c580 --- /dev/null +++ b/docs/ts-sdk-reference/browser-profiles.mdx @@ -0,0 +1,133 @@ +--- +title: Browser Profiles +subtitle: Save and reuse browser state across runs +slug: ts-sdk-reference/browser-profiles +--- + +A browser profile is a snapshot of browser state — cookies, local storage, session data. Create a profile from a completed run, then load it into future workflow runs to skip login and setup steps. + +For conceptual background, see [Browser Profiles](/optimization/browser-profiles). + +--- + +## `createBrowserProfile` + +Create a profile from a completed workflow run. + +```typescript +const profile = await skyvern.createBrowserProfile({ + name: "production-login", + workflow_run_id: "wr_abc123", +}); +console.log(profile.browser_profile_id); // bpf_abc123 +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `name` | `string` | Yes | Display name for the profile. | +| `description` | `string` | No | Optional description. | +| `workflow_run_id` | `string` | No | The workflow run ID to snapshot. The run must have used `persist_browser_session: true`. | +| `browser_session_id` | `string` | No | The browser session ID to snapshot. | + +### Returns `BrowserProfile` + +| Field | Type | Description | +|-------|------|-------------| +| `browser_profile_id` | `string` | Unique ID. Starts with `bpf_`. | +| `name` | `string` | Profile name. | +| `description` | `string \| undefined` | Profile description. | +| `created_at` | `string` | When the profile was created. | + +### Example: Create a profile from a login workflow + +```typescript +// Step 1: Run a workflow with persist_browser_session +const run = await skyvern.runWorkflow({ + body: { + workflow_id: "wpid_login_flow", + parameters: { username: "demo@example.com" }, + }, + waitForCompletion: true, +}); + +// Step 2: Create a profile from the run +const profile = await skyvern.createBrowserProfile({ + name: "demo-account-login", + workflow_run_id: run.run_id, +}); + +// Step 3: Use the profile in future runs (skip login) +const result = await skyvern.runWorkflow({ + body: { + workflow_id: "wpid_extract_invoices", + browser_profile_id: profile.browser_profile_id, + }, + waitForCompletion: true, +}); +``` + + +Session archiving is asynchronous. If `createBrowserProfile` fails immediately after a workflow completes, wait a few seconds and retry. + + +--- + +## `listBrowserProfiles` + +List all browser profiles. + +```typescript +const profiles = await skyvern.listBrowserProfiles({}); +for (const p of profiles) { + console.log(`${p.name} (${p.browser_profile_id})`); +} +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `include_deleted` | `boolean` | No | `undefined` | Include soft-deleted profiles in the results. | + +### Returns `BrowserProfile[]` + +--- + +## `getBrowserProfile` + +Get a single profile by ID. + +```typescript +const profile = await skyvern.getBrowserProfile("bpf_abc123"); +console.log(profile.name); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `profileId` | `string` | Yes | The browser profile ID. | + +### Returns `BrowserProfile` + +--- + +## `deleteBrowserProfile` + +Delete a browser profile. + +```typescript +await skyvern.deleteBrowserProfile("bpf_abc123"); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `profileId` | `string` | Yes | The browser profile ID to delete. | + + +`browser_profile_id` only works with `runWorkflow`, not `runTask`. If you pass it to `runTask`, it will be silently ignored. + diff --git a/docs/ts-sdk-reference/browser-sessions.mdx b/docs/ts-sdk-reference/browser-sessions.mdx new file mode 100644 index 00000000..fcae95ef --- /dev/null +++ b/docs/ts-sdk-reference/browser-sessions.mdx @@ -0,0 +1,124 @@ +--- +title: Browser Sessions +subtitle: Maintain live browser state between API calls +slug: ts-sdk-reference/browser-sessions +--- + +A browser session is a persistent browser instance that stays alive between API calls. Use sessions to chain multiple tasks in the same browser without losing cookies, local storage, or login state. + +For conceptual background, see [Browser Sessions](/optimization/browser-sessions). + +--- + +## `createBrowserSession` + +Spin up a new cloud browser session. + +```typescript +const session = await skyvern.createBrowserSession({ timeout: 60 }); +console.log(session.browser_session_id); // pbs_abc123 +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `timeout` | `number` | No | `60` | Session timeout in minutes (5–1440). Timer starts after the session is ready. | +| `proxy_location` | `ProxyLocation` | No | `undefined` | Route browser traffic through a geographic proxy. | +| `extensions` | `Extensions[]` | No | `undefined` | Browser extensions to install. Options: `"ad-blocker"`, `"captcha-solver"`. | +| `browser_type` | `PersistentBrowserType` | No | `undefined` | Browser type. Options: `"chrome"`, `"msedge"`. | + +### Returns `BrowserSessionResponse` + +| Field | Type | Description | +|-------|------|-------------| +| `browser_session_id` | `string` | Unique ID. Starts with `pbs_`. | +| `status` | `string \| undefined` | Current session status. | +| `browser_address` | `string \| undefined` | CDP address for connecting to the browser. | +| `app_url` | `string \| undefined` | Link to the live browser view in the Cloud UI. | +| `timeout` | `number \| undefined` | Configured timeout in minutes. | +| `started_at` | `string \| undefined` | When the session became ready. | +| `created_at` | `string` | When the session was requested. | + +### Example: Chain multiple tasks in one session + +```typescript +const session = await skyvern.createBrowserSession({}); + +// Step 1: Log in +await skyvern.runTask({ + body: { + prompt: "Log in with username demo@example.com", + url: "https://app.example.com/login", + browser_session_id: session.browser_session_id, + }, + waitForCompletion: true, +}); + +// Step 2: Extract data (same browser, already logged in) +const result = await skyvern.runTask({ + body: { + prompt: "Go to the invoices page and extract all invoice numbers", + browser_session_id: session.browser_session_id, + }, + waitForCompletion: true, +}); +console.log(result.output); + +// Clean up +await skyvern.closeBrowserSession(session.browser_session_id); +``` + +--- + +## `getBrowserSession` + +Get the status and details of a session. + +```typescript +const session = await skyvern.getBrowserSession("pbs_abc123"); +console.log(session.status, session.browser_address); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `browserSessionId` | `string` | Yes | The session ID. | + +### Returns `BrowserSessionResponse` + +--- + +## `getBrowserSessions` + +List all active browser sessions. + +```typescript +const sessions = await skyvern.getBrowserSessions(); +for (const s of sessions) { + console.log(`${s.browser_session_id} — ${s.status}`); +} +``` + +### Returns `BrowserSessionResponse[]` + +--- + +## `closeBrowserSession` + +Close a browser session and release its resources. + +```typescript +await skyvern.closeBrowserSession("pbs_abc123"); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `browserSessionId` | `string` | Yes | The session ID to close. | + + +Closing a session is irreversible. Any unsaved state (cookies, local storage) is lost unless you created a [browser profile](/ts-sdk-reference/browser-profiles) from it. + diff --git a/docs/ts-sdk-reference/complete-reference.mdx b/docs/ts-sdk-reference/complete-reference.mdx new file mode 100644 index 00000000..47f16128 --- /dev/null +++ b/docs/ts-sdk-reference/complete-reference.mdx @@ -0,0 +1,618 @@ +--- +title: Complete Reference (For LLMs) +subtitle: Every method, parameter, and type in one page +slug: ts-sdk-reference/complete-reference +--- + +## Install and initialize + +```bash +npm install @skyvern/client +``` + +```typescript +import { Skyvern } from "@skyvern/client"; + +const skyvern = new Skyvern({ apiKey: "YOUR_API_KEY" }); + +const result = await skyvern.runTask({ + body: { + prompt: "Get the title of the top post on Hacker News", + url: "https://news.ycombinator.com", + }, + waitForCompletion: true, +}); +console.log(result.output); +``` + +**Constructor:** + +```typescript +new Skyvern({ + apiKey: string, // Required + baseUrl?: string, // Override for self-hosted deployments + environment?: SkyvernEnvironment | string, // Cloud (default), Staging, or Local + timeoutInSeconds?: number, // HTTP request timeout (default: 60) + maxRetries?: number, // Retry count (default: 2) + headers?: Record, // Additional headers +}) +``` + +**Environments:** + +```typescript +import { SkyvernEnvironment } from "@skyvern/client"; +// SkyvernEnvironment.Cloud → "https://api.skyvern.com" +// SkyvernEnvironment.Staging → "https://api-staging.skyvern.com" +// SkyvernEnvironment.Local → "http://localhost:8000" +``` + +All methods return promises. Requires Node.js 18+. + +--- + +## Imports + +```typescript +import { + Skyvern, // Main client class + SkyvernEnvironment, // Cloud, Staging, Local + SkyvernError, // Base error class + SkyvernTimeoutError, // HTTP timeout error + SkyvernApi, // Namespace for API types and error subclasses +} from "@skyvern/client"; + +// HTTP error subclasses via SkyvernApi namespace: +// SkyvernApi.BadRequestError — 400 +// SkyvernApi.ForbiddenError — 403 +// SkyvernApi.NotFoundError — 404 +// SkyvernApi.ConflictError — 409 +// SkyvernApi.UnprocessableEntityError — 422 +``` + +**Important:** `SkyvernError` and `SkyvernTimeoutError` are top-level exports. The HTTP-specific errors (`BadRequestError`, etc.) extend `SkyvernError` and are accessed via the `SkyvernApi` namespace. + +--- + +## Tasks + +### `runTask` + +```typescript +const result = await skyvern.runTask({ + body: { + prompt: string, // Required. Natural language instructions. + url?: string, // Starting page URL. + engine?: RunEngine, // "skyvern_v2" (default), "skyvern_v1", "openai_cua", "anthropic_cua", "ui_tars" + max_steps?: number, // Cap AI steps to limit cost. + data_extraction_schema?: Record | string, // JSON Schema for output. + browser_session_id?: string, // Run in existing session. + publish_workflow?: boolean, // Save generated code as reusable workflow. + proxy_location?: ProxyLocation, + webhook_url?: string, + error_code_mapping?: Record, + totp_identifier?: string, + totp_url?: string, + title?: string, + model?: Record, + user_agent?: string, + extra_http_headers?: Record, + browser_address?: string, + }, + waitForCompletion?: boolean, // Poll until finished. Default: false. + timeout?: number, // Max wait (seconds). Default: 1800. +}): Promise +``` + +**`TaskRunResponse` fields:** + +| Field | Type | Description | +|-------|------|-------------| +| `run_id` | `string` | Unique ID (`tsk_...`). | +| `status` | `string` | `created` \| `queued` \| `running` \| `completed` \| `failed` \| `terminated` \| `timed_out` \| `canceled` | +| `output` | `Record \| null` | Extracted data. `null` until completed. | +| `failure_reason` | `string \| undefined` | Error description if failed. | +| `downloaded_files` | `FileInfo[] \| undefined` | Files downloaded during the run. | +| `recording_url` | `string \| undefined` | Session recording video URL. | +| `screenshot_urls` | `string[] \| undefined` | Final screenshots. | +| `app_url` | `string \| undefined` | Link to run in Skyvern UI. | +| `step_count` | `number \| undefined` | Number of AI steps taken. | +| `created_at` | `string` | When the run was created. | +| `finished_at` | `string \| undefined` | When the run finished. | + +### `getRun` + +```typescript +const run = await skyvern.getRun(runId: string): Promise +``` + +Returns status and results for any run (task or workflow). + +### `cancelRun` + +```typescript +await skyvern.cancelRun(runId: string): Promise +``` + +### `getRunTimeline` + +```typescript +const timeline = await skyvern.getRunTimeline(runId: string): Promise +``` + +### `getRunArtifacts` + +```typescript +const artifacts = await skyvern.getRunArtifacts( + runId: string, + request?: { artifact_type?: ArtifactType | ArtifactType[] }, +): Promise +``` + +### `getArtifact` + +```typescript +const artifact = await skyvern.getArtifact(artifactId: string): Promise +``` + +### `retryRunWebhook` + +```typescript +await skyvern.retryRunWebhook(runId: string): Promise +``` + +--- + +## Workflows + +### `runWorkflow` + +```typescript +const result = await skyvern.runWorkflow({ + body: { + workflow_id: string, // Required. Permanent ID (wpid_...). + parameters?: Record, // Input params matching workflow definition. + browser_session_id?: string, + browser_profile_id?: string, // Load saved browser state. + proxy_location?: ProxyLocation, + webhook_url?: string, + title?: string, + totp_identifier?: string, + totp_url?: string, + user_agent?: string, + extra_http_headers?: Record, + browser_address?: string, + }, + template?: boolean, + waitForCompletion?: boolean, // Default: false. + timeout?: number, // Default: 1800. +}): Promise +``` + +**`WorkflowRunResponse` fields:** Same as `TaskRunResponse` plus `run_with`, `ai_fallback`, `script_run`. + +### `createWorkflow` + +```typescript +const workflow = await skyvern.createWorkflow({ + body: { json_definition?: object, yaml_definition?: string }, + folder_id?: string, +}): Promise +``` + +**`Workflow` fields:** `workflow_id`, `workflow_permanent_id`, `version`, `title`, `workflow_definition`, `status`, `created_at` + +### `getWorkflows` + +```typescript +const workflows = await skyvern.getWorkflows({ + page?: number, + page_size?: number, + only_saved_tasks?: boolean, + only_workflows?: boolean, + title?: string, + search_key?: string, + folder_id?: string, + status?: WorkflowStatus | WorkflowStatus[], +}): Promise +``` + +### `getWorkflow` + +```typescript +const workflow = await skyvern.getWorkflow( + workflowPermanentId: string, + request?: { version?: number; template?: boolean }, +): Promise +``` + +### `getWorkflowVersions` + +```typescript +const versions = await skyvern.getWorkflowVersions( + workflowPermanentId: string, + request?: { template?: boolean }, +): Promise +``` + +### `updateWorkflow` + +```typescript +const updated = await skyvern.updateWorkflow( + workflowId: string, // The version ID (not permanent ID). + request?: { json_definition?: object; yaml_definition?: string }, +): Promise +``` + +### `deleteWorkflow` + +```typescript +await skyvern.deleteWorkflow(workflowId: string): Promise +``` + +--- + +## Browser sessions + +A persistent browser instance that stays alive between API calls. Use to chain tasks without losing cookies or login state. + +### `createBrowserSession` + +```typescript +const session = await skyvern.createBrowserSession({ + timeout?: number, // Minutes (5-1440). Default: 60. + proxy_location?: ProxyLocation, + extensions?: Extensions[], // "ad-blocker", "captcha-solver" + browser_type?: PersistentBrowserType, // "chrome", "msedge" +}): Promise +``` + +**`BrowserSessionResponse` fields:** `browser_session_id`, `status`, `browser_address`, `app_url`, `timeout`, `started_at`, `created_at` + +### `getBrowserSession` + +```typescript +const session = await skyvern.getBrowserSession(browserSessionId: string): Promise +``` + +### `getBrowserSessions` + +```typescript +const sessions = await skyvern.getBrowserSessions(): Promise +``` + +### `closeBrowserSession` + +```typescript +await skyvern.closeBrowserSession(browserSessionId: string): Promise +``` + +### Session chaining example + +```typescript +const session = await skyvern.createBrowserSession({}); + +// Step 1: Log in +await skyvern.runTask({ + body: { + prompt: "Log in with username demo@example.com", + url: "https://app.example.com/login", + browser_session_id: session.browser_session_id, + }, + waitForCompletion: true, +}); + +// Step 2: Extract data (same browser, already logged in) +const result = await skyvern.runTask({ + body: { + prompt: "Go to the invoices page and extract all invoice numbers", + browser_session_id: session.browser_session_id, + }, + waitForCompletion: true, +}); +console.log(result.output); + +// Clean up +await skyvern.closeBrowserSession(session.browser_session_id); +``` + +--- + +## Browser profiles + +A saved snapshot of browser state (cookies, local storage). Create from a completed workflow run, then reuse to skip login. + +### `createBrowserProfile` + +```typescript +const profile = await skyvern.createBrowserProfile({ + name: string, + description?: string, + workflow_run_id?: string, // Run must have used persist_browser_session: true. + browser_session_id?: string, +}): Promise +``` + +**`BrowserProfile` fields:** `browser_profile_id`, `name`, `description`, `created_at` + +### `listBrowserProfiles` + +```typescript +const profiles = await skyvern.listBrowserProfiles({ + include_deleted?: boolean, +}): Promise +``` + +### `getBrowserProfile` + +```typescript +const profile = await skyvern.getBrowserProfile(profileId: string): Promise +``` + +### `deleteBrowserProfile` + +```typescript +await skyvern.deleteBrowserProfile(profileId: string): Promise +``` + +--- + +## Credentials + +Store login information securely. Reference by ID instead of passing secrets in code. + +### `createCredential` + +```typescript +const credential = await skyvern.createCredential({ + name: string, + credential_type: CredentialType, // e.g. "password" + credential: object, // Password: { username: "...", password: "..." } +}): Promise +``` + +### `getCredentials` + +```typescript +const creds = await skyvern.getCredentials({ + page?: number, + page_size?: number, +}): Promise +``` + +### `getCredential` + +```typescript +const cred = await skyvern.getCredential(credentialId: string): Promise +``` + +### `deleteCredential` + +```typescript +await skyvern.deleteCredential(credentialId: string): Promise +``` + +### `sendTotpCode` + +Send a TOTP code to Skyvern during a run that requires 2FA. + +```typescript +await skyvern.sendTotpCode({ + totp_identifier: string, + content: string, // The TOTP code value. + task_id?: string, + workflow_id?: string, + workflow_run_id?: string, + source?: string, + expired_at?: string, +}): Promise +``` + +--- + +## Helper methods + +### `login` + +Automate logging into a website using stored credentials. + +```typescript +const result = await skyvern.login({ + credential_type: CredentialType, // Required. "skyvern", "bitwarden", "1password", "azure_vault". + url?: string, + credential_id?: string, // When using "skyvern" type. + prompt?: string, + browser_session_id?: string, + browser_address?: string, + proxy_location?: ProxyLocation, + webhook_url?: string, + totp_identifier?: string, + totp_url?: string, + extra_http_headers?: Record, + waitForCompletion?: boolean, // Default: false. + timeout?: number, // Default: 1800. + // Bitwarden: bitwarden_collection_id, bitwarden_item_id + // 1Password: onepassword_vault_id, onepassword_item_id + // Azure: azure_vault_name, azure_vault_username_key, azure_vault_password_key, azure_vault_totp_secret_key +}): Promise +``` + +### `downloadFiles` + +```typescript +const result = await skyvern.downloadFiles({ + navigation_goal: string, // Required. What to download. + url?: string, + browser_session_id?: string, + browser_profile_id?: string, + download_suffix?: string, // Expected extension, e.g. ".pdf" + download_timeout?: number, + max_steps_per_run?: number, + extra_http_headers?: Record, + waitForCompletion?: boolean, // Default: false. + timeout?: number, // Default: 1800. +}): Promise +``` + +### `uploadFile` + +```typescript +const upload = await skyvern.uploadFile({ file }): Promise +// Returns: { s3_uri: string, presigned_url: string } +``` + +--- + +## Browser automation (Playwright + AI) + +The TypeScript SDK extends Playwright with AI capabilities via cloud browsers. + +### Launch browsers + +```typescript +// Launch new cloud browser +const browser = await skyvern.launchCloudBrowser({ timeout?: number, proxyLocation?: ProxyLocation }); + +// Reuse existing or create new +const browser = await skyvern.useCloudBrowser({ timeout?: number, proxyLocation?: ProxyLocation }); + +// Connect to existing cloud session +const browser = await skyvern.connectToCloudBrowserSession(browserSessionId: string); + +// Connect via CDP +const browser = await skyvern.connectToBrowserOverCdp(cdpUrl: string); +``` + +### Get pages + +```typescript +const page = await browser.getWorkingPage(); // Get or create page +const page = await browser.newPage(); // Always create new page +await browser.close(); // Close browser and session +``` + +### AI-enhanced page methods + +```typescript +// Click with AI fallback +await page.click("#selector"); // Standard Playwright +await page.click({ prompt: "Click the submit button" }); // AI-powered +await page.click("#selector", { prompt: "Click submit" }); // Selector + AI fallback + +// Fill with AI fallback +await page.fill("#email", "user@example.com"); // Standard Playwright +await page.fill({ prompt: "Fill email with user@example.com" }); // AI-powered +await page.fill("#email", "user@example.com", { prompt: "..." }); // Selector + AI fallback + +// Select with AI fallback +await page.selectOption("#country", "us"); // Standard Playwright +await page.selectOption({ prompt: "Select United States from country" }); // AI-powered + +// Single AI actions +await page.act("Click the login button"); // Perform an action +const data = await page.extract({ prompt: "Extract products" }); // Extract data +const ok = await page.validate("User is logged in"); // Validate state (boolean) +const resp = await page.prompt("What is the heading?", schema); // LLM prompt +``` + +### Full task execution via `page.agent` + +```typescript +await page.agent.runTask("Fill out the form", { timeout: 300 }); +await page.agent.login("skyvern", { credentialId: "cred_123" }); +await page.agent.downloadFiles("Download the PDF", { downloadSuffix: ".pdf" }); +await page.agent.runWorkflow("wpid_abc", { parameters: { key: "value" } }); +``` + +--- + +## Error handling + +```typescript +import { SkyvernError, SkyvernTimeoutError, SkyvernApi } from "@skyvern/client"; + +try { + const run = await skyvern.getRun("tsk_nonexistent"); +} catch (e) { + if (e instanceof SkyvernApi.NotFoundError) { + console.log(e.statusCode, e.body); // 404 + } else if (e instanceof SkyvernTimeoutError) { + console.log("Request timed out"); + } else if (e instanceof SkyvernError) { + console.log(e.statusCode, e.body); // Any other HTTP error + } +} +``` + +**Error types:** `SkyvernApi.BadRequestError` (400), `SkyvernApi.ForbiddenError` (403), `SkyvernApi.NotFoundError` (404), `SkyvernApi.ConflictError` (409), `SkyvernApi.UnprocessableEntityError` (422). All inherit from `SkyvernError`. + +**Completion timeout** throws a standard `Error`: + +```typescript +try { + const result = await skyvern.runTask({ + body: { prompt: "...", url: "..." }, + waitForCompletion: true, + timeout: 300, + }); +} catch (e) { + if (e instanceof Error && e.message.includes("Timeout")) { + console.log("Task didn't complete in time"); + } +} +``` + +**Run failure** is not an exception — check `result.status`: + +```typescript +if (result.status === "failed") console.log(result.failure_reason); +if (result.status === "completed") console.log(result.output); +``` + +--- + +## Request options + +Override timeout, retries, or headers per-request (second parameter on all methods): + +```typescript +const result = await skyvern.runTask( + { body: { prompt: "...", url: "..." } }, + { + timeoutInSeconds: 120, + maxRetries: 3, + headers: { "x-custom-header": "value" }, + abortSignal: controller.signal, + }, +); +``` + +--- + +## Polling pattern + +When not using `waitForCompletion`: + +```typescript +const task = await skyvern.runTask({ body: { prompt: "...", url: "..." } }); + +const terminal = ["completed", "failed", "terminated", "timed_out", "canceled"]; +let run; +while (true) { + run = await skyvern.getRun(task.run_id); + if (terminal.includes(run.status)) break; + await new Promise((resolve) => setTimeout(resolve, 5000)); +} +console.log(run.output); +``` + +--- + +## Key constraints + +- `browser_profile_id` works with `runWorkflow` only — silently ignored by `runTask`. +- Only workflow runs with `persist_browser_session: true` produce archives for profile creation. +- Session archiving is async — profile creation may need a short retry delay after a run completes. +- `engine` accepts string values: `"skyvern_v1"`, `"skyvern_v2"`, `"openai_cua"`, `"anthropic_cua"`, `"ui_tars"`. +- Cloud browser methods (`launchCloudBrowser`, `useCloudBrowser`, `connectToCloudBrowserSession`) only work with `Cloud` or `Staging` environments. +- The SDK depends on `playwright` for browser automation features. diff --git a/docs/ts-sdk-reference/credentials.mdx b/docs/ts-sdk-reference/credentials.mdx new file mode 100644 index 00000000..52b02dcb --- /dev/null +++ b/docs/ts-sdk-reference/credentials.mdx @@ -0,0 +1,120 @@ +--- +title: Credentials +subtitle: Store and manage authentication credentials securely +slug: ts-sdk-reference/credentials +--- + +Credentials let you store login information (username/password, TOTP secrets) securely in Skyvern's vault. Reference them by ID in tasks and workflows instead of passing secrets in your code. + +--- + +## `createCredential` + +Store a new credential. + +```typescript +const credential = await skyvern.createCredential({ + name: "my-app-login", + credential_type: "password", + credential: { + username: "demo@example.com", + password: "s3cur3-p4ss", + }, +}); +console.log(credential.credential_id); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `name` | `string` | Yes | Display name for the credential. | +| `credential_type` | `CredentialType` | Yes | Type of credential. | +| `credential` | `object` | Yes | The credential data. Shape depends on `credential_type`. | + +### Returns `CredentialResponse` + +--- + +## `getCredentials` + +List all credentials. Credential values are never returned — only metadata. + +```typescript +const creds = await skyvern.getCredentials({}); +for (const c of creds) { + console.log(`${c.name} (${c.credential_id})`); +} +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `page` | `number` | No | `undefined` | Page number. | +| `page_size` | `number` | No | `undefined` | Results per page. | + +### Returns `CredentialResponse[]` + +--- + +## `getCredential` + +Get a single credential's metadata by ID. + +```typescript +const cred = await skyvern.getCredential("cred_abc123"); +console.log(cred.name, cred.credential_type); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `credentialId` | `string` | Yes | The credential ID. | + +### Returns `CredentialResponse` + +--- + +## `deleteCredential` + +Delete a credential. + +```typescript +await skyvern.deleteCredential("cred_abc123"); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `credentialId` | `string` | Yes | The credential ID to delete. | + +--- + +## `sendTotpCode` + +Send a TOTP (time-based one-time password) code to Skyvern during a run that requires 2FA. Call this when your webhook or polling detects that Skyvern is waiting for a TOTP code. + +```typescript +await skyvern.sendTotpCode({ + totp_identifier: "demo@example.com", + content: "123456", +}); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `totp_identifier` | `string` | Yes | The identifier matching the `totp_identifier` used in the task/workflow. | +| `content` | `string` | Yes | The TOTP code value. | +| `task_id` | `string` | No | Associate with a specific task run. | +| `workflow_id` | `string` | No | Associate with a specific workflow. | +| `workflow_run_id` | `string` | No | Associate with a specific workflow run. | +| `source` | `string` | No | Source of the TOTP code. | +| `expired_at` | `string` | No | When this code expires (ISO 8601 format). | +| `type` | `OtpType` | No | OTP type. | + +### Returns `TotpCode` diff --git a/docs/ts-sdk-reference/error-handling.mdx b/docs/ts-sdk-reference/error-handling.mdx new file mode 100644 index 00000000..eb5d713f --- /dev/null +++ b/docs/ts-sdk-reference/error-handling.mdx @@ -0,0 +1,228 @@ +--- +title: Error Handling +subtitle: Handle API errors, timeouts, and configure retries +slug: ts-sdk-reference/error-handling +--- + +The SDK raises typed exceptions for API errors. All errors extend `SkyvernError` and include the HTTP status code, response body, and raw response. + +--- + +## Error types + +| Exception | Status Code | When it's raised | +|-----------|-------------|------------------| +| `BadRequestError` | 400 | Invalid request parameters. | +| `ForbiddenError` | 403 | Invalid or missing API key. | +| `NotFoundError` | 404 | Resource (run, workflow, session) not found. | +| `ConflictError` | 409 | Resource conflict (e.g., duplicate creation). | +| `UnprocessableEntityError` | 422 | Request validation failed. | +| `SkyvernError` | Any | Base class for all API errors. Catch this as a fallback. | +| `SkyvernTimeoutError` | — | HTTP request timed out. | + +Import errors from the package: + +```typescript +import { SkyvernError, SkyvernTimeoutError, SkyvernApi } from "@skyvern/client"; + +// Base errors are top-level exports: +// SkyvernError — base class for all API errors +// SkyvernTimeoutError — HTTP request timed out + +// HTTP status error subclasses are accessed via the SkyvernApi namespace: +// SkyvernApi.BadRequestError — 400 +// SkyvernApi.ForbiddenError — 403 +// SkyvernApi.NotFoundError — 404 +// SkyvernApi.ConflictError — 409 +// SkyvernApi.UnprocessableEntityError — 422 +``` + +--- + +## Catching errors + +```typescript +import { Skyvern, SkyvernError, SkyvernApi } from "@skyvern/client"; + +const skyvern = new Skyvern({ apiKey: "YOUR_API_KEY" }); + +try { + const run = await skyvern.getRun("tsk_nonexistent"); +} catch (e) { + if (e instanceof SkyvernApi.NotFoundError) { + console.log(`Run not found: ${e.body}`); + } else if (e instanceof SkyvernError) { + console.log(`API error ${e.statusCode}: ${e.body}`); + } +} +``` + +### Error properties + +Every error has these attributes: + +| Property | Type | Description | +|----------|------|-------------| +| `statusCode` | `number \| undefined` | HTTP status code. | +| `body` | `unknown` | Response body (usually an object with error details). | +| `rawResponse` | `RawResponse \| undefined` | The raw HTTP response. | +| `message` | `string` | Human-readable error message. | + +--- + +## Timeouts + +Two different timeouts apply: + +### HTTP request timeout + +Controls how long the SDK waits for the HTTP response from the Skyvern API. Set it in the constructor or per-request: + +```typescript +// Global timeout (applies to all requests) +const skyvern = new Skyvern({ + apiKey: "YOUR_API_KEY", + timeoutInSeconds: 30, +}); + +// Per-request timeout +const result = await skyvern.getRun("tsk_abc123", { + timeoutInSeconds: 10, +}); +``` + +When an HTTP request times out, a `SkyvernTimeoutError` is thrown. + +### Completion timeout + +Controls how long `waitForCompletion` polls before giving up. This is separate from the HTTP timeout: + +```typescript +try { + const result = await skyvern.runTask({ + body: { + prompt: "Extract data", + url: "https://example.com", + }, + waitForCompletion: true, + timeout: 300, // Give up after 5 minutes + }); +} catch (e) { + if (e instanceof Error && e.message.includes("Timeout")) { + console.log("Task didn't complete in time"); + } +} +``` + +The completion timeout throws a standard JavaScript `Error` with a timeout message. + +--- + +## Retries + +Configure automatic retries for transient failures. Set it in the constructor or per-request: + +```typescript +// Global retries (default: 2) +const skyvern = new Skyvern({ + apiKey: "YOUR_API_KEY", + maxRetries: 3, +}); + +// Per-request retries +const result = await skyvern.runTask( + { + body: { + prompt: "Extract product data", + url: "https://example.com/products", + }, + }, + { maxRetries: 5 }, +); +``` + +Retries apply to the HTTP request level (network errors, 5xx responses). They do not retry the entire task if it fails at the AI level — use `getRun` to check the status and re-run if needed. + +--- + +## Abort requests + +Cancel in-flight requests using `AbortSignal`: + +```typescript +const controller = new AbortController(); + +// Cancel after 10 seconds +setTimeout(() => controller.abort(), 10000); + +try { + const result = await skyvern.runTask( + { + body: { + prompt: "Extract data", + url: "https://example.com", + }, + }, + { abortSignal: controller.signal }, + ); +} catch (e) { + if (e instanceof Error && e.name === "AbortError") { + console.log("Request was aborted"); + } +} +``` + +--- + +## Run failure vs API errors + +There are two distinct failure modes: + +**API error** — The HTTP request itself failed. The SDK throws an exception. + +```typescript +import { SkyvernError } from "@skyvern/client"; + +try { + const result = await skyvern.runTask({ + body: { prompt: "..." }, + }); +} catch (e) { + if (e instanceof SkyvernError) { + console.log(`API call failed: ${e.statusCode}`); + } +} +``` + +**Run failure** — The API call succeeded, but the task/workflow failed during execution. No exception is thrown. Check the `status` field: + +```typescript +const result = await skyvern.runTask({ + body: { + prompt: "Fill out the form", + url: "https://example.com", + }, + waitForCompletion: true, +}); + +if (result.status === "failed") { + console.log(`Task failed: ${result.failure_reason}`); +} else if (result.status === "timed_out") { + console.log(`Task exceeded step limit after ${result.step_count} steps`); +} else if (result.status === "completed") { + console.log(`Success: ${JSON.stringify(result.output)}`); +} +``` + +### Run statuses + +| Status | Description | +|--------|-------------| +| `created` | Run initialized, not yet queued. | +| `queued` | Waiting for an available browser. | +| `running` | AI is executing. | +| `completed` | Finished successfully. | +| `failed` | Encountered an error during execution. | +| `terminated` | Manually stopped. | +| `timed_out` | Exceeded step limit (`max_steps`). | +| `canceled` | Canceled before starting. | diff --git a/docs/ts-sdk-reference/helpers.mdx b/docs/ts-sdk-reference/helpers.mdx new file mode 100644 index 00000000..c6d3e962 --- /dev/null +++ b/docs/ts-sdk-reference/helpers.mdx @@ -0,0 +1,164 @@ +--- +title: Helper Methods +subtitle: High-level methods for common automation patterns +slug: ts-sdk-reference/helpers +--- + +These methods wrap common multi-step patterns into single API calls. Under the hood, they create and run specialized workflows. + +--- + +## `login` + +Automate logging into a website using stored credentials. This creates a login workflow, executes it, and optionally waits for completion. + +```typescript +const result = await skyvern.login({ + credential_type: "skyvern", + credential_id: "cred_abc123", + url: "https://app.example.com/login", + waitForCompletion: true, +}); +console.log(result.status); +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `credential_type` | `CredentialType` | Yes | — | How credentials are stored. Options: `"skyvern"`, `"bitwarden"`, `"1password"`, `"azure_vault"`. | +| `url` | `string` | No | `undefined` | The login page URL. | +| `credential_id` | `string` | No | `undefined` | The Skyvern credential ID (when using `"skyvern"` type). | +| `prompt` | `string` | No | `undefined` | Additional instructions for the AI during login. | +| `browser_session_id` | `string` | No | `undefined` | Run login inside an existing browser session. | +| `browser_address` | `string` | No | `undefined` | Connect to a browser at this CDP address. | +| `proxy_location` | `ProxyLocation` | No | `undefined` | Route browser traffic through a geographic proxy. | +| `webhook_url` | `string` | No | `undefined` | URL to receive a POST when the login finishes. | +| `totp_identifier` | `string` | No | `undefined` | Identifier for TOTP verification. | +| `totp_url` | `string` | No | `undefined` | URL to receive TOTP codes. | +| `extra_http_headers` | `Record` | No | `undefined` | Additional HTTP headers. | +| `max_screenshot_scrolling_times` | `number` | No | `undefined` | Number of screenshot scrolls. | +| `waitForCompletion` | `boolean` | No | `false` | Block until the login finishes. | +| `timeout` | `number` | No | `1800` | Max wait time in seconds. | + +**Bitwarden-specific parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `bitwarden_collection_id` | `string` | Bitwarden collection ID. | +| `bitwarden_item_id` | `string` | Bitwarden item ID. | + +**1Password-specific parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `onepassword_vault_id` | `string` | 1Password vault ID. | +| `onepassword_item_id` | `string` | 1Password item ID. | + +**Azure Key Vault-specific parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `azure_vault_name` | `string` | Azure Key Vault name. | +| `azure_vault_username_key` | `string` | Secret name for the username. | +| `azure_vault_password_key` | `string` | Secret name for the password. | +| `azure_vault_totp_secret_key` | `string` | Secret name for the TOTP secret. | + +### Returns `WorkflowRunResponse` + +### Example: Login then extract data + +```typescript +const session = await skyvern.createBrowserSession({}); + +// Login +await skyvern.login({ + credential_type: "skyvern", + credential_id: "cred_abc123", + url: "https://app.example.com/login", + browser_session_id: session.browser_session_id, + waitForCompletion: true, +}); + +// Now extract data from the authenticated session +const result = await skyvern.runTask({ + body: { + prompt: "Go to the billing page and extract all invoices", + browser_session_id: session.browser_session_id, + }, + waitForCompletion: true, +}); +console.log(result.output); +``` + +--- + +## `downloadFiles` + +Navigate to a page and download files. + +```typescript +const result = await skyvern.downloadFiles({ + navigation_goal: "Download the latest monthly report PDF", + url: "https://app.example.com/reports", + waitForCompletion: true, +}); + +for (const f of result.downloaded_files ?? []) { + console.log(f.name); +} +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `navigation_goal` | `string` | Yes | — | Natural language description of what to download. | +| `url` | `string` | No | `undefined` | Starting page URL. | +| `browser_session_id` | `string` | No | `undefined` | Run inside an existing browser session. | +| `browser_profile_id` | `string` | No | `undefined` | Load a browser profile. | +| `proxy_location` | `ProxyLocation` | No | `undefined` | Route through a geographic proxy. | +| `webhook_url` | `string` | No | `undefined` | URL to receive a POST when the download finishes. | +| `download_suffix` | `string` | No | `undefined` | Expected file extension to wait for (e.g., `".pdf"`). | +| `download_timeout` | `number` | No | `undefined` | Max time to wait for the download in seconds. | +| `max_steps_per_run` | `number` | No | `undefined` | Cap AI steps. | +| `extra_http_headers` | `Record` | No | `undefined` | Additional HTTP headers. | +| `waitForCompletion` | `boolean` | No | `false` | Block until the download finishes. | +| `timeout` | `number` | No | `1800` | Max wait time in seconds. | + +### Returns `WorkflowRunResponse` + +The `downloaded_files` field contains the list of files that were downloaded. + + +Unlike the Python SDK where `download_files` does not support `wait_for_completion`, the TypeScript SDK supports `waitForCompletion` on all methods including `downloadFiles`. + + +--- + +## `uploadFile` + +Upload a file to Skyvern's storage. Returns a presigned URL and S3 URI you can reference in tasks and workflows. + +```typescript +import fs from "fs"; + +const upload = await skyvern.uploadFile({ + file: fs.createReadStream("data.csv"), +}); +console.log(upload.s3_uri); // s3://skyvern-uploads/... +console.log(upload.presigned_url); // https://...signed download URL +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `file` | `File \| ReadStream \| Blob` | Yes | The file to upload. | + +### Returns `UploadFileResponse` + +| Field | Type | Description | +|-------|------|-------------| +| `s3_uri` | `string` | S3 URI for the uploaded file. | +| `presigned_url` | `string` | Pre-signed download URL. | diff --git a/docs/ts-sdk-reference/overview.mdx b/docs/ts-sdk-reference/overview.mdx new file mode 100644 index 00000000..47d32495 --- /dev/null +++ b/docs/ts-sdk-reference/overview.mdx @@ -0,0 +1,173 @@ +--- +title: TypeScript SDK +subtitle: Install, authenticate, and configure the Skyvern TypeScript client +slug: ts-sdk-reference/overview +--- + +The `@skyvern/client` package wraps the Skyvern REST API in a typed TypeScript client with built-in browser automation via Playwright. + +```bash +npm install @skyvern/client +``` + + +Requires Node.js 18+. Also compatible with Bun, Deno, and Cloudflare Workers. + + +--- + +## Initialize the client + +The `Skyvern` class provides both API methods and browser automation. All API methods return promises: + +```typescript +import { Skyvern } from "@skyvern/client"; + +const skyvern = new Skyvern({ apiKey: "YOUR_API_KEY" }); + +const result = await skyvern.runTask({ + body: { + prompt: "Get the title of the top post on Hacker News", + url: "https://news.ycombinator.com", + }, + waitForCompletion: true, +}); +console.log(result.output); +``` + +### Constructor parameters + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `apiKey` | `string` | — | **Required.** Your Skyvern API key. Get one at [app.skyvern.com/settings](https://app.skyvern.com/settings/api-keys). | +| `environment` | `SkyvernEnvironment \| string` | `Cloud` | Target environment. Options: `Cloud`, `Staging`, `Local`. | +| `baseUrl` | `string` | `undefined` | Override the API base URL. Use this for self-hosted deployments. | +| `timeoutInSeconds` | `number` | `60` | HTTP request timeout in seconds. | +| `maxRetries` | `number` | `2` | Number of times to retry failed requests. | +| `headers` | `Record` | `undefined` | Additional headers included with every request. | + +--- + +## Environments + +The SDK ships with three built-in environment URLs: + +```typescript +import { SkyvernEnvironment } from "@skyvern/client"; +``` + +| Environment | URL | When to use | +|-------------|-----|-------------| +| `SkyvernEnvironment.Cloud` | `https://api.skyvern.com` | Skyvern Cloud (default) | +| `SkyvernEnvironment.Staging` | `https://api-staging.skyvern.com` | Staging environment | +| `SkyvernEnvironment.Local` | `http://localhost:8000` | Local server started with `skyvern run server` | + +For a self-hosted instance at a custom URL, pass `baseUrl` instead: + +```typescript +const skyvern = new Skyvern({ + apiKey: "YOUR_API_KEY", + baseUrl: "https://skyvern.your-company.com", +}); +``` + +--- + +## `waitForCompletion` + +By default, `runTask` and `runWorkflow` return immediately after the run is queued — you get a `run_id` and need to poll `getRun()` yourself. Pass `waitForCompletion: true` to have the SDK poll automatically until the run reaches a terminal state (`completed`, `failed`, `terminated`, `timed_out`, or `canceled`): + +```typescript +// Returns only after the task finishes (up to 30 min by default) +const result = await skyvern.runTask({ + body: { + prompt: "Fill out the contact form", + url: "https://example.com/contact", + }, + waitForCompletion: true, + timeout: 600, // give up after 10 minutes +}); + +// Without waitForCompletion — returns immediately +const task = await skyvern.runTask({ + body: { + prompt: "Fill out the contact form", + url: "https://example.com/contact", + }, +}); +console.log(task.run_id); // poll with skyvern.getRun(task.run_id) +``` + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `waitForCompletion` | `boolean` | `false` | Poll until the run finishes. | +| `timeout` | `number` | `1800` | Maximum wait time in seconds. Throws `Error` if exceeded. | + +Supported on `runTask`, `runWorkflow`, `login`, and `downloadFiles`. + +--- + +## Request options + +Every method accepts an optional second parameter for per-request overrides of timeout, retries, headers, and abort signal: + +```typescript +const result = await skyvern.runTask( + { + body: { + prompt: "Extract data", + url: "https://example.com", + }, + }, + { + timeoutInSeconds: 120, + maxRetries: 3, + headers: { "x-custom-header": "value" }, + }, +); +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `timeoutInSeconds` | `number` | HTTP timeout for this request. | +| `maxRetries` | `number` | Retry count for this request. | +| `abortSignal` | `AbortSignal` | Signal to abort the request. | +| `apiKey` | `string` | Override the API key for this request. | +| `headers` | `Record` | Additional headers for this request. | + +These override the client-level defaults for that single call only. + +--- + +## Next steps + + + + Run browser automations with `runTask` + + + Create and run multi-step automations + + + Control cloud browsers with Playwright + AI + + + Handle errors and configure retries + + diff --git a/docs/ts-sdk-reference/tasks.mdx b/docs/ts-sdk-reference/tasks.mdx new file mode 100644 index 00000000..8185d282 --- /dev/null +++ b/docs/ts-sdk-reference/tasks.mdx @@ -0,0 +1,288 @@ +--- +title: Tasks +subtitle: Run single browser automations with natural language +slug: ts-sdk-reference/tasks +--- + +A task is a single browser automation. You describe what you want in natural language — Skyvern opens a browser, navigates to the URL, and executes the instructions with AI. + +For when to use tasks vs workflows, see [Run a Task](/running-automations/run-a-task). + +--- + +## `runTask` + +Start a browser automation. Skyvern opens a cloud browser, navigates to the URL, and executes your prompt with AI. + +```typescript +const result = await skyvern.runTask({ + body: { + prompt: "Get the title of the top post", + url: "https://news.ycombinator.com", + }, + waitForCompletion: true, +}); +console.log(result.output); +``` + +### Parameters + +The `runTask` method accepts a single request object with the following shape: + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `body.prompt` | `string` | Yes | — | Natural language instructions for what the AI should do. | +| `body.url` | `string` | No | `undefined` | Starting page URL. If omitted, the AI navigates from a blank page. | +| `body.engine` | `RunEngine` | No | `"skyvern_v2"` | AI engine. Options: `"skyvern_v2"`, `"skyvern_v1"`, `"openai_cua"`, `"anthropic_cua"`, `"ui_tars"`. | +| `body.max_steps` | `number` | No | `undefined` | Cap the number of AI steps to limit cost. Run terminates with `timed_out` if hit. | +| `body.data_extraction_schema` | `Record \| string` | No | `undefined` | JSON schema constraining the output shape. | +| `body.proxy_location` | `ProxyLocation` | No | `undefined` | Route the browser through a geographic proxy. | +| `body.browser_session_id` | `string` | No | `undefined` | Run inside an existing [browser session](/optimization/browser-sessions). | +| `body.publish_workflow` | `boolean` | No | `false` | Save the generated code as a reusable workflow. Only works with `skyvern_v2`. | +| `body.webhook_url` | `string` | No | `undefined` | URL to receive a POST when the run finishes. | +| `body.error_code_mapping` | `Record` | No | `undefined` | Map custom error codes to failure reasons. | +| `body.totp_identifier` | `string` | No | `undefined` | Identifier for TOTP verification. | +| `body.totp_url` | `string` | No | `undefined` | URL to receive TOTP codes. | +| `body.title` | `string` | No | `undefined` | Display name for this run in the dashboard. | +| `body.model` | `Record` | No | `undefined` | Override the output model definition. | +| `body.user_agent` | `string` | No | `undefined` | Custom User-Agent header for the browser. | +| `body.extra_http_headers` | `Record` | No | `undefined` | Additional HTTP headers injected into every browser request. | +| `body.browser_address` | `string` | No | `undefined` | Connect to a browser at this CDP address instead of spinning up a new one. | +| `waitForCompletion` | `boolean` | No | `false` | Block until the run finishes. | +| `timeout` | `number` | No | `1800` | Max wait time in seconds when `waitForCompletion` is `true`. | + +### Returns `TaskRunResponse` + +| Field | Type | Description | +|-------|------|-------------| +| `run_id` | `string` | Unique identifier. Starts with `tsk_` for task runs. | +| `status` | `string` | `"created"`, `"queued"`, `"running"`, `"completed"`, `"failed"`, `"terminated"`, `"timed_out"`, or `"canceled"`. | +| `output` | `Record \| null` | Extracted data from the run. Shape depends on your prompt or `data_extraction_schema`. | +| `downloaded_files` | `FileInfo[] \| undefined` | Files downloaded during the run. | +| `recording_url` | `string \| undefined` | URL to the session recording video. | +| `screenshot_urls` | `string[] \| undefined` | Final screenshots (most recent first). | +| `failure_reason` | `string \| undefined` | Error description if the run failed. | +| `app_url` | `string \| undefined` | Link to view this run in the Cloud UI. | +| `step_count` | `number \| undefined` | Number of AI steps taken. | +| `script_run` | `ScriptRunResponse \| undefined` | Code execution result if the run used generated code. | +| `created_at` | `string` | When the run was created. | +| `finished_at` | `string \| undefined` | When the run finished. | + +### Examples + +**Extract structured data:** + +```typescript +const result = await skyvern.runTask({ + body: { + prompt: "Extract the name, price, and rating of the top 3 products", + url: "https://example.com/products", + data_extraction_schema: { + type: "array", + items: { + type: "object", + properties: { + name: { type: "string" }, + price: { type: "string" }, + rating: { type: "number" }, + }, + }, + }, + }, + waitForCompletion: true, +}); +console.log(result.output); +// [{ name: "Widget A", price: "$29.99", rating: 4.5 }, ...] +``` + +**Run inside an existing browser session:** + +```typescript +const session = await skyvern.createBrowserSession({}); + +const result = await skyvern.runTask({ + body: { + prompt: "Log in and download the latest invoice", + url: "https://app.example.com/login", + browser_session_id: session.browser_session_id, + }, + waitForCompletion: true, +}); +``` + +**Limit cost with max_steps:** + +```typescript +const result = await skyvern.runTask({ + body: { + prompt: "Fill out the contact form", + url: "https://example.com/contact", + max_steps: 10, + }, + waitForCompletion: true, +}); +``` + +**Publish as a reusable workflow:** + +```typescript +const result = await skyvern.runTask({ + body: { + prompt: "Fill out the contact form with the provided data", + url: "https://example.com/contact", + publish_workflow: true, + }, + waitForCompletion: true, +}); +// The generated workflow is saved and can be re-triggered via runWorkflow +``` + +--- + +## `getRun` + +Get the current status and results of any run (task or workflow). + +```typescript +const run = await skyvern.getRun("tsk_v2_486305187432193504"); +console.log(run.status, run.output); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `runId` | `string` | Yes | The run ID returned by `runTask` or `runWorkflow`. | + +### Returns `GetRunResponse` + +A discriminated union based on `run_type`. All variants share the same core fields as `TaskRunResponse` above, plus a `run_type` field (`task_v1`, `task_v2`, `openai_cua`, `anthropic_cua`, `ui_tars`, `workflow_run`). + +Workflow run responses additionally include `run_with` and `ai_fallback` fields. + +--- + +## `cancelRun` + +Cancel a running or queued run. + +```typescript +await skyvern.cancelRun("tsk_v2_486305187432193504"); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `runId` | `string` | Yes | The run ID to cancel. | + +The run transitions to `canceled` status. If the run has already finished, this is a no-op. + +--- + +## `getRunTimeline` + +Get the step-by-step timeline of a run. Each entry represents one AI action with screenshots and reasoning. + +```typescript +const timeline = await skyvern.getRunTimeline("tsk_v2_486305187432193504"); +for (const step of timeline) { + console.log(`Step ${step.order}: ${step.type} — ${step.status}`); +} +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `runId` | `string` | Yes | The run ID. | + +### Returns `WorkflowRunTimeline[]` + +Each timeline entry contains step details including type, status, order, and associated artifacts. + +--- + +## `getRunArtifacts` + +Get all artifacts (screenshots, recordings, generated code, etc.) for a run. + +```typescript +const artifacts = await skyvern.getRunArtifacts("tsk_v2_486305187432193504"); +for (const artifact of artifacts) { + console.log(`${artifact.artifact_type}: ${artifact.uri}`); +} +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `runId` | `string` | Yes | The run ID. | +| `artifactType` | `ArtifactType \| ArtifactType[]` | No | Filter by artifact type. | + +### Returns `Artifact[]` + +--- + +## `getArtifact` + +Get a single artifact by ID. + +```typescript +const artifact = await skyvern.getArtifact("art_486305187432193504"); +console.log(artifact.uri); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `artifactId` | `string` | Yes | The artifact ID. | + +### Returns `Artifact` + +--- + +## `retryRunWebhook` + +Re-send the webhook notification for a completed run. Useful if your webhook endpoint was down when the run finished. + +```typescript +await skyvern.retryRunWebhook("tsk_v2_486305187432193504"); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `runId` | `string` | Yes | The run ID. | + +--- + +## Polling pattern + +If you don't use `waitForCompletion`, poll `getRun` manually: + +```typescript +const task = await skyvern.runTask({ + body: { + prompt: "Extract product data", + url: "https://example.com/products", + }, +}); + +const terminalStatuses = ["completed", "failed", "terminated", "timed_out", "canceled"]; +let run; +while (true) { + run = await skyvern.getRun(task.run_id); + if (terminalStatuses.includes(run.status)) break; + await new Promise((resolve) => setTimeout(resolve, 5000)); +} + +console.log(run.output); +``` + + +For production, prefer `waitForCompletion: true` or [webhooks](/going-to-production/webhooks) over manual polling. + diff --git a/docs/ts-sdk-reference/workflows.mdx b/docs/ts-sdk-reference/workflows.mdx new file mode 100644 index 00000000..e486a051 --- /dev/null +++ b/docs/ts-sdk-reference/workflows.mdx @@ -0,0 +1,273 @@ +--- +title: Workflows +subtitle: Create and run multi-step browser automations +slug: ts-sdk-reference/workflows +--- + +A workflow chains multiple steps (blocks) into a single automation. Workflows support loops, conditionals, data passing between steps, and code-based re-execution. + +For conceptual background, see [Build a Workflow](/multi-step-automations/build-a-workflow). + +--- + +## `runWorkflow` + +Execute a workflow by its permanent ID. Skyvern opens a cloud browser and runs each block in sequence. + +```typescript +const result = await skyvern.runWorkflow({ + body: { + workflow_id: "wpid_abc123", + }, + waitForCompletion: true, +}); +console.log(result.output); +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `body.workflow_id` | `string` | Yes | — | The workflow's permanent ID (`wpid_...`). | +| `body.parameters` | `Record` | No | `undefined` | Input parameters defined in the workflow. Keys must match parameter names. | +| `body.browser_session_id` | `string` | No | `undefined` | Run inside an existing [browser session](/optimization/browser-sessions). | +| `body.browser_profile_id` | `string` | No | `undefined` | Load a [browser profile](/optimization/browser-profiles) (cookies, storage) into the session. | +| `body.proxy_location` | `ProxyLocation` | No | `undefined` | Route the browser through a geographic proxy. | +| `body.webhook_url` | `string` | No | `undefined` | URL to receive a POST when the run finishes. | +| `body.title` | `string` | No | `undefined` | Display name for this run in the dashboard. | +| `body.totp_identifier` | `string` | No | `undefined` | Identifier for TOTP verification. | +| `body.totp_url` | `string` | No | `undefined` | URL to receive TOTP codes. | +| `body.user_agent` | `string` | No | `undefined` | Custom User-Agent header for the browser. | +| `body.extra_http_headers` | `Record` | No | `undefined` | Additional HTTP headers injected into every browser request. | +| `body.browser_address` | `string` | No | `undefined` | Connect to a browser at this CDP address. | +| `template` | `boolean` | No | `undefined` | Run a template workflow. | +| `waitForCompletion` | `boolean` | No | `false` | Block until the workflow finishes. | +| `timeout` | `number` | No | `1800` | Max wait time in seconds when `waitForCompletion` is `true`. | + +### Returns `WorkflowRunResponse` + +| Field | Type | Description | +|-------|------|-------------| +| `run_id` | `string` | Unique identifier. Starts with `wr_` for workflow runs. | +| `status` | `string` | `"created"`, `"queued"`, `"running"`, `"completed"`, `"failed"`, `"terminated"`, `"timed_out"`, or `"canceled"`. | +| `output` | `Record \| null` | Extracted data from the workflow's output block. | +| `downloaded_files` | `FileInfo[] \| undefined` | Files downloaded during the run. | +| `recording_url` | `string \| undefined` | URL to the session recording. | +| `failure_reason` | `string \| undefined` | Error description if the run failed. | +| `app_url` | `string \| undefined` | Link to view this run in the Cloud UI. | +| `step_count` | `number \| undefined` | Total AI steps taken across all blocks. | +| `run_with` | `string \| undefined` | Whether the run used `"code"` or `"agent"`. | +| `ai_fallback` | `boolean \| undefined` | Whether AI fallback was configured. | +| `script_run` | `ScriptRunResponse \| undefined` | Code execution result. Contains `ai_fallback_triggered` if code was used. | + +### Examples + +**Pass parameters to a workflow:** + +```typescript +const result = await skyvern.runWorkflow({ + body: { + workflow_id: "wpid_invoice_extraction", + parameters: { + company_name: "Acme Corp", + date_range: "2025-01-01 to 2025-12-31", + }, + }, + waitForCompletion: true, +}); +``` + +**Run with a browser profile (skip login):** + +```typescript +const result = await skyvern.runWorkflow({ + body: { + workflow_id: "wpid_daily_report", + browser_profile_id: "bpf_abc123", + }, + waitForCompletion: true, +}); +``` + +--- + +## `createWorkflow` + +Create a new workflow from a JSON or YAML definition. + +```typescript +const workflow = await skyvern.createWorkflow({ + body: { + json_definition: { + title: "Extract Products", + workflow_definition: { + parameters: [ + { + key: "target_url", + parameter_type: "workflow", + workflow_parameter_type: "string", + description: "URL to scrape", + }, + ], + blocks: [ + { + block_type: "task", + label: "extract", + prompt: "Extract the top 3 products with name and price", + url: "{{ target_url }}", + }, + ], + }, + }, + }, +}); +console.log(workflow.workflow_permanent_id); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `body.json_definition` | `object` | No | Workflow definition as a JSON object. | +| `body.yaml_definition` | `string` | No | Workflow definition as a YAML string. | +| `folder_id` | `string` | No | Folder to organize the workflow in. | + +You must provide either `body.json_definition` or `body.yaml_definition`. + +### Returns `Workflow` + +| Field | Type | Description | +|-------|------|-------------| +| `workflow_id` | `string` | Unique ID for this version. | +| `workflow_permanent_id` | `string` | Stable ID across all versions. Use this to run workflows. | +| `version` | `number` | Version number. | +| `title` | `string` | Workflow title. | +| `workflow_definition` | `WorkflowDefinition` | The full definition including blocks and parameters. | +| `status` | `string \| undefined` | Workflow status. | +| `created_at` | `string` | When the workflow was created. | + +--- + +## `getWorkflows` + +List all workflows. Supports filtering and pagination. + +```typescript +const workflows = await skyvern.getWorkflows({}); +for (const wf of workflows) { + console.log(`${wf.title} (${wf.workflow_permanent_id})`); +} +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `page` | `number` | No | `undefined` | Page number for pagination. | +| `page_size` | `number` | No | `undefined` | Number of results per page. | +| `only_saved_tasks` | `boolean` | No | `undefined` | Only return saved tasks. | +| `only_workflows` | `boolean` | No | `undefined` | Only return workflows (not saved tasks). | +| `only_templates` | `boolean` | No | `undefined` | Only return templates. | +| `title` | `string` | No | `undefined` | Filter by exact title. | +| `search_key` | `string` | No | `undefined` | Search by title. | +| `folder_id` | `string` | No | `undefined` | Filter by folder. | +| `status` | `WorkflowStatus \| WorkflowStatus[]` | No | `undefined` | Filter by status. | + +### Returns `Workflow[]` + +--- + +## `getWorkflow` + +Get a specific workflow by its permanent ID. + +```typescript +const workflow = await skyvern.getWorkflow("wpid_abc123"); +console.log(workflow.title, `v${workflow.version}`); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `workflowPermanentId` | `string` | Yes | The workflow's permanent ID. | +| `version` | `number` | No | Specific version to retrieve. Defaults to latest. | +| `template` | `boolean` | No | Whether to fetch a template workflow. | + +### Returns `Workflow` + +--- + +## `getWorkflowVersions` + +List all versions of a workflow. + +```typescript +const versions = await skyvern.getWorkflowVersions("wpid_abc123"); +for (const v of versions) { + console.log(`v${v.version} — ${v.modified_at}`); +} +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `workflowPermanentId` | `string` | Yes | The workflow's permanent ID. | +| `template` | `boolean` | No | Whether to fetch template versions. | + +### Returns `Workflow[]` + +--- + +## `updateWorkflow` + +Update an existing workflow's definition. + +```typescript +const updated = await skyvern.updateWorkflow("wpid_abc123", { + json_definition: { + title: "Extract Products Updated", + workflow_definition: { + blocks: [ + { + block_type: "task", + label: "extract_data", + prompt: "Extract the top 5 products", + url: "https://example.com/products", + }, + ], + parameters: [], + }, + }, +}); +console.log(`Updated to v${updated.version}`); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `workflowId` | `string` | Yes | The workflow's permanent ID (`wpid_...`). | +| `json_definition` | `object` | No | Updated workflow definition as JSON. | +| `yaml_definition` | `string` | No | Updated workflow definition as YAML. | + +### Returns `Workflow` + +Creates a new version of the workflow. + +--- + +## `deleteWorkflow` + +Delete a workflow. + +```typescript +await skyvern.deleteWorkflow("wf_abc123"); +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `workflowId` | `string` | Yes | The workflow version ID to delete. |