diff --git a/fern/docs.yml b/fern/docs.yml new file mode 100644 index 00000000..8301c1a1 --- /dev/null +++ b/fern/docs.yml @@ -0,0 +1,60 @@ +instances: + - url: https://skyvern.docs.buildwithfern.com +title: Skyvern +favicon: images/skyvern_favicon.png +logo: + light: images/skyvern_logo_blackbg.png + dark: images/skyvern_logo.png + height: 28 +colors: + accentPrimary: + dark: '#0D9373' + light: '#07C983' + background: + dark: '#000000' + light: '#FFFFFF' +navigation: + - section: Getting Started + contents: + - page: Introduction + path: introduction.mdx + - page: Skyvern In Action + path: getting-started/skyvern-in-action.mdx + - page: Task Prompting Guide + path: getting-started/prompting-guide.mdx + - section: Tasks + contents: + - page: Introduction + path: running-tasks/introduction.mdx + - page: Tasks API + path: running-tasks/api-spec.mdx + - page: Webhooks FAQ + path: running-tasks/webhooks-faq.mdx + - page: Visualizing Results + path: running-tasks/visualizing-results.mdx + - page: Advanced Settings for tasks + path: running-tasks/advanced-features.mdx + - section: Workflows (Beta) + contents: + - page: Introduction + path: workflows/introduction.mdx + - page: Creating Workflows + path: workflows/creating-workflows.mdx + - page: Getting Existing Workflows + path: workflows/getting-workflows.mdx + - page: Running Workflows + path: workflows/running-workflows.mdx + - page: Workflow Blocks + path: workflows/workflow-blocks.mdx + - page: What the heck is a parameter? + path: workflows/what-is-a-parameter.mdx + - section: Integrations + contents: + - page: API Integrations + path: integrations/api.mdx + - page: Zapier + path: integrations/zapier.mdx + - page: '' + path: integrations/make.com.mdx + - page: Workato + path: integrations/workato.mdx diff --git a/fern/fern.config.json b/fern/fern.config.json new file mode 100644 index 00000000..f459022e --- /dev/null +++ b/fern/fern.config.json @@ -0,0 +1,4 @@ +{ + "version": "0.47.2", + "organization": "skyverndocs" +} \ No newline at end of file diff --git a/fern/getting-started/prompting-guide.mdx b/fern/getting-started/prompting-guide.mdx new file mode 100644 index 00000000..69ddaec4 --- /dev/null +++ b/fern/getting-started/prompting-guide.mdx @@ -0,0 +1,90 @@ +--- +title: Task Prompting Guide +slug: getting-started/prompting-guide +--- + + +## TL;DR + +* Use key words “complete” or “terminate” to let Skyvern know when the task is done or should be ended, respectively + * Be specific when prompting, write as if you are talking to a seven year old. Verbosity is your friend. +* Ensure your problem is formatted as a single clearly defined goal with guardrails + * For instance, “generate an insurance quote” will be more successful than a sequence like “generate multiple insurance quotes and compare them to find the best option” +* Add guardrails like “close cookie dialogs” to instruct Skyvern when it encounters unexpected obstacles + * Some foreseeable obstacles include pop-ups, confirmations, cookie pop-ups, ad-banners, and more +* Give Skyvern concrete examples of what to do and not to do to. For example, asking it to navigate to the home page if it can't find it's looking for can be a good idea. + +## Step by Step + +A good 95% of the time, you can prevent a task failure before it even begins. Here are the steps to help optimize your run. + +### 1. Do you know what you’re trying to accomplish? + +Have a very clear idea of the problem you’re trying to have Skyvern solve. Ask yourself: + +What is the my goal? Can I describe it very clearly so Skyvern knows I've accomplished my goal? + +Does the site have anything that might derail Skyvern, like captchas, cookie dialogs, or pop-ups? + +Do you need to pre-load information or configure specific outputs or error messages? + +While some of these, like specifying how to act when encountering obstacles, are optional, goals and pre-loaded information are more critical. + +* Goal(s): if your task has multiple goals, Skyvern will not be able to complete it. +* Input(s): be clear about your inputs and give Skyvern instruction on what to do if it encounters required inputs it doesn’t have the answer to. If Skyvern sees inputs, it will try its best to accomplish its goal, which could mean it might make up information or make reasonable assumptions. + * You can ask Skyvern to make up information or terminate if asked anything it doesn’t have the answer to + * If you want to add concrete information about yourself, you have to provide that in advance in JSON (Navigation Payload) or natural language (Navigation Goal) formats + + +### 2. Can Skyvern accomplish your goal? + +Skyvern does some tasks very well, so part of this is knowing if your task fits within what Skyvern can do. + +What Skyvern does well: + +* Filling out long, monotonous forms +* Automating applications +* E-commerce procurement or analysis +* Downloading files + +What Skyvern doesn’t reliably execute: + +* Recursively scrape or iterate over multiple items +* Completing multiple goals in a sequence + * However, our newest Workflows feature will allow you to accommodate that. Please reach out to us (https://meetings.hubspot.com/skyvern/demo) if you'd like to learn more! + +### 3. Is your prompt well-written? + +Skyvern needs specific direction. The difference between a task completing and failing could be one word adding a little bit of clarity. Here is detailed information about each input type and what it requires. + +**What makes for a good prompt?** + +1. *(required) URL:* Skyvern's starting point +1. *(often required) Navigation Goal:* details where Skyvern is going and what Skyvern is doing. Clear Navigation Goals will be a single goal, broken down into steps. You need to specify when the goal is complete, using “COMPLETE”, or when to abandon that goal, using “TERMINATE” + * The navigation goal is not used to load the URL. Asking Skyvern to "go to website A" in this field will not have the intended effect + * Terminations result in Skyvern explaining why it stopped navigating + * This field can be omitted if you only want Skyvern to extract data +1. *(optional) Data Extraction Goal:* aside from where Skyvern is going and what Skyvern is doing, is there anything that Skyvern is extracting and returning back? A good data extraction goal is specific about what Skyvern is returning to the user + * Note that data extractions only happen AFTER Skyvern is finished navigating +1. *(optional) Navigation Payload:* if you need any content inputted during your task flow, that content goes here in JSON format + * If you want to run the same task for different users (i.e. filling out the same form multiple times), you should keep everything else the same and update the Navigation Payload +1. *(optional) Extracted Information Schema:* if you have a data extraction goal, some users need it formatted in a certain way for internal purposes. Navigation payload accepts JSON formatted specifications for how the data should be returned +1. *(optional) Webhook Callback URL:* This URL can be specified if you would like Skyvern to notify you when it's finished executing +1. *(optional) Max Steps:* some users want to cap cost through the number of steps the task can take + +## Prompt Examples + +**Good Navigation Goals** + +* Search for 'black waterproof mascara' in the search bar. Sort the results by popularity. Identify the first product in the sorted list. COMPLETE when the name and details of the most popular waterproof mascara are identified. +* Navigate to this YouTube channel and watch ChannelNameHere’s latest videos. Summarize the content of these videos. COMPLETE when summaries of the latest 5 videos are obtained. Guardrails: Do not interact with any other content or profiles. +* Fill out the job application form with the provided details. COMPLETE when the application form is successfully submitted. TERMINATE if the job form requires a cover letter. TERMINATE if there are any required questions that ask me to write a personalized paragraph. Guardrails: Do not apply to jobs that require relocation outside of Austin, TX. Do not respond to any optional questions. + +**Poor Navigation Goals** + +* Visit every URL on this page, analyze its content, and return a summary. COMPLETE when every summary is returned. TERMINATE if you are unable to access a link. + * “Do this, then this, then this” requires iterations, which is not supported by Skyvern tasks +* Download meeting transcripts and then generate a meeting summary for each. Then send out each summary to the attendees that were at each meeting. Make sure the summary goes to the right recipients. COMPLETE when you have sent the emails. TERMINATE if you are unable to download any transcripts. + * This is another iteration example, and we do not offer sending emails in our tasks feature right now +* Generate a home insurance quote. Do not generate an auto insurance quote. + * This example does not have completion parameters to tell Skyvern when it has achieved its goal diff --git a/fern/getting-started/skyvern-in-action.mdx b/fern/getting-started/skyvern-in-action.mdx new file mode 100644 index 00000000..af97f0b5 --- /dev/null +++ b/fern/getting-started/skyvern-in-action.mdx @@ -0,0 +1,55 @@ +--- +title: Skyvern In Action +subtitle: Examples of Skyvern running in production +slug: getting-started/skyvern-in-action +--- + + +## Automatically apply to jobs on sites like Lever.co +Skyvern can be instructed to navigate to job application websites like Lever.co and automatically generate answers, fill out and submit the job application. + +[💡 See it for yourself](https://app.skyvern.com/create/job_application) + +

+ Skyvern applying to a demo job on lever.co +

+ +## Automate transactions on e-commerce websites +Skyvern can be instructed to navigate to e-commerce websites, search for products, and add them to cart. Skyvern can even purchase the underlying items! + +[💡 See it for yourself](https://app.skyvern.com/create/finditparts) + +

+ Skyvern adding products to cart on finditparts.com +

+ +## Navigating to government websites to register accounts or fill out forms +Skyvern can navigate complex and boring government forms and fill them out with given information. It's especially powerful because the forms can change their layouts, and Skyvern will continue filling them out correctly. + +[💡 See it for yourself](https://app.skyvern.com/create/california_edd) +``` +./run_ui.sh california_edd +``` +

