From fc99ed09f13de975b5d5fbf5bdf8097da9d1bfc2 Mon Sep 17 00:00:00 2001 From: Suchintan Date: Tue, 18 Jun 2024 01:53:18 -0400 Subject: [PATCH] Add task and workflow docs (#486) --- .../quickstart-open-source.mdx | 2 + .../quickstart-skyvern-cloud.mdx | 1 + .../supported-functionality.mdx | 1 + docs/images/api_key_image.png | Bin 0 -> 72321 bytes docs/integrations/api.mdx | 2 + docs/integrations/make.com.mdx | 1 + docs/integrations/zapier.mdx | 1 + docs/mint.json | 9 +- docs/running-tasks/advanced-features.mdx | 2 + docs/running-tasks/api-spec.mdx | 99 +++++ docs/running-tasks/introduction.mdx | 16 + docs/running-tasks/prompting-tips.mdx | 2 + docs/running-tasks/visualizing-results.mdx | 2 + docs/running-tasks/webhooks-faq.mdx | 36 ++ docs/workflows/creating-workflows.mdx | 347 ++++++++++++++++++ docs/workflows/introduction.mdx | 16 + docs/workflows/running-workflows.mdx | 209 +++++++++++ docs/workflows/workflow-blocks.mdx | 2 + 18 files changed, 743 insertions(+), 5 deletions(-) create mode 100644 docs/getting-started/quickstart-open-source.mdx create mode 100644 docs/getting-started/quickstart-skyvern-cloud.mdx create mode 100644 docs/getting-started/supported-functionality.mdx create mode 100644 docs/images/api_key_image.png create mode 100644 docs/integrations/api.mdx create mode 100644 docs/integrations/make.com.mdx create mode 100644 docs/integrations/zapier.mdx create mode 100644 docs/running-tasks/advanced-features.mdx create mode 100644 docs/running-tasks/api-spec.mdx create mode 100644 docs/running-tasks/introduction.mdx create mode 100644 docs/running-tasks/prompting-tips.mdx create mode 100644 docs/running-tasks/visualizing-results.mdx create mode 100644 docs/running-tasks/webhooks-faq.mdx create mode 100644 docs/workflows/creating-workflows.mdx create mode 100644 docs/workflows/introduction.mdx create mode 100644 docs/workflows/running-workflows.mdx create mode 100644 docs/workflows/workflow-blocks.mdx diff --git a/docs/getting-started/quickstart-open-source.mdx b/docs/getting-started/quickstart-open-source.mdx new file mode 100644 index 00000000..2b8c58dd --- /dev/null +++ b/docs/getting-started/quickstart-open-source.mdx @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/docs/getting-started/quickstart-skyvern-cloud.mdx b/docs/getting-started/quickstart-skyvern-cloud.mdx new file mode 100644 index 00000000..1d49b6a6 --- /dev/null +++ b/docs/getting-started/quickstart-skyvern-cloud.mdx @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/getting-started/supported-functionality.mdx b/docs/getting-started/supported-functionality.mdx new file mode 100644 index 00000000..1d49b6a6 --- /dev/null +++ b/docs/getting-started/supported-functionality.mdx @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/images/api_key_image.png b/docs/images/api_key_image.png new file mode 100644 index 0000000000000000000000000000000000000000..b512bee89b933756932de54b30a6d28637c97f44 GIT binary patch literal 72321 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 literal 0 HcmV?d00001 diff --git a/docs/integrations/api.mdx b/docs/integrations/api.mdx new file mode 100644 index 00000000..2b8c58dd --- /dev/null +++ b/docs/integrations/api.mdx @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/docs/integrations/make.com.mdx b/docs/integrations/make.com.mdx new file mode 100644 index 00000000..1d49b6a6 --- /dev/null +++ b/docs/integrations/make.com.mdx @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/integrations/zapier.mdx b/docs/integrations/zapier.mdx new file mode 100644 index 00000000..1d49b6a6 --- /dev/null +++ b/docs/integrations/zapier.mdx @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/mint.json b/docs/mint.json index 2fb1f87c..723892e3 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -63,19 +63,18 @@ "getting-started/skyvern-in-action", "getting-started/quickstart-skyvern-cloud", "getting-started/quickstart-open-source", - "getting-started/supported-features" + "getting-started/supported-functionality" ] }, { "group": "Tasks", "pages": [ "running-tasks/introduction", - "running-tasks/prompting-tips", - "running-tasks/advanced-features", "running-tasks/api-spec", - "running-tasks/webhooks", + "running-tasks/webhooks-faq", "running-tasks/visualizing-results", - "running-tasks/visualizing-results-advanced" + "running-tasks/prompting-tips", + "running-tasks/advanced-features" ] }, { diff --git a/docs/running-tasks/advanced-features.mdx b/docs/running-tasks/advanced-features.mdx new file mode 100644 index 00000000..2b8c58dd --- /dev/null +++ b/docs/running-tasks/advanced-features.mdx @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/docs/running-tasks/api-spec.mdx b/docs/running-tasks/api-spec.mdx new file mode 100644 index 00000000..6303d6a0 --- /dev/null +++ b/docs/running-tasks/api-spec.mdx @@ -0,0 +1,99 @@ +--- +title: API Spec +description: 'The core building block in Skyvern' +--- + +Tasks are the building block of Skyvern. They represent a single instruction to the browser to go do something using language models. Ex. “Go to alibaba and extract this information” + +## Request - Initiate a task (Webhook) + +### Body + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| url | String | yes | https://jobs.lever.co/leverdemo-8/45d39614-464a-4b62-a5cd-8683ce4fb80a/apply | The website that you would like to browse / scrape. This should be the ideal starting point for the agent | +| webhook_callback_url | String | no | … | The callback URL once our system is finished processing this async task | +| navigation_goal | String | no | Apply for a job | The prompt that tells the agent what the user-facing goal is. This is the guiding light for the LLM as it navigates a particular website / sitemap to achieve this specified goal | +| data_extraction_goal | String | no | Was the job application successful? | The prompt that instructs the agent to extract information once the agent has achieved its user_goal | +| navigation_payload | Object | no | "name": "Chris P. Bacon",
"email": "mailto:chris@pbacon.com" | JSON-formatted payload with any “facts” or information that would help the agent perform its job. In the case of navigating an insurance quote, this payload would include any user information to help fill out the insurance flow such as date of birth, or age they got their license, and so on

This can include nested information, and the formatting isn’t validated | +| proxy_location | String | yes | RESIDENTIAL | Proxy location for the web-browsing request. Please pass RESIDENTIAL as a value | +| extracted_information_schema | JSON | no | | Used to enforce a JSON schema spec to be enforced in the data_extraction_goal. Similar to https://json-schema.org/ definition. | + +## Example Request (Apply for a job) + +```python +{ + "url": "https://jobs.lever.co/leverdemo-8/45d39614-464a-4b62-a5cd-8683ce4fb80a/apply", + "navigation_goal": "Apply for a job", + "data_extraction_goal": "Was the job application successful?", + "proxy_location": "RESIDENTIAL", + "navigation_payload": { + "name": "Chris P. Bacon", + "email": "chris@pbacon.com" + } +} +``` + +## Response + +| Parameter | Type | Always returned? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| task_id | String | yes | t_123456 | The task id associated with this specific task | + +## Response Webhook - Task conclusion (POST) + +### Headers + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| x-skyvern-signature | String | yes | v0=a2114d57b48eac39b9ad189
dd8316235a7b4a8d21a10bd275
19666489c69b503 | Authentication token that allows our service to communicate with your backend service via callback / webhook
We’ll be using the same strategy slack uses, as defined here: https://api.slack.com/authentication/verifying-requests-from-slack#making__validating-a-request | +| x-skyvern-timestamp | String | yes | 1531420618 | Timestamp used to decode and validate the incoming webhook call

We’ll be using the same strategy slack uses, as defined here: https://api.slack.com/authentication/verifying-requests-from-slack#making__validating-a-request | + +### Body + +| Parameter | Type | Always returned? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| task_id | String | yes | t_123456 | The task id associated with this specific task | +| extracted_information | Object | Yes | 'price’: ‘$100.0’ | Unstructured JSON payload containing the extracted information as specified by the users’ input prompt | +| screenshot_url | String | Yes | … url to screenshot … | Screenshot of the final page, where the data extraction occurs | +| recording_url | String | Yes | .. url to recording … | Recording of the entire browsing session to help debug any issues | +| failure_reason | String | No | “Failed to pass this page - missing information: date of birth” | A failure reason that caused the job to fail. This can range from internal errors (Skyvern side) or external errors (insufficient information provided) | + +## Request - Task Details (GET) + +You can use this API to poll for task status updates if you don’t want to wait for webhook callbacks. + +Request type: `GET` + +Production:`api.skyvern.com/api/v1/tasks/{task_id}` + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| task_id | String | yes | t_123 | The id of the task you want to check the status of | + +## Request - List Task Details (GET) + +Request type: `GET` + +Production:`api.skyvern.com/api/v1/tasks/` + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| page | Integer | no | 1 | default=1 +has to be ≥1 | +| page_size | Integer | no | 10 | default=10 +has to be ≥1 | + +## Response - Task Details (GET) + +| Parameter | Type | Sample Value | Description | +| --- | --- | --- | --- | +| request | JSON | | Includes the initial request sent to create the task. Fields included: url,webhook_callback_url,navigation_goal,data_extraction_goal,navigation_payload,proxy_location,extracted_information_schema | +| task_id | String | t_123 | The id of the task you want to check the status of | +| status | String | SUCCESS / FAILURE / IN_PROGRESS | String indicating the status of this task | +| created_at | Timestamp | 2022-11-22T22:55:55 | Timestamp indicating when the task was created. | +| modified_at | Timestamp | 2022-11-22T22:55:55 | Timestamp indicating when the task was last updated. Used to detect long-running tasks. | +| extracted_information | Object | Yes | 'price’: ‘$100.0’ | +| screenshot_url | String | Yes | … url to screenshot … | +| recording_url | String | Yes | .. url to recording … | +| failure_reason | String | No | “Failed to pass this page - missing information: invalid password” | diff --git a/docs/running-tasks/introduction.mdx b/docs/running-tasks/introduction.mdx new file mode 100644 index 00000000..394ae5f2 --- /dev/null +++ b/docs/running-tasks/introduction.mdx @@ -0,0 +1,16 @@ +--- +title: Introduction +description: 'Tasks are the building block of Skyvern' +--- + +# Getting your API Key + +1. Navigate to [app.skyvern.com](https://app.skyvern.com) and log into your account +1. Validate that you're in the correct account (personal vs organization) +1. Click on "Settings" +1. Click Reveal to see your API key. This is the unique key associated with your account that allows you to intract with Skyvern + + + + + \ No newline at end of file diff --git a/docs/running-tasks/prompting-tips.mdx b/docs/running-tasks/prompting-tips.mdx new file mode 100644 index 00000000..2b8c58dd --- /dev/null +++ b/docs/running-tasks/prompting-tips.mdx @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/docs/running-tasks/visualizing-results.mdx b/docs/running-tasks/visualizing-results.mdx new file mode 100644 index 00000000..2b8c58dd --- /dev/null +++ b/docs/running-tasks/visualizing-results.mdx @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/docs/running-tasks/webhooks-faq.mdx b/docs/running-tasks/webhooks-faq.mdx new file mode 100644 index 00000000..281d63f6 --- /dev/null +++ b/docs/running-tasks/webhooks-faq.mdx @@ -0,0 +1,36 @@ +--- +title: Webhooks FAQ +description: 'How Skyvern notifies you when its done' +--- + +# FAQ +## Webhooks vs HTTP requests? + +We use Webhooks for executing tasks as the expected runtime of these jobs can exceed default HTTP timeouts (1 minute) + +## How do we handle webhook authentication? (ie how can we handle callbacks?) + +- a python example for how to generate the signature: + +```python +def validate_skyvern_request_headers(request: Request) -> bool: + header_skyvern_signature = request.headers["x-skyvern-signature"] + payload = request.body() # this is a bytes + hash_obj = hmac.new(SKYVERN_API_KEY.encode("utf-8"), msg=payload, digestmod=hashlib.sha256) + client_generated_signature = hash_obj.hexdigest() + return header_skyvern_signature == client_generated_signature +``` + +SKYVERN_API_KEY: this is the [api key](/running-tasks/introduction) specific to your organization + +# Webhook common parameters + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| webhook_callback_url | String | yes | … | | + +# Required Headers + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| x-api-key | String | yes | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e
yJleHAiOjQ4MjU0MjI5NzUsInN1YiI6
Im9fMTA2MTUxNzEyNjQ5ODUxMzQ2In0 | Bearer token that gives your backend access to the Skyvern API. This will be manually provided by us | diff --git a/docs/workflows/creating-workflows.mdx b/docs/workflows/creating-workflows.mdx new file mode 100644 index 00000000..f5b75cdb --- /dev/null +++ b/docs/workflows/creating-workflows.mdx @@ -0,0 +1,347 @@ +--- +title: Creating Workflows +description: 'Creating complex multi-step workflows' +--- + +## Building workflows + +Workflows represent chaining multiple blocks together. Imagine calling multiple tasks in a row, doing conditional logic, extracting data to a CSV, etc. All of these ideas will be supported within our workflows feature + +All of our workflows are defined in **YAML** format, and allow chaining multiple components together to generate some defined output + +Today, we’re building the workflows for most of our customers as we iterate on the specification. +This is a cumbersome experience -- rest assured that we are improving our web application that will offer a significantly enhanced user experience for this process. + +## Request - Create Workflow (YAML) +`POST api.skyvern.com/api/v1/workflows` + +Use this API to create a workflow. The response of this API is a `workflow_permanent_id`, which can be used to run workflows below + + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| title | String | yes | Calculate a product price diff % | A title for a workflow | +| description | String | yes | Compare two products' price diff % on alibaba vs newlabelwholesale | A description for a workflow | + +## Workflow Parameters + +Workflow parameters are specific parameters you’re going to be passing into the workflows to allow execution + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| key | String | yes | alibaba_url | unique key corresponding to a specific parameter | +| parameter_type | Enum | yes | workflow | The type of parameter for the workflow. Meant to indicate whether this parameter is being passed in via the run workflow endpoint (workflow), or whether a parameter is the output of a different workflow step (output). Can be workflow , context, aws_secret, or output | +| workflow_parameter_type | Enum | no? | string | The actual type of the parameter, meant to be used for type-safety reasons.
Supported types:
STRING = "string"
INTEGER = "integer"
FLOAT = "float"
BOOLEAN = "boolean"
JSON = "json” | +| description | string | yes | Alibaba product URL for checking the price of the product | Description of the parameter | + +## Blocks + +Blocks are the building block (pun intended) of Skyvern’s workflows. Each block is one discrete task you want to occur. Multiple blocks may be chained together, with outputs from one block being fed as inputs to the next block. + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| block_type | Enum | yes | Task | Signifying the type of block this is in the workflow | +| label | String | yes | get_alibaba_price | The unique identifier for this block within this workflow | +| parameter_keys | Array | yes | parameter_keys:
- alibaba_price
- NLW_price | The list of parameters this block depends on for execution | +| output_parameter_key | string | yes | output_parameter_key: price_diff_percentage | The optional output of the block, so that it may be used by other blocks | +| \{\{ block specific parameters }} | ?? | yes | | Other parameters, specific to the block_type specified above. These are covered below | + + +### TaskBlock + +The magic block. Skyvern navigates through the websites to take actions and/or extract information. + +Example block: +``` +- block_type: task + label: login + parameter_keys: + - credentials + url: website_url + navigation_goal: >- + If you're not on the login page, navigate to login page and login using + the credentials given. First, take actions on promotional popups or cookie prompts that could prevent taking other action on the web page. If you fail to login to find the login page or can't login after several trials, terminate. If login is + completed, you're successful. + data_extraction_goal: >- + Extract anything for the sake of this demo + error_code_mapping: + stuck_with_popups: terminate and return this error if you can't close popups after several tries and can't take the necessary actions on the website because there is a blocking popup on the page + failed_to_login: terminate and return this error if you fail logging in to the page +``` + +### ForLoopBlock +Iterate over something such as a CSV or the output of a previous block. The blocks nedted under `loop_blocks` are the blocks that will be repeated for each entry in the + +``` +- block_type: for_loop + label: iterate_over_order_ids + loop_over_parameter_key: order_ids + continue_on_failure: true + loop_blocks: + - block_type: task + label: download_invoice_for_order + complete_on_download: true + continue_on_failure: true + parameter_keys: + - order_id + url: order_history_url + navigation_goal: >- + Download the invoice of the order with the given order ID. + Make sure to download the invoice for the given order id. + If the element tree doesn't have a matching order id, check the screenshots. + Complete if you have successfully downloaded the invoice according to action history, if you were able to download it, you'll see download_triggered=True for the last step. + If you don't see a way to download an invoice, navigate to the order page if possible. + If there's no way to download an invoice terminate. + If the text suggests printing, you can assume you can download it. + Return click action with download=True if you want to trigger a download. + error_code_mapping: + not_possible_to_download_invoice: return this error if the website doesn't allow downloading/viewing invoices + cant_solve_captcha: return this error if captcha isn't solved after multiple retries +``` + +### CodeBlock +This block executes user-defined code within our execution environment. It’s able to take parameters as input and transform them based on a certain specification + +**Example Block** + +```json +- block_type: code + label: calculate_percentage_diff + parameter_keys: + - alibaba_price + - amazon_price + code: | + if amazon_price["unitPrice"] and alibaba_price["unitPrice"]: + result = 1.0 * (alibaba_price["unitPrice"] - amazon_price["unitPrice"]) / amazon_price["unitPrice"] + else: + result = None + output_parameter_key: price_diff_percentage +``` + +### TextPromptBlock + +Do a custom OpenAI query as a part of your workflow + +``` +- block_type: text_prompt + label: generate_new_title + parameter_keys: + - alibaba_title + - amazon_title + llm_key: OPENAI_GPT4O + prompt: > + You're given two e-commerce product titles. Use both and generate a + better one. + + Title 1: {{ alibaba_title }} + Title 2: {{ amazon_title }} + output_parameter_key: new_title +``` + +### DownloadToS3Block +### UploadToS3Block + +Persists files inside S3 + +``` + - block_type: upload_to_s3 + label: upload_downloaded_files_to_s3 + path: SKYVERN_DOWNLOAD_DIRECTORY +``` + +### SendEmailBlock + +Sends an email with some data + +``` + - block_type: send_email + label: send_email + smtp_host_secret_parameter_key: smtp_host + smtp_port_secret_parameter_key: smtp_port + smtp_username_secret_parameter_key: smtp_username + smtp_password_secret_parameter_key: smtp_password + sender: hello@skyvern.com + recipients: + - founders@skyvern.com + subject: Skyvern - Downloaded Invoices Demo + body: website_url + file_attachments: + - SKYVERN_DOWNLOAD_DIRECTORY +``` + + +## Managing Credentials +This is something the Skyvern team will need to set you up with today. If you're interested, please [book a call with Suchintan](https://meetings.hubspot.com/suchintan) + + +## Common concepts +### `continue_on_failure` + +`continue_on_failure` flag indicates whether a failed block execution should block subsequent blocks or not + +### `error_code_mapping` + +Maps errors to specific error codes so you can have deterministic outputs + +### `output_parameter_key` (autogenerated) + +Specifies the output parameter of a specific block so it can be re-used in a subsequent block + +Its format is always: `{label}_output` + +ie the output parameter for a block like this (which can be referenced in subsequent blocks) would be: `login_output` +``` +- block_type: task + label: login + parameter_keys: + - credentials + url: website_url + navigation_goal: >- + If you're not on the login page, navigate to login page and login using + the credentials given. First, take actions on promotional popups or cookie prompts that could prevent taking other action on the web page. If you fail to login to find the login page or can't login after several trials, terminate. If login is + completed, you're successful. + data_extraction_goal: >- + Extract anything for the sake of this demo + error_code_mapping: + stuck_with_popups: terminate and return this error if you can't close popups after several tries and can't take the necessary actions on the website because there is a blocking popup on the page + failed_to_login: terminate and return this error if you fail logging in to the page +``` + + +## Example workflow +``` +title: Invoice Downloading Demo (Jun 13) +description: >- + Login to the website, download all the invoices after a date, email the + invoices +workflow_definition: + parameters: + - key: website_url + parameter_type: workflow + workflow_parameter_type: string + - key: credentials + parameter_type: bitwarden_login_credential + bitwarden_client_id_aws_secret_key: SECRET + bitwarden_client_secret_aws_secret_key: SECRET + bitwarden_master_password_aws_secret_key: SECRET + bitwarden_collection_id: SECRET + url_parameter_key: website_url + - key: invoice_retrieval_start_date + parameter_type: workflow + workflow_parameter_type: string + - key: smtp_host + parameter_type: aws_secret + aws_key: SKYVERN_SMTP_HOST_AWS_SES + - key: smtp_port + parameter_type: aws_secret + aws_key: SKYVERN_SMTP_PORT_AWS_SES + - key: smtp_username + parameter_type: aws_secret + aws_key: SKYVERN_SMTP_USERNAME_SES + - key: smtp_password + parameter_type: aws_secret + aws_key: SKYVERN_SMTP_PASSWORD_SES + - parameter_type: context + key: order_history_url + source_parameter_key: get_order_history_page_url_and_qualifying_order_ids_output + - parameter_type: context + key: order_ids + source_parameter_key: get_order_history_page_url_and_qualifying_order_ids_output + - parameter_type: context + key: order_id + source_parameter_key: order_ids + blocks: + - block_type: task + label: login + parameter_keys: + - credentials + url: website_url + navigation_goal: >- + If you're not on the login page, navigate to login page and login using the credentials given, and then navigate to the personal account page. First, take actions on promotional popups or cookie prompts that could prevent taking other action on the web page. Then, try to login and navigate to the personal account page. If you fail to login to find the login page or can't login after several trials, terminate. If you're on the personal account page, consider the goal is completed. + error_code_mapping: + stuck_with_popups: terminate and return this error if you can't close popups after several tries and can't take the necessary actions on the website because there is a blocking popup on the page + failed_to_login: terminate and return this error if you fail logging in to the page + - block_type: task + label: get_order_history_page_url_and_qualifying_order_ids + parameter_keys: + - invoice_retrieval_start_date + navigation_goal: Find the order history page. If there is no orders after given start date, terminate. + data_extraction_goal: >- + You need to extract the order history page url by looking at the current + page you're on. You need to extract contact emails you see on the page. You also need to extract the order ids for orders that + happened on or after invoice_retrieval_start_date. Make sure to filter + only the orders that happened on or after invoice_retrieval_start_date. You need to compare each order's date with the invoice_download_start_date. You can only include an order in the output if the order's date is after or the same as the invoice_download_start_date. + While comparing dates, first compare year, then month, then day. invoice_retrieval_start_date + is in YYYY-MM-DD format. The dates on the websites may be in different formats, compare accordingly and compare year, date, and month. + error_code_mapping: + failed_to_find_order_history_page: return this error if you can't find the order history page on the website + no_orders_found_after_start_date: return this error if there are no orders after the specified invoice_download_start_date + data_schema: + type: object + properties: + order_history_url: + type: url + description: >- + The exact URL of the order history page. Do not make any + assumptions. Return the URL that's passed along in this context. + contact_emails: + type: array + items: + type: string + description: Contact email for the ecommerce website you're on. If you can't find any return null + date_comparison_scratchpad: + type: string + description: >- + You are supposed to filter the orders that happened on or after the invoice_download_start_date. Think through how you will approach this task step-by-step here. Consider these before starting the comparison: + - What format is the order date in? How can you parse it into a structured format? + - What is the correct way to compare two dates? + - How will you compare the order dates to the invoice_download_start_date? + + Write out your thought process before filling out the order_ids field below. Remember, the original date may be in any format, so parse it carefully! The invoice_download_start_date will be an exact date you can directly compare against in the format YYYY-MM-DD. + order_ids: + type: array + items: + type: object + properties: + order_date: + type: iso-8601-date-string + order_id: + type: string + description: >- + Return a list of order id strings. Do not return order ids of + orders that happened before the specified + invoice_retrieval_start_date + - block_type: for_loop + label: iterate_over_order_ids + loop_over_parameter_key: order_ids + continue_on_failure: true + loop_blocks: + - block_type: task + label: download_invoice_for_order + complete_on_download: true + continue_on_failure: true + parameter_keys: + - order_id + url: order_history_url + navigation_goal: Download the invoice of the order with the given order ID. Make sure to download the invoice for the given order id. If the element tree doesn't have a matching order id, check the screenshots. Complete if you have successfully downloaded the invoice according to action history, if you were able to download it, you'll see download_triggered=True for the last step. If you don't see a way to download an invoice, navigate to the order page if possible. If there's no way to download an invoice terminate. If the text suggests printing, you can assume you can download it. Return click action with download=True if you want to trigger a download. + error_code_mapping: + not_possible_to_download_invoice: return this error if the website doesn't allow downloading/viewing invoices + cant_solve_captcha: return this error if captcha isn't solved after multiple retries + - block_type: upload_to_s3 + label: upload_downloaded_files_to_s3 + path: SKYVERN_DOWNLOAD_DIRECTORY + - block_type: send_email + label: send_email + smtp_host_secret_parameter_key: smtp_host + smtp_port_secret_parameter_key: smtp_port + smtp_username_secret_parameter_key: smtp_username + smtp_password_secret_parameter_key: smtp_password + sender: hello@skyvern.com + recipients: + - founders@skyvern.com + subject: Skyvern - Downloaded Invoices Demo + body: website_url + file_attachments: + - SKYVERN_DOWNLOAD_DIRECTORY + +``` diff --git a/docs/workflows/introduction.mdx b/docs/workflows/introduction.mdx new file mode 100644 index 00000000..93f2db21 --- /dev/null +++ b/docs/workflows/introduction.mdx @@ -0,0 +1,16 @@ +--- +title: Introduction +description: 'Workflows -- chaining multiple tasks together' +--- + +Workflows represent chaining multiple blocks together. Imagine calling multiple tasks in a row, doing conditional logic, extracting data to a CSV, etc. All of these ideas will be supported within our workflows feature. + +Building blocks supported today: + +1. TaskBlock: The **magic** block. Skyvern navigates through the websites to take actions and/or extract information. +2. ForLoopBlock +3. CodeBlock +4. TextPromptBlock +5. DownloadToS3Block +6. UploadToS3Block +7. SendEmailBlock diff --git a/docs/workflows/running-workflows.mdx b/docs/workflows/running-workflows.mdx new file mode 100644 index 00000000..4f27e32d --- /dev/null +++ b/docs/workflows/running-workflows.mdx @@ -0,0 +1,209 @@ +--- +title: Running Workflows +description: 'Executing complex multi-step workflows' +--- + +## Running workflows + +### `POST /workflows/{workflow_permanent_id}/run` + +You can see the generic endpoint definition below. We’ll go into the specifics of the invoice retrieval workflow in the next section. + +### Body + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| data | JSON | no | \{
"website_url": "YOUR_URL",
"invoice_retrieval_start_date": "2024-04-15"
\}, | The data field is used to pass in required and optional parameters that a workflow accepts. For the invoice retrieval workflow, required fields are website_url and invoice_retrieval_start_date | +| webhook_callback_url | String | no | … | Our system will send the webhook once it is finished executing the workflow run. | +| proxy_location | String | no | RESIDENTIAL | Proxy location for the web browser. Please pass RESIDENTIAL.
If we use residential proxies, Skyvern’s requests to the websites will be less suspicious. | + +### Response + +| Parameter | Type | Always returned? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| workflow_permanent_id | String | yes | wpid_123456 | The workflow id | +| workflow_run_id | String | yes | wr_123456 | The workflow run id that represents this specific workflow run.
You can use this id to match the webhook response to the initial request. | + +### Sample Request & Response - Invoice retrieval + +```bash +-- Sample Request +curl --location 'https://api.skyvern.com/api/v1/workflows/wpid_123456/run' \ +--header 'x-api-key: ' \ +--header 'Content-Type: application/json' \ +--data '{ + "data": { + "website_url": "your_website", + "invoice_retrieval_start_date": "2024-04-15" + }, + "proxy_location": "RESIDENTIAL", + "webhook_callback_url": "" +}' + +-- Sample Response +{ + "workflow_id": "wpid_123456", + "workflow_run_id": "wr_123456" +} +``` + +## Retrieving workflow runs + +### `GET /workflows/{workflow_id}/runs/{workflow_run_id}` + +### Response + +| Parameter | Type | Sample value | Description | +| --- | --- | --- | --- | +| workflow_id | String | wpid_123456 | | +| workflow_run_id | String | wr_123456 | | +| status | String | completed | Status of the workflow run. Possible values: created, running, failed, terminated, completed | +| proxy_location | JSON | RESIDENTIAL | | +| webhook_callback_url | String | 127.0.0.1:8000/api/v1/webhook | | +| created_at | Timestamp | 2024-05-16T08:35:24.920793 | Timestamp for when the workflow run is created | +| modified_at | Timestamp | 2024-05-16T08:42:32.568908 | Last modified timestamp for the workflow run | +| parameters | JSON | see sample response below | The parameters that the workflow run was triggered with. For the invoice retrieval workflow, this field will have the website_url and invoice_retrieval_start_date values you sent. | +| screenshot_urls | list[String] | see sample response below | Final screenshots for the last 3 tasks in the workflow. | +| recording_url | String | see sample response below | The full browser recording. | +| outputs | JSON | see sample response below | See the explaining outputs section | + +### Sample response + +```json +{ + "workflow_id": "wpid_123456", + "workflow_run_id": "wr_123456", + "status": "completed", + "proxy_location": "RESIDENTIAL", + "webhook_callback_url": "127.0.0.1:8000/api/v1/webhook", + "created_at": "2024-05-16T08:35:24.920793", + "modified_at": "2024-05-16T08:42:32.568908", + "parameters": { + "website_url": "YOUR_WEBSITE_URL", + "invoice_retrieval_start_date": "2024-04-15" + }, + "screenshot_urls": [ + "https://skyvern-artifacts.s3.amazonaws.com/...", + "https://skyvern-artifacts.s3.amazonaws.com/...", + "https://skyvern-artifacts.s3.amazonaws.com/..." + ], + "recording_url": "https://skyvern-artifacts.s3.amazonaws.com/...", + "outputs": { + "login_output": { + "task_id": "tsk_1234", + "status": "completed", + "extracted_information": null, + "failure_reason": null, + "errors": [] + }, + "get_order_history_page_url_and_qualifying_order_ids_output": { + "task_id": "tsk_258409009008559418", + "status": "completed", + "extracted_information": { + ... + }, + "failure_reason": null, + "errors": [] + }, + "iterate_over_order_ids_output": [ + [ + { + ... + } + ] + ], + "download_invoice_for_order_output": { + "task_id": "tsk_258409361195877732", + "status": "completed", + "extracted_information": null, + "failure_reason": null, + "errors": [] + }, + "upload_downloaded_files_to_s3_output": [ + "s3://skyvern-uploads/..." + ], + "send_email_output": { + "success": true + } + } +} +``` + +## Webhooks + +Skyvern always sends webhooks when a workflow run is executed. The status for an executed workflow run can be: `completed, failed, terminated`. + +The webhook body is the same as the get workflow run endpoint. + +### Webhook Headers + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| x-skyvern-signature | String | yes | v0=a2114d57b48eac39b9ad189dd8316235a7b4a8d21a10bd27519666489c69b503 | Authentication token that allows our service to communicate with your backend service via callback / webhook

