diff --git a/fern/browser-sessions/introduction.mdx b/fern/browser-sessions/introduction.mdx new file mode 100644 index 00000000..a80b1d88 --- /dev/null +++ b/fern/browser-sessions/introduction.mdx @@ -0,0 +1,33 @@ +--- +title: Introduction +subtitle: Run continuous tasks and workflows with a long-lived browser session +slug: browser-sessions/introduction +--- + +## Why Browser Sessions? +Skyvern Browser Session is a way to persist the real-time state of the browser, so that any run can continue from where the previous run left off. Here are some scenarios when Skyvern Browser Session comes in handy: +- You have multiple continuous tasks that need to interact with the browser in real-time without much delay. For example, you are developing a phone agent for your customer support center and your agent needs access to real time information in the browser. +- You have several related tasks that may need to be executed but with interruptions in between. For example, you are developing an shopping agent that needs human in the loop to help fulfill the purchase. + +Skyvern Browser Sessions is currently is only available via [API & SDK](/api-reference/api-reference/browser-session/create-browser-session). + +## Create a Browser Session + +```python +from skyvern import Skyvern + +skyvern = Skyvern(api_key="YOUR_API_KEY") +browser_session = await skyvern.browser_sessions.create_browser_session( + timeout=60, +) +``` + +The `timeout` parameter (`>=5, <=10080`) is the max time in minutes that the browser session can run. + + + +## Get Information Of A Browser Session +[API doc](/api-reference/api-reference/browser-session/get-browser-session) + +## Close a Browser Session +[API doc](/api-reference/api-reference/browser-session/close-browser-session) \ No newline at end of file diff --git a/fern/credentials/credit_cards.mdx b/fern/credentials/credit-cards.mdx similarity index 100% rename from fern/credentials/credit_cards.mdx rename to fern/credentials/credit-cards.mdx diff --git a/fern/credentials/totp.mdx b/fern/credentials/totp.mdx index 95376c09..60d18b8c 100644 --- a/fern/credentials/totp.mdx +++ b/fern/credentials/totp.mdx @@ -15,7 +15,7 @@ Save your username and password in [Skyvern Credential](https://app.skyvern.com/ See [Password Management](/credentials/passwords#manage-passwords-in-skyvern-cloud) for more details. ## Option 2: Get Code From Your Endpoint -You can pass `totp_verification_url` when [creating a task](/running-tasks/api-spec#request-initiate-a-task). Inside this endpoint hosted by you, you have to conform to the following schema: +You can pass `totp_url` when running [a task](/api-reference/api-reference/agent/run-task) or a [workflow](/api-reference/api-reference/agent/run-workflow). Inside this endpoint hosted by you, you have to conform to the following schema: ### Set Up Your TOTP Endpoint For websites that requires a verification code to complete a task, you have to set up a TOTP endpoint for Skyvern to fetch the verification code. @@ -47,10 +47,12 @@ def validate_skyvern_request_headers(request: Request) -> bool: return header_skyvern_signature == client_generated_signature ``` -SKYVERN_API_KEY: this is the [api key](/running-tasks/introduction) specific to your organization +SKYVERN_API_KEY: you can get the API KEY from [Skyvern Settings](https://app.skyvern.com/settings). ## Option 3: Push Code To Skyvern -You can pass `totp_identifier` when [creating a task](/running-tasks/api-spec#request-initiate-a-task). When the TOTP code arrives at your inbox or as a text message, all you need to do is to send the email/message (Gmail + Zapier integration can be a good solution to set up email forwarding) to Skyvern's TOTP receiver endpoint. See the [TOTP API for more details](https://docs.skyvern.com/api-reference/api-reference/credentials/send-totp-code). +Find TOTP API doc [here](/api-reference/api-reference/credentials/send-totp-code). + +You can pass `totp_identifier` when running [a task](/api-reference/api-reference/agent/run-task) or a [workflow](/api-reference/api-reference/agent/run-workflow). When the TOTP code arrives at your inbox, all you need to do is to send the email/message (Gmail + Zapier integration can be a good solution to set up email forwarding) to Skyvern's TOTP endpoint. ### Forwarding Your Email To Skyvern (Gmail + Zapier) This setup requires a Zapier pro plan account. @@ -98,7 +100,7 @@ In the Setup, choose “POST” under the `Action event` selection. Then click In the “Configure”, set up these in order to make a POST request to Skyvern’s TOTP API: -- URL: [`https://api.skyvern.com/api/v1/totp`](https://api.skyvern.com/api/v1/totp) +- URL: [`https://api.skyvern.com/v1/credentials/totp`](https://api.skyvern.com/v1/credentials/totp) - Payload Type: json - Data: - totp_identifier: choose `Raw To Email` after clicking the “+” sign diff --git a/fern/docs.yml b/fern/docs.yml index 44ad46a2..f5bc82e6 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -74,14 +74,16 @@ navigation: path: getting-started/prompting-guide.mdx - section: Tasks contents: - - page: Tasks API - path: running-tasks/api-spec.mdx - - page: Webhooks FAQ - path: running-tasks/webhooks-faq.mdx + - page: Task Features + path: running-tasks/run-tasks.mdx - page: Visualizing Results path: running-tasks/visualizing-results.mdx + - page: Webhooks FAQ + path: running-tasks/webhooks-faq.mdx - page: Advanced Settings for tasks path: running-tasks/advanced-features.mdx + - page: Legacy Task APIs + path: running-tasks/api-spec.mdx - section: Workflows contents: - page: Introduction @@ -103,11 +105,15 @@ navigation: - page: Password Management path: credentials/passwords.mdx - page: Credit Card Management - path: credentials/credit_cards.mdx + path: credentials/credit-cards.mdx - page: TOTP (2FA/MFA/Verification Code) path: credentials/totp.mdx - page: Bitwarden path: credentials/bitwarden.mdx + - section: Browser Sessions (Beta) + contents: + - page: Introduction + path: browser-sessions/introduction.mdx - section: Integrations contents: - page: Skyvern MCP diff --git a/fern/fern.config.json b/fern/fern.config.json index bd91a3d3..71948d36 100644 --- a/fern/fern.config.json +++ b/fern/fern.config.json @@ -1,4 +1,4 @@ { "organization": "skyvern", - "version": "0.57.15" + "version": "0.63.6" } \ No newline at end of file diff --git a/fern/getting-started/quickstart.mdx b/fern/getting-started/quickstart.mdx index 8eec7a81..aeb25ffe 100644 --- a/fern/getting-started/quickstart.mdx +++ b/fern/getting-started/quickstart.mdx @@ -6,7 +6,7 @@ slug: getting-started/quickstart ## Skyvern Cloud Sign up on https://app.skyvern.com/ to get $5 free credits. -Ask the Skyvern agent to run a task and see it in action live! Here are some examples you can try: +Ask the Skyvern agent to run a task and see it in action! Here are some examples you can try: - `Navigate to the Hacker News homepage and get the top 3 posts.` - `Go to google finance and find the "AAPL" stock price. COMPLETE when the search results for "AAPL" are displayed and the stock price is extracted.` @@ -40,7 +40,7 @@ More API & SDK information can be found in the [API Reference](/api-reference) s ### Run Task Locally You can also run browser tasks locally in your python code but it takes a bit more effort to set up the environment: -1. **Configure Skyvern** Run the setup wizard which will guide you through the configuration process, including Skyvern [MCP](https://github.com/Skyvern-AI/skyvern/blob/main/integrations/mcp/README.md) integration. This will generate a `.env` as the configuration settings file. +1. **Configure Skyvern** Run the setup wizard which will guide you through the configuration process, including Skyvern [MCP](/integrations/mcp) integration. This will generate a `.env` as the configuration settings file. ```bash skyvern init ``` diff --git a/fern/images/run_tasks/ui_run_task.png b/fern/images/run_tasks/ui_run_task.png new file mode 100644 index 00000000..023e7bef Binary files /dev/null and b/fern/images/run_tasks/ui_run_task.png differ diff --git a/fern/openapi/skyvern_openapi.json b/fern/openapi/skyvern_openapi.json index e3780088..d718dfbe 100644 --- a/fern/openapi/skyvern_openapi.json +++ b/fern/openapi/skyvern_openapi.json @@ -463,6 +463,134 @@ ] } ] + }, + "get": { + "tags": [ + "Workflows" + ], + "summary": "Get Workflows", + "description": "Get all workflows with the latest version for the organization.", + "operationId": "get_workflows_v1_workflows_get", + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "default": 1, + "title": "Page" + } + }, + { + "name": "page_size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "default": 10, + "title": "Page Size" + } + }, + { + "name": "only_saved_tasks", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false, + "title": "Only Saved Tasks" + } + }, + { + "name": "only_workflows", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false, + "title": "Only Workflows" + } + }, + { + "name": "title", + "in": "query", + "required": false, + "schema": { + "type": "string", + "default": "", + "title": "Title" + } + }, + { + "name": "template", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false, + "title": "Template" + } + }, + { + "name": "x-api-key", + "in": "header", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "API key for authentication", + "title": "X-Api-Key" + }, + "description": "API key for authentication" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Workflow" + }, + "title": "Response Get Workflows V1 Workflows Get" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "x-fern-sdk-group-name": "workflows", + "x-fern-sdk-method-name": "get_workflows", + "x-fern-examples": [ + { + "code-samples": [ + { + "sdk": "python", + "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nworkflows = await skyvern.workflows.get_workflows()\nprint(workflows)\n" + } + ] + } + ] } }, "/v1/workflows/{workflow_id}": { @@ -628,6 +756,151 @@ ] } }, + "/v1/artifacts/{artifact_id}": { + "get": { + "tags": [ + "Artifacts" + ], + "summary": "Get an artifact", + "description": "Get an artifact", + "operationId": "get_artifact_v1_artifacts__artifact_id__get", + "parameters": [ + { + "name": "artifact_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Artifact Id" + } + }, + { + "name": "x-api-key", + "in": "header", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "API key for authentication", + "title": "X-Api-Key" + }, + "description": "API key for authentication" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved artifact", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Artifact" + } + } + } + }, + "404": { + "description": "Artifact not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "x-fern-sdk-group-name": "artifacts", + "x-fern-sdk-method-name": "get_artifact" + } + }, + "/v1/runs/{run_id}/retry_webhook": { + "post": { + "tags": [ + "Agent" + ], + "summary": "Retry run webhook", + "description": "Retry sending the webhook for a run", + "operationId": "retry_run_webhook_v1_runs__run_id__retry_webhook_post", + "parameters": [ + { + "name": "run_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "description": "The id of the task run or the workflow run.", + "examples": [ + "tsk_123", + "wr_123" + ], + "title": "Run Id" + }, + "description": "The id of the task run or the workflow run." + }, + { + "name": "x-api-key", + "in": "header", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "API key for authentication", + "title": "X-Api-Key" + }, + "description": "API key for authentication" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "x-fern-sdk-group-name": "agent", + "x-fern-sdk-method-name": "retry_run_webhook", + "x-fern-examples": [ + { + "code-samples": [ + { + "sdk": "python", + "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nawait skyvern.agent.retry_run_webhook(run_id=\"tsk_v2_123\")\n" + } + ] + } + ] + } + }, "/v1/browser_sessions": { "post": { "tags": [ @@ -1823,6 +2096,176 @@ ], "title": "ActionBlockYAML" }, + "Artifact": { + "properties": { + "created_at": { + "type": "string", + "title": "Created At", + "description": "The creation datetime of the task.", + "examples": [ + "2023-01-01T00:00:00Z" + ] + }, + "modified_at": { + "type": "string", + "title": "Modified At", + "description": "The modification datetime of the task.", + "examples": [ + "2023-01-01T00:00:00Z" + ] + }, + "artifact_id": { + "type": "string", + "title": "Artifact Id" + }, + "artifact_type": { + "$ref": "#/components/schemas/ArtifactType" + }, + "uri": { + "type": "string", + "title": "Uri" + }, + "task_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Task Id" + }, + "step_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Step Id" + }, + "workflow_run_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Workflow Run Id" + }, + "workflow_run_block_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Workflow Run Block Id" + }, + "observer_cruise_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observer Cruise Id" + }, + "observer_thought_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observer Thought Id" + }, + "ai_suggestion_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ai Suggestion Id" + }, + "signed_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Signed Url" + }, + "organization_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Organization Id" + } + }, + "type": "object", + "required": [ + "created_at", + "modified_at", + "artifact_id", + "artifact_type", + "uri" + ], + "title": "Artifact" + }, + "ArtifactType": { + "type": "string", + "enum": [ + "recording", + "browser_console_log", + "skyvern_log", + "skyvern_log_raw", + "screenshot", + "screenshot_llm", + "screenshot_action", + "screenshot_final", + "llm_prompt", + "llm_request", + "llm_response", + "llm_response_parsed", + "llm_response_rendered", + "visible_elements_id_css_map", + "visible_elements_id_frame_map", + "visible_elements_tree", + "visible_elements_tree_trimmed", + "visible_elements_tree_in_prompt", + "hashed_href_map", + "visible_elements_id_xpath_map", + "html", + "html_scrape", + "html_action", + "trace", + "har" + ], + "title": "ArtifactType" + }, "BitwardenCreditCardDataParameter": { "properties": { "parameter_type": { diff --git a/fern/running-tasks/advanced-features.mdx b/fern/running-tasks/advanced-features.mdx index 29e98e34..04fb18c4 100644 --- a/fern/running-tasks/advanced-features.mdx +++ b/fern/running-tasks/advanced-features.mdx @@ -3,7 +3,7 @@ title: Advanced Settings for tasks subtitle: How to use advanced settings for tasks slug: running-tasks/advanced-features --- - + DEPRECATION ALERT: the content in this page including endpoints mentioned here is being deprecated. Last supported date: Jan 1, 2026. If you're looking for TOTP (2FA/MFA) information, move to the new [TOTP](/credentials/totp) page. ## Overriding the max_steps paramter in the task If you want the task to execute for a specific number of steps, you can use the `x-max-steps-override` header in the request. This will override the default `max_steps` parameter set in the task. diff --git a/fern/running-tasks/api-spec.mdx b/fern/running-tasks/api-spec.mdx index a3c8b9f2..65a04572 100644 --- a/fern/running-tasks/api-spec.mdx +++ b/fern/running-tasks/api-spec.mdx @@ -1,10 +1,14 @@ --- -title: Tasks API +title: Legacy Task APIs subtitle: The core building block in Skyvern slug: running-tasks/api-spec --- -Tasks are the building block of Skyvern. They represent a single instruction (goal) to the browser to go do something using language models. Ex. "Go to alibaba and extract this information" + +DEPRECATION ALERT: the APIs in this page are being deprecated. Last supported date: Jan 1, 2026. Please use the [Run Task](/running-tasks/run-tasks) API and migrated to the new API. + + +Tasks are the building block of Skyvern. They represent a single instruction (goal) to the browser to go do something using language models. Ex. "Search for Skyvern on googgle.com and summarize the information about Skyvern." ## Request - Initiate a task Request type: `POST` diff --git a/fern/running-tasks/run-tasks.mdx b/fern/running-tasks/run-tasks.mdx new file mode 100644 index 00000000..8e68bce9 --- /dev/null +++ b/fern/running-tasks/run-tasks.mdx @@ -0,0 +1,85 @@ +--- +title: Task Features +slug: running-tasks/run-tasks +--- + +## Run A Task +- See the [Quickstart](/getting-started/quickstart) to run a simple task. +- See the [Run Task API and SDK](/api-reference/api-reference/agent/run-task). + +There are many features to help automate and improve your task experience. Check out the features along with its parameter name below. + +All the features are enabled through API & SDK. Some features are enabled through [Skyvern's Discover page](https://app.skyvern.com/discover) as well. + +Configure advanced settings in the UI + + +### [Engine](/api-reference/api-reference/agent/run-task#request.body.engine) + +Parameter: `engine` + +This parameter defines the engine that powers the agent task. + +- `skyvern-2.0`: this is the default engine. It's the latest Skyvern agent that performs really well with complex and multi-step tasks. It scores **state of the art** 85.85% on the [WebVoyager benchmark](https://blog.skyvern.com/skyvern-2-0-state-of-the-art-web-navigation-with-85-8-on-webvoyager-eval/). +- `skyvern-1.0`: performs really well for tasks with a simple goal, like filling a form, or searching for information on Google. +- `openai-cua`: uses OpenAI's CUA model. +- `anthropic-cua`: uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. + + +### [Data Extraction Schema](/api-reference/api-reference/agent/run-task#request.body.data_extraction_schema) + +Parameter: `data_extraction_schema` + +The schema for data to be extracted from the webpage. If you're looking for consistent data schema being returned by the agent, it's highly recommended to use https://json-schema.org/. + +### [Send Webhook](/api-reference/api-reference/agent/run-task#request.body.webhook_url) + +Parameter: `webhook_url` + +You can set the `webhook_url` to receive the update when the task is done. Check [Webhooks FAQ](/running-tasks/webhooks-faq) for more details. + +### [Max Steps](/api-reference/api-reference/agent/run-task#request.body.max_steps) + +Parameter: `max_steps` + +Maximum number of steps the task can take. Task will fail if it exceeds this number. Cautions: you are charged per step so please set this number to a reasonable value. Contact sales@skyvern.com for custom pricing. + +### [Error Code Mapping](/api-reference/api-reference/agent/run-task#request.body.error_code_mapping) + +Parameter: `error_code_mapping` + +Custom mapping of error codes to error messages if Skyvern encounters an error. + +For example: +```json +[ + {"login_failed": "The login credentials are incorrect or the account is locked"}, + {"maintenance_mode": "The website is down for maintenance"}, +] +``` +With this mapping, if Skyvern encounters a login failure, the task output will show `{"error": "login_failed"}`, which makes it easy to codify error handling. + +### [Proxy Location](/api-reference/api-reference/agent/run-task#request.body.proxy_location) + +Parameter: `proxy_location` + +Some websites block requests from certain countries. You can set a proxy location to route the browser traffic through. + +### TOTP (2FA/MFA/Verification) Code +- [totp_identifier](/api-reference/api-reference/agent/run-task#request.body.totp_identifier): Skyvern can receive the TOTP code and use this identifier to identify the code for authentication. +- [totp_url](/api-reference/api-reference/agent/run-task#request.body.totp_url): Skyvern makes a request to this URL to fetch the TOTP code when needed. + +More details can be found in the [TOTP section](/credentials/totp). + +### [Run Task in a Persistent Browser Session](/api-reference/api-reference/agent/run-task#request.body.browser_session_id) (`browser_session_id`) +You can set a browser session to use for the task. Having a browser session can persist the real-time state of the browser, so that the next run can continue from where the previous run left off. + +See the [Browser Sessions](/browser-sessions/introduction) section to see how to create a browser session. + +## View A Task +Skyvern has a rich feature for you to understand what's happening with your task. See [Visualizing Results](/running-tasks/visualizing-results). + +The [GET Run](/api-reference/api-reference/agent/get-run) endpoint shows the status of the task. + +## Cancel A Task +A task that has not started or is in the running state can be cancelled through the UI. It can also be done with the [Cancel Run](/api-reference/api-reference/agent/cancel-run) endpoint. \ No newline at end of file diff --git a/fern/running-tasks/webhooks-faq.mdx b/fern/running-tasks/webhooks-faq.mdx index 48dedab2..6e3a2586 100644 --- a/fern/running-tasks/webhooks-faq.mdx +++ b/fern/running-tasks/webhooks-faq.mdx @@ -3,12 +3,40 @@ title: Webhooks FAQ subtitle: How Skyvern notifies you when its done slug: running-tasks/webhooks-faq --- - - -# 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) +Expected runtime of Skyvern's tasks and workflows can exceed default HTTP timeouts (1 minute). So we recommend using receiving webhook notifications you when it's done. + +To set up webhook callback: +- Set [webhook_url in Run Task](api-reference/api-reference/agent/run-task#request.body.webhook_url) to receive the update when the task is done. +- Set [webhook_url in Run Workflow](https://docs.skyvern.com/api-reference/api-reference/agent/run-workflow#request.body.webhook_url) to receive the update when a workflow run is done. + +To fetch the status of a run: +- Use the [Get Run](/api-reference/api-reference/agent/get-run) endpoint for the status of a task or workflow run + +## Webhook payload schema + +The webhook request body is a JSON object with the following fields: +```json +{ + "run_id": "The ID of the task or the workflow run. For examples: tsk_123, tsk_v2_123, wr_123", + "run_type": "The type of the run. Examples: task_v1, task_v2, workflow_run, openai_cua, anthropic_cua.", + "status": "The status of the run", + "output": "The output of the run", + "downloaded_files": "A list of download file objects", + "recording_url": "The URL of the recording", + "screenshot_urls": "URLs of the last three screenshots. The first one in the list is the latest screenshot.", + "failure_reason": "The reason for the failure if any", + "app_url": "The URL to the run in the Skyvern app", + "created_at": "The timestamp when the run was created", + "modified_at": "The timestamp when the run was last modified", +} +``` +For detailed schema, please refer to the [Run Response](/api-reference/api-reference/agent/get-run#response). + +Notes: +- The webhook payload won't contain the `run_request` field as the [Run Response](/api-reference/api-reference/agent/get-run#response) does. +- There are legacy fields in the actual payload for backward compatibility, which are not listed here and will be removed in the future. Please use the fields above. ## How do we handle webhook authentication? (ie how can we handle callbacks?) @@ -40,10 +68,6 @@ function validateSkyvernRequestHeaders(req) { -SKYVERN_API_KEY: this is the [api key](/running-tasks/introduction) specific to your organization +## Can I Replay Webhook? -# Webhook common parameters - -| Parameter | Type | Required? | Sample Value | Description | -| --- | --- | --- | --- | --- | -| webhook_callback_url | String | yes | … | | +Yes, you can replay a webhook by using the [Retry Webhook](/api-reference/api-reference/agent/retry-webhook) endpoint. \ No newline at end of file diff --git a/skyvern/client/__init__.py b/skyvern/client/__init__.py index c8b48727..aa820e57 100644 --- a/skyvern/client/__init__.py +++ b/skyvern/client/__init__.py @@ -13,6 +13,8 @@ from .types import ( ActionBlockParametersItem_Output, ActionBlockParametersItem_Workflow, ActionBlockYaml, + Artifact, + ArtifactType, AwsSecretParameter, AwsSecretParameterYaml, BitwardenCreditCardDataParameter, @@ -317,7 +319,7 @@ from .types import ( WorkflowStatus, ) from .errors import BadRequestError, ForbiddenError, NotFoundError, UnprocessableEntityError -from . import agent, browser_session, credentials, workflows +from . import agent, artifacts, browser_session, credentials, workflows from .agent import ( AgentGetRunResponse, AgentGetRunResponse_AnthropicCua, @@ -350,6 +352,8 @@ __all__ = [ "AgentGetRunResponse_TaskV1", "AgentGetRunResponse_TaskV2", "AgentGetRunResponse_WorkflowRun", + "Artifact", + "ArtifactType", "AsyncSkyvern", "AwsSecretParameter", "AwsSecretParameterYaml", @@ -662,6 +666,7 @@ __all__ = [ "WorkflowStatus", "__version__", "agent", + "artifacts", "browser_session", "credentials", "workflows", diff --git a/skyvern/client/agent/client.py b/skyvern/client/agent/client.py index 96c8ab53..a6b6f6a8 100644 --- a/skyvern/client/agent/client.py +++ b/skyvern/client/agent/client.py @@ -429,6 +429,65 @@ class AgentClient: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def retry_run_webhook( + self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Optional[typing.Any]: + """ + Retry sending the webhook for a run + + Parameters + ---------- + run_id : str + The id of the task run or the workflow run. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[typing.Any] + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.agent.retry_run_webhook( + run_id="tsk_123", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/runs/{jsonable_encoder(run_id)}/retry_webhook", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + class AsyncAgentClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): @@ -869,3 +928,70 @@ class AsyncAgentClient: except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + + async def retry_run_webhook( + self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Optional[typing.Any]: + """ + Retry sending the webhook for a run + + Parameters + ---------- + run_id : str + The id of the task run or the workflow run. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[typing.Any] + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.agent.retry_run_webhook( + run_id="tsk_123", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/runs/{jsonable_encoder(run_id)}/retry_webhook", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/skyvern/client/client.py b/skyvern/client/client.py index dc13ffb9..87c3f256 100644 --- a/skyvern/client/client.py +++ b/skyvern/client/client.py @@ -6,11 +6,13 @@ import httpx from .core.client_wrapper import SyncClientWrapper from .agent.client import AgentClient from .workflows.client import WorkflowsClient +from .artifacts.client import ArtifactsClient from .browser_session.client import BrowserSessionClient from .credentials.client import CredentialsClient from .core.client_wrapper import AsyncClientWrapper from .agent.client import AsyncAgentClient from .workflows.client import AsyncWorkflowsClient +from .artifacts.client import AsyncArtifactsClient from .browser_session.client import AsyncBrowserSessionClient from .credentials.client import AsyncCredentialsClient @@ -75,6 +77,7 @@ class Skyvern: ) self.agent = AgentClient(client_wrapper=self._client_wrapper) self.workflows = WorkflowsClient(client_wrapper=self._client_wrapper) + self.artifacts = ArtifactsClient(client_wrapper=self._client_wrapper) self.browser_session = BrowserSessionClient(client_wrapper=self._client_wrapper) self.credentials = CredentialsClient(client_wrapper=self._client_wrapper) @@ -139,6 +142,7 @@ class AsyncSkyvern: ) self.agent = AsyncAgentClient(client_wrapper=self._client_wrapper) self.workflows = AsyncWorkflowsClient(client_wrapper=self._client_wrapper) + self.artifacts = AsyncArtifactsClient(client_wrapper=self._client_wrapper) self.browser_session = AsyncBrowserSessionClient(client_wrapper=self._client_wrapper) self.credentials = AsyncCredentialsClient(client_wrapper=self._client_wrapper) diff --git a/skyvern/client/core/client_wrapper.py b/skyvern/client/core/client_wrapper.py index 76d052a3..b26c6416 100644 --- a/skyvern/client/core/client_wrapper.py +++ b/skyvern/client/core/client_wrapper.py @@ -16,7 +16,7 @@ class BaseClientWrapper: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "skyvern", - "X-Fern-SDK-Version": "0.1.85", + "X-Fern-SDK-Version": "0.1.86", } if self._api_key is not None: headers["x-api-key"] = self._api_key diff --git a/skyvern/client/types/__init__.py b/skyvern/client/types/__init__.py index c6ef0a21..b03a1c51 100644 --- a/skyvern/client/types/__init__.py +++ b/skyvern/client/types/__init__.py @@ -14,6 +14,8 @@ from .action_block_parameters_item import ( ActionBlockParametersItem_Workflow, ) from .action_block_yaml import ActionBlockYaml +from .artifact import Artifact +from .artifact_type import ArtifactType from .aws_secret_parameter import AwsSecretParameter from .aws_secret_parameter_yaml import AwsSecretParameterYaml from .bitwarden_credit_card_data_parameter import BitwardenCreditCardDataParameter @@ -366,6 +368,8 @@ __all__ = [ "ActionBlockParametersItem_Output", "ActionBlockParametersItem_Workflow", "ActionBlockYaml", + "Artifact", + "ArtifactType", "AwsSecretParameter", "AwsSecretParameterYaml", "BitwardenCreditCardDataParameter", diff --git a/skyvern/client/types/artifact.py b/skyvern/client/types/artifact.py new file mode 100644 index 00000000..1821664a --- /dev/null +++ b/skyvern/client/types/artifact.py @@ -0,0 +1,41 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from .artifact_type import ArtifactType +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Artifact(UniversalBaseModel): + created_at: str = pydantic.Field() + """ + The creation datetime of the task. + """ + + modified_at: str = pydantic.Field() + """ + The modification datetime of the task. + """ + + artifact_id: str + artifact_type: ArtifactType + uri: str + task_id: typing.Optional[str] = None + step_id: typing.Optional[str] = None + workflow_run_id: typing.Optional[str] = None + workflow_run_block_id: typing.Optional[str] = None + observer_cruise_id: typing.Optional[str] = None + observer_thought_id: typing.Optional[str] = None + ai_suggestion_id: typing.Optional[str] = None + signed_url: typing.Optional[str] = None + organization_id: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/skyvern/client/types/artifact_type.py b/skyvern/client/types/artifact_type.py new file mode 100644 index 00000000..97faa4a5 --- /dev/null +++ b/skyvern/client/types/artifact_type.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ArtifactType = typing.Union[ + typing.Literal[ + "recording", + "browser_console_log", + "skyvern_log", + "skyvern_log_raw", + "screenshot", + "screenshot_llm", + "screenshot_action", + "screenshot_final", + "llm_prompt", + "llm_request", + "llm_response", + "llm_response_parsed", + "llm_response_rendered", + "visible_elements_id_css_map", + "visible_elements_id_frame_map", + "visible_elements_tree", + "visible_elements_tree_trimmed", + "visible_elements_tree_in_prompt", + "hashed_href_map", + "visible_elements_id_xpath_map", + "html", + "html_scrape", + "html_action", + "trace", + "har", + ], + typing.Any, +] diff --git a/skyvern/client/workflows/client.py b/skyvern/client/workflows/client.py index b3f7be8b..91ce4162 100644 --- a/skyvern/client/workflows/client.py +++ b/skyvern/client/workflows/client.py @@ -2,14 +2,14 @@ import typing from ..core.client_wrapper import SyncClientWrapper -from ..types.workflow_create_yaml_request import WorkflowCreateYamlRequest from ..core.request_options import RequestOptions from ..types.workflow import Workflow -from ..core.serialization import convert_and_respect_annotation_metadata from ..core.pydantic_utilities import parse_obj_as from ..errors.unprocessable_entity_error import UnprocessableEntityError from json.decoder import JSONDecodeError from ..core.api_error import ApiError +from ..types.workflow_create_yaml_request import WorkflowCreateYamlRequest +from ..core.serialization import convert_and_respect_annotation_metadata from ..core.jsonable_encoder import jsonable_encoder from ..core.client_wrapper import AsyncClientWrapper @@ -21,6 +21,88 @@ class WorkflowsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper + def get_workflows( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + only_saved_tasks: typing.Optional[bool] = None, + only_workflows: typing.Optional[bool] = None, + title: typing.Optional[str] = None, + template: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[Workflow]: + """ + Get all workflows with the latest version for the organization. + + Parameters + ---------- + page : typing.Optional[int] + + page_size : typing.Optional[int] + + only_saved_tasks : typing.Optional[bool] + + only_workflows : typing.Optional[bool] + + title : typing.Optional[str] + + template : typing.Optional[bool] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[Workflow] + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.workflows.get_workflows() + """ + _response = self._client_wrapper.httpx_client.request( + "v1/workflows", + method="GET", + params={ + "page": page, + "page_size": page_size, + "only_saved_tasks": only_saved_tasks, + "only_workflows": only_workflows, + "title": title, + "template": template, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[Workflow], + parse_obj_as( + type_=typing.List[Workflow], # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + def create_workflow( self, *, @@ -233,6 +315,96 @@ class AsyncWorkflowsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper + async def get_workflows( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + only_saved_tasks: typing.Optional[bool] = None, + only_workflows: typing.Optional[bool] = None, + title: typing.Optional[str] = None, + template: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[Workflow]: + """ + Get all workflows with the latest version for the organization. + + Parameters + ---------- + page : typing.Optional[int] + + page_size : typing.Optional[int] + + only_saved_tasks : typing.Optional[bool] + + only_workflows : typing.Optional[bool] + + title : typing.Optional[str] + + template : typing.Optional[bool] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[Workflow] + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.workflows.get_workflows() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/workflows", + method="GET", + params={ + "page": page, + "page_size": page_size, + "only_saved_tasks": only_saved_tasks, + "only_workflows": only_workflows, + "title": title, + "template": template, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[Workflow], + parse_obj_as( + type_=typing.List[Workflow], # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + async def create_workflow( self, *, diff --git a/skyvern/forge/sdk/schemas/tasks.py b/skyvern/forge/sdk/schemas/tasks.py index 23209202..c0254f43 100644 --- a/skyvern/forge/sdk/schemas/tasks.py +++ b/skyvern/forge/sdk/schemas/tasks.py @@ -16,6 +16,7 @@ from skyvern.exceptions import ( ) from skyvern.forge.sdk.db.enums import TaskType from skyvern.forge.sdk.schemas.files import FileInfo +from skyvern.schemas.docs.doc_strings import PROXY_LOCATION_DOC_STRING from skyvern.schemas.runs import ProxyLocation from skyvern.utils.url_validators import validate_url @@ -65,8 +66,7 @@ class TaskBase(BaseModel): ) proxy_location: ProxyLocation | None = Field( default=None, - description="The location of the proxy to use for the task.", - examples=["US-WA", "US-CA", "US-FL", "US-NY", "US-TX"], + description=PROXY_LOCATION_DOC_STRING, ) extracted_information_schema: dict[str, Any] | list | str | None = Field( default=None, diff --git a/skyvern/forge/sdk/services/org_auth_service.py b/skyvern/forge/sdk/services/org_auth_service.py index cf4bd28f..f5431dcf 100644 --- a/skyvern/forge/sdk/services/org_auth_service.py +++ b/skyvern/forge/sdk/services/org_auth_service.py @@ -24,7 +24,12 @@ ALGORITHM = "HS256" async def get_current_org( - x_api_key: Annotated[str | None, Header(description="API key for authentication")] = None, + x_api_key: Annotated[ + str | None, + Header( + description="Skyvern API key for authentication. API key can be found at https://app.skyvern.com/settings." + ), + ] = None, authorization: Annotated[str | None, Header(include_in_schema=False)] = None, ) -> Organization: if not x_api_key and not authorization: diff --git a/skyvern/library/skyvern.py b/skyvern/library/skyvern.py index 1fee0641..5559e3de 100644 --- a/skyvern/library/skyvern.py +++ b/skyvern/library/skyvern.py @@ -325,7 +325,7 @@ class Skyvern(AsyncSkyvern): data_extraction_schema = data_extraction_schema or task_generation.extracted_information_schema task_request = TaskRequest( - title=title, + title=title or task_generation.suggested_title, url=url, navigation_goal=navigation_goal, navigation_payload=navigation_payload, diff --git a/skyvern/schemas/docs/__init__.py b/skyvern/schemas/docs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/skyvern/schemas/docs/doc_examples.py b/skyvern/schemas/docs/doc_examples.py new file mode 100644 index 00000000..c15fd16f --- /dev/null +++ b/skyvern/schemas/docs/doc_examples.py @@ -0,0 +1,28 @@ +TASK_PROMPT_EXAMPLES = [ + "Find the top 3 posts on Hacker News.", + 'Go to google finance, extract the "AAPL" stock price for me with the date.', +] + +TASK_URL_EXAMPLES = [ + "https://www.hackernews.com", + "https://www.google.com/finance", +] + +ERROR_CODE_MAPPING_EXAMPLES = [ + {"login_failed": "The login credentials are incorrect or the account is locked"}, + {"maintenance_mode": "The website is down for maintenance"}, +] + +TOTP_IDENTIFIER_EXAMPLES = [ + "john.doe@example.com", + "4155555555", + "user_123", +] + +TOTP_URL_EXAMPLES = [ + "https://my-totp-service.com/totp", +] + +BROWSER_SESSION_ID_EXAMPLES = [ + "pbs_123", +] diff --git a/skyvern/schemas/docs/doc_strings.py b/skyvern/schemas/docs/doc_strings.py new file mode 100644 index 00000000..64366c39 --- /dev/null +++ b/skyvern/schemas/docs/doc_strings.py @@ -0,0 +1,63 @@ +TASK_PROMPT_DOC_STRING = """ +The goal or task description for Skyvern to accomplish +""" + +TASK_URL_DOC_STRING = """ +The starting URL for the task. If not provided, Skyvern will attempt to determine an appropriate URL +""" + +TASK_ENGINE_DOC_STRING = """ +The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. +""" + +PROXY_LOCATION_DOC_STRING = """ +Geographic Proxy location to route the browser traffic through. This is only available in Skyvern Cloud. + +Available geotargeting options: +- RESIDENTIAL: the default value. Skyvern Cloud uses a random US residential proxy. +- RESIDENTIAL_ES: Spain +- RESIDENTIAL_IE: Ireland +- RESIDENTIAL_GB: United Kingdom +- RESIDENTIAL_IN: India +- RESIDENTIAL_JP: Japan +- RESIDENTIAL_FR: France +- RESIDENTIAL_DE: Germany +- RESIDENTIAL_NZ: New Zealand +- RESIDENTIAL_ZA: South Africa +- RESIDENTIAL_AR: Argentina +- RESIDENTIAL_ISP: ISP proxy +- US-CA: California +- US-NY: New York +- US-TX: Texas +- US-FL: Florida +- US-WA: Washington +- NONE: No proxy +""" + +DATA_EXTRACTION_SCHEMA_DOC_STRING = """ +The schema for data to be extracted from the webpage. If you're looking for consistent data schema being returned by the agent, it's highly recommended to use https://json-schema.org/. +""" + +ERROR_CODE_MAPPING_DOC_STRING = """ +Custom mapping of error codes to error messages if Skyvern encounters an error. +""" + +MAX_STEPS_DOC_STRING = """ +Maximum number of steps the task can take. Task will fail if it exceeds this number. Cautions: you are charged per step so please set this number to a reasonable value. Contact sales@skyvern.com for custom pricing. +""" + +WEBHOOK_URL_DOC_STRING = """ +URL to send task status updates to after a run is finished. Refer to https://docs.skyvern.com/running-tasks/webhooks-faq for more details. +""" + +TOTP_IDENTIFIER_DOC_STRING = """ +Identifier for the TOTP/2FA/MFA code when the code is pushed to Skyvern. Refer to https://docs.skyvern.com/credentials/totp#option-3-push-code-to-skyvern for more details. +""" + +TOTP_URL_DOC_STRING = """ +URL that serves TOTP/2FA/MFA codes for Skyvern to use during the workflow run. Refer to https://docs.skyvern.com/credentials/totp#option-2-get-code-from-your-endpoint for more details. +""" + +BROWSER_SESSION_ID_DOC_STRING = """ +Run the task or workflow in the specific Skyvern browser session. Having a browser session can persist the real-time state of the browser, so that the next run can continue from where the previous run left off. +""" diff --git a/skyvern/schemas/runs.py b/skyvern/schemas/runs.py index 62bbbcc2..987870d2 100644 --- a/skyvern/schemas/runs.py +++ b/skyvern/schemas/runs.py @@ -8,6 +8,27 @@ from zoneinfo import ZoneInfo from pydantic import BaseModel, Field, field_validator from skyvern.forge.sdk.schemas.files import FileInfo +from skyvern.schemas.docs.doc_examples import ( + BROWSER_SESSION_ID_EXAMPLES, + ERROR_CODE_MAPPING_EXAMPLES, + TASK_PROMPT_EXAMPLES, + TASK_URL_EXAMPLES, + TOTP_IDENTIFIER_EXAMPLES, + TOTP_URL_EXAMPLES, +) +from skyvern.schemas.docs.doc_strings import ( + BROWSER_SESSION_ID_DOC_STRING, + DATA_EXTRACTION_SCHEMA_DOC_STRING, + ERROR_CODE_MAPPING_DOC_STRING, + MAX_STEPS_DOC_STRING, + PROXY_LOCATION_DOC_STRING, + TASK_ENGINE_DOC_STRING, + TASK_PROMPT_DOC_STRING, + TASK_URL_DOC_STRING, + TOTP_IDENTIFIER_DOC_STRING, + TOTP_URL_DOC_STRING, + WEBHOOK_URL_DOC_STRING, +) from skyvern.utils.url_validators import validate_url @@ -188,42 +209,59 @@ class RunStatus(StrEnum): class TaskRunRequest(BaseModel): - prompt: str = Field(description="The goal or task description for Skyvern to accomplish") + prompt: str = Field( + description=TASK_PROMPT_DOC_STRING, + examples=TASK_PROMPT_EXAMPLES, + ) url: str | None = Field( default=None, - description="The starting URL for the task. If not provided, Skyvern will attempt to determine an appropriate URL", + description=TASK_URL_DOC_STRING, + examples=TASK_URL_EXAMPLES, ) engine: RunEngine = Field( default=RunEngine.skyvern_v2, - description="The Skyvern engine version to use for this task. The default value is skyvern-2.0.", + description=TASK_ENGINE_DOC_STRING, + ) + title: str | None = Field( + default=None, description="The title for the task", examples=["The title of my first skyvern task"] ) - title: str | None = Field(default=None, description="The title for the task") proxy_location: ProxyLocation | None = Field( - default=ProxyLocation.RESIDENTIAL, description="Geographic Proxy location to route the browser traffic through" + default=ProxyLocation.RESIDENTIAL, + description=PROXY_LOCATION_DOC_STRING, ) data_extraction_schema: dict | list | str | None = Field( - default=None, description="Schema defining what data should be extracted from the webpage" + default=None, + description=DATA_EXTRACTION_SCHEMA_DOC_STRING, ) error_code_mapping: dict[str, str] | None = Field( - default=None, description="Custom mapping of error codes to error messages if Skyvern encounters an error" + default=None, + description=ERROR_CODE_MAPPING_DOC_STRING, + examples=ERROR_CODE_MAPPING_EXAMPLES, ) max_steps: int | None = Field( - default=None, description="Maximum number of steps the task can take before timing out" + default=None, + description=MAX_STEPS_DOC_STRING, + examples=[10, 25], ) webhook_url: str | None = Field( - default=None, description="URL to send task status updates to after a run is finished" + default=None, + description=WEBHOOK_URL_DOC_STRING, + examples=["https://my-site.com/webhook"], ) totp_identifier: str | None = Field( default=None, - description="Identifier for TOTP (Time-based One-Time Password) authentication if codes are being pushed to Skyvern", + description=TOTP_IDENTIFIER_DOC_STRING, + examples=TOTP_IDENTIFIER_EXAMPLES, ) totp_url: str | None = Field( default=None, - description="URL for TOTP authentication setup if Skyvern should be polling endpoint for 2FA codes", + description=TOTP_URL_DOC_STRING, + examples=TOTP_URL_EXAMPLES, ) browser_session_id: str | None = Field( default=None, - description="ID of an existing browser session to reuse, having it continue from the current screen state", + description=BROWSER_SESSION_ID_DOC_STRING, + examples=BROWSER_SESSION_ID_EXAMPLES, ) publish_workflow: bool = Field( default=False, @@ -258,7 +296,8 @@ class WorkflowRunRequest(BaseModel): parameters: dict[str, Any] = Field(default={}, description="Parameters to pass to the workflow") title: str | None = Field(default=None, description="The title for this workflow run") proxy_location: ProxyLocation | None = Field( - default=ProxyLocation.RESIDENTIAL, description="Location of proxy to use for this workflow run" + default=ProxyLocation.RESIDENTIAL, + description=PROXY_LOCATION_DOC_STRING, ) webhook_url: str | None = Field( default=None, @@ -266,11 +305,13 @@ class WorkflowRunRequest(BaseModel): ) totp_url: str | None = Field( default=None, - description="URL that serves TOTP/2FA/MFA codes for Skyvern to use during the workflow run. Refer to https://docs.skyvern.com/running-tasks/advanced-features#get-code-from-your-endpoint", + description=TOTP_URL_DOC_STRING, + examples=TOTP_URL_EXAMPLES, ) totp_identifier: str | None = Field( default=None, - description="Identifier for the TOTP/2FA/MFA code when the code is pushed to Skyvern. Refer to https://docs.skyvern.com/running-tasks/advanced-features#time-based-one-time-password-totp", + description=TOTP_IDENTIFIER_DOC_STRING, + examples=TOTP_IDENTIFIER_EXAMPLES, ) browser_session_id: str | None = Field( default=None,