Compare commits
580 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b0fce76e7 | ||
|
|
24863e8505 | ||
|
|
ad1b50cf58 | ||
|
|
806977ece8 | ||
|
|
962acb3cdd | ||
|
|
4d2aeda083 | ||
|
|
38b178f22f | ||
|
|
9b18e40d45 | ||
|
|
0ee505b24b | ||
|
|
295d1935f5 | ||
|
|
f2acc92939 | ||
|
|
c269e36c16 | ||
|
|
55709c945e | ||
|
|
9e49dff964 | ||
|
|
f09632c51c | ||
|
|
95e57cf43d | ||
|
|
b4e6c8f1cc | ||
|
|
e9ef9529ca | ||
|
|
3aaffb667d | ||
|
|
59fd1982d8 | ||
|
|
e174afd63f | ||
|
|
edf38e68fc | ||
|
|
bf3624d788 | ||
|
|
d79359d55c | ||
|
|
7b4dd7e7c2 | ||
|
|
7120df409d | ||
|
|
97da02c149 | ||
|
|
65d28b1666 | ||
|
|
33ee848e01 | ||
|
|
3e260f21bf | ||
|
|
6a5226d197 | ||
|
|
bb7fe7158f | ||
|
|
8b78d8e8f1 | ||
|
|
633b65d33d | ||
|
|
26f73ec044 | ||
|
|
7681a7cd2b | ||
|
|
ac7ffaf6eb | ||
|
|
d72b6a1ba0 | ||
|
|
400fd43d7b | ||
|
|
c2038aaafc | ||
|
|
ac01aca99c | ||
|
|
265679e9dd | ||
|
|
2452bf60e1 | ||
|
|
777e842c39 | ||
|
|
337c002595 | ||
|
|
f339ff76da | ||
|
|
a3ce97384c | ||
|
|
1eb2e64f03 | ||
|
|
78fa30ed11 | ||
|
|
bee2b836ce | ||
|
|
323adca6a1 | ||
|
|
bff497e2e5 | ||
|
|
9949fb0ded | ||
|
|
87303f70b1 | ||
|
|
fa5bef92f3 | ||
|
|
abaf77f41b | ||
|
|
29a100956f | ||
|
|
cedd5a9c1c | ||
|
|
30674711a7 | ||
|
|
3fc353fe04 | ||
|
|
c78637ae87 | ||
|
|
b7c1383f81 | ||
|
|
95d1e966fa | ||
|
|
5142883ed6 | ||
|
|
632b8ec501 | ||
|
|
d0094d3568 | ||
|
|
147eea686f | ||
|
|
caf7420309 | ||
|
|
e7a57dd653 | ||
|
|
ab94965186 | ||
|
|
ee0964b43a | ||
|
|
d0614586f2 | ||
|
|
f939ec8d32 | ||
|
|
f920d193eb | ||
|
|
e116aaf35c | ||
|
|
e2edbd9aea | ||
|
|
90e29f9fc9 | ||
|
|
c14b6cb95f | ||
|
|
368d4a5453 | ||
|
|
4c4db2a1c3 | ||
|
|
f22243ea3f | ||
|
|
45505ef3e1 | ||
|
|
ef9476e8fa | ||
|
|
298ab5550c | ||
|
|
754751559a | ||
|
|
75df48f09e | ||
|
|
fe5f183952 | ||
|
|
af2a0ffcbd | ||
|
|
3c2c44c11a | ||
|
|
9089feadc7 | ||
|
|
ba2ec32e15 | ||
|
|
d723de621d | ||
|
|
4d06850f1c | ||
|
|
fdfaf3bbf7 | ||
|
|
d71ea50d9a | ||
|
|
bcc765f15c | ||
|
|
453db78251 | ||
|
|
2bd0c07665 | ||
|
|
f4bdd49b0a | ||
|
|
43cf66c145 | ||
|
|
7bd572c230 | ||
|
|
552f0dd437 | ||
|
|
4dc6094473 | ||
|
|
7eecd12f82 | ||
|
|
8f61fe84ea | ||
|
|
5106524ed7 | ||
|
|
eeec9f38b9 | ||
|
|
ec773e02d6 | ||
|
|
f2f3399e67 | ||
|
|
8ab0db16d1 | ||
|
|
cef0be8d3b | ||
|
|
f78ad441fc | ||
|
|
cc485dfedb | ||
|
|
ade173ea11 | ||
|
|
b38764df3b | ||
|
|
a050833653 | ||
|
|
23f94b93b7 | ||
|
|
e82ad57df7 | ||
|
|
3672af57da | ||
|
|
a77a3bbccb | ||
|
|
54bc868931 | ||
|
|
e594525c7e | ||
|
|
b72f4be7e8 | ||
|
|
10d2b44145 | ||
|
|
2d94acf6a2 | ||
|
|
121d323ec2 | ||
|
|
a95bab83a3 | ||
|
|
69ae62db5b | ||
|
|
d36556a6de | ||
|
|
31c333af5d | ||
|
|
1fc396e2c1 | ||
|
|
2d99adc09a | ||
|
|
973f67b0f8 | ||
|
|
7f8f30241e | ||
|
|
a62dbe996f | ||
|
|
ece73f51e4 | ||
|
|
085c718712 | ||
|
|
9842cb5327 | ||
|
|
ac0bfa20b6 | ||
|
|
778257a379 | ||
|
|
56fb4f88bb | ||
|
|
dcb5a24c66 | ||
|
|
86e31de917 | ||
|
|
babe19b186 | ||
|
|
c7fead53ff | ||
|
|
b934c6165d | ||
|
|
234ebcba02 | ||
|
|
b8e789d665 | ||
|
|
6e788520d7 | ||
|
|
7feeefe552 | ||
|
|
7b4dd9ada8 | ||
|
|
6bb409814a | ||
|
|
34d3196c64 | ||
|
|
c1c2f65580 | ||
|
|
4439cabdbd | ||
|
|
36f0d47a77 | ||
|
|
6d63c5508e | ||
|
|
852040d107 | ||
|
|
db3c87b650 | ||
|
|
e79393b600 | ||
|
|
38d160c18a | ||
|
|
0401d0960b | ||
|
|
d10191f6ab | ||
|
|
bb9c183fb3 | ||
|
|
03e23fe9ba | ||
|
|
1c5ec09f9a | ||
|
|
d735f172be | ||
|
|
720d47d754 | ||
|
|
ef22a35461 | ||
|
|
1fea7f8abc | ||
|
|
c49ab35dab | ||
|
|
3536333904 | ||
|
|
e60b983cfe | ||
|
|
226796b113 | ||
|
|
53474e4ce7 | ||
|
|
6fcbbda66e | ||
|
|
42edab6de3 | ||
|
|
ae61830ec5 | ||
|
|
56dc1c51de | ||
|
|
b111a8b95d | ||
|
|
81ab993975 | ||
|
|
07618ceaf9 | ||
|
|
8a118cadfe | ||
|
|
6ebf0c6f24 | ||
|
|
d1cee63485 | ||
|
|
6b3d91e6b6 | ||
|
|
cddad3a3f0 | ||
|
|
cd088a4ce0 | ||
|
|
e94e2c0172 | ||
|
|
8a8af0d4af | ||
|
|
cfb3922705 | ||
|
|
3b6cba4f08 | ||
|
|
830674adc9 | ||
|
|
e164e26164 | ||
|
|
4e40b037cd | ||
|
|
fe84736f31 | ||
|
|
5950e00c10 | ||
|
|
fb6ff274ae | ||
|
|
e52e90fd79 | ||
|
|
86ae763d0e | ||
|
|
83edbca038 | ||
|
|
542dcc5dd4 | ||
|
|
b3fb369d89 | ||
|
|
53d3955d06 | ||
|
|
a3724498b5 | ||
|
|
0ca97ff587 | ||
|
|
744e0b3d66 | ||
|
|
f4efa23a5d | ||
|
|
dd88233151 | ||
|
|
fbfe3abffd | ||
|
|
cae1885c3a | ||
|
|
4f752a0677 | ||
|
|
6ea5783a3e | ||
|
|
7c643b6a80 | ||
|
|
ebb6f8f43c | ||
|
|
93151f62a6 | ||
|
|
798689d76d | ||
|
|
5808d8dcf3 | ||
|
|
5155891bfc | ||
|
|
17cbbefb68 | ||
|
|
4ee1e13365 | ||
|
|
53ad490ff8 | ||
|
|
527e9d2333 | ||
|
|
86c4a5e80c | ||
|
|
5fafb3bbcc | ||
|
|
4d1c0f7d3a | ||
|
|
7739f4315e | ||
|
|
50f4692c76 | ||
|
|
203ff03fdf | ||
|
|
af4ed12684 | ||
|
|
7d4304907c | ||
|
|
0bd0da7d7c | ||
|
|
6b5787753a | ||
|
|
8914ba161c | ||
|
|
8a39e196dc | ||
|
|
a2dda9c8b5 | ||
|
|
17d4201376 | ||
|
|
9266ba3539 | ||
|
|
1de08f3eeb | ||
|
|
ab5d58a6ed | ||
|
|
bb3471a1c2 | ||
|
|
87dfc5a6d7 | ||
|
|
84cf1b5a86 | ||
|
|
86095f81b8 | ||
|
|
0cd6da173c | ||
|
|
bb0ecbae30 | ||
|
|
29dfa9dc37 | ||
|
|
a23465353a | ||
|
|
0fc435d4a7 | ||
|
|
9770e8ecf4 | ||
|
|
24119e0aad | ||
|
|
b9c8300a72 | ||
|
|
88fcf2cce8 | ||
|
|
5e47a3a69d | ||
|
|
18ccfdb053 | ||
|
|
e428b35c42 | ||
|
|
95afc4374f | ||
|
|
6bcba9c489 | ||
|
|
3e75fccb1e | ||
|
|
46f22cdad7 | ||
|
|
1451bd491f | ||
|
|
b4eef3f699 | ||
|
|
7cfd4f7dda | ||
|
|
e29108b57b | ||
|
|
ff581e8224 | ||
|
|
779bcd31f5 | ||
|
|
8c4b389159 | ||
|
|
e1f190a985 | ||
|
|
8d26fa3f01 | ||
|
|
896d09837d | ||
|
|
e5c0008e1d | ||
|
|
e75f13c8b8 | ||
|
|
1282faf300 | ||
|
|
0e2bfbb2fa | ||
|
|
25f8e28734 | ||
|
|
e68b56ab45 | ||
|
|
4d14cb17b9 | ||
|
|
ca128c4cb8 | ||
|
|
d1acaabcb0 | ||
|
|
c24b392796 | ||
|
|
746644c849 | ||
|
|
739dd15abd | ||
|
|
dded39cb59 | ||
|
|
c755c5543d | ||
|
|
a293dbfae5 | ||
|
|
c2802b29d3 | ||
|
|
01325c074c | ||
|
|
412c6320da | ||
|
|
de75d71fea | ||
|
|
db2d3736bb | ||
|
|
c5a08b440e | ||
|
|
c5f970216d | ||
|
|
5053de80d1 | ||
|
|
19df0bd30f | ||
|
|
7a525a6d26 | ||
|
|
d30575bb9a | ||
|
|
89ffbccbdb | ||
|
|
cb3a4aedac | ||
|
|
56e31ce2ca | ||
|
|
9dfafd5fcc | ||
|
|
3fc3fe8912 | ||
|
|
b870b60808 | ||
|
|
3de50e3d3e | ||
|
|
9f9d78b9a8 | ||
|
|
dc7f200a6f | ||
|
|
3fee904db7 | ||
|
|
8ef76850e6 | ||
|
|
160274281b | ||
|
|
a8783cfbdb | ||
|
|
f5f2fc89e3 | ||
|
|
24318bf302 | ||
|
|
7e440cee6a | ||
|
|
705c563a94 | ||
|
|
0c1a9ad4eb | ||
|
|
2c49a74a95 | ||
|
|
45d0b0dcff | ||
|
|
4b2ce1ae85 | ||
|
|
4c3f2b416a | ||
|
|
794a81b485 | ||
|
|
78046d5ffd | ||
|
|
f7ac31d359 | ||
|
|
1770a8819b | ||
|
|
4f5b65ae35 | ||
|
|
31660cd1c8 | ||
|
|
d2bbba19f1 | ||
|
|
15a24f0247 | ||
|
|
791ef8738a | ||
|
|
5be88a649b | ||
|
|
d323696365 | ||
|
|
3ba690edcd | ||
|
|
18d1f2509f | ||
|
|
2e0f43b078 | ||
|
|
c37edd98a8 | ||
|
|
d283b1d094 | ||
|
|
7bafb06ed0 | ||
|
|
d9c0e707a7 | ||
|
|
ae99e976b6 | ||
|
|
f86799234d | ||
|
|
63bf452ff3 | ||
|
|
ef516e867e | ||
|
|
5968124299 | ||
|
|
bd3aefeb1b | ||
|
|
4c65c2c1e8 | ||
|
|
93cc27844c | ||
|
|
f37111f654 | ||
|
|
147a1096bd | ||
|
|
80c40f0bdf | ||
|
|
f623361e21 | ||
|
|
de730d4b57 | ||
|
|
b97d196482 | ||
|
|
8deb5d5dc0 | ||
|
|
69d09b580e | ||
|
|
290425a6f9 | ||
|
|
e9d2638c45 | ||
|
|
48091df93e | ||
|
|
d39737333b | ||
|
|
838bb19bf4 | ||
|
|
b07fed5393 | ||
|
|
8a19b3eb6c | ||
|
|
7638e7d8f6 | ||
|
|
d76aabff15 | ||
|
|
842905a7f4 | ||
|
|
a75b83a319 | ||
|
|
64ac33305c | ||
|
|
fe1531bd59 | ||
|
|
103c6ef44c | ||
|
|
1b696b1639 | ||
|
|
3734d076c9 | ||
|
|
eebea3c733 | ||
|
|
4be2ca4ba4 | ||
|
|
94038ebf03 | ||
|
|
6f46a25fca | ||
|
|
3235d4e648 | ||
|
|
54752d8b64 | ||
|
|
016f0dec71 | ||
|
|
0acb24ca65 | ||
|
|
86ca446701 | ||
|
|
aae8eb68a1 | ||
|
|
bc4056fa22 | ||
|
|
fa946f2128 | ||
|
|
2fc261a35d | ||
|
|
6824bbf5af | ||
|
|
5294745c2c | ||
|
|
0074d7cf0e | ||
|
|
00bf6e69f2 | ||
|
|
bdf3ce5512 | ||
|
|
7b0624e6f5 | ||
|
|
d0655589cc | ||
|
|
cbf4e8da8d | ||
|
|
ba5fac7308 | ||
|
|
6ab1fddda7 | ||
|
|
2842f713c0 | ||
|
|
475119f2a4 | ||
|
|
895617db00 | ||
|
|
0fb955e8cf | ||
|
|
98e769593e | ||
|
|
a2fc5bc2fb | ||
|
|
fca18fefef | ||
|
|
778f3828c4 | ||
|
|
211de42ea3 | ||
|
|
f5d83aa222 | ||
|
|
cbf6587e64 | ||
|
|
7ce14347fa | ||
|
|
03c38fff06 | ||
|
|
9ba9f28dd3 | ||
|
|
01f3507797 | ||
|
|
aa8f721891 | ||
|
|
6c2227effd | ||
|
|
9d6c5f11f2 | ||
|
|
48f8e7bb0c | ||
|
|
8206da4f50 | ||
|
|
328308c680 | ||
|
|
eefd0c15fc | ||
|
|
44b2e959b9 | ||
|
|
a0f2c5d60e | ||
|
|
79b6878e35 | ||
|
|
ab9c092806 | ||
|
|
e2d65f62b5 | ||
|
|
b6a25971d4 | ||
|
|
16f6049ade | ||
|
|
2a4a20c057 | ||
|
|
d02ead94fb | ||
|
|
ae05ec1842 | ||
|
|
f906ea83d5 | ||
|
|
ada154bd18 | ||
|
|
6bdb772e7b | ||
|
|
4d0b721966 | ||
|
|
b5ad775942 | ||
|
|
a824fb9915 | ||
|
|
3f4193844d | ||
|
|
3799f019fd | ||
|
|
4c29a9dde6 | ||
|
|
90cf3c54ef | ||
|
|
cb0eb8c5ff | ||
|
|
ef62e8aafc | ||
|
|
dad762956a | ||
|
|
bf682bdca8 | ||
|
|
d3a036f59f | ||
|
|
3010c0ab51 | ||
|
|
b844eb4e96 | ||
|
|
c3faa4ca41 | ||
|
|
9e9519566a | ||
|
|
64aa5cacdb | ||
|
|
efbf5051b0 | ||
|
|
5e66b1692d | ||
|
|
7b64c080f8 | ||
|
|
ad858e93da | ||
|
|
db83d3e8aa | ||
|
|
be16e53531 | ||
|
|
96812553b9 | ||
|
|
87029c4b12 | ||
|
|
22d402535d | ||
|
|
32de1a6ab5 | ||
|
|
35af3238d6 | ||
|
|
9659998eaf | ||
|
|
44f45b0203 | ||
|
|
595164f9b2 | ||
|
|
baf204a52f | ||
|
|
7cba2b2cfc | ||
|
|
3b94344b35 | ||
|
|
e7047891a7 | ||
|
|
24ba340bcb | ||
|
|
78bd720789 | ||
|
|
d940e36fdb | ||
|
|
8670e78d62 | ||
|
|
997186b626 | ||
|
|
318b506b70 | ||
|
|
d04b5a650b | ||
|
|
9f68f9cbb1 | ||
|
|
911b609927 | ||
|
|
d78d78cc46 | ||
|
|
2506938f7d | ||
|
|
49b0fe928c | ||
|
|
3a0ec0010c | ||
|
|
4d8da05e1c | ||
|
|
f9d6f26037 | ||
|
|
4a2bdc3d0e | ||
|
|
a97e5726e2 | ||
|
|
cdcd669919 | ||
|
|
b6cd2cf472 | ||
|
|
33de2b6256 | ||
|
|
209d715a4a | ||
|
|
cb6854bc5c | ||
|
|
377d13adcb | ||
|
|
888c98dfae | ||
|
|
3c6ef3a0f4 | ||
|
|
e9d4680a8e | ||
|
|
ed3e10a9c1 | ||
|
|
1e5f814cb0 | ||
|
|
0986298ac9 | ||
|
|
dde7012708 | ||
|
|
2bf4394176 | ||
|
|
edd80635d2 | ||
|
|
b056551406 | ||
|
|
00741613b1 | ||
|
|
f1c559f91f | ||
|
|
c4551d98e3 | ||
|
|
46ad8367ff | ||
|
|
974dbc4a3b | ||
|
|
5f809e5c11 | ||
|
|
3b57f26713 | ||
|
|
4fd53c6c6d | ||
|
|
02fad3997c | ||
|
|
ba276b03c0 | ||
|
|
34145d36a7 | ||
|
|
250e3ba9bc | ||
|
|
368d0eba12 | ||
|
|
b6159bfbbc | ||
|
|
03c9981d95 | ||
|
|
c0d3d0d3ad | ||
|
|
a2e1e01539 | ||
|
|
a090a632c4 | ||
|
|
e62255f3c9 | ||
|
|
269ebb10fc | ||
|
|
b98eded6f3 | ||
|
|
a35c768b3b | ||
|
|
eaf4ec6211 | ||
|
|
340f4857ed | ||
|
|
a07820e722 | ||
|
|
6d46bf7151 | ||
|
|
9fe9d70449 | ||
|
|
8cf43bffad | ||
|
|
93f333e767 | ||
|
|
55fee99ae5 | ||
|
|
abfc476cde | ||
|
|
edb298e0d5 | ||
|
|
338c91b611 | ||
|
|
13ed2d60b3 | ||
|
|
ae8fcddb2f | ||
|
|
de11bfcbec | ||
|
|
d25ede611d | ||
|
|
efda3e7323 | ||
|
|
dd62cdcdac | ||
|
|
873312a2a6 | ||
|
|
9814c885d9 | ||
|
|
394bec9ff6 | ||
|
|
4a8e647083 | ||
|
|
006bce80aa | ||
|
|
cdacadb95d | ||
|
|
d0e0982dcd | ||
|
|
0e97f5d803 | ||
|
|
3ae0e91ba6 | ||
|
|
4480b81120 | ||
|
|
f6450c13b5 | ||
|
|
c6bdf9bab7 | ||
|
|
978922ef91 | ||
|
|
9b3f73eb45 | ||
|
|
43e0fdf7b4 | ||
|
|
59c11985c8 | ||
|
|
10519abe00 | ||
|
|
dbe733bf7e | ||
|
|
2e7dfcfc31 | ||
|
|
fdcd19df79 | ||
|
|
6bf56f20ee | ||
|
|
fe94791a09 | ||
|
|
6d84d5931b | ||
|
|
2f8541c472 | ||
|
|
156c63fc4f | ||
|
|
f67fda31a0 | ||
|
|
d31fdc0ec3 | ||
|
|
be24e191d2 | ||
|
|
15405812e3 | ||
|
|
c4d6ae37ee | ||
|
|
311d7d016e | ||
|
|
5ad7d68d8b | ||
|
|
964859fb2d | ||
|
|
bb74c38f6e | ||
|
|
b3a2affbaf | ||
|
|
33295db191 | ||
|
|
daa0f5f33a | ||
|
|
3ab230a9e7 | ||
|
|
49cfcd96c2 | ||
|
|
9bdceef101 | ||
|
|
da9870abfc | ||
|
|
0348064f6c | ||
|
|
2773821fb2 | ||
|
|
d60296b463 | ||
|
|
46b4f2e25b | ||
|
|
40761ace1f | ||
|
|
8e6794daa7 |
|
|
@ -4,6 +4,9 @@
|
|||
**/traces
|
||||
**/inputs
|
||||
**/har
|
||||
**/downloads
|
||||
**/browser_sessions
|
||||
**/credential_vault
|
||||
**/.git
|
||||
**/.github
|
||||
**/.mypy_cache
|
||||
|
|
|
|||
46
.env.example
|
|
@ -86,8 +86,9 @@ YUTORI_TOOL_SET=""
|
|||
|
||||
# LLM_KEY: The chosen language model to use. This should be one of the models
|
||||
# provided by the enabled LLM providers (e.g., OPENAI_GPT5_5, OPENAI_GPT5_4,
|
||||
# ANTHROPIC_CLAUDE4.7_OPUS, ANTHROPIC_CLAUDE4.6_SONNET, GEMINI_3_PRO,
|
||||
# BEDROCK_ANTHROPIC_CLAUDE4.7_OPUS_INFERENCE_PROFILE).
|
||||
# ANTHROPIC_CLAUDE5_FABLE, ANTHROPIC_CLAUDE4.7_OPUS, ANTHROPIC_CLAUDE4.6_SONNET,
|
||||
# GEMINI_3_PRO, BEDROCK_ANTHROPIC_CLAUDE5_FABLE_INFERENCE_PROFILE,
|
||||
# BEDROCK_ANTHROPIC_CLAUDE5_FABLE_WITH_FALLBACK).
|
||||
# See docs: https://www.skyvern.com/docs/self-hosted/llm-configuration
|
||||
LLM_KEY=""
|
||||
# a cheaper LLM providers to help finishing some small tasks, like custom selection or svg conversion. If empty, it will be the same as LLM_KEY
|
||||
|
|
@ -138,12 +139,29 @@ ANALYTICS_ID="anonymous"
|
|||
# OP_SERVICE_ACCOUNT_TOKEN: API token for 1Password integration
|
||||
OP_SERVICE_ACCOUNT_TOKEN=""
|
||||
|
||||
# =============================================================================
|
||||
# SKYVERN CREDENTIAL VAULT CONFIGURATION
|
||||
# =============================================================================
|
||||
# Built-in encrypted local vault used by default by the OSS Docker Compose setup.
|
||||
# Docker also sets ENABLE_LOCAL_CREDENTIAL_VAULT=true and persists this under /data/credential_vault.
|
||||
CREDENTIAL_VAULT_TYPE=skyvern
|
||||
ENABLE_LOCAL_CREDENTIAL_VAULT=true
|
||||
# LOCAL_CREDENTIAL_VAULT_PATH=/data/credential_vault
|
||||
# Production self-hosters should set LOCAL_CREDENTIAL_VAULT_KEY from an external secret store.
|
||||
# If unset, Skyvern generates .fernet_key inside LOCAL_CREDENTIAL_VAULT_PATH; backups or host-dir
|
||||
# exposure of that directory include both encrypted items and the key needed to decrypt them.
|
||||
# LOCAL_CREDENTIAL_VAULT_KEY=
|
||||
# The OSS Docker volumes for browser_sessions/ and downloads/ can contain plaintext cookies,
|
||||
# session tokens, and downloaded files. Treat them as sensitive and exclude them from casual backups.
|
||||
|
||||
# Enable recording skyvern logs as artifacts
|
||||
ENABLE_LOG_ARTIFACTS=false
|
||||
|
||||
# =============================================================================
|
||||
# SKYVERN BITWARDEN CONFIGURATION
|
||||
# =============================================================================
|
||||
# Set CREDENTIAL_VAULT_TYPE=bitwarden to use Bitwarden or vaultwarden instead
|
||||
# of the built-in Skyvern credential vault.
|
||||
# Your organization ID in official Bitwarden server or vaultwarden (if using organizations)
|
||||
SKYVERN_AUTH_BITWARDEN_ORGANIZATION_ID=your-org-id-here
|
||||
|
||||
|
|
@ -178,3 +196,27 @@ SKYVERN_AUTH_BITWARDEN_CLIENT_SECRET=your-client-secret-here
|
|||
# Optional: override Redis URL specifically for notifications (falls back to REDIS_URL)
|
||||
# NOTIFICATION_REDIS_URL=
|
||||
# REDIS_URL=redis://localhost:6379/0
|
||||
|
||||
# =============================================================================
|
||||
# OPTIONAL: GCP SELF-HOSTED DEPLOYMENT
|
||||
# =============================================================================
|
||||
# Uncomment to run Skyvern on Google Cloud with GCS storage and Secret Manager
|
||||
# credentials. Auth uses Application Default Credentials (Workload Identity on
|
||||
# GKE, or GOOGLE_APPLICATION_CREDENTIALS pointing at a service-account key).
|
||||
|
||||
# Store artifacts/screenshots/browser sessions/uploads in Google Cloud Storage
|
||||
# SKYVERN_STORAGE_TYPE=gcs
|
||||
# GCS_PROJECT_ID=your-gcp-project-id
|
||||
# GCS_BUCKET_ARTIFACTS=skyvern-artifacts
|
||||
# GCS_BUCKET_SCREENSHOTS=skyvern-screenshots
|
||||
# GCS_BUCKET_BROWSER_SESSIONS=skyvern-browser-sessions
|
||||
# GCS_BUCKET_UPLOADS=skyvern-uploads
|
||||
# Service account that signs GCS download URLs; required only under Workload
|
||||
# Identity, where the runtime SA has no signing key of its own.
|
||||
# GCS_SIGNER_SA_EMAIL=skyvern@your-gcp-project-id.iam.gserviceaccount.com
|
||||
|
||||
# Store workflow credentials in GCP Secret Manager instead of Bitwarden
|
||||
# CREDENTIAL_VAULT_TYPE=gcp
|
||||
# GCP_CREDENTIAL_VAULT_PROJECT_ID=your-gcp-project-id
|
||||
# Secret-id prefix; must be unique per Skyvern deployment sharing a project
|
||||
# GCP_CREDENTIAL_VAULT_PREFIX=skyvern-cred-
|
||||
|
|
|
|||
43
.github/workflows/sdk-release.yml
vendored
|
|
@ -12,37 +12,53 @@ jobs:
|
|||
check-version-change:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version_changed: ${{ steps.check.outputs.version_changed }}
|
||||
should_publish: ${{ steps.check.outputs.should_publish }}
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
persist-credentials: false
|
||||
- name: Check if version changed
|
||||
- name: Decide whether to publish
|
||||
id: check
|
||||
run: |
|
||||
# Get version from current pyproject.toml
|
||||
# Compare current vs previous commit, AND check PyPI for the new version.
|
||||
# Without the PyPI check, reverts (1.0.37 -> 1.0.36) and re-bumps after a
|
||||
# revert (1.0.36 -> 1.0.37, where 1.0.37 was already published) both look
|
||||
# like "version changed" and crash the publish step with HTTP 400.
|
||||
CURRENT_VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
|
||||
|
||||
# Get version from previous commit
|
||||
git checkout HEAD^1
|
||||
PREVIOUS_VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
|
||||
|
||||
if [ "$CURRENT_VERSION" != "$PREVIOUS_VERSION" ]; then
|
||||
echo "Version changed from $PREVIOUS_VERSION to $CURRENT_VERSION"
|
||||
echo "version_changed=true" >> $GITHUB_OUTPUT
|
||||
if [ "$CURRENT_VERSION" = "$PREVIOUS_VERSION" ]; then
|
||||
echo "Version unchanged at $CURRENT_VERSION; skipping publish."
|
||||
echo "should_publish=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
echo "Version changed from $PREVIOUS_VERSION to $CURRENT_VERSION."
|
||||
|
||||
# Treat both skyvern and skyvern-ui as already-published only if both
|
||||
# are present on PyPI at the new version. If either is missing (e.g.
|
||||
# the first release of a new sibling package), proceed.
|
||||
PYPI_INDEX="https://pypi.org/pypi"
|
||||
SKYVERN_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$PYPI_INDEX/skyvern/$CURRENT_VERSION/json")
|
||||
SKYVERN_UI_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$PYPI_INDEX/skyvern-ui/$CURRENT_VERSION/json")
|
||||
echo "PyPI lookup: skyvern=$SKYVERN_STATUS skyvern-ui=$SKYVERN_UI_STATUS"
|
||||
|
||||
if [ "$SKYVERN_STATUS" = "200" ] && [ "$SKYVERN_UI_STATUS" = "200" ]; then
|
||||
echo "Both packages already at $CURRENT_VERSION on PyPI; skipping publish."
|
||||
echo "should_publish=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Version remained at $CURRENT_VERSION"
|
||||
echo "version_changed=false" >> $GITHUB_OUTPUT
|
||||
echo "should_publish=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
run-ci:
|
||||
needs: check-version-change
|
||||
if: needs.check-version-change.outputs.version_changed == 'true'
|
||||
if: needs.check-version-change.outputs.should_publish == 'true'
|
||||
uses: ./.github/workflows/ci.yml
|
||||
build-sdk:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-version-change, run-ci]
|
||||
if: needs.check-version-change.outputs.version_changed == 'true'
|
||||
if: needs.check-version-change.outputs.should_publish == 'true'
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
|
@ -123,7 +139,12 @@ jobs:
|
|||
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
|
||||
with:
|
||||
packages-dir: dist/skyvern-ui/
|
||||
# Defense-in-depth: if check-version-change ever misses an edge case
|
||||
# (e.g. half-published release where one sibling landed), skip files
|
||||
# already on PyPI rather than failing the whole publish step.
|
||||
skip-existing: true
|
||||
- name: Publish skyvern to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
|
||||
with:
|
||||
packages-dir: dist/skyvern/
|
||||
skip-existing: true
|
||||
|
|
|
|||
2
.gitignore
vendored
|
|
@ -162,6 +162,7 @@ ig_*
|
|||
|
||||
# Skyvern ignores
|
||||
browser_sessions/
|
||||
credential_vault/
|
||||
videos/
|
||||
skyvern/artifacts/
|
||||
artifacts/
|
||||
|
|
@ -189,6 +190,7 @@ tags.temp.tmp
|
|||
|
||||
# copy of Chrome user profile from Chrome >= 136
|
||||
tmp/user_data_dir
|
||||
tmp/
|
||||
|
||||
# Claude
|
||||
.claude/*
|
||||
|
|
|
|||
|
|
@ -132,3 +132,6 @@ repos:
|
|||
rev: v0.17.2
|
||||
hooks:
|
||||
- id: yamlfmt
|
||||
# Helm chart templates contain Go templating ({{ ... }}) and are not
|
||||
# valid standalone YAML, so yamlfmt cannot parse them.
|
||||
exclude: ^k8s/charts/.*/templates/
|
||||
|
|
|
|||
12
Dockerfile
|
|
@ -11,6 +11,7 @@ RUN uv pip compile pyproject.toml --extra server --python-version 3.11 -o requir
|
|||
FROM python:3.11-slim-bookworm
|
||||
WORKDIR /app
|
||||
COPY --from=requirements-stage /tmp/requirements.txt /app/requirements.txt
|
||||
COPY ./skyvern/forge/sdk/utils/tesseract_languages.py /tmp/tesseract_languages.py
|
||||
RUN pip install --upgrade pip setuptools wheel
|
||||
# --no-deps: requirements.txt is fully resolved by uv, including the
|
||||
# pyproject overrides that loosen litellm's jsonschema==4.23.0 pin.
|
||||
|
|
@ -18,7 +19,13 @@ RUN pip install --upgrade pip setuptools wheel
|
|||
RUN pip install --no-cache-dir --no-deps -r requirements.txt
|
||||
RUN playwright install-deps
|
||||
RUN playwright install
|
||||
RUN apt-get install -y xauth x11-apps netpbm gpg ca-certificates x11vnc && apt-get clean
|
||||
RUN apt-get update && \
|
||||
apt-get install -y xauth x11-apps netpbm gpg ca-certificates x11vnc tesseract-ocr $(python /tmp/tesseract_languages.py --apt-packages) && \
|
||||
tesseract --version && \
|
||||
rm /tmp/tesseract_languages.py && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pip install --no-cache-dir websockify
|
||||
|
||||
COPY .nvmrc /app/.nvmrc
|
||||
|
|
@ -47,6 +54,9 @@ ENV VIDEO_PATH=/data/videos
|
|||
ENV HAR_PATH=/data/har
|
||||
ENV LOG_PATH=/data/log
|
||||
ENV ARTIFACT_STORAGE_PATH=/data/artifacts
|
||||
ENV DOWNLOAD_PATH=/data/downloads
|
||||
ENV BROWSER_SESSION_BASE_PATH=/data/browser_sessions
|
||||
ENV LOCAL_CREDENTIAL_VAULT_PATH=/data/credential_vault
|
||||
|
||||
# cache tiktoken
|
||||
RUN python /app/scripts/load_tiktoken.py
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
"""add workflow_copilot_completion_criteria_sets table
|
||||
|
||||
Revision ID: 218048b68412
|
||||
Revises: a8c4e2f9d6b1
|
||||
Create Date: 2026-06-14T22:21:36.243898+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "218048b68412"
|
||||
down_revision: Union[str, None] = "a8c4e2f9d6b1"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
_TABLE = "workflow_copilot_completion_criteria_sets"
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
conn = op.get_bind()
|
||||
inspector = sa.inspect(conn)
|
||||
if inspector.has_table(_TABLE):
|
||||
return
|
||||
|
||||
if conn.dialect.name == "postgresql":
|
||||
op.execute(sa.text("SET lock_timeout = '2s'"))
|
||||
|
||||
op.create_table(
|
||||
_TABLE,
|
||||
sa.Column("completion_criteria_set_id", sa.String(), nullable=False),
|
||||
sa.Column("organization_id", sa.String(), nullable=False),
|
||||
sa.Column("workflow_copilot_chat_id", sa.String(), nullable=False),
|
||||
sa.Column("goal_epoch", sa.Integer(), nullable=False),
|
||||
sa.Column("status", sa.String(), nullable=False),
|
||||
sa.Column("criteria", sa.JSON(), nullable=False),
|
||||
sa.Column("source_turn_id", sa.String(), nullable=True),
|
||||
sa.Column("source_goal_text", sa.UnicodeText(), nullable=True),
|
||||
sa.Column("consecutive_all_no_evidence", sa.Integer(), nullable=False),
|
||||
sa.Column("tripwire_fired", sa.Boolean(), nullable=False),
|
||||
sa.Column("last_fully_satisfied_workflow_yaml", sa.UnicodeText(), nullable=True),
|
||||
sa.Column("superseded_by_set_id", sa.String(), nullable=True),
|
||||
sa.Column("superseded_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("supersede_reason", sa.String(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("modified_at", sa.DateTime(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("completion_criteria_set_id"),
|
||||
)
|
||||
op.create_index("wcccs_org_chat_index", _TABLE, ["organization_id", "workflow_copilot_chat_id"])
|
||||
|
||||
if conn.dialect.name == "postgresql":
|
||||
op.execute(sa.text("SET lock_timeout = '0'"))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
conn = op.get_bind()
|
||||
inspector = sa.inspect(conn)
|
||||
if not inspector.has_table(_TABLE):
|
||||
return
|
||||
op.drop_index("wcccs_org_chat_index", table_name=_TABLE)
|
||||
op.drop_table(_TABLE)
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
"""add sequential_key lookup index on workflow_runs
|
||||
|
||||
Revision ID: cfc2318acdf9
|
||||
Revises: 218048b68412
|
||||
Create Date: 2026-06-16T08:03:01.419039+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "cfc2318acdf9"
|
||||
down_revision: Union[str, None] = "218048b68412"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
with op.get_context().autocommit_block():
|
||||
op.execute("SET statement_timeout = '24h';")
|
||||
op.execute("""
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS ix_workflow_runs_sequential_key_lookup
|
||||
ON workflow_runs (workflow_permanent_id, sequential_key, queued_at)
|
||||
WHERE status IN ('queued', 'running', 'paused') AND browser_session_id IS NULL
|
||||
""")
|
||||
op.execute("RESET statement_timeout;")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
with op.get_context().autocommit_block():
|
||||
op.execute("DROP INDEX CONCURRENTLY IF EXISTS ix_workflow_runs_sequential_key_lookup")
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
"""add browser_profile_loaded to persistent_browser_sessions
|
||||
|
||||
Revision ID: 1fee32b3d7c6
|
||||
Revises: cfc2318acdf9
|
||||
Create Date: 2026-06-16T12:53:28.144752+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "1fee32b3d7c6"
|
||||
down_revision: Union[str, None] = "cfc2318acdf9"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"persistent_browser_sessions",
|
||||
sa.Column("browser_profile_loaded", sa.Boolean(), server_default=sa.true(), nullable=False),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("persistent_browser_sessions", "browser_profile_loaded")
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
"""add downloaded_file_count to workflow_run_blocks
|
||||
|
||||
Revision ID: 58b0ced36529
|
||||
Revises: 1fee32b3d7c6
|
||||
Create Date: 2026-06-19T20:44:46.548990+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "58b0ced36529"
|
||||
down_revision: Union[str, None] = "1fee32b3d7c6"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.execute("SET LOCAL lock_timeout = '5s'")
|
||||
op.add_column("workflow_run_blocks", sa.Column("downloaded_file_count", sa.Integer(), nullable=True))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("workflow_run_blocks", "downloaded_file_count")
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
"""add copilot chat history indexes
|
||||
|
||||
Revision ID: 61c9acf9f3ba
|
||||
Revises: 58b0ced36529
|
||||
Create Date: 2026-06-22 11:22:49.851792+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "61c9acf9f3ba"
|
||||
down_revision: Union[str, None] = "58b0ced36529"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
with op.get_context().autocommit_block():
|
||||
op.execute("SET statement_timeout = '1h';")
|
||||
op.execute("""
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS wccm_org_chat_index
|
||||
ON workflow_copilot_chat_messages (organization_id, workflow_copilot_chat_id);
|
||||
""")
|
||||
op.execute("""
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS wcc_org_created_at_index
|
||||
ON workflow_copilot_chats (organization_id, created_at);
|
||||
""")
|
||||
op.execute("RESET statement_timeout;")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
with op.get_context().autocommit_block():
|
||||
op.execute("DROP INDEX CONCURRENTLY IF EXISTS wccm_org_chat_index;")
|
||||
op.execute("DROP INDEX CONCURRENTLY IF EXISTS wcc_org_created_at_index;")
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
"""add tag values table
|
||||
|
||||
Revision ID: 2c76348b4e7a
|
||||
Revises: 61c9acf9f3ba
|
||||
Create Date: 2026-06-24T16:30:09.366617+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "2c76348b4e7a"
|
||||
down_revision: Union[str, None] = "61c9acf9f3ba"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_table(
|
||||
"tag_values",
|
||||
sa.Column("tag_value_id", sa.String(), nullable=False),
|
||||
sa.Column("organization_id", sa.String(), nullable=False),
|
||||
sa.Column("key", sa.String(), nullable=False),
|
||||
sa.Column("value", sa.String(), nullable=False),
|
||||
sa.Column("color", sa.String(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("modified_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("deleted_at", sa.DateTime(), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
["organization_id"],
|
||||
["organizations.organization_id"],
|
||||
),
|
||||
sa.PrimaryKeyConstraint("tag_value_id"),
|
||||
)
|
||||
op.create_index(
|
||||
"ix_tag_values_org_key_value_active",
|
||||
"tag_values",
|
||||
["organization_id", "key", "value"],
|
||||
unique=True,
|
||||
postgresql_where=sa.text("deleted_at IS NULL"),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index(
|
||||
"ix_tag_values_org_key_value_active",
|
||||
table_name="tag_values",
|
||||
postgresql_where=sa.text("deleted_at IS NULL"),
|
||||
)
|
||||
op.drop_table("tag_values")
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
"""add browser_profile_key to workflows
|
||||
|
||||
Revision ID: 45128d67bc1a
|
||||
Revises: 2c76348b4e7a
|
||||
Create Date: 2026-06-25T00:17:17.827852+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "45128d67bc1a"
|
||||
down_revision: Union[str, None] = "2c76348b4e7a"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column("workflows", sa.Column("browser_profile_key", sa.String(), nullable=True))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("workflows", "browser_profile_key")
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
"""add proxy pin fields
|
||||
|
||||
Revision ID: a1cad008154a
|
||||
Revises: 45128d67bc1a
|
||||
Create Date: 2026-06-26T19:26:11.232122+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "a1cad008154a"
|
||||
down_revision: Union[str, None] = "45128d67bc1a"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.execute("SET LOCAL lock_timeout = '5s'")
|
||||
op.add_column("credentials", sa.Column("proxy_location", sa.String(), nullable=True))
|
||||
op.add_column("credentials", sa.Column("proxy_session_id", sa.String(), nullable=True))
|
||||
op.add_column("browser_profiles", sa.Column("proxy_location", sa.String(), nullable=True))
|
||||
op.add_column("browser_profiles", sa.Column("proxy_session_id", sa.String(), nullable=True))
|
||||
op.add_column("persistent_browser_sessions", sa.Column("proxy_session_id", sa.String(), nullable=True))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("persistent_browser_sessions", "proxy_session_id")
|
||||
op.drop_column("browser_profiles", "proxy_session_id")
|
||||
op.drop_column("browser_profiles", "proxy_location")
|
||||
op.drop_column("credentials", "proxy_session_id")
|
||||
op.drop_column("credentials", "proxy_location")
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
"""managed browser profiles for save and reuse session
|
||||
|
||||
Revision ID: ecf365563e98
|
||||
Revises: a1cad008154a
|
||||
Create Date: 2026-07-02T23:17:33.611632+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "ecf365563e98"
|
||||
down_revision: Union[str, None] = "a1cad008154a"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"browser_profiles",
|
||||
sa.Column("is_managed", sa.Boolean(), server_default=sa.text("false"), nullable=False),
|
||||
)
|
||||
op.add_column("browser_profiles", sa.Column("workflow_permanent_id", sa.String(), nullable=True))
|
||||
op.add_column("browser_profiles", sa.Column("browser_profile_key_digest", sa.String(), nullable=True))
|
||||
op.create_index(
|
||||
"uq_browser_profiles_org_name_user",
|
||||
"browser_profiles",
|
||||
["organization_id", "name"],
|
||||
unique=True,
|
||||
postgresql_where=sa.text("is_managed = false"),
|
||||
sqlite_where=sa.text("is_managed = false"),
|
||||
)
|
||||
op.create_index(
|
||||
"uq_browser_profiles_managed_segment",
|
||||
"browser_profiles",
|
||||
["organization_id", "workflow_permanent_id", "browser_profile_key_digest"],
|
||||
unique=True,
|
||||
# Exclude soft-deleted rows so deleting a managed profile doesn't tombstone the
|
||||
# segment — the next run re-creates it instead of colliding on the unique key.
|
||||
postgresql_where=sa.text("is_managed = true AND deleted_at IS NULL"),
|
||||
sqlite_where=sa.text("is_managed = true AND deleted_at IS NULL"),
|
||||
)
|
||||
op.create_index("idx_browser_profiles_wpid", "browser_profiles", ["workflow_permanent_id"], unique=False)
|
||||
op.drop_constraint("uc_org_browser_profile_name", "browser_profiles", type_="unique")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.execute("DELETE FROM browser_profiles WHERE is_managed = true")
|
||||
op.create_unique_constraint("uc_org_browser_profile_name", "browser_profiles", ["organization_id", "name"])
|
||||
op.drop_index("idx_browser_profiles_wpid", table_name="browser_profiles")
|
||||
op.drop_index(
|
||||
"uq_browser_profiles_managed_segment",
|
||||
table_name="browser_profiles",
|
||||
postgresql_where=sa.text("is_managed = true AND deleted_at IS NULL"),
|
||||
)
|
||||
op.drop_index(
|
||||
"uq_browser_profiles_org_name_user",
|
||||
table_name="browser_profiles",
|
||||
postgresql_where=sa.text("is_managed = false"),
|
||||
)
|
||||
op.drop_column("browser_profiles", "browser_profile_key_digest")
|
||||
op.drop_column("browser_profiles", "workflow_permanent_id")
|
||||
op.drop_column("browser_profiles", "is_managed")
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
"""add enable_self_healing to workflows
|
||||
|
||||
Revision ID: 2ac47bc1c075
|
||||
Revises: ecf365563e98
|
||||
Create Date: 2026-07-03T03:33:20.863940+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "2ac47bc1c075"
|
||||
down_revision: Union[str, None] = "ecf365563e98"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"workflows",
|
||||
sa.Column("enable_self_healing", sa.Boolean(), nullable=False, server_default=sa.false()),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("workflows", "enable_self_healing")
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
"""add workflow run credential selections
|
||||
|
||||
Revision ID: aff1632dc377
|
||||
Revises: 2ac47bc1c075
|
||||
Create Date: 2026-07-03T18:53:23.324057+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "aff1632dc377"
|
||||
down_revision: Union[str, None] = "2ac47bc1c075"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column("credential_parameters", sa.Column("credential_ids", sa.JSON(), nullable=True))
|
||||
op.add_column("credential_parameters", sa.Column("selection_strategy", sa.String(), nullable=True))
|
||||
op.create_table(
|
||||
"workflow_run_credential_selections",
|
||||
sa.Column("selection_id", sa.String(), nullable=False),
|
||||
sa.Column("organization_id", sa.String(), nullable=False),
|
||||
sa.Column("workflow_run_id", sa.String(), nullable=False),
|
||||
sa.Column("workflow_permanent_id", sa.String(), nullable=False),
|
||||
sa.Column("parameter_key", sa.String(), nullable=False),
|
||||
sa.Column("credential_id", sa.String(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("selection_id"),
|
||||
sa.UniqueConstraint("workflow_run_id", "parameter_key", name="uq_wrcs_workflow_run_parameter_key"),
|
||||
)
|
||||
op.create_index(
|
||||
"idx_wrcs_lru_lookup",
|
||||
"workflow_run_credential_selections",
|
||||
["organization_id", "workflow_permanent_id", "parameter_key", "credential_id", "created_at"],
|
||||
unique=False,
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index("idx_wrcs_lru_lookup", table_name="workflow_run_credential_selections")
|
||||
op.drop_table("workflow_run_credential_selections")
|
||||
op.drop_column("credential_parameters", "selection_strategy")
|
||||
op.drop_column("credential_parameters", "credential_ids")
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
"""browser profile name unique partial on deleted_at
|
||||
|
||||
Revision ID: e2d87251fee8
|
||||
Revises: aff1632dc377
|
||||
Create Date: 2026-07-07T15:35:51.042177+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "e2d87251fee8"
|
||||
down_revision: Union[str, None] = "aff1632dc377"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.drop_index(
|
||||
"uq_browser_profiles_org_name_user",
|
||||
table_name="browser_profiles",
|
||||
postgresql_where=sa.text("is_managed = false"),
|
||||
)
|
||||
op.create_index(
|
||||
"uq_browser_profiles_org_name_user",
|
||||
"browser_profiles",
|
||||
["organization_id", "name"],
|
||||
unique=True,
|
||||
postgresql_where=sa.text("is_managed = false AND deleted_at IS NULL"),
|
||||
sqlite_where=sa.text("is_managed = false AND deleted_at IS NULL"),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index(
|
||||
"uq_browser_profiles_org_name_user",
|
||||
table_name="browser_profiles",
|
||||
postgresql_where=sa.text("is_managed = false AND deleted_at IS NULL"),
|
||||
)
|
||||
op.create_index(
|
||||
"uq_browser_profiles_org_name_user",
|
||||
"browser_profiles",
|
||||
["organization_id", "name"],
|
||||
unique=True,
|
||||
postgresql_where=sa.text("is_managed = false"),
|
||||
sqlite_where=sa.text("is_managed = false"),
|
||||
)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
"""add pin_saved_session_ip to workflows
|
||||
|
||||
Revision ID: 5b618ec6dce6
|
||||
Revises: e2d87251fee8
|
||||
Create Date: 2026-07-07T21:21:37.964227+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "5b618ec6dce6"
|
||||
down_revision: Union[str, None] = "e2d87251fee8"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.execute("SET LOCAL lock_timeout = '5s'")
|
||||
op.add_column(
|
||||
"workflows",
|
||||
sa.Column("pin_saved_session_ip", sa.Boolean(), nullable=False, server_default=sa.false()),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("workflows", "pin_saved_session_ip")
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
"""add workflow run tag events table
|
||||
|
||||
Revision ID: bec06d149264
|
||||
Revises: 5b618ec6dce6
|
||||
Create Date: 2026-07-08T17:54:31.712270+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "bec06d149264"
|
||||
down_revision: Union[str, None] = "5b618ec6dce6"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_table(
|
||||
"workflow_run_tag_events",
|
||||
sa.Column("tag_event_id", sa.String(), nullable=False),
|
||||
sa.Column("workflow_run_id", sa.String(), nullable=False),
|
||||
sa.Column("organization_id", sa.String(), nullable=False),
|
||||
sa.Column("key", sa.String(), nullable=True),
|
||||
sa.Column("value", sa.String(), nullable=True),
|
||||
sa.Column("event_type", sa.String(), nullable=False),
|
||||
sa.Column("set_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("set_by", sa.String(), nullable=False),
|
||||
sa.Column("source", sa.String(), nullable=False),
|
||||
sa.Column("caller_type", sa.String(), nullable=True),
|
||||
sa.Column("superseded_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("inherited_from_tag_event_id", sa.String(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("modified_at", sa.DateTime(), nullable=False),
|
||||
sa.CheckConstraint("event_type IN ('set', 'delete')", name="ck_workflow_run_tag_events_event_type"),
|
||||
sa.CheckConstraint(
|
||||
"source IN ('manual', 'bulk_apply', 'backfill', 'inherited', 'import', 'system')",
|
||||
name="ck_workflow_run_tag_events_source",
|
||||
),
|
||||
sa.CheckConstraint(
|
||||
"caller_type IS NULL OR caller_type IN ('user', 'api_key', 'system')",
|
||||
name="ck_workflow_run_tag_events_caller_type",
|
||||
),
|
||||
sa.CheckConstraint(
|
||||
"event_type != 'set' OR value IS NOT NULL",
|
||||
name="ck_workflow_run_tag_events_set_has_value",
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["workflow_run_id"],
|
||||
["workflow_runs.workflow_run_id"],
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["organization_id"],
|
||||
["organizations.organization_id"],
|
||||
),
|
||||
sa.PrimaryKeyConstraint("tag_event_id"),
|
||||
)
|
||||
op.create_index(
|
||||
"workflow_run_tag_events_org_wr_set_at_idx",
|
||||
"workflow_run_tag_events",
|
||||
["organization_id", "workflow_run_id", "set_at"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
"workflow_run_tag_events_org_key_value_active_idx",
|
||||
"workflow_run_tag_events",
|
||||
["organization_id", "key", "value"],
|
||||
unique=False,
|
||||
postgresql_include=["workflow_run_id"],
|
||||
postgresql_where=sa.text("superseded_at IS NULL AND event_type = 'set'"),
|
||||
)
|
||||
op.create_index(
|
||||
"workflow_run_tag_events_org_value_active_idx",
|
||||
"workflow_run_tag_events",
|
||||
["organization_id", "value"],
|
||||
unique=False,
|
||||
postgresql_include=["workflow_run_id"],
|
||||
postgresql_where=sa.text("superseded_at IS NULL AND event_type = 'set'"),
|
||||
)
|
||||
op.create_index(
|
||||
"workflow_run_tag_events_org_set_at_idx",
|
||||
"workflow_run_tag_events",
|
||||
["organization_id", "set_at"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
"workflow_run_tag_events_active_grouped_unique",
|
||||
"workflow_run_tag_events",
|
||||
["organization_id", "workflow_run_id", "key"],
|
||||
unique=True,
|
||||
postgresql_where=sa.text("superseded_at IS NULL AND event_type = 'set' AND key IS NOT NULL"),
|
||||
sqlite_where=sa.text("superseded_at IS NULL AND event_type = 'set' AND key IS NOT NULL"),
|
||||
)
|
||||
op.create_index(
|
||||
"workflow_run_tag_events_active_label_unique",
|
||||
"workflow_run_tag_events",
|
||||
["organization_id", "workflow_run_id", "value"],
|
||||
unique=True,
|
||||
postgresql_where=sa.text("superseded_at IS NULL AND event_type = 'set' AND key IS NULL"),
|
||||
sqlite_where=sa.text("superseded_at IS NULL AND event_type = 'set' AND key IS NULL"),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index(
|
||||
"workflow_run_tag_events_active_label_unique",
|
||||
table_name="workflow_run_tag_events",
|
||||
postgresql_where=sa.text("superseded_at IS NULL AND event_type = 'set' AND key IS NULL"),
|
||||
)
|
||||
op.drop_index(
|
||||
"workflow_run_tag_events_active_grouped_unique",
|
||||
table_name="workflow_run_tag_events",
|
||||
postgresql_where=sa.text("superseded_at IS NULL AND event_type = 'set' AND key IS NOT NULL"),
|
||||
)
|
||||
op.drop_index("workflow_run_tag_events_org_set_at_idx", table_name="workflow_run_tag_events")
|
||||
op.drop_index(
|
||||
"workflow_run_tag_events_org_value_active_idx",
|
||||
table_name="workflow_run_tag_events",
|
||||
postgresql_include=["workflow_run_id"],
|
||||
postgresql_where=sa.text("superseded_at IS NULL AND event_type = 'set'"),
|
||||
)
|
||||
op.drop_index(
|
||||
"workflow_run_tag_events_org_key_value_active_idx",
|
||||
table_name="workflow_run_tag_events",
|
||||
postgresql_include=["workflow_run_id"],
|
||||
postgresql_where=sa.text("superseded_at IS NULL AND event_type = 'set'"),
|
||||
)
|
||||
op.drop_index("workflow_run_tag_events_org_wr_set_at_idx", table_name="workflow_run_tag_events")
|
||||
op.drop_table("workflow_run_tag_events")
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
"""add heal episodes and proposals
|
||||
|
||||
Revision ID: e1227914ecfe
|
||||
Revises: bec06d149264
|
||||
Create Date: 2026-07-09T22:47:11.311011+00:00
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "e1227914ecfe"
|
||||
down_revision: Union[str, None] = "bec06d149264"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_table(
|
||||
"heal_episodes",
|
||||
sa.Column("heal_episode_id", sa.String(), nullable=False),
|
||||
sa.Column("organization_id", sa.String(), nullable=False),
|
||||
sa.Column("workflow_permanent_id", sa.String(), nullable=False),
|
||||
sa.Column("workflow_id", sa.String(), nullable=False),
|
||||
sa.Column("workflow_run_id", sa.String(), nullable=False),
|
||||
sa.Column("workflow_run_block_id", sa.String(), nullable=False),
|
||||
sa.Column("block_label", sa.String(), nullable=False),
|
||||
sa.Column("engine", sa.String(), nullable=False),
|
||||
sa.Column("status", sa.String(), nullable=False),
|
||||
sa.Column("skip_reason", sa.String(), nullable=True),
|
||||
sa.Column("block_prompt", sa.UnicodeText(), nullable=True),
|
||||
sa.Column("block_code", sa.UnicodeText(), nullable=True),
|
||||
sa.Column("block_steps", sa.JSON(), nullable=True),
|
||||
sa.Column("snapshot_available", sa.Boolean(), nullable=False, server_default=sa.false()),
|
||||
sa.Column("convergence_eligible", sa.Boolean(), nullable=False, server_default=sa.false()),
|
||||
sa.Column("parameter_binding_keys", sa.JSON(), nullable=True),
|
||||
sa.Column("exception_class", sa.String(), nullable=True),
|
||||
sa.Column("failing_line", sa.Integer(), nullable=True),
|
||||
sa.Column("matched_step_index", sa.Integer(), nullable=True),
|
||||
sa.Column("failure_message", sa.UnicodeText(), nullable=True),
|
||||
sa.Column("escalation_task_id", sa.String(), nullable=True),
|
||||
sa.Column("wall_clock_ms", sa.Integer(), nullable=True),
|
||||
sa.Column("action_count", sa.Integer(), nullable=True),
|
||||
sa.Column("output_obligation", sa.String(), nullable=True),
|
||||
sa.Column("dom_snapshot_artifact_id", sa.String(), nullable=True),
|
||||
sa.Column("scout_transcript_artifact_id", sa.String(), nullable=True),
|
||||
sa.Column("screenshot_artifact_id", sa.String(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("modified_at", sa.DateTime(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("heal_episode_id"),
|
||||
)
|
||||
op.create_index(
|
||||
"he_org_wpid_index",
|
||||
"heal_episodes",
|
||||
["organization_id", "workflow_permanent_id", "created_at"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index("he_org_created_at_index", "heal_episodes", ["organization_id", "created_at"], unique=False)
|
||||
op.create_index("he_org_wrid_index", "heal_episodes", ["organization_id", "workflow_run_id"], unique=False)
|
||||
|
||||
op.create_table(
|
||||
"workflow_heal_proposals",
|
||||
sa.Column("heal_proposal_id", sa.String(), nullable=False),
|
||||
sa.Column("organization_id", sa.String(), nullable=False),
|
||||
sa.Column("workflow_permanent_id", sa.String(), nullable=False),
|
||||
sa.Column("block_label", sa.String(), nullable=False),
|
||||
sa.Column("candidate_definition", sa.JSON(), nullable=False),
|
||||
sa.Column("provenance", sa.JSON(), nullable=True),
|
||||
sa.Column("episode_ids", sa.JSON(), nullable=False),
|
||||
sa.Column("rendered_diff", sa.UnicodeText(), nullable=True),
|
||||
sa.Column("base_version", sa.Integer(), nullable=False),
|
||||
sa.Column("base_definition_hash", sa.String(), nullable=False),
|
||||
sa.Column("status", sa.String(), nullable=False, server_default=sa.text("'proposed'")),
|
||||
sa.Column("adopted_workflow_id", sa.String(), nullable=True),
|
||||
sa.Column("episode_window", sa.String(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("modified_at", sa.DateTime(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("heal_proposal_id"),
|
||||
)
|
||||
op.create_index(
|
||||
"hp_org_wpid_index",
|
||||
"workflow_heal_proposals",
|
||||
["organization_id", "workflow_permanent_id"],
|
||||
unique=False,
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
"organizations",
|
||||
sa.Column("selfheal_screenshot_capture_enabled", sa.Boolean(), nullable=False, server_default=sa.false()),
|
||||
)
|
||||
op.add_column("organizations", sa.Column("selfheal_artifact_retention_days", sa.Integer(), nullable=True))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("organizations", "selfheal_artifact_retention_days")
|
||||
op.drop_column("organizations", "selfheal_screenshot_capture_enabled")
|
||||
|
||||
op.drop_index("hp_org_wpid_index", table_name="workflow_heal_proposals")
|
||||
op.drop_table("workflow_heal_proposals")
|
||||
|
||||
op.drop_index("he_org_wrid_index", table_name="heal_episodes")
|
||||
op.drop_index("he_org_created_at_index", table_name="heal_episodes")
|
||||
op.drop_index("he_org_wpid_index", table_name="heal_episodes")
|
||||
op.drop_table("heal_episodes")
|
||||
|
|
@ -38,6 +38,9 @@ services:
|
|||
- ./videos:/data/videos
|
||||
- ./har:/data/har
|
||||
- ./log:/data/log
|
||||
- ./downloads:/data/downloads
|
||||
- ./browser_sessions:/data/browser_sessions
|
||||
- ./credential_vault:/data/credential_vault
|
||||
# Generated credentials allow the UI to pick up the local API key on first startup.
|
||||
- ./.skyvern:/app/.skyvern
|
||||
# Uncomment the following two lines if you want to connect to any local changes
|
||||
|
|
@ -62,6 +65,11 @@ services:
|
|||
- BROWSER_REMOTE_DEBUGGING_URL=${BROWSER_REMOTE_DEBUGGING_URL:-http://127.0.0.1:9222}
|
||||
- BROWSER_REMOTE_DEBUGGING_HOST_HEADER=${BROWSER_REMOTE_DEBUGGING_HOST_HEADER:-}
|
||||
- BROWSER_CDP_CONNECT_TIMEOUT_MS=${BROWSER_CDP_CONNECT_TIMEOUT_MS:-120000}
|
||||
- DOWNLOAD_PATH=/data/downloads
|
||||
- BROWSER_SESSION_BASE_PATH=/data/browser_sessions
|
||||
- CREDENTIAL_VAULT_TYPE=${CREDENTIAL_VAULT_TYPE:-skyvern}
|
||||
- ENABLE_LOCAL_CREDENTIAL_VAULT=${ENABLE_LOCAL_CREDENTIAL_VAULT:-true}
|
||||
- LOCAL_CREDENTIAL_VAULT_PATH=/data/credential_vault
|
||||
- ENABLE_CODE_BLOCK=true
|
||||
# --- Control your own browser (Chrome/Chromium) ---
|
||||
# Prefer Chrome's chrome://inspect/#remote-debugging flow for an existing profile.
|
||||
|
|
|
|||
114
docs/changelog-emails/2026-06-june.md
Normal file
|
|
@ -0,0 +1,114 @@
|
|||

|
||||
|
||||
# Skyvern Changelog — June 2026
|
||||
|
||||
*Everything we shipped in June 2026 — weeks of June 1, 8, 15, and 22.*
|
||||
|
||||
---
|
||||
|
||||
## Workflows Are Now Agents
|
||||
|
||||
We renamed **Workflows to Agents** across the product, the public API, and the docs. The API now lives under **`/agents`** (e.g. `POST /v1/run/agents`) and accepts an **`agent_id`** alias for `workflow_id` — same `wpid_` value, echoed back in responses. It's fully backwards-compatible: your existing `workflow_id` inputs, `/workflows` endpoints, SDK methods, and bookmarked doc URLs all keep working.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Workflow Studio (Preview)
|
||||
|
||||
Meet the next-generation editor. **Workflow Studio** is an opt-in preview that reimagines how you build: a refreshed **build canvas**, an **integrated live browser view**, and a built-in **run viewer** — all in one place. Take control of the live browser, center the viewport, and watch a run unfold without leaving the editor. Flip it on from Feature Preview in Settings.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Code-First Code Blocks
|
||||
|
||||
For when you want to drop to code. Code blocks now have a **dedicated code editor** with **syntax highlighting**, **Jinja parameter hints**, and a **run timeline** that records every action — including `page.evaluate(...)` calls. A **Build ↔ Code toggle** flips between visual and code editing, block labels and extraction output render correctly, and Copilot-generated code blocks support a **typed extraction schema** and fill logins with your stored credentials.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Copilot: Ask, Build, Code — With Memory
|
||||
|
||||
The Copilot got sharper about intent and context. It now **routes every request by mode** — **Ask** answers without touching your workflow, **Build** creates or edits it, **Code** generates executable code blocks. It **remembers the full chat history per workflow**, so prior context and decisions carry forward as you keep building. And its **repair loop is honest now**: when consecutive fixes make no verified progress, it stops after three tries and escalates cleanly — draft preserved — instead of spinning.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## A Bigger Model Menu
|
||||
|
||||
More choice for every run. New this month: **DeepSeek**, **Xiaomi MiMo** (and **MiMo-V2.5** via OpenRouter), **Gemini 3.5 Flash**, **GPT-5-mini** (your own OpenAI key or via OpenRouter), and **Claude Opus 4.8** (Anthropic + Bedrock). OpenRouter runs now track token counts and cost like every other provider. (Gemini 2.5 Pro/Flash are deprecated; CUA and the Claude Opus family are now enterprise-only.)
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Credentials & OTP, Everywhere
|
||||
|
||||
Logins that just work. Pull credentials straight from **1Password** (with an item picker) or **Bitwarden**, look up one-time passcodes from **Gmail** via OAuth, and **fill OTP at runtime** from your stored TOTP secrets — even inside code blocks. Expired credential sessions **auto re-save**, and you can **clear a saved credential** without deleting and recreating it.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Multi-Tab Browser Control
|
||||
|
||||
Automations that span tabs. The autonomous agent loop can now **open and work across multiple browser tabs** at once — following new-tab links and handling pop-ups — so flows that jump between tabs no longer dead-end.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Self-Host on Google Cloud
|
||||
|
||||
Full GCP-native deployments. Self-hosted Skyvern now supports **Google Cloud Storage** for artifacts and **GCP Secret Manager** as a vault backend — so you can run the whole stack on Google Cloud with your own storage and secrets.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Quick List — June
|
||||
|
||||
**New features**
|
||||
- **Analytics drill-down & tag filters** — period-aware per-agent drill-down (avg duration, credits/run, period-over-period trends) plus filtering runs and metrics by workflow tag
|
||||
- **Agent Directory Tree** — the agents/folders list is now a navigable tree for nested hierarchies
|
||||
- **Self-serve editor onboarding** — a get-started modal, a 4-stop guided tour, and smart empty states for faster time-to-first-automation
|
||||
- **Bulk actions on the agents list** — select multiple agents and act on them at once
|
||||
- **Label management in Settings** — rename, recolor, and soft-delete tags
|
||||
- **Browser profiles in MCP sessions** — associate a browser profile with MCP-driven runs for credential/state reuse
|
||||
- **Feature Preview panel in Settings** — opt into upcoming features before they're fully released
|
||||
- **Workflow schedules in open source** — self-hosted deployments now support schedules
|
||||
- **Uncapped workflow runtime** — configure long-running automations with no maximum time limit
|
||||
|
||||
**Improvements**
|
||||
- Structured output is verified against its schema before a run is marked complete
|
||||
- Tasks return a best-effort **partial deliverable** when they exhaust their credit budget
|
||||
- The task planner prefers **loop-based tasks** for repeated same-shaped work, and can now emit EXTRACT_INFORMATION / GOTO_URL actions
|
||||
- The agent **acts immediately on stalled pages** and **halts reliably on terminal blockers** instead of spinning
|
||||
- Remote browser sessions capped at 4 hours; debug sessions stay open after a run so you can inspect the final page
|
||||
- End-state screenshots captured for **every open tab** at completion; per-run recordings clipped to the run window and stored as downloadable artifacts
|
||||
- Run app + recording URLs surfaced in MCP and CLI responses; run-ID search fallback on the runs list
|
||||
- Batched cache invalidation on workflow save (removed a per-block N+1) for faster saves on large workflows
|
||||
- OpenRouter cost tracking; analytics tag filters accept labels, groups, or `group:label`
|
||||
- Improved authenticator-2FA credential setup; PDF field mapping by positional labels
|
||||
- Copilot data-write blocks default to `continue_on_failure=false`; code-repair progress shown as quiet indicators
|
||||
|
||||
**Bug fixes**
|
||||
- Fixed the workflow builder freezing on an infinite FlowRenderer layout loop
|
||||
- Fixed the code editor crashing (stack overflow) on large or deeply-nested JSON
|
||||
- Fixed the app failing to load after a deploy from stale chunks — it now auto-recovers with a cache-busting reload
|
||||
- Fixed login credentials not reattaching after editing a workflow via MCP
|
||||
- Fixed conditional routing not being preserved when loading a v1-format workflow
|
||||
- Fixed the active run context being lost when switching organizations
|
||||
- Fixed multi-step logins not advancing when credentials filled JavaScript-gated fields
|
||||
- Fixed scanned PDFs being parsed as a single page instead of page-by-page
|
||||
- Fixed shadow-DOM text nodes being missed during element text extraction
|
||||
- Fixed runs not stopping when a configured time limit was exceeded
|
||||
- Fixed credits not recorded when data was captured inside a Navigate block
|
||||
- Fixed telephone inputs dropping digits on bare NANP-format numbers
|
||||
- Fixed persistent sessions reporting a stale cached session as live
|
||||
- Fixed FileUpload blocks silently skipping when no file was provided (now a clean no-op)
|
||||
- Fixed the block library drawer overflowing its container in the workflow builder
|
||||
BIN
docs/changelog-emails/images/2026-06-00-header.png
Normal file
|
After Width: | Height: | Size: 394 KiB |
BIN
docs/changelog-emails/images/2026-06-01-agents-rename.png
Normal file
|
After Width: | Height: | Size: 443 KiB |
BIN
docs/changelog-emails/images/2026-06-02-workflow-studio.png
Normal file
|
After Width: | Height: | Size: 470 KiB |
BIN
docs/changelog-emails/images/2026-06-03-code-first.png
Normal file
|
After Width: | Height: | Size: 401 KiB |
BIN
docs/changelog-emails/images/2026-06-04-copilot.png
Normal file
|
After Width: | Height: | Size: 426 KiB |
BIN
docs/changelog-emails/images/2026-06-05-models.png
Normal file
|
After Width: | Height: | Size: 446 KiB |
BIN
docs/changelog-emails/images/2026-06-06-credentials.png
Normal file
|
After Width: | Height: | Size: 432 KiB |
BIN
docs/changelog-emails/images/2026-06-07-multi-tab.png
Normal file
|
After Width: | Height: | Size: 429 KiB |
BIN
docs/changelog-emails/images/2026-06-08-gcp-self-host.png
Normal file
|
After Width: | Height: | Size: 458 KiB |
|
|
@ -13,6 +13,9 @@ keywords:
|
|||
<div className="cl-page">
|
||||
<div className="cl-sidebar">
|
||||
<p className="cl-sidebar-title">TIMELINE</p>
|
||||
<a href="#week-jun-30-2026" className="cl-sidebar-link">Week of Jun 30, 2026</a>
|
||||
<a href="#week-jun-22-2026" className="cl-sidebar-link">Week of Jun 22, 2026</a>
|
||||
<a href="#week-jun-15-2026" className="cl-sidebar-link">Week of Jun 15, 2026</a>
|
||||
<a href="#week-jun-8-2026" className="cl-sidebar-link">Week of Jun 8, 2026</a>
|
||||
<a href="#week-jun-1-2026" className="cl-sidebar-link">Week of Jun 1, 2026</a>
|
||||
<a href="#week-may-25-2026" className="cl-sidebar-link">Week of May 25, 2026</a>
|
||||
|
|
@ -20,31 +23,168 @@ keywords:
|
|||
<a href="#week-may-11-2026" className="cl-sidebar-link">Week of May 11, 2026</a>
|
||||
<a href="#week-may-4-2026" className="cl-sidebar-link">Week of May 4, 2026</a>
|
||||
<a href="#week-apr-27-2026" className="cl-sidebar-link">Week of Apr 27, 2026</a>
|
||||
<a href="#v1-0-24" className="cl-sidebar-link">v1.0.24 — Apr 21, 2026</a>
|
||||
<a href="#v1-0-23" className="cl-sidebar-link">v1.0.23 — Apr 14, 2026</a>
|
||||
<a href="#v1-0-22" className="cl-sidebar-link">v1.0.22 — Feb 26, 2026</a>
|
||||
<a href="#v1-0-21" className="cl-sidebar-link">v1.0.21 — Feb 24, 2026</a>
|
||||
<a href="#v1-0-20" className="cl-sidebar-link">v1.0.20 — Feb 21, 2026</a>
|
||||
<a href="#v1-0-19" className="cl-sidebar-link">v1.0.19 — Feb 20, 2026</a>
|
||||
<a href="#v1-0-18" className="cl-sidebar-link">v1.0.18 — Feb 19, 2026</a>
|
||||
<a href="#v1-0-17" className="cl-sidebar-link">v1.0.17 — Feb 19, 2026</a>
|
||||
<a href="#v1-0-16" className="cl-sidebar-link">v1.0.16 — Feb 19, 2026</a>
|
||||
<a href="#v1-0-15" className="cl-sidebar-link">v1.0.15 — Feb 17, 2026</a>
|
||||
<a href="#v1-0-14" className="cl-sidebar-link">v1.0.14 — Feb 17, 2026</a>
|
||||
<a href="#v1-0-13" className="cl-sidebar-link">v1.0.13 — Feb 10, 2026</a>
|
||||
<a href="#v1-0-12" className="cl-sidebar-link">v1.0.12 — Feb 3, 2026</a>
|
||||
<a href="#v1-0-11" className="cl-sidebar-link">v1.0.11 — Jan 29, 2026</a>
|
||||
<a href="#v1-0-10" className="cl-sidebar-link">v1.0.10 — Jan 22, 2026</a>
|
||||
<a href="#v1-0-9" className="cl-sidebar-link">v1.0.9 — Jan 20, 2026</a>
|
||||
<a href="#v1-0-8" className="cl-sidebar-link">v1.0.8 — Jan 9, 2026</a>
|
||||
<a href="#week-apr-20-2026" className="cl-sidebar-link">Week of Apr 20, 2026</a>
|
||||
<a href="#week-apr-13-2026" className="cl-sidebar-link">Week of Apr 13, 2026</a>
|
||||
<a href="#week-feb-23-2026" className="cl-sidebar-link">Week of Feb 23, 2026</a>
|
||||
<a href="#week-feb-16-2026" className="cl-sidebar-link">Week of Feb 16, 2026</a>
|
||||
<a href="#week-feb-9-2026" className="cl-sidebar-link">Week of Feb 9, 2026</a>
|
||||
<a href="#week-feb-2-2026" className="cl-sidebar-link">Week of Feb 2, 2026</a>
|
||||
<a href="#week-jan-26-2026" className="cl-sidebar-link">Week of Jan 26, 2026</a>
|
||||
<a href="#week-jan-19-2026" className="cl-sidebar-link">Week of Jan 19, 2026</a>
|
||||
<a href="#week-jan-5-2026" className="cl-sidebar-link">Week of Jan 5, 2026</a>
|
||||
</div>
|
||||
|
||||
<div className="cl-content">
|
||||
<h1 className="cl-title">Changelog</h1>
|
||||
<p className="cl-subtitle">New features, improvements, and fixes in Skyvern</p>
|
||||
|
||||
<a id="week-jun-30-2026"></a>
|
||||
<Update label="Week of June 30, 2026" description="Workflow Studio UX improvements, faster enrichment, code-block self-heal, extraction accuracy, bug fixes">
|
||||
|
||||
## Improvements
|
||||
|
||||
- **Block Type Shown in Workflow Studio Header** — The block detail panel in Workflow Studio now displays the block type in the header, making it easier to identify what kind of block you're editing at a glance. ([#6956](https://github.com/Skyvern-AI/skyvern/pull/6956))
|
||||
- **Improved Extraction Accuracy for Absent Data** — The agent now better handles cases where requested output is genuinely absent from the page, reducing false positives in extraction results. ([#6957](https://github.com/Skyvern-AI/skyvern/pull/6957))
|
||||
- **Data-Only Validation Skips Page Evidence** — Validation steps that check only extracted data no longer capture page screenshots when they aren't needed, reducing unnecessary work during runs. ([#6960](https://github.com/Skyvern-AI/skyvern/pull/6960))
|
||||
- **Copilot Block Runs Routed to UI Worker** — Copilot block runs are now dispatched to a dedicated UI worker, keeping the editor responsive during live automation. ([#6962](https://github.com/Skyvern-AI/skyvern/pull/6962))
|
||||
- **Clearer Invalid JSON Errors in Workflow Editor** — The workflow editor now surfaces a descriptive error when a parameter contains invalid JSON, making it faster to diagnose and fix configuration mistakes. ([#6963](https://github.com/Skyvern-AI/skyvern/pull/6963))
|
||||
- **"Ignore System Prompt" Moved to Advanced Settings** — The "Ignore system prompt" option has been relocated to the advanced settings panel, reducing clutter in the default block configuration view. ([#6964](https://github.com/Skyvern-AI/skyvern/pull/6964))
|
||||
- **Empty Extra HTTP Headers Hidden** — Extra HTTP header fields that are empty no longer appear in block configurations, reducing visual noise in the workflow editor. ([#6966](https://github.com/Skyvern-AI/skyvern/pull/6966))
|
||||
- **Block Selection Persisted in URL** — The selected block in Workflow Studio is now encoded in the URL, so your selection is preserved on reload and can be shared via link. ([#6969](https://github.com/Skyvern-AI/skyvern/pull/6969))
|
||||
- **Code-Block Self-Heal Minimum Retry Floor** — The code-block self-healing loop now enforces a minimum number of repair attempts before giving up, preventing premature failures on recoverable errors. ([#6971](https://github.com/Skyvern-AI/skyvern/pull/6971))
|
||||
- **Faster Live-Draft Enrichment** — Workflow recording live-draft enrichment now uses a faster model and a shorter debounce interval, making draft suggestions appear noticeably sooner while recording. ([#6973](https://github.com/Skyvern-AI/skyvern/pull/6973))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Fixed syntax highlighting disappearing when viewing large webhook payloads. ([#6967](https://github.com/Skyvern-AI/skyvern/pull/6967))
|
||||
- Fixed LLM blocks not enforcing their configured output schema, which could allow malformed data to propagate to downstream blocks. ([#6965](https://github.com/Skyvern-AI/skyvern/pull/6965))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="week-jun-22-2026"></a>
|
||||
<Update label="Week of June 22, 2026" description="Workflow Studio preview, new models, label management, Gmail OTP, Copilot improvements, analytics filters, bug fixes">
|
||||
|
||||
## New features
|
||||
|
||||
- **Gmail-Backed OTP Lookup** — Agents can now retrieve one-time passwords from Gmail via OAuth, enabling automated login flows that depend on email-delivered verification codes. ([#6769](https://github.com/Skyvern-AI/skyvern/pull/6769))
|
||||
- **Copilot Chat History per Workflow** — The Copilot now retains its full conversation history scoped to each individual workflow, so prior context and decisions are preserved as you continue building. ([#6767](https://github.com/Skyvern-AI/skyvern/pull/6767))
|
||||
- **Code-First Editor Polish** — Code-first code blocks now display block labels, correctly render extraction output, and include a Build-vs-Code toggle for switching between visual and code editing modes. ([#6771](https://github.com/Skyvern-AI/skyvern/pull/6771))
|
||||
- **Workflow Studio (Preview)** — A redesigned workflow editor with a refreshed build canvas, integrated browser view, and run viewer is now available as an opt-in preview, giving teams an early look at the next-generation authoring experience. ([#6782](https://github.com/Skyvern-AI/skyvern/pull/6782))
|
||||
- **DeepSeek and Xiaomi MiMo Models** — DeepSeek and Xiaomi MiMo are now available in the model dropdown for agent runs. Gemini 2.5 Pro and 2.5 Flash have been deprecated. ([#6831](https://github.com/Skyvern-AI/skyvern/pull/6831))
|
||||
- **Label Management Settings** — Labels can now be renamed, recolored, and soft-deleted directly from the Settings page, making it easier to maintain a clean tag taxonomy. ([#6830](https://github.com/Skyvern-AI/skyvern/pull/6830))
|
||||
- **Browser Profiles in MCP Sessions** — Browser sessions initiated via MCP can now be associated with a browser profile, enabling credential and state reuse across MCP-driven runs. ([#6798](https://github.com/Skyvern-AI/skyvern/pull/6798))
|
||||
- **Workflow-Tag Filter on Analytics** — The analytics dashboard now supports filtering runs and metrics by workflow tag. ([#6780](https://github.com/Skyvern-AI/skyvern/pull/6780))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **Copilot Repair Shows Quiet Progress** — The Copilot's code-seam repair steps now appear as compact progress indicators instead of repeated chat messages, keeping the conversation readable during long repairs. ([#6746](https://github.com/Skyvern-AI/skyvern/pull/6746))
|
||||
- **Collapsible Sidebar with Avatar** — The left sidebar now features an edge toggle, a closed-state user avatar, and a smooth open/close animation for a more polished navigation experience. ([#6754](https://github.com/Skyvern-AI/skyvern/pull/6754))
|
||||
- **Structured Output Verified Before Completion** — Runs that produce structured data now verify the output satisfies the configured schema before marking the run as successfully complete. ([#6751](https://github.com/Skyvern-AI/skyvern/pull/6751))
|
||||
- **MCP Workflow Overlap Settings Preserved** — Overlap settings configured via MCP are now retained correctly when the workflow is subsequently edited, preventing unintentional resets. ([#6748](https://github.com/Skyvern-AI/skyvern/pull/6748))
|
||||
- **Browser Profile List Sorted Newest First** — The browser profile picker now orders profiles with the most recently created at the top, making recent profiles easier to find and select. ([#6739](https://github.com/Skyvern-AI/skyvern/pull/6739))
|
||||
- **Remote Browser Sessions Capped at Four Hours** — Remote browser sessions now have a maximum duration of four hours, preventing orphaned sessions from consuming resources indefinitely.
|
||||
- **Debug Sessions Stay Open After Runs** — Browser sessions launched from the workflow editor in debug mode now remain alive after a run completes, so you can inspect the final page state without the session closing immediately. ([#6832](https://github.com/Skyvern-AI/skyvern/pull/6832))
|
||||
- **GPT-5 Mini via OpenRouter** — GPT-5 Mini is now available as a selectable model via OpenRouter. ([#6816](https://github.com/Skyvern-AI/skyvern/pull/6816))
|
||||
- **Extraction and AI Steps in Code-Block View** — Extraction and AI steps are now surfaced in the code-block run view, filling a gap in execution visibility. ([#6823](https://github.com/Skyvern-AI/skyvern/pull/6823))
|
||||
- **Color Palette for Grouped Workflow Tags** — Tags that belong to a group are now displayed with a curated color palette, making it easier to distinguish tag groups at a glance. ([#6801](https://github.com/Skyvern-AI/skyvern/pull/6801))
|
||||
- **Improved Authenticator 2FA Credential Setup** — The credential setup flow for authenticator-based 2FA has been improved with clearer guidance and a smoother configuration experience. ([#6783](https://github.com/Skyvern-AI/skyvern/pull/6783))
|
||||
- **Copilot Data-Write Blocks Default to Safe Failure Mode** — New Copilot-generated data-write blocks now default to `continue_on_failure=false`, preventing downstream blocks from running on bad data. ([#6779](https://github.com/Skyvern-AI/skyvern/pull/6779))
|
||||
- **End-State Screenshots for All Open Tabs** — Task runs now capture end-state screenshots for every open tab at completion, giving a full snapshot of the browser state. ([#6777](https://github.com/Skyvern-AI/skyvern/pull/6777))
|
||||
- **Partial Deliverable on Budget Exhaustion** — Tasks that hit their credit budget now return the best-effort deliverable collected so far instead of failing without output. ([#6778](https://github.com/Skyvern-AI/skyvern/pull/6778))
|
||||
- **Planner Supports EXTRACT_INFORMATION and GOTO_URL** — The task planner can now emit EXTRACT_INFORMATION and GOTO_URL actions, expanding the set of strategies available during automated planning. ([#6800](https://github.com/Skyvern-AI/skyvern/pull/6800))
|
||||
- **Copilot Completion Recognition Improvements** — The Copilot completion recognizer is now more authoritative and evidence-backed, with stable criteria counts and more reliable recognition across runs. ([#6789](https://github.com/Skyvern-AI/skyvern/pull/6789))
|
||||
- **Copilot Code Repair Loop Reliability** — The Copilot code authoring repair loop is now more reliable, reducing cases where stuck repairs would stall progress. ([#6792](https://github.com/Skyvern-AI/skyvern/pull/6792))
|
||||
- **Workflow Studio Browser and Panel Improvements** — The Workflow Studio editor now supports take-control and viewport centering for the live browser, with alignment and toolbar polish for the run/editor panels. ([#6810](https://github.com/Skyvern-AI/skyvern/pull/6810))
|
||||
- **Analytics Tag Filters Accept Flexible Input Shapes** — Analytics tag filters now accept labels, groups, or `group:label` pairs in all three supported filter shapes. ([#6802](https://github.com/Skyvern-AI/skyvern/pull/6802))
|
||||
- **Run ID Search Fallback on Runs List** — The runs list now falls back to searching by run ID when no parameter-value match is found, making it easier to locate specific runs. ([#6788](https://github.com/Skyvern-AI/skyvern/pull/6788))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Fixed login credentials not being reattached after editing a workflow via MCP, which could cause credential-gated runs to fail. ([#6761](https://github.com/Skyvern-AI/skyvern/pull/6761))
|
||||
- Fixed conditional routing logic not being preserved when loading a workflow stored in the v1 format. ([#6760](https://github.com/Skyvern-AI/skyvern/pull/6760))
|
||||
- Fixed the active run context being lost when switching between organizations, requiring a page refresh to restore the correct run view. ([#6753](https://github.com/Skyvern-AI/skyvern/pull/6753))
|
||||
- Fixed browser connection settings defined in a TaskV2 block not being forwarded to child task runs. ([#6750](https://github.com/Skyvern-AI/skyvern/pull/6750))
|
||||
- Fixed telephone number inputs dropping digits when bare NANP-format phone numbers were typed. ([#6826](https://github.com/Skyvern-AI/skyvern/pull/6826))
|
||||
- Fixed the workflow builder freezing due to an infinite FlowRenderer dimension/layout feedback loop. ([#6824](https://github.com/Skyvern-AI/skyvern/pull/6824))
|
||||
- Fixed the code editor crashing with a stack overflow when opened on large or deeply-nested JSON. ([#6817](https://github.com/Skyvern-AI/skyvern/pull/6817))
|
||||
- Fixed the app failing to load after a deploy due to stale webpack chunks; the app now auto-recovers via a cache-busting reload. ([#6818](https://github.com/Skyvern-AI/skyvern/pull/6818))
|
||||
- Fixed runs returning an incorrect terminal outcome when the extraction schema had been modified after the initial recording. ([#6815](https://github.com/Skyvern-AI/skyvern/pull/6815))
|
||||
- Fixed MCP workflow edits dropping non-credential parameter-to-block links. ([#6813](https://github.com/Skyvern-AI/skyvern/pull/6813))
|
||||
- Fixed address bar paste not working in the VNC streaming view. ([#6812](https://github.com/Skyvern-AI/skyvern/pull/6812))
|
||||
- Fixed newly added workflow blocks not receiving focus in the editor. ([#6809](https://github.com/Skyvern-AI/skyvern/pull/6809))
|
||||
- Fixed Copilot code-block file downloads being written to the wrong directory. ([#6797](https://github.com/Skyvern-AI/skyvern/pull/6797))
|
||||
- Fixed parameter-value search not appearing in the v2 runs list. ([#6796](https://github.com/Skyvern-AI/skyvern/pull/6796))
|
||||
- Fixed extra actions firing after selecting a combobox option during text entry. ([#6787](https://github.com/Skyvern-AI/skyvern/pull/6787))
|
||||
- Fixed shadow DOM text nodes being missed during element text extraction. ([#6791](https://github.com/Skyvern-AI/skyvern/pull/6791))
|
||||
- Fixed persistent browser sessions incorrectly reporting a cached session as live when it had become stale.
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="week-jun-15-2026"></a>
|
||||
<Update label="Week of June 15, 2026" description="Code-first code block editor, analytics drill-down, copilot repair loop, OTP fill, uncapped runtimes, voice input fixes">
|
||||
|
||||
## New features
|
||||
|
||||
- **OTP Fill at Runtime in Code-Block Sandbox** — Code blocks can now fill OTP fields using your stored TOTP credentials at runtime, enabling fully automated two-factor authentication flows without manual input. ([#6571](https://github.com/Skyvern-AI/skyvern/pull/6571))
|
||||
- **Uncapped Workflow Runtime** — Workflows can now be configured to run without a maximum time limit, enabling long-running automations that previously timed out. ([#6567](https://github.com/Skyvern-AI/skyvern/pull/6567))
|
||||
- **Code-First Code Block Editor** — Code blocks now feature a dedicated code editor with syntax highlighting, Jinja parameter hints, and a run timeline showing each action taken, giving developers full visibility and control over code-driven automations. ([#6604](https://github.com/Skyvern-AI/skyvern/pull/6604))
|
||||
- **Period-Aware Analytics Drill-Down** — The agent analytics drill-down panel now respects the selected time period (7/30/90/365 days or custom range) and shows per-agent average duration, credits per run, and period-over-period trends.
|
||||
- **Agent Directory Tree** — The agents and folders list has been redesigned as a navigable directory tree, making it easier to browse and organize agents across nested folder hierarchies. ([#6631](https://github.com/Skyvern-AI/skyvern/pull/6631))
|
||||
- **GCP Self-Host: Storage and Vault** — Self-hosted deployments on Google Cloud Platform now support GCS artifact storage and GCP Secret Manager vault, enabling full GCP-native deployments. ([#6632](https://github.com/Skyvern-AI/skyvern/pull/6632))
|
||||
- **1Password Credential Picker** — Credential inputs now include an item picker for 1Password vaults, letting you browse and select vault items directly during credential setup. ([#6651](https://github.com/Skyvern-AI/skyvern/pull/6651))
|
||||
- **Typed Extraction Schema for Copilot Code Blocks** — Copilot-generated code blocks now support a typed data extraction schema (matching `data_schema` parity), enabling structured data output from code-block automations. ([#6674](https://github.com/Skyvern-AI/skyvern/pull/6674))
|
||||
- **SDK-Backed Remote Browser Provider** — Agents can now connect to external browser providers via SDK, enabling tighter integration with third-party remote browser services. ([#6687](https://github.com/Skyvern-AI/skyvern/pull/6687))
|
||||
- **Bitwarden Credential Integration** — Saved credentials can now be sourced directly from Bitwarden vaults, bringing Bitwarden to full UI and functional parity with other supported credential providers. ([#6729](https://github.com/Skyvern-AI/skyvern/pull/6729))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **Smarter Loop Planning for Repeated Work** — The task planner now prefers loop-based tasks when it detects repeated same-shaped operations, improving throughput on multi-item automation runs. ([#6575](https://github.com/Skyvern-AI/skyvern/pull/6575))
|
||||
- **Agent Auto-Acts on Stalled Pages** — When the agent re-evaluates a page that hasn't changed, it now applies steering heuristics and acts immediately instead of stalling. ([#6577](https://github.com/Skyvern-AI/skyvern/pull/6577))
|
||||
- **Final Answer Surfaced Directly** — The task agent now returns the final deliverable directly instead of spinning through redundant synthesis steps, reducing latency on completed tasks. ([#6574](https://github.com/Skyvern-AI/skyvern/pull/6574))
|
||||
- **Copilot Stops Stuck Repair Loops** — The Workflow Copilot now detects when consecutive repairs make no verified progress, halts after three attempts, and presents an honest escalation with the draft preserved for review. ([#6608](https://github.com/Skyvern-AI/skyvern/pull/6608))
|
||||
- **Voice Input Microphone Permission** — The browser microphone permission prompt now appears correctly when using voice dictation in the Prompt Box and Workflow Copilot. ([#6601](https://github.com/Skyvern-AI/skyvern/pull/6601))
|
||||
- **`page.evaluate` Recorded in Code Block Timeline** — JavaScript `page.evaluate(...)` calls made inside code blocks are now recorded as actions in the run timeline, filling a gap in execution visibility. ([#6600](https://github.com/Skyvern-AI/skyvern/pull/6600))
|
||||
- **Active Run Shown on Browser Session Page** — Browser session detail pages now display which workflow run currently occupies the session, making it easier to understand session usage. ([#6691](https://github.com/Skyvern-AI/skyvern/pull/6691))
|
||||
- **Distinct Visual for Terminate Actions** — Terminate actions now appear with a distinct amber triangle icon in the run timeline, making it easy to spot where a run was stopped. ([#6693](https://github.com/Skyvern-AI/skyvern/pull/6693))
|
||||
- **PDF Field Mapping by Positional Labels** — PDF form filling now uses positional field labels to improve accuracy when mapping data to form fields with ambiguous names. ([#6663](https://github.com/Skyvern-AI/skyvern/pull/6663))
|
||||
- **MiMo-V2.5 Model Support via OpenRouter** — Added Xiaomi MiMo-V2.5 as a selectable LLM via OpenRouter for agent runs. ([#6636](https://github.com/Skyvern-AI/skyvern/pull/6636))
|
||||
- **Settings "API Keys" Renamed to "General"** — The "API Keys" section in Settings has been renamed to "General" to better reflect its full scope of configuration options. ([#6642](https://github.com/Skyvern-AI/skyvern/pull/6642))
|
||||
- **Run URLs Surfaced in MCP and CLI** — The agent app URL and session recording URLs are now included in run responses returned via MCP and the CLI, making it easier to link directly to a live run. ([#6719](https://github.com/Skyvern-AI/skyvern/pull/6719))
|
||||
- **Email OTP Credentials Supported in Copilot** — The Copilot can now use stored email OTP credentials when generating and validating code-block automations that require email-based authentication. ([#6716](https://github.com/Skyvern-AI/skyvern/pull/6716))
|
||||
- **Auto-Fill Default Google Account for Sheets Blocks** — Google Sheets blocks now automatically select the default linked Google account, reducing manual setup when configuring Sheets integrations. ([#6715](https://github.com/Skyvern-AI/skyvern/pull/6715))
|
||||
- **Copilot Output Accurately Reflects Verified Results** — The Copilot no longer under-reports successfully verified output, ensuring the run summary accurately reflects what was accomplished. ([#6710](https://github.com/Skyvern-AI/skyvern/pull/6710))
|
||||
- **Runs Halt Reliably on Terminal Blockers** — When the agent encounters strong evidence of an unresolvable blocker (such as a persistent challenge page), it now stops immediately rather than continuing to attempt further actions. ([#6714](https://github.com/Skyvern-AI/skyvern/pull/6714))
|
||||
- **Workflow Save Performance Improved** — Cache invalidation on workflow save is now batched, eliminating a per-block N+1 query pattern that slowed saves for large workflows. ([#6718](https://github.com/Skyvern-AI/skyvern/pull/6718))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Fixed the Run Inputs panel collapsing unexpectedly when filtering Run History. ([#6573](https://github.com/Skyvern-AI/skyvern/pull/6573))
|
||||
- Fixed the agent incorrectly retrying click fallbacks after an action dispatch timed out, causing unintended interactions. ([#6569](https://github.com/Skyvern-AI/skyvern/pull/6569))
|
||||
- Fixed session recordings and page interpretation not resuming correctly after navigation, causing missed recording segments. ([#6568](https://github.com/Skyvern-AI/skyvern/pull/6568))
|
||||
- Fixed code block runs not generating a recording entry, causing the Recording tab to appear empty. ([#6607](https://github.com/Skyvern-AI/skyvern/pull/6607))
|
||||
- Fixed code block action screenshots not appearing on the run Overview page. ([#6605](https://github.com/Skyvern-AI/skyvern/pull/6605))
|
||||
- Fixed long usernames or email addresses hiding the sidebar collapse button on desktop.
|
||||
- Fixed the FileParserBlock crashing instead of surfacing a clear error when it encountered an unparseable file. ([#6657](https://github.com/Skyvern-AI/skyvern/pull/6657))
|
||||
- Fixed the Inputs field missing from the Code view of code-first code blocks. ([#6633](https://github.com/Skyvern-AI/skyvern/pull/6633))
|
||||
- Fixed Copilot-synthesized download blocks not downloading the file during code replay. ([#6637](https://github.com/Skyvern-AI/skyvern/pull/6637), [#6638](https://github.com/Skyvern-AI/skyvern/pull/6638))
|
||||
- Fixed multi-step login flows not advancing when credentials were filled into JavaScript-gated fields. ([#6650](https://github.com/Skyvern-AI/skyvern/pull/6650))
|
||||
- Fixed an infinite update loop on the workflow build page when certain block configurations were active. ([#6660](https://github.com/Skyvern-AI/skyvern/pull/6660))
|
||||
- Fixed adopted-session file downloads not being available as run artifacts after the session ended. ([#6679](https://github.com/Skyvern-AI/skyvern/pull/6679))
|
||||
- Fixed the run timeline showing action and step rows for non-code blocks when they should only appear for code blocks. ([#6675](https://github.com/Skyvern-AI/skyvern/pull/6675))
|
||||
- Fixed workflow run actions not appearing in the timeline for all block types.
|
||||
- Fixed workflow runs not stopping when a configured time limit was exceeded. ([#6677](https://github.com/Skyvern-AI/skyvern/pull/6677))
|
||||
- Fixed the analytics plan-tier badge showing the incorrect tier for some organizations.
|
||||
- Fixed credits not being recorded when data was captured inside a Navigate block in task runs. ([#6698](https://github.com/Skyvern-AI/skyvern/pull/6698))
|
||||
- Fixed Copilot directory mode synthesizing incorrect code bindings. ([#6702](https://github.com/Skyvern-AI/skyvern/pull/6702))
|
||||
- Fixed FileUpload blocks silently skipping the upload when no file was provided, instead of recording a clean no-op and continuing. ([#6728](https://github.com/Skyvern-AI/skyvern/pull/6728))
|
||||
- Fixed the product tour not launching when triggered from the "Take a tour" menu option. ([#6727](https://github.com/Skyvern-AI/skyvern/pull/6727))
|
||||
- Fixed scanned PDF files being parsed as a single large page rather than processed page-by-page, which caused extraction to miss content on multi-page documents. ([#6722](https://github.com/Skyvern-AI/skyvern/pull/6722))
|
||||
- Fixed the block library drawer overflowing its container bounds in the workflow builder. ([#6721](https://github.com/Skyvern-AI/skyvern/pull/6721))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="week-jun-8-2026"></a>
|
||||
<Update label="Week of June 8, 2026" description="Editor onboarding, Copilot modes, GCS storage, API docs split, OTP fixes">
|
||||
<Update label="Week of June 8, 2026" description="Multi-tab agent control, Gemini 3.5 Flash, GCP Vault, bulk agent actions, credential clears, code-block credentials">
|
||||
|
||||
## New features
|
||||
|
||||
|
|
@ -52,6 +192,16 @@ keywords:
|
|||
- **GCS Storage Backend** — Added Google Cloud Storage as an artifact storage backend for self-hosted deployments. ([#6442](https://github.com/Skyvern-AI/skyvern/pull/6442))
|
||||
- **Key-Optional Labels and Flexible Tag Filters** — Tags now support key-optional labels, and tag filter queries accept more flexible formats for richer agent organization. ([#6458](https://github.com/Skyvern-AI/skyvern/pull/6458))
|
||||
- **Self-Serve Editor Onboarding** — New users in the workflow editor now see a get-started modal with intent routing and template cards, a 4-stop guided product tour, and smart empty states on the dashboard and runs pages to accelerate time-to-first-automation. ([#6475](https://github.com/Skyvern-AI/skyvern/pull/6475))
|
||||
- **Multi-Tab Browser Control** — The autonomous agent loop can now open and interact with multiple browser tabs simultaneously, enabling workflows that span across new tab links and pop-ups. ([#6507](https://github.com/Skyvern-AI/skyvern/pull/6507))
|
||||
- **Gemini 3.5 Flash Model Support** — Added Google Gemini 3.5 Flash as a selectable LLM for agent runs, providing a faster inference option. ([#6505](https://github.com/Skyvern-AI/skyvern/pull/6505))
|
||||
- **GCP Secret Manager Vault Adapter** — Added Google Cloud Secret Manager as a supported vault backend for storing and retrieving secrets in self-hosted deployments. ([#6488](https://github.com/Skyvern-AI/skyvern/pull/6488))
|
||||
- **Bulk Actions on Agents List** — You can now select multiple agents at once and apply bulk actions directly from the agents list page. ([#6485](https://github.com/Skyvern-AI/skyvern/pull/6485))
|
||||
- **Self-Service Credential Clears** — Saved credentials can now be individually cleared from the credentials settings page without deleting and recreating them. ([#6480](https://github.com/Skyvern-AI/skyvern/pull/6480))
|
||||
- **Per-Run Session Recordings as Artifacts** — Recordings are now clipped to each run's time window and stored as downloadable run-scoped artifacts. ([#6479](https://github.com/Skyvern-AI/skyvern/pull/6479))
|
||||
- **Credential-Aware Scouting in Code-Block Mode** — The Copilot now uses saved credentials while scouting pages for code-block generation and produces credential-typed code that fills login fields using your stored credentials. ([#6521](https://github.com/Skyvern-AI/skyvern/pull/6521))
|
||||
- **Claude Fable 5 Model Support** — Added Claude Fable 5 as a selectable model for agent runs. ([#6539](https://github.com/Skyvern-AI/skyvern/pull/6539))
|
||||
- **Live Browser Recording with Instant Placeholders** — Session recordings now commit navigation and wait blocks immediately as placeholders during live recording, with support for capture pause and draft interpretation. ([#6561](https://github.com/Skyvern-AI/skyvern/pull/6561))
|
||||
- **Act-and-Observe Copilot Scouting** — The Copilot's page scouting now uses act-and-observe interactions that return bounded page evidence alongside gathered actions, improving code-block generation accuracy. ([#6533](https://github.com/Skyvern-AI/skyvern/pull/6533))
|
||||
|
||||
## Improvements
|
||||
|
||||
|
|
@ -64,6 +214,13 @@ keywords:
|
|||
- **Block Title Editable from Settings Sidebar** — Workflow block titles can now be edited from the right-hand settings sidebar, without needing to use the inline editor on the canvas. ([#6443](https://github.com/Skyvern-AI/skyvern/pull/6443))
|
||||
- **API Reference Split into Agents and Runs Sections** — The public API reference is now organized into separate Agents and Runs sections for easier navigation. ([#6448](https://github.com/Skyvern-AI/skyvern/pull/6448))
|
||||
- **Label-First Tag Editor and Flexible Tag Filter UI** — The tag editor now accepts standalone labels or `group:label` format in a single input, and the filter bar supports filtering by label, group, or group:label for richer agent organization. ([#6470](https://github.com/Skyvern-AI/skyvern/pull/6470))
|
||||
- **2FA Field Progressive Disclosure in Login Block** — Two-factor authentication fields in the login workflow block are now collapsed by default and expanded on demand, reducing visual noise for workflows that don't use 2FA. ([#6490](https://github.com/Skyvern-AI/skyvern/pull/6490))
|
||||
- **Persistent Browser Session Profile Generation Now Opt-In** — Automatic browser profile generation during persistent sessions is now opt-in, giving you explicit control over when profiles are captured. ([#6489](https://github.com/Skyvern-AI/skyvern/pull/6489))
|
||||
- **Icon-Only Status Pills on Mobile Viewports** — Status badges now render in a compact icon-only format on small screen widths, preventing layout overflow on mobile devices. ([#6481](https://github.com/Skyvern-AI/skyvern/pull/6481))
|
||||
- **Hardened Webhook Delivery** — Workflow webhook delivery is now more reliable, with improved handling of transient failures and prioritized delivery ordering. ([#6478](https://github.com/Skyvern-AI/skyvern/pull/6478))
|
||||
- **Reduced Live Recording Draft Latency** — Live session recordings now appear almost instantly with placeholder entries, with final blocks committed after a short debounce window. ([#6553](https://github.com/Skyvern-AI/skyvern/pull/6553))
|
||||
- **Copilot Stops on Terminal Blockers** — The Copilot now correctly halts when it reaches a condition that blocks further progress, preventing runaway sessions. ([#6535](https://github.com/Skyvern-AI/skyvern/pull/6535))
|
||||
- **Copilot Chat Shows Run Outcome Verdict** — The Copilot chat timeline now reflects the actual run outcome verdict, giving a more accurate view of what the agent accomplished. ([#6532](https://github.com/Skyvern-AI/skyvern/pull/6532))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
|
|
@ -72,6 +229,23 @@ keywords:
|
|||
- Fixed persistent-session screen recordings not appearing in the run view when the recording timestamp fell outside the run's time window. ([#6454](https://github.com/Skyvern-AI/skyvern/pull/6454))
|
||||
- Fixed Copilot inconsistently asking for a URL before running discovery when the user had only named a site without providing one. ([#6473](https://github.com/Skyvern-AI/skyvern/pull/6473))
|
||||
- Fixed Copilot asking for a URL after already successfully navigating to the requested site during discovery. ([#6472](https://github.com/Skyvern-AI/skyvern/pull/6472))
|
||||
- Fixed self-hosted deployments rejecting requests with "Invalid credentials" (HTTP 403) when the Docker UI injected an API key that the container's server incorrectly filtered out.
|
||||
- Fixed persistent session recordings not being finalized when the video encoding process outlasted the session's cleanup window. ([#6519](https://github.com/Skyvern-AI/skyvern/pull/6519))
|
||||
- Fixed the saved credentials status indicator not updating until the page was manually refreshed. ([#6517](https://github.com/Skyvern-AI/skyvern/pull/6517))
|
||||
- Fixed the workflow run timeline rendering blocks in branch-tree order instead of execution order, producing a confusing step sequence. ([#6515](https://github.com/Skyvern-AI/skyvern/pull/6515))
|
||||
- Fixed downloaded files inside loop blocks being shared across all iterations instead of scoped to the block that downloaded them. ([#6487](https://github.com/Skyvern-AI/skyvern/pull/6487))
|
||||
- Fixed session recordings defaulting to an incorrect resolution; recordings now use Playwright's default viewport size. ([#6524](https://github.com/Skyvern-AI/skyvern/pull/6524))
|
||||
- Fixed Copilot failing to recognize and use a saved credential when the credential ID was typed with a space or hyphen separator instead of an underscore; malformed IDs are now normalized and resolved correctly. ([#6529](https://github.com/Skyvern-AI/skyvern/pull/6529))
|
||||
- Fixed Copilot chat showing workflow blocks as completed even when the overall run goal was not demonstrated — the recorded run outcome verdict is now surfaced in the chat narrative. ([#6528](https://github.com/Skyvern-AI/skyvern/pull/6528))
|
||||
- Fixed Copilot browser sessions incorrectly blocking localhost navigation during page scouting, which could prevent evidence from being gathered from locally-served pages. ([#6527](https://github.com/Skyvern-AI/skyvern/pull/6527))
|
||||
- Fixed single-element JSON arrays being unwrapped to a scalar when passed as workflow run inputs. ([#6560](https://github.com/Skyvern-AI/skyvern/pull/6560))
|
||||
- Fixed code blocks silently dropping non-dict return values instead of passing them through to downstream blocks. ([#6556](https://github.com/Skyvern-AI/skyvern/pull/6556))
|
||||
- Fixed the task agent ignoring the `max_iterations` override, causing runs to exceed their configured step limit. ([#6544](https://github.com/Skyvern-AI/skyvern/pull/6544))
|
||||
- Fixed generated workflow parameter keys being duplicated, which caused a hard failure when the workflow was run. ([#6543](https://github.com/Skyvern-AI/skyvern/pull/6543))
|
||||
- Fixed task runs completing successfully even when a required sub-goal had not been satisfied. ([#6546](https://github.com/Skyvern-AI/skyvern/pull/6546))
|
||||
- Fixed the credential-clear confirmation dialog being hidden behind other overlays. ([#6542](https://github.com/Skyvern-AI/skyvern/pull/6542))
|
||||
- Fixed click actions on elements wrapped in disabled containers not being retargeted to the clickable child element. ([#6540](https://github.com/Skyvern-AI/skyvern/pull/6540))
|
||||
- Fixed Copilot loop detector incorrectly triggering at block dispatch boundaries. ([#6550](https://github.com/Skyvern-AI/skyvern/pull/6550))
|
||||
|
||||
</Update>
|
||||
|
||||
|
|
@ -261,8 +435,8 @@ keywords:
|
|||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-24"></a>
|
||||
<Update label="v1.0.24 — April 21, 2026" description="Copilot reliability, run recordings, 2FA improvements, and more">
|
||||
<a id="week-apr-20-2026"></a>
|
||||
<Update label="Week of April 20, 2026" description="Copilot reliability, run recordings, 2FA improvements, and more">
|
||||
|
||||
## Improvements
|
||||
|
||||
|
|
@ -279,8 +453,8 @@ keywords:
|
|||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-23"></a>
|
||||
<Update label="v1.0.23 — April 14, 2026" description="Saudi Arabia proxy, workflow error mapping, smarter caching, MCP OAuth, AI output summaries, and reliability fixes">
|
||||
<a id="week-apr-13-2026"></a>
|
||||
<Update label="Week of April 13, 2026" description="Saudi Arabia proxy, workflow error mapping, smarter caching, MCP OAuth, AI output summaries, and reliability fixes">
|
||||
|
||||
## New features
|
||||
|
||||
|
|
@ -324,38 +498,35 @@ keywords:
|
|||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-22"></a>
|
||||
<Update label="v1.0.22 — February 26, 2026" description="Adaptive caching, Workflow Trigger block, CLI signup, and more">
|
||||
<a id="week-feb-23-2026"></a>
|
||||
<Update label="Week of February 23, 2026" description="Adaptive caching, Workflow Trigger block, CLI signup, reserved parameters, new LLM models">
|
||||
|
||||
## New features
|
||||
|
||||
- **Adaptive Caching (Script Generation)** — Skyvern can now learn from repeated workflow runs and generate cached scripts that speed up future executions. When a block runs successfully, Skyvern records a reusable script and replays it on subsequent runs, falling back to the AI agent only if the script fails. ([#4908](https://github.com/Skyvern-AI/skyvern/pull/4908), [#4916](https://github.com/Skyvern-AI/skyvern/pull/4916), [#4917](https://github.com/Skyvern-AI/skyvern/pull/4917), [#4920](https://github.com/Skyvern-AI/skyvern/pull/4920), [#4922](https://github.com/Skyvern-AI/skyvern/pull/4922), [#4931](https://github.com/Skyvern-AI/skyvern/pull/4931))
|
||||
|
||||
- **Workflow Trigger Block** — A new block type that lets one workflow trigger another from within the workflow editor. Chain workflows together as building blocks for complex automations. ([#4885](https://github.com/Skyvern-AI/skyvern/pull/4885))
|
||||
|
||||
- **Browser-based CLI Signup** — New users can sign up for Skyvern Cloud directly from the CLI. Running `skyvern signup` opens a browser flow that creates your account and stores your API key locally. ([#4925](https://github.com/Skyvern-AI/skyvern/pull/4925))
|
||||
|
||||
- **Interactive ngrok Tunnel** — `skyvern browser serve` can now create an ngrok tunnel automatically, making it easy to expose your local browser to Skyvern Cloud without manual network configuration. ([#4924](https://github.com/Skyvern-AI/skyvern/pull/4924))
|
||||
|
||||
- **South Korea Proxy Location** — Added `RESIDENTIAL_KR` as a proxy geolocation option for automations targeting South Korean websites. ([#4918](https://github.com/Skyvern-AI/skyvern/pull/4918))
|
||||
|
||||
- **Downloaded Files Tab** — Browser session detail pages now include a Downloaded Files tab for viewing and accessing files captured during a session. ([#4911](https://github.com/Skyvern-AI/skyvern/pull/4911))
|
||||
|
||||
- **CDP Proxy Authentication** — Remote browser connections now support authenticated proxies via the CDP `Fetch.authRequired` protocol. ([#4936](https://github.com/Skyvern-AI/skyvern/pull/4936))
|
||||
|
||||
- **Remote Browser Download Interception** — File downloads triggered by XHR requests and other non-navigation events are now captured when using remote CDP browser connections. ([#4906](https://github.com/Skyvern-AI/skyvern/pull/4906), [#4921](https://github.com/Skyvern-AI/skyvern/pull/4921), [#4934](https://github.com/Skyvern-AI/skyvern/pull/4934))
|
||||
- **`current_date` Reserved Parameter** — Workflows now have a built-in `current_date` parameter that resolves to today's date automatically. ([#4854](https://github.com/Skyvern-AI/skyvern/pull/4854))
|
||||
- **Reserved Parameters in Block Editor** — The workflow block parameter picker now shows reserved system parameters, making them discoverable without memorizing names. ([#4857](https://github.com/Skyvern-AI/skyvern/pull/4857))
|
||||
- **Natural Language Loop `data_schema`** — Loop blocks driven by natural language extraction now support a `data_schema` field for consistent output structure. ([#4851](https://github.com/Skyvern-AI/skyvern/pull/4851))
|
||||
- **Gemini 3.1 Pro and Inception Mercury-2** — Two new LLM engine options for your automations. ([#4847](https://github.com/Skyvern-AI/skyvern/pull/4847))
|
||||
- **MCP Server on API Service** — The MCP remote server is now mounted at `/mcp` on the existing API, eliminating the need for a separate process. ([#4843](https://github.com/Skyvern-AI/skyvern/pull/4843))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **Renamed "Login-Free" to "Saved Profile"** — Clearer terminology throughout the UI. Browser session checkbox wording has also been improved. ([#4914](https://github.com/Skyvern-AI/skyvern/pull/4914))
|
||||
|
||||
- **TOTP Verification Improvements** — Better timer handling, expired code retry, 2FA banner suppression, and more reliable goal-text extraction during TOTP flows. ([#4860](https://github.com/Skyvern-AI/skyvern/pull/4860))
|
||||
|
||||
- **TOTP Webhook includes `workflow_permanent_id`** — Easier to identify which workflow is requesting a 2FA code. ([#4871](https://github.com/Skyvern-AI/skyvern/pull/4871))
|
||||
|
||||
- **Consolidated Gemini 3 Pro Model Key** — `VERTEX_GEMINI_3_PRO` now auto-resolves to the latest version, so you no longer need to update config when Google releases point versions. ([#4926](https://github.com/Skyvern-AI/skyvern/pull/4926))
|
||||
|
||||
- **Browser Rotation for Remote Connections** — Remote browser environments now support context rotation, improving reliability for long-running automations. ([#4929](https://github.com/Skyvern-AI/skyvern/pull/4929))
|
||||
- Workflow save validation (HTTP 422) now returns clear, field-level error messages. ([#4852](https://github.com/Skyvern-AI/skyvern/pull/4852))
|
||||
- Browser launch errors now show actionable messages instead of raw exceptions. ([#4844](https://github.com/Skyvern-AI/skyvern/pull/4844))
|
||||
- Cloud LLM fallback overrides are now properly applied when selecting models. ([#4839](https://github.com/Skyvern-AI/skyvern/pull/4839))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
|
|
@ -367,151 +538,53 @@ keywords:
|
|||
- MCP remote auth token comparison no longer fails on encrypted tokens. ([#4863](https://github.com/Skyvern-AI/skyvern/pull/4863))
|
||||
- `skyvern quickstart` now handles local PostgreSQL without a pre-existing `skyvern` role. ([#4878](https://github.com/Skyvern-AI/skyvern/pull/4878))
|
||||
- WebSocket URLs through ngrok tunnels now rewrite correctly for live browser streaming. ([#4927](https://github.com/Skyvern-AI/skyvern/pull/4927))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-21"></a>
|
||||
<Update label="v1.0.21 — February 24, 2026" description="Reserved parameters, data_schema for loops, new LLM models">
|
||||
|
||||
## New features
|
||||
|
||||
- **`current_date` Reserved Parameter** — Workflows now have a built-in `current_date` parameter that resolves to today's date automatically. ([#4854](https://github.com/Skyvern-AI/skyvern/pull/4854))
|
||||
|
||||
- **Reserved Parameters in Block Editor** — The workflow block parameter picker now shows reserved system parameters, making them discoverable without memorizing names. ([#4857](https://github.com/Skyvern-AI/skyvern/pull/4857))
|
||||
|
||||
- **Natural Language Loop `data_schema`** — Loop blocks driven by natural language extraction now support a `data_schema` field for consistent output structure. ([#4851](https://github.com/Skyvern-AI/skyvern/pull/4851))
|
||||
|
||||
- **Gemini 3.1 Pro and Inception Mercury-2** — Two new LLM engine options for your automations. ([#4847](https://github.com/Skyvern-AI/skyvern/pull/4847))
|
||||
|
||||
- **MCP Server on API Service** — The MCP remote server is now mounted at `/mcp` on the existing API, eliminating the need for a separate process. ([#4843](https://github.com/Skyvern-AI/skyvern/pull/4843))
|
||||
|
||||
## Improvements
|
||||
|
||||
- Workflow save validation (HTTP 422) now returns clear, field-level error messages. ([#4852](https://github.com/Skyvern-AI/skyvern/pull/4852))
|
||||
- Browser launch errors now show actionable messages instead of raw exceptions. ([#4844](https://github.com/Skyvern-AI/skyvern/pull/4844))
|
||||
- Cloud LLM fallback overrides are now properly applied when selecting models. ([#4839](https://github.com/Skyvern-AI/skyvern/pull/4839))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Conditional blocks no longer crash when all branches use Jinja templates. ([#4849](https://github.com/Skyvern-AI/skyvern/pull/4849))
|
||||
- Conditional blocks no longer misinterpret resolved Jinja template variables. ([#4841](https://github.com/Skyvern-AI/skyvern/pull/4841))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-20"></a>
|
||||
<Update label="v1.0.20 — February 21, 2026" description="Browser profile testing UI and 2FA verification flow">
|
||||
<a id="week-feb-16-2026"></a>
|
||||
<Update label="Week of February 16, 2026" description="Unified Browser Task block, browser profile testing, 2FA detection, Skills package, Claude Opus 4.6, MCP block discovery">
|
||||
|
||||
## New features
|
||||
|
||||
- **Browser Profile Testing UI (Frontend)** — The Browsers page now lets you launch a test run against a saved browser profile to confirm its login state is still valid before scheduling production workflows. ([#4833](https://github.com/Skyvern-AI/skyvern/pull/4833))
|
||||
|
||||
- **2FA Verification Code UI and Notifications** — When a workflow pauses for a 2FA code, the UI now shows a clear prompt and pushes a notification so you don't miss it. ([#4787](https://github.com/Skyvern-AI/skyvern/pull/4787))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **2FA Backend Cleanup** — Refactored the 2FA pipeline to make code delivery more reliable across both the UI form and the API endpoint. ([#4826](https://github.com/Skyvern-AI/skyvern/pull/4826))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-19"></a>
|
||||
<Update label="v1.0.19 — February 20, 2026" description="Admin impersonation controls and configuration improvements">
|
||||
|
||||
## New features
|
||||
|
||||
- **Gated Admin Impersonation for MCP API Keys** — Adds gated admin controls so support engineers can impersonate an organization scope when troubleshooting MCP-based automations, with audit-friendly access controls. ([#4822](https://github.com/Skyvern-AI/skyvern/pull/4822))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **Environment Variables Override Mounted API Keys** — In Skyvern's Streamlit-based deployment, env vars now take precedence over keys baked into the image, making local overrides simpler. ([#4824](https://github.com/Skyvern-AI/skyvern/pull/4824))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-18"></a>
|
||||
<Update label="v1.0.18 — February 19, 2026" description="Browser profile testing and saved-profile workflows">
|
||||
|
||||
## New features
|
||||
|
||||
- **Browser Profile Testing** — Test browser profiles directly from the UI to verify that saved login sessions are still valid. Workflows can also run with a saved browser profile, enabling login-free automations that reuse authenticated sessions. ([#4818](https://github.com/Skyvern-AI/skyvern/pull/4818))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- When both a TOTP credential and a webhook are configured for 2FA, the credential is now correctly prioritized. ([#4811](https://github.com/Skyvern-AI/skyvern/pull/4811))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-17"></a>
|
||||
<Update label="v1.0.17 — February 19, 2026" description="Skills package and cached script management">
|
||||
|
||||
## New features
|
||||
|
||||
- **Skyvern Skills Package** — The new `skyvern skill` CLI command provides pre-built workflow templates and reference documentation for common automation patterns. ([#4817](https://github.com/Skyvern-AI/skyvern/pull/4817))
|
||||
|
||||
- **Clear Cached Scripts API** — A new endpoint lets you clear cached automation scripts for a workflow when a target website changes and you want to force Skyvern to re-learn. ([#4809](https://github.com/Skyvern-AI/skyvern/pull/4809))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-16"></a>
|
||||
<Update label="v1.0.16 — February 19, 2026" description="2FA detection, full CLI parity, Claude Opus 4.6 CUA">
|
||||
|
||||
## New features
|
||||
|
||||
- **Automatic 2FA Detection Without TOTP Credentials** — Skyvern now detects when a website asks for a 2FA code even without pre-configured TOTP credentials. The system pauses and waits for you to provide the code via the UI or webhook. ([#4786](https://github.com/Skyvern-AI/skyvern/pull/4786))
|
||||
|
||||
- **Full CLI Parity with MCP** — The CLI now supports browser session management, credential management, block operations, and enhanced workflow commands. Everything available through MCP is now accessible from the command line. ([#4789](https://github.com/Skyvern-AI/skyvern/pull/4789), [#4792](https://github.com/Skyvern-AI/skyvern/pull/4792), [#4793](https://github.com/Skyvern-AI/skyvern/pull/4793))
|
||||
|
||||
- **Claude Opus 4.6 CUA Support** — Anthropic's Claude Opus 4.6 is now available as a Computer Use Agent model for driving browser interactions. ([#4780](https://github.com/Skyvern-AI/skyvern/pull/4780))
|
||||
|
||||
## Improvements
|
||||
|
||||
- The workflow run timeline now properly displays loop iterations and conditional branches, making complex runs easier to debug. ([#4782](https://github.com/Skyvern-AI/skyvern/pull/4782))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Fixed conditional blocks evaluating the wrong value after Jinja template rendering. ([#4801](https://github.com/Skyvern-AI/skyvern/pull/4801))
|
||||
- Fixed MFA resolution priority when both TOTP credentials and webhooks are configured. ([#4800](https://github.com/Skyvern-AI/skyvern/pull/4800))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-15"></a>
|
||||
<Update label="v1.0.15 — February 17, 2026" description="Claude Opus 4.6 model support">
|
||||
|
||||
## New features
|
||||
|
||||
- **Anthropic Claude Opus 4.6** — Added Claude Opus 4.6 as an available LLM engine for web automation tasks. ([#4777](https://github.com/Skyvern-AI/skyvern/pull/4777), [#4778](https://github.com/Skyvern-AI/skyvern/pull/4778))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-14"></a>
|
||||
<Update label="v1.0.14 — February 17, 2026" description="Unified Browser Task block, MCP block discovery, and credential editing">
|
||||
|
||||
## New features
|
||||
|
||||
- **Unified Browser Task Block** — The Navigation V1 and Task V2 blocks have been merged into a single **Browser Task** block. The block now exposes both engines as a dropdown, simplifying the workflow editor and reducing block-type confusion. ([#4695](https://github.com/Skyvern-AI/skyvern/pull/4695))
|
||||
|
||||
- **Block Discovery MCP Tools** — Added MCP tools that let AI assistants enumerate available block types and their schemas, plus richer instructions for building workflows through MCP. ([#4683](https://github.com/Skyvern-AI/skyvern/pull/4683))
|
||||
|
||||
- **Edit Existing Credentials API** — A new endpoint lets you update credential values without deleting and recreating them, preserving credential IDs across changes. ([#4693](https://github.com/Skyvern-AI/skyvern/pull/4693))
|
||||
|
||||
- **Filter Workflow Runs by Error Code and Search Key** — The workflow runs list endpoint now supports `error_code` and `search_key` query parameters for narrowing down failed runs. ([#4694](https://github.com/Skyvern-AI/skyvern/pull/4694))
|
||||
|
||||
- **GPT-5 Mini in Model Selector** — GPT-5 Mini is now selectable as an LLM engine. GPT-5 has been hidden in favor of more reliable variants. ([#4686](https://github.com/Skyvern-AI/skyvern/pull/4686))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **2FA Backend Cleanup** — Refactored the 2FA pipeline to make code delivery more reliable across both the UI form and the API endpoint. ([#4826](https://github.com/Skyvern-AI/skyvern/pull/4826))
|
||||
- **Environment Variables Override Mounted API Keys** — In Skyvern's Streamlit-based deployment, env vars now take precedence over keys baked into the image, making local overrides simpler. ([#4824](https://github.com/Skyvern-AI/skyvern/pull/4824))
|
||||
- The workflow run timeline now properly displays loop iterations and conditional branches, making complex runs easier to debug. ([#4782](https://github.com/Skyvern-AI/skyvern/pull/4782))
|
||||
- **Block Failure Reasons Surfaced in UI** — Every block type now shows its `failure_reason` in the run timeline, making debugging non-obvious failures faster. ([#4672](https://github.com/Skyvern-AI/skyvern/pull/4672))
|
||||
|
||||
- **Webhook Payload Truncation in Logs** — Large webhook payloads are now truncated in log entries, keeping logs readable without losing context. ([#4701](https://github.com/Skyvern-AI/skyvern/pull/4701))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- When both a TOTP credential and a webhook are configured for 2FA, the credential is now correctly prioritized. ([#4811](https://github.com/Skyvern-AI/skyvern/pull/4811))
|
||||
- Fixed conditional blocks evaluating the wrong value after Jinja template rendering. ([#4801](https://github.com/Skyvern-AI/skyvern/pull/4801))
|
||||
- Fixed MFA resolution priority when both TOTP credentials and webhooks are configured. ([#4800](https://github.com/Skyvern-AI/skyvern/pull/4800))
|
||||
- Fixed the cursor jumping to the end while editing conditional expressions in the workflow editor. ([#4682](https://github.com/Skyvern-AI/skyvern/pull/4682))
|
||||
- Fixed dotted Jinja variables (e.g. `{{ block_output.field }}`) rendering incorrectly in the expression preview. ([#4684](https://github.com/Skyvern-AI/skyvern/pull/4684))
|
||||
- The API now returns 404 instead of 500 when a workflow is not found. ([#4699](https://github.com/Skyvern-AI/skyvern/pull/4699))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-13"></a>
|
||||
<Update label="v1.0.13 — February 10, 2026" description="Cached scripts for control-flow blocks, OTEL, and workflow editor polish">
|
||||
<a id="week-feb-9-2026"></a>
|
||||
<Update label="Week of February 9, 2026" description="Cached scripts for control-flow blocks, OTEL, and workflow editor polish">
|
||||
|
||||
## New features
|
||||
|
||||
|
|
@ -541,8 +614,8 @@ keywords:
|
|||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-12"></a>
|
||||
<Update label="v1.0.12 — February 3, 2026" description="Task V2 termination, ForLoop caching, and cleaner conditional debugging">
|
||||
<a id="week-feb-2-2026"></a>
|
||||
<Update label="Week of February 2, 2026" description="Task V2 termination, ForLoop caching, and cleaner conditional debugging">
|
||||
|
||||
## New features
|
||||
|
||||
|
|
@ -574,8 +647,8 @@ keywords:
|
|||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-11"></a>
|
||||
<Update label="v1.0.11 — January 29, 2026" description="Workflow Copilot GA, Browser Sessions v2 frontend, and TOTP improvements">
|
||||
<a id="week-jan-26-2026"></a>
|
||||
<Update label="Week of January 26, 2026" description="Workflow Copilot GA, Browser Sessions v2 frontend, and TOTP improvements">
|
||||
|
||||
## New features
|
||||
|
||||
|
|
@ -605,26 +678,32 @@ keywords:
|
|||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-10"></a>
|
||||
<Update label="v1.0.10 — January 22, 2026" description="Browser Sessions v2 backend, general text CAPTCHA, and TOTP webhook retries">
|
||||
<a id="week-jan-19-2026"></a>
|
||||
<Update label="Week of January 19, 2026" description="Browser Sessions v2, Print PDF block, Copilot streaming, general text CAPTCHA, HTTP file downloads">
|
||||
|
||||
## New features
|
||||
|
||||
- **Browser Sessions v2 (Backend)** — A new persistent browser session architecture with cleaner lifecycle management, better resource reuse, and improved reliability for long-running automations. The frontend follows in v1.0.11. ([#4515](https://github.com/Skyvern-AI/skyvern/pull/4515))
|
||||
|
||||
- **General Text CAPTCHA Solver** — Skyvern can now solve a wider range of text-based CAPTCHAs without site-specific configuration. ([#4517](https://github.com/Skyvern-AI/skyvern/pull/4517))
|
||||
|
||||
- **TOTP Webhook Retries** — TOTP webhook delivery now retries automatically on transient failures, reducing the rate of "no code received" errors during 2FA flows. ([#4518](https://github.com/Skyvern-AI/skyvern/pull/4518))
|
||||
|
||||
- **Block-Label Validation in `run_blocks`** — The `run_blocks` endpoint now validates block labels up front, returning a clear error instead of failing partway through execution. ([#4500](https://github.com/Skyvern-AI/skyvern/pull/4500))
|
||||
- **Print PDF Block** — A new workflow block that prints the current page to PDF and saves it to your run's downloaded files, useful for archiving receipts, invoices, and reports. ([#4452](https://github.com/Skyvern-AI/skyvern/pull/4452))
|
||||
- **HTTP File Downloads** — The HTTP Request block can now download files directly via HTTP (not just GET JSON), enabling workflows that pull artifacts from authenticated APIs. ([#4440](https://github.com/Skyvern-AI/skyvern/pull/4440))
|
||||
- **Workflow Copilot Streaming with Cancel** — The Workflow Copilot now streams its responses with a cancel button, so you can stop generation mid-stream if you want to refine your prompt. ([#4437](https://github.com/Skyvern-AI/skyvern/pull/4437), [#4456](https://github.com/Skyvern-AI/skyvern/pull/4456))
|
||||
- **"Execute on Any Outcome" (Finally) Block Option** — Blocks can now be configured to run regardless of whether prior blocks succeeded, enabling cleanup steps and "always send report" workflows. ([#4443](https://github.com/Skyvern-AI/skyvern/pull/4443))
|
||||
- **Persistent Browser Session Uptime Billing** — Billing v2 now meters persistent browser session uptime separately, with PostHog feature flags controlling rollout. ([#4444](https://github.com/Skyvern-AI/skyvern/pull/4444))
|
||||
- **GPT-5 Mini Flex Engine** — Added GPT-5 Mini Flex as an available LLM engine. ([#4432](https://github.com/Skyvern-AI/skyvern/pull/4432))
|
||||
- **Clipboard Copy over HTTP** — The browser now exposes clipboard copy functionality that works in HTTP-served browser sessions, not just HTTPS. ([#4446](https://github.com/Skyvern-AI/skyvern/pull/4446))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **Confirmation Dialog Shows Affected Blocks** — Deleting a parameter or block now lists every block that references it, so you don't accidentally break downstream logic. ([#4519](https://github.com/Skyvern-AI/skyvern/pull/4519))
|
||||
|
||||
- **Workflow Updates Return 409 on Race** — Concurrent workflow updates now return HTTP 409 instead of silently overwriting each other. ([#4510](https://github.com/Skyvern-AI/skyvern/pull/4510))
|
||||
|
||||
- **Tiktoken Caching** — Tokenizer instances are now cached, cutting per-step overhead on token counting. ([#4521](https://github.com/Skyvern-AI/skyvern/pull/4521))
|
||||
- **HTTP Block Boolean and Integer Templates** — The HTTP Request block now correctly passes boolean and integer template values without coercing them to strings. ([#4435](https://github.com/Skyvern-AI/skyvern/pull/4435))
|
||||
- **Bitwarden and Azure Vault Tooltips** — Added inline help tooltips explaining how to set up Bitwarden and Azure Key Vault credential sources. ([#4447](https://github.com/Skyvern-AI/skyvern/pull/4447))
|
||||
- **Smaller S3 Objects Use STANDARD Tier** — Storage cost optimization: small artifacts now use STANDARD instead of GLACIER_IR. ([#4453](https://github.com/Skyvern-AI/skyvern/pull/4453))
|
||||
- **Reduced Max SVG Parsing** — Lowered the SVG parsing cap to prevent runaway memory usage on pathological pages. ([#4430](https://github.com/Skyvern-AI/skyvern/pull/4430))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
|
|
@ -634,39 +713,8 @@ keywords:
|
|||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-9"></a>
|
||||
<Update label="v1.0.9 — January 20, 2026" description="Print PDF block, Workflow Copilot streaming, and persistent session billing">
|
||||
|
||||
## New features
|
||||
|
||||
- **Print PDF Block** — A new workflow block that prints the current page to PDF and saves it to your run's downloaded files, useful for archiving receipts, invoices, and reports. ([#4452](https://github.com/Skyvern-AI/skyvern/pull/4452))
|
||||
|
||||
- **HTTP File Downloads** — The HTTP Request block can now download files directly via HTTP (not just GET JSON), enabling workflows that pull artifacts from authenticated APIs. ([#4440](https://github.com/Skyvern-AI/skyvern/pull/4440))
|
||||
|
||||
- **Workflow Copilot Streaming with Cancel** — The Workflow Copilot now streams its responses with a cancel button, so you can stop generation mid-stream if you want to refine your prompt. ([#4437](https://github.com/Skyvern-AI/skyvern/pull/4437), [#4456](https://github.com/Skyvern-AI/skyvern/pull/4456))
|
||||
|
||||
- **"Execute on Any Outcome" (Finally) Block Option** — Blocks can now be configured to run regardless of whether prior blocks succeeded, enabling cleanup steps and "always send report" workflows. ([#4443](https://github.com/Skyvern-AI/skyvern/pull/4443))
|
||||
|
||||
- **Persistent Browser Session Uptime Billing** — Billing v2 now meters persistent browser session uptime separately, with PostHog feature flags controlling rollout. ([#4444](https://github.com/Skyvern-AI/skyvern/pull/4444))
|
||||
|
||||
- **GPT-5 Mini Flex Engine** — Added GPT-5 Mini Flex as an available LLM engine. ([#4432](https://github.com/Skyvern-AI/skyvern/pull/4432))
|
||||
|
||||
- **Clipboard Copy over HTTP** — The browser now exposes clipboard copy functionality that works in HTTP-served browser sessions, not just HTTPS. ([#4446](https://github.com/Skyvern-AI/skyvern/pull/4446))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **HTTP Block Boolean and Integer Templates** — The HTTP Request block now correctly passes boolean and integer template values without coercing them to strings. ([#4435](https://github.com/Skyvern-AI/skyvern/pull/4435))
|
||||
|
||||
- **Bitwarden and Azure Vault Tooltips** — Added inline help tooltips explaining how to set up Bitwarden and Azure Key Vault credential sources. ([#4447](https://github.com/Skyvern-AI/skyvern/pull/4447))
|
||||
|
||||
- **Smaller S3 Objects Use STANDARD Tier** — Storage cost optimization: small artifacts now use STANDARD instead of GLACIER_IR. ([#4453](https://github.com/Skyvern-AI/skyvern/pull/4453))
|
||||
|
||||
- **Reduced Max SVG Parsing** — Lowered the SVG parsing cap to prevent runaway memory usage on pathological pages. ([#4430](https://github.com/Skyvern-AI/skyvern/pull/4430))
|
||||
|
||||
</Update>
|
||||
|
||||
<a id="v1-0-8"></a>
|
||||
<Update label="v1.0.8 — January 9, 2026" description="Workflow Copilot v1, Azure secret storage, and per-action billing">
|
||||
<a id="week-jan-5-2026"></a>
|
||||
<Update label="Week of January 5, 2026" description="Workflow Copilot v1, Azure secret storage, and per-action billing">
|
||||
|
||||
## New features
|
||||
|
||||
|
|
|
|||
|
|
@ -23,14 +23,14 @@ Open **Billing** in the sidebar to see available plans and your current balance.
|
|||
|
||||
<img src="/images/cloud/settings-billing-overview.png" alt="Billing page showing plan options and current balance" />
|
||||
|
||||
| Plan | Price | Credits/month | Estimated actions | Concurrent runs |
|
||||
|------|-------|---------------|-------------------|-----------------|
|
||||
| **Free** | $0 | 1,000 | ~170 | 1 |
|
||||
| **Hobby** | $29/month | 30,000 | ~1,200 | 10 |
|
||||
| **Pro** | $149/month | 150,000 | ~6,200 | 25 |
|
||||
| Plan | Price | Credits | Estimated actions | Concurrent runs |
|
||||
|------|-------|---------|-------------------|-----------------|
|
||||
| **Free** | $0 | 5,000 one-time | ~200 | 1 |
|
||||
| **Hobby** | $29/month | 30,000/month | ~1,200 | 10 |
|
||||
| **Pro** | $149/month | 150,000/month | ~6,200 | 25 |
|
||||
| **Enterprise** | Custom | Unlimited | Unlimited | Unlimited |
|
||||
|
||||
**Free** is available to all new accounts with zero commitment. **Hobby** and **Pro** are monthly subscriptions. Click **Switch to Hobby** or **Switch to Pro** to change plans. Your remaining dollar balance is applied as a credit toward your first subscription payment.
|
||||
**Free** is available to all new accounts with a one-time credit grant and zero commitment. **Hobby** and **Pro** are monthly subscriptions. Click **Switch to Hobby** or **Switch to Pro** to change plans. Your remaining dollar balance is applied as a credit toward your first subscription payment.
|
||||
|
||||
<Note>
|
||||
Need HIPAA compliance, SOC-2 reports, custom code blocks, or dedicated support? Use the **Book a call** link at the bottom of the Billing page to discuss **Enterprise**, or visit [skyvern.com/pricing](https://skyvern.com/pricing) for a complete feature comparison.
|
||||
|
|
@ -40,7 +40,7 @@ Need HIPAA compliance, SOC-2 reports, custom code blocks, or dedicated support?
|
|||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Free: Try Skyvern with zero commitment">
|
||||
**1,000 credits/month** (~170 actions)
|
||||
**5,000 one-time credits** (~200 actions)
|
||||
|
||||
Perfect for evaluating Skyvern and prototyping automations.
|
||||
|
||||
|
|
@ -117,11 +117,11 @@ The **Your Current Balance** section shows your remaining dollar balance. Credit
|
|||
## FAQ
|
||||
|
||||
<Accordion title="How do credits work?">
|
||||
Each browser action the AI takes (clicking, typing, navigating, extracting) costs one credit. Credits are deducted in real time as runs execute. Your plan includes a monthly credit allowance that resets each billing cycle. Unused credits don't roll over.
|
||||
Each browser action the AI takes (clicking, typing, navigating, extracting) costs one credit. Credits are deducted in real time as runs execute. Free accounts receive a one-time credit grant. Paid plans include a monthly credit allowance that resets each billing cycle. Unused included credits don't roll over.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Can I buy more credits?">
|
||||
Yes. If you exhaust your monthly allowance, you can purchase additional credits from the Billing page. You can also upgrade to a higher plan for a larger monthly allowance.
|
||||
Yes. If you exhaust your included allowance, you can purchase additional credits from the Billing page. You can also upgrade to a higher plan for a larger monthly allowance.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Can I cancel anytime?">
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ From the session detail page, click **Stop**. A confirmation dialog appears. The
|
|||
Sessions also close automatically when their timeout expires, **even if a task is still running**. Set timeouts with enough margin for your longest expected task.
|
||||
|
||||
<Warning>
|
||||
Closed sessions cannot be reopened. If you need the same login state later, create a [browser profile](/cloud/browser-management/browser-profiles) before closing.
|
||||
Closed sessions cannot be reopened, and a session only saves its browser state at close when profile generation is enabled for it. The **Save browser session** credential flow handles this automatically; for API-created sessions, see [Save a session's profile](/developers/optimization/browser-sessions#save-a-sessions-profile). If you need the same login state later, capture it as a [browser profile](/cloud/browser-management/browser-profiles) before closing.
|
||||
</Warning>
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -58,9 +58,13 @@ Browser-based blocks (Browser Task, Browser Action, Extraction, Login, File Down
|
|||
| **Max Steps Override** | Cap the number of AI reasoning steps |
|
||||
| **Disable Cache** | Skip cached script execution |
|
||||
| **TOTP Identifier** | Link TOTP credentials for 2FA handling |
|
||||
| **TOTP Verification URL** | Endpoint for fetching TOTP codes |
|
||||
| **TOTP Verification URL** | Endpoint this block polls when it needs a 2FA code |
|
||||
| **Error Code Mapping** | Map error conditions to custom error codes (JSON) |
|
||||
|
||||
<Note>
|
||||
Set **TOTP Verification URL** on the block that may encounter 2FA. Top-level workflow run `totp_url` values do not automatically populate empty block fields.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Browser Automation
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ Restart Skyvern after setting these variables.
|
|||
| Status stays Inactive | Verify the API base URL is a valid URL and the API token is not empty. The configuration is validated on save but does not make a live request to your server. |
|
||||
| Credentials not created | Review your API logs for auth errors. Ensure the response includes an `id` field. Skyvern expects HTTP 200 for all operations. |
|
||||
| Credentials not retrieved | Ensure the GET response includes all required fields for the credential type (`username` and `password` for passwords, all card fields for credit cards, `secret_value` for secrets). |
|
||||
| Env config not working | Restart Skyvern after setting variables. Verify `CREDENTIAL_VAULT_TYPE=custom` is set and both URL and token are provided. The default vault type is `bitwarden`, so this variable must be explicitly set. |
|
||||
| Env config not working | Restart Skyvern after setting variables. Verify `CREDENTIAL_VAULT_TYPE=custom` is set and both URL and token are provided. Deployment defaults vary, so `custom` must be explicitly set for an external service. |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ The preferred method. Skyvern generates valid 6-digit codes on demand during log
|
|||
<Step title="Select Authenticator App">
|
||||
Choose **Authenticator App** from the three options.
|
||||
</Step>
|
||||
<Step title="Paste your TOTP secret key">
|
||||
Enter the secret key into the **Authenticator Key** field and click **Save**.
|
||||
<Step title="Add your TOTP setup key">
|
||||
Enter the secret key into the **Authenticator Key** field, or click **Scan QR** to upload a QR code image from the site's 2FA setup screen. Then click **Save**.
|
||||
<img src="/images/cloud/totp-setup-2.png" alt="Add Credential dialog with Authenticator App selected and the Authenticator Key field" />
|
||||
</Step>
|
||||
</Steps>
|
||||
|
|
@ -53,7 +53,7 @@ The secret key is the base32-encoded string behind the QR code you'd normally sc
|
|||
- **LastPass**: Edit the login → Advanced Settings → copy the TOTP secret
|
||||
- **Site settings**: Many sites show a "Can't scan?" link during 2FA setup that reveals the text key
|
||||
|
||||
If you only have a QR code, decode it to extract the `secret=` parameter from the `otpauth://totp/...?secret=BASE32KEY` URI.
|
||||
If you only have a QR code, use **Scan QR** in the credential form or paste the full `otpauth://totp/...?secret=BASE32KEY` URI.
|
||||
</Accordion>
|
||||
|
||||
---
|
||||
|
|
@ -171,7 +171,13 @@ This turns email-based 2FA into something nearly as automated as an authenticato
|
|||
|
||||
## Server-fetched codes (totp_url)
|
||||
|
||||
Instead of pushing codes to Skyvern, you can have Skyvern pull them from your server. Pass `totp_url` when running a [task](/cloud/getting-started/run-from-code) or [agent](/cloud/building-agents/build-an-agent), and Skyvern will call your endpoint when it needs a verification code.
|
||||
Instead of pushing codes to Skyvern, you can have Skyvern pull them from your server. Skyvern calls your endpoint only when the automation reaches a page that asks for a verification code.
|
||||
|
||||
<Warning>
|
||||
For saved agents or workflows, configure the endpoint on the block that performs the login. Open the browser, action, file download, or login block and set **TOTP Verification URL**. Passing `totp_url` only in the top-level workflow run request does not automatically populate a block whose **TOTP Verification URL** is empty.
|
||||
</Warning>
|
||||
|
||||
If the endpoint changes per run, create a workflow parameter such as `totp_url`, set the block's **TOTP Verification URL** to `{{ totp_url }}`, and pass the URL in `parameters` when starting the run.
|
||||
|
||||
Your endpoint must accept a POST request with `task_id`, `workflow_run_id`, and `workflow_permanent_id` in the body, and return:
|
||||
|
||||
|
|
@ -246,7 +252,7 @@ curl -X GET "https://api.skyvern.com/v1/credentials/totp?totp_identifier=user@ex
|
|||
| `otp_type` | Filter by `totp` or `magic_link` |
|
||||
| `limit` | Number of records (default 50, max 200) |
|
||||
|
||||
Returns a list ordered newest first. Only codes created within the last 10 minutes (configurable via `TOTP_LIFESPAN_MINUTES`) are returned.
|
||||
Returns historical records ordered newest first, capped by `limit`. Runtime polling still only uses unexpired codes within `TOTP_LIFESPAN_MINUTES`.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
|
|
|
|||
306
docs/design/2026-06-15-workflow-build-recent-activity-design.md
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
# Workflow Build — Recent Activity History (SKY-11075)
|
||||
|
||||
Replace the bottom-of-canvas **dot/carousel indicator** on `/workflows/:id/build` with a
|
||||
real recent-activity history view that's easy to scan and lets you jump directly to a
|
||||
specific recent activity.
|
||||
|
||||
Status: **Final — recent activity is a compact run selector locked to the right
|
||||
run-detail panel; the A/B/C style and placement preview toggles were removed. See
|
||||
the Round 7 section below.**
|
||||
|
||||
---
|
||||
|
||||
## 1. Frame
|
||||
|
||||
- **Page:** Workflow editor, *build* mode — `/workflows/:id/build` (and the run-loaded
|
||||
variant `/workflows/:wpid/:workflowRunId/:blockLabel/build`). The history surface only
|
||||
renders in **debug/browser mode** (`showBrowser`), bottom-center over the canvas+code
|
||||
pane. Redesign of an existing affordance.
|
||||
- **Job to be done:** While iterating on a workflow you fire blocks/the workflow many times
|
||||
in one debug session. Today those runs collapse into a row of identical ~16px dots whose
|
||||
only metadata is a hover tooltip. You can't tell at a glance *what* ran, *whether it
|
||||
passed*, *how long it took*, or *which mode* (agent vs cached code) — you must hover each
|
||||
dot one by one. The job: make each recent run legible at a glance and jump straight to it.
|
||||
- **Deciding constraint — what counts as "recent activity":** **Debug-session runs**
|
||||
(confirmed with requester). Each entry = one block/workflow run triggered in the current
|
||||
debug session, sourced from `GET /debug-session/{id}/runs` (`useDebugSessionRunsQuery`).
|
||||
No new backend. Deliberately distinct from (a) the global **Runs** page and (b) the
|
||||
right-side **run-detail timeline** (`DebuggerRun`/`DebuggerRunTimeline`) which shows the
|
||||
*inside* of one selected run. This surface is the *list of runs*; selecting one drives the
|
||||
existing detail rail — no overlapping history surfaces.
|
||||
- **Open sub-question (requester):** is a dock/strip the best surface, or do we want a
|
||||
"proper timeline"? → resolved via the concepts below; requester to pick direction.
|
||||
- **Platform:** web.
|
||||
- **North star references:** Databricks pipeline run-selector + event log; Vercel Activity feed.
|
||||
|
||||
### Data available per entry (`DebugSessionRun`) — today all hidden behind one dot
|
||||
`block_label`, `status` (running/completed/failed/terminated/timed_out/canceled/queued/
|
||||
skipped), `created_at` / `queued_at` / `started_at` / `finished_at` (→ duration + "x ago"),
|
||||
`failure_reason`, `run_with` (agent | code), `code_gen`, `ai_fallback`, `workflow_run_id`,
|
||||
`workflow_permanent_id`, `script_run_id`. Selecting → `navigate(/workflows/{wpid}/{workflow_run_id}/{block_label}/build)`.
|
||||
|
||||
---
|
||||
|
||||
## 2. DS inventory (read from code — Figma DS is thin by design)
|
||||
|
||||
| Need | Reuse (exists in repo) |
|
||||
|---|---|
|
||||
| Status glyph | `StatusDot` pattern (WorkflowRunTimelineBlockItem): `CheckCircledIcon text-success`, `CrossCircledIcon text-destructive`, `ReloadIcon animate-spin text-sky-400`, neutral `rounded-full bg-slate-600` |
|
||||
| Block-type glyph | `WorkflowBlockIcon` (per `WorkflowBlockType`) |
|
||||
| Type / mode pills | inline pill convention `rounded bg-slate-700/70 px-1.5 py-0.5 text-[10px] font-medium` |
|
||||
| Relative time / duration | `formatMs(Date.now()-created).ago`, `formatDuration(toDuration(ms))`, `tabular-nums` |
|
||||
| Tooltip | `Tip` (`@/components/Tip`) |
|
||||
| Scroll container | `ScrollArea` (`@/components/ui/scroll-area`) |
|
||||
| Dropdown / flyout | `Popover` (`@/components/ui/popover`) |
|
||||
| Expand / collapse | `Collapsible` (`@/components/ui/collapsible`) |
|
||||
| Buttons / badges | `Button`, `Badge` |
|
||||
| Surface tokens | `bg-neutral-50 dark:bg-background`, `border-neutral-200 dark:border-neutral-800`, focus `focus-visible:ring-1 focus-visible:ring-white/40` |
|
||||
|
||||
Conventions: build-mode rails skew dark (`slate-*`); pills `text-[10px]`, `tabular-nums` for
|
||||
numbers; every interactive row is a `<button>` with a visible focus ring.
|
||||
|
||||
## 3. Gap ledger (DS lacks → candidate Step-5 tickets)
|
||||
- No dedicated **Status badge** component — status color/icon mapping is re-derived inline in
|
||||
several places (`StatusDot`, run cards). Candidate: extract a shared `RunStatusBadge`.
|
||||
- No **horizontal "activity strip"/run-history rail** primitive.
|
||||
- (Append as concepts/implementation pressure the library.)
|
||||
|
||||
---
|
||||
|
||||
## 4. Inspiration (Mobbin — web)
|
||||
|
||||
1. **Databricks — pipeline "Update details"** — editor canvas with a **Run: {timestamp}
|
||||
[status]** selector top-left, a detail panel (Update ID, *Status, Duration, Start time,
|
||||
Run time, Completion date*), and a timestamped **Event log** below. Closest analog: a
|
||||
build canvas whose run history is a compact selector + per-run metadata.
|
||||
[link](https://mobbin.com/screens/2a53f9eb-b8e1-4958-afb7-f441acbdf414). a11y: the
|
||||
selector must be a real listbox/menu button, not a click-only div.
|
||||
2. **Vercel — Activity** — scannable vertical feed: each row = entity icon + plain-language
|
||||
description + **relative time** ("42m"), grouped by date, left filter rail. Gold standard
|
||||
for "legible at a glance."
|
||||
[link](https://mobbin.com/screens/2f3056eb-a31a-4b3e-ae4b-1bcc1352117f). a11y: relative
|
||||
time needs a `title`/`<time datetime>` with the absolute timestamp.
|
||||
3. **WorkOS — Events** — master-detail: list (event + date/time) on the left, metadata on the
|
||||
right. [link](https://mobbin.com/screens/a5b50327-60e0-4075-9cfd-7f383d18265c).
|
||||
4. **Okta — System Log** / **Stripe — Events** / **Cloudflare — Observability** — dense log
|
||||
tables (timestamp · type · message), some with a count-over-time bar.
|
||||
[Okta](https://mobbin.com/screens/70f42b3f-1823-4cb2-872d-346ad3eab8dc) ·
|
||||
[Stripe](https://mobbin.com/screens/5423e185-8374-4b6c-a4a0-2d3ae9adc1d0) ·
|
||||
[Cloudflare](https://mobbin.com/screens/db64bfde-eac6-4786-8c29-62b98eb1a149). a11y:
|
||||
color-coded status must pair with an icon/text, not color alone.
|
||||
|
||||
---
|
||||
|
||||
## 5. Concepts
|
||||
|
||||
All three keep the data scope (debug-session runs), keep the existing bottom-center anchor
|
||||
over the canvas+code pane, and preserve the existing select→navigate behavior. They differ in
|
||||
*how the history is surfaced*.
|
||||
|
||||
### Concept A — "Activity Strip" (in-place horizontal chips)
|
||||
- **Thesis:** smallest change. Swap the row of bare dots for a row of legible **chips** in the
|
||||
same pill, scrolling horizontally. Each chip: status glyph + block icon + block label +
|
||||
"x ago"; duration/mode in tooltip. Click → navigate.
|
||||
- **Lineage:** Databricks run-selector (canvas-anchored) + Vercel chip legibility.
|
||||
- **DS:** `StatusDot`, `WorkflowBlockIcon`, pills, `ScrollArea`, `formatMs`. Same wrapper/position.
|
||||
- **Tradeoffs:** + tiny diff, preserves muscle memory, fast. − horizontal scroll is less
|
||||
scannable than vertical; limited metadata per chip; long lists hide off-screen.
|
||||
|
||||
### Concept B — "Activity History panel" (collapsed timeline bar → expanding vertical list) — RECOMMENDED
|
||||
- **Thesis:** the dock's **collapsed** state is a slim **status-segment bar** — one thin
|
||||
segment per run, colored by status, newest on the right, labeled "N runs · last ✓ 2m ago".
|
||||
That's the at-a-glance, time-ordered "timeline." Click/hover **expands upward** into a
|
||||
**vertical, scannable list**: one rich row per run = status glyph · block icon · block name ·
|
||||
type pill · mode pill (Agent/Code) · duration · "x ago", with a one-line failure reason on
|
||||
failures. Newest first. Row click → navigate (existing behavior); current run highlighted.
|
||||
- **Lineage:** Vercel Activity feed (legible rows) + Okta count-over-time bar (collapsed
|
||||
status density) + WorkOS master-detail (list feeds the existing right-side detail rail).
|
||||
- **DS:** `Popover`/`Collapsible` + `ScrollArea`, the `WorkflowRunTimelineBlockItem` row
|
||||
vocabulary, `StatusDot`, pills. New: a small **status-segment bar** (gap-ledger item).
|
||||
- **Tradeoffs:** + most legible (vertical rows, full metadata — directly satisfies the AC),
|
||||
+ collapsed footprint stays tiny so the canvas isn't crowded, + serves *both* the
|
||||
"scannable history" and "proper timeline" instincts, + scales to long lists.
|
||||
− one extra primitive (segment bar); − popover sizing over the canvas needs care.
|
||||
|
||||
### Concept C — "Run Selector + Segmented Timeline" (header selector + bottom bar)
|
||||
- **Thesis:** Databricks-style. A **run selector** near the header ("Run: Login ✓ · 2m ago ▾")
|
||||
opens the activity list, *and* a persistent thin **segmented timeline bar** sits at the
|
||||
bottom (each run a proportional, status-colored segment; hover→tooltip, click→navigate).
|
||||
- **Lineage:** Databricks run-selector + Okta status-density bar.
|
||||
- **DS:** `Popover`, segment bar (new), `StatusDot` colors.
|
||||
- **Tradeoffs:** + strongest "timeline" metaphor, scales well. − most net-new UI and two
|
||||
surfaces (header + bottom) risk fragmenting the history; − largest build/QA; − header is
|
||||
already busy in build mode.
|
||||
|
||||
## 6. Recommendation & Decision
|
||||
|
||||
**Recommend Concept B.** It's the most faithful to the acceptance criteria — each entry
|
||||
legible at a glance with real metadata, and one click to jump to a run — while keeping the
|
||||
collapsed footprint as small as today's dot pill. Its collapsed status-segment bar answers the
|
||||
requester's "proper timeline?" instinct without splitting the history across two surfaces
|
||||
(Concept C's main risk), and it reuses the established run-row vocabulary so it looks native.
|
||||
|
||||
Decision (2026-06-15): requester chose to **build all three (A, B, C) behind a live variant
|
||||
toggle** so they can compare directly in the PR preview, then collapse to one winner later.
|
||||
Implementation ships a `RecentActivity` orchestrator that renders the variant selected by a
|
||||
persisted (localStorage + `?activityVariant=` URL seed) toggle; default = B.
|
||||
|
||||
## 7. Implementation (shipped)
|
||||
|
||||
New module `skyvern-frontend/src/routes/workflows/debugger/recentActivity/`:
|
||||
- `useRecentActivity.ts` — data hook (debug-session runs, sorted asc; block-type map;
|
||||
`navigateToRun` preserving the old select→navigate target, now also resolving nested loop
|
||||
blocks for the "block still exists" guard).
|
||||
- `runActivity.ts` / `RunGlyphs.tsx` — shared status/duration/time helpers + status/block glyphs.
|
||||
- `RecentActivitySegmentBar.tsx`, `RecentActivityList.tsx` — shared primitives.
|
||||
- `RecentActivityStrip.tsx` (A), `RecentActivityPanel.tsx` (B), `RecentActivityTimeline.tsx`
|
||||
(C), `RecentActivityVariantToggle.tsx`, `RecentActivity.tsx` (orchestrator).
|
||||
- `src/store/RecentActivityVariantStore.ts` — variant store.
|
||||
- `Workspace.tsx` now renders `<RecentActivity />`; `DebuggerBlockRuns.tsx` deleted.
|
||||
|
||||
Verification: `tsc --noEmit` ✓, `eslint --max-warnings 0` ✓, `vite build` ✓. Live visual
|
||||
verification of the populated state needs a debug session with ≥1 run (backend + browser
|
||||
session) — delegated to the PR preview by design (the whole point of the A/B/C toggle).
|
||||
|
||||
### Gap ledger outcome (→ Step 5 DS ticket)
|
||||
- Shipped one-off **`RecentActivitySegmentBar`** (status-segment/timeline-bar primitive) — DS has none.
|
||||
- Re-derived **run-status → icon/color** inline (`RunGlyphs` + `STATUS_PILL_TONE`/`SEGMENT_FILL`)
|
||||
because there's no shared `RunStatusBadge`.
|
||||
- Filed **SKY-11082** (team Skyvern AI) to extract both primitives into the DS once the winning
|
||||
variant is chosen. Pure helpers covered by `runActivity.test.ts`.
|
||||
|
||||
---
|
||||
|
||||
# Round 2 — Placement exploration (2026-06-16)
|
||||
|
||||
The A/B/C work settled the *surface design*; this round explores *where on the build page*
|
||||
the surface lives. Orthogonal axis: any style (A/B/C) can sit at any placement.
|
||||
|
||||
## Frame (placement)
|
||||
|
||||
The surface only renders in **debug/browser mode** (`showBrowser`), inside the vertical
|
||||
`Splitter`. Candidate regions and their occupants:
|
||||
- **Left pane** = code (left half) + infinite canvas (right half). Bottom-left corner holds the
|
||||
FlowRenderer controls (FitView/Lock/GlobalCollapse); top is overlaid by `WorkflowHeader`
|
||||
(`absolute left-6 top-8 h-20`) and header-anchored sub-panels (`top-[8.5rem]`).
|
||||
- **Right pane** (`skyvern-split-right`) = live browser + footer (copilot/power/reload); far
|
||||
right edge holds the run-detail **timeline rail** (`w-[5rem]`, expandable, `z-[15]`).
|
||||
|
||||
**Deciding constraint:** a placement must not block the live browser, the canvas controls, or
|
||||
the run-detail timeline, and should not fight the header/sub-panels. So placements are
|
||||
pointer-events-transparent floating bands (only the dock itself captures clicks).
|
||||
|
||||
## Inspiration (Mobbin — web, node-canvas editors)
|
||||
- **WRITER — Blueprints**: execution log as a full-width **bottom** panel (node rows + status +
|
||||
Trace + duration). [link](https://mobbin.com/screens/2368f17d-4fcc-4590-912d-08cb39245dab)
|
||||
- **n8n — Executions**: run history as a **left side panel** (status + duration, auto-refresh),
|
||||
entered via a top **Editor | Executions** tab.
|
||||
[link](https://mobbin.com/screens/d3af4413-04f9-4534-8aa4-01916d2b4910)
|
||||
- **StackAI — Version history / Run Details**: **right side panel** co-located with the run
|
||||
(status, timestamps, duration, tokens).
|
||||
[link](https://mobbin.com/screens/cffa32bb-fa1e-43fa-913b-27001b35f395) ·
|
||||
[link](https://mobbin.com/screens/bb0174f4-60aa-4e30-ac5f-73679b160f38)
|
||||
- **Databricks** (round 1): top **run-selector** + bottom **event log** in one editor.
|
||||
|
||||
## Placement concepts
|
||||
|
||||
- **P1 — Bottom dock (baseline, current):** floating bottom-center over the canvas/code pane.
|
||||
Lineage: WRITER bottom log + StackAI bottom toolbar. + canvas stays clear, controls reachable.
|
||||
− easy to miss; far from where the eye starts.
|
||||
- **P2 — Top rail (under header):** pinned top-center over the canvas/code pane, just below the
|
||||
header. Lineage: n8n Editor|Executions top tab + Databricks top run-selector. + high
|
||||
discoverability, reads top-down, near run controls. − competes with header sub-panels when one
|
||||
is open; popover opens downward over the canvas.
|
||||
- **P3 — Browser-pane header (co-located with run viewing):** pinned to the top of the right
|
||||
(live-browser) pane, so picking a recent run sits beside viewing that run + its detail
|
||||
timeline. Lineage: StackAI right-side run history/details. + strongest pick→view coherence
|
||||
(directly answers the ticket's "reconcile with run viewing"). − eats a strip of browser space;
|
||||
must clear the far-right timeline rail.
|
||||
|
||||
**Recommendation:** **P3 (browser-pane header)** for coherence — it puts "which run" right next
|
||||
to "this run's browser + timeline," which is the actual debugging loop — with **P1** as the
|
||||
low-risk default if we want the canvas untouched. P2 is the most discoverable but the most
|
||||
crowded.
|
||||
|
||||
**Decision (2026-06-16):** per the established pattern, build all three behind a **placement
|
||||
toggle** (orthogonal to the A/B/C style toggle; persisted via localStorage + `?activityPlacement=`
|
||||
URL seed; default `bottom`) so they can be compared live in the PR preview.
|
||||
|
||||
### Gap-ledger addition
|
||||
- No shared **floating-dock anchor** convention for build-canvas overlays (each overlay
|
||||
re-implements `absolute … pointer-events-none [&>*]:pointer-events-auto`). Minor; noted on
|
||||
[[SKY-11082]] rather than a new ticket.
|
||||
|
||||
## Round 2 decision — style converges to one "Activity Timeline" (2026-06-16)
|
||||
|
||||
Requester: "I like C the most, and B for its compression and all the events in one place."
|
||||
→ **Merge B + C into a single default surface** and drop A (and the A/B/C style toggle):
|
||||
|
||||
**Activity Timeline** — compact two-row dock:
|
||||
- Row 1: a **run selector** ("Run: ✓ Login · 2m ago ▾") + a compression summary ("N runs ·
|
||||
last ✓ 2m ago"). The selector opens **B's consolidated, scannable event list**
|
||||
(`RecentActivityList`) — all events in one place.
|
||||
- Row 2: a **persistent segmented timeline bar** (C) — proportional, status-colored; hover→tip,
|
||||
click a segment → jump to that run.
|
||||
|
||||
This keeps C's timeline metaphor + direct segment navigation, with B's compression (compact
|
||||
collapsed form) and single consolidated list. Built behind the **placement toggle** (bottom /
|
||||
top / right) so location can still be compared in the PR preview.
|
||||
|
||||
## Round 3 decision — placement locked to browser-pane header (2026-06-16)
|
||||
|
||||
Requester locked the **browser-pane header (right)** placement. Removed the placement toggle +
|
||||
store and the bottom/top anchors; `RecentActivity` now mounts unconditionally at the top of the
|
||||
live-browser pane (`popoverSide="bottom"`). Rendered visual proof (mock runs) below — produced
|
||||
via a throwaway standalone preview page, not committed.
|
||||
|
||||

|
||||
|
||||
## Round 4 — re-added the 3-way placement toggle (2026-06-16)
|
||||
|
||||
Reverted the round-3 lock: requester wants to compare bottom / top / right **by eye** in the
|
||||
preview rather than commit blind. Restored `RecentActivityPlacementStore` +
|
||||
`RecentActivityPlacementToggle` and the three Workspace anchors (default `bottom`,
|
||||
`?activityPlacement=` URL seed). Decide, then re-lock.
|
||||
|
||||

|
||||
|
||||
## Round 5 — drop floating, integrate the run selector (2026-06-16)
|
||||
|
||||
Real screenshots showed every floating placement collides with canvas/browser content and
|
||||
duplicates the existing right-side run-detail panel (`DebuggerRunTimeline`: Actions/Steps/Credits
|
||||
+ block/action timeline) — the overlap the ticket warned about. So: **remove the floating dock,
|
||||
segmented bar, and placement toggle**, and make recent-activity a compact **run selector** that
|
||||
opens the consolidated list. Two integration points behind a small mode toggle (default `panel`,
|
||||
`?activityMode=panel|toolbar`):
|
||||
- **panel:** selector at the top of the right run-detail panel (`DebuggerRun`) — co-located with
|
||||
viewing; picking a run drives the panel below.
|
||||
- **toolbar:** selector as a dropdown in the editor header toolbar (`EditorActionToolbar`).
|
||||
Removed: `RecentActivity`, `RecentActivityTimeline`, `RecentActivitySegmentBar`,
|
||||
`RecentActivityPlacementToggle`, `RecentActivityPlacementStore`. Added: `RecentActivityRunSelector`,
|
||||
`RecentActivityIntegrationStore`, `RecentActivityIntegrationToggle`.
|
||||
|
||||
## Round 6 — timeline strip below the browser (2026-06-16)
|
||||
|
||||
Panel/toolbar selectors still read as bolted-on. Requester idea: dock the timeline as a
|
||||
horizontal strip **below the live browser session window** — the browser is what you're
|
||||
watching, so a run history beneath it is contextual (WRITER bottom log / Databricks event-log
|
||||
lineage). Added as a third integration option (`browser`) on the mode toggle:
|
||||
`RecentActivityStrip` — a scannable horizontal row of run chips (oldest→newest, auto-scrolled to
|
||||
newest, click→jump) + an "N runs ▾" button opening the consolidated list. Mounted between the
|
||||
browser stream and its footer in both VNC and CDP panels. Compare via the Panel/Toolbar/Browser
|
||||
toggle (`?activityMode=panel|toolbar|browser`).
|
||||
|
||||
## Round 7 — placement locked to the run-detail panel; preview toggle removed (final, 2026-06-29)
|
||||
|
||||
Compared the three integrations live in the PR preview and **locked `panel`**: the run
|
||||
selector mounts at the top of the right run-detail panel (`DebuggerRun`), co-located with
|
||||
viewing a run, which reconciles the history surface with run viewing (the ticket's open
|
||||
question) without a second overlapping surface. Removed the exploration scaffolding —
|
||||
`RecentActivityIntegrationStore` (+test), `RecentActivityIntegrationToggle`, and
|
||||
`RecentActivityStrip` — plus the toolbar/browser wirings in `WorkflowHeader`/`Workspace`.
|
||||
`RecentActivityRunSelector` mounts unconditionally (it self-hides until the debug session has
|
||||
≥1 run) and its now-single-use `variant`/`popoverSide` props were dropped. Run rows in the
|
||||
consolidated list are disabled while a workflow run is in progress (navigation is a no-op
|
||||
then), covered by `RecentActivityList.test.tsx`. Dead exports `SEGMENT_FILL` and
|
||||
`getRunTooltip` (orphaned when the segment bar / strip were cut) were removed.
|
||||
BIN
docs/design/activity-timeline-placements.png
Normal file
|
After Width: | Height: | Size: 265 KiB |
BIN
docs/design/activity-timeline-preview.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
|
|
@ -40,6 +40,8 @@ Select the method that matches how you receive verification codes:
|
|||
|
||||
When you enable 2FA on a website, you're typically shown a QR code or a secret key. Store this secret with your credential, and Skyvern generates valid codes automatically.
|
||||
|
||||
In the Skyvern UI, paste the manual key or full `otpauth://` URI into **Authenticator Key**. You can also click **Scan QR** and upload a QR code image from the site's 2FA setup screen.
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
import os
|
||||
|
|
@ -312,6 +314,12 @@ If `content` is longer than 10 characters, Skyvern's AI extracts the verificatio
|
|||
|
||||
Instead of pushing codes to Skyvern, you implement an endpoint that Skyvern polls until a code is available.
|
||||
|
||||
<Warning>
|
||||
For saved workflows or agents, configure the endpoint on the specific browser block that can encounter 2FA. Use the block's **TOTP Verification URL** field, or set that field to a workflow parameter such as `{{ totp_url }}` and pass the value in `parameters` when starting the run.
|
||||
|
||||
Passing `totp_url` only at the top level of a workflow run does not automatically populate every block. If the block's **TOTP Verification URL** is empty, that block will not call your endpoint.
|
||||
</Warning>
|
||||
|
||||
### Step 1: Implement the endpoint
|
||||
|
||||
Your endpoint must accept POST requests and return the verification code:
|
||||
|
|
@ -355,9 +363,9 @@ def verify_skyvern_request(request, api_key: str) -> bool:
|
|||
return hmac.compare_digest(signature, expected)
|
||||
```
|
||||
|
||||
### Step 3: Configure the login
|
||||
### Step 3: Configure the login or block
|
||||
|
||||
Pass `totp_url` when running your login:
|
||||
For a one-off login task, pass `totp_url` in the login request:
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
|
|
@ -382,6 +390,22 @@ curl -X POST "https://api.skyvern.com/v1/run/tasks/login" \
|
|||
```
|
||||
</CodeGroup>
|
||||
|
||||
For a saved workflow or agent, configure the block that may see the 2FA prompt:
|
||||
|
||||
1. Open the browser, action, file download, or login block that performs the login.
|
||||
2. Set **TOTP Verification URL** to your endpoint.
|
||||
3. If the endpoint changes per run, create a workflow parameter such as `totp_url`, set the block's **TOTP Verification URL** to `{{ totp_url }}`, and pass the URL in the run's `parameters`.
|
||||
|
||||
```typescript TypeScript
|
||||
const body: SkyvernRunWorkflowRequest = {
|
||||
workflow_id: "wpid_123",
|
||||
parameters: {
|
||||
totp_url: "https://your-server.com/totp-webhook",
|
||||
// other workflow parameters...
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Skyvern polls your endpoint every 10 seconds until a code is returned or the timeout is reached.
|
||||
|
||||
---
|
||||
|
|
@ -498,7 +522,7 @@ curl -X GET "https://api.skyvern.com/v1/credentials/totp?totp_identifier=user@ex
|
|||
| `limit` | Number of records (default 50, max 200) |
|
||||
|
||||
<Note>
|
||||
Skyvern only returns codes from the last 10 minutes (configurable via `TOTP_LIFESPAN_MINUTES`).
|
||||
This endpoint returns historical records ordered newest first, capped by `limit`. Runtime polling still only uses unexpired codes within `TOTP_LIFESPAN_MINUTES`.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -24,20 +24,84 @@ Profiles are ideal when you:
|
|||
|
||||
## How profiles work
|
||||
|
||||
You can create a blank profile with only `name` and optional `description`, then pass that profile to future agent runs. Blank profiles are seeded from the configured default browser profile directory when available, with a minimal loadable profile skeleton as a fallback.
|
||||
|
||||
When an agent runs with `persist_browser_session=true`, Skyvern archives the browser state (cookies, storage, session files) after the run completes. This archiving happens asynchronously in the background. Once the archive is ready, you can create a profile from it, then pass that profile to future agent runs to restore the saved state.
|
||||
|
||||
For [browser sessions](/developers/optimization/browser-sessions), profile saving is opt-in: a session archives its state when it ends only if it has `generate_browser_profile` enabled or was started from a saved profile. See [Save a session's profile](/developers/optimization/browser-sessions#save-a-sessions-profile).
|
||||
|
||||
---
|
||||
|
||||
## Create a Browser Profile
|
||||
|
||||
Create a blank profile when you want a reusable profile ID before any browsing has happened. Create a sourced profile when you want to capture cookies, localStorage, and session files from a workflow run or browser session.
|
||||
|
||||
### Blank profile
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
import asyncio
|
||||
from skyvern import Skyvern
|
||||
|
||||
async def main():
|
||||
client = Skyvern(api_key="YOUR_API_KEY")
|
||||
|
||||
profile = await client.create_browser_profile(
|
||||
name="fresh-profile",
|
||||
description="Blank profile for future runs",
|
||||
)
|
||||
print(f"Profile created: {profile.browser_profile_id}")
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
import { Skyvern } from "@skyvern/client";
|
||||
|
||||
async function main() {
|
||||
const client = new Skyvern({ apiKey: process.env.SKYVERN_API_KEY! });
|
||||
|
||||
const profile = await client.createBrowserProfile({
|
||||
name: "fresh-profile",
|
||||
description: "Blank profile for future runs",
|
||||
});
|
||||
|
||||
console.log(`Profile created: ${profile.browser_profile_id}`);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -s -X POST "https://api.skyvern.com/v1/browser_profiles" \
|
||||
-H "x-api-key: $SKYVERN_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "fresh-profile",
|
||||
"description": "Blank profile for future runs"
|
||||
}'
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
**Parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|----------------------|--------|------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `name` | string | Required unique display name |
|
||||
| `description` | string | Optional profile description |
|
||||
| `browser_session_id` | string | Omit for a blank profile |
|
||||
| `workflow_run_id` | string | Omit for a blank profile |
|
||||
| `proxy_location` | string \| object | Optional pinned proxy location for the profile's residential ISP identity (e.g. `RESIDENTIAL_ISP`, or a `GeoTarget` object) |
|
||||
| `proxy_session_id` | string | Optional advanced reuse key for the profile's pinned proxy identity |
|
||||
|
||||
### From an agent run
|
||||
|
||||
Create an agent with `persist_browser_session=true` in the agent definition, run it, wait for completion, then create a profile from the run. Session archiving happens asynchronously, so add brief retry logic when creating the profile.
|
||||
|
||||
<Note>
|
||||
`persist_browser_session` must be set when **creating the agent**, not when running it. It is an agent definition property, not a runtime parameter.
|
||||
</Note>
|
||||
|
||||
### From an agent run
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
import asyncio
|
||||
|
|
@ -224,12 +288,16 @@ done
|
|||
|
||||
### From a browser session
|
||||
|
||||
You can also create a profile from a [Browser Session](/developers/optimization/browser-sessions) that was used inside an agent with `persist_browser_session=true`. After the agent run completes and the session is closed, pass the session ID instead of the workflow run ID.
|
||||
You can also create a profile from a closed [Browser Session](/developers/optimization/browser-sessions) that was set to save its profile. Create the session with `generate_browser_profile` enabled (or [turn it on while the session is alive](/developers/optimization/browser-sessions#save-a-sessions-profile)), close the session, then pass the session ID instead of the workflow run ID.
|
||||
|
||||
<Warning>
|
||||
Only sessions that were part of an agent with `persist_browser_session=true` produce an archive. A session created with `create_browser_session()` alone does not archive its state. Archiving happens asynchronously after the session closes, so add retry logic.
|
||||
Sessions do not save their profile by default. If the session did not have `generate_browser_profile` enabled and was not started from a saved profile, this call fails with a `400` error — retrying does not help. Update API scripts and integrations that create profiles from closed sessions; n8n users may need updated Skyvern nodes. Profiles created from workflow runs (`persist_browser_session=true`) are unaffected.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
For opted-in sessions, the archive uploads asynchronously after the session closes, so keep brief retry logic for the transient "not persisted yet" window.
|
||||
</Note>
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
import asyncio
|
||||
|
|
@ -238,7 +306,7 @@ from skyvern import Skyvern
|
|||
async def main():
|
||||
client = Skyvern(api_key="YOUR_API_KEY")
|
||||
|
||||
# browser_session_id from a workflow run with persist_browser_session=true
|
||||
# browser_session_id from a closed session created with generate_browser_profile enabled
|
||||
session_id = "pbs_your_session_id"
|
||||
|
||||
# Create profile from the closed session (retry while archive uploads)
|
||||
|
|
@ -266,7 +334,7 @@ import { Skyvern } from "@skyvern/client";
|
|||
async function main() {
|
||||
const client = new Skyvern({ apiKey: process.env.SKYVERN_API_KEY! });
|
||||
|
||||
// browser_session_id from a workflow run with persist_browser_session=true
|
||||
// browser_session_id from a closed session created with generate_browser_profile enabled
|
||||
const sessionId = "pbs_your_session_id";
|
||||
|
||||
// Create profile from the closed session (retry while archive uploads)
|
||||
|
|
@ -295,8 +363,17 @@ main();
|
|||
```
|
||||
|
||||
```bash cURL
|
||||
# browser_session_id from a workflow run with persist_browser_session=true
|
||||
SESSION_ID="pbs_your_session_id"
|
||||
# Create a session that saves its profile when it ends
|
||||
SESSION_ID=$(curl -s -X POST "https://api.skyvern.com/v1/browser_sessions" \
|
||||
-H "x-api-key: $SKYVERN_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"generate_browser_profile": true}' | jq -r '.browser_session_id')
|
||||
|
||||
# ... run your tasks against $SESSION_ID here ...
|
||||
|
||||
# Close the session so the profile uploads
|
||||
curl -s -X POST "https://api.skyvern.com/v1/browser_sessions/$SESSION_ID/close" \
|
||||
-H "x-api-key: $SKYVERN_API_KEY"
|
||||
|
||||
# Create profile (retry while session archives)
|
||||
for i in {1..10}; do
|
||||
|
|
@ -322,7 +399,7 @@ done
|
|||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `name` | string | Required. Display name for the profile. Must be unique within your organization |
|
||||
| `browser_session_id` | string | ID of the closed browser session (starts with `pbs_`). The session must have been part of an agent with `persist_browser_session=true` |
|
||||
| `browser_session_id` | string | ID of the closed browser session (starts with `pbs_`). The session must have had `generate_browser_profile` enabled or been started from a saved profile |
|
||||
| `description` | string | Optional description of the profile's purpose |
|
||||
|
||||
---
|
||||
|
|
@ -747,6 +824,57 @@ In a real scenario, step 1 would be a login agent that authenticates with a site
|
|||
|
||||
---
|
||||
|
||||
## Pin a proxy identity
|
||||
|
||||
A browser profile can carry a pinned residential ISP proxy identity so that every run reusing the profile reaches the target site from the same IP and locale. Pinning is opt-in and uses two fields:
|
||||
|
||||
- `proxy_location` — set to `RESIDENTIAL_ISP` (or a `GeoTarget` object) to opt the profile into a static ISP identity.
|
||||
- `proxy_session_id` — opaque Skyvern-managed sticky-session key. Omit it to let Skyvern generate one automatically when `proxy_location` is `RESIDENTIAL_ISP`.
|
||||
|
||||
When a run uses a profile that has a pinned proxy, Skyvern routes traffic through the same residential ISP identity the profile was last associated with, even if the run request does not set `proxy_location`.
|
||||
|
||||
### Set a pin at create time
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
profile = await client.create_browser_profile(
|
||||
name="prod-salesforce-admin",
|
||||
description="Pinned residential ISP identity",
|
||||
proxy_location="RESIDENTIAL_ISP",
|
||||
)
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -s -X POST "https://api.skyvern.com/v1/browser_profiles" \
|
||||
-H "x-api-key: $SKYVERN_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "prod-salesforce-admin",
|
||||
"description": "Pinned residential ISP identity",
|
||||
"proxy_location": "RESIDENTIAL_ISP"
|
||||
}'
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Rotate the pinned identity
|
||||
|
||||
Update the profile with `rotate_proxy_session_id: true` to ask Skyvern to mint a fresh sticky-session id while keeping the same `proxy_location`. Use this when the existing IP gets flagged or when you want to start a new identity for the same profile.
|
||||
|
||||
```bash cURL
|
||||
curl -s -X PATCH "https://api.skyvern.com/v1/browser_profiles/$PROFILE_ID" \
|
||||
-H "x-api-key: $SKYVERN_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{ "rotate_proxy_session_id": true }'
|
||||
```
|
||||
|
||||
To clear the pin entirely, set `proxy_location` to `null` in the same update call.
|
||||
|
||||
<Note>
|
||||
`proxy_session_id` is only valid alongside `RESIDENTIAL_ISP`. Requests that supply `proxy_session_id` with any other `proxy_location` are rejected with a 400.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Best practices
|
||||
|
||||
### Use descriptive names
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ curl -X POST "https://api.skyvern.com/v1/browser_sessions" \
|
|||
| `proxy_location` | string | Geographic proxy location (Cloud only). See [Proxy & Geolocation](/developers/going-to-production/proxy-geolocation) for available options |
|
||||
| `browser_type` | string | Browser type: `chrome` or `msedge` |
|
||||
| `extensions` | array | Extensions to install: `ad-blocker`, `captcha-solver` |
|
||||
| `generate_browser_profile` | boolean | REST API only for now — not yet accepted by the SDK methods. Save the session's browser profile (cookies, localStorage, session files) when the session ends, so it can be turned into a reusable [browser profile](/developers/optimization/browser-profiles). Default: `false`. See [Save a session's profile](#save-a-sessions-profile) |
|
||||
|
||||
**Example response:**
|
||||
|
||||
|
|
@ -367,6 +368,43 @@ You cannot use both `browser_session_id` and `browser_profile_id` in the same re
|
|||
|
||||
---
|
||||
|
||||
## Save a session's profile
|
||||
|
||||
By default, a browser session does **not** save its browser profile when it ends. To capture the session's state (cookies, localStorage, session files) for reuse, opt in with `generate_browser_profile`. Python and TypeScript SDK support for this flag is rolling out; until your SDK version includes it, call the REST API directly (the Python SDK can also pass it via `request_options` with `additional_body_parameters={"generate_browser_profile": True}`).
|
||||
|
||||
```bash
|
||||
curl -X POST "https://api.skyvern.com/v1/browser_sessions" \
|
||||
-H "x-api-key: $SKYVERN_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"timeout": 60,
|
||||
"generate_browser_profile": true
|
||||
}'
|
||||
```
|
||||
|
||||
You can also toggle the flag on a live session. The value is read when the session ends, so the update takes effect as long as the session is still open. Updating a session that has already closed returns a `409` error.
|
||||
|
||||
```bash
|
||||
curl -X PATCH "https://api.skyvern.com/v1/browser_sessions/pbs_abc123" \
|
||||
-H "x-api-key: $SKYVERN_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"generate_browser_profile": true}'
|
||||
```
|
||||
|
||||
To confirm the setting on an existing session, fetch it with `GET /v1/browser_sessions/{browser_session_id}` — the response includes `generate_browser_profile`.
|
||||
|
||||
Once the session closes and its profile finishes uploading, turn it into a reusable profile with [`create_browser_profile`](/developers/optimization/browser-profiles#from-a-browser-session).
|
||||
|
||||
<Note>
|
||||
Sessions started from a saved profile (`browser_profile_id`) always save their profile when they end, regardless of this flag. This does not update the original profile — to keep the refreshed login state, create a new profile from the closed session and use the new profile's ID in future runs.
|
||||
</Note>
|
||||
|
||||
<Warning>
|
||||
**Behavior change:** sessions previously saved their profile automatically. Creating a browser profile from a closed session now fails with a `400` error unless the session had `generate_browser_profile` enabled or was started from a profile — retrying does not help. Update API scripts and integrations that create profiles from closed sessions; n8n users may need updated Skyvern nodes. Creating profiles from workflow runs (`persist_browser_session`) is unaffected.
|
||||
</Warning>
|
||||
|
||||
---
|
||||
|
||||
## Close a session
|
||||
|
||||
Close a session to release resources and stop billing. The browser shuts down immediately.
|
||||
|
|
@ -694,7 +732,7 @@ Skyvern also offers [Browser Profiles](/developers/optimization/browser-profiles
|
|||
| **Best for** | Back-to-back tasks, human-in-the-loop, real-time agents | Repeated logins, scheduled agents, shared auth state |
|
||||
|
||||
<Tip>
|
||||
You can create a [Browser Profile](/developers/optimization/browser-profiles) from a completed session to save its authenticated state for future reuse.
|
||||
You can create a [Browser Profile](/developers/optimization/browser-profiles) from a completed session to save its authenticated state for future reuse. The session must have [`generate_browser_profile` enabled](#save-a-sessions-profile) or have been started from a profile.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ keywords:
|
|||
- budget
|
||||
---
|
||||
|
||||
Skyvern Cloud uses a **credit-based billing model**. Each plan includes a monthly credit allowance that determines how many actions you can run.
|
||||
Skyvern Cloud uses a **credit-based billing model**. Free accounts include a one-time credit grant. Paid plans include a monthly credit allowance that determines how many actions you can run.
|
||||
|
||||
| Plan | Price | Actions Included |
|
||||
|------|-------|------------------|
|
||||
| Free | $0 | ~170 |
|
||||
| Free | $0 | ~200 |
|
||||
| Hobby | $29 | ~1,200 |
|
||||
| Pro | $149 | ~6,200 |
|
||||
| Enterprise | Custom | Unlimited |
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 26 KiB |
BIN
docs/pr-screenshots/bitwarden-credentials-passwords-tab.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
docs/pr-screenshots/bitwarden-workflow-editor-picker.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
docs/pr-screenshots/credentials-authenticator-qr-after.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
docs/pr-screenshots/credentials-authenticator-qr-before.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
docs/pr-screenshots/duplicate-block-menu-desktop.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
docs/pr-screenshots/duplicate-block-menu-mobile.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
docs/pr-screenshots/model-dropdown-after.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
docs/pr-screenshots/model-dropdown-before.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
docs/pr-screenshots/onepassword-credentials-passwords-tab.png
Normal file
|
After Width: | Height: | Size: 254 KiB |
BIN
docs/pr-screenshots/onepassword-custom-value.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
docs/pr-screenshots/onepassword-item-picker-open.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
docs/pr-screenshots/onepassword-item-picker.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
docs/pr-screenshots/oss-duplicate-menu.png
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
docs/pr-screenshots/oss-duplicate-result.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
docs/pr-screenshots/proxy-pin-browser-profile-detail.png
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
docs/pr-screenshots/proxy-pin-create-profile-dialog.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
docs/pr-screenshots/proxy-pin-credential-modal-rotate.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
docs/pr-screenshots/proxy-pin-credential-modal.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 118 KiB |
|
|
@ -19,7 +19,7 @@ profile = await client.create_browser_profile(
|
|||
name="production-login",
|
||||
workflow_run_id="wr_abc123",
|
||||
)
|
||||
print(profile.browser_profile_id) # bpf_abc123
|
||||
print(profile.browser_profile_id) # bp_abc123
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
|
|
@ -27,7 +27,7 @@ const profile = await skyvern.createBrowserProfile({
|
|||
name: "production-login",
|
||||
workflow_run_id: "wr_abc123",
|
||||
});
|
||||
console.log(profile.browser_profile_id); // bpf_abc123
|
||||
console.log(profile.browser_profile_id); // bp_abc123
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ console.log(profile.browser_profile_id); // bpf_abc123
|
|||
| `name` | `str` | Yes | Display name for the profile. |
|
||||
| `description` | `str` | No | Optional description. |
|
||||
| `workflow_run_id` | `str` | Conditional | The workflow run ID to snapshot. The run must have used `persist_browser_session=True`. Required if `browser_session_id` is not provided. |
|
||||
| `browser_session_id` | `str` | Conditional | The browser session ID to snapshot. Required if `workflow_run_id` is not provided. |
|
||||
| `browser_session_id` | `str` | Conditional | The browser session ID to snapshot. The session must have had `generate_browser_profile` enabled or been started from a saved profile. Required if `workflow_run_id` is not provided. |
|
||||
| `request_options` | `RequestOptions` | No | Per-request configuration (see below). |
|
||||
|
||||
You must provide either `workflow_run_id` or `browser_session_id`.
|
||||
|
|
@ -47,7 +47,7 @@ You must provide either `workflow_run_id` or `browser_session_id`.
|
|||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `browser_profile_id` | `str` | Unique ID. Starts with `bpf_`. |
|
||||
| `browser_profile_id` | `str` | Unique ID. Starts with `bp_`. |
|
||||
| `name` | `str` | Profile name. |
|
||||
| `description` | `str \| None` | Profile description. |
|
||||
| `created_at` | `datetime` | When the profile was created. |
|
||||
|
|
@ -105,7 +105,7 @@ const result = await skyvern.runWorkflow({
|
|||
</CodeGroup>
|
||||
|
||||
<Info>
|
||||
Session archiving is asynchronous. If `create_browser_profile` fails immediately after a workflow completes, wait a few seconds and retry.
|
||||
Session archiving is asynchronous. If `create_browser_profile` fails immediately after a run or session ends, wait a few seconds and retry. A `400` error saying the session was not configured to generate a browser profile is permanent — recreate the session with `generate_browser_profile` enabled. See [Save a session's profile](/developers/optimization/browser-sessions#save-a-sessions-profile).
|
||||
</Info>
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ Delete a browser profile.
|
|||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
await client.delete_browser_profile("bpf_abc123")
|
||||
await client.delete_browser_profile("bp_abc123")
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
await skyvern.deleteBrowserProfile("bpf_abc123");
|
||||
await skyvern.deleteBrowserProfile("bp_abc123");
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ Get a single profile by ID.
|
|||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
profile = await client.get_browser_profile("bpf_abc123")
|
||||
profile = await client.get_browser_profile("bp_abc123")
|
||||
print(profile.name)
|
||||
```
|
||||
|
||||
```typescript TypeScript
|
||||
const profile = await skyvern.getBrowserProfile("bpf_abc123");
|
||||
const profile = await skyvern.getBrowserProfile("bp_abc123");
|
||||
console.log(profile.name);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
|
|
|||
|
|
@ -33,9 +33,14 @@ console.log(session.browser_session_id); // pbs_abc123
|
|||
| `proxy_location` | `ProxyLocation` | No | `None` | Route browser traffic through a geographic proxy. |
|
||||
| `extensions` | `list[Extensions]` | No | `None` | Browser extensions to install. Options: `"ad-blocker"`, `"captcha-solver"`. |
|
||||
| `browser_type` | `PersistentBrowserType` | No | `None` | Browser type. Options: `"chrome"`, `"msedge"`. |
|
||||
| `browser_profile_id` | `str` | No | `None` | Load a browser profile (cookies, localStorage) into this session. ID starts with `bpf_`. |
|
||||
| `browser_profile_id` | `str` | No | `None` | Load a browser profile (cookies, localStorage) into this session. ID starts with `bp_`. |
|
||||
| `generate_browser_profile` | `bool` | No | `False` | REST API only for now — not yet accepted by the SDK methods (see note below). Save the session's browser profile when it ends so it can be turned into a reusable [browser profile](/sdk-reference/browser-profiles/create-browser-profile). Sessions started with `browser_profile_id` always save theirs. |
|
||||
| `request_options` | `RequestOptions` | No | | Per-request configuration (see below). |
|
||||
|
||||
<Note>
|
||||
`generate_browser_profile` is not yet accepted as a keyword by the SDK methods (watch the [changelog](/changelog) for SDK availability). Until SDK support lands, pass it from Python via `request_options` with `additional_body_parameters={"generate_browser_profile": True}` (see [Request options](#request-options) below); from TypeScript, call the REST API directly. You can also toggle it on a live session via `PATCH /v1/browser_sessions/{browser_session_id}` — the value is read when the session ends. See [Save a session's profile](/developers/optimization/browser-sessions#save-a-sessions-profile).
|
||||
</Note>
|
||||
|
||||
### Returns `BrowserSessionResponse`
|
||||
|
||||
| Field | Type | Description |
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ for (const c of creds) {
|
|||
|-----------|------|----------|---------|-------------|
|
||||
| `page` | `int` | No | `None` | Page number. |
|
||||
| `page_size` | `int` | No | `None` | Results per page. |
|
||||
| `vault_type` | `CredentialVaultType` | No | `None` | Filter credentials by vault type (e.g. `"custom"`, `"bitwarden"`, `"azure_vault"`). |
|
||||
| `vault_type` | `CredentialVaultType` | No | `None` | Filter credentials by vault type (e.g. `"skyvern"`, `"custom"`, `"bitwarden"`, `"azure_vault"`). |
|
||||
| `request_options` | `RequestOptions` | No | `None` | Per-request configuration (see below). |
|
||||
|
||||
### Returns `list[CredentialResponse]`
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ for (const f of result.downloaded_files ?? []) {
|
|||
| `max_steps_per_run` | `int` | No | `None` | Cap AI steps. |
|
||||
| `extra_http_headers` | `dict[str, str]` | No | `None` | Additional HTTP headers. |
|
||||
| `totp_identifier` | `str` | No | `None` | Identifier for TOTP verification. |
|
||||
| `totp_url` | `str` | No | `None` | URL to receive TOTP codes. |
|
||||
| `totp_url` | `str` | No | `None` | Endpoint Skyvern polls to fetch TOTP codes. |
|
||||
| `browser_address` | `str` | No | `None` | Connect to a browser at this CDP address. |
|
||||
| `max_screenshot_scrolling_times` | `int` | No | `None` | Number of screenshot scrolls. |
|
||||
| `waitForCompletion` (TS only) | `boolean` | No | `false` | Block until the download finishes. |
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ console.log(result.status);
|
|||
| `proxy_location` | `ProxyLocation` | No | `None` | Route browser traffic through a geographic proxy. |
|
||||
| `webhook_url` | `str` | No | `None` | URL to receive a POST when the login finishes. |
|
||||
| `totp_identifier` | `str` | No | `None` | Identifier for TOTP verification. |
|
||||
| `totp_url` | `str` | No | `None` | URL to receive TOTP codes. |
|
||||
| `totp_url` | `str` | No | `None` | Endpoint Skyvern polls to fetch TOTP codes. |
|
||||
| `wait_for_completion` (Python) / `waitForCompletion` (TS) | `bool` | No | `False` | Block until the login finishes. |
|
||||
| `timeout` | `float` | No | `1800` | Max wait time in seconds. |
|
||||
| `extra_http_headers` | `dict[str, str]` | No | `None` | Additional HTTP headers. |
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ console.log(result.output);
|
|||
| `webhook_url` | `str` | No | `None` | URL to receive a POST when the run finishes. |
|
||||
| `error_code_mapping` | `dict[str, str]` | No | `None` | Map custom error codes to failure reasons. |
|
||||
| `totp_identifier` | `str` | No | `None` | Identifier for TOTP verification. |
|
||||
| `totp_url` | `str` | No | `None` | URL to receive TOTP codes. |
|
||||
| `totp_url` | `str` | No | `None` | Endpoint Skyvern polls to fetch TOTP codes. |
|
||||
| `title` | `str` | No | `None` | Display name for this run in the dashboard. |
|
||||
| `model` | `dict` | No | `None` | Override the output model definition. |
|
||||
| `user_agent` | `str` | No | `None` | Custom User-Agent header for the browser. |
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ console.log(result.output);
|
|||
| `webhook_url` | `str` | No | `None` | URL to receive a POST when the run finishes. |
|
||||
| `title` | `str` | No | `None` | Display name for this run in the dashboard. |
|
||||
| `totp_identifier` | `str` | No | `None` | Identifier for TOTP verification. |
|
||||
| `totp_url` | `str` | No | `None` | URL to receive TOTP codes. |
|
||||
| `totp_url` | `str` | No | `None` | Workflow-level TOTP endpoint metadata. For saved agents/workflows, set **TOTP Verification URL** on the block that may encounter 2FA, or template that block field from a workflow parameter. |
|
||||
| `template` | `bool` | No | `None` | Run a template workflow. |
|
||||
| `user_agent` | `str` | No | `None` | Custom User-Agent header for the browser. |
|
||||
| `extra_http_headers` | `dict[str, str]` | No | `None` | Additional HTTP headers injected into every browser request. |
|
||||
|
|
@ -121,7 +121,7 @@ result = await client.run_workflow(
|
|||
```python Python
|
||||
result = await client.run_workflow(
|
||||
workflow_id="wpid_daily_report",
|
||||
browser_profile_id="bpf_abc123",
|
||||
browser_profile_id="bp_abc123",
|
||||
wait_for_completion=True,
|
||||
)
|
||||
```
|
||||
|
|
@ -130,7 +130,7 @@ result = await client.run_workflow(
|
|||
const result = await skyvern.runWorkflow({
|
||||
body: {
|
||||
workflow_id: "wpid_daily_report",
|
||||
browser_profile_id: "bpf_abc123",
|
||||
browser_profile_id: "bp_abc123",
|
||||
},
|
||||
waitForCompletion: true,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -64,6 +64,16 @@ codex mcp get skyvern
|
|||
|
||||
If you previously configured Skyvern with an `x-api-key` header, run `codex mcp remove skyvern` first so Codex does not skip the OAuth handshake. You do not need to run `codex mcp login skyvern` after `add` — the OAuth flow runs inline. Use `codex mcp login skyvern` only to re-authenticate after a token expires or to request custom `--scopes`.
|
||||
|
||||
<Note>
|
||||
If `codex mcp add` fails with `resource is not allowed for this authorization server`, your Codex version derived a trailing-slash `resource` from the URL. Pass the slashless resource explicitly:
|
||||
|
||||
```bash
|
||||
codex mcp add skyvern --url https://api.skyvern.com/mcp/ --oauth-resource https://api.skyvern.com/mcp
|
||||
```
|
||||
|
||||
Skyvern Cloud accepts both forms, so the flag is only needed on older self-hosted deployments.
|
||||
</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="Cursor">
|
||||
|
||||
|
|
@ -130,18 +140,19 @@ claude mcp add-json skyvern '{"type":"http","url":"https://api.skyvern.com/mcp/"
|
|||
3. When Claude Desktop opens the Skyvern installer preview, click **Install**.
|
||||
4. In the **Configure Skyvern** dialog, paste your Skyvern API key.
|
||||
5. Leave **Skyvern MCP URL** set to `https://api.skyvern.com/mcp/` unless you are connecting to a different deployment, then click **Save**.
|
||||
6. In Claude, ask: "Create a Skyvern browser session". A working setup returns a Skyvern browser session id.
|
||||
|
||||
If double-clicking is blocked by your system, you can instead open **Claude Desktop > Settings > Extensions > Install Extension** and select the downloaded file manually.
|
||||
|
||||
The bundle defaults to `https://api.skyvern.com/mcp/` and removes the separate Node.js requirement.
|
||||
|
||||
**Linux, self-hosted, or advanced fallback (requires Node.js >= 20)**
|
||||
<Note>
|
||||
If Claude says Skyvern "needs authorization" or mentions OAuth, the API key is not configured. Open Claude Desktop **Settings -> Extensions -> Skyvern -> Configure**, paste your Skyvern API key, and save.
|
||||
</Note>
|
||||
|
||||
Add this manual bridge to your Claude Desktop config file:
|
||||
**Linux manual config (requires Node.js >= 20)**
|
||||
|
||||
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
||||
- **Linux**: `~/.config/Claude/claude_desktop_config.json`
|
||||
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
||||
On Linux, add this manual bridge to `~/.config/Claude/claude_desktop_config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -159,7 +170,7 @@ Add this manual bridge to your Claude Desktop config file:
|
|||
}
|
||||
```
|
||||
|
||||
Use this fallback for Linux or any Claude Desktop setup where the one-click bundle is not available. It uses [mcp-remote](https://www.npmjs.com/package/mcp-remote) to bridge the remote MCP server to stdio and requires Node.js >= 20.
|
||||
Use this Linux path when the one-click bundle is not available on your platform. It uses [mcp-remote](https://www.npmjs.com/package/mcp-remote) to bridge the remote MCP server to stdio and requires Node.js >= 20.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Cursor">
|
||||
|
|
|
|||
|
|
@ -12,16 +12,32 @@ Browser Profiles capture the full browser state (cookies, storage, session files
|
|||
- Want to fan out multiple workflows that all reuse the same authenticated browser state.
|
||||
- Need an audit-friendly way to persist state separate from long-lived browser sessions.
|
||||
|
||||
Whereas a **browser session** is a temporary, real-time browser, a **browser profile** is a reusable snapshot created from that session (or from a workflow run that persisted its session). Profiles are scoped to your organization and can be reused as often as you need.
|
||||
Whereas a **browser session** is a temporary, real-time browser, a **browser profile** is a reusable profile archive. You can create one blank, from a browser session, or from a workflow run that persisted its session. Profiles are scoped to your organization and can be reused as often as you need.
|
||||
|
||||
## How Browser Profiles Work
|
||||
|
||||
1. Run a workflow with `persist_browser_session: true` **or** open a persistent browser session.
|
||||
2. Close the workflow run or browser session so Skyvern can upload the archived state.
|
||||
1. Create a blank profile with only `name`, or run a workflow with `persist_browser_session: true` **or** open a persistent browser session.
|
||||
2. For workflow and browser-session sources, close the workflow run or browser session so Skyvern can upload the archived state.
|
||||
3. Create a browser profile from that source once the upload finishes.
|
||||
4. Pass `browser_profile_id` to subsequent workflow runs to restore the saved state instantly.
|
||||
4. Pass `browser_profile_id` to subsequent workflow runs to start from the saved profile archive.
|
||||
|
||||
## Option A — Create a Profile from a Workflow Run
|
||||
## Option A — Create a Blank Profile
|
||||
|
||||
Use this approach when you want a reusable profile ID before any browsing has happened. Skyvern seeds the profile from the configured default browser profile directory when available, with a minimal loadable profile skeleton as a fallback.
|
||||
|
||||
```python
|
||||
from skyvern import Skyvern
|
||||
|
||||
skyvern = Skyvern(api_key="YOUR_API_KEY")
|
||||
|
||||
browser_profile = await skyvern.browser_profiles.create_browser_profile(
|
||||
name="fresh-profile",
|
||||
description="Blank profile for future runs",
|
||||
)
|
||||
print(browser_profile.browser_profile_id)
|
||||
```
|
||||
|
||||
## Option B — Create a Profile from a Workflow Run
|
||||
|
||||
Use this approach when you already ran a workflow with `persist_browser_session: true`. Always poll the run (e.g., `GET /v1/runs/{run_id}`) until it reaches `status = "completed"` before attempting to create the profile—Skyvern only begins uploading the archived browser state once the run finishes.
|
||||
|
||||
|
|
@ -67,7 +83,7 @@ async def create_profile_with_retry(
|
|||
raise RuntimeError("Session never finished uploading a profile archive")
|
||||
```
|
||||
|
||||
## Option B — Create a Profile from a Browser Session
|
||||
## Option C — Create a Profile from a Browser Session
|
||||
|
||||
If you opened a persistent browser session directly (without a workflow), close it and then create a profile using the session ID:
|
||||
|
||||
|
|
@ -100,4 +116,3 @@ print(workflow_run.run_id)
|
|||
```
|
||||
|
||||
If the workflow also sets `persist_browser_session: true`, you can capture a fresh profile again at the end and keep the cycle going.
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ Skyvern supports logging into websites that require a 2FA/MFA/Verification code.
|
|||
|
||||
Step 1: Save your username and password in [Skyvern Credential](https://app.skyvern.com/credentials). See [Password Management](/credentials/passwords#manage-passwords-in-skyvern-cloud) for more details.
|
||||
|
||||
Step 2: Add your account by manually entering the secret key (extracted from the QR code). Not sure how to get it? [Follow this guide](https://bitwarden.com/help/integrated-authenticator/).
|
||||
Step 2: Add your account by entering the secret key, pasting the full `otpauth://` URI, or clicking **Scan QR** to upload a QR code image from the site's 2FA setup screen. Not sure how to get the key? [Follow this guide](https://bitwarden.com/help/integrated-authenticator/).
|
||||
|
||||
> 💡 Don't have the key? Contact [Skyvern Support](mailto:support@skyvern.com) and we can help you get it.
|
||||
|
||||
|
|
@ -228,4 +228,4 @@ curl -X GET "https://api.skyvern.com/v1/credentials/totp?totp_identifier=user@ex
|
|||
- `otp_type` *(optional)* – filter on `totp` or `magic_link`.
|
||||
- `limit` *(optional)* – number of records to return (default `50`, maximum `200`).
|
||||
|
||||
The response is a list of TOTP objects, ordered newest first. Skyvern only returns codes created within the last `TOTP_LIFESPAN_MINUTES` (10 minutes by default).
|
||||
The response is a list of TOTP objects, ordered newest first and capped by `limit`. Runtime polling still only uses unexpired codes within `TOTP_LIFESPAN_MINUTES`.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ mode: custom
|
|||
<div className="cl-page">
|
||||
<div className="cl-sidebar">
|
||||
<p className="cl-sidebar-title">TIMELINE</p>
|
||||
<a href="#week-of-june-30%2C-2026" className="cl-sidebar-link">Week of Jun 30, 2026</a>
|
||||
<a href="#week-of-june-22%2C-2026" className="cl-sidebar-link">Week of Jun 22, 2026</a>
|
||||
<a href="#week-of-june-15%2C-2026" className="cl-sidebar-link">Week of Jun 15, 2026</a>
|
||||
<a href="#week-of-june-8%2C-2026" className="cl-sidebar-link">Week of Jun 8, 2026</a>
|
||||
<a href="#week-of-june-1%2C-2026" className="cl-sidebar-link">Week of Jun 1, 2026</a>
|
||||
<a href="#week-of-may-25%2C-2026" className="cl-sidebar-link">Week of May 25, 2026</a>
|
||||
|
|
@ -17,19 +20,157 @@ mode: custom
|
|||
<a href="#week-of-april-21%2C-2026" className="cl-sidebar-link">Week of Apr 21, 2026</a>
|
||||
<a href="#week-of-april-14%2C-2026" className="cl-sidebar-link">Week of Apr 14, 2026</a>
|
||||
<a href="#week-of-march-30%2C-2026" className="cl-sidebar-link">Week of Mar 30, 2026</a>
|
||||
<a href="#v1-0-22-—-february-26%2C-2026" className="cl-sidebar-link">v1.0.22 — Feb 26, 2026</a>
|
||||
<a href="#v1-0-21-—-february-24%2C-2026" className="cl-sidebar-link">v1.0.21 — Feb 24, 2026</a>
|
||||
<a href="#v1-0-18-—-february-19%2C-2026" className="cl-sidebar-link">v1.0.18 — Feb 19, 2026</a>
|
||||
<a href="#v1-0-17-—-february-19%2C-2026" className="cl-sidebar-link">v1.0.17 — Feb 19, 2026</a>
|
||||
<a href="#v1-0-16-—-february-19%2C-2026" className="cl-sidebar-link">v1.0.16 — Feb 19, 2026</a>
|
||||
<a href="#v1-0-15-—-february-17%2C-2026" className="cl-sidebar-link">v1.0.15 — Feb 17, 2026</a>
|
||||
<a href="#week-of-february-23%2C-2026" className="cl-sidebar-link">Week of Feb 23, 2026</a>
|
||||
<a href="#week-of-february-16%2C-2026" className="cl-sidebar-link">Week of Feb 16, 2026</a>
|
||||
</div>
|
||||
|
||||
<div className="cl-content">
|
||||
<h1 className="cl-title">Changelog</h1>
|
||||
<p className="cl-subtitle">New features, improvements, and fixes in Skyvern</p>
|
||||
|
||||
<Update label="Week of June 8, 2026" description="Editor onboarding, Copilot modes, GCS storage, API docs split, OTP fixes">
|
||||
<Update label="Week of June 30, 2026" description="Workflow Studio UX improvements, faster enrichment, code-block self-heal, extraction accuracy, bug fixes">
|
||||
|
||||
## Improvements
|
||||
|
||||
- **Block Type Shown in Workflow Studio Header** — The block detail panel in Workflow Studio now displays the block type in the header, making it easier to identify what kind of block you're editing at a glance. ([#6956](https://github.com/Skyvern-AI/skyvern/pull/6956))
|
||||
- **Improved Extraction Accuracy for Absent Data** — The agent now better handles cases where requested output is genuinely absent from the page, reducing false positives in extraction results. ([#6957](https://github.com/Skyvern-AI/skyvern/pull/6957))
|
||||
- **Data-Only Validation Skips Page Evidence** — Validation steps that check only extracted data no longer capture page screenshots when they aren't needed, reducing unnecessary work during runs. ([#6960](https://github.com/Skyvern-AI/skyvern/pull/6960))
|
||||
- **Copilot Block Runs Routed to UI Worker** — Copilot block runs are now dispatched to a dedicated UI worker, keeping the editor responsive during live automation. ([#6962](https://github.com/Skyvern-AI/skyvern/pull/6962))
|
||||
- **Clearer Invalid JSON Errors in Workflow Editor** — The workflow editor now surfaces a descriptive error when a parameter contains invalid JSON, making it faster to diagnose and fix configuration mistakes. ([#6963](https://github.com/Skyvern-AI/skyvern/pull/6963))
|
||||
- **"Ignore System Prompt" Moved to Advanced Settings** — The "Ignore system prompt" option has been relocated to the advanced settings panel, reducing clutter in the default block configuration view. ([#6964](https://github.com/Skyvern-AI/skyvern/pull/6964))
|
||||
- **Empty Extra HTTP Headers Hidden** — Extra HTTP header fields that are empty no longer appear in block configurations, reducing visual noise in the workflow editor. ([#6966](https://github.com/Skyvern-AI/skyvern/pull/6966))
|
||||
- **Block Selection Persisted in URL** — The selected block in Workflow Studio is now encoded in the URL, so your selection is preserved on reload and can be shared via link. ([#6969](https://github.com/Skyvern-AI/skyvern/pull/6969))
|
||||
- **Code-Block Self-Heal Minimum Retry Floor** — The code-block self-healing loop now enforces a minimum number of repair attempts before giving up, preventing premature failures on recoverable errors. ([#6971](https://github.com/Skyvern-AI/skyvern/pull/6971))
|
||||
- **Faster Live-Draft Enrichment** — Workflow recording live-draft enrichment now uses a faster model and a shorter debounce interval, making draft suggestions appear noticeably sooner while recording. ([#6973](https://github.com/Skyvern-AI/skyvern/pull/6973))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Fixed syntax highlighting disappearing when viewing large webhook payloads. ([#6967](https://github.com/Skyvern-AI/skyvern/pull/6967))
|
||||
- Fixed LLM blocks not enforcing their configured output schema, which could allow malformed data to propagate to downstream blocks. ([#6965](https://github.com/Skyvern-AI/skyvern/pull/6965))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Week of June 22, 2026" description="Workflow Studio preview, new models, label management, Gmail OTP, Copilot improvements, analytics filters, bug fixes">
|
||||
|
||||
## New features
|
||||
|
||||
- **Gmail-Backed OTP Lookup** — Agents can now retrieve one-time passwords from Gmail via OAuth, enabling automated login flows that depend on email-delivered verification codes. ([#6769](https://github.com/Skyvern-AI/skyvern/pull/6769))
|
||||
- **Copilot Chat History per Workflow** — The Copilot now retains its full conversation history scoped to each individual workflow, so prior context and decisions are preserved as you continue building. ([#6767](https://github.com/Skyvern-AI/skyvern/pull/6767))
|
||||
- **Code-First Editor Polish** — Code-first code blocks now display block labels, correctly render extraction output, and include a Build-vs-Code toggle for switching between visual and code editing modes. ([#6771](https://github.com/Skyvern-AI/skyvern/pull/6771))
|
||||
- **Workflow Studio (Preview)** — A redesigned workflow editor with a refreshed build canvas, integrated browser view, and run viewer is now available as an opt-in preview, giving teams an early look at the next-generation authoring experience. ([#6782](https://github.com/Skyvern-AI/skyvern/pull/6782))
|
||||
- **DeepSeek and Xiaomi MiMo Models** — DeepSeek and Xiaomi MiMo are now available in the model dropdown for agent runs. Gemini 2.5 Pro and 2.5 Flash have been deprecated. ([#6831](https://github.com/Skyvern-AI/skyvern/pull/6831))
|
||||
- **Label Management Settings** — Labels can now be renamed, recolored, and soft-deleted directly from the Settings page, making it easier to maintain a clean tag taxonomy. ([#6830](https://github.com/Skyvern-AI/skyvern/pull/6830))
|
||||
- **Browser Profiles in MCP Sessions** — Browser sessions initiated via MCP can now be associated with a browser profile, enabling credential and state reuse across MCP-driven runs. ([#6798](https://github.com/Skyvern-AI/skyvern/pull/6798))
|
||||
- **Workflow-Tag Filter on Analytics** — The analytics dashboard now supports filtering runs and metrics by workflow tag. ([#6780](https://github.com/Skyvern-AI/skyvern/pull/6780))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **Copilot Repair Shows Quiet Progress** — The Copilot's code-seam repair steps now appear as compact progress indicators instead of repeated chat messages, keeping the conversation readable during long repairs. ([#6746](https://github.com/Skyvern-AI/skyvern/pull/6746))
|
||||
- **Collapsible Sidebar with Avatar** — The left sidebar now features an edge toggle, a closed-state user avatar, and a smooth open/close animation for a more polished navigation experience. ([#6754](https://github.com/Skyvern-AI/skyvern/pull/6754))
|
||||
- **Structured Output Verified Before Completion** — Runs that produce structured data now verify the output satisfies the configured schema before marking the run as successfully complete. ([#6751](https://github.com/Skyvern-AI/skyvern/pull/6751))
|
||||
- **MCP Workflow Overlap Settings Preserved** — Overlap settings configured via MCP are now retained correctly when the workflow is subsequently edited, preventing unintentional resets. ([#6748](https://github.com/Skyvern-AI/skyvern/pull/6748))
|
||||
- **Browser Profile List Sorted Newest First** — The browser profile picker now orders profiles with the most recently created at the top, making recent profiles easier to find and select. ([#6739](https://github.com/Skyvern-AI/skyvern/pull/6739))
|
||||
- **Remote Browser Sessions Capped at Four Hours** — Remote browser sessions now have a maximum duration of four hours, preventing orphaned sessions from consuming resources indefinitely.
|
||||
- **Debug Sessions Stay Open After Runs** — Browser sessions launched from the workflow editor in debug mode now remain alive after a run completes, so you can inspect the final page state without the session closing immediately. ([#6832](https://github.com/Skyvern-AI/skyvern/pull/6832))
|
||||
- **GPT-5 Mini via OpenRouter** — GPT-5 Mini is now available as a selectable model via OpenRouter. ([#6816](https://github.com/Skyvern-AI/skyvern/pull/6816))
|
||||
- **Extraction and AI Steps in Code-Block View** — Extraction and AI steps are now surfaced in the code-block run view, filling a gap in execution visibility. ([#6823](https://github.com/Skyvern-AI/skyvern/pull/6823))
|
||||
- **Color Palette for Grouped Workflow Tags** — Tags that belong to a group are now displayed with a curated color palette, making it easier to distinguish tag groups at a glance. ([#6801](https://github.com/Skyvern-AI/skyvern/pull/6801))
|
||||
- **Improved Authenticator 2FA Credential Setup** — The credential setup flow for authenticator-based 2FA has been improved with clearer guidance and a smoother configuration experience. ([#6783](https://github.com/Skyvern-AI/skyvern/pull/6783))
|
||||
- **Copilot Data-Write Blocks Default to Safe Failure Mode** — New Copilot-generated data-write blocks now default to `continue_on_failure=false`, preventing downstream blocks from running on bad data. ([#6779](https://github.com/Skyvern-AI/skyvern/pull/6779))
|
||||
- **End-State Screenshots for All Open Tabs** — Task runs now capture end-state screenshots for every open tab at completion, giving a full snapshot of the browser state. ([#6777](https://github.com/Skyvern-AI/skyvern/pull/6777))
|
||||
- **Partial Deliverable on Budget Exhaustion** — Tasks that hit their credit budget now return the best-effort deliverable collected so far instead of failing without output. ([#6778](https://github.com/Skyvern-AI/skyvern/pull/6778))
|
||||
- **Planner Supports EXTRACT_INFORMATION and GOTO_URL** — The task planner can now emit EXTRACT_INFORMATION and GOTO_URL actions, expanding the set of strategies available during automated planning. ([#6800](https://github.com/Skyvern-AI/skyvern/pull/6800))
|
||||
- **Copilot Completion Recognition Improvements** — The Copilot completion recognizer is now more authoritative and evidence-backed, with stable criteria counts and more reliable recognition across runs. ([#6789](https://github.com/Skyvern-AI/skyvern/pull/6789))
|
||||
- **Copilot Code Repair Loop Reliability** — The Copilot code authoring repair loop is now more reliable, reducing cases where stuck repairs would stall progress. ([#6792](https://github.com/Skyvern-AI/skyvern/pull/6792))
|
||||
- **Workflow Studio Browser and Panel Improvements** — The Workflow Studio editor now supports take-control and viewport centering for the live browser, with alignment and toolbar polish for the run/editor panels. ([#6810](https://github.com/Skyvern-AI/skyvern/pull/6810))
|
||||
- **Analytics Tag Filters Accept Flexible Input Shapes** — Analytics tag filters now accept labels, groups, or `group:label` pairs in all three supported filter shapes. ([#6802](https://github.com/Skyvern-AI/skyvern/pull/6802))
|
||||
- **Run ID Search Fallback on Runs List** — The runs list now falls back to searching by run ID when no parameter-value match is found, making it easier to locate specific runs. ([#6788](https://github.com/Skyvern-AI/skyvern/pull/6788))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Fixed login credentials not being reattached after editing a workflow via MCP, which could cause credential-gated runs to fail. ([#6761](https://github.com/Skyvern-AI/skyvern/pull/6761))
|
||||
- Fixed conditional routing logic not being preserved when loading a workflow stored in the v1 format. ([#6760](https://github.com/Skyvern-AI/skyvern/pull/6760))
|
||||
- Fixed the active run context being lost when switching between organizations, requiring a page refresh to restore the correct run view. ([#6753](https://github.com/Skyvern-AI/skyvern/pull/6753))
|
||||
- Fixed browser connection settings defined in a TaskV2 block not being forwarded to child task runs. ([#6750](https://github.com/Skyvern-AI/skyvern/pull/6750))
|
||||
- Fixed telephone number inputs dropping digits when bare NANP-format phone numbers were typed. ([#6826](https://github.com/Skyvern-AI/skyvern/pull/6826))
|
||||
- Fixed the workflow builder freezing due to an infinite FlowRenderer dimension/layout feedback loop. ([#6824](https://github.com/Skyvern-AI/skyvern/pull/6824))
|
||||
- Fixed the code editor crashing with a stack overflow when opened on large or deeply-nested JSON. ([#6817](https://github.com/Skyvern-AI/skyvern/pull/6817))
|
||||
- Fixed the app failing to load after a deploy due to stale webpack chunks; the app now auto-recovers via a cache-busting reload. ([#6818](https://github.com/Skyvern-AI/skyvern/pull/6818))
|
||||
- Fixed runs returning an incorrect terminal outcome when the extraction schema had been modified after the initial recording. ([#6815](https://github.com/Skyvern-AI/skyvern/pull/6815))
|
||||
- Fixed MCP workflow edits dropping non-credential parameter-to-block links. ([#6813](https://github.com/Skyvern-AI/skyvern/pull/6813))
|
||||
- Fixed address bar paste not working in the VNC streaming view. ([#6812](https://github.com/Skyvern-AI/skyvern/pull/6812))
|
||||
- Fixed newly added workflow blocks not receiving focus in the editor. ([#6809](https://github.com/Skyvern-AI/skyvern/pull/6809))
|
||||
- Fixed Copilot code-block file downloads being written to the wrong directory. ([#6797](https://github.com/Skyvern-AI/skyvern/pull/6797))
|
||||
- Fixed parameter-value search not appearing in the v2 runs list. ([#6796](https://github.com/Skyvern-AI/skyvern/pull/6796))
|
||||
- Fixed extra actions firing after selecting a combobox option during text entry. ([#6787](https://github.com/Skyvern-AI/skyvern/pull/6787))
|
||||
- Fixed shadow DOM text nodes being missed during element text extraction. ([#6791](https://github.com/Skyvern-AI/skyvern/pull/6791))
|
||||
- Fixed persistent browser sessions incorrectly reporting a cached session as live when it had become stale.
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Week of June 15, 2026" description="Code-first code block editor, analytics drill-down, copilot repair loop, OTP fill, uncapped runtimes, voice input fixes">
|
||||
|
||||
## New features
|
||||
|
||||
- **OTP Fill at Runtime in Code-Block Sandbox** — Code blocks can now fill OTP fields using your stored TOTP credentials at runtime, enabling fully automated two-factor authentication flows without manual input. ([#6571](https://github.com/Skyvern-AI/skyvern/pull/6571))
|
||||
- **Uncapped Workflow Runtime** — Workflows can now be configured to run without a maximum time limit, enabling long-running automations that previously timed out. ([#6567](https://github.com/Skyvern-AI/skyvern/pull/6567))
|
||||
- **Code-First Code Block Editor** — Code blocks now feature a dedicated code editor with syntax highlighting, Jinja parameter hints, and a run timeline showing each action taken, giving developers full visibility and control over code-driven automations. ([#6604](https://github.com/Skyvern-AI/skyvern/pull/6604))
|
||||
- **Period-Aware Analytics Drill-Down** — The agent analytics drill-down panel now respects the selected time period (7/30/90/365 days or custom range) and shows per-agent average duration, credits per run, and period-over-period trends.
|
||||
- **Agent Directory Tree** — The agents and folders list has been redesigned as a navigable directory tree, making it easier to browse and organize agents across nested folder hierarchies. ([#6631](https://github.com/Skyvern-AI/skyvern/pull/6631))
|
||||
- **GCP Self-Host: Storage and Vault** — Self-hosted deployments on Google Cloud Platform now support GCS artifact storage and GCP Secret Manager vault, enabling full GCP-native deployments. ([#6632](https://github.com/Skyvern-AI/skyvern/pull/6632))
|
||||
- **1Password Credential Picker** — Credential inputs now include an item picker for 1Password vaults, letting you browse and select vault items directly during credential setup. ([#6651](https://github.com/Skyvern-AI/skyvern/pull/6651))
|
||||
- **Typed Extraction Schema for Copilot Code Blocks** — Copilot-generated code blocks now support a typed data extraction schema (matching `data_schema` parity), enabling structured data output from code-block automations. ([#6674](https://github.com/Skyvern-AI/skyvern/pull/6674))
|
||||
- **SDK-Backed Remote Browser Provider** — Agents can now connect to external browser providers via SDK, enabling tighter integration with third-party remote browser services. ([#6687](https://github.com/Skyvern-AI/skyvern/pull/6687))
|
||||
- **Bitwarden Credential Integration** — Saved credentials can now be sourced directly from Bitwarden vaults, bringing Bitwarden to full UI and functional parity with other supported credential providers. ([#6729](https://github.com/Skyvern-AI/skyvern/pull/6729))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **Smarter Loop Planning for Repeated Work** — The task planner now prefers loop-based tasks when it detects repeated same-shaped operations, improving throughput on multi-item automation runs. ([#6575](https://github.com/Skyvern-AI/skyvern/pull/6575))
|
||||
- **Agent Auto-Acts on Stalled Pages** — When the agent re-evaluates a page that hasn't changed, it now applies steering heuristics and acts immediately instead of stalling. ([#6577](https://github.com/Skyvern-AI/skyvern/pull/6577))
|
||||
- **Final Answer Surfaced Directly** — The task agent now returns the final deliverable directly instead of spinning through redundant synthesis steps, reducing latency on completed tasks. ([#6574](https://github.com/Skyvern-AI/skyvern/pull/6574))
|
||||
- **Copilot Stops Stuck Repair Loops** — The Workflow Copilot now detects when consecutive repairs make no verified progress, halts after three attempts, and presents an honest escalation with the draft preserved for review. ([#6608](https://github.com/Skyvern-AI/skyvern/pull/6608))
|
||||
- **Voice Input Microphone Permission** — The browser microphone permission prompt now appears correctly when using voice dictation in the Prompt Box and Workflow Copilot. ([#6601](https://github.com/Skyvern-AI/skyvern/pull/6601))
|
||||
- **`page.evaluate` Recorded in Code Block Timeline** — JavaScript `page.evaluate(...)` calls made inside code blocks are now recorded as actions in the run timeline, filling a gap in execution visibility. ([#6600](https://github.com/Skyvern-AI/skyvern/pull/6600))
|
||||
- **Active Run Shown on Browser Session Page** — Browser session detail pages now display which workflow run currently occupies the session, making it easier to understand session usage. ([#6691](https://github.com/Skyvern-AI/skyvern/pull/6691))
|
||||
- **Distinct Visual for Terminate Actions** — Terminate actions now appear with a distinct amber triangle icon in the run timeline, making it easy to spot where a run was stopped. ([#6693](https://github.com/Skyvern-AI/skyvern/pull/6693))
|
||||
- **PDF Field Mapping by Positional Labels** — PDF form filling now uses positional field labels to improve accuracy when mapping data to form fields with ambiguous names. ([#6663](https://github.com/Skyvern-AI/skyvern/pull/6663))
|
||||
- **MiMo-V2.5 Model Support via OpenRouter** — Added Xiaomi MiMo-V2.5 as a selectable LLM via OpenRouter for agent runs. ([#6636](https://github.com/Skyvern-AI/skyvern/pull/6636))
|
||||
- **Settings "API Keys" Renamed to "General"** — The "API Keys" section in Settings has been renamed to "General" to better reflect its full scope of configuration options. ([#6642](https://github.com/Skyvern-AI/skyvern/pull/6642))
|
||||
- **Run URLs Surfaced in MCP and CLI** — The agent app URL and session recording URLs are now included in run responses returned via MCP and the CLI, making it easier to link directly to a live run. ([#6719](https://github.com/Skyvern-AI/skyvern/pull/6719))
|
||||
- **Email OTP Credentials Supported in Copilot** — The Copilot can now use stored email OTP credentials when generating and validating code-block automations that require email-based authentication. ([#6716](https://github.com/Skyvern-AI/skyvern/pull/6716))
|
||||
- **Auto-Fill Default Google Account for Sheets Blocks** — Google Sheets blocks now automatically select the default linked Google account, reducing manual setup when configuring Sheets integrations. ([#6715](https://github.com/Skyvern-AI/skyvern/pull/6715))
|
||||
- **Copilot Output Accurately Reflects Verified Results** — The Copilot no longer under-reports successfully verified output, ensuring the run summary accurately reflects what was accomplished. ([#6710](https://github.com/Skyvern-AI/skyvern/pull/6710))
|
||||
- **Runs Halt Reliably on Terminal Blockers** — When the agent encounters strong evidence of an unresolvable blocker (such as a persistent challenge page), it now stops immediately rather than continuing to attempt further actions. ([#6714](https://github.com/Skyvern-AI/skyvern/pull/6714))
|
||||
- **Workflow Save Performance Improved** — Cache invalidation on workflow save is now batched, eliminating a per-block N+1 query pattern that slowed saves for large workflows. ([#6718](https://github.com/Skyvern-AI/skyvern/pull/6718))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Fixed the Run Inputs panel collapsing unexpectedly when filtering Run History. ([#6573](https://github.com/Skyvern-AI/skyvern/pull/6573))
|
||||
- Fixed the agent incorrectly retrying click fallbacks after an action dispatch timed out, causing unintended interactions. ([#6569](https://github.com/Skyvern-AI/skyvern/pull/6569))
|
||||
- Fixed session recordings and page interpretation not resuming correctly after navigation, causing missed recording segments. ([#6568](https://github.com/Skyvern-AI/skyvern/pull/6568))
|
||||
- Fixed code block runs not generating a recording entry, causing the Recording tab to appear empty. ([#6607](https://github.com/Skyvern-AI/skyvern/pull/6607))
|
||||
- Fixed code block action screenshots not appearing on the run Overview page. ([#6605](https://github.com/Skyvern-AI/skyvern/pull/6605))
|
||||
- Fixed long usernames or email addresses hiding the sidebar collapse button on desktop.
|
||||
- Fixed the File Parser block crashing when a downloaded file isn't a valid PDF (e.g. a site returns a short plain-text error instead of the expected document); the block now surfaces a clear parse error instead of failing the run unexpectedly. ([#6657](https://github.com/Skyvern-AI/skyvern/pull/6657))
|
||||
- Fixed the Inputs field missing from the Code view of code-first code blocks. ([#6633](https://github.com/Skyvern-AI/skyvern/pull/6633))
|
||||
- Fixed Copilot-synthesized download blocks not downloading the file during code replay. ([#6637](https://github.com/Skyvern-AI/skyvern/pull/6637), [#6638](https://github.com/Skyvern-AI/skyvern/pull/6638))
|
||||
- Fixed multi-step login flows not advancing when credentials were filled into JavaScript-gated fields. ([#6650](https://github.com/Skyvern-AI/skyvern/pull/6650))
|
||||
- Fixed an infinite update loop on the workflow build page when certain block configurations were active. ([#6660](https://github.com/Skyvern-AI/skyvern/pull/6660))
|
||||
- Fixed adopted-session file downloads not being available as run artifacts after the session ended. ([#6679](https://github.com/Skyvern-AI/skyvern/pull/6679))
|
||||
- Fixed the run timeline showing action and step rows for non-code blocks when they should only appear for code blocks. ([#6675](https://github.com/Skyvern-AI/skyvern/pull/6675))
|
||||
- Fixed workflow run actions not appearing in the timeline for all block types.
|
||||
- Fixed workflow runs not stopping when a configured time limit was exceeded. ([#6677](https://github.com/Skyvern-AI/skyvern/pull/6677))
|
||||
- Fixed the analytics plan-tier badge showing the incorrect tier for some organizations.
|
||||
- Fixed credits not being recorded when data was captured inside a Navigate block in task runs. ([#6698](https://github.com/Skyvern-AI/skyvern/pull/6698))
|
||||
- Fixed Copilot directory mode synthesizing incorrect code bindings. ([#6702](https://github.com/Skyvern-AI/skyvern/pull/6702))
|
||||
- Fixed FileUpload blocks silently skipping the upload when no file was provided, instead of recording a clean no-op and continuing. ([#6728](https://github.com/Skyvern-AI/skyvern/pull/6728))
|
||||
- Fixed the product tour not launching when triggered from the "Take a tour" menu option. ([#6727](https://github.com/Skyvern-AI/skyvern/pull/6727))
|
||||
- Fixed scanned PDF files being parsed as a single large page rather than processed page-by-page, which caused extraction to miss content on multi-page documents. ([#6722](https://github.com/Skyvern-AI/skyvern/pull/6722))
|
||||
- Fixed the block library drawer overflowing its container bounds in the workflow builder. ([#6721](https://github.com/Skyvern-AI/skyvern/pull/6721))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Week of June 8, 2026" description="Multi-tab agent control, Gemini 3.5 Flash, GCP Vault, bulk agent actions, credential clears, code-block credentials">
|
||||
|
||||
## New features
|
||||
|
||||
|
|
@ -37,6 +178,16 @@ mode: custom
|
|||
- **GCS Storage Backend** — Added Google Cloud Storage as an artifact storage backend for self-hosted deployments. ([#6442](https://github.com/Skyvern-AI/skyvern/pull/6442))
|
||||
- **Key-Optional Labels and Flexible Tag Filters** — Tags now support key-optional labels, and tag filter queries accept more flexible formats for richer agent organization. ([#6458](https://github.com/Skyvern-AI/skyvern/pull/6458))
|
||||
- **Self-Serve Editor Onboarding** — New users in the workflow editor now see a get-started modal with intent routing and template cards, a 4-stop guided product tour, and smart empty states on the dashboard and runs pages to accelerate time-to-first-automation. ([#6475](https://github.com/Skyvern-AI/skyvern/pull/6475))
|
||||
- **Multi-Tab Browser Control** — The autonomous agent loop can now open and interact with multiple browser tabs simultaneously, enabling workflows that span across new tab links and pop-ups. ([#6507](https://github.com/Skyvern-AI/skyvern/pull/6507))
|
||||
- **Gemini 3.5 Flash Model Support** — Added Google Gemini 3.5 Flash as a selectable LLM for agent runs, providing a faster inference option. ([#6505](https://github.com/Skyvern-AI/skyvern/pull/6505))
|
||||
- **GCP Secret Manager Vault Adapter** — Added Google Cloud Secret Manager as a supported vault backend for storing and retrieving secrets in self-hosted deployments. ([#6488](https://github.com/Skyvern-AI/skyvern/pull/6488))
|
||||
- **Bulk Actions on Agents List** — You can now select multiple agents at once and apply bulk actions directly from the agents list page. ([#6485](https://github.com/Skyvern-AI/skyvern/pull/6485))
|
||||
- **Self-Service Credential Clears** — Saved credentials can now be individually cleared from the credentials settings page without deleting and recreating them. ([#6480](https://github.com/Skyvern-AI/skyvern/pull/6480))
|
||||
- **Per-Run Session Recordings as Artifacts** — Recordings are now clipped to each run's time window and stored as downloadable run-scoped artifacts. ([#6479](https://github.com/Skyvern-AI/skyvern/pull/6479))
|
||||
- **Credential-Aware Scouting in Code-Block Mode** — The Copilot now uses saved credentials while scouting pages for code-block generation and produces credential-typed code that fills login fields using your stored credentials. ([#6521](https://github.com/Skyvern-AI/skyvern/pull/6521))
|
||||
- **Claude Fable 5 Model Support** — Added Claude Fable 5 as a selectable model for agent runs. ([#6539](https://github.com/Skyvern-AI/skyvern/pull/6539))
|
||||
- **Live Browser Recording with Instant Placeholders** — Session recordings now commit navigation and wait blocks immediately as placeholders during live recording, with support for capture pause and draft interpretation. ([#6561](https://github.com/Skyvern-AI/skyvern/pull/6561))
|
||||
- **Act-and-Observe Copilot Scouting** — The Copilot's page scouting now uses act-and-observe interactions that return bounded page evidence alongside gathered actions, improving code-block generation accuracy. ([#6533](https://github.com/Skyvern-AI/skyvern/pull/6533))
|
||||
|
||||
## Improvements
|
||||
|
||||
|
|
@ -49,6 +200,13 @@ mode: custom
|
|||
- **Block Title Editable from Settings Sidebar** — Workflow block titles can now be edited from the right-hand settings sidebar, without needing to use the inline editor on the canvas. ([#6443](https://github.com/Skyvern-AI/skyvern/pull/6443))
|
||||
- **API Reference Split into Agents and Runs Sections** — The public API reference is now organized into separate Agents and Runs sections for easier navigation. ([#6448](https://github.com/Skyvern-AI/skyvern/pull/6448))
|
||||
- **Label-First Tag Editor and Flexible Tag Filter UI** — The tag editor now accepts standalone labels or `group:label` format in a single input, and the filter bar supports filtering by label, group, or group:label for richer agent organization. ([#6470](https://github.com/Skyvern-AI/skyvern/pull/6470))
|
||||
- **2FA Field Progressive Disclosure in Login Block** — Two-factor authentication fields in the login workflow block are now collapsed by default and expanded on demand, reducing visual noise for workflows that don't use 2FA. ([#6490](https://github.com/Skyvern-AI/skyvern/pull/6490))
|
||||
- **Persistent Browser Session Profile Generation Now Opt-In** — Automatic browser profile generation during persistent sessions is now opt-in, giving you explicit control over when profiles are captured. ([#6489](https://github.com/Skyvern-AI/skyvern/pull/6489))
|
||||
- **Icon-Only Status Pills on Mobile Viewports** — Status badges now render in a compact icon-only format on small screen widths, preventing layout overflow on mobile devices. ([#6481](https://github.com/Skyvern-AI/skyvern/pull/6481))
|
||||
- **Hardened Webhook Delivery** — Workflow webhook delivery is now more reliable, with improved handling of transient failures and prioritized delivery ordering. ([#6478](https://github.com/Skyvern-AI/skyvern/pull/6478))
|
||||
- **Reduced Live Recording Draft Latency** — Live session recordings now appear almost instantly with placeholder entries, with final blocks committed after a short debounce window. ([#6553](https://github.com/Skyvern-AI/skyvern/pull/6553))
|
||||
- **Copilot Stops on Terminal Blockers** — The Copilot now correctly halts when it reaches a condition that blocks further progress, preventing runaway sessions. ([#6535](https://github.com/Skyvern-AI/skyvern/pull/6535))
|
||||
- **Copilot Chat Shows Run Outcome Verdict** — The Copilot chat timeline now reflects the actual run outcome verdict, giving a more accurate view of what the agent accomplished. ([#6532](https://github.com/Skyvern-AI/skyvern/pull/6532))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
|
|
@ -57,6 +215,23 @@ mode: custom
|
|||
- Fixed persistent-session screen recordings not appearing in the run view when the recording timestamp fell outside the run's time window. ([#6454](https://github.com/Skyvern-AI/skyvern/pull/6454))
|
||||
- Fixed Copilot inconsistently asking for a URL before running discovery when the user had only named a site without providing one. ([#6473](https://github.com/Skyvern-AI/skyvern/pull/6473))
|
||||
- Fixed Copilot asking for a URL after already successfully navigating to the requested site during discovery. ([#6472](https://github.com/Skyvern-AI/skyvern/pull/6472))
|
||||
- Fixed self-hosted deployments rejecting requests with "Invalid credentials" (HTTP 403) when the Docker UI injected an API key that the container's server incorrectly filtered out.
|
||||
- Fixed persistent session recordings not being finalized when the video encoding process outlasted the session's cleanup window. ([#6519](https://github.com/Skyvern-AI/skyvern/pull/6519))
|
||||
- Fixed the saved credentials status indicator not updating until the page was manually refreshed. ([#6517](https://github.com/Skyvern-AI/skyvern/pull/6517))
|
||||
- Fixed the workflow run timeline rendering blocks in branch-tree order instead of execution order, producing a confusing step sequence. ([#6515](https://github.com/Skyvern-AI/skyvern/pull/6515))
|
||||
- Fixed downloaded files inside loop blocks being shared across all iterations instead of scoped to the block that downloaded them. ([#6487](https://github.com/Skyvern-AI/skyvern/pull/6487))
|
||||
- Fixed session recordings defaulting to an incorrect resolution; recordings now use Playwright's default viewport size. ([#6524](https://github.com/Skyvern-AI/skyvern/pull/6524))
|
||||
- Fixed Copilot failing to recognize and use a saved credential when the credential ID was typed with a space or hyphen separator instead of an underscore; malformed IDs are now normalized and resolved correctly. ([#6529](https://github.com/Skyvern-AI/skyvern/pull/6529))
|
||||
- Fixed Copilot chat showing workflow blocks as completed even when the overall run goal was not demonstrated — the recorded run outcome verdict is now surfaced in the chat narrative. ([#6528](https://github.com/Skyvern-AI/skyvern/pull/6528))
|
||||
- Fixed Copilot browser sessions incorrectly blocking localhost navigation during page scouting, which could prevent evidence from being gathered from locally-served pages. ([#6527](https://github.com/Skyvern-AI/skyvern/pull/6527))
|
||||
- Fixed single-element JSON arrays being unwrapped to a scalar when passed as workflow run inputs. ([#6560](https://github.com/Skyvern-AI/skyvern/pull/6560))
|
||||
- Fixed code blocks silently dropping non-dict return values instead of passing them through to downstream blocks. ([#6556](https://github.com/Skyvern-AI/skyvern/pull/6556))
|
||||
- Fixed the task agent ignoring the `max_iterations` override, causing runs to exceed their configured step limit. ([#6544](https://github.com/Skyvern-AI/skyvern/pull/6544))
|
||||
- Fixed generated workflow parameter keys being duplicated, which caused a hard failure when the workflow was run. ([#6543](https://github.com/Skyvern-AI/skyvern/pull/6543))
|
||||
- Fixed task runs completing successfully even when a required sub-goal had not been satisfied. ([#6546](https://github.com/Skyvern-AI/skyvern/pull/6546))
|
||||
- Fixed the credential-clear confirmation dialog being hidden behind other overlays. ([#6542](https://github.com/Skyvern-AI/skyvern/pull/6542))
|
||||
- Fixed click actions on elements wrapped in disabled containers not being retargeted to the clickable child element. ([#6540](https://github.com/Skyvern-AI/skyvern/pull/6540))
|
||||
- Fixed Copilot loop detector incorrectly triggering at block dispatch boundaries. ([#6550](https://github.com/Skyvern-AI/skyvern/pull/6550))
|
||||
|
||||
</Update>
|
||||
|
||||
|
|
@ -317,37 +492,34 @@ mode: custom
|
|||
|
||||
</Update>
|
||||
|
||||
<Update label="v1.0.22 — February 26, 2026" description="Adaptive caching, Workflow Trigger block, CLI signup, and more">
|
||||
<Update label="Week of February 23, 2026" description="Adaptive caching, Workflow Trigger block, CLI signup, reserved parameters, new LLM models">
|
||||
|
||||
## New features
|
||||
|
||||
- **Adaptive Caching (Script Generation)** — Skyvern can now learn from repeated workflow runs and generate cached scripts that speed up future executions. When a block runs successfully, Skyvern records a reusable script and replays it on subsequent runs, falling back to the AI agent only if the script fails. ([#4908](https://github.com/Skyvern-AI/skyvern/pull/4908), [#4916](https://github.com/Skyvern-AI/skyvern/pull/4916), [#4917](https://github.com/Skyvern-AI/skyvern/pull/4917), [#4920](https://github.com/Skyvern-AI/skyvern/pull/4920), [#4922](https://github.com/Skyvern-AI/skyvern/pull/4922), [#4931](https://github.com/Skyvern-AI/skyvern/pull/4931))
|
||||
|
||||
- **Workflow Trigger Block** — A new block type that lets one workflow trigger another from within the workflow editor. Chain workflows together as building blocks for complex automations. ([#4885](https://github.com/Skyvern-AI/skyvern/pull/4885))
|
||||
|
||||
- **Browser-based CLI Signup** — New users can sign up for Skyvern Cloud directly from the CLI. Running `skyvern signup` opens a browser flow that creates your account and stores your API key locally. ([#4925](https://github.com/Skyvern-AI/skyvern/pull/4925))
|
||||
|
||||
- **Interactive ngrok Tunnel** — `skyvern browser serve` can now create an ngrok tunnel automatically, making it easy to expose your local browser to Skyvern Cloud without manual network configuration. ([#4924](https://github.com/Skyvern-AI/skyvern/pull/4924))
|
||||
|
||||
- **South Korea Proxy Location** — Added `RESIDENTIAL_KR` as a proxy geolocation option for automations targeting South Korean websites. ([#4918](https://github.com/Skyvern-AI/skyvern/pull/4918))
|
||||
|
||||
- **Downloaded Files Tab** — Browser session detail pages now include a Downloaded Files tab for viewing and accessing files captured during a session. ([#4911](https://github.com/Skyvern-AI/skyvern/pull/4911))
|
||||
|
||||
- **CDP Proxy Authentication** — Remote browser connections now support authenticated proxies via the CDP `Fetch.authRequired` protocol. ([#4936](https://github.com/Skyvern-AI/skyvern/pull/4936))
|
||||
|
||||
- **Remote Browser Download Interception** — File downloads triggered by XHR requests and other non-navigation events are now captured when using remote CDP browser connections. ([#4906](https://github.com/Skyvern-AI/skyvern/pull/4906), [#4921](https://github.com/Skyvern-AI/skyvern/pull/4921), [#4934](https://github.com/Skyvern-AI/skyvern/pull/4934))
|
||||
- **`current_date` Reserved Parameter** — Workflows now have a built-in `current_date` parameter that resolves to today's date automatically. ([#4854](https://github.com/Skyvern-AI/skyvern/pull/4854))
|
||||
- **Reserved Parameters in Block Editor** — The workflow block parameter picker now shows reserved system parameters, making them discoverable without memorizing names. ([#4857](https://github.com/Skyvern-AI/skyvern/pull/4857))
|
||||
- **Natural Language Loop `data_schema`** — Loop blocks driven by natural language extraction now support a `data_schema` field for consistent output structure. ([#4851](https://github.com/Skyvern-AI/skyvern/pull/4851))
|
||||
- **Gemini 3.1 Pro and Inception Mercury-2** — Two new LLM engine options for your automations. ([#4847](https://github.com/Skyvern-AI/skyvern/pull/4847))
|
||||
- **MCP Server on API Service** — The MCP remote server is now mounted at `/mcp` on the existing API, eliminating the need for a separate process. ([#4843](https://github.com/Skyvern-AI/skyvern/pull/4843))
|
||||
|
||||
## Improvements
|
||||
|
||||
- **Renamed "Login-Free" to "Saved Profile"** — Clearer terminology throughout the UI. Browser session checkbox wording has also been improved. ([#4914](https://github.com/Skyvern-AI/skyvern/pull/4914))
|
||||
|
||||
- **TOTP Verification Improvements** — Better timer handling, expired code retry, 2FA banner suppression, and more reliable goal-text extraction during TOTP flows. ([#4860](https://github.com/Skyvern-AI/skyvern/pull/4860))
|
||||
|
||||
- **TOTP Webhook includes `workflow_permanent_id`** — Easier to identify which workflow is requesting a 2FA code. ([#4871](https://github.com/Skyvern-AI/skyvern/pull/4871))
|
||||
|
||||
- **Consolidated Gemini 3 Pro Model Key** — `VERTEX_GEMINI_3_PRO` now auto-resolves to the latest version, so you no longer need to update config when Google releases point versions. ([#4926](https://github.com/Skyvern-AI/skyvern/pull/4926))
|
||||
|
||||
- **Browser Rotation for Remote Connections** — Remote browser environments now support context rotation, improving reliability for long-running automations. ([#4929](https://github.com/Skyvern-AI/skyvern/pull/4929))
|
||||
- Workflow save validation (HTTP 422) now returns clear, field-level error messages. ([#4852](https://github.com/Skyvern-AI/skyvern/pull/4852))
|
||||
- Browser launch errors now show actionable messages instead of raw exceptions. ([#4844](https://github.com/Skyvern-AI/skyvern/pull/4844))
|
||||
- Cloud LLM fallback overrides are now properly applied when selecting models. ([#4839](https://github.com/Skyvern-AI/skyvern/pull/4839))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
|
|
@ -359,67 +531,22 @@ mode: custom
|
|||
- MCP remote auth token comparison no longer fails on encrypted tokens. ([#4863](https://github.com/Skyvern-AI/skyvern/pull/4863))
|
||||
- `skyvern quickstart` now handles local PostgreSQL without a pre-existing `skyvern` role. ([#4878](https://github.com/Skyvern-AI/skyvern/pull/4878))
|
||||
- WebSocket URLs through ngrok tunnels now rewrite correctly for live browser streaming. ([#4927](https://github.com/Skyvern-AI/skyvern/pull/4927))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="v1.0.21 — February 24, 2026" description="Reserved parameters, data_schema for loops, new LLM models">
|
||||
|
||||
## New features
|
||||
|
||||
- **`current_date` Reserved Parameter** — Workflows now have a built-in `current_date` parameter that resolves to today's date automatically. ([#4854](https://github.com/Skyvern-AI/skyvern/pull/4854))
|
||||
|
||||
- **Reserved Parameters in Block Editor** — The workflow block parameter picker now shows reserved system parameters, making them discoverable without memorizing names. ([#4857](https://github.com/Skyvern-AI/skyvern/pull/4857))
|
||||
|
||||
- **Natural Language Loop `data_schema`** — Loop blocks driven by natural language extraction now support a `data_schema` field for consistent output structure. ([#4851](https://github.com/Skyvern-AI/skyvern/pull/4851))
|
||||
|
||||
- **Gemini 3.1 Pro and Inception Mercury-2** — Two new LLM engine options for your automations. ([#4847](https://github.com/Skyvern-AI/skyvern/pull/4847))
|
||||
|
||||
- **MCP Server on API Service** — The MCP remote server is now mounted at `/mcp` on the existing API, eliminating the need for a separate process. ([#4843](https://github.com/Skyvern-AI/skyvern/pull/4843))
|
||||
|
||||
## Improvements
|
||||
|
||||
- Workflow save validation (HTTP 422) now returns clear, field-level error messages. ([#4852](https://github.com/Skyvern-AI/skyvern/pull/4852))
|
||||
- Browser launch errors now show actionable messages instead of raw exceptions. ([#4844](https://github.com/Skyvern-AI/skyvern/pull/4844))
|
||||
- Cloud LLM fallback overrides are now properly applied when selecting models. ([#4839](https://github.com/Skyvern-AI/skyvern/pull/4839))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Conditional blocks no longer crash when all branches use Jinja templates. ([#4849](https://github.com/Skyvern-AI/skyvern/pull/4849))
|
||||
- Conditional blocks no longer misinterpret resolved Jinja template variables. ([#4841](https://github.com/Skyvern-AI/skyvern/pull/4841))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="v1.0.18 — February 19, 2026" description="Browser profile testing and saved-profile workflows">
|
||||
<Update label="Week of February 16, 2026" description="Browser profile testing, Skills package, 2FA detection, full CLI parity, Claude Opus 4.6">
|
||||
|
||||
## New features
|
||||
|
||||
- **Browser Profile Testing** — Test browser profiles directly from the UI to verify that saved login sessions are still valid. Workflows can also run with a saved browser profile, enabling login-free automations that reuse authenticated sessions. ([#4818](https://github.com/Skyvern-AI/skyvern/pull/4818))
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- When both a TOTP credential and a webhook are configured for 2FA, the credential is now correctly prioritized. ([#4811](https://github.com/Skyvern-AI/skyvern/pull/4811))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="v1.0.17 — February 19, 2026" description="Skills package and cached script management">
|
||||
|
||||
## New features
|
||||
|
||||
- **Skyvern Skills Package** — The new `skyvern skill` CLI command provides pre-built workflow templates and reference documentation for common automation patterns. ([#4817](https://github.com/Skyvern-AI/skyvern/pull/4817))
|
||||
|
||||
- **Clear Cached Scripts API** — A new endpoint lets you clear cached automation scripts for a workflow when a target website changes and you want to force Skyvern to re-learn. ([#4809](https://github.com/Skyvern-AI/skyvern/pull/4809))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="v1.0.16 — February 19, 2026" description="2FA detection, full CLI parity, Claude Opus 4.6 CUA">
|
||||
|
||||
## New features
|
||||
|
||||
- **Automatic 2FA Detection Without TOTP Credentials** — Skyvern now detects when a website asks for a 2FA code even without pre-configured TOTP credentials. The system pauses and waits for you to provide the code via the UI or webhook. ([#4786](https://github.com/Skyvern-AI/skyvern/pull/4786))
|
||||
|
||||
- **Full CLI Parity with MCP** — The CLI now supports browser session management, credential management, block operations, and enhanced workflow commands. Everything available through MCP is now accessible from the command line. ([#4789](https://github.com/Skyvern-AI/skyvern/pull/4789), [#4792](https://github.com/Skyvern-AI/skyvern/pull/4792), [#4793](https://github.com/Skyvern-AI/skyvern/pull/4793))
|
||||
|
||||
- **Claude Opus 4.6 CUA Support** — Anthropic's Claude Opus 4.6 is now available as a Computer Use Agent model for driving browser interactions. ([#4780](https://github.com/Skyvern-AI/skyvern/pull/4780))
|
||||
- **Anthropic Claude Opus 4.6** — Added Claude Opus 4.6 as an available LLM engine for web automation tasks. ([#4777](https://github.com/Skyvern-AI/skyvern/pull/4777), [#4778](https://github.com/Skyvern-AI/skyvern/pull/4778))
|
||||
|
||||
## Improvements
|
||||
|
||||
|
|
@ -427,17 +554,10 @@ mode: custom
|
|||
|
||||
## Bug fixes
|
||||
|
||||
- When both a TOTP credential and a webhook are configured for 2FA, the credential is now correctly prioritized. ([#4811](https://github.com/Skyvern-AI/skyvern/pull/4811))
|
||||
- Fixed conditional blocks evaluating the wrong value after Jinja template rendering. ([#4801](https://github.com/Skyvern-AI/skyvern/pull/4801))
|
||||
- Fixed MFA resolution priority when both TOTP credentials and webhooks are configured. ([#4800](https://github.com/Skyvern-AI/skyvern/pull/4800))
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="v1.0.15 — February 17, 2026" description="Claude Opus 4.6 model support">
|
||||
|
||||
## New features
|
||||
|
||||
- **Anthropic Claude Opus 4.6** — Added Claude Opus 4.6 as an available LLM engine for web automation tasks. ([#4777](https://github.com/Skyvern-AI/skyvern/pull/4777), [#4778](https://github.com/Skyvern-AI/skyvern/pull/4778))
|
||||
|
||||
</Update>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,286 +0,0 @@
|
|||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
- [Skyvern Langchain](#skyvern-langchain)
|
||||
- [Installation](#installation)
|
||||
- [Basic Usage](#basic-usage)
|
||||
- [Run a task(sync) locally in your local environment](#run-a-tasksync-locally-in-your-local-environment)
|
||||
- [Run a task(async) locally in your local environment](#run-a-taskasync-locally-in-your-local-environment)
|
||||
- [Get a task locally in your local environment](#get-a-task-locally-in-your-local-environment)
|
||||
- [Run a task(sync) by calling skyvern APIs](#run-a-tasksync-by-calling-skyvern-apis)
|
||||
- [Run a task(async) by calling skyvern APIs](#run-a-taskasync-by-calling-skyvern-apis)
|
||||
- [Get a task by calling skyvern APIs](#get-a-task-by-calling-skyvern-apis)
|
||||
- [Agent Usage](#agent-usage)
|
||||
- [Run a task(async) locally in your local environment and wait until the task is finished](#run-a-taskasync-locally-in-your-local-environment-and-wait-until-the-task-is-finished)
|
||||
- [Run a task(async) by calling skyvern APIs and wait until the task is finished](#run-a-taskasync-by-calling-skyvern-apis-and-wait-until-the-task-is-finished)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
# Skyvern Langchain
|
||||
|
||||
This is a langchain integration for Skyvern.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install skyvern-langchain
|
||||
```
|
||||
|
||||
To run the example scenarios, you might need to install other langchain dependencies.
|
||||
```bash
|
||||
pip install langchain-openai
|
||||
pip install langchain-community
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
This is the only basic usage of skyvern langchain tool. If you want a full langchain integration experience, please refer to the [Agent Usage](#agent-usage) section to play with langchain agent.
|
||||
|
||||
Go to [Langchain Tools](https://python.langchain.com/v0.1/docs/modules/tools/) to see more advanced langchain tool usage.
|
||||
|
||||
|
||||
### Run a task(sync) locally in your local environment
|
||||
> sync task won't return until the task is finished.
|
||||
|
||||
:warning: :warning: if you want to run this code block, you need to run `skyvern init` command in your terminal to set up skyvern first.
|
||||
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from skyvern_langchain.agent import RunTask
|
||||
|
||||
run_task = RunTask()
|
||||
|
||||
async def main():
|
||||
# to run skyvern agent locally, must run `skyvern init` first
|
||||
print(await run_task.ainvoke("Navigate to the Hacker News homepage and get the top 3 posts."))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### Run a task(async) locally in your local environment
|
||||
> async task will return immediately and the task will be running in the background.
|
||||
|
||||
:warning: :warning: if you want to run the task in the background, you need to keep the script running until the task is finished, otherwise the task will be killed when the script is finished.
|
||||
|
||||
:warning: :warning: if you want to run this code block, you need to run `skyvern init` command in your terminal to set up skyvern first.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from skyvern_langchain.agent import DispatchTask
|
||||
|
||||
dispatch_task = DispatchTask()
|
||||
|
||||
async def main():
|
||||
# to run skyvern agent locally, must run `skyvern init` first
|
||||
print(await dispatch_task.ainvoke("Navigate to the Hacker News homepage and get the top 3 posts."))
|
||||
|
||||
# keep the script running until the task is finished
|
||||
await asyncio.sleep(600)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
|
||||
### Get a task locally in your local environment
|
||||
|
||||
:warning: :warning: if you want to run this code block, you need to run `skyvern init` command in your terminal to set up skyvern first.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from skyvern_langchain.agent import GetTask
|
||||
|
||||
get_task = GetTask()
|
||||
|
||||
async def main():
|
||||
# to run skyvern agent locally, must run `skyvern init` first
|
||||
print(await get_task.ainvoke("<task_id>"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
|
||||
### Run a task(sync) by calling skyvern APIs
|
||||
> sync task won't return until the task is finished.
|
||||
|
||||
no need to run `skyvern init` command in your terminal to set up skyvern before using this integration.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from skyvern_langchain.client import RunTask
|
||||
|
||||
run_task = RunTask(
|
||||
api_key="<your_organization_api_key>",
|
||||
)
|
||||
# or you can load the api_key from SKYVERN_API_KEY in .env
|
||||
# run_task = RunTask()
|
||||
|
||||
async def main():
|
||||
print(await run_task.ainvoke("Navigate to the Hacker News homepage and get the top 3 posts."))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### Run a task(async) by calling skyvern APIs
|
||||
> async task will return immediately and the task will be running in the background.
|
||||
|
||||
no need to run `skyvern init` command in your terminal to set up skyvern before using this integration.
|
||||
|
||||
the task is actually running in the skyvern cloud service, so you don't need to keep your script running until the task is finished.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from skyvern_langchain.client import DispatchTask
|
||||
|
||||
dispatch_task = DispatchTask(
|
||||
api_key="<your_organization_api_key>",
|
||||
)
|
||||
# or you can load the api_key from SKYVERN_API_KEY in .env
|
||||
# dispatch_task = DispatchTask()
|
||||
|
||||
async def main():
|
||||
print(await dispatch_task.ainvoke("Navigate to the Hacker News homepage and get the top 3 posts."))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
|
||||
### Get a task by calling skyvern APIs
|
||||
> async task will return immediately and the task will be running in the background.
|
||||
|
||||
no need to run `skyvern init` command in your terminal to set up skyvern before using this integration.
|
||||
|
||||
the task is actually running in the skyvern cloud service, so you don't need to keep your script running until the task is finished.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from skyvern_langchain.client import GetTask
|
||||
|
||||
get_task = GetTask(
|
||||
api_key="<your_organization_api_key>",
|
||||
)
|
||||
# or you can load the api_key from SKYVERN_API_KEY in .env
|
||||
# get_task = GetTask()
|
||||
|
||||
async def main():
|
||||
print(await get_task.ainvoke("<task_id>"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Agent Usage
|
||||
|
||||
Langchain is more powerful when used with [Langchain Agents](https://python.langchain.com/v0.1/docs/modules/agents/).
|
||||
|
||||
The following two examples show how to build an agent that executes a specified task, waits for its completion, and then returns the results. For example, the agent is tasked with navigating to the Hacker News homepage and retrieving the top three posts.
|
||||
|
||||
|
||||
### Run a task(async) locally in your local environment and wait until the task is finished
|
||||
|
||||
> async task will return immediately and the task will be running in the background. You can use `GetTask` tool to poll the task information until the task is finished.
|
||||
|
||||
:warning: :warning: if you want to run this code block, you need to run `skyvern init` command in your terminal to set up skyvern first.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from dotenv import load_dotenv
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain.agents import initialize_agent, AgentType
|
||||
from skyvern_langchain.agent import DispatchTask, GetTask
|
||||
|
||||
from langchain_community.tools.sleep.tool import SleepTool
|
||||
|
||||
# load OpenAI API key from .env
|
||||
load_dotenv()
|
||||
|
||||
llm = ChatOpenAI(model="gpt-4o", temperature=0)
|
||||
|
||||
dispatch_task = DispatchTask()
|
||||
get_task = GetTask()
|
||||
|
||||
agent = initialize_agent(
|
||||
llm=llm,
|
||||
tools=[
|
||||
dispatch_task,
|
||||
get_task,
|
||||
SleepTool(),
|
||||
],
|
||||
verbose=True,
|
||||
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
# use sleep tool to set up the polling logic until the task is completed, if you only want to dispatch a task, you can remove the sleep tool
|
||||
print(await agent.ainvoke("Run a task with Skyvern. The task is about 'Navigate to the Hacker News homepage and get the top 3 posts.' Then, get this task information until it's completed. The task information re-get interval should be 60s."))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
|
||||
### Run a task(async) by calling skyvern APIs and wait until the task is finished
|
||||
|
||||
> async task will return immediately and the task will be running in the background. You can use `GetTask` tool to poll the task information until the task is finished.
|
||||
|
||||
no need to run `skyvern init` command in your terminal to set up skyvern before using this integration.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from dotenv import load_dotenv
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain.agents import initialize_agent, AgentType
|
||||
from skyvern_langchain.client import DispatchTask, GetTask
|
||||
|
||||
from langchain_community.tools.sleep.tool import SleepTool
|
||||
|
||||
# load OpenAI API key from .env
|
||||
load_dotenv()
|
||||
|
||||
llm = ChatOpenAI(model="gpt-4o", temperature=0)
|
||||
|
||||
dispatch_task = DispatchTask(
|
||||
api_key="<your_organization_api_key>",
|
||||
)
|
||||
# or you can load the api_key from SKYVERN_API_KEY in .env
|
||||
# dispatch_task = DispatchTask()
|
||||
|
||||
get_task = GetTask(
|
||||
api_key="<your_organization_api_key>",
|
||||
)
|
||||
# or you can load the api_key from SKYVERN_API_KEY in .env
|
||||
# get_task = GetTask()
|
||||
|
||||
agent = initialize_agent(
|
||||
llm=llm,
|
||||
tools=[
|
||||
dispatch_task,
|
||||
get_task,
|
||||
SleepTool(),
|
||||
],
|
||||
verbose=True,
|
||||
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
# use sleep tool to set up the polling logic until the task is completed, if you only want to dispatch a task, you can remove the sleep tool
|
||||
print(await agent.ainvoke("Run a task with Skyvern. The task is about 'Navigate to the Hacker News homepage and get the top 3 posts.' Then, get this task information until it's completed. The task information re-get interval should be 60s."))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
[project]
|
||||
name = "skyvern-langchain"
|
||||
version = "0.2.1"
|
||||
description = ""
|
||||
authors = [{ name = "lawyzheng", email = "lawy@skyvern.com" }]
|
||||
requires-python = ">=3.11,<3.14"
|
||||
readme = "README.md"
|
||||
|
||||
dependencies = [
|
||||
"skyvern>=0.2.0",
|
||||
"langchain>=1.2.0",
|
||||
"langchain-core>=1.3.3",
|
||||
"urllib3>=2.7.0",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
override-dependencies = [
|
||||
"authlib>=1.6.11",
|
||||
"pyasn1>=0.6.3",
|
||||
"pyjwt>=2.12.0",
|
||||
"fastmcp>=3.2.0",
|
||||
"mcp>=1.23.0",
|
||||
"websockets>=15.0.1",
|
||||
# litellm 1.83.7+ pins these exactly; relax for security upgrade.
|
||||
"jsonschema>=4.23.0",
|
||||
"python-dotenv>=1.2.2",
|
||||
"openai>=2.24.0",
|
||||
# Dependabot moderate security upgrades (transitive)
|
||||
"mako>=1.3.11",
|
||||
"pypdf>=6.10.2",
|
||||
"python-multipart>=0.0.26",
|
||||
"cryptography>=46.0.7",
|
||||
"pygments>=2.20.0",
|
||||
# Dependabot high security upgrades (transitive)
|
||||
"litellm>=1.83.10",
|
||||
"langsmith>=0.8.0",
|
||||
]
|
||||
|
||||
[tool.uv.sources]
|
||||
skyvern = { path = "../.." }
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[dependency-groups]
|
||||
dev = ["twine>=6.1.0,<7"]
|
||||
|
||||
[tool.hatch.build.targets.sdist]
|
||||
include = ["skyvern_langchain"]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
include = ["skyvern_langchain"]
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
from typing import Any, Type
|
||||
|
||||
from langchain.tools import BaseTool
|
||||
from litellm import BaseModel
|
||||
from pydantic import Field
|
||||
from skyvern_langchain.schema import CreateTaskInput, GetTaskInput
|
||||
from skyvern_langchain.settings import settings
|
||||
|
||||
from skyvern import Skyvern
|
||||
from skyvern.client.types.get_run_response import GetRunResponse
|
||||
from skyvern.client.types.task_run_response import TaskRunResponse
|
||||
from skyvern.schemas.runs import RunEngine
|
||||
|
||||
|
||||
class SkyvernTaskBaseTool(BaseTool):
|
||||
engine: RunEngine = Field(default=settings.engine)
|
||||
run_task_timeout_seconds: int = Field(default=settings.run_task_timeout_seconds)
|
||||
agent: Skyvern = Skyvern.local()
|
||||
|
||||
def _run(self, *args: Any, **kwargs: Any) -> None:
|
||||
raise NotImplementedError("skyvern task tool does not support sync")
|
||||
|
||||
|
||||
class RunTask(SkyvernTaskBaseTool):
|
||||
name: str = "run-skyvern-agent-task"
|
||||
description: str = """Use Skyvern agent to run a task. This function won't return until the task is finished."""
|
||||
args_schema: Type[BaseModel] = CreateTaskInput
|
||||
|
||||
async def _arun(self, user_prompt: str, url: str | None = None) -> TaskRunResponse:
|
||||
return await self.agent.run_task(
|
||||
prompt=user_prompt,
|
||||
url=url,
|
||||
engine=self.engine,
|
||||
timeout=self.run_task_timeout_seconds,
|
||||
wait_for_completion=True,
|
||||
)
|
||||
|
||||
|
||||
class DispatchTask(SkyvernTaskBaseTool):
|
||||
name: str = "dispatch-skyvern-agent-task"
|
||||
description: str = """Use Skyvern agent to dispatch a task. This function will return immediately and the task will be running in the background."""
|
||||
args_schema: Type[BaseModel] = CreateTaskInput
|
||||
|
||||
async def _arun(self, user_prompt: str, url: str | None = None) -> TaskRunResponse:
|
||||
return await self.agent.run_task(
|
||||
prompt=user_prompt,
|
||||
url=url,
|
||||
engine=self.engine,
|
||||
timeout=self.run_task_timeout_seconds,
|
||||
wait_for_completion=False,
|
||||
)
|
||||
|
||||
|
||||
class GetTask(SkyvernTaskBaseTool):
|
||||
name: str = "get-skyvern-agent-task"
|
||||
description: str = """Use Skyvern agent to get a task."""
|
||||
args_schema: Type[BaseModel] = GetTaskInput
|
||||
|
||||
async def _arun(self, task_id: str) -> GetRunResponse | None:
|
||||
return await self.agent.get_run(run_id=task_id)
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
from typing import Any, Type
|
||||
|
||||
from langchain.tools import BaseTool
|
||||
from pydantic import BaseModel, Field
|
||||
from skyvern_langchain.schema import CreateTaskInput, GetTaskInput
|
||||
from skyvern_langchain.settings import settings
|
||||
|
||||
from skyvern import Skyvern
|
||||
from skyvern.client import SkyvernEnvironment
|
||||
from skyvern.client.types.get_run_response import GetRunResponse
|
||||
from skyvern.client.types.task_run_response import TaskRunResponse
|
||||
from skyvern.schemas.runs import RunEngine
|
||||
|
||||
|
||||
class SkyvernTaskBaseTool(BaseTool):
|
||||
api_key: str = Field(default=settings.api_key)
|
||||
base_url: str = Field(default=settings.base_url)
|
||||
engine: RunEngine = Field(default=settings.engine)
|
||||
run_task_timeout_seconds: int = Field(default=settings.run_task_timeout_seconds)
|
||||
|
||||
def get_client(self) -> Skyvern:
|
||||
return Skyvern(environment=SkyvernEnvironment.CLOUD, base_url=self.base_url, api_key=self.api_key)
|
||||
|
||||
def _run(self, *args: Any, **kwargs: Any) -> None:
|
||||
raise NotImplementedError("skyvern task tool does not support sync")
|
||||
|
||||
|
||||
class RunTask(SkyvernTaskBaseTool):
|
||||
name: str = "run-skyvern-client-task"
|
||||
description: str = """Use Skyvern client to run a task. This function won't return until the task is finished."""
|
||||
args_schema: Type[BaseModel] = CreateTaskInput
|
||||
|
||||
async def _arun(self, user_prompt: str, url: str | None = None) -> TaskRunResponse:
|
||||
return await self.get_client().run_task(
|
||||
timeout=self.run_task_timeout_seconds,
|
||||
url=url,
|
||||
prompt=user_prompt,
|
||||
engine=self.engine,
|
||||
wait_for_completion=True,
|
||||
)
|
||||
|
||||
|
||||
class DispatchTask(SkyvernTaskBaseTool):
|
||||
name: str = "dispatch-skyvern-client-task"
|
||||
description: str = """Use Skyvern client to dispatch a task. This function will return immediately and the task will be running in the background."""
|
||||
args_schema: Type[BaseModel] = CreateTaskInput
|
||||
|
||||
async def _arun(self, user_prompt: str, url: str | None = None) -> TaskRunResponse:
|
||||
return await self.get_client().run_task(
|
||||
timeout=self.run_task_timeout_seconds,
|
||||
url=url,
|
||||
prompt=user_prompt,
|
||||
engine=self.engine,
|
||||
wait_for_completion=False,
|
||||
)
|
||||
|
||||
|
||||
class GetTask(SkyvernTaskBaseTool):
|
||||
name: str = "get-skyvern-client-task"
|
||||
description: str = """Use Skyvern client to get a task."""
|
||||
args_schema: Type[BaseModel] = GetTaskInput
|
||||
|
||||
async def _arun(self, task_id: str) -> GetRunResponse | None:
|
||||
return await self.get_client().get_run(run_id=task_id)
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class CreateTaskInput(BaseModel):
|
||||
user_prompt: str
|
||||
url: str | None = None
|
||||
|
||||
|
||||
class GetTaskInput(BaseModel):
|
||||
task_id: str
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
from dotenv import load_dotenv
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
from skyvern.schemas.runs import RunEngine
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
api_key: str = ""
|
||||
base_url: str = "https://api.skyvern.com"
|
||||
engine: RunEngine = RunEngine.skyvern_v2
|
||||
run_task_timeout_seconds: int = 60 * 60
|
||||
|
||||
class Config:
|
||||
env_prefix = "SKYVERN_"
|
||||
|
||||
|
||||
load_dotenv()
|
||||
settings = Settings()
|
||||
1453
integrations/langchain/uv.lock
generated
|
|
@ -1,294 +0,0 @@
|
|||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
- [Skyvern LlamaIndex](#skyvern-llamaindex)
|
||||
- [Installation](#installation)
|
||||
- [Basic Usage](#basic-usage)
|
||||
- [Run a task(sync) locally in your local environment](#run-a-tasksync-locally-in-your-local-environment)
|
||||
- [Run a task(async) locally in your local environment](#run-a-taskasync-locally-in-your-local-environment)
|
||||
- [Get a task locally in your local environment](#get-a-task-locally-in-your-local-environment)
|
||||
- [Run a task(sync) by calling skyvern APIs](#run-a-tasksync-by-calling-skyvern-apis)
|
||||
- [Run a task(async) by calling skyvern APIs](#run-a-taskasync-by-calling-skyvern-apis)
|
||||
- [Get a task by calling skyvern APIs](#get-a-task-by-calling-skyvern-apis)
|
||||
- [Advanced Usage](#advanced-usage)
|
||||
- [Dispatch a task(async) locally in your local environment and wait until the task is finished](#dispatch-a-taskasync-locally-in-your-local-environment-and-wait-until-the-task-is-finished)
|
||||
- [Dispatch a task(async) by calling skyvern APIs and wait until the task is finished](#dispatch-a-taskasync-by-calling-skyvern-apis-and-wait-until-the-task-is-finished)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
# Skyvern LlamaIndex
|
||||
|
||||
This is a LlamaIndex integration for Skyvern.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install skyvern-llamaindex
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Run a task(sync) locally in your local environment
|
||||
> sync task won't return until the task is finished.
|
||||
|
||||
:warning: :warning: if you want to run this code block, you need to run `skyvern init` command in your terminal to set up skyvern first.
|
||||
|
||||
|
||||
```python
|
||||
from dotenv import load_dotenv
|
||||
from llama_index.agent.openai import OpenAIAgent
|
||||
from llama_index.llms.openai import OpenAI
|
||||
from skyvern_llamaindex.agent import SkyvernTool
|
||||
|
||||
# load OpenAI API key from .env
|
||||
load_dotenv()
|
||||
|
||||
skyvern_tool = SkyvernTool()
|
||||
|
||||
agent = OpenAIAgent.from_tools(
|
||||
tools=[skyvern_tool.run_task()],
|
||||
llm=OpenAI(model="gpt-4o"),
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
response = agent.chat("Run a task with Skyvern. The task is about 'Navigate to the Hacker News homepage and get the top 3 posts.'")
|
||||
print(response)
|
||||
```
|
||||
|
||||
### Run a task(async) locally in your local environment
|
||||
> async task will return immediately and the task will be running in the background.
|
||||
|
||||
:warning: :warning: if you want to run the task in the background, you need to keep the agent running until the task is finished, otherwise the task will be killed when the agent finished the chat.
|
||||
|
||||
:warning: :warning: if you want to run this code block, you need to run `skyvern init` command in your terminal to set up skyvern first.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from dotenv import load_dotenv
|
||||
from llama_index.agent.openai import OpenAIAgent
|
||||
from llama_index.llms.openai import OpenAI
|
||||
from skyvern_llamaindex.agent import SkyvernTool
|
||||
from llama_index.core.tools import FunctionTool
|
||||
|
||||
# load OpenAI API key from .env
|
||||
load_dotenv()
|
||||
|
||||
async def sleep(seconds: int) -> str:
|
||||
await asyncio.sleep(seconds)
|
||||
return f"Slept for {seconds} seconds"
|
||||
|
||||
# define a sleep tool to keep the agent running until the task is finished
|
||||
sleep_tool = FunctionTool.from_defaults(
|
||||
async_fn=sleep,
|
||||
description="Sleep for a given number of seconds",
|
||||
name="sleep",
|
||||
)
|
||||
|
||||
skyvern_tool = SkyvernTool()
|
||||
|
||||
agent = OpenAIAgent.from_tools(
|
||||
tools=[skyvern_tool.dispatch_task(), sleep_tool],
|
||||
llm=OpenAI(model="gpt-4o"),
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
response = agent.chat("Run a task with Skyvern. The task is about 'Navigate to the Hacker News homepage and get the top 3 posts.' Then, sleep for 10 minutes.")
|
||||
print(response)
|
||||
```
|
||||
|
||||
### Get a task locally in your local environment
|
||||
|
||||
:warning: :warning: if you want to run this code block, you need to run `skyvern init` command in your terminal to set up skyvern first.
|
||||
|
||||
```python
|
||||
from dotenv import load_dotenv
|
||||
from llama_index.agent.openai import OpenAIAgent
|
||||
from llama_index.llms.openai import OpenAI
|
||||
from skyvern_llamaindex.agent import SkyvernTool
|
||||
|
||||
# load OpenAI API key from .env
|
||||
load_dotenv()
|
||||
|
||||
skyvern_tool = SkyvernTool()
|
||||
|
||||
agent = OpenAIAgent.from_tools(
|
||||
tools=[skyvern_tool.get_task()],
|
||||
llm=OpenAI(model="gpt-4o"),
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
response = agent.chat("Get the task information with Skyvern. The task id is '<task_id>'.")
|
||||
print(response)
|
||||
```
|
||||
|
||||
### Run a task(sync) by calling skyvern APIs
|
||||
> sync task won't return until the task is finished.
|
||||
|
||||
no need to run `skyvern init` command in your terminal to set up skyvern before using this integration.
|
||||
|
||||
```python
|
||||
from dotenv import load_dotenv
|
||||
from llama_index.agent.openai import OpenAIAgent
|
||||
from llama_index.llms.openai import OpenAI
|
||||
from skyvern_llamaindex.client import SkyvernTool
|
||||
|
||||
# load OpenAI API key from .env
|
||||
load_dotenv()
|
||||
|
||||
skyvern_tool = SkyvernTool(api_key="<your_organization_api_key>")
|
||||
# or you can load the api_key from SKYVERN_API_KEY in .env
|
||||
# skyvern_tool = SkyvernTool()
|
||||
|
||||
agent = OpenAIAgent.from_tools(
|
||||
tools=[skyvern_tool.run_task()],
|
||||
llm=OpenAI(model="gpt-4o"),
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
response = agent.chat("Run a task with Skyvern. The task is about 'Navigate to the Hacker News homepage and get the top 3 posts.'")
|
||||
print(response)
|
||||
```
|
||||
|
||||
### Run a task(async) by calling skyvern APIs
|
||||
> async task will return immediately and the task will be running in the background.
|
||||
|
||||
no need to run `skyvern init` command in your terminal to set up skyvern before using this integration.
|
||||
|
||||
the task is actually running in the skyvern cloud service, so you don't need to keep your agent running until the task is finished.
|
||||
|
||||
```python
|
||||
from dotenv import load_dotenv
|
||||
from llama_index.agent.openai import OpenAIAgent
|
||||
from llama_index.llms.openai import OpenAI
|
||||
from skyvern_llamaindex.client import SkyvernTool
|
||||
|
||||
# load OpenAI API key from .env
|
||||
load_dotenv()
|
||||
|
||||
skyvern_tool = SkyvernTool(api_key="<your_organization_api_key>")
|
||||
# or you can load the api_key from SKYVERN_API_KEY in .env
|
||||
# skyvern_tool = SkyvernTool()
|
||||
|
||||
agent = OpenAIAgent.from_tools(
|
||||
tools=[skyvern_tool.dispatch_task()],
|
||||
llm=OpenAI(model="gpt-4o"),
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
response = agent.chat("Run a task with Skyvern. The task is about 'Navigate to the Hacker News homepage and get the top 3 posts.'")
|
||||
print(response)
|
||||
```
|
||||
|
||||
|
||||
### Get a task by calling skyvern APIs
|
||||
|
||||
no need to run `skyvern init` command in your terminal to set up skyvern before using this integration.
|
||||
|
||||
```python
|
||||
from dotenv import load_dotenv
|
||||
from llama_index.agent.openai import OpenAIAgent
|
||||
from llama_index.llms.openai import OpenAI
|
||||
from skyvern_llamaindex.client import SkyvernTool
|
||||
|
||||
# load OpenAI API key from .env
|
||||
load_dotenv()
|
||||
|
||||
skyvern_tool = SkyvernTool(api_key="<your_organization_api_key>")
|
||||
# or you can load the api_key from SKYVERN_API_KEY in .env
|
||||
# skyvern_tool = SkyvernTool()
|
||||
|
||||
agent = OpenAIAgent.from_tools(
|
||||
tools=[skyvern_tool.get_task()],
|
||||
llm=OpenAI(model="gpt-4o"),
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
response = agent.chat("Get the task information with Skyvern. The task id is '<task_id>'.")
|
||||
print(response)
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
To provide some examples of how to integrate Skyvern with other llama-index tools in the agent.
|
||||
|
||||
### Dispatch a task(async) locally in your local environment and wait until the task is finished
|
||||
> dispatch task will return immediately and the task will be running in the background. You can use `get_task` tool to poll the task information until the task is finished.
|
||||
|
||||
:warning: :warning: if you want to run this code block, you need to run `skyvern init` command in your terminal to set up skyvern first.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from dotenv import load_dotenv
|
||||
from llama_index.agent.openai import OpenAIAgent
|
||||
from llama_index.llms.openai import OpenAI
|
||||
from llama_index.core.tools import FunctionTool
|
||||
from skyvern_llamaindex.agent import SkyvernTool
|
||||
|
||||
# load OpenAI API key from .env
|
||||
load_dotenv()
|
||||
|
||||
async def sleep(seconds: int) -> str:
|
||||
await asyncio.sleep(seconds)
|
||||
return f"Slept for {seconds} seconds"
|
||||
|
||||
sleep_tool = FunctionTool.from_defaults(
|
||||
async_fn=sleep,
|
||||
description="Sleep for a given number of seconds",
|
||||
name="sleep",
|
||||
)
|
||||
|
||||
skyvern_tool = SkyvernTool()
|
||||
|
||||
agent = OpenAIAgent.from_tools(
|
||||
tools=[skyvern_tool.dispatch_task(), skyvern_tool.get_task(), sleep_tool],
|
||||
llm=OpenAI(model="gpt-4o"),
|
||||
verbose=True,
|
||||
max_function_calls=10,
|
||||
)
|
||||
|
||||
response = agent.chat("Run a task with Skyvern. The task is about 'Navigate to the Hacker News homepage and get the top 3 posts.' Then, get this task information until it's completed. The task information re-get interval should be 60s.")
|
||||
print(response)
|
||||
|
||||
```
|
||||
|
||||
### Dispatch a task(async) by calling skyvern APIs and wait until the task is finished
|
||||
> dispatch task will return immediately and the task will be running in the background. You can use `get_task` tool to poll the task information until the task is finished.
|
||||
|
||||
no need to run `skyvern init` command in your terminal to set up skyvern before using this integration.
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from dotenv import load_dotenv
|
||||
from llama_index.agent.openai import OpenAIAgent
|
||||
from llama_index.llms.openai import OpenAI
|
||||
from llama_index.core.tools import FunctionTool
|
||||
from skyvern_llamaindex.client import SkyvernTool
|
||||
|
||||
# load OpenAI API key from .env
|
||||
load_dotenv()
|
||||
|
||||
async def sleep(seconds: int) -> str:
|
||||
await asyncio.sleep(seconds)
|
||||
return f"Slept for {seconds} seconds"
|
||||
|
||||
sleep_tool = FunctionTool.from_defaults(
|
||||
async_fn=sleep,
|
||||
description="Sleep for a given number of seconds",
|
||||
name="sleep",
|
||||
)
|
||||
|
||||
skyvern_tool = SkyvernTool(api_key="<your_organization_api_key>")
|
||||
# or you can load the api_key from SKYVERN_API_KEY in .env
|
||||
# skyvern_tool = SkyvernTool()
|
||||
|
||||
agent = OpenAIAgent.from_tools(
|
||||
tools=[skyvern_tool.dispatch_task(), skyvern_tool.get_task(), sleep_tool],
|
||||
llm=OpenAI(model="gpt-4o"),
|
||||
verbose=True,
|
||||
max_function_calls=10,
|
||||
)
|
||||
|
||||
response = agent.chat("Run a task with Skyvern. The task is about 'Navigate to the Hacker News homepage and get the top 3 posts.' Then, get this task information until it's completed. The task information re-get interval should be 60s.")
|
||||
print(response)
|
||||
|
||||
```
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
[project]
|
||||
name = "skyvern-llamaindex"
|
||||
version = "0.2.2"
|
||||
description = "Skyvern integration for LlamaIndex"
|
||||
authors = [{ name = "lawyzheng", email = "lawy@skyvern.com" }]
|
||||
requires-python = ">=3.11,<3.14"
|
||||
readme = "README.md"
|
||||
dependencies = [
|
||||
"skyvern>=0.2.0",
|
||||
"llama-index>=0.12.19,<0.14",
|
||||
# Dependabot #645 (GHSA-qccp-gfcp-xxvc / CVE-2026-44431): urllib3 < 2.7.0
|
||||
# forwards sensitive headers across origins on proxied low-level redirects.
|
||||
"urllib3>=2.7.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[dependency-groups]
|
||||
dev = ["twine>=6.1.0,<7"]
|
||||
|
||||
# Security: override vulnerable transitive dependency versions (SKY-8441)
|
||||
# Using override-dependencies because several of these conflict with
|
||||
# skyvern's pinned ranges (e.g. pypdf<6, python-multipart<0.0.19).
|
||||
[tool.uv]
|
||||
override-dependencies = [
|
||||
"authlib>=1.6.11",
|
||||
"pyasn1>=0.6.3",
|
||||
"PyJWT>=2.12.0",
|
||||
"fastmcp>=3.2.0",
|
||||
"mcp>=1.23.0",
|
||||
"pypdf>=6.10.2",
|
||||
"pillow>=12.1.1",
|
||||
"nltk>=3.9.3",
|
||||
"python-multipart>=0.0.26",
|
||||
"starlette>=0.49.1",
|
||||
"google-cloud-aiplatform>=1.133.0",
|
||||
# Cascading overrides needed to unblock the above security constraints:
|
||||
# fastmcp>=3.2.0 requires websockets>=15 (skyvern pins <13)
|
||||
"websockets>=15.0.1",
|
||||
# litellm 1.83.7+ pins openai==2.24.0 (security upgrade); override
|
||||
# llama-index-llms-openai's openai<2 declaration so the integration can
|
||||
# take the patched litellm.
|
||||
"openai>=2.24.0",
|
||||
# litellm 1.83.7+ also pins these exactly.
|
||||
"jsonschema>=4.23.0",
|
||||
"python-dotenv>=1.0.0",
|
||||
# Dependabot moderate security upgrades (transitive)
|
||||
"mako>=1.3.11",
|
||||
"cryptography>=46.0.7",
|
||||
"pygments>=2.20.0",
|
||||
# Dependabot #631 (GHSA-gphh-9q3h-jgpp / CVE-2026-44209): banks <= 2.4.1
|
||||
# renders prompt templates with an unsandboxed Jinja2 environment (SSTI -> RCE).
|
||||
# Pulled in transitively via llama-index-core. Fixed in 2.4.2.
|
||||
"banks>=2.4.2",
|
||||
]
|
||||
|
||||
[tool.uv.sources]
|
||||
skyvern = { path = "../.." }
|
||||
|
||||
[tool.hatch.build.targets.sdist]
|
||||
include = ["skyvern_llamaindex"]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
include = ["skyvern_llamaindex"]
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
from typing import Any, List
|
||||
|
||||
from llama_index.core.tools import FunctionTool
|
||||
from llama_index.core.tools.tool_spec.base import SPEC_FUNCTION_TYPE, BaseToolSpec
|
||||
from skyvern_llamaindex.settings import settings
|
||||
|
||||
from skyvern import Skyvern
|
||||
from skyvern.client.types.get_run_response import GetRunResponse
|
||||
from skyvern.client.types.task_run_response import TaskRunResponse
|
||||
from skyvern.schemas.runs import RunEngine
|
||||
|
||||
|
||||
class SkyvernTool:
|
||||
def __init__(self, agent: Skyvern | None = None):
|
||||
if agent is None:
|
||||
agent = Skyvern.local()
|
||||
self.agent = agent
|
||||
|
||||
def run_task(self) -> FunctionTool:
|
||||
task_tool_spec = SkyvernTaskToolSpec(agent=self.agent)
|
||||
return task_tool_spec.to_tool_list(["run_task"])[0]
|
||||
|
||||
def dispatch_task(self) -> FunctionTool:
|
||||
task_tool_spec = SkyvernTaskToolSpec(agent=self.agent)
|
||||
return task_tool_spec.to_tool_list(["dispatch_task"])[0]
|
||||
|
||||
def get_task(self) -> FunctionTool:
|
||||
task_tool_spec = SkyvernTaskToolSpec(agent=self.agent)
|
||||
return task_tool_spec.to_tool_list(["get_task"])[0]
|
||||
|
||||
|
||||
class SkyvernTaskToolSpec(BaseToolSpec):
|
||||
spec_functions: List[SPEC_FUNCTION_TYPE] = [
|
||||
"run_task",
|
||||
"dispatch_task",
|
||||
"get_task",
|
||||
]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
agent: Skyvern | None = None,
|
||||
engine: RunEngine = settings.engine,
|
||||
run_task_timeout_seconds: int = settings.run_task_timeout_seconds,
|
||||
) -> None:
|
||||
if agent is None:
|
||||
agent = Skyvern.local()
|
||||
self.agent = agent
|
||||
self.engine = engine
|
||||
self.run_task_timeout_seconds = run_task_timeout_seconds
|
||||
|
||||
async def run_task(
|
||||
self,
|
||||
user_prompt: str | None = None,
|
||||
url: str | None = None,
|
||||
*_: Any,
|
||||
**kw: Any,
|
||||
) -> TaskRunResponse:
|
||||
"""
|
||||
Use Skyvern agent to run a task. This function won't return until the task is finished.
|
||||
|
||||
Args:
|
||||
user_prompt[str]: The user's prompt describing the task.
|
||||
url (Optional[str]): The URL of the target website for the task.
|
||||
"""
|
||||
if user_prompt is None and kw.get("args"):
|
||||
user_prompt = kw["args"][0]
|
||||
|
||||
if url is None:
|
||||
if kw.get("args") and len(kw["args"]) > 1:
|
||||
url = kw["args"][1]
|
||||
elif kw.get("kwargs"):
|
||||
url = kw["kwargs"].get("url")
|
||||
|
||||
assert user_prompt is not None, "user_prompt is required"
|
||||
|
||||
return await self.agent.run_task(
|
||||
prompt=user_prompt,
|
||||
url=url,
|
||||
engine=self.engine,
|
||||
timeout=self.run_task_timeout_seconds,
|
||||
wait_for_completion=True,
|
||||
)
|
||||
|
||||
async def dispatch_task(
|
||||
self,
|
||||
user_prompt: str | None = None,
|
||||
url: str | None = None,
|
||||
*_: Any,
|
||||
**kw: Any,
|
||||
) -> TaskRunResponse:
|
||||
"""
|
||||
Use Skyvern agent to dispatch a task. This function will return immediately and the task will be running in the background.
|
||||
|
||||
Args:
|
||||
user_prompt[str]: The user's prompt describing the task.
|
||||
url (Optional[str]): The URL of the target website for the task.
|
||||
"""
|
||||
if user_prompt is None and kw.get("args"):
|
||||
user_prompt = kw["args"][0]
|
||||
|
||||
if url is None:
|
||||
if kw.get("args") and len(kw["args"]) > 1:
|
||||
url = kw["args"][1]
|
||||
elif kw.get("kwargs"):
|
||||
url = kw["kwargs"].get("url")
|
||||
|
||||
assert user_prompt is not None, "user_prompt is required"
|
||||
|
||||
return await self.agent.run_task(
|
||||
prompt=user_prompt,
|
||||
url=url,
|
||||
engine=self.engine,
|
||||
timeout=self.run_task_timeout_seconds,
|
||||
wait_for_completion=False,
|
||||
)
|
||||
|
||||
async def get_task(self, task_id: str | None = None, *_: Any, **kwargs: Any) -> GetRunResponse | None:
|
||||
"""
|
||||
Use Skyvern agent to get a task.
|
||||
|
||||
Args:
|
||||
task_id[str]: The id of the task.
|
||||
"""
|
||||
if task_id is None and "args" in kwargs:
|
||||
task_id = kwargs["args"][0]
|
||||
|
||||
assert task_id is not None, "task_id is required"
|
||||
return await self.agent.get_run(run_id=task_id)
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
from typing import Any, List
|
||||
|
||||
from llama_index.core.tools import FunctionTool
|
||||
from llama_index.core.tools.tool_spec.base import SPEC_FUNCTION_TYPE, BaseToolSpec
|
||||
from pydantic import BaseModel
|
||||
from skyvern_llamaindex.settings import settings
|
||||
|
||||
from skyvern import Skyvern
|
||||
from skyvern.client import SkyvernEnvironment
|
||||
from skyvern.client.types.get_run_response import GetRunResponse
|
||||
from skyvern.client.types.task_run_response import TaskRunResponse
|
||||
from skyvern.schemas.runs import RunEngine
|
||||
|
||||
|
||||
class SkyvernTool(BaseModel):
|
||||
api_key: str = settings.api_key
|
||||
base_url: str = settings.base_url
|
||||
|
||||
def run_task(self) -> FunctionTool:
|
||||
task_tool_spec = SkyvernTaskToolSpec(
|
||||
api_key=self.api_key,
|
||||
base_url=self.base_url,
|
||||
)
|
||||
|
||||
return task_tool_spec.to_tool_list(["run_task"])[0]
|
||||
|
||||
def dispatch_task(self) -> FunctionTool:
|
||||
task_tool_spec = SkyvernTaskToolSpec(
|
||||
api_key=self.api_key,
|
||||
base_url=self.base_url,
|
||||
)
|
||||
|
||||
return task_tool_spec.to_tool_list(["dispatch_task"])[0]
|
||||
|
||||
def get_task(self) -> FunctionTool:
|
||||
task_tool_spec = SkyvernTaskToolSpec(
|
||||
api_key=self.api_key,
|
||||
base_url=self.base_url,
|
||||
)
|
||||
|
||||
return task_tool_spec.to_tool_list(["get_task"])[0]
|
||||
|
||||
|
||||
class SkyvernTaskToolSpec(BaseToolSpec):
|
||||
spec_functions: List[SPEC_FUNCTION_TYPE] = [
|
||||
"run_task",
|
||||
"dispatch_task",
|
||||
"get_task",
|
||||
]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
api_key: str = settings.api_key,
|
||||
base_url: str = settings.base_url,
|
||||
engine: RunEngine = settings.engine,
|
||||
run_task_timeout_seconds: int = settings.run_task_timeout_seconds,
|
||||
):
|
||||
self.engine = engine
|
||||
self.run_task_timeout_seconds = run_task_timeout_seconds
|
||||
self.client = Skyvern(environment=SkyvernEnvironment.CLOUD, base_url=base_url, api_key=api_key)
|
||||
|
||||
async def run_task(
|
||||
self,
|
||||
user_prompt: str | None = None,
|
||||
url: str | None = None,
|
||||
*_: Any,
|
||||
**kw: Any,
|
||||
) -> TaskRunResponse:
|
||||
"""
|
||||
Use Skyvern client to run a task. This function won't return until the task is finished.
|
||||
|
||||
Args:
|
||||
user_prompt[str]: The user's prompt describing the task.
|
||||
url (Optional[str]): The URL of the target website for the task.
|
||||
"""
|
||||
if user_prompt is None and kw.get("args"):
|
||||
user_prompt = kw["args"][0]
|
||||
|
||||
if url is None:
|
||||
if kw.get("args") and len(kw["args"]) > 1:
|
||||
url = kw["args"][1]
|
||||
elif kw.get("kwargs"):
|
||||
url = kw["kwargs"].get("url")
|
||||
|
||||
assert user_prompt is not None, "user_prompt is required"
|
||||
|
||||
return await self.client.run_task(
|
||||
prompt=user_prompt,
|
||||
url=url,
|
||||
engine=self.engine,
|
||||
timeout=self.run_task_timeout_seconds,
|
||||
wait_for_completion=True,
|
||||
)
|
||||
|
||||
async def dispatch_task(
|
||||
self,
|
||||
user_prompt: str | None = None,
|
||||
url: str | None = None,
|
||||
*_: Any,
|
||||
**kw: Any,
|
||||
) -> TaskRunResponse:
|
||||
"""
|
||||
Use Skyvern client to dispatch a task. This function will return immediately and the task will be running in the background.
|
||||
|
||||
Args:
|
||||
user_prompt[str]: The user's prompt describing the task.
|
||||
url (Optional[str]): The URL of the target website for the task.
|
||||
"""
|
||||
if user_prompt is None and kw.get("args"):
|
||||
user_prompt = kw["args"][0]
|
||||
|
||||
if url is None:
|
||||
if kw.get("args") and len(kw["args"]) > 1:
|
||||
url = kw["args"][1]
|
||||
elif kw.get("kwargs"):
|
||||
url = kw["kwargs"].get("url")
|
||||
|
||||
assert user_prompt is not None, "user_prompt is required"
|
||||
return await self.client.run_task(
|
||||
prompt=user_prompt,
|
||||
url=url,
|
||||
engine=self.engine,
|
||||
timeout=self.run_task_timeout_seconds,
|
||||
wait_for_completion=False,
|
||||
)
|
||||
|
||||
async def get_task(self, task_id: str | None = None, *_: Any, **kwargs: Any) -> GetRunResponse | None:
|
||||
"""
|
||||
Use Skyvern client to get a task.
|
||||
|
||||
Args:
|
||||
task_id[str]: The id of the task.
|
||||
"""
|
||||
if task_id is None and "args" in kwargs:
|
||||
task_id = kwargs["args"][0]
|
||||
|
||||
assert task_id is not None, "task_id is required"
|
||||
return await self.client.get_run(run_id=task_id)
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
from dotenv import load_dotenv
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
from skyvern.schemas.runs import RunEngine
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
api_key: str = ""
|
||||
base_url: str = "https://api.skyvern.com"
|
||||
engine: RunEngine = RunEngine.skyvern_v2
|
||||
run_task_timeout_seconds: int = 60 * 60
|
||||
|
||||
class Config:
|
||||
env_prefix = "SKYVERN_"
|
||||
|
||||
|
||||
load_dotenv()
|
||||
settings = Settings()
|
||||
2586
integrations/llama_index/uv.lock
generated
10
k8s/charts/skyvern-ui/.helmignore
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Patterns to ignore when building packages.
|
||||
.DS_Store
|
||||
.git/
|
||||
.gitignore
|
||||
*.tmproj
|
||||
*.tmp
|
||||
*.bak
|
||||
*.orig
|
||||
.idea/
|
||||
.vscode/
|
||||
14
k8s/charts/skyvern-ui/Chart.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
apiVersion: v2
|
||||
name: skyvern-ui
|
||||
description: Skyvern UI — prebuilt frontend bundle served with runtime env injection
|
||||
type: application
|
||||
# Chart version — bump on chart changes.
|
||||
version: 0.1.0
|
||||
# Default Skyvern UI image version this chart targets.
|
||||
appVersion: "v1.0.42"
|
||||
home: https://www.skyvern.com
|
||||
sources:
|
||||
- https://github.com/Skyvern-AI/skyvern
|
||||
maintainers:
|
||||
- name: Skyvern
|
||||
url: https://www.skyvern.com
|
||||
28
k8s/charts/skyvern-ui/templates/NOTES.txt
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
Skyvern UI ({{ .Values.image.repository }}:{{ .Values.image.tag }}) has been deployed.
|
||||
|
||||
IMPORTANT — do NOT override the container command.
|
||||
This chart deliberately runs the image's own entrypoint, which injects the
|
||||
VITE_* runtime config into the prebuilt bundle and serves it. Adding a
|
||||
`command:`/`args:` such as ["npm","run","start"] forces a runtime build that
|
||||
the production image cannot perform and will crashloop ("tsc: not found").
|
||||
|
||||
Access the UI:
|
||||
{{- if .Values.ingress.enabled }}
|
||||
http(s)://{{ (index .Values.ingress.hosts 0).host }}
|
||||
{{- else if eq .Values.service.type "ClusterIP" }}
|
||||
kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "skyvern-ui.fullname" . }} 8080:{{ .Values.service.port }}
|
||||
then open http://localhost:8080
|
||||
{{- else }}
|
||||
Service type {{ .Values.service.type }} — resolve the external address with:
|
||||
kubectl --namespace {{ .Release.Namespace }} get svc {{ include "skyvern-ui.fullname" . }}
|
||||
{{- end }}
|
||||
|
||||
Backend wiring (set in values.yaml -> config):
|
||||
VITE_API_BASE_URL = {{ .Values.config.apiBaseUrl }}
|
||||
VITE_WSS_BASE_URL = {{ .Values.config.wssBaseUrl }}
|
||||
VITE_ARTIFACT_API_BASE_URL = {{ .Values.config.artifactApiBaseUrl }}
|
||||
{{- if and (not .Values.apiKey.value) (not .Values.apiKey.existingSecret) }}
|
||||
|
||||
WARNING: no API key configured (apiKey.value / apiKey.existingSecret). The UI
|
||||
will start but cannot authenticate to the backend until one is provided.
|
||||
{{- end }}
|
||||
48
k8s/charts/skyvern-ui/templates/_helpers.tpl
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{{/* Expand the name of the chart. */}}
|
||||
{{- define "skyvern-ui.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/* Create a default fully qualified app name. */}}
|
||||
{{- define "skyvern-ui.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/* Chart name and version as used by the chart label. */}}
|
||||
{{- define "skyvern-ui.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/* Common labels */}}
|
||||
{{- define "skyvern-ui.labels" -}}
|
||||
helm.sh/chart: {{ include "skyvern-ui.chart" . }}
|
||||
{{ include "skyvern-ui.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/* Selector labels */}}
|
||||
{{- define "skyvern-ui.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "skyvern-ui.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/* Name of the Secret holding the API key (chart-managed or external). */}}
|
||||
{{- define "skyvern-ui.apiKeySecretName" -}}
|
||||
{{- if .Values.apiKey.existingSecret }}
|
||||
{{- .Values.apiKey.existingSecret }}
|
||||
{{- else }}
|
||||
{{- include "skyvern-ui.fullname" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
14
k8s/charts/skyvern-ui/templates/configmap.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "skyvern-ui.fullname" . }}
|
||||
labels:
|
||||
{{- include "skyvern-ui.labels" . | nindent 4 }}
|
||||
data:
|
||||
VITE_API_BASE_URL: {{ .Values.config.apiBaseUrl | quote }}
|
||||
VITE_WSS_BASE_URL: {{ .Values.config.wssBaseUrl | quote }}
|
||||
VITE_ARTIFACT_API_BASE_URL: {{ .Values.config.artifactApiBaseUrl | quote }}
|
||||
VITE_BROWSER_STREAMING_MODE: {{ .Values.config.browserStreamingMode | quote }}
|
||||
VITE_ENABLE_CODE_BLOCK: {{ .Values.config.enableCodeBlock | quote }}
|
||||
VITE_ENABLE_LOG_ARTIFACTS: {{ .Values.config.enableLogArtifacts | quote }}
|
||||
VITE_ENABLE_2FA_NOTIFICATIONS: {{ .Values.config.enable2faNotifications | quote }}
|
||||