+ +

+ +## Retrieving insurance quotes from insurance providers in any language +Skyvern can navigate complex multi-part forms and fill out forms in any language + +[💡 See it for yourself](https://app.skyvern.com/create/geico) +

+ +

+ +[💡 See it for yourself](https://app.skyvern.com/create/bci_seguros) +

+ +

+ +## Log into a portal and download invoices +Skyvern can log into a website, navigate until it finds a page with invoices, and download the invoices + +

+ +

\ No newline at end of file diff --git a/fern/images/Skyvern-diagram.excalidraw b/fern/images/Skyvern-diagram.excalidraw new file mode 100644 index 00000000..9bbd0bdc --- /dev/null +++ b/fern/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/fern/images/api_key_image.png b/fern/images/api_key_image.png new file mode 100644 index 00000000..b512bee8 Binary files /dev/null and b/fern/images/api_key_image.png differ diff --git a/fern/images/bci_seguros_recording.gif b/fern/images/bci_seguros_recording.gif new file mode 100644 index 00000000..43c33d31 Binary files /dev/null and b/fern/images/bci_seguros_recording.gif differ diff --git a/fern/images/contact_forms.gif b/fern/images/contact_forms.gif new file mode 100644 index 00000000..202312f6 Binary files /dev/null and b/fern/images/contact_forms.gif differ diff --git a/fern/images/edd_services.gif b/fern/images/edd_services.gif new file mode 100644 index 00000000..e0fd192b Binary files /dev/null and b/fern/images/edd_services.gif differ diff --git a/fern/images/finditparts_recording_crop.gif b/fern/images/finditparts_recording_crop.gif new file mode 100644 index 00000000..c874f8e8 Binary files /dev/null and b/fern/images/finditparts_recording_crop.gif differ diff --git a/fern/images/geico_shu_recording_cropped.gif b/fern/images/geico_shu_recording_cropped.gif new file mode 100644 index 00000000..3d5617cb Binary files /dev/null and b/fern/images/geico_shu_recording_cropped.gif differ diff --git a/fern/images/invoice_downloading.gif b/fern/images/invoice_downloading.gif new file mode 100644 index 00000000..78732721 Binary files /dev/null and b/fern/images/invoice_downloading.gif differ diff --git a/fern/images/invoice_downloading_workflow_example.png b/fern/images/invoice_downloading_workflow_example.png new file mode 100644 index 00000000..41162917 Binary files /dev/null and b/fern/images/invoice_downloading_workflow_example.png differ diff --git a/fern/images/job_application_demo.gif b/fern/images/job_application_demo.gif new file mode 100644 index 00000000..6a7503d0 Binary files /dev/null and b/fern/images/job_application_demo.gif differ diff --git a/fern/images/secure_password_task_example.png b/fern/images/secure_password_task_example.png new file mode 100644 index 00000000..d7e5df1f Binary files /dev/null and b/fern/images/secure_password_task_example.png differ diff --git a/fern/images/skyvern-system-diagram-dark.png b/fern/images/skyvern-system-diagram-dark.png new file mode 100644 index 00000000..251a3e3b Binary files /dev/null and b/fern/images/skyvern-system-diagram-dark.png differ diff --git a/fern/images/skyvern-system-diagram-light.png b/fern/images/skyvern-system-diagram-light.png new file mode 100644 index 00000000..356d0d96 Binary files /dev/null and b/fern/images/skyvern-system-diagram-light.png differ diff --git a/fern/images/skyvern_demo_video_v2.1.mp4 b/fern/images/skyvern_demo_video_v2.1.mp4 new file mode 100644 index 00000000..fc5e65ab Binary files /dev/null and b/fern/images/skyvern_demo_video_v2.1.mp4 differ diff --git a/fern/images/skyvern_favicon.png b/fern/images/skyvern_favicon.png new file mode 100644 index 00000000..fe3d46ca Binary files /dev/null and b/fern/images/skyvern_favicon.png differ diff --git a/fern/images/skyvern_logo.png b/fern/images/skyvern_logo.png new file mode 100644 index 00000000..c93ed9c5 Binary files /dev/null and b/fern/images/skyvern_logo.png differ diff --git a/fern/images/skyvern_logo_blackbg.png b/fern/images/skyvern_logo_blackbg.png new file mode 100644 index 00000000..304a872a Binary files /dev/null and b/fern/images/skyvern_logo_blackbg.png differ diff --git a/fern/images/skyvern_visualizer_debug_action_screenshot.png b/fern/images/skyvern_visualizer_debug_action_screenshot.png new file mode 100644 index 00000000..88ae094d Binary files /dev/null and b/fern/images/skyvern_visualizer_debug_action_screenshot.png differ diff --git a/fern/images/skyvern_visualizer_debug_llm_response.png b/fern/images/skyvern_visualizer_debug_llm_response.png new file mode 100644 index 00000000..295e8d58 Binary files /dev/null and b/fern/images/skyvern_visualizer_debug_llm_response.png differ diff --git a/fern/images/skyvern_visualizer_run_task.png b/fern/images/skyvern_visualizer_run_task.png new file mode 100644 index 00000000..27f16cf1 Binary files /dev/null and b/fern/images/skyvern_visualizer_run_task.png differ diff --git a/fern/images/task_creation_form_example.png b/fern/images/task_creation_form_example.png new file mode 100644 index 00000000..f8e49fbd Binary files /dev/null and b/fern/images/task_creation_form_example.png differ diff --git a/fern/images/totp/create_email_forwarding.png b/fern/images/totp/create_email_forwarding.png new file mode 100644 index 00000000..20f43cec Binary files /dev/null and b/fern/images/totp/create_email_forwarding.png differ diff --git a/fern/images/totp/create_zap.png b/fern/images/totp/create_zap.png new file mode 100644 index 00000000..ed5e1588 Binary files /dev/null and b/fern/images/totp/create_zap.png differ diff --git a/fern/images/totp/create_zap_action.png b/fern/images/totp/create_zap_action.png new file mode 100644 index 00000000..b57f8da0 Binary files /dev/null and b/fern/images/totp/create_zap_action.png differ diff --git a/fern/images/totp/create_zap_action_event_post.png b/fern/images/totp/create_zap_action_event_post.png new file mode 100644 index 00000000..5438345f Binary files /dev/null and b/fern/images/totp/create_zap_action_event_post.png differ diff --git a/fern/images/totp/create_zap_email.png b/fern/images/totp/create_zap_email.png new file mode 100644 index 00000000..1862ae85 Binary files /dev/null and b/fern/images/totp/create_zap_email.png differ diff --git a/fern/images/totp/create_zap_email_setup.png b/fern/images/totp/create_zap_email_setup.png new file mode 100644 index 00000000..1249bded Binary files /dev/null and b/fern/images/totp/create_zap_email_setup.png differ diff --git a/fern/images/totp/create_zap_input_email.png b/fern/images/totp/create_zap_input_email.png new file mode 100644 index 00000000..2d78c2f8 Binary files /dev/null and b/fern/images/totp/create_zap_input_email.png differ diff --git a/fern/images/totp/create_zap_trigger.png b/fern/images/totp/create_zap_trigger.png new file mode 100644 index 00000000..a7d0b986 Binary files /dev/null and b/fern/images/totp/create_zap_trigger.png differ diff --git a/fern/images/totp/create_zap_webhook.png b/fern/images/totp/create_zap_webhook.png new file mode 100644 index 00000000..697347ea Binary files /dev/null and b/fern/images/totp/create_zap_webhook.png differ diff --git a/fern/images/totp/create_zap_webhook_complete.png b/fern/images/totp/create_zap_webhook_complete.png new file mode 100644 index 00000000..bdd580e7 Binary files /dev/null and b/fern/images/totp/create_zap_webhook_complete.png differ diff --git a/fern/images/totp/test_end_to_end.png b/fern/images/totp/test_end_to_end.png new file mode 100644 index 00000000..8dd22a26 Binary files /dev/null and b/fern/images/totp/test_end_to_end.png differ diff --git a/fern/images/visualizing_results/navigate_to_task.png b/fern/images/visualizing_results/navigate_to_task.png new file mode 100644 index 00000000..0ca0b1d4 Binary files /dev/null and b/fern/images/visualizing_results/navigate_to_task.png differ diff --git a/fern/images/visualizing_results/view_actions.png b/fern/images/visualizing_results/view_actions.png new file mode 100644 index 00000000..86dd985a Binary files /dev/null and b/fern/images/visualizing_results/view_actions.png differ diff --git a/fern/images/visualizing_results/view_diagnostics.png b/fern/images/visualizing_results/view_diagnostics.png new file mode 100644 index 00000000..f019e257 Binary files /dev/null and b/fern/images/visualizing_results/view_diagnostics.png differ diff --git a/fern/images/visualizing_results/view_parameters.png b/fern/images/visualizing_results/view_parameters.png new file mode 100644 index 00000000..d06b221d Binary files /dev/null and b/fern/images/visualizing_results/view_parameters.png differ diff --git a/fern/images/visualizing_results/view_recording.png b/fern/images/visualizing_results/view_recording.png new file mode 100644 index 00000000..bedfe2c9 Binary files /dev/null and b/fern/images/visualizing_results/view_recording.png differ diff --git a/fern/images/what_is_a_parameter/p.1.png b/fern/images/what_is_a_parameter/p.1.png new file mode 100644 index 00000000..f65fb7d3 Binary files /dev/null and b/fern/images/what_is_a_parameter/p.1.png differ diff --git a/fern/images/what_is_a_parameter/p.2.png b/fern/images/what_is_a_parameter/p.2.png new file mode 100644 index 00000000..287cf50e Binary files /dev/null and b/fern/images/what_is_a_parameter/p.2.png differ diff --git a/fern/images/what_is_a_parameter/p.3.png b/fern/images/what_is_a_parameter/p.3.png new file mode 100644 index 00000000..8a38df03 Binary files /dev/null and b/fern/images/what_is_a_parameter/p.3.png differ diff --git a/fern/images/what_is_a_parameter/p.4.png b/fern/images/what_is_a_parameter/p.4.png new file mode 100644 index 00000000..eec455d7 Binary files /dev/null and b/fern/images/what_is_a_parameter/p.4.png differ diff --git a/fern/images/what_is_a_parameter/p.5.png b/fern/images/what_is_a_parameter/p.5.png new file mode 100644 index 00000000..c6ac953d Binary files /dev/null and b/fern/images/what_is_a_parameter/p.5.png differ diff --git a/fern/images/what_is_a_parameter/p.6.png b/fern/images/what_is_a_parameter/p.6.png new file mode 100644 index 00000000..68940726 Binary files /dev/null and b/fern/images/what_is_a_parameter/p.6.png differ diff --git a/fern/images/what_is_a_parameter/p.7.png b/fern/images/what_is_a_parameter/p.7.png new file mode 100644 index 00000000..3f92c3f3 Binary files /dev/null and b/fern/images/what_is_a_parameter/p.7.png differ diff --git a/fern/images/what_is_a_parameter/p.8.png b/fern/images/what_is_a_parameter/p.8.png new file mode 100644 index 00000000..bb7678a0 Binary files /dev/null and b/fern/images/what_is_a_parameter/p.8.png differ diff --git a/fern/images/what_is_a_parameter/p.9.png b/fern/images/what_is_a_parameter/p.9.png new file mode 100644 index 00000000..f0e97164 Binary files /dev/null and b/fern/images/what_is_a_parameter/p.9.png differ diff --git a/fern/images/what_is_a_parameter/u.1.png b/fern/images/what_is_a_parameter/u.1.png new file mode 100644 index 00000000..a1ab7a28 Binary files /dev/null and b/fern/images/what_is_a_parameter/u.1.png differ diff --git a/fern/images/what_is_a_parameter/u.2.png b/fern/images/what_is_a_parameter/u.2.png new file mode 100644 index 00000000..0fb4c587 Binary files /dev/null and b/fern/images/what_is_a_parameter/u.2.png differ diff --git a/fern/images/workato/s1img1.png b/fern/images/workato/s1img1.png new file mode 100644 index 00000000..2ccba590 Binary files /dev/null and b/fern/images/workato/s1img1.png differ diff --git a/fern/images/workato/s1img2.png b/fern/images/workato/s1img2.png new file mode 100644 index 00000000..73265199 Binary files /dev/null and b/fern/images/workato/s1img2.png differ diff --git a/fern/images/workato/s1img3.png b/fern/images/workato/s1img3.png new file mode 100644 index 00000000..8fe92822 Binary files /dev/null and b/fern/images/workato/s1img3.png differ diff --git a/fern/images/workato/s1img4.png b/fern/images/workato/s1img4.png new file mode 100644 index 00000000..f21272d3 Binary files /dev/null and b/fern/images/workato/s1img4.png differ diff --git a/fern/images/workato/s1img5.png b/fern/images/workato/s1img5.png new file mode 100644 index 00000000..a0b170fe Binary files /dev/null and b/fern/images/workato/s1img5.png differ diff --git a/fern/images/workato/s1img6.png b/fern/images/workato/s1img6.png new file mode 100644 index 00000000..688a977b Binary files /dev/null and b/fern/images/workato/s1img6.png differ diff --git a/fern/images/workato/s1img7.png b/fern/images/workato/s1img7.png new file mode 100644 index 00000000..845cf3ae Binary files /dev/null and b/fern/images/workato/s1img7.png differ diff --git a/fern/images/workato/s2img1.png b/fern/images/workato/s2img1.png new file mode 100644 index 00000000..918df13b Binary files /dev/null and b/fern/images/workato/s2img1.png differ diff --git a/fern/images/workato/s2img2.png b/fern/images/workato/s2img2.png new file mode 100644 index 00000000..97233b50 Binary files /dev/null and b/fern/images/workato/s2img2.png differ diff --git a/fern/images/workato/s2img3.png b/fern/images/workato/s2img3.png new file mode 100644 index 00000000..b01901fb Binary files /dev/null and b/fern/images/workato/s2img3.png differ diff --git a/fern/images/workato/s2img4.png b/fern/images/workato/s2img4.png new file mode 100644 index 00000000..abdcf9cf Binary files /dev/null and b/fern/images/workato/s2img4.png differ diff --git a/fern/images/workato/s3img1.png b/fern/images/workato/s3img1.png new file mode 100644 index 00000000..8e0857d2 Binary files /dev/null and b/fern/images/workato/s3img1.png differ diff --git a/fern/images/workato/s3img2.png b/fern/images/workato/s3img2.png new file mode 100644 index 00000000..6a27f5d0 Binary files /dev/null and b/fern/images/workato/s3img2.png differ diff --git a/fern/images/workato/s5img1.png b/fern/images/workato/s5img1.png new file mode 100644 index 00000000..73cd3de2 Binary files /dev/null and b/fern/images/workato/s5img1.png differ diff --git a/fern/images/workato/s5img2.png b/fern/images/workato/s5img2.png new file mode 100644 index 00000000..34a8c9d3 Binary files /dev/null and b/fern/images/workato/s5img2.png differ diff --git a/fern/images/workato/s5img3.png b/fern/images/workato/s5img3.png new file mode 100644 index 00000000..088ecaef Binary files /dev/null and b/fern/images/workato/s5img3.png differ diff --git a/fern/images/workato/s8img1.png b/fern/images/workato/s8img1.png new file mode 100644 index 00000000..ae1836c6 Binary files /dev/null and b/fern/images/workato/s8img1.png differ diff --git a/fern/images/workato/s8img2.png b/fern/images/workato/s8img2.png new file mode 100644 index 00000000..cda31a2a Binary files /dev/null and b/fern/images/workato/s8img2.png differ diff --git a/fern/images/zapier/z.1.png b/fern/images/zapier/z.1.png new file mode 100644 index 00000000..c53d858b Binary files /dev/null and b/fern/images/zapier/z.1.png differ diff --git a/fern/images/zapier/z.10ag.png b/fern/images/zapier/z.10ag.png new file mode 100644 index 00000000..b7a81144 Binary files /dev/null and b/fern/images/zapier/z.10ag.png differ diff --git a/fern/images/zapier/z.10bg.png b/fern/images/zapier/z.10bg.png new file mode 100644 index 00000000..f9fe148e Binary files /dev/null and b/fern/images/zapier/z.10bg.png differ diff --git a/fern/images/zapier/z.11ag.png b/fern/images/zapier/z.11ag.png new file mode 100644 index 00000000..a1b9b67e Binary files /dev/null and b/fern/images/zapier/z.11ag.png differ diff --git a/fern/images/zapier/z.11bg.png b/fern/images/zapier/z.11bg.png new file mode 100644 index 00000000..480a6283 Binary files /dev/null and b/fern/images/zapier/z.11bg.png differ diff --git a/fern/images/zapier/z.12ag.png b/fern/images/zapier/z.12ag.png new file mode 100644 index 00000000..84044f5b Binary files /dev/null and b/fern/images/zapier/z.12ag.png differ diff --git a/fern/images/zapier/z.12bg.png b/fern/images/zapier/z.12bg.png new file mode 100644 index 00000000..8f063b56 Binary files /dev/null and b/fern/images/zapier/z.12bg.png differ diff --git a/fern/images/zapier/z.2.png b/fern/images/zapier/z.2.png new file mode 100644 index 00000000..13717a6b Binary files /dev/null and b/fern/images/zapier/z.2.png differ diff --git a/fern/images/zapier/z.3.png b/fern/images/zapier/z.3.png new file mode 100644 index 00000000..1f12cc3c Binary files /dev/null and b/fern/images/zapier/z.3.png differ diff --git a/fern/images/zapier/z.4.png b/fern/images/zapier/z.4.png new file mode 100644 index 00000000..2eac2fd2 Binary files /dev/null and b/fern/images/zapier/z.4.png differ diff --git a/fern/images/zapier/z.5.png b/fern/images/zapier/z.5.png new file mode 100644 index 00000000..828459d1 Binary files /dev/null and b/fern/images/zapier/z.5.png differ diff --git a/fern/images/zapier/z.6w.png b/fern/images/zapier/z.6w.png new file mode 100644 index 00000000..b8ee5588 Binary files /dev/null and b/fern/images/zapier/z.6w.png differ diff --git a/fern/images/zapier/z.7w.png b/fern/images/zapier/z.7w.png new file mode 100644 index 00000000..ae9b6e71 Binary files /dev/null and b/fern/images/zapier/z.7w.png differ diff --git a/fern/images/zapier/z.8w.png b/fern/images/zapier/z.8w.png new file mode 100644 index 00000000..a68f75f7 Binary files /dev/null and b/fern/images/zapier/z.8w.png differ diff --git a/fern/images/zapier/z.9w.png b/fern/images/zapier/z.9w.png new file mode 100644 index 00000000..7a4b221d Binary files /dev/null and b/fern/images/zapier/z.9w.png differ diff --git a/fern/integrations/api.mdx b/fern/integrations/api.mdx new file mode 100644 index 00000000..af628b98 --- /dev/null +++ b/fern/integrations/api.mdx @@ -0,0 +1,86 @@ +--- +title: API Integrations +subtitle: How to integrate and validate Skyverns API +slug: integrations/api +--- + + +# Organizations API Documentation + +## Get Organizations + +Retrieves the organization information for the current authenticated user. + +### Endpoint + +``` +GET https://api.skyvern.com/api/v1/organizations +``` + +### Authentication + +This endpoint requires Bearer Token authentication. Include the token in the `x-api-key` header of your request. + +``` +x-api-key: +``` + +### Response + +#### Successful Response (200 OK) + +The API will return a JSON object containing an array of organizations associated with the authenticated user. + +```json +{ + "organizations": [ + { + "organization_id": "uuid-string", + "organization_name": "Organization Name" + } + ] +} +``` + +- `organizations`: An array of organization objects + - `organization_id`: A unique identifier for the organization (UUID format) + - `organization_name`: The name of the organization + +#### Error Responses + +- `401 Unauthorized`: The request lacks valid authentication credentials +- `403 Forbidden`: The authenticated user does not have permission to access the requested resource +- `500 Internal Server Error`: An unexpected error occurred on the server + +### Example Request + +Using cURL: + +```bash +curl -X GET "https://api.skyvern.com/api/v1/organizations" \ + -H "x-api-key: your_api_key_here" +``` + +Using Python with the `requests` library: + +```python +import requests + +url = "https://api.skyvern.com/api/v1/organizations" +headers = { + "x-api-key": "your_api_key" +} + +response = requests.get(url, headers=headers) + +if response.status_code == 200: + organizations = response.json()["organizations"] + for org in organizations: + print(f"Organization ID: {org['organization_id']}") + print(f"Organization Name: {org['organization_name']}") +else: + print(f"Error: {response.status_code}") + print(response.text) +``` + +Remember to replace `your_api_key` with your API Key token retrieved from Skyvern's setting page \ No newline at end of file diff --git a/fern/integrations/make.com.mdx b/fern/integrations/make.com.mdx new file mode 100644 index 00000000..ce1f555d --- /dev/null +++ b/fern/integrations/make.com.mdx @@ -0,0 +1,5 @@ +--- +slug: integrations/make.com +--- + + \ No newline at end of file diff --git a/fern/integrations/workato.mdx b/fern/integrations/workato.mdx new file mode 100644 index 00000000..106ea51c --- /dev/null +++ b/fern/integrations/workato.mdx @@ -0,0 +1,140 @@ +--- +title: Workato +slug: integrations/workato +--- + + +## Running a Skyvern Task in Workato + +### Setup + +1. Navigate to the community library tab, and search for Skyvern under “custom connectors” + ![image](../images/workato/s1img1.png) + +2. Once you find Skyvern and click into the app, you will be able to press “install” in the upper right hand corner + ![image](../images/workato/s1img2.png) + +3. Make sure to select “release latest version” to be able to add your Skyvern integrator into your workflows + ![image](../images/workato/s1img3.png) + +4. You will then need to create a new workflow or “recipe” + + 1. If you are a returning user, you will configure setup, location, and starting point + + 2. If you are a new user, you will configure recipe and project name, location, project description, and starting point + +5. Once you’ve created your new workflow, set the trigger, add an “action in app” and search for Skyvern + + 1. If Skyvern is not showing up in this search, it is likely that there was a misstep in tasks 1-3 + ![image](../images/workato/s1img4.png) + +6. Once you select the Skyvern integration, pick your action. This section will describe how to set up, configure, and test the “Create and Run Task” action + ![image](../images/workato/s1img5.png) + ![image](../images/workato/s1img6.png) + +7. You will then be brought to the “Connection” tab where you need to link your Skyvern account. You will need to have a Skyvern account to be able to run to this integration. So after creating your account and/or logging in, navigate to settings and copy your API Key + ![image](../images/workato/s1img7.png) + +8. When you’re back to Workato, having copied your Skyvern API key, add a new connection and paste it under the API key input field + +9. Once you’ve connected your account, all of the setup requirements are done and you will move onto setting up your integration + +### Configure + +1. *(required) URL:* Skyvern’s starting point + +2. *(often required) Navigation Goal:* details where Skyvern is going and what Skyvern is doing. Clear Navigation Goals will be a single goal, broken down into steps. You need to specify when the goal is complete, using “COMPLETE”, or when to abandon that goal, using “TERMINATE” + + * The navigation goal is not used to load the URL. Asking Skyvern to “go to website A” in this field will not have the intended effect + + * Terminations result in Skyvern explaining why it stopped navigating + + * This field can be omitted if you only want Skyvern to extract data + +3. *(optional) Data Extraction Goal:* aside from where Skyvern is going and what Skyvern is doing, is there anything that Skyvern is extracting and returning back? A good data extraction goal is specific about what Skyvern is returning to the user + + * Note that data extractions only happen AFTER Skyvern is finished navigating + +4. *(optional) Navigation Payload:* if you need any content inputted during your task flow, that content goes here in JSON format + + * If you want to run the same task for different users (i.e. filling out the same form multiple times), you should keep everything else the same and update the Navigation Payload + +5. *(optional) Extracted Information Schema:* if you have a data extraction goal, some users need it formatted in a certain way for internal purposes. Navigation payload accepts JSON formatted specifications for how the data should be returned + +6. *(optional) Webhook Callback URL:* This URL can be specified if you would like Skyvern to notify you when it’s finished executing + +7. *(optional) Max Steps:* some users want to cap cost through the number of steps the task can take + +![image](../images/workato/s2img1.png) + +![image](../images/workato/s2img2.png) + +![image](../images/workato/s2img3.png) + +![image](../images/workato/s2img4.png) + +### Test + +1. Testing in Workato is done by testing the entire “recipe,” or workflow. Make sure to hit the “save” button in the upper right hand corner and then “test recipe” + +2. Once the flow is triggered, Workato will tell you what nodes in the sequence ran successfully, failed, and why. Make sure to click through each node to see what the inputs were and their corresponding outputs. Note that you should also check your Skyvern account to see if the task was correctly triggered and the contents are correct under “parameters” + +![image](../images/workato/s3img1.png) + +![image](../images/workato/s3img2.png) + +## Running a Skyvern Workflow in Workato + +### Setup + +1. First, create your workflow in Skyvern. The purpose of this block is to run a pre-configured workflow inside of Workato. Every workflow tool has limitations, allowing you to run a Skyvern workflow in another workflow builder extends the possibilities of their tool + +2. Complete the same setup as detailed above in the task block instructions, following steps 1-9. At the end of the setup you will have configured a trigger, selected the “Run a Workflow” action, and connected your Skyvern account + +### Configure + +1. Select what workflow you would like to run + + 1. If there are no selections, make sure to check your Skyvern account and see if you have any saved workflows you can run + +2. Once you’ve selected the workflow you’d like to run, the only thing you need to configure are whatever parameters you have linked in your workflow. + + 1. If you don’t have parameters, and instead have fixed values, don’t worry about this step! + +3. If your workflow has parameters, they should populate. Add or amend the values to customize the workflow run + +![image](../images/workato/s5img1.png) + +![image](../images/workato/s5img2.png) + +![image](../images/workato/s5img3.png) + +### Test + +1. Testing in Workato is done by testing the entire “recipe,” or workflow. Make sure to hit the “save” button in the upper right hand corner and then “test recipe.” See the task block “test” instructions above for more detail on debugging + +## Adding a Previously Ran Task or Workflow in Workato + +### Setup + +1. This block “gets,” or pulls the output of a previous run into your Workato workflow. The Get a Workflow does so for a workflow run, the Get a Task does so for a task run. + +2. Complete the same setup as detailed above in the the task block instructions, following steps 1-9. At the end of the setup you will have configured a trigger, selected the “Get a Task” or “Get a Workflow” action, and connected your Skyvern account + +### Configure + +1. Since this action is pulling a previously ran task or workflow, the run you want to use needs to have already run/finished running to be able to pull it into your Workato workflow + +2. Depending on whether you selected a “Get a Task” or “Get a Workflow” action, find the appropriate ID + + 1. The Workflow Run ID starts with a WR and the Task ID starts with a TSK + +3. Once you’ve selected the Workflow Run ID or Task ID for the run you would like to add to your action, paste it into the input field + +![image](../images/workato/s8img1.png) + +![image](../images/workato/s8img2.png) + +### Test + +1. Testing in Workato is done by testing the entire “recipe,” or workflow. Make sure to hit the “save” button in the upper right hand corner and then “test recipe.” See the task block “test” instructions above for more detail on debugging \ No newline at end of file diff --git a/fern/integrations/zapier.mdx b/fern/integrations/zapier.mdx new file mode 100644 index 00000000..32480f48 --- /dev/null +++ b/fern/integrations/zapier.mdx @@ -0,0 +1,110 @@ +--- +title: Zapier +slug: integrations/zapier +--- + + +## Running a Skyvern Task in Zapier + +### Setup + +1. Get a Skyvern account, navigate to settings and copy your API Key, you will need to link this in your Skyvern block in Zapier + +2. Add a Skyvern Block, and select the “Run a Task” Action Event + +3. A required “Account” section should populate, here is where you paste your [API Key](https://docs.skyvern.com/running-tasks/introduction#getting-your-api-key) + +4. Once you’ve connected your account, you can press next and proceed to the second step “Configure” + ![image](../images/zapier/z.1.png) + ![image](../images/zapier/z.2.png) + +### Configure + +1. *(required) URL:* Skyvern’s starting point + +2. *(often required) Navigation Goal:* details where Skyvern is going and what Skyvern is doing. Clear Navigation Goals will be a single goal, broken down into steps. You need to specify when the goal is complete, using “COMPLETE”, or when to abandon that goal, using “TERMINATE” + + * The navigation goal is not used to load the URL. Asking Skyvern to “go to website A” in this field will not have the intended effect + + * Terminations result in Skyvern explaining why it stopped navigating + + * This field can be omitted if you only want Skyvern to extract data + +3. *(optional) Data Extraction Goal:* aside from where Skyvern is going and what Skyvern is doing, is there anything that Skyvern is extracting and returning back? A good data extraction goal is specific about what Skyvern is returning to the user + + * Note that data extractions only happen AFTER Skyvern is finished navigating + +4. *(optional) Navigation Payload:* if you need any content inputted during your task flow, that content goes here in JSON format + + * If you want to run the same task for different users (i.e. filling out the same form multiple times), you should keep everything else the same and update the Navigation Payload + +5. *(optional) Extracted Information Schema:* if you have a data extraction goal, some users need it formatted in a certain way for internal purposes. Navigation payload accepts JSON formatted specifications for how the data should be returned + +6. *(optional) Webhook Callback URL:* This URL can be specified if you would like Skyvern to notify you when it’s finished executing + +7. *(optional) Max Steps:* some users want to cap cost through the number of steps the task can take + ![image](../images/zapier/z.3.png) + ![image](../images/zapier/z.4.png) + +### Test + +1. This page will tell you what information “Data In” will be going to Skyvern, and what is empty. Make sure to check this before you “test step,” which we would highly recommend + +2. Upon pressing “test step,” go to your Skyvern account where you can see it run. If everything worked as expected, fabulous! If not, feel free to refine your prompt in Skyvern before heading back to Zapier and sending another test + ![image](../images/zapier/z.5.png) + +## Running a Skyvern Workflow in Zapier + +### Setup + +1. First, create your workflow in Skyvern. The purpose of this block is to run a pre-configured workflow inside of Zapier. Every workflow tool has limitations, allowing you to run a Skyvern workflow in another workflow builder extends the possibilities of their tool + +2. Like with the task block, you will need to link your Skyvern account using your API key found in settings + ![image](../images/zapier/z.6w.png) + +### Configure + +1. Select what workflow you would like to run + + 1. If there are no selections, make sure to check your Skyvern account and see if you have any saved workflows you can run + +2. Once you’ve selected the workflow you’d like to run, the only thing you need to configure are whatever parameters you have linked in your workflow. + + 1. If you don’t have parameters, and instead have fixed values, don’t worry! + +3. If your workflow has parameters, they should populate. Add or amend the values to customize the workflow run + ![image](../images/zapier/z.7w.png) + ![image](../images/zapier/z.8w.png) + +### Test + +1. Upon pressing “test step,” go to your Skyvern account where you can see the workflow run. If everything worked as expected, fabulous! If not, try debugging in Skyvern before you retest in Zapier + ![image](../images/zapier/z.9w.png) + +## Adding a Previously Ran Task or Workflow in Zapier + +### Setup + +1. This block “gets,” or pulls the output of a previous run into your Zapier workflow. The Get a Workflow does so for a workflow run, the Get a Task does so for a task run. + +2. Like with the task block, you will need to link your Skyvern account using your API key found in settings + ![image](../images/zapier/z.10ag.png) + ![image](../images/zapier/z.10bg.png) + +### Configure + +1. Since this action is pulling a previously ran task or workflow, the run you want to use needs to have already run/finished running to be able to pull it into your zap + +2. Depending on whether you selected a “Get a Task” or “Get a Workflow” action, find the appropriate ID + + 1. The Workflow Run ID starts with a WR and the Task ID starts with a TSK + +3. Once you’ve selected the Workflow Run ID or Task ID for the run you would like to add to your action, paste it into the input field + ![image](../images/zapier/z.11ag.png) + ![image](../images/zapier/z.11bg.png) + +### Test + +1. Upon pressing “test step,” the task or workflow details should populate. If everything worked as expected, fabulous! If not, it might be that you linked the incorrect account or the ID is incorrect + ![image](../images/zapier/z.12ag.png) + ![image](../images/zapier/z.12bg.png) diff --git a/fern/introduction.mdx b/fern/introduction.mdx new file mode 100644 index 00000000..cafc367c --- /dev/null +++ b/fern/introduction.mdx @@ -0,0 +1,89 @@ +--- +title: Introduction +subtitle: 🐉 Automate Browser-based workflows using LLMs and Computer Vision 🐉 +slug: introduction +--- + + +[Skyvern](https://www.skyvern.com) automates browser-based workflows using LLMs and computer vision. It provides a simple API endpoint to fully automate manual workflows, replacing brittle or unreliable automation solutions. +

+ Recording of Skyvern automating an insurance quote being generated on Geico.com +

+ +# Why Skyvern? + +Traditional approaches to browser automations required writing custom scripts for websites, often relying on DOM parsing and XPath-based interactions which would break whenever the website layouts changed. + +Instead of only relying on code-defined XPath interactions, Skyvern relies on prompts in addition to computer vision and LLMs to the mix to parse items in the viewport in real-time, create a plan for interaction and interact with them. + +This approach gives us a few advantages: + +1. Skyvern can operate on websites it’s never seen before, as it’s able to map visual elements to actions necessary to complete a workflow, without any customized code +1. Skyvern is resistant to website layout changes, as there are no pre-determined XPaths or other selectors our system is looking for while trying to navigate +1. Skyvern is able to take a single workflow and apply it to a large number of websites, as it’s able to reason through the interactions necessary to complete the workflow +1. Skyvern leverages LLMs to reason through interactions to ensure we can cover complex situations. Examples include: + 1. If you wanted to get an auto insurance quote from Geico, the answer to a common question “Were you eligible to drive at 18?” could be inferred from the driver receiving their license at age 16 + 1. If you were doing competitor analysis, it’s understanding that an Arnold Palmer 22 oz can at 7/11 is almost definitely the same product as a 23 oz can at Gopuff (even though the sizes are slightly different, which could be a rounding error!) + +Want to see examples of Skyvern in action? [Check out some examples we have here](/getting-started/skyvern-in-action) + +# How it works +Skyvern was inspired by the Task-Driven autonomous agent design popularized by [BabyAGI](https://github.com/yoheinakajima/babyagi) and [AutoGPT](https://github.com/Significant-Gravitas/AutoGPT) -- with one major bonus: we give Skyvern the ability to interact with websites using browser automation libraries like [Playwright](https://playwright.dev/). + + + Skyvern's system diagram + Skyvern's system diagram + + + +## Skyvern use-cases + + + + Watch Skyvern automatically apply to jobs + + + Watch Skyvern automate purchases on e-commerce websites + + + Watch Skyvern automate interacting with government websites + + + Watch Skyvern navigate complex multi-page forms in any language + + + +## Quickstart + + + Start automating tasks with the hosted version of Skyvern + + + Start automating tasks in your own cloud + + + diff --git a/fern/running-tasks/advanced-features.mdx b/fern/running-tasks/advanced-features.mdx new file mode 100644 index 00000000..8853571f --- /dev/null +++ b/fern/running-tasks/advanced-features.mdx @@ -0,0 +1,163 @@ +--- +title: Advanced Settings for tasks +subtitle: How to use advanced settings for tasks +slug: running-tasks/advanced-features +--- + + +## 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. + +```json +POST https://api.skyvern.com/api/v1/tasks + +Headers: +{ + "x-api-key": "YOUR_API_KEY", + "x-max-steps-override": 10 +} + +Body: +.. usual task body .. +``` + +## Time-based One-time Password (TOTP) + +Skyvern supports one-time password (see https://www.twilio.com/docs/glossary/totp for more information), also known as 2FA/MFA, in two ways: 1) Skyvern gets the code from your endpoint 2) You push the the code to Skyvern. + +### 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: + +#### 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. + +Here's the TOTP endpoint contract you should use: + +Request (POST): +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| task_id | String | yes | tsk_123 | The task ID that needs the verification to be done | + +Response: +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| task_id | String | yes | tsk_123 | The task ID that needs the verification to be done | +| verification_code | String | no | 123456 | The verification code | + +#### Validate The Sender of The Request +Same as the webhook API, your server needs to make sure it’s Skyvern that’s making the request. + +- a python example for how to generate and validate 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 + +### 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 below) + +#### Skyvern's TOTP Endpoint +This endpoint takes your TOTP/2FA/MFA code, stores it in Skyvern’s database and uses it while running tasks/workflows. + +Request type: `POST` + +Endpoint url: `https://api.skyvern.com/api/v1/totp` + +Authentication: same as other Skyvern APIs, you need to pass your api key with the `x-api-key` header. + +Request data: +| field | required | type | example | description | +| --- | --- | --- | --- | --- | +| totp_identifier | yes | string | An email address or phone number which received the code | this is a required field as this is the best way for skyvern to know what the identifier | +| content | yes | string | | the email content of a 2FA email; the text message for the verification code | +| task_id | no | string | tsk_22222222 | used to help skyvern locate the totp code more accurately for your task | +| workflow_id | no | string | wpid_12345 | used to help better locate the totp code accurately for your workflow | +| source | no | string | email, phone, app, etc | | +| expired_at | no | timestamp | 2024-09-18T05:15:02 | The expiration time of the code. If provided, skyvern uses it to decide if the code is valid | + +#### Forwarding Your Email To Skyvern (Gmail + Zapier) +This setup requires a Zapier pro plan account. + +**Step 1. Create a Zapier Zap** + +Go to https://zapier.com/app/home and create new Zaps +

+ +

+ +In the newly created Zap draft, Click the “Trigger” button +

+ +

+ +Click `Email by Zapier` +

+ +

+ +In the Email “Setup”, pick `New Inbound Email` in the `Trigger event` selection. Click `Continue` to complete the “Setup” +

+ +

+ +In Email “Configure”, create an email address which will be used to forward emails for TOTP codes. Click “Continue”. +

+ +

+ +Let’s add the Action to complete the Zapier setup before coming back to test it. Click the “Action” button and add `Webhooks by Zapier` +

+ +

+ +

+ +

+ +In the Setup, choose “POST” under the `Action event` selection. Then click “Continue”. +

+ +

+ +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) +- Payload Type: json +- Data: + - totp_identifier: choose `Raw To Email` after clicking the “+” sign + - content: choose `Body Plain` after clicking the “+” sign + - source: email +- Headers: + - x-api-key: `Your Skyvern API Key` + +

