SDK: use Skyvern.local() factory method (#4206)
This commit is contained in:
committed by
GitHub
parent
32fb2315f0
commit
e1693b2fef
@@ -50,7 +50,7 @@ You can also run browser tasks locally with Python code, with a little bit of se
|
|||||||
from skyvern import Skyvern
|
from skyvern import Skyvern
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
skyvern = Skyvern()
|
skyvern = Skyvern(api_key="YOUR_LOCAL_API_KEY")
|
||||||
|
|
||||||
asyncio.run(skyvern.run_task(prompt="Find the top post on hackernews today"))
|
asyncio.run(skyvern.run_task(prompt="Find the top post on hackernews today"))
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ Laminar.initialize(disabled_instruments=set([Instruments.OPENAI]))
|
|||||||
# Configure LiteLLM to trace all LLM calls made by Skyvern
|
# Configure LiteLLM to trace all LLM calls made by Skyvern
|
||||||
litellm.callbacks = [LaminarLiteLLMCallback()]
|
litellm.callbacks = [LaminarLiteLLMCallback()]
|
||||||
|
|
||||||
skyvern = Skyvern()
|
skyvern = Skyvern(api_key="YOUR_API_KEY")
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
task = await skyvern.run_task(
|
task = await skyvern.run_task(
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ For example, if you want to get the title, URL, and points of the top post on Ha
|
|||||||
```python
|
```python
|
||||||
from skyvern import Skyvern
|
from skyvern import Skyvern
|
||||||
|
|
||||||
skyvern = Skyvern()
|
skyvern = Skyvern(api_key="YOUR_API_KEY")
|
||||||
task = await skyvern.run_task(
|
task = await skyvern.run_task(
|
||||||
prompt="Find the top post on hackernews today",
|
prompt="Find the top post on hackernews today",
|
||||||
data_extraction_schema={
|
data_extraction_schema={
|
||||||
@@ -159,7 +159,7 @@ When you are sending a run task request the Skyvern service, you can set the `wa
|
|||||||
```python
|
```python
|
||||||
from skyvern import Skyvern
|
from skyvern import Skyvern
|
||||||
|
|
||||||
skyvern = Skyvern()
|
skyvern = Skyvern(api_key="YOUR_API_KEY")
|
||||||
task = await skyvern.run_task(
|
task = await skyvern.run_task(
|
||||||
prompt="Find the top post on hackernews today",
|
prompt="Find the top post on hackernews today",
|
||||||
# the request will be hanging until the task is done
|
# the request will be hanging until the task is done
|
||||||
@@ -173,7 +173,7 @@ Instead of waiting, you can also set the `webhook_url` in the run task request a
|
|||||||
```python
|
```python
|
||||||
from skyvern import Skyvern
|
from skyvern import Skyvern
|
||||||
|
|
||||||
skyvern = Skyvern()
|
skyvern = Skyvern(api_key="YOUR_API_KEY")
|
||||||
task = await skyvern.run_task(
|
task = await skyvern.run_task(
|
||||||
prompt="Find the top post on hackernews today",
|
prompt="Find the top post on hackernews today",
|
||||||
webhook_url="https://your-webhook-url.com",
|
webhook_url="https://your-webhook-url.com",
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from skyvern.schemas.runs import RunEngine
|
|||||||
class SkyvernTaskBaseTool(BaseTool):
|
class SkyvernTaskBaseTool(BaseTool):
|
||||||
engine: RunEngine = Field(default=settings.engine)
|
engine: RunEngine = Field(default=settings.engine)
|
||||||
run_task_timeout_seconds: int = Field(default=settings.run_task_timeout_seconds)
|
run_task_timeout_seconds: int = Field(default=settings.run_task_timeout_seconds)
|
||||||
agent: Skyvern = Skyvern()
|
agent: Skyvern = Skyvern.local()
|
||||||
|
|
||||||
def _run(self, *args: Any, **kwargs: Any) -> None:
|
def _run(self, *args: Any, **kwargs: Any) -> None:
|
||||||
raise NotImplementedError("skyvern task tool does not support sync")
|
raise NotImplementedError("skyvern task tool does not support sync")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from skyvern.schemas.runs import RunEngine
|
|||||||
class SkyvernTool:
|
class SkyvernTool:
|
||||||
def __init__(self, agent: Skyvern | None = None):
|
def __init__(self, agent: Skyvern | None = None):
|
||||||
if agent is None:
|
if agent is None:
|
||||||
agent = Skyvern()
|
agent = Skyvern.local()
|
||||||
self.agent = agent
|
self.agent = agent
|
||||||
|
|
||||||
def run_task(self) -> FunctionTool:
|
def run_task(self) -> FunctionTool:
|
||||||
@@ -44,7 +44,7 @@ class SkyvernTaskToolSpec(BaseToolSpec):
|
|||||||
run_task_timeout_seconds: int = settings.run_task_timeout_seconds,
|
run_task_timeout_seconds: int = settings.run_task_timeout_seconds,
|
||||||
) -> None:
|
) -> None:
|
||||||
if agent is None:
|
if agent is None:
|
||||||
agent = Skyvern()
|
agent = Skyvern.local()
|
||||||
self.agent = agent
|
self.agent = agent
|
||||||
self.engine = engine
|
self.engine = engine
|
||||||
self.run_task_timeout_seconds = run_task_timeout_seconds
|
self.run_task_timeout_seconds = run_task_timeout_seconds
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import asyncio
|
|||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import tempfile
|
import tempfile
|
||||||
from typing import Any, overload
|
from typing import Any
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
import structlog
|
import structlog
|
||||||
@@ -15,7 +15,6 @@ from skyvern.client.types.task_run_response import TaskRunResponse
|
|||||||
from skyvern.client.types.workflow_run_response import WorkflowRunResponse
|
from skyvern.client.types.workflow_run_response import WorkflowRunResponse
|
||||||
from skyvern.forge.sdk.api.llm.models import LLMConfig, LLMRouterConfig
|
from skyvern.forge.sdk.api.llm.models import LLMConfig, LLMRouterConfig
|
||||||
from skyvern.library.constants import DEFAULT_AGENT_HEARTBEAT_INTERVAL, DEFAULT_AGENT_TIMEOUT, DEFAULT_CDP_PORT
|
from skyvern.library.constants import DEFAULT_AGENT_HEARTBEAT_INTERVAL, DEFAULT_AGENT_TIMEOUT, DEFAULT_CDP_PORT
|
||||||
from skyvern.library.embedded_server_factory import create_embedded_server
|
|
||||||
from skyvern.library.skyvern_browser import SkyvernBrowser
|
from skyvern.library.skyvern_browser import SkyvernBrowser
|
||||||
from skyvern.schemas.run_blocks import CredentialType
|
from skyvern.schemas.run_blocks import CredentialType
|
||||||
from skyvern.schemas.runs import ProxyLocation, RunEngine, RunStatus
|
from skyvern.schemas.runs import ProxyLocation, RunEngine, RunStatus
|
||||||
@@ -33,13 +32,13 @@ class Skyvern(AsyncSkyvern):
|
|||||||
Example:
|
Example:
|
||||||
```python
|
```python
|
||||||
|
|
||||||
# Initialize with remote environment and API key
|
# Remote mode: Connect to Skyvern Cloud (API key required)
|
||||||
skyvern = Skyvern(environment=SkyvernEnvironment.CLOUD, api_key="your-api-key")
|
skyvern = Skyvern(api_key="your-api-key")
|
||||||
|
|
||||||
# Or in embedded mode (run `skyvern quickstart` first):
|
# Local/embedded mode (run `skyvern quickstart` first):
|
||||||
skyvern = Skyvern()
|
skyvern = Skyvern.local()
|
||||||
|
|
||||||
# Launch a local browser
|
# Launch a local browser (works only in local environment)
|
||||||
browser = await skyvern.launch_local_browser(headless=False)
|
browser = await skyvern.launch_local_browser(headless=False)
|
||||||
page = await browser.get_working_page()
|
page = await browser.get_working_page()
|
||||||
|
|
||||||
@@ -81,12 +80,11 @@ class Skyvern(AsyncSkyvern):
|
|||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@overload
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
environment: SkyvernEnvironment,
|
|
||||||
api_key: str,
|
api_key: str,
|
||||||
|
environment: SkyvernEnvironment = SkyvernEnvironment.CLOUD,
|
||||||
base_url: str | None = None,
|
base_url: str | None = None,
|
||||||
timeout: float | None = None,
|
timeout: float | None = None,
|
||||||
follow_redirects: bool | None = True,
|
follow_redirects: bool | None = True,
|
||||||
@@ -95,11 +93,11 @@ class Skyvern(AsyncSkyvern):
|
|||||||
"""Remote mode: Connect to Skyvern Cloud or self-hosted instance.
|
"""Remote mode: Connect to Skyvern Cloud or self-hosted instance.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
environment: The Skyvern environment to connect to. Use SkyvernEnvironment.CLOUD
|
|
||||||
for Skyvern Cloud or SkyvernEnvironment.PRODUCTION/STAGING for self-hosted
|
|
||||||
instances.
|
|
||||||
api_key: API key for authenticating with Skyvern.
|
api_key: API key for authenticating with Skyvern.
|
||||||
Can be found on the settings page: https://app.skyvern.com/settings
|
Can be found on the settings page: https://app.skyvern.com/settings
|
||||||
|
environment: The Skyvern environment to connect to. Use SkyvernEnvironment.CLOUD
|
||||||
|
for Skyvern Cloud or SkyvernEnvironment.PRODUCTION/STAGING for self-hosted
|
||||||
|
instances. Defaults to SkyvernEnvironment.CLOUD.
|
||||||
base_url: Override the base URL for the Skyvern API. If not provided, uses the default URL for
|
base_url: Override the base URL for the Skyvern API. If not provided, uses the default URL for
|
||||||
the specified environment.
|
the specified environment.
|
||||||
timeout: Timeout in seconds for API requests. If not provided, uses the default timeout.
|
timeout: Timeout in seconds for API requests. If not provided, uses the default timeout.
|
||||||
@@ -107,102 +105,6 @@ class Skyvern(AsyncSkyvern):
|
|||||||
httpx_client: Custom httpx AsyncClient for making API requests.
|
httpx_client: Custom httpx AsyncClient for making API requests.
|
||||||
If not provided, a default client will be created.
|
If not provided, a default client will be created.
|
||||||
"""
|
"""
|
||||||
...
|
|
||||||
|
|
||||||
@overload
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
*,
|
|
||||||
llm_config: LLMRouterConfig | LLMConfig | None = None,
|
|
||||||
settings: dict[str, Any] | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""Embedded mode: Run Skyvern locally in-process.
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
Run `skyvern quickstart` first to set up your local environment and create a .env file.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
llm_config: Optional custom LLM configuration (LLMConfig or LLMRouterConfig).
|
|
||||||
If provided, this will be registered as "CUSTOM_LLM" and used as the primary LLM,
|
|
||||||
overriding the LLM_KEY setting from your .env file.
|
|
||||||
If not provided, uses the LLM configured via LLM_KEY in your .env file.
|
|
||||||
|
|
||||||
Example 1 - Using environment variables (recommended):
|
|
||||||
```python
|
|
||||||
from skyvern import Skyvern
|
|
||||||
from skyvern.forge.sdk.api.llm.models import LLMConfig
|
|
||||||
|
|
||||||
# Assumes OPENAI_API_KEY is set in your environment
|
|
||||||
llm_config = LLMConfig(
|
|
||||||
model_name="gpt-4o",
|
|
||||||
required_env_vars=["OPENAI_API_KEY"],
|
|
||||||
supports_vision=True,
|
|
||||||
add_assistant_prefix=False,
|
|
||||||
)
|
|
||||||
skyvern = Skyvern(llm_config=llm_config)
|
|
||||||
```
|
|
||||||
|
|
||||||
Example 2 - Explicitly providing credentials:
|
|
||||||
```python
|
|
||||||
from skyvern import Skyvern
|
|
||||||
from skyvern.forge.sdk.api.llm.models import LLMConfig, LiteLLMParams
|
|
||||||
|
|
||||||
llm_config = LLMConfig(
|
|
||||||
model_name="gpt-4o",
|
|
||||||
required_env_vars=[], # No env vars required
|
|
||||||
supports_vision=True,
|
|
||||||
add_assistant_prefix=False,
|
|
||||||
litellm_params=LiteLLMParams(
|
|
||||||
api_base="https://api.openai.com/v1",
|
|
||||||
api_key="sk-...", # Your API key
|
|
||||||
),
|
|
||||||
)
|
|
||||||
skyvern = Skyvern(llm_config=llm_config)
|
|
||||||
```
|
|
||||||
settings: Optional dictionary of Skyvern settings to override.
|
|
||||||
These override the corresponding settings from your .env file.
|
|
||||||
Example: {"MAX_STEPS_PER_RUN": 100, "BROWSER_TYPE": "chromium-headful"}
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
*,
|
|
||||||
environment: SkyvernEnvironment | None = None,
|
|
||||||
base_url: str | None = None,
|
|
||||||
api_key: str | None = None,
|
|
||||||
timeout: float | None = None,
|
|
||||||
follow_redirects: bool | None = True,
|
|
||||||
httpx_client: httpx.AsyncClient | None = None,
|
|
||||||
llm_config: LLMRouterConfig | LLMConfig | None = None,
|
|
||||||
settings: dict[str, Any] | None = None,
|
|
||||||
):
|
|
||||||
if environment is None:
|
|
||||||
if httpx_client is not None:
|
|
||||||
raise ValueError("httpx_client is not supported in embedded mode")
|
|
||||||
|
|
||||||
if not os.path.exists(".env"):
|
|
||||||
raise ValueError("Please run `skyvern quickstart` to set up your local Skyvern environment")
|
|
||||||
|
|
||||||
load_dotenv(".env")
|
|
||||||
api_key = os.getenv("SKYVERN_API_KEY")
|
|
||||||
if not api_key:
|
|
||||||
raise ValueError("SKYVERN_API_KEY is not set. Provide api_key or set SKYVERN_API_KEY in .env file.")
|
|
||||||
|
|
||||||
super().__init__(
|
|
||||||
environment=SkyvernEnvironment.LOCAL,
|
|
||||||
api_key=api_key,
|
|
||||||
timeout=timeout,
|
|
||||||
follow_redirects=follow_redirects,
|
|
||||||
httpx_client=create_embedded_server(
|
|
||||||
llm_config=llm_config,
|
|
||||||
settings_overrides=settings,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
if not api_key:
|
|
||||||
raise ValueError(f"Missing api_key for {environment.name}")
|
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
base_url=base_url,
|
base_url=base_url,
|
||||||
environment=environment,
|
environment=environment,
|
||||||
@@ -213,10 +115,104 @@ class Skyvern(AsyncSkyvern):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self._environment = environment
|
self._environment = environment
|
||||||
self._api_key = api_key
|
self._api_key: str | None = api_key
|
||||||
|
|
||||||
self._playwright: Playwright | None = None
|
self._playwright: Playwright | None = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def local(
|
||||||
|
cls,
|
||||||
|
*,
|
||||||
|
llm_config: LLMRouterConfig | LLMConfig | None = None,
|
||||||
|
settings: dict[str, Any] | None = None,
|
||||||
|
) -> "Skyvern":
|
||||||
|
"""Local/embedded mode: Run Skyvern locally in-process.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
Run `skyvern quickstart` first to set up your local environment and create a .env file
|
||||||
|
|
||||||
|
Args:
|
||||||
|
llm_config: Optional custom LLM configuration (LLMConfig or LLMRouterConfig).
|
||||||
|
If provided, this will be registered as "CUSTOM_LLM" and used as the primary LLM,
|
||||||
|
overriding the LLM_KEY setting from your .env file.
|
||||||
|
If not provided, uses the LLM configured via LLM_KEY in your .env file.
|
||||||
|
|
||||||
|
Example 1 - Using .env configuration (simplest, recommended):
|
||||||
|
```python
|
||||||
|
from skyvern import Skyvern
|
||||||
|
|
||||||
|
# Uses LLM_KEY and other settings from your .env file
|
||||||
|
# Created by running `skyvern quickstart`
|
||||||
|
skyvern = Skyvern.local()
|
||||||
|
```
|
||||||
|
|
||||||
|
Example 2 - Custom LLM with environment variables:
|
||||||
|
```python
|
||||||
|
from skyvern import Skyvern
|
||||||
|
from skyvern.forge.sdk.api.llm.models import LLMConfig
|
||||||
|
|
||||||
|
# Assumes OPENAI_API_KEY is set in your environment
|
||||||
|
skyvern = Skyvern.local(
|
||||||
|
llm_config=LLMConfig(
|
||||||
|
model_name="gpt-4o",
|
||||||
|
required_env_vars=["OPENAI_API_KEY"],
|
||||||
|
supports_vision=True,
|
||||||
|
add_assistant_prefix=False,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Example 3 - Explicitly providing credentials:
|
||||||
|
```python
|
||||||
|
from skyvern import Skyvern
|
||||||
|
from skyvern.forge.sdk.api.llm.models import LLMConfig, LiteLLMParams
|
||||||
|
|
||||||
|
skyvern = Skyvern.local(
|
||||||
|
llm_config=LLMConfig(
|
||||||
|
model_name="gpt-4o",
|
||||||
|
required_env_vars=[], # No env vars required
|
||||||
|
supports_vision=True,
|
||||||
|
add_assistant_prefix=False,
|
||||||
|
litellm_params=LiteLLMParams(
|
||||||
|
api_base="https://api.openai.com/v1",
|
||||||
|
api_key="sk-...", # Your API key
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
settings: Optional dictionary of Skyvern settings to override.
|
||||||
|
These override the corresponding settings from your .env file.
|
||||||
|
Example: {"MAX_STEPS_PER_RUN": 100, "BROWSER_TYPE": "chromium-headful"}
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Skyvern: A Skyvern instance running in local/embedded mode.
|
||||||
|
"""
|
||||||
|
from skyvern.library.embedded_server_factory import create_embedded_server # noqa: PLC0415
|
||||||
|
|
||||||
|
if not os.path.exists(".env"):
|
||||||
|
raise ValueError("Please run `skyvern quickstart` to set up your local Skyvern environment")
|
||||||
|
|
||||||
|
load_dotenv(".env")
|
||||||
|
api_key = os.getenv("SKYVERN_API_KEY")
|
||||||
|
if not api_key:
|
||||||
|
raise ValueError("SKYVERN_API_KEY is not set. Provide api_key or set SKYVERN_API_KEY in .env file.")
|
||||||
|
|
||||||
|
obj = cls.__new__(cls)
|
||||||
|
|
||||||
|
AsyncSkyvern.__init__(
|
||||||
|
obj,
|
||||||
|
environment=SkyvernEnvironment.LOCAL,
|
||||||
|
httpx_client=create_embedded_server(
|
||||||
|
llm_config=llm_config,
|
||||||
|
settings_overrides=settings,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
obj._environment = SkyvernEnvironment.LOCAL
|
||||||
|
obj._api_key = None
|
||||||
|
obj._playwright = None
|
||||||
|
|
||||||
|
return obj
|
||||||
|
|
||||||
async def run_task(
|
async def run_task(
|
||||||
self,
|
self,
|
||||||
prompt: str,
|
prompt: str,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class SkyvernBrowser(BrowserContext):
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
```python
|
```python
|
||||||
skyvern = Skyvern()
|
skyvern = Skyvern.local()
|
||||||
browser = await skyvern.launch_local_browser()
|
browser = await skyvern.launch_local_browser()
|
||||||
|
|
||||||
# Get or create the working page
|
# Get or create the working page
|
||||||
@@ -32,7 +32,6 @@ class SkyvernBrowser(BrowserContext):
|
|||||||
_browser_context: The underlying Playwright BrowserContext.
|
_browser_context: The underlying Playwright BrowserContext.
|
||||||
_browser_session_id: Optional session ID for persistent browser sessions.
|
_browser_session_id: Optional session ID for persistent browser sessions.
|
||||||
_browser_address: Optional address for remote browser connections.
|
_browser_address: Optional address for remote browser connections.
|
||||||
_client: The AsyncSkyvern client for API communication.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|||||||
Reference in New Issue
Block a user