diff --git a/docs/cloud/getting-started.mdx b/docs/cloud/getting-started.mdx new file mode 100644 index 00000000..07234258 --- /dev/null +++ b/docs/cloud/getting-started.mdx @@ -0,0 +1,144 @@ +--- +title: Getting Started +slug: cloud/getting-started +--- + +Run browser automations without writing code. This guide walks you through running your first task in the Cloud UI. + + +Prefer to integrate via code? Check out the [SDK Quickstart](/getting-started/quickstart) instead. + + +## Opening Skyvern Cloud + +Visit [app.skyvern.com](https://app.skyvern.com) and sign-up or sign-in to your account. + +You'll land on the **Discover** page—your starting point for running automations. + +discover page in skyvern + +## Understanding the Interface + +The left sidebar organizes everything you need: + +**Build** +- **Discover** — Run one-off tasks with natural language prompts +- **Workflows** — Create and manage multi-step automations +- **Runs** — View execution history for all your tasks and workflows +- **Browsers** — Monitor active browser sessions + +**Agents** +- Pre-built templates for common use cases: form filling, data extraction, job applications, insurance quotes, and more. Select one to start with a working example. + +**General** +- **Billing** — View usage and manage your plan +- **Credentials** — Store logins securely for authenticated sites +- **Settings** — Copy your API key and configure account settings + +## Run Your First Task + +The fastest way to see Skyvern in action is to run a task directly from the Discover page. + +### Step 1: Enter your prompt + + + +In the main input field, describe what you want to accomplish. + + +Be specific about the goal, completion criteria, visual indicators, and all necessary data. + + +Check out our detailed [Prompting Guide](/prompting-guide). + +You can also select one of the quick-action buttons below the input for common example tasks like "Add a product to cart" or "Get an insurance quote." + +### Step 2: Configure settings (optional) + +Click the gear icon to access additional options: + +additional settings + +| Setting | What it does | +|---------|-------------| +| **Proxy Location** | Run automations from different geographic locations | +| **Browser Session ID** | Share login state between workflows | +| **2FA Identifier** | Handle two-factor authentication automatically | +| **Publish Workflow** | Save this task as a reusable template | +| **Data Schema** | Define structured JSON output format | + + +Use a JSON schema to get typed output: + +```json +{ + "type": "object", + "properties": { + "product_name": { "type": "string" }, + "price": { "type": "number" } + } +} +``` + + +### Step 3: Run the task + +Click the send button to start. + +In the background, Skyvern opens a browser, navigates to the URL you specified (or finds it using search), and interacts with the website component to get the job done. + +## Watch the Live Browser + +Once your task starts, you'll see the execution screen with two main panels: + + + +| **Left: Task configuration** | **Center: Live Browser** | **Right: Agent Logs** | +|---------|---------|-------------| +| Shows the block being executed with its URL and prompt. The status badge indicates whether the task is running, completed, or failed. | A real-time view of the browser as Skyvern navigates. You'll see pages load, forms fill, and buttons click—exactly as if you were doing it yourself. | A real-time log of LLM's reasoning output and tool usage. Useful for troubleshooting complex workflows. | + +The **"take control"** button lets you intervene and use the agent's browser yourself if it needs help with something unexpected, like a CAPTCHA or unusual login flow. + +## Review the Results + +After the task completes, go to **Runs** and open your latest task. + + + +### Extracted Data + +The AI extracts data based on your prompt and returns it as structured JSON: + +```json +{ + "post_title": "There's a ridiculous amount of tech in a disposable vape" +} +``` + +### Results Tabs + +The results page has several tabs: + +- **Actions** — Step-by-step breakdown of every action the AI took, with screenshots and reasoning +- **Recording** — Full video replay of the browser session +- **Parameters** — The task configuration you submitted (URL, prompt, webhooks, proxy, schema) +- **Diagnostics** — Debug info for troubleshooting: LLM prompts, element trees, annotated screenshots + +## What's Next? + + + + Create reusable, multi-step automations with the visual workflow builder + + + Store credentials securely for sites that require authentication + + diff --git a/docs/docs.json b/docs/docs.json new file mode 100644 index 00000000..fbf66976 --- /dev/null +++ b/docs/docs.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://mintlify.com/docs.json", + "theme": "mint", + "name": "Skyvern", + "colors": { + "primary": "#6366F1", + "light": "#818CF8", + "dark": "#4F46E5" + }, + "logo": { + "light": "/logo/light.svg", + "dark": "/logo/dark.svg", + "href": "https://skyvern.com" + }, + "favicon": "/favicon.svg", + "navigation": { + "tabs": [ + { + "tab": "Documentation", + "groups": [ + { + "group": "Getting Started", + "pages": [ + "getting-started/quickstart", + "getting-started/core-concepts" + ] + }, + { + "group": "Running Automations", + "pages": [ + "running-automations/run-a-task", + "running-automations/task-parameters", + "running-automations/extract-structured-data" + ] + } + ] + }, + { + "tab": "Cloud UI", + "groups": [ + { + "group": "Cloud UI", + "pages": [ + "cloud/getting-started" + ] + } + ] + } + ] + }, + "navbar": { + "links": [ + { + "label": "Dashboard", + "href": "https://app.skyvern.com" + } + ], + "primary": { + "type": "button", + "label": "Get API Key", + "href": "https://app.skyvern.com/settings/api-keys" + } + }, + "footer": { + "socials": { + "github": "https://github.com/Skyvern-AI/skyvern", + "discord": "https://discord.gg/skyvern", + "twitter": "https://twitter.com/skyvernai" + } + }, + "api": { + "playground": { + "display": "interactive" + } + } +} diff --git a/docs/favicon.svg b/docs/favicon.svg new file mode 100644 index 00000000..19fb5445 --- /dev/null +++ b/docs/favicon.svg @@ -0,0 +1,4 @@ + + + S + diff --git a/docs/getting-started/core-concepts.mdx b/docs/getting-started/core-concepts.mdx new file mode 100644 index 00000000..afd194b4 --- /dev/null +++ b/docs/getting-started/core-concepts.mdx @@ -0,0 +1,406 @@ +--- +title: Core Concepts +subtitle: The building blocks of Skyvern automations +slug: getting-started/core-concepts +--- + +Skyvern has eight core concepts. Master these and you can build any browser automation. + +--- + +## Tasks + +A **Task** is a single automation job—think of it as asking Skyvern to do one thing. You provide a prompt describing the goal, and Skyvern navigates the browser to complete it. + +```python +from skyvern import Skyvern + +skyvern = Skyvern(api_key="YOUR_API_KEY") + +result = await skyvern.run_task( + prompt="Find the top 3 posts on the front page", + url="https://news.ycombinator.com", + data_extraction_schema={ + "type": "object", + "properties": { + "posts": { + "type": "array", + "items": {"type": "string"} + } + } + } +) + +print(result.output) # {"posts": ["Post 1", "Post 2", "Post 3"]} +``` + +**Key properties:** + +| Property | Description | +|----------|-------------| +| `prompt` | Natural language description of the goal (required) | +| `url` | Starting URL for the task | +| `data_extraction_schema` | JSON Schema defining expected output structure | +| `max_steps` | Maximum steps allowed (controls cost) | +| `engine` | AI model to use (see [Engines](#engines) below) | +| `browser_session_id` | Run in an existing browser session | +| `webhook_url` | Callback URL for async completion | + +**Use Tasks for:** one-off automations, quick data extraction, prototyping before building a workflow. + +When you need reusable, multi-step automations, use **Workflows** instead. + +--- + +## Workflows + +A **Workflow** is a reusable template composed of blocks. Unlike tasks, workflows can be versioned, shared across your team, and executed repeatedly with different parameters. + +``` +┌─────────────────────────────────────────────────────────────┐ +│ WORKFLOW │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ +│ │ Navigate │ → │ Login │ → │ Extract │ → │ Download │ │ +│ │ Block │ │ Block │ │ Block │ │ Block │ │ +│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ +│ │ +│ Parameters: {{search_query}}, {{max_price}} │ +│ Each block can reference outputs from previous blocks │ +└─────────────────────────────────────────────────────────────┘ +``` + +```python +result = await skyvern.run_workflow( + workflow_id="wpid_abc123", + parameters={ + "search_query": "wireless headphones", + "max_price": 100 + } +) + +print(result.output) +``` + +Workflows support Jinja templating: +- Reference parameters: `{{search_query}}` +- Reference previous block outputs: `{{extract_block.product_name}}` + +**Use Workflows for:** repeatable automations, multi-step processes, team-shared templates, complex logic with loops or conditionals. + +See [Workflow Blocks](/workflows/workflow-blocks-details) for the full block reference. + +--- + +## Blocks + +Blocks are the building units of workflows. Each block performs one specific task, and blocks execute sequentially—each can reference outputs from previous blocks. + +### Navigation & Interaction + +| Block | Purpose | +|-------|---------| +| **Navigation** | AI-guided navigation toward a goal—Skyvern figures out the clicks and inputs | +| **Action** | Perform a single specific action (click, type, select, upload) | +| **Go to URL** | Navigate directly to a specific URL | +| **Login** | Authenticate using stored credentials | +| **Wait** | Pause execution for a specified duration | +| **Human Interaction** | Pause for manual intervention (CAPTCHA, approval, etc.) | + +### Data & Files + +| Block | Purpose | +|-------|---------| +| **Extract** | Pull structured data from a page into JSON | +| **File Download** | Download files from websites | +| **File Upload** | Upload files to form fields | +| **File Parser** | Process PDFs, CSVs, and Excel files | +| **PDF Parser** | Specialized PDF text extraction | + +### Logic & Control Flow + +| Block | Purpose | +|-------|---------| +| **Conditional** | Branch workflow based on conditions (if/else) | +| **For Loop** | Repeat a sequence of blocks over a list | +| **Validation** | Assert conditions; halt workflow on failure | +| **Code** | Execute custom Python/Playwright scripts | + +### Communication & Integration + +| Block | Purpose | +|-------|---------| +| **HTTP Request** | Make API calls to external services | +| **Text Prompt** | Text-only LLM prompt (no browser interaction) | +| **Send Email** | Send email messages | + +For detailed block configuration, see [Workflow Blocks](/workflows/workflow-blocks-details). + +--- + +## Runs + +Every time you execute a task or workflow, Skyvern creates a **Run** to track progress and store outputs. + +``` + ┌→ completed + │ + ├→ failed + │ +created → queued → running ─┼→ timed_out + │ + ├→ terminated + │ + └→ canceled +``` + +```python +result = await skyvern.run_task( + prompt="Extract the main heading", + url="https://example.com" +) + +print(result.run_id) # "tsk_abc123" +print(result.status) # "completed" +print(result.output) # {"heading": "Welcome"} +``` + +**Run identifiers:** +- Task runs: `tsk_*` prefix +- Workflow runs: `wr_*` prefix + +**Run response fields:** + +| Field | Description | +|-------|-------------| +| `run_id` | Unique identifier | +| `status` | Current lifecycle state | +| `output` | Extracted data (matches your schema) | +| `recording_url` | Video of the execution | +| `screenshot_urls` | Screenshots captured during execution | +| `downloaded_files` | Files retrieved (with URLs and checksums) | +| `failure_reason` | Error details if failed | +| `step_count` | Number of steps taken | + + +**Billing:** You're billed per step. A step is one AI decision + action cycle. Use `max_steps` to cap costs during development. + + +--- + +## Credentials + +Credentials provide secure storage for authentication data. Skyvern encrypts credentials at rest and in transit, and injects them directly into the browser—**credentials are never sent to or seen by the LLM**. + +``` +┌─────────────────────────────────────────────────────────────┐ +│ SECURITY MODEL │ +│ │ +│ You store credentials Skyvern encrypts & stores │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌─────────────┐ ┌─────────────────┐ │ +│ │ Skyvern UI │ │ Encrypted Vault │ │ +│ │ or API │ ─────────── │ (or Bitwarden, │ │ +│ └─────────────┘ │ 1Password) │ │ +│ └────────┬────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────┐ │ +│ │ Login Block │ │ +│ │ injects into │ │ +│ │ browser fields │ │ +│ └─────────────────┘ │ +│ │ │ +│ LLM sees: "login happened" │ +│ LLM never sees: actual credentials │ +└─────────────────────────────────────────────────────────────┘ +``` + +**Supported credential types:** +- Usernames and passwords +- TOTP codes (authenticator apps) +- Credit cards + +**Credential sources:** +- **Skyvern** — Native encrypted storage +- **Bitwarden** — Sync from your Bitwarden vault +- **1Password** — Sync from your 1Password vault +- **Azure Key Vault** — Enterprise secret management + +See [Credentials](/credentials/introduction) for setup instructions. + +--- + +## Browser Sessions & Profiles + +Skyvern offers two ways to manage browser state across runs: + +``` +┌─────────────────────────────────────────────────────────────┐ +│ │ +│ BROWSER SESSION BROWSER PROFILE │ +│ (live, temporary) (saved, reusable) │ +│ │ +│ ┌─────────────┐ ┌─────────────┐ │ +│ │ Active │ ──save──▶ │ Snapshot │ │ +│ │ Browser │ │ of state │ │ +│ │ Instance │ ◀──restore── │ (cookies, │ │ +│ └─────────────┘ │ storage) │ │ +│ └─────────────┘ │ +│ • Expires after timeout • Persists indefinitely │ +│ • For real-time chaining • For skipping login │ +│ • Max 24 hours • Shared across team │ +│ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### Browser Sessions + +A live browser instance that maintains state across multiple tasks. Use sessions when you need to chain tasks in real-time or allow human intervention. + +```python +# Create a session (default: 60 minutes, max: 24 hours) +session = await skyvern.create_browser_session(timeout=120) + +# Run tasks in the same session +await skyvern.run_task( + prompt="Log in with the test account", + url="https://example.com/login", + browser_session_id=session.browser_session_id +) + +# Second task reuses the authenticated state +await skyvern.run_task( + prompt="Extract the account balance", + url="https://example.com/dashboard", + browser_session_id=session.browser_session_id +) + +# Clean up +await skyvern.close_browser_session( + browser_session_id=session.browser_session_id +) +``` + +**Session limits:** 5 to 1,440 minutes (24 hours max). Default: 60 minutes. + +### Browser Profiles + +A saved snapshot of browser state. Unlike sessions, profiles persist indefinitely and can be reused across days or weeks—perfect for skipping login on repeated runs. + +```python +# Create a profile from a completed run +profile = await skyvern.browser_profiles.create_browser_profile( + name="my-authenticated-profile", + workflow_run_id=run.run_id +) + +# Future runs restore the authenticated state +await skyvern.run_workflow( + workflow_id="wpid_extract_data", + browser_profile_id=profile.browser_profile_id +) +``` + +**What's saved:** Cookies, authentication tokens, local storage, session storage. + +See [Browser Sessions](/browser-sessions/introduction) for details. + +--- + +## Artifacts + +Every run generates artifacts for observability, debugging, and audit trails. + +```python +result = await skyvern.run_task( + prompt="Download the quarterly report", + url="https://example.com" +) + +print(result.recording_url) # Full video of execution +print(result.screenshot_urls) # List of screenshot URLs +print(result.downloaded_files) # [{"url": "...", "checksum": "..."}] +``` + +| Artifact | Description | +|----------|-------------| +| **Recordings** | End-to-end video of the entire run | +| **Screenshots** | Captured after each action | +| **Downloaded files** | Files retrieved during execution | +| **Logs** | JSON-structured logs at step, task, and workflow levels | +| **HAR files** | HTTP Archive data for network debugging | + +In the Skyvern UI, go to **Runs** → click a run → view the **Actions** and **Recording** tabs. + +--- + +## Engines + +Skyvern supports multiple AI engines for task execution: + +| Engine | Description | +|--------|-------------| +| `skyvern-2.0` | Latest Skyvern model (default, recommended) | +| `skyvern-1.0` | Previous Skyvern model | +| `openai-cua` | OpenAI Computer Use Agent | +| `anthropic-cua` | Anthropic Computer Use Agent | +| `ui-tars` | UI-TARS model | + +Specify the engine when running a task: + +```python +result = await skyvern.run_task( + prompt="Extract pricing data", + url="https://example.com", + engine="skyvern-2.0" +) +``` + +--- + +## Quick Reference + +| I want to... | Use | +|--------------|-----| +| Run a one-off automation | [Task](#tasks) | +| Build a reusable multi-step process | [Workflow](#workflows) | +| Keep a browser open between tasks | [Browser Session](#browser-sessions) | +| Skip login on repeated runs | [Browser Profile](#browser-profiles) | +| Store secrets securely | [Credentials](#credentials) | +| Debug a failed run | [Artifacts](#artifacts) | + +--- + +## Next Steps + + + + Run your first task in 5 minutes + + + Create multi-step automations + + + Full reference for all block types + + + Complete API documentation + + diff --git a/docs/getting-started/quickstart.mdx b/docs/getting-started/quickstart.mdx new file mode 100644 index 00000000..92250625 --- /dev/null +++ b/docs/getting-started/quickstart.mdx @@ -0,0 +1,393 @@ +--- +title: API Quickstart +slug: getting-started/quickstart +--- + +Run your first browser automation in 5 minutes. By the end of this guide, you'll scrape the top post from Hacker News using Skyvern's AI agent. + + +Prefer a visual interface? Try the [Cloud UI](/cloud/getting-started) instead — no code required. + + +## Step 1: Get your API key + +Get Skyvern API key + +Sign up at [app.skyvern.com](https://app.skyvern.com) and go to [Settings](https://app.skyvern.com/settings) to copy your API key. + +When you make API calls, Skyvern spins up a cloud browser, executes your task with AI, and returns the results. You can watch the browser live at any time. + +## Step 2: Install the SDK + + +```bash Python +pip install skyvern +``` + +```bash TypeScript +npm install @skyvern/client +``` + + + +The Skyvern SDK requires Python 3.11, 3.12, or 3.13. If you encounter version errors, try using pipx: + +```bash +pipx install skyvern +``` + +pipx installs Python packages in isolated environments while making them globally available. + + +## Step 3: Run your first task + +Let's scrape the title of the #1 post on Hacker News. You only need two parameters: + +- **`prompt`** — Natural language instructions for what the AI should do. Be specific about the data you want extracted. +- **`url`** — The starting page. Skyvern's AI will navigate from here based on your prompt. + +The SDK uses async/await because Skyvern spins up a cloud browser and executes your task remotely, which can take 30-60 seconds. + + +```python Python +import os +import asyncio +from skyvern import Skyvern + +async def main(): + client = Skyvern(api_key=os.getenv("SKYVERN_API_KEY")) + + result = await client.run_task( + prompt="Go to news.ycombinator.com and get the title of the #1 post", + url="https://news.ycombinator.com", + ) + + print(f"Run ID: {result.run_id}") + print(f"Status: {result.status}") + +asyncio.run(main()) +``` + +```typescript TypeScript +import { SkyvernClient } from "@skyvern/client"; + +async function main() { + const client = new SkyvernClient({ + apiKey: process.env.SKYVERN_API_KEY, + }); + + const result = await client.runTask({ + body: { + prompt: "Go to news.ycombinator.com and get the title of the #1 post", + url: "https://news.ycombinator.com", + }, + }); + + console.log(`Run ID: ${result.run_id}`); + console.log(`Status: ${result.status}`); +} + +main(); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Go to news.ycombinator.com and get the title of the #1 post", + "url": "https://news.ycombinator.com" + }' +``` + + +The response includes a `run_id` you'll use to check status and fetch results. + +## Step 4: Check the status + +Since tasks run asynchronously, you have two options: + +1. **Polling** — Periodically check the task status (shown below) +2. **Webhooks** — Get notified when the task completes ([see webhooks guide](/running-tasks/webhooks-faq)) + +The code below polls every 5 seconds until the task reaches a terminal state. Once complete, `run.output` contains the extracted data as a dictionary. + + +```python Python +import os +import asyncio +from skyvern import Skyvern + +async def main(): + client = Skyvern(api_key=os.getenv("SKYVERN_API_KEY")) + + result = await client.run_task( + prompt="Go to news.ycombinator.com and get the title of the #1 post", + url="https://news.ycombinator.com", + ) + + run_id = result.run_id + print(f"Task started: {run_id}") + + while True: + run = await client.get_run(run_id) + print(f"Status: {run.status}") + + if run.status in ["completed", "failed", "terminated", "timed_out", "canceled"]: + break + + await asyncio.sleep(5) + + print(f"Final status: {run.status}") + print(f"Output: {run.output}") + +asyncio.run(main()) +``` + +```typescript TypeScript +import { SkyvernClient } from "@skyvern/client"; + +async function main() { + const client = new SkyvernClient({ + apiKey: process.env.SKYVERN_API_KEY, + }); + + const result = await client.runTask({ + body: { + prompt: "Go to news.ycombinator.com and get the title of the #1 post", + url: "https://news.ycombinator.com", + }, + }); + + const runId = result.run_id; + console.log(`Task started: ${runId}`); + + while (true) { + const run = await client.getRun(runId); + console.log(`Status: ${run.status}`); + + if (["completed", "failed", "terminated", "timed_out", "canceled"].includes(run.status)) { + console.log(`Output: ${JSON.stringify(run.output)}`); + break; + } + + await new Promise((resolve) => setTimeout(resolve, 5000)); + } +} + +main(); +``` + +```bash cURL +RUN_ID="your_run_id_here" + +while true; do + RESPONSE=$(curl -s -X GET "https://api.skyvern.com/v1/runs/$RUN_ID" \ + -H "x-api-key: $SKYVERN_API_KEY") + + STATUS=$(echo "$RESPONSE" | jq -r '.status') + echo "Status: $STATUS" + + if [[ "$STATUS" == "completed" || "$STATUS" == "failed" || "$STATUS" == "terminated" || "$STATUS" == "timed_out" || "$STATUS" == "canceled" ]]; then + echo "$RESPONSE" | jq '.output' + break + fi + + sleep 5 +done +``` + + +**Run states:** +- `created` — Task initialized, not yet queued +- `queued` — Waiting for an available browser +- `running` — AI is navigating and executing +- `completed` — Task finished successfully +- `failed` — Task encountered an error +- `terminated` — Task was manually stopped +- `timed_out` — Task exceeded time limit +- `canceled` — Task was cancelled before starting + +## Step 5: View your results + +When the task completes, you'll get a response like this: + +```json +{ + "run_id": "tsk_v2_486305187432193504", + "status": "completed", + "output": { + "top_post_title": "Linux kernel framework for PCIe device emulation, in userspace" + }, + "downloaded_files": [], + "recording_url": "https://skyvern-artifacts.s3.amazonaws.com/v1/production/.../recording.webm?...", + "screenshot_urls": ["https://skyvern-artifacts.s3.amazonaws.com/v1/production/.../screenshot_final.png?..."], + "app_url": "https://app.skyvern.com/runs/wr_486305187432193510", + "step_count": 2, + "run_type": "task_v2" +} +``` + +The `output` contains whatever data the AI extracted based on your prompt. The `app_url` links to the Cloud UI where you can view the full run details. + +## Step 6: Watch the recording + +Every task is recorded. There are two ways to access recordings: + +### From the API response + +The `recording_url` field is included in every completed run response: + +```json +{ + "run_id": "tsk_v2_486305187432193504", + "status": "completed", + "recording_url": "https://skyvern-artifacts.s3.amazonaws.com/v1/production/o_485917350850524254/tsk_.../recording.webm?AWSAccessKeyId=...&Signature=...&Expires=..." +} +``` + +### From the Cloud UI + +Navigate to [Runs](https://app.skyvern.com/runs) and click on your run to see the Recording tab. + +Recording tab in Skyvern Cloud + +### What you'll see + +- **Live browser view** — Watch the AI navigate in real-time +- **Recording** — Full video replay of the session +- **Actions** — Step-by-step breakdown with screenshots +- **AI Reasoning** — See why the AI made each decision + +This is invaluable for debugging and understanding how Skyvern interprets your prompts. + +--- + +## Run with a local browser + +You can run Skyvern with a browser on your own machine. This is useful for development, debugging, or automating internal tools on your local network. + +**Prerequisites:** +- Skyvern SDK installed (`pip install skyvern`) +- PostgreSQL database (local install or Docker) +- An LLM API key (OpenAI, Anthropic, Azure OpenAI, Gemini, Ollama, or any OpenAI-compatible provider) + + +Docker is optional. If you have PostgreSQL installed locally, Skyvern will detect and use it automatically. Use `skyvern init --no-postgres` to skip database setup entirely if you're managing PostgreSQL separately. + + +### Set up local Skyvern + +```bash +skyvern init +``` + +