We’ll be using the same strategy slack uses, as defined here: https://api.slack.com/authentication/verifying-requests-from-slack#making__validating-a-request | +| x-skyvern-timestamp | String | yes | 1531420618 | Timestamp used to decode and validate the incoming webhook call + +We’ll be using the same strategy slack uses, as defined here: https://api.slack.com/authentication/verifying-requests-from-slack#making__validating-a-request | + +## Explaining `outputs` + +If you checked out the sample response, you probably thought “What the heck is this field right here?”. + +We previously went over that workflows are essentially a list of building blocks. `outputs` field has the output for every single block that a workflow has. Before we start analyzing the `outputs` from the sample above, let’s go over the building blocks for the invoice retrieval workflow. + +### Building blocks of invoice retrieval workflow: + +| # | Block type | Block label | Purpose | +| --- | --- | --- | --- | +| 1 | TaskBlock | login | Find login page, login to the website | +| 2 | TaskBlock | get_order_history_page_url_and_qualifying_order_ids | Find the order history page, extract order history page url, contact emails, and order details for orders after the start date | +| 3 | ForLoopBlock | iterate_over_order_ids | The contents of the ForLoop is executed for each order id that’s extracted from the previous step. | +| 4 | TaskBlock [within ForLoopBlock] | download_invoice_for_order | For a given order id, find a way to download the invoice, download it. | +| 5 | UploadToS3Block | upload_downloaded_files_to_s3 | Upload all downloaded invoices to S3 | +| 6 | SendEmailBlock | send_email | Send an email attaching all the downloaded invoices | + +### ⚠️ Still in development, not a blocker + +1. The blocks within the ForLoop show up twice: within the ForLoop output and as a root block. +2. UploadToS3Block output is S3 URIs at the moment. They’ll be updated with signed urls instead. +3. Add block type to each object in `outputs`, define the output structure for each block for easier integration. + + +```json +... +"outputs": { + "login_output": { + "task_id": "tsk_1234", + "status": "completed", + "extracted_information": null, + "failure_reason": null, + "errors": [] + }, + "get_order_history_page_url_and_qualifying_order_ids_output": { + "task_id": "tsk_1234", + "status": "completed", + "extracted_information": { + ... + }, + "failure_reason": null, + "errors": [] + }, + "iterate_over_order_ids_output": [ + ... + ], + "download_invoice_for_order_output": { + "task_id": "tsk_1234", + "status": "completed", + "extracted_information": null, + "failure_reason": null, + "errors": [] + }, + "upload_downloaded_files_to_s3_output": [ + "s3://skyvern-uploads/...", + "s3://skyvern-uploads/..." + ], + "send_email_output": { + "success": true + } +} +... +``` diff --git a/docs/workflows/workflow-blocks.mdx b/docs/workflows/workflow-blocks.mdx new file mode 100644 index 00000000..2b8c58dd --- /dev/null +++ b/docs/workflows/workflow-blocks.mdx @@ -0,0 +1,2 @@ + + \ No newline at end of file