+ +

+Click Continue + +**Step 2. Add forwarding email and create a filter in Gmail** + +Go to Gmail Settings → Forwarding and POP/IMAP (https://mail.google.com/mail/u/0/#settings/fwdandpop) → click “Add a forwarding address” → enter the zapier email address you just created. There might be some verifications, including a verification email from Zapier, you have to complete here. + +After setting up the forwarding email address, go to “Filters and Blocked Addresses” (https://mail.google.com/mail/u/0/#settings/filters). Click “Create a new filter” and set up your email filtering rule for your TOTP (2FA/MFA) emails. Click “Create filter”. Check “Forward it to” and pick the new email address and update filter. + +

+ +

+ +**Step 3. Test it end to end!** + +You can forward any previous TOTP (2FA/MFA) email to the Zapier email address you created in Step 1. + +In Zapier: under the “Test” of the Webhooks action, send a request to test it out. If your test is successful, you should see a `A request was sent to Webhooks by Zapier` message + +

+ +

diff --git a/fern/running-tasks/api-spec.mdx b/fern/running-tasks/api-spec.mdx new file mode 100644 index 00000000..fd86c5e2 --- /dev/null +++ b/fern/running-tasks/api-spec.mdx @@ -0,0 +1,151 @@ +--- +title: Tasks API +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” + +## Request - Initiate a task +Request type: `POST` + +Production:`https://api.skyvern.com/api/v1/tasks/` + +### Header + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| x-api-key | String | yes | [your-api-key-here] | Bearer token that gives your backend access to the Skyvern API. This will be manually provided by us | +| x-max-steps-override | Integer | no | 10 | Overrides any max step configuration for the initiated task | + +### Body + +| Parameter | Type | Required? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| url | HttpUrl | yes | https://www.example.com | It must be a http or https URL | +| 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 | +| webhook_callback_url | HttpUrl | no | … | The callback URL once our system is finished processing this async task | +| 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. | +| totp_verification_url | HttpUrl | no | https://mywebsite.com/two_factor_code | The url of your TOTP endpoint. If this field is provided, Skyvern will call the url to fetch the TOTP/2FA/MFA code when needed | +| totp_identifier | String | no | myemail@example.com / 4155558888 | The email address or the phone number which receives the TOTP/2FA/MFA code. If this field is provided, Skyvern will fetch the code that is pushed to [Skyvern's TOTP API](https://docs.skyvern.com/running-tasks/advanced-features#push-code-to-skyvern) | + +## Example Request (Apply for a job) + +```python +POST https://api.skyvern.com/api/v1/tasks/ + +{ + "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 +Each task has an associated `task_id` -- a unique identifier you can use to look up information about any task. + +| 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) +If a `webhook_callback_url` is specified within your task request, Skyvern will make a callback to your system letting you know that it has either finished, terminated or failed a task execution. + +The following headers can be used to validate it's an authentic Skyvern request. + +### 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 +These parameters are returned in the body of the `webhook_callback_url`. + +| Parameter | Type | Always returned? | Sample Value | Description | +| --- | --- | --- | --- | --- | +| task_id | String | yes | t_123456 | The task id associated with this specific task | +| status | String | yes | success | The status of the 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 | tsk_123 | The id of the task you want to check the status of | +| status | String | created / queued / running / completed / terminated / failed / canceled | String indicating the status of this task. created: the initial state when the task is created; queued: the task has been enqueued and is waiting to be picked up by a worker to execute; running: the task is being executed; completed: the task has successfully completed; terminated: the agent doesn't believe the task could be completed so it terminated the task; failed: the task failed due to a specific reason; canceled: the task is canceled by the user | +| 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 | 'price’: ‘$100.0’ | | +| screenshot_url | String | "https://skyvern-artifacts.s3.amazonaws.com/production/tsk_123/...screenshot_final.png" | … url to screenshot … | +| recording_url | String | "https://skyvern-artifacts.s3.amazonaws.com/production/tsk_123/...recording.webm" | ... url to recording … | +| action_screenshot_urls | List[str] | ["https://skyvern-artifacts.s3.amazonaws.com/production/tsk_123/step_2...action.png", "https://skyvern-artifacts.s3.amazonaws.com/production/tsk_123/step_0...action.png", "https://skyvern-artifacts.s3.amazonaws.com/production/tsk_123/step_0...action.png"] | 3 screenshots for the lastest 3 actions that Skyvern took. | +| failure_reason | String | “Failed to pass this page - missing information: invalid password” | The reason why the task failed. Examples: "Max steps per task (10) exceeded ..." - by default, a task as a cap on the number of steps per task for budget control. This can be configured in your organization settings page; "Max retries per step (3) exceeded..." - this means Skyvern ran into some internal failures. Skyvern Agent is not perfect and doesn't have 100% web coverage today. When it runs into pages it cannot navigate through or take actions on, this failure_reason shows up. (Currently we're improving Skyvern's abilility as well as the failure_reason to show better errors to help generate better feedbacks to your failure) | + +## Request - List Steps (GET) +Each task is made up of "steps" which are the individual actions Skyvern takes to complete the task. You can use this endpoint to get all the steps of the task. + +Request type: `GET` + +Production: `https://api.skyvern.com/api/v1/tasks/{task_id}/steps` + +## Response - List Steps (GET) +The response is a list of Step Object. + +### Step Object +| Parameter | Type | Sample Value | Description | +| --- | --- | --- | --- | +| organization_id | String | o_123 | Your organization id | +| task_id | String | tsk_123 | The id of the task | +| step_id | String | stp_123 | The id of the step | +| status | String | created / running / completed / failed / canceled | The status of the step | +| order | Integer | 0 / 1 / 2 | The zero based index of the step. 0 is the first step of the task. | +| retry_index | Integer | 0 / 1 / 2 / 3 | When a step fails, the retry step will have a retry_index that's larger than 0 | +| input_token_count | Integer | 19223 | The number of input tokens used in this step | +| output_token_count | Integer | 500 | The number of output tokens generated in this step | + +## Request - Cancel A Task (POST) +A task that's in any of thsese states can be canceled: ["created", "queued", "running"]. This stops the execution of a task. + +Request type: `POST` + +Production: `https://api.skyvern.com/api/v1/tasks/{task_id}/cancel` diff --git a/fern/running-tasks/introduction.mdx b/fern/running-tasks/introduction.mdx new file mode 100644 index 00000000..7b0b6620 --- /dev/null +++ b/fern/running-tasks/introduction.mdx @@ -0,0 +1,16 @@ +--- +title: Introduction +subtitle: Tasks are the building block of Skyvern +slug: running-tasks/introduction +--- + + +# 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/fern/running-tasks/visualizing-results.mdx b/fern/running-tasks/visualizing-results.mdx new file mode 100644 index 00000000..039e6591 --- /dev/null +++ b/fern/running-tasks/visualizing-results.mdx @@ -0,0 +1,58 @@ +--- +title: Visualizing Results +subtitle: How to understand the information shown by Skyvern +slug: running-tasks/visualizing-results +--- + + +# Visualizing Results +Skyvern comes bundled with a Visualizer to help you understand what's going on with your tasks. To get started, navigate to the task history page and click on any task. + + + + +## Actions +Each action that Skyvern takes can be viewed in the Action viewer. It's accompanied with a screenshot of the screen state *after* the action has executed + + + +## Recording +Each Skyvern task comes with a recording of the entire operation (end to end). To view the recording, click on the recording tab. + + + +## Task Parameters +The task parameters are the inputs that you provided to Skyvern. This includes the URL, the extraction rules, and any other information that you provided to Skyvern. + + + +## Diagnostic Logs +The diagnostics tab contains information used by Skyvern to do its processing. It includes information such as the annotated screenshots, action screenshots, element tree, prompt, action list, page HTML, and the raw LLM Request. + + + +## Accessing results via API + +You can also access the results of a task via the API. + +The following endpoint can be used to get the results of a task: +``` +GET https://api.skyvern.com/api/v1/tasks/{task_id}/steps?page=1&page_size=15 +``` + +The response will contain a list of steps, alongside their actions and other relevant information + +The following endpoint can be used to retrieve artifacts for a specific step: +``` +GET https://api.skyvern.com/api/v1/tasks/{task_id}/steps/{step_id}/artifacts +``` + +## Artifacts configurations +By default, Skyvern stores artifacts, including video recording, screenshots, llm requests and responses, html and skyvern parsed html elements locally in the `/artifacts` folder under the skyvern repository. +You can also have skyvern to upload atrifacts to your s3 buckets. To do this, first set up these environment variables: +- `AWS_DEFAULT_REGION`: `us-east-1`, `us-west-1`, ... +- `AWS_ACCESS_KEY_ID` +- `AWS_SECRET_ACCESS_KEY` +- `SKYVERN_STORAGE_TYPE`: set it to be `s3`. The default is `local` + +Make sure these s3 buckets are created: `skyvern-artifacts`, `skyvern-screenshots`. These are the default bucket names skyvern uses. To customize the bucket names, change these two env variables: `AWS_S3_BUCKET_ARTIFACTS` and `AWS_S3_BUCKET_SCREENSHOTS` diff --git a/fern/running-tasks/webhooks-faq.mdx b/fern/running-tasks/webhooks-faq.mdx new file mode 100644 index 00000000..48dedab2 --- /dev/null +++ b/fern/running-tasks/webhooks-faq.mdx @@ -0,0 +1,49 @@ +--- +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) + +## How do we handle webhook authentication? (ie how can we handle callbacks?) + + +```python Python +import hmac +from fastapi import Request + +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 +``` + +```javascript Javascript +const crypto = require('crypto'); + +function validateSkyvernRequestHeaders(req) { + const headerSkyvernSignature = req.headers['x-skyvern-signature']; + const payload = req.body; // assuming req.body is a Buffer or string + const hash = crypto.createHmac('sha256', process.env.SKYVERN_API_KEY) + .update(payload) + .digest('hex'); + return headerSkyvernSignature === hash; +} +``` + + + +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 | … | | diff --git a/fern/workflows/creating-workflows.mdx b/fern/workflows/creating-workflows.mdx new file mode 100644 index 00000000..979e466c --- /dev/null +++ b/fern/workflows/creating-workflows.mdx @@ -0,0 +1,245 @@ +--- +title: Creating Workflows +subtitle: Creating complex multi-step workflows +slug: workflows/creating-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”
FILE_URL = "file_url” | +| 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 | + +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 +8. FileParserBlock + +To read about specific blocks, check out [the block documentation](/workflows/workflow-blocks) + + +## Managing Credentials and Sensitive Information +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/skyvern/demo) + + +## 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 + +### `persist_browser_session` + +The `persist_browser_session` flag indicates whether the browser session should be retained between different workflow runs. When enabled, it uses the same `user_data_dir` for each run and updates it at the end of each run. This is useful for maintaining the browser state, such as login sessions and cookies, across multiple runs of the same workflow, leading to more efficient and seamless execution. + +> **Note:** This flag is set at the workflow level, not the block level, meaning it applies to the entire workflow's session persistence rather than individual blocks. + +### `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/fern/workflows/getting-workflows.mdx b/fern/workflows/getting-workflows.mdx new file mode 100644 index 00000000..6c4f9196 --- /dev/null +++ b/fern/workflows/getting-workflows.mdx @@ -0,0 +1,156 @@ +--- +title: Getting Existing Workflows +subtitle: '' +slug: workflows/getting-workflows +--- + + +# Workflows API Specification + +## Endpoint + +### `GET /api/v1/workflows` + +This endpoint retrieves a list of workflows. + +### Request +* **URL:** `https://api.skyvern.com/api/v1/workflows` +* **Method:** `GET` +* **Query Parameters:** + * `page`: The page number to retrieve (default: `1`). + * `only_workflows`: Set to `true` to only retrieve workflows. + +### Headers + + +* **x-api-key:** `String` `yes` `[your-api-key-here]` + +### Example Curl Request + +```bash +curl 'https://api.skyvern.com/api/v1/workflows?page=1&only_workflows=true' \ + -H 'x-api-key: [your-api-key-here]' \ +``` + +## API Response Structure + +The API returns a JSON array where each element represents a workflow object. Below is the structure and documentation for each field. + +```json +[ + { + "workflow_id": "string", + "organization_id": "string", + "title": "string", + "workflow_permanent_id": "string", + "version": "integer", + "is_saved_task": "boolean", + "description": "string", + "proxy_location": "string | null", + "webhook_callback_url": "string | null", + "totp_verification_url": "string | null", + "workflow_definition": { + "parameters": [ + { + "parameter_type": "string", + "key": "string", + "description": "string | null" + } + ], + "blocks": [ + { + "label": "string", + "block_type": "string" + } + ] + } + } +] +``` + +### Fields + +* **workflow_id** (`string`): + * A unique identifier for the workflow. This ID is used to reference the workflow in various operations and tasks. + +* **organization_id** (`string`): + * The unique identifier of the organization to which the workflow belongs. This is useful for segregating workflows by different organizations. + +* **title** (`string`): + * The human-readable title of the workflow. It typically describes the primary task or purpose of the workflow. + +* **workflow_permanent_id** (`string`): + * A permanent and unique identifier for the workflow. Unlike `workflow_id`, this ID remains consistent across different versions of the workflow. + +* **version** (`integer`): + * Indicates the version number of the workflow. This is incremented with each update or modification to the workflow. + +* **is_saved_task** (`boolean`): + * A flag indicating whether the workflow is saved as a task for future use (`true`) or not (`false`). + +* **description** (`string`): + * A brief description of what the workflow does. This may include the primary goal or steps involved in the workflow. + +* **proxy_location** (`string | null`): + * The location setting for the proxy, if applicable. It could be `RESIDENTIAL`, `DATACENTER`, or `null` if no proxy is used. + +* **webhook_callback_url** (`string | null`): + * The URL to which callbacks will be sent once the workflow completes or if specific events occur during its execution. This field may be `null` if no webhook is configured. + +* **totp_verification_url** (`string | null`): + * The URL for TOTP (Time-based One-Time Password) verification, if required. This field is `null` if TOTP verification is not necessary for the workflow. + +* **workflow_definition** (`object`): + * Contains the detailed definition of the workflow, including the parameters and blocks that make up the workflow. + + * **parameters** (`array`): + * A list of parameters used by the workflow. Each parameter defines a key-value pair that may include the type of parameter, its key, and an optional description. Parameters help in customizing and controlling the workflow's behavior. + + * **blocks** (`array`): + * A series of blocks that represent individual tasks or actions within the workflow. Each block includes a label and type, which define the nature and purpose of the task within the workflow. Blocks can range from simple tasks, like logging in, to more complex sequences of actions. + + + +Example Response +Here’s an example of what the API might return: +``` +[ + { + "workflow_id": "w_297763518988864302", + "organization_id": "o_197675547813248794", + "title": "Test Workday Application", + "workflow_permanent_id": "wpid_297751296240552836", + "version": 4, + "is_saved_task": false, + "description": "Login Workday and submit the application", + "proxy_location": "RESIDENTIAL", + "webhook_callback_url": null, + "totp_verification_url": null, + "workflow_definition": { + "parameters": [ + { + "parameter_type": "output", + "key": "login_output", + "description": "Output parameter for block login" + }, + { + "parameter_type": "workflow", + "key": "website_url", + "description": null + } + ], + "blocks": [ + { + "label": "login", + "block_type": "task" + }, + { + "label": "submit", + "block_type": "task" + } + ] + } + } +] + +``` \ No newline at end of file diff --git a/fern/workflows/introduction.mdx b/fern/workflows/introduction.mdx new file mode 100644 index 00000000..4e7d92ca --- /dev/null +++ b/fern/workflows/introduction.mdx @@ -0,0 +1,19 @@ +--- +title: Introduction +subtitle: Workflows -- chaining multiple tasks together +slug: workflows/introduction +--- + + +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 +8. FileParserBlock diff --git a/fern/workflows/running-workflows.mdx b/fern/workflows/running-workflows.mdx new file mode 100644 index 00000000..0703bed0 --- /dev/null +++ b/fern/workflows/running-workflows.mdx @@ -0,0 +1,211 @@ +--- +title: Running Workflows +subtitle: Executing complex multi-step workflows +slug: workflows/running-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/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/fern/workflows/what-is-a-parameter.mdx b/fern/workflows/what-is-a-parameter.mdx new file mode 100644 index 00000000..c3283046 --- /dev/null +++ b/fern/workflows/what-is-a-parameter.mdx @@ -0,0 +1,97 @@ +--- +title: What the heck is a parameter? +slug: workflows/what-is-a-parameter +--- + + +## What is a Parameter? + +Parameters allow you to replace specific values with placeholders that can be customized run by run. + +If I have a series of task blocks in a workflow that go to Sephora, search for a specific black mascara, add 100 to my cart and purchase, I would have to go in and manually change those items every time if I wanted to do so for a different website, a different product, and different quantity. For those three values, instead of putting in the fixed Sephora URL, product number, and quantity, I can create placeholders for those string value inputs. + +* So, instead of “www.sephora.com” the placeholder parameter would be “website_URL” +* Instead of “ID 123456”, “product_ID” +* And instead of “100”, “quantity” + +With these registered as parameters, the user doesn’t have to change the values in each node if they want to change the site, product, or quantity, they only have to write them in after pressing “run”. In this case, the “Sephora Purchase Acquisition” becomes a template for more general “Purchase Acquisitions” that can be customized more easily without tampering with the inner workings of the workflow. + +## Adding a Parameter + +**Step 1.** To create a placeholder value, you must first create one using the “parameters” dropdown in the Workflow Editor + + + +**Step 2.** Add a workflow parameter + +* Note that if you are looking to add a username or password parameter, you must first contact us + + + + + +**Step 3.** Add a key that will act as the name for the parameter. You can also include a description or set a default value if you wish. Note that a default value pre-populates the run parameter, but can be overrode + + + + + + + +**Step 4.** Input the parameter. In this case, we are using the website_URL parameter in the URL of the task block (this is considered a “parameterized field”). For other parameters, you might need to link it in the parameters drop down. **Make sure you read the “Using Parameters” section—this is critical!** + + + + + +**Step 5.** Press “Run” after you are done configuring your workflow and input values for any parameters you have linked throughout your workflow. Note that if you set a default value, it will automatically populate here. + + + +## Using Parameters + +There are two ways to use parameters in Skyvern’s Workflow Agent (Beta): + +### 1. Parameterized Fields: certain fields can accept a fixed string value or a parameter + + +If you are looking to load a parameterized value into the following fields, you can only do so by passing the parameter’s key, or name, as text into the input: + +* Task block: URL, Suffix, TOTP Identifier +* For Loop: loop over value +* File Parser: URL +* Send Email: recipients, body + +**Steps** + +1. Create the parameter in the parameter dropdown in the menu. In this case, the key is “website_URL” +2. Type the key freeform into the task URL + + + + +### 2. Block Parameters: any parameter linked in the block that will be passed into the LLM as context Skyvern needs to complete the task. Any other non-parameterized fields accept block parameters this way. + + +Create this value when you have details that vary from run-to-run: + +* For instance, you can parameterize usernames or passwords, how to do something, dates, or uploaded files + * Ask yourself: does this vary run-by-run? If the answer is yes, there might be value in creating a parameter for it +* Examples: start_date, end_date, procurement_list_file, email_recipients, how_to_download_an_invoice +* to load these values, you can add them in the workflow editor using the run parameters tab in the header +* Make sure to check if this value needs to go into a parameterized field, if not, load them into the parameters drop down, you don’t need to worry about the placement or order as the LLM pieces together what goes where + +**Steps** + +1. Create the parameter in the parameter dropdown in the menu. In this case, the parameter keys are start_date, end_date, and how_to_find_invoices_page +2. Link the values in the parameters dropdown menu + + + + +## Future Plans for Parameters + +Our main goal is to make every field a parameterized field and remove block parameters + +* We know it’s confusing, but it’s only temporary! In the future we’re headed toward loading parameters directly into each input field. +* One day, your prompt may look like “Find the invoices page using **/how_to_find_invoices_page**, filter the invoices using **/start_date** and **/end_date** provided.” Or perhaps brackets as are traditionally used in code. diff --git a/fern/workflows/workflow-blocks.mdx b/fern/workflows/workflow-blocks.mdx new file mode 100644 index 00000000..8975cf18 --- /dev/null +++ b/fern/workflows/workflow-blocks.mdx @@ -0,0 +1,209 @@ +--- +title: Workflow Blocks +subtitle: Individual Blocks within Skyvern +slug: workflows/workflow-blocks +--- + + + +## 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 +``` +Inputs: + +1. **URL *(often required):*** Skyvern Agent’s starting point. Ideally the website you’d like to automate. + - In the workflows interface, if this input is left blank it will continue where the previous node left off. The idea of a navigation goal is to set or reset where the agent starts off. + - If you’re logging in to a site using the first task block, you would want to leave URL blank for the second block so that it can continue after logging in +2. **Navigation Goal *(often required):*** details where Skyvern is going and what Skyvern is doing. Clear Navigation Goals will be a single goal, broken down into steps. Avoid supplying multiple goals. You need to specify when the goal is complete, using “COMPLETE”, or when to abandon that goal, using “TERMINATE” + - The navigation goal is not used to load the URL. Asking Skyvern to “go to website A” in this field will not have the intended effect + - Terminations result in Skyvern explaining why it stopped navigating + - This field can be omitted if you only want Skyvern to extract data without navigating anywhere else +3. **Data Extraction Goal *(optional):*** aside from where Skyvern is going and what Skyvern is doing, is there anything that Skyvern is extracting and returning back? A good data extraction goal is specific about what Skyvern is returning to the user + - Note that data extractions only happen after Skyvern is finished navigating +4. **Extracted Information Schema *(optional):*** if you have a data extraction goal, some users need it formatted in a certain way for internal purposes. Navigation payload accepts JSON formatted specifications for how the data should be returned +5. **Max Steps Override *(optional):*** some users want to cap cost through the number of steps the task can take +6. **Max Retries *(optional):*** the number of times a step can be retried if it fails +7. **Complete on Download *(optional):*** Allows Skyvern to complete the task after a file has been downloaded +8. **File Suffix *(optional):*** an identifier attached to the downloaded file +9. **TOTP URL and TOTP Identifier *(optional):*** if you have an internal system where you can store the 2FA TOTP code, this URL calls on this storage space. The identifier allows you to link the code to the task, this is critical if you are running multiple tasks concurrently. [Contact us](https://meetings.hubspot.com/skyvern/demo?uuid=7c83865f-1a92-4c44-9e52-1ba0dbc04f7a) if you would like to set up 2FA retreival in your workflows. +10. **Parameters *(optional):*** parameters are self-defined placeholders that are specified run-to-run. They can either be workflow parameters, passed in via an API call, or output parameters, extracted from a previous task block. If specified, they are used by Skyvern to assist in the navigation, to fill out forms or further influence what actions to take on a website. + + +## ForLoopBlock +Iterate over something such as a CSV or the output of a previous block. The blocks nested 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 +``` +Inputs: + +1. **Loop Value *(required):*** This is the value that the loop will iterate over. For instance, if you have for every invoice ID, do X, invoice ID would be the value for this input. + * Please [contact us](https://meetings.hubspot.com/skyvern/demo?uuid=7c83865f-1a92-4c44-9e52-1ba0dbc04f7a) if you would like to add a loop block. Since we’re in beta, the loop value needs to be parameterized from the backend. + 2. **Another block nested within the loop (required)** + + +## CodeBlock +This block executes user-defined Python code within our execution environment. It’s able to take parameters as input and transform them based on a certain specification. + +In addition to running simple code snippets, CodeBlock allows you to: +- execute asynchronous code +- control your browser page inside Skyvern + +**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 +``` + +**Example Block with Browser Control** + +```json +- block_type: code + label: get_tab_details + code: | + print("Getting tab details") + result = { + "url": skyvern_page.url, + "title": await skyvern_page.title() + } + print("Got details:", result) + print("Now I want to see a cat") + await skyvern_page.goto("https://cataas.com/cat") +``` +Inputs: + +1. **Code *(required):*** Insert your custom Python code so that you can define your own custom block. + + +## 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 +``` + +Inputs: + +1. **Prompt *(required):*** Write a natural language prompt to be sent to the LLM to generate a text response +2. **JSON Schema *(optional):*** Craft a JSON input that structures the LLM output for use in another programming task + +## DownloadToS3Block / UploadToS3Block + +Persists files inside S3 + +``` +- block_type: upload_to_s3 + label: upload_downloaded_files_to_s3 + path: SKYVERN_DOWNLOAD_DIRECTORY +``` + + +* Since we’re in beta, this feature is unavailable right now, [contact us](https://meetings.hubspot.com/skyvern/demo?uuid=7c83865f-1a92-4c44-9e52-1ba0dbc04f7a) if you would like to use it. + +## 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 +``` + +Inputs: + +1. **Recipients *(required):*** a list of people who will receive the email separated by commas +2. **Subject/Body *(optional):*** the header and body of an email +3. **File attachments *(optional):*** since we’re still in beta, you will need to [contact us](https://meetings.hubspot.com/skyvern/demo?uuid=7c83865f-1a92-4c44-9e52-1ba0dbc04f7a) to upload attachments to the email + +## FileParserBlock + +Downloads and parses a file to be used within other workflow blocks. + +**Supported types:** CSV + +``` +- block_type: file_url_parser + label: csv_parser + file_type: csv + file_url: +``` + +Inputs: + +1. **File URL *(required):*** This block allows you to use a CSV within your workflow. + * Since we’re still in beta, you will need to [contact us](https://meetings.hubspot.com/skyvern/demo?uuid=7c83865f-1a92-4c44-9e52-1ba0dbc04f7a) to load a value into this block