+ Skyvern init interactive setup wizard +

+ + +This interactive wizard will: +1. Set up your database (detects local PostgreSQL or uses Docker) +2. Configure your LLM provider +3. Choose browser mode (headless, headful, or connect to existing Chrome) +4. Generate local API credentials +5. Download the Chromium browser + +This will generate a .env file that stores your local configuration, LLM api keys and your local `BASE_URL` and `SKYVERN_API_KEY`: +```.env +ENV='local' +ENABLE_OPENAI='true' +OPENAI_API_KEY='' +... +LLM_KEY='OPENAI_GPT4O' +SECONDARY_LLM_KEY='' +BROWSER_TYPE='chromium-headful' +MAX_SCRAPING_RETRIES='0' +VIDEO_PATH='./videos' +BROWSER_ACTION_TIMEOUT_MS='5000' +MAX_STEPS_PER_RUN='50' +LOG_LEVEL='INFO' +LITELLM_LOG='CRITICAL' +DATABASE_STRING='postgresql+psycopg://skyvern@localhost/skyvern' +PORT='8000' +... +SKYVERN_BASE_URL='http://localhost:8000' +SKYVERN_API_KEY='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ5MTMzODQ2MDksInN1YiI6Im9fNDg0MjIwNjY3MzYzNzA2Njk4In0.Crwy0-y7hpMVSyhzNJGzDu_oaMvrK76RbRb7YhSo3YA' +``` + +### Start the local server + +```bash +skyvern run server +``` + +

+ Skyvern local server logs +

+ +### Run a task locally + +The only difference from cloud is the `base_url` parameter pointing to your local server. The API is identical, so the same code works in both environments — develop locally, deploy to cloud without changes. + +```python +import os +import asyncio +from skyvern import Skyvern + +async def main(): + client = Skyvern( + base_url="http://localhost:8000", + api_key=os.getenv("SKYVERN_API_KEY") + ) + + result = await client.run_task( + prompt="Go to news.ycombinator.com and get the title of the #1 post", + url="https://news.ycombinator.com", + ) + + print(f"Run ID: {result.run_id}") + +asyncio.run(main()) +``` + +A browser window will open on your machine (if you chose headful mode). Recordings and logs are saved in the directory where you started the server. + + + +--- + +## Next steps + + + + Define a schema to get typed JSON output from your automations + + + Store credentials securely for sites that require authentication + + + Chain multiple steps together for complex automations + + + Get notified when tasks complete instead of polling + + diff --git a/docs/images/Skyvern-diagram.excalidraw b/docs/images/Skyvern-diagram.excalidraw new file mode 100644 index 00000000..9bbd0bdc --- /dev/null +++ b/docs/images/Skyvern-diagram.excalidraw @@ -0,0 +1,2424 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "id": "g6UEPkTZwdgp6fHXpTYue", + "type": "rectangle", + "x": 5020.133610498352, + "y": 215.97931985294076, + "width": 847.1426295401064, + "height": 1185.9566839692557, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 271057910, + "version": 389, + "versionNonce": 1203105206, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718867, + "link": null, + "locked": false + }, + { + "id": "8DBvW1Duqk2D4K9Iq6uON", + "type": "text", + "x": 6097.453125, + "y": 599.359375, + "width": 12.159988403320312, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 557729334, + "version": 14, + "versionNonce": 1364903670, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718867, + "link": null, + "locked": false, + "text": "S", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 18, + "containerId": null, + "originalText": "S", + "lineHeight": 1.25 + }, + { + "id": "tW333cqey9esehhYBu7TN", + "type": "text", + "x": 5130.353137175972, + "y": 262.9153477363161, + "width": 609.0764066807745, + "height": 215.61761501209278, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 439783018, + "version": 334, + "versionNonce": 1044513142, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718867, + "link": null, + "locked": false, + "text": "Skyvern", + "fontSize": 172.49409200967403, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 152.00000000000026, + "containerId": null, + "originalText": "Skyvern", + "lineHeight": 1.25 + }, + { + "id": "FFCNXMgzfsp51cxIRY_dw", + "type": "rectangle", + "x": 5231.7207713964335, + "y": -2.711234543365663, + "width": 1622.2311580882351, + "height": 160.8685661764706, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 1726200554, + "version": 80, + "versionNonce": 1685285162, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718867, + "link": null, + "locked": false + }, + { + "id": "XM0u0KhJWqKjfjrFogGf9", + "type": "text", + "x": 5280.847609631728, + "y": 45.324151486046276, + "width": 1514.8404651155656, + "height": 70.26424632352939, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 1126078838, + "version": 206, + "versionNonce": 1571985014, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718867, + "link": null, + "locked": false, + "text": "Prompt: Go to Geico and generate an insurance quote", + "fontSize": 56.2113970588235, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 50.000000000000014, + "containerId": null, + "originalText": "Prompt: Go to Geico and generate an insurance quote", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 587, + "versionNonce": 146057706, + "isDeleted": false, + "id": "Rx3iADCDZop9A09een65H", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5038.010982793492, + "y": 774.2821018536929, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 799.8736213235297, + "height": 132.91590073529414, + "seed": 1201001526, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "g8eaSe_EX7x9SeHWeHA_B" + }, + { + "id": "4c3uVRqeBB2jZhAyHjrgH", + "type": "arrow" + }, + { + "id": "-0jCmfJUKf6v8fzgMJ_RJ", + "type": "arrow" + } + ], + "updated": 1709525805893, + "link": null, + "locked": false + }, + { + "id": "g8eaSe_EX7x9SeHWeHA_B", + "type": "text", + "x": 5093.067910642757, + "y": 818.24005222134, + "width": 689.759765625, + "height": 45, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 1377540534, + "version": 454, + "versionNonce": 1901400746, + "isDeleted": false, + "boundElements": null, + "updated": 1709525810203, + "link": null, + "locked": false, + "text": "Step 3: Extract interactable elements", + "fontSize": 36, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 32, + "containerId": "Rx3iADCDZop9A09een65H", + "originalText": "Step 3: Extract interactable elements", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 644, + "versionNonce": 1463001386, + "isDeleted": false, + "id": "MfXNvwv3aRSRpkDIoNHG3", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5036.39103794055, + "y": 928.1998408242827, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 799.8736213235297, + "height": 132.91590073529414, + "seed": 543803562, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "gZ6yKr25Trl2Rq86MK5_T" + }, + { + "id": "N14QMNmvuPjsnXGW7SonM", + "type": "arrow" + } + ], + "updated": 1709525812576, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 584, + "versionNonce": 20057590, + "isDeleted": false, + "id": "gZ6yKr25Trl2Rq86MK5_T", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5119.725950408955, + "y": 972.1577911919297, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 633.2037963867188, + "height": 45, + "seed": 977216362, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525815683, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Step 4: Call a LLM to plan actions", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "MfXNvwv3aRSRpkDIoNHG3", + "originalText": "Step 4: Call a LLM to plan actions", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "id": "u0ykYNV_HhUaduAZ6E0w2", + "type": "arrow", + "x": 5855.560385367021, + "y": 525.8756549454152, + "width": 321.5877757352937, + "height": 233.00978229426056, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 1635728874, + "version": 833, + "versionNonce": 1303151158, + "isDeleted": false, + "boundElements": null, + "updated": 1709525789905, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 321.5877757352937, + -233.00978229426056 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "SJh7bigchaUzh9FSmRZMZ", + "focus": 0.8299457673821683, + "gap": 13.849954044122569 + }, + "endBinding": { + "elementId": "J2z3LruV51iXuj4N_VcDB", + "focus": 0.9270480868271056, + "gap": 7.490808823522002 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "OxnRRXwsQitgt-If-jPem", + "type": "rectangle", + "x": 6088.476286102313, + "y": 172.67939045663513, + "width": 790.1424632352946, + "height": 455.15854779411745, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 541969066, + "version": 485, + "versionNonce": 505971754, + "isDeleted": false, + "boundElements": [ + { + "id": "u0ykYNV_HhUaduAZ6E0w2", + "type": "arrow" + } + ], + "updated": 1709525718867, + "link": null, + "locked": false + }, + { + "id": "JJfqzpfO_h-69wvNDUm4z", + "type": "line", + "x": 6088.108639043489, + "y": 253.06771766251768, + "width": 784.0992647058829, + "height": 0.12637867647072198, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 1614794602, + "version": 358, + "versionNonce": 431008630, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718867, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 784.0992647058829, + -0.12637867647072198 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": null + }, + { + "id": "NMvYzVw6aGPHjaO1xNajv", + "type": "ellipse", + "x": 6108.007536102313, + "y": 202.6656036919294, + "width": 33.432904411764866, + "height": 32.43336397058829, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 544549866, + "version": 251, + "versionNonce": 395996906, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718867, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 313, + "versionNonce": 414698678, + "isDeleted": false, + "id": "ptQ5B_qwPPn1JbVPwaJLk", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6162.821414778784, + "y": 203.13090700075293, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 33.432904411764866, + "height": 32.43336397058829, + "seed": 578727862, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1709525718867, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 287, + "versionNonce": 1224802730, + "isDeleted": false, + "id": "WjaKChE0wYk_YgcBcBfeJ", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6216.796598602313, + "y": 202.13136655957646, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 33.432904411764866, + "height": 32.43336397058829, + "seed": 1217575478, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1709525718867, + "link": null, + "locked": false + }, + { + "id": "kH0vKRIFnMq_UeS5aMBmf", + "type": "rectangle", + "x": 6302.998344925841, + "y": 174.44869192722354, + "width": 279.3313419117658, + "height": 77.24034926470586, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 1802638838, + "version": 349, + "versionNonce": 80266742, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "VYgscTKWn8Y4Jg-kyujjN" + } + ], + "updated": 1709525718867, + "link": null, + "locked": false + }, + { + "id": "VYgscTKWn8Y4Jg-kyujjN", + "type": "text", + "x": 6360.33204566688, + "y": 190.56886655957646, + "width": 164.6639404296875, + "height": 45, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 1475975786, + "version": 197, + "versionNonce": 495402090, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718867, + "link": null, + "locked": false, + "text": "Geico.com", + "fontSize": 36, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 32, + "containerId": "kH0vKRIFnMq_UeS5aMBmf", + "originalText": "Geico.com", + "lineHeight": 1.25 + }, + { + "id": "OYJ0K3D89u2EvJ3dUekc8", + "type": "rectangle", + "x": 6207.731800808196, + "y": 340.5217617801642, + "width": 234.00735294117635, + "height": 71.36948529411767, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 811579446, + "version": 713, + "versionNonce": 1660428074, + "isDeleted": false, + "boundElements": [ + { + "id": "4c3uVRqeBB2jZhAyHjrgH", + "type": "arrow" + } + ], + "updated": 1709525718867, + "link": null, + "locked": false + }, + { + "id": "J20hWXeF7gbCeY0o6nNYz", + "type": "text", + "x": 6198.138510367017, + "y": 275.81587942722354, + "width": 536.039794921875, + "height": 45, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 1431126186, + "version": 330, + "versionNonce": 1246282166, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718867, + "link": null, + "locked": false, + "text": "When did you get your license?", + "fontSize": 36, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 32, + "containerId": null, + "originalText": "When did you get your license?", + "lineHeight": 1.25 + }, + { + "id": "hs4uy06yfEU8_YHkr2xH0", + "type": "text", + "x": 6223.276378014077, + "y": 356.1697397213411, + "width": 210.8655426860632, + "height": 42.81709558823524, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 1256407978, + "version": 322, + "versionNonce": 577968886, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718868, + "link": null, + "locked": false, + "text": "YYYY/MM/DD", + "fontSize": 34.253676470588196, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 29.999999999999993, + "containerId": null, + "originalText": "YYYY/MM/DD", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 756, + "versionNonce": 1176024938, + "isDeleted": false, + "id": "FThLbXNsVVxBT5Rd5HEEt", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6478.837039778784, + "y": 431.26165148604707, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 234.00735294117635, + "height": 71.36948529411767, + "seed": 583350, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "9vQ0W7OacIXj1utJEbVOW" + }, + { + "id": "-0jCmfJUKf6v8fzgMJ_RJ", + "type": "arrow" + } + ], + "updated": 1709525718868, + "link": null, + "locked": false + }, + { + "id": "9vQ0W7OacIXj1utJEbVOW", + "type": "text", + "x": 6554.116732484724, + "y": 444.44639413310585, + "width": 83.44796752929688, + "height": 45, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 521942710, + "version": 276, + "versionNonce": 1317030966, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718868, + "link": null, + "locked": false, + "text": "Next", + "fontSize": 36, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 32, + "containerId": "FThLbXNsVVxBT5Rd5HEEt", + "originalText": "Next", + "lineHeight": 1.25 + }, + { + "id": "4c3uVRqeBB2jZhAyHjrgH", + "type": "arrow", + "x": 5844.68033021996, + "y": 787.0217664699799, + "width": 364.65785048012276, + "height": 370.7072657192259, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 1362153258, + "version": 1081, + "versionNonce": 1079523882, + "isDeleted": false, + "boundElements": null, + "updated": 1709525805893, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 364.65785048012276, + -370.7072657192259 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "Rx3iADCDZop9A09een65H", + "focus": 0.7605240781476672, + "gap": 6.795726102937806 + }, + "endBinding": { + "elementId": "OYJ0K3D89u2EvJ3dUekc8", + "focus": 0.49928180564276564, + "gap": 4.423253676472086 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "-0jCmfJUKf6v8fzgMJ_RJ", + "type": "arrow", + "x": 5845.6109368376065, + "y": 824.5370578943607, + "width": 622.7288237454377, + "height": 321.1578978582746, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 1601432630, + "version": 1041, + "versionNonce": 523974570, + "isDeleted": false, + "boundElements": null, + "updated": 1709525805893, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 622.7288237454377, + -321.1578978582746 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "Rx3iADCDZop9A09een65H", + "focus": 0.7114795089668824, + "gap": 7.726332720584651 + }, + "endBinding": { + "elementId": "FThLbXNsVVxBT5Rd5HEEt", + "focus": 0.3053618949231662, + "gap": 10.523897058823422 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "Z4zhvosj7MDWKDlzC0Bst", + "type": "rectangle", + "x": 6133.593473602313, + "y": 693.3825154566357, + "width": 969.6691176470597, + "height": 443.8304227941171, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 1027240746, + "version": 555, + "versionNonce": 510485738, + "isDeleted": false, + "boundElements": [ + { + "id": "N14QMNmvuPjsnXGW7SonM", + "type": "arrow" + } + ], + "updated": 1709525718868, + "link": null, + "locked": false + }, + { + "id": "9YOw18DZAiXbD5RU_1I4S", + "type": "rectangle", + "x": 6149.884833896431, + "y": 707.6977728095765, + "width": 538.2123161764716, + "height": 145, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 244052714, + "version": 475, + "versionNonce": 637876138, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "MyXG7QtlsRUIpBu7b_gVA" + } + ], + "updated": 1709525718868, + "link": null, + "locked": false + }, + { + "id": "MyXG7QtlsRUIpBu7b_gVA", + "type": "text", + "x": 6159.305078898729, + "y": 712.6977728095765, + "width": 519.371826171875, + "height": 135, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 2016233578, + "version": 883, + "versionNonce": 298512374, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718868, + "link": null, + "locked": false, + "text": "We're trying to generate an \ninsurance quote. What should\nwe do here?", + "fontSize": 36, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 122, + "containerId": "9YOw18DZAiXbD5RU_1I4S", + "originalText": "We're trying to generate an insurance quote. What should we do here?", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 909, + "versionNonce": 2023010922, + "isDeleted": false, + "id": "SoI9KZ6WB_t-1kq_IIPVd", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6647.598528749373, + "y": 860.0599051625177, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 430.67555147058835, + "height": 145, + "seed": 1345335606, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "rkmSMBVKSZWWrr9aA1dyf" + } + ], + "updated": 1709525718868, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1262, + "versionNonce": 437627498, + "isDeleted": false, + "id": "rkmSMBVKSZWWrr9aA1dyf", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6663.694391642871, + "y": 887.5599051625177, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 398.48382568359375, + "height": 90, + "seed": 1757452918, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525979101, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Action 1: Fill in license \ndate of: 2010/03/10", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "SoI9KZ6WB_t-1kq_IIPVd", + "originalText": "Action 1: Fill in license date of: 2010/03/10", + "lineHeight": 1.25, + "baseline": 77 + }, + { + "id": "N14QMNmvuPjsnXGW7SonM", + "type": "arrow", + "x": 5845.748804484668, + "y": 928.4341205937844, + "width": 276.96461397058647, + "height": 91.92101568108262, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 326611050, + "version": 1329, + "versionNonce": 321616234, + "isDeleted": false, + "boundElements": null, + "updated": 1709525812576, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 276.96461397058647, + -91.92101568108262 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "MfXNvwv3aRSRpkDIoNHG3", + "gap": 9.484145220588289, + "focus": 0.3505465312545591 + }, + "endBinding": { + "elementId": "Z4zhvosj7MDWKDlzC0Bst", + "gap": 10.880055147058556, + "focus": 0.6355530133476511 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "type": "rectangle", + "version": 798, + "versionNonce": 556205686, + "isDeleted": false, + "id": "OhMEx_L17jeyoDhz3EOMR", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5034.012821028784, + "y": 1221.3294364125181, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 799.8736213235297, + "height": 132.91590073529414, + "seed": 134469622, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "diH2_j2sx4jydu57C6K5U" + }, + { + "id": "xFFihnpoB0szgNjDciJvP", + "type": "arrow" + } + ], + "updated": 1709525846309, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 747, + "versionNonce": 2025338410, + "isDeleted": false, + "id": "diH2_j2sx4jydu57C6K5U", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5297.29368686633, + "y": 1265.2873867801652, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 273.3118896484375, + "height": 45, + "seed": 485583158, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525860196, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Step 6: Repeat", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "OhMEx_L17jeyoDhz3EOMR", + "originalText": "Step 6: Repeat", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "id": "xFFihnpoB0szgNjDciJvP", + "type": "arrow", + "x": 5025.408312102143, + "y": 1219.0621634315676, + "width": 96.24310661764775, + "height": 631.3887651764887, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 821273514, + "version": 1149, + "versionNonce": 10772726, + "isDeleted": false, + "boundElements": null, + "updated": 1709525846309, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -84.12871717630242, + -442.2812104749323 + ], + [ + 12.114389441345338, + -631.3887651764887 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "OhMEx_L17jeyoDhz3EOMR", + "focus": -0.9585304771065847, + "gap": 8.898207720591017 + }, + "endBinding": { + "elementId": "SJh7bigchaUzh9FSmRZMZ", + "focus": 0.8643395663753203, + "gap": 4.3141084558801595 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "UPN9jjo2ARx-vVr_qzRd_", + "type": "text", + "x": 6995.737315514072, + "y": 713.8765411919293, + "width": 70.7039794921875, + "height": 45, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 2, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 801704298, + "version": 45, + "versionNonce": 1199960106, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718868, + "link": null, + "locked": false, + "text": "LLM", + "fontSize": 36, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 32, + "containerId": null, + "originalText": "LLM", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 998, + "versionNonce": 1345322870, + "isDeleted": false, + "id": "7WNlW7KHIIoHH0AmiDdow", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6652.044760367015, + "y": 1028.1780117801645, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 430.67555147058835, + "height": 82.47702205882388, + "seed": 144861558, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "20ysVYXvGuBvAQsGzkWaT" + } + ], + "updated": 1709525718868, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1370, + "versionNonce": 174742250, + "isDeleted": false, + "id": "20ysVYXvGuBvAQsGzkWaT", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6690.0825940857085, + "y": 1046.9165228095765, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 354.5998840332031, + "height": 45, + "seed": 2126629558, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525718868, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Action 2: Click Next", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "7WNlW7KHIIoHH0AmiDdow", + "originalText": "Action 2: Click Next", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "type": "text", + "version": 75, + "versionNonce": 1814864054, + "isDeleted": false, + "id": "FKjCUamSYxdAPZWK4TgfG", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6093.50785245119, + "y": 1596.4169011106708, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 12.159988403320312, + "height": 25, + "seed": 1300297706, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525718868, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "S", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "S", + "lineHeight": 1.25, + "baseline": 18 + }, + { + "type": "line", + "version": 452, + "versionNonce": 854814122, + "isDeleted": false, + "id": "i0fJXOgbd2eCrEJEzHOZz", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6084.16336649468, + "y": 1250.1252437731885, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 874.2876838235297, + "height": 3.630514705882433, + "seed": 1932421802, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1709525718868, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 874.2876838235297, + -3.630514705882433 + ] + ] + }, + { + "type": "ellipse", + "version": 312, + "versionNonce": 981670390, + "isDeleted": false, + "id": "55EtPkr1WYz3eXtT156U-", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6104.062263553504, + "y": 1199.7231298026002, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 33.432904411764866, + "height": 32.43336397058829, + "seed": 1344243050, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1709525718868, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 374, + "versionNonce": 1984702570, + "isDeleted": false, + "id": "7Ir9qUC-J10z8YJdXsFil", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6158.876142229974, + "y": 1200.1884331114238, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 33.432904411764866, + "height": 32.43336397058829, + "seed": 228542506, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1709525718868, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 348, + "versionNonce": 37251894, + "isDeleted": false, + "id": "THo01XRKhkCiNsmM2KTfe", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6212.851326053504, + "y": 1199.1888926702472, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 33.432904411764866, + "height": 32.43336397058829, + "seed": 1939387114, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1709525718868, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 410, + "versionNonce": 742361898, + "isDeleted": false, + "id": "zq_EGEm81_Ru6z0o5RnLL", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6299.053072377032, + "y": 1171.5062180378943, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 279.3313419117658, + "height": 77.24034926470586, + "seed": 345425322, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "OdBJ2GP46ob9E_NK8YFqP" + } + ], + "updated": 1709525718868, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 258, + "versionNonce": 1639027830, + "isDeleted": false, + "id": "OdBJ2GP46ob9E_NK8YFqP", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6356.386773118071, + "y": 1187.6263926702472, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 164.6639404296875, + "height": 45, + "seed": 2042921066, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525718868, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Geico.com", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "zq_EGEm81_Ru6z0o5RnLL", + "originalText": "Geico.com", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "type": "text", + "version": 419, + "versionNonce": 71452842, + "isDeleted": false, + "id": "6QJmhdDi4Ep_TmFZM_wjE", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6158.864653259384, + "y": 1289.4864570084824, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 738.9357299804688, + "height": 45, + "seed": 242937322, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525718868, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "What's the make model year of your car?", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "What's the make model year of your car?", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "type": "rectangle", + "version": 781, + "versionNonce": 346292726, + "isDeleted": false, + "id": "LYbvMIn8yNzkScpwnoIo9", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6664.149579729976, + "y": 1520.311365096718, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 234.00735294117635, + "height": 71.36948529411767, + "seed": 1200880490, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "xu_gQHA1npkl7v6AGXZdV" + } + ], + "updated": 1709525957091, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 302, + "versionNonce": 939283254, + "isDeleted": false, + "id": "xu_gQHA1npkl7v6AGXZdV", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6739.429272435916, + "y": 1533.4961077437767, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 83.44796752929688, + "height": 45, + "seed": 1259666986, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525957091, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Next", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "LYbvMIn8yNzkScpwnoIo9", + "originalText": "Next", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "type": "rectangle", + "version": 597, + "versionNonce": 1440512554, + "isDeleted": false, + "id": "6rDEatPJ6OWz2tH9-LSUJ", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 6063.14310595525, + "y": 1164.309675383106, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 934.0073529411766, + "height": 456.9967830882352, + "seed": 1540442730, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "id": "nxoPelw3wE8LEf-Ey2WMr", + "type": "arrow" + } + ], + "updated": 1709525869623, + "link": null, + "locked": false + }, + { + "id": "0BPspmxW5-EnXGfbmuddY", + "type": "text", + "x": 6199.218473602307, + "y": 1365.131136780165, + "width": 88.81196594238281, + "height": 45, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 2, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 130014506, + "version": 68, + "versionNonce": 294736106, + "isDeleted": false, + "boundElements": null, + "updated": 1709525718868, + "link": null, + "locked": false, + "text": "Make", + "fontSize": 36, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "baseline": 32, + "containerId": null, + "originalText": "Make", + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 182, + "versionNonce": 2036284778, + "isDeleted": false, + "id": "jVR7FAsIv9w6ULP5GNSn3", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 6198.068464895824, + "y": 1425.6044823684006, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 97.16395568847656, + "height": 45, + "seed": 1311642346, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525951371, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Model", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Model", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "type": "text", + "version": 171, + "versionNonce": 1134473974, + "isDeleted": false, + "id": "DqlCBus7gz0D_YXOBDSLq", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 6206.082267816892, + "y": 1475.4781036919294, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 77.75996398925781, + "height": 45, + "seed": 818732534, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525954960, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Year", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Year", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "type": "rectangle", + "version": 951, + "versionNonce": 1849455018, + "isDeleted": false, + "id": "SJh7bigchaUzh9FSmRZMZ", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5041.836809999369, + "y": 463.574381265459, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 799.8736213235297, + "height": 132.91590073529414, + "seed": 1616456246, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "8monUZMbS0CLimZREYSHC" + }, + { + "id": "xFFihnpoB0szgNjDciJvP", + "type": "arrow" + }, + { + "id": "u0ykYNV_HhUaduAZ6E0w2", + "type": "arrow" + } + ], + "updated": 1709525747929, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 841, + "versionNonce": 516394934, + "isDeleted": false, + "id": "8monUZMbS0CLimZREYSHC", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5185.867706354493, + "y": 507.5323316331061, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 511.81182861328125, + "height": 45, + "seed": 1533178742, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525759518, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Step 1: Draw Bounding Boxes", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "SJh7bigchaUzh9FSmRZMZ", + "originalText": "Step 1: Draw Bounding Boxes", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "type": "rectangle", + "version": 924, + "versionNonce": 174287274, + "isDeleted": false, + "id": "mujam8Ii0EAp04bVapS5Q", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5042.342324705247, + "y": 622.2370650889882, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 799.8736213235297, + "height": 132.91590073529414, + "seed": 338435178, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "0wv0IsjZe3u7vdSqZNfmv" + } + ], + "updated": 1709525799427, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 793, + "versionNonce": 1448911978, + "isDeleted": false, + "id": "0wv0IsjZe3u7vdSqZNfmv", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5066.025229117012, + "y": 666.1950154566352, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 752.5078125, + "height": 45, + "seed": 1912667946, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525799427, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Step 2. Parse HTML + extract the image", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "mujam8Ii0EAp04bVapS5Q", + "originalText": "Step 2. Parse HTML + extract the image", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "id": "bBoDOGJT9JWKEpLj73uFG", + "type": "rectangle", + "x": 6199.52867580819, + "y": 327.1945558978118, + "width": 256.6636029411766, + "height": 99.51746323529403, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 2, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 918784362, + "version": 75, + "versionNonce": 827743466, + "isDeleted": false, + "boundElements": null, + "updated": 1709525764811, + "link": null, + "locked": false + }, + { + "id": "J2z3LruV51iXuj4N_VcDB", + "type": "rectangle", + "x": 6184.638969925837, + "y": 270.34712942722354, + "width": 571.174172794118, + "height": 54.710477941176464, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 2, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 1628385194, + "version": 65, + "versionNonce": 245151350, + "isDeleted": false, + "boundElements": [ + { + "id": "u0ykYNV_HhUaduAZ6E0w2", + "type": "arrow" + } + ], + "updated": 1709525789273, + "link": null, + "locked": false + }, + { + "id": "RJqXaNwOPoanjYbpxNytm", + "type": "rectangle", + "x": 6469.174815514072, + "y": 420.33564045663536, + "width": 257.6056985294126, + "height": 95.22058823529403, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 2, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 1113120682, + "version": 61, + "versionNonce": 1081029802, + "isDeleted": false, + "boundElements": null, + "updated": 1709525781209, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 759, + "versionNonce": 1857035434, + "isDeleted": false, + "id": "8SnbL2jLVLBTkKIJHELoa", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5034.162177646424, + "y": 1072.8344915595767, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 799.8736213235297, + "height": 132.91590073529414, + "seed": 2030955370, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "EyaK14IxW30HhpTQh0v2d" + }, + { + "id": "nxoPelw3wE8LEf-Ey2WMr", + "type": "arrow" + } + ], + "updated": 1709525869622, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 718, + "versionNonce": 1328208694, + "isDeleted": false, + "id": "EyaK14IxW30HhpTQh0v2d", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 5217.1090591089705, + "y": 1116.7924419272238, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 433.9798583984375, + "height": 45, + "seed": 399568426, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525855979, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "Step 5: Execute actions", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "8SnbL2jLVLBTkKIJHELoa", + "originalText": "Step 5: Execute actions", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "id": "nxoPelw3wE8LEf-Ey2WMr", + "type": "arrow", + "x": 5838.062683161132, + "y": 1137.1325154566352, + "width": 211.2362132352937, + "height": 236.1213235294117, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 2, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "seed": 604091382, + "version": 45, + "versionNonce": 345700202, + "isDeleted": false, + "boundElements": null, + "updated": 1709525869622, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 211.2362132352937, + 236.1213235294117 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "8SnbL2jLVLBTkKIJHELoa", + "focus": -0.8835529403930085, + "gap": 4.026884191177487 + }, + "endBinding": { + "elementId": "6rDEatPJ6OWz2tH9-LSUJ", + "focus": -0.6901109018873545, + "gap": 13.844209558824332 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "iQjZhS4SlCVbdLyyDwryO", + "type": "rectangle", + "x": 6350.424815514072, + "y": 1366.498324280165, + "width": 229.04411764705947, + "height": 55, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "seed": 616755434, + "version": 82, + "versionNonce": 1503437738, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "KwkoSVnHtbthL5mKVKTpp" + } + ], + "updated": 1709525941393, + "link": null, + "locked": false + }, + { + "id": "KwkoSVnHtbthL5mKVKTpp", + "type": "text", + "x": 6365.532880502153, + "y": 1371.498324280165, + "width": 198.82798767089844, + "height": 45, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "groupIds": [], + "frameId": null, + "roundness": null, + "seed": 1001514474, + "version": 38, + "versionNonce": 509517418, + "isDeleted": false, + "boundElements": null, + "updated": 1709525941394, + "link": null, + "locked": false, + "text": " v", + "fontSize": 36, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "baseline": 32, + "containerId": "iQjZhS4SlCVbdLyyDwryO", + "originalText": " v", + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 136, + "versionNonce": 203495274, + "isDeleted": false, + "id": "AiAJbvkQGKesySwB5AZdQ", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 6347.5066169846605, + "y": 1416.3880301625181, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 229.04411764705947, + "height": 55, + "seed": 698384042, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "FEi2Wn3gFUhT_zkXt6nwP" + } + ], + "updated": 1709525945961, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 92, + "versionNonce": 933141034, + "isDeleted": false, + "id": "FEi2Wn3gFUhT_zkXt6nwP", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 6362.614681972741, + "y": 1421.3880301625181, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 198.82798767089844, + "height": 45, + "seed": 388962666, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525945961, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": " v", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "AiAJbvkQGKesySwB5AZdQ", + "originalText": " v", + "lineHeight": 1.25, + "baseline": 32 + }, + { + "type": "rectangle", + "version": 193, + "versionNonce": 1414701814, + "isDeleted": false, + "id": "3CJG6PNDOaePM3lUbLPXd", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 6349.2299625728965, + "y": 1467.6747948684, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 229.04411764705947, + "height": 55, + "seed": 2094028534, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "4vC4m0bZ67xgWsieA86uF" + } + ], + "updated": 1709525960926, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 150, + "versionNonce": 724489270, + "isDeleted": false, + "id": "4vC4m0bZ67xgWsieA86uF", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 6364.338027560977, + "y": 1472.6747948684, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 198.82798767089844, + "height": 45, + "seed": 1641416758, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1709525960926, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": " v", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "3CJG6PNDOaePM3lUbLPXd", + "originalText": " v", + "lineHeight": 1.25, + "baseline": 32 + } + ], + "appState": { + "gridSize": null, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/docs/images/advanced-settings-discover.png b/docs/images/advanced-settings-discover.png new file mode 100644 index 00000000..edacef89 Binary files /dev/null and b/docs/images/advanced-settings-discover.png differ diff --git a/docs/images/api_key_image.png b/docs/images/api_key_image.png new file mode 100644 index 00000000..b512bee8 Binary files /dev/null and b/docs/images/api_key_image.png differ diff --git a/docs/images/bci_seguros_recording.gif b/docs/images/bci_seguros_recording.gif new file mode 100644 index 00000000..43c33d31 Binary files /dev/null and b/docs/images/bci_seguros_recording.gif differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_create_collection.png b/docs/images/bitwarden/bitwarden_tutorial_create_collection.png new file mode 100644 index 00000000..3796a3ee Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_create_collection.png differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_create_collection_access.png b/docs/images/bitwarden/bitwarden_tutorial_create_collection_access.png new file mode 100644 index 00000000..606772d5 Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_create_collection_access.png differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_create_collection_name.png b/docs/images/bitwarden/bitwarden_tutorial_create_collection_name.png new file mode 100644 index 00000000..98cc57be Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_create_collection_name.png differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_create_collection_uuid.png b/docs/images/bitwarden/bitwarden_tutorial_create_collection_uuid.png new file mode 100644 index 00000000..ca6fd787 Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_create_collection_uuid.png differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_create_organization.png b/docs/images/bitwarden/bitwarden_tutorial_create_organization.png new file mode 100644 index 00000000..2d2722d0 Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_create_organization.png differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_create_skyvern_task_block.png b/docs/images/bitwarden/bitwarden_tutorial_create_skyvern_task_block.png new file mode 100644 index 00000000..3ba3148a Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_create_skyvern_task_block.png differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_create_skyvern_workflow.png b/docs/images/bitwarden/bitwarden_tutorial_create_skyvern_workflow.png new file mode 100644 index 00000000..1e57df4f Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_create_skyvern_workflow.png differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_goto_admin.png b/docs/images/bitwarden/bitwarden_tutorial_goto_admin.png new file mode 100644 index 00000000..bd49ba50 Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_goto_admin.png differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_goto_members.png b/docs/images/bitwarden/bitwarden_tutorial_goto_members.png new file mode 100644 index 00000000..2a3b3c6f Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_goto_members.png differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_invite_member.png b/docs/images/bitwarden/bitwarden_tutorial_invite_member.png new file mode 100644 index 00000000..e1e31f87 Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_invite_member.png differ diff --git a/docs/images/bitwarden/bitwarden_tutorial_invite_skyvern.png b/docs/images/bitwarden/bitwarden_tutorial_invite_skyvern.png new file mode 100644 index 00000000..c506e664 Binary files /dev/null and b/docs/images/bitwarden/bitwarden_tutorial_invite_skyvern.png differ diff --git a/docs/images/block_example_v2.png b/docs/images/block_example_v2.png new file mode 100644 index 00000000..672b4287 Binary files /dev/null and b/docs/images/block_example_v2.png differ diff --git a/docs/images/claude_mcp_demo.mp4 b/docs/images/claude_mcp_demo.mp4 new file mode 100644 index 00000000..17cdf729 Binary files /dev/null and b/docs/images/claude_mcp_demo.mp4 differ diff --git a/docs/images/cloud/discover-page.png b/docs/images/cloud/discover-page.png new file mode 100644 index 00000000..77314df2 Binary files /dev/null and b/docs/images/cloud/discover-page.png differ diff --git a/docs/images/cloud/live-browser-view.png b/docs/images/cloud/live-browser-view.png new file mode 100644 index 00000000..28507f40 Binary files /dev/null and b/docs/images/cloud/live-browser-view.png differ diff --git a/docs/images/cloud/results-overview.png b/docs/images/cloud/results-overview.png new file mode 100644 index 00000000..c311217c Binary files /dev/null and b/docs/images/cloud/results-overview.png differ diff --git a/docs/images/contact_forms.gif b/docs/images/contact_forms.gif new file mode 100644 index 00000000..202312f6 Binary files /dev/null and b/docs/images/contact_forms.gif differ diff --git a/docs/images/credential_management/add_credit_card.png b/docs/images/credential_management/add_credit_card.png new file mode 100644 index 00000000..30cbf5fb Binary files /dev/null and b/docs/images/credential_management/add_credit_card.png differ diff --git a/docs/images/credential_management/add_credit_card_detail.png b/docs/images/credential_management/add_credit_card_detail.png new file mode 100644 index 00000000..2b7411d2 Binary files /dev/null and b/docs/images/credential_management/add_credit_card_detail.png differ diff --git a/docs/images/credential_management/add_password.png b/docs/images/credential_management/add_password.png new file mode 100644 index 00000000..1aa3c0f8 Binary files /dev/null and b/docs/images/credential_management/add_password.png differ diff --git a/docs/images/credential_management/add_password_detail.png b/docs/images/credential_management/add_password_detail.png new file mode 100644 index 00000000..5a03273b Binary files /dev/null and b/docs/images/credential_management/add_password_detail.png differ diff --git a/docs/images/credential_management/delete_credit_card.png b/docs/images/credential_management/delete_credit_card.png new file mode 100644 index 00000000..dbce98a5 Binary files /dev/null and b/docs/images/credential_management/delete_credit_card.png differ diff --git a/docs/images/credential_management/delete_password.png b/docs/images/credential_management/delete_password.png new file mode 100644 index 00000000..8e3e5513 Binary files /dev/null and b/docs/images/credential_management/delete_password.png differ diff --git a/docs/images/cursor_search_jobs.mp4 b/docs/images/cursor_search_jobs.mp4 new file mode 100644 index 00000000..0794dbbe Binary files /dev/null and b/docs/images/cursor_search_jobs.mp4 differ diff --git a/docs/images/discover-page.png b/docs/images/discover-page.png new file mode 100644 index 00000000..9baae485 Binary files /dev/null and b/docs/images/discover-page.png differ diff --git a/docs/images/edd_services.gif b/docs/images/edd_services.gif new file mode 100644 index 00000000..e0fd192b Binary files /dev/null and b/docs/images/edd_services.gif differ diff --git a/docs/images/finditparts_recording_crop.gif b/docs/images/finditparts_recording_crop.gif new file mode 100644 index 00000000..c874f8e8 Binary files /dev/null and b/docs/images/finditparts_recording_crop.gif differ diff --git a/docs/images/geico_shu_recording_cropped.gif b/docs/images/geico_shu_recording_cropped.gif new file mode 100644 index 00000000..3d5617cb Binary files /dev/null and b/docs/images/geico_shu_recording_cropped.gif differ diff --git a/docs/images/get-api-key.png b/docs/images/get-api-key.png new file mode 100644 index 00000000..9d12a1ce Binary files /dev/null and b/docs/images/get-api-key.png differ diff --git a/docs/images/invoice_downloading.gif b/docs/images/invoice_downloading.gif new file mode 100644 index 00000000..78732721 Binary files /dev/null and b/docs/images/invoice_downloading.gif differ diff --git a/docs/images/invoice_downloading_workflow_example.png b/docs/images/invoice_downloading_workflow_example.png new file mode 100644 index 00000000..41162917 Binary files /dev/null and b/docs/images/invoice_downloading_workflow_example.png differ diff --git a/docs/images/job_application_demo.gif b/docs/images/job_application_demo.gif new file mode 100644 index 00000000..6a7503d0 Binary files /dev/null and b/docs/images/job_application_demo.gif differ diff --git a/docs/images/makecom/makecom_new_connection.png b/docs/images/makecom/makecom_new_connection.png new file mode 100644 index 00000000..6124d757 Binary files /dev/null and b/docs/images/makecom/makecom_new_connection.png differ diff --git a/docs/images/makecom/makecom_run_task.png b/docs/images/makecom/makecom_run_task.png new file mode 100644 index 00000000..073da0a1 Binary files /dev/null and b/docs/images/makecom/makecom_run_task.png differ diff --git a/docs/images/makecom/makecom_search_skyvern.png b/docs/images/makecom/makecom_search_skyvern.png new file mode 100644 index 00000000..c5aed66c Binary files /dev/null and b/docs/images/makecom/makecom_search_skyvern.png differ diff --git a/docs/images/n8n/add_credential.png b/docs/images/n8n/add_credential.png new file mode 100644 index 00000000..a48f2809 Binary files /dev/null and b/docs/images/n8n/add_credential.png differ diff --git a/docs/images/n8n/add_node.png b/docs/images/n8n/add_node.png new file mode 100644 index 00000000..a733f6f5 Binary files /dev/null and b/docs/images/n8n/add_node.png differ diff --git a/docs/images/n8n/dispatch_task.png b/docs/images/n8n/dispatch_task.png new file mode 100644 index 00000000..46f82199 Binary files /dev/null and b/docs/images/n8n/dispatch_task.png differ diff --git a/docs/images/n8n/save_credential.png b/docs/images/n8n/save_credential.png new file mode 100644 index 00000000..e5706d6a Binary files /dev/null and b/docs/images/n8n/save_credential.png differ diff --git a/docs/images/n8n/ui_install.png b/docs/images/n8n/ui_install.png new file mode 100644 index 00000000..7517c6ac Binary files /dev/null and b/docs/images/n8n/ui_install.png differ diff --git a/docs/images/n8n/ui_install_success.png b/docs/images/n8n/ui_install_success.png new file mode 100644 index 00000000..1b1d2d0b Binary files /dev/null and b/docs/images/n8n/ui_install_success.png differ diff --git a/docs/images/observability/laminar-skyvern.png b/docs/images/observability/laminar-skyvern.png new file mode 100644 index 00000000..6216eb4f Binary files /dev/null and b/docs/images/observability/laminar-skyvern.png differ diff --git a/docs/images/performance/webbench_overall.png b/docs/images/performance/webbench_overall.png new file mode 100644 index 00000000..03c25779 Binary files /dev/null and b/docs/images/performance/webbench_overall.png differ diff --git a/docs/images/performance/webbench_write.png b/docs/images/performance/webbench_write.png new file mode 100644 index 00000000..281b4ff3 Binary files /dev/null and b/docs/images/performance/webbench_write.png differ diff --git a/docs/images/provided_list.png b/docs/images/provided_list.png new file mode 100644 index 00000000..6df32bf5 Binary files /dev/null and b/docs/images/provided_list.png differ diff --git a/docs/images/quickstart/agent-working.png b/docs/images/quickstart/agent-working.png new file mode 100644 index 00000000..5ae7cf6e Binary files /dev/null and b/docs/images/quickstart/agent-working.png differ diff --git a/docs/images/quickstart/prompt-input.png b/docs/images/quickstart/prompt-input.png new file mode 100644 index 00000000..4f7fefc3 Binary files /dev/null and b/docs/images/quickstart/prompt-input.png differ diff --git a/docs/images/quickstart/quickstart_prompt.png b/docs/images/quickstart/quickstart_prompt.png new file mode 100644 index 00000000..b077e189 Binary files /dev/null and b/docs/images/quickstart/quickstart_prompt.png differ diff --git a/docs/images/quickstart/quickstart_task_live.png b/docs/images/quickstart/quickstart_task_live.png new file mode 100644 index 00000000..4a9ac926 Binary files /dev/null and b/docs/images/quickstart/quickstart_task_live.png differ diff --git a/docs/images/run_tasks/cancel_run.png b/docs/images/run_tasks/cancel_run.png new file mode 100644 index 00000000..ab7bfc46 Binary files /dev/null and b/docs/images/run_tasks/cancel_run.png differ diff --git a/docs/images/run_tasks/ui_run_task.png b/docs/images/run_tasks/ui_run_task.png new file mode 100644 index 00000000..023e7bef Binary files /dev/null and b/docs/images/run_tasks/ui_run_task.png differ diff --git a/docs/images/scraped_list.png b/docs/images/scraped_list.png new file mode 100644 index 00000000..38bad8cf Binary files /dev/null and b/docs/images/scraped_list.png differ diff --git a/docs/images/secure_password_task_example.png b/docs/images/secure_password_task_example.png new file mode 100644 index 00000000..d7e5df1f Binary files /dev/null and b/docs/images/secure_password_task_example.png differ diff --git a/docs/images/skyvern-agent-local.gif b/docs/images/skyvern-agent-local.gif new file mode 100644 index 00000000..d639b4a8 Binary files /dev/null and b/docs/images/skyvern-agent-local.gif differ diff --git a/docs/images/skyvern-agent-local.mp4 b/docs/images/skyvern-agent-local.mp4 new file mode 100644 index 00000000..8644c824 Binary files /dev/null and b/docs/images/skyvern-agent-local.mp4 differ diff --git a/docs/images/skyvern-init.gif b/docs/images/skyvern-init.gif new file mode 100644 index 00000000..aa003e67 Binary files /dev/null and b/docs/images/skyvern-init.gif differ diff --git a/docs/images/skyvern-run-server.gif b/docs/images/skyvern-run-server.gif new file mode 100644 index 00000000..3f9cbd5c Binary files /dev/null and b/docs/images/skyvern-run-server.gif differ diff --git a/docs/images/skyvern-system-diagram-dark.png b/docs/images/skyvern-system-diagram-dark.png new file mode 100644 index 00000000..251a3e3b Binary files /dev/null and b/docs/images/skyvern-system-diagram-dark.png differ diff --git a/docs/images/skyvern-system-diagram-light.png b/docs/images/skyvern-system-diagram-light.png new file mode 100644 index 00000000..356d0d96 Binary files /dev/null and b/docs/images/skyvern-system-diagram-light.png differ diff --git a/docs/images/skyvern_2_0_screenshot.png b/docs/images/skyvern_2_0_screenshot.png new file mode 100644 index 00000000..777367dc Binary files /dev/null and b/docs/images/skyvern_2_0_screenshot.png differ diff --git a/docs/images/skyvern_2_0_system_diagram.png b/docs/images/skyvern_2_0_system_diagram.png new file mode 100644 index 00000000..217136e3 Binary files /dev/null and b/docs/images/skyvern_2_0_system_diagram.png differ diff --git a/docs/images/skyvern_demo_video_v2.1.mp4 b/docs/images/skyvern_demo_video_v2.1.mp4 new file mode 100644 index 00000000..fc5e65ab Binary files /dev/null and b/docs/images/skyvern_demo_video_v2.1.mp4 differ diff --git a/docs/images/skyvern_favicon.png b/docs/images/skyvern_favicon.png new file mode 100644 index 00000000..fe3d46ca Binary files /dev/null and b/docs/images/skyvern_favicon.png differ diff --git a/docs/images/skyvern_favicon_small.png b/docs/images/skyvern_favicon_small.png new file mode 100644 index 00000000..07534a2b Binary files /dev/null and b/docs/images/skyvern_favicon_small.png differ diff --git a/docs/images/skyvern_logo.png b/docs/images/skyvern_logo.png new file mode 100644 index 00000000..c93ed9c5 Binary files /dev/null and b/docs/images/skyvern_logo.png differ diff --git a/docs/images/skyvern_logo_blackbg.png b/docs/images/skyvern_logo_blackbg.png new file mode 100644 index 00000000..304a872a Binary files /dev/null and b/docs/images/skyvern_logo_blackbg.png differ diff --git a/docs/images/skyvern_visualizer_debug_action_screenshot.png b/docs/images/skyvern_visualizer_debug_action_screenshot.png new file mode 100644 index 00000000..88ae094d Binary files /dev/null and b/docs/images/skyvern_visualizer_debug_action_screenshot.png differ diff --git a/docs/images/skyvern_visualizer_debug_llm_response.png b/docs/images/skyvern_visualizer_debug_llm_response.png new file mode 100644 index 00000000..295e8d58 Binary files /dev/null and b/docs/images/skyvern_visualizer_debug_llm_response.png differ diff --git a/docs/images/skyvern_visualizer_run_task.png b/docs/images/skyvern_visualizer_run_task.png new file mode 100644 index 00000000..27f16cf1 Binary files /dev/null and b/docs/images/skyvern_visualizer_run_task.png differ diff --git a/docs/images/task_creation_form_example.png b/docs/images/task_creation_form_example.png new file mode 100644 index 00000000..f8e49fbd Binary files /dev/null and b/docs/images/task_creation_form_example.png differ diff --git a/docs/images/totp/create_email_forwarding.png b/docs/images/totp/create_email_forwarding.png new file mode 100644 index 00000000..20f43cec Binary files /dev/null and b/docs/images/totp/create_email_forwarding.png differ diff --git a/docs/images/totp/create_zap.png b/docs/images/totp/create_zap.png new file mode 100644 index 00000000..ed5e1588 Binary files /dev/null and b/docs/images/totp/create_zap.png differ diff --git a/docs/images/totp/create_zap_action.png b/docs/images/totp/create_zap_action.png new file mode 100644 index 00000000..b57f8da0 Binary files /dev/null and b/docs/images/totp/create_zap_action.png differ diff --git a/docs/images/totp/create_zap_action_event_post.png b/docs/images/totp/create_zap_action_event_post.png new file mode 100644 index 00000000..5438345f Binary files /dev/null and b/docs/images/totp/create_zap_action_event_post.png differ diff --git a/docs/images/totp/create_zap_email.png b/docs/images/totp/create_zap_email.png new file mode 100644 index 00000000..1862ae85 Binary files /dev/null and b/docs/images/totp/create_zap_email.png differ diff --git a/docs/images/totp/create_zap_email_setup.png b/docs/images/totp/create_zap_email_setup.png new file mode 100644 index 00000000..1249bded Binary files /dev/null and b/docs/images/totp/create_zap_email_setup.png differ diff --git a/docs/images/totp/create_zap_input_email.png b/docs/images/totp/create_zap_input_email.png new file mode 100644 index 00000000..2d78c2f8 Binary files /dev/null and b/docs/images/totp/create_zap_input_email.png differ diff --git a/docs/images/totp/create_zap_trigger.png b/docs/images/totp/create_zap_trigger.png new file mode 100644 index 00000000..a7d0b986 Binary files /dev/null and b/docs/images/totp/create_zap_trigger.png differ diff --git a/docs/images/totp/create_zap_webhook.png b/docs/images/totp/create_zap_webhook.png new file mode 100644 index 00000000..697347ea Binary files /dev/null and b/docs/images/totp/create_zap_webhook.png differ diff --git a/docs/images/totp/create_zap_webhook_complete.png b/docs/images/totp/create_zap_webhook_complete.png new file mode 100644 index 00000000..bdd580e7 Binary files /dev/null and b/docs/images/totp/create_zap_webhook_complete.png differ diff --git a/docs/images/totp/test_end_to_end.png b/docs/images/totp/test_end_to_end.png new file mode 100644 index 00000000..8dd22a26 Binary files /dev/null and b/docs/images/totp/test_end_to_end.png differ diff --git a/docs/images/view-recording.png b/docs/images/view-recording.png new file mode 100644 index 00000000..63321865 Binary files /dev/null and b/docs/images/view-recording.png differ diff --git a/docs/images/visualizing_results/navigate_to_task.png b/docs/images/visualizing_results/navigate_to_task.png new file mode 100644 index 00000000..b5973019 Binary files /dev/null and b/docs/images/visualizing_results/navigate_to_task.png differ diff --git a/docs/images/visualizing_results/view_actions.png b/docs/images/visualizing_results/view_actions.png new file mode 100644 index 00000000..86dd985a Binary files /dev/null and b/docs/images/visualizing_results/view_actions.png differ diff --git a/docs/images/visualizing_results/view_diagnostics.png b/docs/images/visualizing_results/view_diagnostics.png new file mode 100644 index 00000000..f019e257 Binary files /dev/null and b/docs/images/visualizing_results/view_diagnostics.png differ diff --git a/docs/images/visualizing_results/view_parameters.png b/docs/images/visualizing_results/view_parameters.png new file mode 100644 index 00000000..d06b221d Binary files /dev/null and b/docs/images/visualizing_results/view_parameters.png differ diff --git a/docs/images/visualizing_results/view_recording.png b/docs/images/visualizing_results/view_recording.png new file mode 100644 index 00000000..bedfe2c9 Binary files /dev/null and b/docs/images/visualizing_results/view_recording.png differ diff --git a/docs/images/what_is_a_parameter/add_credential_parameter.png b/docs/images/what_is_a_parameter/add_credential_parameter.png new file mode 100644 index 00000000..caeadffe Binary files /dev/null and b/docs/images/what_is_a_parameter/add_credential_parameter.png differ diff --git a/docs/images/what_is_a_parameter/add_parameter_jinja_syntax.png b/docs/images/what_is_a_parameter/add_parameter_jinja_syntax.png new file mode 100644 index 00000000..0de4a122 Binary files /dev/null and b/docs/images/what_is_a_parameter/add_parameter_jinja_syntax.png differ diff --git a/docs/images/what_is_a_parameter/login_credential_parameter.png b/docs/images/what_is_a_parameter/login_credential_parameter.png new file mode 100644 index 00000000..6e598b3a Binary files /dev/null and b/docs/images/what_is_a_parameter/login_credential_parameter.png differ diff --git a/docs/images/what_is_a_parameter/p.1.png b/docs/images/what_is_a_parameter/p.1.png new file mode 100644 index 00000000..798d72fe Binary files /dev/null and b/docs/images/what_is_a_parameter/p.1.png differ diff --git a/docs/images/what_is_a_parameter/p.2.png b/docs/images/what_is_a_parameter/p.2.png new file mode 100644 index 00000000..c7ed5659 Binary files /dev/null and b/docs/images/what_is_a_parameter/p.2.png differ diff --git a/docs/images/what_is_a_parameter/p.3.png b/docs/images/what_is_a_parameter/p.3.png new file mode 100644 index 00000000..f85c6c43 Binary files /dev/null and b/docs/images/what_is_a_parameter/p.3.png differ diff --git a/docs/images/what_is_a_parameter/p.4.png b/docs/images/what_is_a_parameter/p.4.png new file mode 100644 index 00000000..52cda390 Binary files /dev/null and b/docs/images/what_is_a_parameter/p.4.png differ diff --git a/docs/images/what_is_a_parameter/p.5.png b/docs/images/what_is_a_parameter/p.5.png new file mode 100644 index 00000000..59bfb27a Binary files /dev/null and b/docs/images/what_is_a_parameter/p.5.png differ diff --git a/docs/images/what_is_a_parameter/p.6.png b/docs/images/what_is_a_parameter/p.6.png new file mode 100644 index 00000000..68940726 Binary files /dev/null and b/docs/images/what_is_a_parameter/p.6.png differ diff --git a/docs/images/what_is_a_parameter/p.7.png b/docs/images/what_is_a_parameter/p.7.png new file mode 100644 index 00000000..3f92c3f3 Binary files /dev/null and b/docs/images/what_is_a_parameter/p.7.png differ diff --git a/docs/images/what_is_a_parameter/p.8.png b/docs/images/what_is_a_parameter/p.8.png new file mode 100644 index 00000000..bb7678a0 Binary files /dev/null and b/docs/images/what_is_a_parameter/p.8.png differ diff --git a/docs/images/what_is_a_parameter/p.9.png b/docs/images/what_is_a_parameter/p.9.png new file mode 100644 index 00000000..f0e97164 Binary files /dev/null and b/docs/images/what_is_a_parameter/p.9.png differ diff --git a/docs/images/what_is_a_parameter/run_workflow.png b/docs/images/what_is_a_parameter/run_workflow.png new file mode 100644 index 00000000..7f712885 Binary files /dev/null and b/docs/images/what_is_a_parameter/run_workflow.png differ diff --git a/docs/images/what_is_a_parameter/run_workflow_with_credential.png b/docs/images/what_is_a_parameter/run_workflow_with_credential.png new file mode 100644 index 00000000..2665b1c9 Binary files /dev/null and b/docs/images/what_is_a_parameter/run_workflow_with_credential.png differ diff --git a/docs/images/what_is_a_parameter/u.1.png b/docs/images/what_is_a_parameter/u.1.png new file mode 100644 index 00000000..a1ab7a28 Binary files /dev/null and b/docs/images/what_is_a_parameter/u.1.png differ diff --git a/docs/images/what_is_a_parameter/u.2.png b/docs/images/what_is_a_parameter/u.2.png new file mode 100644 index 00000000..0fb4c587 Binary files /dev/null and b/docs/images/what_is_a_parameter/u.2.png differ diff --git a/docs/images/windsurf_demo_fast.mp4 b/docs/images/windsurf_demo_fast.mp4 new file mode 100644 index 00000000..7fd74bf6 Binary files /dev/null and b/docs/images/windsurf_demo_fast.mp4 differ diff --git a/docs/images/workato/s1img1.png b/docs/images/workato/s1img1.png new file mode 100644 index 00000000..2ccba590 Binary files /dev/null and b/docs/images/workato/s1img1.png differ diff --git a/docs/images/workato/s1img2.png b/docs/images/workato/s1img2.png new file mode 100644 index 00000000..73265199 Binary files /dev/null and b/docs/images/workato/s1img2.png differ diff --git a/docs/images/workato/s1img3.png b/docs/images/workato/s1img3.png new file mode 100644 index 00000000..8fe92822 Binary files /dev/null and b/docs/images/workato/s1img3.png differ diff --git a/docs/images/workato/s1img4.png b/docs/images/workato/s1img4.png new file mode 100644 index 00000000..f21272d3 Binary files /dev/null and b/docs/images/workato/s1img4.png differ diff --git a/docs/images/workato/s1img5.png b/docs/images/workato/s1img5.png new file mode 100644 index 00000000..a0b170fe Binary files /dev/null and b/docs/images/workato/s1img5.png differ diff --git a/docs/images/workato/s1img6.png b/docs/images/workato/s1img6.png new file mode 100644 index 00000000..688a977b Binary files /dev/null and b/docs/images/workato/s1img6.png differ diff --git a/docs/images/workato/s1img7.png b/docs/images/workato/s1img7.png new file mode 100644 index 00000000..845cf3ae Binary files /dev/null and b/docs/images/workato/s1img7.png differ diff --git a/docs/images/workato/s2img1.png b/docs/images/workato/s2img1.png new file mode 100644 index 00000000..918df13b Binary files /dev/null and b/docs/images/workato/s2img1.png differ diff --git a/docs/images/workato/s2img2.png b/docs/images/workato/s2img2.png new file mode 100644 index 00000000..97233b50 Binary files /dev/null and b/docs/images/workato/s2img2.png differ diff --git a/docs/images/workato/s2img3.png b/docs/images/workato/s2img3.png new file mode 100644 index 00000000..b01901fb Binary files /dev/null and b/docs/images/workato/s2img3.png differ diff --git a/docs/images/workato/s2img4.png b/docs/images/workato/s2img4.png new file mode 100644 index 00000000..abdcf9cf Binary files /dev/null and b/docs/images/workato/s2img4.png differ diff --git a/docs/images/workato/s3img1.png b/docs/images/workato/s3img1.png new file mode 100644 index 00000000..8e0857d2 Binary files /dev/null and b/docs/images/workato/s3img1.png differ diff --git a/docs/images/workato/s3img2.png b/docs/images/workato/s3img2.png new file mode 100644 index 00000000..6a27f5d0 Binary files /dev/null and b/docs/images/workato/s3img2.png differ diff --git a/docs/images/workato/s5img1.png b/docs/images/workato/s5img1.png new file mode 100644 index 00000000..73cd3de2 Binary files /dev/null and b/docs/images/workato/s5img1.png differ diff --git a/docs/images/workato/s5img2.png b/docs/images/workato/s5img2.png new file mode 100644 index 00000000..34a8c9d3 Binary files /dev/null and b/docs/images/workato/s5img2.png differ diff --git a/docs/images/workato/s5img3.png b/docs/images/workato/s5img3.png new file mode 100644 index 00000000..088ecaef Binary files /dev/null and b/docs/images/workato/s5img3.png differ diff --git a/docs/images/workato/s8img1.png b/docs/images/workato/s8img1.png new file mode 100644 index 00000000..ae1836c6 Binary files /dev/null and b/docs/images/workato/s8img1.png differ diff --git a/docs/images/workato/s8img2.png b/docs/images/workato/s8img2.png new file mode 100644 index 00000000..cda31a2a Binary files /dev/null and b/docs/images/workato/s8img2.png differ diff --git a/docs/images/workflows/clone-workflow.png b/docs/images/workflows/clone-workflow.png new file mode 100644 index 00000000..ea28cc19 Binary files /dev/null and b/docs/images/workflows/clone-workflow.png differ diff --git a/docs/images/workflows/create-workflow.png b/docs/images/workflows/create-workflow.png new file mode 100644 index 00000000..164abd27 Binary files /dev/null and b/docs/images/workflows/create-workflow.png differ diff --git a/docs/images/workflows/delete-block.png b/docs/images/workflows/delete-block.png new file mode 100644 index 00000000..da9f5d87 Binary files /dev/null and b/docs/images/workflows/delete-block.png differ diff --git a/docs/images/workflows/download-workflow.png b/docs/images/workflows/download-workflow.png new file mode 100644 index 00000000..dcaef95d Binary files /dev/null and b/docs/images/workflows/download-workflow.png differ diff --git a/docs/images/workflows/run-workflow.png b/docs/images/workflows/run-workflow.png new file mode 100644 index 00000000..18e9cb3e Binary files /dev/null and b/docs/images/workflows/run-workflow.png differ diff --git a/docs/images/zapier/z.1.png b/docs/images/zapier/z.1.png new file mode 100644 index 00000000..c53d858b Binary files /dev/null and b/docs/images/zapier/z.1.png differ diff --git a/docs/images/zapier/z.10ag.png b/docs/images/zapier/z.10ag.png new file mode 100644 index 00000000..b7a81144 Binary files /dev/null and b/docs/images/zapier/z.10ag.png differ diff --git a/docs/images/zapier/z.10bg.png b/docs/images/zapier/z.10bg.png new file mode 100644 index 00000000..f9fe148e Binary files /dev/null and b/docs/images/zapier/z.10bg.png differ diff --git a/docs/images/zapier/z.11ag.png b/docs/images/zapier/z.11ag.png new file mode 100644 index 00000000..a1b9b67e Binary files /dev/null and b/docs/images/zapier/z.11ag.png differ diff --git a/docs/images/zapier/z.11bg.png b/docs/images/zapier/z.11bg.png new file mode 100644 index 00000000..480a6283 Binary files /dev/null and b/docs/images/zapier/z.11bg.png differ diff --git a/docs/images/zapier/z.12ag.png b/docs/images/zapier/z.12ag.png new file mode 100644 index 00000000..84044f5b Binary files /dev/null and b/docs/images/zapier/z.12ag.png differ diff --git a/docs/images/zapier/z.12bg.png b/docs/images/zapier/z.12bg.png new file mode 100644 index 00000000..8f063b56 Binary files /dev/null and b/docs/images/zapier/z.12bg.png differ diff --git a/docs/images/zapier/z.2.png b/docs/images/zapier/z.2.png new file mode 100644 index 00000000..13717a6b Binary files /dev/null and b/docs/images/zapier/z.2.png differ diff --git a/docs/images/zapier/z.3.png b/docs/images/zapier/z.3.png new file mode 100644 index 00000000..1f12cc3c Binary files /dev/null and b/docs/images/zapier/z.3.png differ diff --git a/docs/images/zapier/z.4.png b/docs/images/zapier/z.4.png new file mode 100644 index 00000000..2eac2fd2 Binary files /dev/null and b/docs/images/zapier/z.4.png differ diff --git a/docs/images/zapier/z.5.png b/docs/images/zapier/z.5.png new file mode 100644 index 00000000..828459d1 Binary files /dev/null and b/docs/images/zapier/z.5.png differ diff --git a/docs/images/zapier/z.6w.png b/docs/images/zapier/z.6w.png new file mode 100644 index 00000000..b8ee5588 Binary files /dev/null and b/docs/images/zapier/z.6w.png differ diff --git a/docs/images/zapier/z.7w.png b/docs/images/zapier/z.7w.png new file mode 100644 index 00000000..ae9b6e71 Binary files /dev/null and b/docs/images/zapier/z.7w.png differ diff --git a/docs/images/zapier/z.8w.png b/docs/images/zapier/z.8w.png new file mode 100644 index 00000000..a68f75f7 Binary files /dev/null and b/docs/images/zapier/z.8w.png differ diff --git a/docs/images/zapier/z.9w.png b/docs/images/zapier/z.9w.png new file mode 100644 index 00000000..7a4b221d Binary files /dev/null and b/docs/images/zapier/z.9w.png differ diff --git a/docs/logo/dark.svg b/docs/logo/dark.svg new file mode 100644 index 00000000..bc6bd1e9 --- /dev/null +++ b/docs/logo/dark.svg @@ -0,0 +1,3 @@ + + Skyvern + diff --git a/docs/logo/light.svg b/docs/logo/light.svg new file mode 100644 index 00000000..94c44a4e --- /dev/null +++ b/docs/logo/light.svg @@ -0,0 +1,3 @@ + + Skyvern + diff --git a/docs/running-automations/extract-structured-data.mdx b/docs/running-automations/extract-structured-data.mdx new file mode 100644 index 00000000..a33d706f --- /dev/null +++ b/docs/running-automations/extract-structured-data.mdx @@ -0,0 +1,815 @@ +--- +title: Extract Structured Data +subtitle: Get consistent, typed output from your tasks +slug: running-automations/extract-structured-data +--- + +export const FIELD_TYPES = [ + { value: "string", label: "String" }, + { value: "number", label: "Number" }, + { value: "integer", label: "Integer" }, + { value: "boolean", label: "Boolean" }, +] + +export const SchemaBuilder = () => { + const [schemaType, setSchemaType] = useState("single") + const [arrayName, setArrayName] = useState("items") + const [fields, setFields] = useState([ + { id: "1", name: "title", type: "string", description: "The title" }, + ]) + const [outputFormat, setOutputFormat] = useState("python") + const [copied, setCopied] = useState(false) + + const addField = () => { + setFields([...fields, { id: String(Date.now()), name: "", type: "string", description: "" }]) + } + + const removeField = (id) => { + if (fields.length > 1) setFields(fields.filter((f) => f.id !== id)) + } + + const updateField = (id, key, value) => { + setFields(fields.map((f) => (f.id === id ? { ...f, [key]: value } : f))) + } + + // Track duplicate field names + const duplicateNames = useMemo(() => { + const names = fields.map((f) => f.name).filter((n) => n.trim() !== "") + const counts = {} + names.forEach((n) => { counts[n] = (counts[n] || 0) + 1 }) + return new Set(Object.keys(counts).filter((n) => counts[n] > 1)) + }, [fields]) + + const schema = useMemo(() => { + const properties = {} + fields.forEach((field) => { + if (field.name) { + properties[field.name] = { + type: field.type, + description: field.description || `The ${field.name}`, + } + } + }) + if (schemaType === "array") { + return { + type: "object", + properties: { + [arrayName]: { + type: "array", + description: "List of extracted items", + items: { type: "object", properties }, + }, + }, + } + } + return { type: "object", properties } + }, [fields, schemaType, arrayName]) + + const formattedOutput = useMemo(() => { + const jsonStr = JSON.stringify(schema, null, 2) + if (outputFormat === "python") { + // Only replace JSON literals at value positions (after ": "), not inside quoted strings + return `data_extraction_schema=${jsonStr.replace(/: null/g, ": None").replace(/: true/g, ": True").replace(/: false/g, ": False")}` + } + if (outputFormat === "typescript") { + return `data_extraction_schema: ${jsonStr}` + } + return `"data_extraction_schema": ${jsonStr}` + }, [schema, outputFormat]) + + const copyToClipboard = async () => { + await navigator.clipboard.writeText(formattedOutput) + setCopied(true) + setTimeout(() => setCopied(false), 2000) + } + + return ( +
+
+ +
+ {[ + { value: "single", label: "Single object", desc: "Extract one item with multiple fields" }, + { value: "array", label: "List of items", desc: "Extract multiple items with the same structure" }, + ].map((type) => ( + + ))} +
+
+ + {schemaType === "array" && ( +
+ + setArrayName(e.target.value)} + className="w-full p-2 border rounded-md text-sm" + placeholder="items" + /> +
+ )} + +
+ +
+ {fields.map((field) => ( +
+ updateField(field.id, "name", e.target.value)} + placeholder="Field name" + className={`w-32 p-2 border rounded-md text-sm ${duplicateNames.has(field.name) ? "border-red-500 bg-red-50" : ""}`} + title={duplicateNames.has(field.name) ? "Duplicate field name - will be overwritten in schema" : ""} + /> + + updateField(field.id, "description", e.target.value)} + placeholder="Description (helps AI understand what to extract)" + className="flex-1 p-2 border rounded-md text-sm" + /> + +
+ ))} +
+ + {duplicateNames.size > 0 && ( +
+ Duplicate field names detected. Only the last field with each name will appear in the schema. +
+ )} +
+ +
+
+ +
+ {["python", "typescript", "curl"].map((format) => ( + + ))} +
+
+
+
+            {formattedOutput}
+          
+ +
+
+
+ ) +} + +By default, Skyvern returns extracted data in whatever format makes sense for the task. +Pass a `data_extraction_schema` to enforce a specific structure using [JSON Schema.](https://json-schema.org/) + +--- + +## Define a schema + +Add `data_extraction_schema` parameter to your task with a JSON Schema object: + + +```python Python +result = await client.run_task( + prompt="Get the title of the top post", + url="https://news.ycombinator.com", + data_extraction_schema={ + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "The title of the top post" + } + } + } +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get the title of the top post", + url: "https://news.ycombinator.com", + data_extraction_schema: { + type: "object", + properties: { + title: { + type: "string", + description: "The title of the top post", + }, + }, + }, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get the title of the top post", + "url": "https://news.ycombinator.com", + "data_extraction_schema": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "The title of the top post" + } + } + } + }' +``` + + +The `description` field in each property helps Skyvern understand what data to extract. Be specific. + + +`description` fields drive extraction quality. Vague descriptions like "the data" produce vague results. Be specific: "The product price in USD, without currency symbol." + + +--- + +## Schema format + +Skyvern uses standard JSON Schema. Common types: + +| Type | JSON Schema | Example value | +|------|-------------|---------------| +| String | `{"type": "string"}` | `"Hello world"` | +| Number | `{"type": "number"}` | `19.99` | +| Integer | `{"type": "integer"}` | `42` | +| Boolean | `{"type": "boolean"}` | `true` | +| Array | `{"type": "array", "items": {...}}` | `[1, 2, 3]` | +| Object | `{"type": "object", "properties": {...}}` | `{"key": "value"}` | + + +A schema doesn't guarantee all fields are populated. If the data isn't on the page, fields return `null`. Design your code to handle missing values. + + +--- + +## Build your schema + +Use the interactive builder below to generate a schema, then copy it into your code. + + + +--- + +## Examples + +### Single value + +Extract one piece of information, such as the current price of Bitcoin: + + +```python Python +result = await client.run_task( + prompt="Get the current Bitcoin price in USD", + url="https://coinmarketcap.com/currencies/bitcoin/", + data_extraction_schema={ + "type": "object", + "properties": { + "price": { + "type": "number", + "description": "Current Bitcoin price in USD" + } + } + } +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get the current Bitcoin price in USD", + url: "https://coinmarketcap.com/currencies/bitcoin/", + data_extraction_schema: { + type: "object", + properties: { + price: { + type: "number", + description: "Current Bitcoin price in USD", + }, + }, + }, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get the current Bitcoin price in USD", + "url": "https://coinmarketcap.com/currencies/bitcoin/", + "data_extraction_schema": { + "type": "object", + "properties": { + "price": { + "type": "number", + "description": "Current Bitcoin price in USD" + } + } + } + }' +``` + + +**Output (when completed):** + +```json +{ + "price": 104521.37 +} +``` + +--- + +### List of items + +Extract multiple items with the same structure, such as the top posts from a news site: + + +```python Python +result = await client.run_task( + prompt="Get the top 5 posts", + url="https://news.ycombinator.com", + data_extraction_schema={ + "type": "object", + "properties": { + "posts": { + "type": "array", + "description": "Top 5 posts from the front page", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "Post title" + }, + "points": { + "type": "integer", + "description": "Number of points" + }, + "url": { + "type": "string", + "description": "Link to the post" + } + } + } + } + } + } +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get the top 5 posts", + url: "https://news.ycombinator.com", + data_extraction_schema: { + type: "object", + properties: { + posts: { + type: "array", + description: "Top 5 posts from the front page", + items: { + type: "object", + properties: { + title: { + type: "string", + description: "Post title", + }, + points: { + type: "integer", + description: "Number of points", + }, + url: { + type: "string", + description: "Link to the post", + }, + }, + }, + }, + }, + }, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get the top 5 posts", + "url": "https://news.ycombinator.com", + "data_extraction_schema": { + "type": "object", + "properties": { + "posts": { + "type": "array", + "description": "Top 5 posts from the front page", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "Post title" + }, + "points": { + "type": "integer", + "description": "Number of points" + }, + "url": { + "type": "string", + "description": "Link to the post" + } + } + } + } + } + } + }' +``` + + +**Output (when completed):** + +```json +{ + "posts": [ + { + "title": "Running Claude Code dangerously (safely)", + "points": 342, + "url": "https://blog.emilburzo.com/2026/01/running-claude-code-dangerously-safely/" + }, + { + "title": "Linux kernel framework for PCIe device emulation", + "points": 287, + "url": "https://github.com/cakehonolulu/pciem" + }, + { + "title": "I'm addicted to being useful", + "points": 256, + "url": "https://www.seangoedecke.com/addicted-to-being-useful/" + }, + { + "title": "Level S4 solar radiation event", + "points": 198, + "url": "https://www.swpc.noaa.gov/news/g4-severe-geomagnetic-storm" + }, + { + "title": "WebAssembly Text Format parser performance", + "points": 176, + "url": "https://blog.gplane.win/posts/improve-wat-parser-perf.html" + } + ] +} +``` + + +Arrays without limits extract everything visible on the page. Specify limits in your prompt (e.g., "top 5 posts") or the array description to control output size. + + +--- + +### Nested objects + +Extract hierarchical data, such as a product with its pricing and availability: + + +```python Python +result = await client.run_task( + prompt="Get product details including pricing and availability", + url="https://www.amazon.com/dp/B0EXAMPLE", + data_extraction_schema={ + "type": "object", + "properties": { + "product": { + "type": "object", + "description": "Product information", + "properties": { + "name": { + "type": "string", + "description": "Product name" + }, + "pricing": { + "type": "object", + "description": "Pricing details", + "properties": { + "current_price": { + "type": "number", + "description": "Current price in USD" + }, + "original_price": { + "type": "number", + "description": "Original price before discount" + }, + "discount_percent": { + "type": "integer", + "description": "Discount percentage" + } + } + }, + "availability": { + "type": "object", + "description": "Stock information", + "properties": { + "in_stock": { + "type": "boolean", + "description": "Whether the item is in stock" + }, + "delivery_estimate": { + "type": "string", + "description": "Estimated delivery date" + } + } + } + } + } + } + } +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get product details including pricing and availability", + url: "https://www.amazon.com/dp/B0EXAMPLE", + data_extraction_schema: { + type: "object", + properties: { + product: { + type: "object", + description: "Product information", + properties: { + name: { + type: "string", + description: "Product name", + }, + pricing: { + type: "object", + description: "Pricing details", + properties: { + current_price: { + type: "number", + description: "Current price in USD", + }, + original_price: { + type: "number", + description: "Original price before discount", + }, + discount_percent: { + type: "integer", + description: "Discount percentage", + }, + }, + }, + availability: { + type: "object", + description: "Stock information", + properties: { + in_stock: { + type: "boolean", + description: "Whether the item is in stock", + }, + delivery_estimate: { + type: "string", + description: "Estimated delivery date", + }, + }, + }, + }, + }, + }, + }, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get product details including pricing and availability", + "url": "https://www.amazon.com/dp/B0EXAMPLE", + "data_extraction_schema": { + "type": "object", + "properties": { + "product": { + "type": "object", + "description": "Product information", + "properties": { + "name": { + "type": "string", + "description": "Product name" + }, + "pricing": { + "type": "object", + "description": "Pricing details", + "properties": { + "current_price": { + "type": "number", + "description": "Current price in USD" + }, + "original_price": { + "type": "number", + "description": "Original price before discount" + }, + "discount_percent": { + "type": "integer", + "description": "Discount percentage" + } + } + }, + "availability": { + "type": "object", + "description": "Stock information", + "properties": { + "in_stock": { + "type": "boolean", + "description": "Whether the item is in stock" + }, + "delivery_estimate": { + "type": "string", + "description": "Estimated delivery date" + } + } + } + } + } + } + } + }' +``` + + +**Output (when completed):** + +```json +{ + "product": { + "name": "Wireless Bluetooth Headphones", + "pricing": { + "current_price": 79.99, + "original_price": 129.99, + "discount_percent": 38 + }, + "availability": { + "in_stock": true, + "delivery_estimate": "Tomorrow, Jan 21" + } + } +} +``` + +--- + +## Accessing extracted data + +The extracted data appears in the `output` field of the completed run. Poll until the task reaches a terminal state, then access the output. + + +```python Python +result = await client.run_task( + prompt="Get the top post", + url="https://news.ycombinator.com", + data_extraction_schema={ + "type": "object", + "properties": { + "title": {"type": "string", "description": "Post title"}, + "points": {"type": "integer", "description": "Points"} + } + } +) + +run_id = result.run_id + +while True: + run = await client.get_run(run_id) + + if run.status in ["completed", "failed", "terminated", "timed_out", "canceled"]: + break + + await asyncio.sleep(5) + +# Access the extracted data +print(f"Output: {run.output}") +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get the top post", + url: "https://news.ycombinator.com", + data_extraction_schema: { + type: "object", + properties: { + title: { type: "string", description: "Post title" }, + points: { type: "integer", description: "Points" }, + }, + }, + }, +}); + +const runId = result.run_id; + +while (true) { + const run = await client.getRun(runId); + + if (["completed", "failed", "terminated", "timed_out", "canceled"].includes(run.status)) { + console.log(`Output: ${JSON.stringify(run.output)}`); + break; + } + + await new Promise((resolve) => setTimeout(resolve, 5000)); +} +``` + +```bash cURL +RUN_ID="your_run_id_here" + +while true; do + RESPONSE=$(curl -s -X GET "https://api.skyvern.com/v1/runs/$RUN_ID" \ + -H "x-api-key: $SKYVERN_API_KEY") + + STATUS=$(echo "$RESPONSE" | jq -r '.status') + + if [[ "$STATUS" == "completed" || "$STATUS" == "failed" || "$STATUS" == "terminated" || "$STATUS" == "timed_out" || "$STATUS" == "canceled" ]]; then + echo "$RESPONSE" | jq '.output' + break + fi + + sleep 5 +done +``` + + +If using webhooks, the same `output` field appears in the webhook payload. + +--- + +## Next steps + + + + All available parameters for run_task + + + Execute tasks and retrieve results + + diff --git a/docs/running-automations/run-a-task.mdx b/docs/running-automations/run-a-task.mdx new file mode 100644 index 00000000..56fee948 --- /dev/null +++ b/docs/running-automations/run-a-task.mdx @@ -0,0 +1,490 @@ +--- +title: Run a Task +subtitle: Execute a single browser automation with natural language +slug: running-automations/run-a-task +--- + +A **Task** is the simplest way to automate a browser action. + +You describe what you want in natural language, and Skyvern's AI navigates the web to complete it. + +--- + +## Call `run_task` + +A task has one required parameter and one commonly used optional parameter: + +- **`prompt`** (required) — Natural language instructions describing what the AI should do +- **`url`** (optional) — The starting page for the automation + +For additional parameters like engines, proxies, and extraction schemas, see [Task Parameters](/running-automations/task-parameters). + +When you call `run_task`, Skyvern spins up a cloud browser, navigates to the URL, and executes your prompt. A typical task takes 30–90 seconds depending on complexity. + + +```python Python +import os +import asyncio +from skyvern import Skyvern + +async def main(): + client = Skyvern(api_key=os.getenv("SKYVERN_API_KEY")) + + result = await client.run_task( + prompt="Get the title of the top post", + url="https://news.ycombinator.com", + ) + + print(f"Run ID: {result.run_id}") + print(f"Status: {result.status}") + +asyncio.run(main()) +``` + +```typescript TypeScript +import { SkyvernClient } from "@skyvern/client"; + +async function main() { + const client = new SkyvernClient({ + apiKey: process.env.SKYVERN_API_KEY, + }); + + const result = await client.runTask({ + body: { + prompt: "Get the title of the top post", + url: "https://news.ycombinator.com", + }, + }); + + console.log(`Run ID: ${result.run_id}`); + console.log(`Status: ${result.status}`); +} + +main(); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get the title of the top post", + "url": "https://news.ycombinator.com" + }' +``` + + +**Example response:** + +```json +{ + "run_id": "tsk_v2_486305187432193504", + "status": "queued", + "output": null, + "downloaded_files": null, + "recording_url": null, + "screenshot_urls": null, + "failure_reason": null, + "created_at": "2026-01-20T11:52:29.276851", + "modified_at": "2026-01-20T11:52:29.484284", + "app_url": "https://app.skyvern.com/runs/wr_486305187432193510", + "run_type": "task_v2" +} +``` + +The response includes a `run_id`. Use this ID to check status, fetch results, and retrieve artifacts. + + +`run_task` returns immediately—the task is queued, not finished. Always poll or use webhooks to get results. + + +--- + +## Get results + +The `run_task` call queues the task and returns immediately. + +Use the `run_id` to fetch results once the task reaches a terminal state. + +| Status | Description | +|--------|-------------| +| `created` | Task initialized, not yet queued | +| `queued` | Waiting for an available browser | +| `running` | AI is navigating and executing | +| `completed` | Task finished successfully—check `output` for results | +| `failed` | Task encountered an error—check `failure_reason` and retry or adjust your prompt | +| `terminated` | Task was manually stopped | +| `timed_out` | Task exceeded time limit—increase `max_steps` or simplify the task | +| `canceled` | Task was canceled before starting | + +You have three options for retrieving results: + +### Option 1: Polling + +Poll `get_run` until status is terminal (`completed`, `failed`, `terminated`, `timed_out`, or `canceled`). + + +```python Python +run_id = result.run_id + +while True: + run = await client.get_run(run_id) + + if run.status in ["completed", "failed", "terminated", "timed_out", "canceled"]: + break + + await asyncio.sleep(5) + +print(f"Output: {run.output}") +``` + +```typescript TypeScript +const runId = result.run_id; + +while (true) { + const run = await client.getRun(runId); + + if (["completed", "failed", "terminated", "timed_out", "canceled"].includes(run.status)) { + console.log(`Output: ${JSON.stringify(run.output)}`); + break; + } + + await new Promise((resolve) => setTimeout(resolve, 5000)); +} +``` + +```bash cURL +#!/bin/bash +RUN_ID="YOUR_RUN_ID" + +while true; do + RESPONSE=$(curl -s -X GET "https://api.skyvern.com/v1/runs/$RUN_ID" \ + -H "x-api-key: $SKYVERN_API_KEY") + + STATUS=$(echo "$RESPONSE" | jq -r '.status') + echo "Status: $STATUS" + + if [[ "$STATUS" == "completed" || "$STATUS" == "failed" || "$STATUS" == "terminated" || "$STATUS" == "timed_out" || "$STATUS" == "canceled" ]]; then + echo "$RESPONSE" | jq '.output' + break + fi + + sleep 5 +done +``` + + + +Your polling loop must check **all** terminal states: `completed`, `failed`, `terminated`, `timed_out`, `canceled`. Missing one causes infinite loops. + + +### Option 2: Webhooks + +Pass a `webhook_url` when creating the task. Skyvern sends a POST request to your URL when the task completes. + + +```python Python +result = await client.run_task( + prompt="Get the title of the top post", + url="https://news.ycombinator.com", + webhook_url="https://your-server.com/webhook", +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get the title of the top post", + url: "https://news.ycombinator.com", + webhook_url: "https://your-server.com/webhook", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get the title of the top post", + "url": "https://news.ycombinator.com", + "webhook_url": "https://your-server.com/webhook" + }' +``` + + +Skyvern sends a POST request with the full run data when the task completes or fails. + +### Option 3: Wait for completion (Python only) + +Block until the task finishes instead of polling manually. + +```python Python +result = await client.run_task( + prompt="Get the title of the top post", + url="https://news.ycombinator.com", + wait_for_completion=True, +) +print(result.output) +``` + +--- + +## Understand the response + +The response from polling (`get_run`) and webhooks have slightly different structures. Both contain the core task data, but webhooks include additional metadata. + + +```json Polling Response +{ + "run_id": "tsk_v2_486305187432193504", + "status": "completed", + "output": { + "top_post_title": "Linux kernel framework for PCIe device emulation, in userspace" + }, + "downloaded_files": [], + "recording_url": "https://skyvern-artifacts.s3.amazonaws.com/v1/production/.../recording.webm?...", + "screenshot_urls": ["https://skyvern-artifacts.s3.amazonaws.com/.../screenshot_final.png?..."], + "failure_reason": null, + "errors": [], + "step_count": 2, + "run_type": "task_v2", + "app_url": "https://app.skyvern.com/runs/wr_486305187432193510", + "browser_session_id": null, + "browser_profile_id": null, + "created_at": "2026-01-20T11:52:29.276851", + "modified_at": "2026-01-20T11:54:08.822807", + "queued_at": "2026-01-20T11:52:29.483922", + "started_at": "2026-01-20T11:52:31.835337", + "finished_at": "2026-01-20T11:54:08.821985", + "run_request": { + "prompt": "Get the title of the top post", + "url": "https://news.ycombinator.com/", + "engine": "skyvern-2.0" + } +} +``` + +```json Webhook Payload +{ + "task_id": "tsk_v2_486306851394503256", + "run_id": "tsk_v2_486306851394503256", + "status": "completed", + "output": { + "top_post_title": "Linux kernel framework for PCIe device emulation, in userspace" + }, + "summary": "I have successfully navigated to Hacker News and extracted the title of the top post.", + "prompt": "Get the title of the top post", + "url": "https://news.ycombinator.com/", + "downloaded_files": [], + "recording_url": "https://skyvern-artifacts.s3.amazonaws.com/v1/production/.../recording.webm?...", + "screenshot_urls": ["https://skyvern-artifacts.s3.amazonaws.com/.../screenshot_final.png?..."], + "failure_reason": null, + "errors": [], + "step_count": 2, + "run_type": "task_v2", + "app_url": "https://app.skyvern.com/runs/wr_486306851394503262", + "organization_id": "o_485917350850524254", + "workflow_run_id": "wr_486306851394503262", + "proxy_location": "RESIDENTIAL", + "webhook_callback_url": "https://your-server.com/webhook", + "created_at": "2026-01-20T11:58:57.414123", + "modified_at": "2026-01-20T12:00:31.513449", + "queued_at": "2026-01-20T11:58:57.607233", + "started_at": "2026-01-20T11:58:59.395028", + "finished_at": "2026-01-20T12:00:31.512692" +} +``` + + + +Webhook payloads differ from polling responses: webhooks include `summary` and `organization_id`; polling includes `run_request`. Plan your integration accordingly. + + +**Common fields (both polling and webhook):** + +| Field | Type | Description | +|-------|------|-------------| +| `run_id` | string | Unique identifier for this run | +| `status` | string | Current status: `queued`, `running`, `completed`, `failed`, `terminated`, `timed_out`, `canceled` | +| `output` | object \| null | Extracted data from the task | +| `downloaded_files` | array | Files downloaded during execution | +| `recording_url` | string \| null | Video recording of the browser session | +| `screenshot_urls` | array \| null | Screenshots captured (latest first) | +| `failure_reason` | string \| null | Error message if the run failed | +| `errors` | array | List of errors encountered | +| `step_count` | integer \| null | Number of steps executed | +| `run_type` | string | Type of run: `task_v2`, `openai_cua`, `anthropic_cua` | +| `app_url` | string | Link to view this run in Skyvern Cloud | +| `created_at` | datetime | When the run was created | +| `modified_at` | datetime | When the run was last updated | +| `queued_at` | datetime \| null | When the run entered the queue | +| `started_at` | datetime \| null | When execution began | +| `finished_at` | datetime \| null | When execution completed | + +**Polling-only fields:** + +| Field | Type | Description | +|-------|------|-------------| +| `run_request` | object | Original request parameters (prompt, url, engine, etc.) | +| `browser_session_id` | string \| null | ID of the browser session used | +| `browser_profile_id` | string \| null | ID of the browser profile used | +| `max_screenshot_scrolls` | integer \| null | Number of scrolls for screenshots | +| `script_run` | object \| null | Script run result if AI fallback triggered | + +**Webhook-only fields:** + +| Field | Type | Description | +|-------|------|-------------| +| `task_id` | string | Same as `run_id` | +| `summary` | string | AI-generated description of what was done | +| `prompt` | string | The prompt from the original request | +| `url` | string | The URL from the original request | +| `organization_id` | string | Your organization ID | +| `workflow_run_id` | string | Associated workflow run ID | +| `proxy_location` | string | Proxy location used (e.g., `RESIDENTIAL`) | +| `webhook_callback_url` | string | The webhook URL that received this payload | + +--- + +## Get artifacts + +The run response contains high-level data like `output`, `recording_url`, and `screenshot_urls`. + +Every run also generates Artifacts, such as screenshots, reasoning logs, downloaded files, for observability. To get them, use `get_run_artifacts`. + + +```python Python +artifacts = await client.get_run_artifacts(run_id) + +for artifact in artifacts: + print(f"{artifact.artifact_type}: {artifact.signed_url}") +``` + +```typescript TypeScript +const artifacts = await client.getRunArtifacts(runId); + +for (const artifact of artifacts) { + console.log(`${artifact.artifact_type}: ${artifact.signed_url}`); +} +``` + +```bash cURL +curl -X GET "https://api.skyvern.com/v1/runs/RUN_ID/artifacts" \ + -H "x-api-key: $SKYVERN_API_KEY" +``` + + +This returns a list of artifacts. + +**Example response:** + +```json +[ + { + "artifact_id": "a_486305284826607484", + "artifact_type": "recording", + "uri": "s3://skyvern-artifacts/v1/production/.../recording.webm", + "signed_url": "https://skyvern-artifacts.s3.amazonaws.com/v1/production/.../recording.webm?...", + "task_id": "tsk_486305246171901814", + "step_id": "stp_486305250466869112", + "workflow_run_id": "wr_486305187432193510", + "workflow_run_block_id": null, + "run_id": "tsk_v2_486305187432193504", + "organization_id": "o_485917350850524254", + "created_at": "2026-01-20T11:52:52.083001", + "modified_at": "2026-01-20T11:52:52.083003" + }, + { + "artifact_id": "a_486305516754841578", + "artifact_type": "screenshot_final", + "uri": "s3://skyvern-artifacts/v1/production/.../screenshot_final.png", + "signed_url": "https://skyvern-artifacts.s3.amazonaws.com/v1/production/.../screenshot_final.png?...", + "task_id": "tsk_486305439445430190", + "step_id": "stp_486305439445430192", + "workflow_run_id": "wr_486305187432193510", + "workflow_run_block_id": null, + "run_id": "tsk_v2_486305187432193504", + "organization_id": "o_485917350850524254", + "created_at": "2026-01-20T11:53:46.468908", + "modified_at": "2026-01-20T11:53:46.468910" + } +] +``` + +**Artifact fields:** + +| Field | Type | Description | +|-------|------|-------------| +| `artifact_id` | string | Unique identifier for the artifact | +| `artifact_type` | string | Type of artifact (see table below) | +| `uri` | string | Internal storage path | +| `signed_url` | string \| null | Pre-signed URL for downloading | +| `task_id` | string \| null | Associated task ID | +| `step_id` | string \| null | Associated step ID | +| `run_id` | string \| null | Associated run ID (e.g., `tsk_v2_...`) | +| `workflow_run_id` | string \| null | Associated workflow run ID | +| `workflow_run_block_id` | string \| null | Associated workflow block ID | +| `organization_id` | string | Organization that owns this artifact | +| `created_at` | datetime | When the artifact was created | +| `modified_at` | datetime | When the artifact was last modified | + +**Artifact types:** + +| Type | Description | +|------|-------------| +| `recording` | Full video of the browser session | +| `screenshot` | Screenshot captured during execution | +| `screenshot_action` | Screenshot taken after an action | +| `screenshot_final` | Final screenshot when task completed | +| `screenshot_llm` | Screenshot sent to the LLM for analysis | +| `html` | Page HTML at various points | +| `html_scrape` | Scraped HTML content | +| `html_action` | HTML captured after an action | +| `har` | HTTP Archive file for network debugging | +| `trace` | Execution trace data | +| `pdf` | PDF files generated or downloaded | +| `script_file` | Generated script files | +| `browser_console_log` | Browser console output | +| `skyvern_log` | Skyvern execution logs | +| `skyvern_log_raw` | Raw Skyvern execution logs | +| `llm_prompt` | Prompt sent to the LLM | +| `llm_request` | Full request sent to the LLM | +| `llm_response` | Response from the LLM | +| `llm_response_parsed` | Parsed LLM response | +| `llm_response_rendered` | Rendered LLM response | +| `visible_elements_tree` | DOM tree of visible elements | +| `visible_elements_tree_trimmed` | Trimmed DOM tree | +| `visible_elements_tree_in_prompt` | DOM tree included in prompt | +| `visible_elements_id_css_map` | CSS selector map for elements | +| `visible_elements_id_frame_map` | Frame map for elements | +| `visible_elements_id_xpath_map` | XPath map for elements | +| `hashed_href_map` | Hashed href mapping | + +You can filter by artifact type using query parameters: + +```bash +curl -X GET "https://api.skyvern.com/v1/runs/RUN_ID/artifacts?artifact_type=screenshot&artifact_type=recording" \ + -H "x-api-key: $SKYVERN_API_KEY" +``` + +--- + +## Next steps + + + + Configure engines, proxies, extraction schemas, etc when running a task + + + Define a schema to get typed JSON output from your automations + + diff --git a/docs/running-automations/task-parameters.mdx b/docs/running-automations/task-parameters.mdx new file mode 100644 index 00000000..f6ccb4b3 --- /dev/null +++ b/docs/running-automations/task-parameters.mdx @@ -0,0 +1,842 @@ +--- +title: Task Parameters +subtitle: Configure how your task runs +slug: running-automations/task-parameters +--- + +This page covers all parameters you can pass to `run_task`. + +Only `prompt` is a required parameter. + + +--- + +## Quick reference + +| Parameter | Type | Use this to | +|-----------|------|-------------| +| [`prompt`](#prompt) **(Required)** | string | Give natural language instructions for the AI | +| [`url`](#url) | string | Give a starting URL for the task | +| [`engine`](#engine) | string | Choose a different Agent model | +| [`data_extraction_schema`](#data_extraction_schema) | object | Get consistent, structured JSON output | +| [`max_steps`](#max_steps) | integer | Limit how long the Agent runs and cap costs | +| [`proxy_location`](#proxy_location) | string \| object | Access geo-restricted content or reduce bot detection | +| [`browser_session_id`](#browser_session_id) | string | Maintain state (cookies, login) across multiple tasks | +| [`totp_identifier`](#totp_identifier) | string | Handle 2FA when pushing codes to Skyvern | +| [`totp_url`](#totp_url) | string | Have Skyvern fetch 2FA codes from your endpoint | +| [`error_code_mapping`](#error_code_mapping) | object | Get custom error codes for programmatic handling | +| [`webhook_url`](#webhook_url) | string | Get notified when the task completes | +| [`title`](#title) | string | Label the task in the Skyvern UI | +| [`extra_http_headers`](#extra_http_headers) | object | Add custom headers (e.g., Authorization) to browser requests | +| [`publish_workflow`](#publish_workflow) | boolean | Convert this task into a reusable workflow | +| [`max_screenshot_scrolls`](#max_screenshot_scrolls) | integer | Capture lazy-loaded content in screenshots | +| [`browser_address`](#browser_address) | string | Connect to your own browser for local development | +| [`include_action_history_in_verification`](#include_action_history_in_verification) | boolean | Improve verification accuracy for multi-step forms | +| [`model`](#model) | object | Configure model settings (e.g., temperature) | + +--- + +## `prompt` + +**Required.** Natural language instructions describing what the AI should do. + + +```python Python +result = await client.run_task( + prompt="Find the cheapest flight from NYC to LAX on March 15" +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Find the cheapest flight from NYC to LAX on March 15", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Find the cheapest flight from NYC to LAX on March 15" + }' +``` + + +Be specific about your goal and what data you want extracted. The more detailed your prompt, the better the results. + +--- + +## `url` + +The starting page for the automation. Skyvern navigates from here based on your prompt. + + +```python Python +result = await client.run_task( + prompt="Get the top headline", + url="https://news.ycombinator.com" +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get the top headline", + url: "https://news.ycombinator.com", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get the top headline", + "url": "https://news.ycombinator.com" + }' +``` + + +If not provided, Skyvern attempts to determine an appropriate starting URL from your prompt. + +--- + +## `engine` + +The AI engine that powers the task. These are not iterations—they're suited for different purposes. + +| Engine | Description | +|--------|-------------| +| `skyvern-2.0` | **Default.** Multi-objective, flexible, handles complex multi-step tasks. 85.85% on WebVoyager benchmark. Slower and more expensive. | +| `skyvern-1.0` | Single objective, precise, faster, cheaper. Best for simple tasks like form filling or single-page extraction. | +| `openai-cua` | OpenAI's Computer Use Agent | +| `anthropic-cua` | Anthropic Claude Sonnet with computer use | +| `ui-tars` | UI-TARS model (Seed1.5-VL) via Doubao API | + + +Use `skyvern-1.0` when you have a clear, single goal and want faster, cheaper execution. Use `skyvern-2.0` when the task requires flexibility or multiple steps. + + + +```python Python +result = await client.run_task( + prompt="Fill out the contact form", + engine="skyvern-1.0" +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Fill out the contact form", + engine: "skyvern-1.0", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Fill out the contact form", + "engine": "skyvern-1.0" + }' +``` + + +--- + +## `data_extraction_schema` + +A [JSON Schema](https://json-schema.org/) defining the structure of output data. + +Use this when you need consistent, typed responses. + + +```python Python +result = await client.run_task( + prompt="Find the top post on Hacker News", + data_extraction_schema={ + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "The title of the top post" + }, + "points": { + "type": "integer", + "description": "Number of points" + } + } + } +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Find the top post on Hacker News", + data_extraction_schema: { + type: "object", + properties: { + title: { + type: "string", + description: "The title of the top post", + }, + points: { + type: "integer", + description: "Number of points", + }, + }, + }, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Find the top post on Hacker News", + "data_extraction_schema": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "The title of the top post" + }, + "points": { + "type": "integer", + "description": "Number of points" + } + } + } + }' +``` + + +Without a schema, output format varies based on what the AI extracts. With a schema, output matches your defined structure. + +--- + +## `max_steps` + +Maximum number of steps the task can take. The task fails if it exceeds this limit. + + +```python Python +result = await client.run_task( + prompt="Get the current stock price of AAPL", + max_steps=10 +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get the current stock price of AAPL", + max_steps: 10, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get the current stock price of AAPL", + "max_steps": 10 + }' +``` + + +On the cloud-hosted version, you're billed per step. Set this to a reasonable value during development to cap costs. + + +Set `max_steps` during development to avoid runaway costs. A task that loops or gets stuck will keep consuming steps until it hits this limit. + + +--- + +## `proxy_location` + +Route browser traffic through a residential proxy in a specific location. + +Use this for geo-restricted content or to reduce bot detection. + +**Country-level pools:** + +| Value | Location | +|-------|----------| +| `RESIDENTIAL` | Random US residential (default) | +| `RESIDENTIAL_GB` | United Kingdom | +| `RESIDENTIAL_DE` | Germany | +| `RESIDENTIAL_FR` | France | +| `RESIDENTIAL_ES` | Spain | +| `RESIDENTIAL_IE` | Ireland | +| `RESIDENTIAL_IN` | India | +| `RESIDENTIAL_JP` | Japan | +| `RESIDENTIAL_AU` | Australia | +| `RESIDENTIAL_CA` | Canada | +| `RESIDENTIAL_BR` | Brazil | +| `RESIDENTIAL_MX` | Mexico | +| `RESIDENTIAL_AR` | Argentina | +| `RESIDENTIAL_NZ` | New Zealand | +| `RESIDENTIAL_ZA` | South Africa | +| `RESIDENTIAL_IT` | Italy | +| `RESIDENTIAL_NL` | Netherlands | +| `RESIDENTIAL_PH` | Philippines | +| `RESIDENTIAL_TR` | Turkey | +| `RESIDENTIAL_ISP` | ISP proxy | +| `NONE` | No proxy | + + +```python Python +result = await client.run_task( + prompt="Get UK-specific pricing", + proxy_location="RESIDENTIAL_GB" +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get UK-specific pricing", + proxy_location: "RESIDENTIAL_GB", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get UK-specific pricing", + "proxy_location": "RESIDENTIAL_GB" + }' +``` + + +**Granular targeting (US states/cities):** + + +```python Python +result = await client.run_task( + prompt="Get California pricing", + proxy_location={ + "country": "US", + "subdivision": "CA", + "city": "San Francisco" + } +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get California pricing", + proxy_location: { + country: "US", + subdivision: "CA", + city: "San Francisco", + }, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get California pricing", + "proxy_location": { + "country": "US", + "subdivision": "CA", + "city": "San Francisco" + } + }' +``` + + +The full list of available proxy locations is shown above. Use `NONE` to disable proxies. + + +For geo-restricted sites, `proxy_location` is required—without it, you'll get blocked or see wrong regional content (e.g., US prices instead of UK prices). + + +--- + +## `browser_session_id` + +Run the task in an existing persistent browser session. + +Use this to maintain state (cookies, localStorage) across multiple tasks. + + +```python Python +result = await client.run_task( + prompt="Extract account data", + browser_session_id="pbs_123" +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Extract account data", + browser_session_id: "pbs_123", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Extract account data", + "browser_session_id": "pbs_123" + }' +``` + + +Browser sessions persist cookies, localStorage, and authentication state across multiple tasks. + +--- + +## `totp_identifier` + +Identifier for TOTP codes when you push codes to Skyvern's API. + +Use this for two-factor authentication during task execution. + + +```python Python +result = await client.run_task( + prompt="Log in and extract account balance", + totp_identifier="my-2fa-credential" +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Log in and extract account balance", + totp_identifier: "my-2fa-credential", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Log in and extract account balance", + "totp_identifier": "my-2fa-credential" + }' +``` + + +TOTP codes are used for two-factor authentication during automated logins. + +--- + +## `totp_url` + +URL that Skyvern calls to fetch TOTP codes when needed. + +Use this when Skyvern should retrieve codes from your endpoint. + + +```python Python +result = await client.run_task( + prompt="Log in and extract account balance", + totp_url="https://your-server.com/totp" +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Log in and extract account balance", + totp_url: "https://your-server.com/totp", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Log in and extract account balance", + "totp_url": "https://your-server.com/totp" + }' +``` + + +TOTP codes are used for two-factor authentication during automated logins. + +--- + +## `error_code_mapping` + +Map specific error conditions to custom error codes. + +Use this to make programmatic error handling easier. + + +```python Python +result = await client.run_task( + prompt="Log in and extract data", + error_code_mapping={ + "login_failed": "The login credentials are incorrect or the account is locked", + "maintenance_mode": "The website is down for maintenance" + } +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Log in and extract data", + error_code_mapping: { + login_failed: "The login credentials are incorrect or the account is locked", + maintenance_mode: "The website is down for maintenance", + }, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Log in and extract data", + "error_code_mapping": { + "login_failed": "The login credentials are incorrect or the account is locked", + "maintenance_mode": "The website is down for maintenance" + } + }' +``` + + +If Skyvern encounters a login failure matching your description, `output` contains `{"error": "login_failed"}` instead of a generic error message. + +--- + +## `webhook_url` + +URL to receive a POST request when the task completes. + +Use this instead of polling for production systems. + + +```python Python +result = await client.run_task( + prompt="Extract pricing data", + webhook_url="https://your-server.com/webhook" +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Extract pricing data", + webhook_url: "https://your-server.com/webhook", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Extract pricing data", + "webhook_url": "https://your-server.com/webhook" + }' +``` + + +Skyvern sends a POST request with the full run data when the task completes or fails. + +--- + +## `title` + +Display name for the task in the Skyvern UI. + + +```python Python +result = await client.run_task( + prompt="Get the top post", + title="HN Top Post Scraper" +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Get the top post", + title: "HN Top Post Scraper", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Get the top post", + "title": "HN Top Post Scraper" + }' +``` + + +--- + +## `extra_http_headers` + +Additional HTTP headers to include in browser requests. + + +```python Python +result = await client.run_task( + prompt="Access protected resource", + extra_http_headers={ + "Authorization": "Bearer your-token" + } +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Access protected resource", + extra_http_headers: { + Authorization: "Bearer your-token", + }, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Access protected resource", + "extra_http_headers": { + "Authorization": "Bearer your-token" + } + }' +``` + + +--- + +## `publish_workflow` + +Convert this task into a reusable workflow. Only available for `skyvern-2.0`. + + +```python Python +result = await client.run_task( + prompt="Fill out the contact form with provided data", + publish_workflow=True +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Fill out the contact form with provided data", + publish_workflow: true, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Fill out the contact form with provided data", + "publish_workflow": true + }' +``` + + +--- + +## `max_screenshot_scrolls` + +Number of scrolls for post-action screenshots. + +Use this for pages with lazy-loaded content. + + +```python Python +result = await client.run_task( + prompt="Extract all product listings", + max_screenshot_scrolls=3 +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Extract all product listings", + max_screenshot_scrolls: 3, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Extract all product listings", + "max_screenshot_scrolls": 3 + }' +``` + + +--- + +## `browser_address` + +Connect to a browser at a specific CDP address. + +Use this for local development only. + + +```python Python +result = await client.run_task( + prompt="Automate my local browser", + browser_address="http://127.0.0.1:9222" +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Automate my local browser", + browser_address: "http://127.0.0.1:9222", + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Automate my local browser", + "browser_address": "http://127.0.0.1:9222" + }' +``` + + +--- + +## `model` + +Optional model configuration for the task. + + +```python Python +result = await client.run_task( + prompt="Extract data from the page", + model={"temperature": 0.5} +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Extract data from the page", + model: { temperature: 0.5 }, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Extract data from the page", + "model": {"temperature": 0.5} + }' +``` + + +--- + +## `include_action_history_in_verification` + +Include action history when verifying task completion. Default: `false`. + + +```python Python +result = await client.run_task( + prompt="Complete the multi-step form", + include_action_history_in_verification=True +) +``` + +```typescript TypeScript +const result = await client.runTask({ + body: { + prompt: "Complete the multi-step form", + include_action_history_in_verification: true, + }, +}); +``` + +```bash cURL +curl -X POST "https://api.skyvern.com/v1/run/tasks" \ + -H "x-api-key: $SKYVERN_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "Complete the multi-step form", + "include_action_history_in_verification": true + }' +``` + + +--- + +## Next steps + + + + Define a schema to get typed JSON output + + + Execute tasks and retrieve results + +