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
|
||||
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"))
|
||||
```
|
||||
|
||||
@@ -37,7 +37,7 @@ Laminar.initialize(disabled_instruments=set([Instruments.OPENAI]))
|
||||
# Configure LiteLLM to trace all LLM calls made by Skyvern
|
||||
litellm.callbacks = [LaminarLiteLLMCallback()]
|
||||
|
||||
skyvern = Skyvern()
|
||||
skyvern = Skyvern(api_key="YOUR_API_KEY")
|
||||
|
||||
async def main():
|
||||
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
|
||||
from skyvern import Skyvern
|
||||
|
||||
skyvern = Skyvern()
|
||||
skyvern = Skyvern(api_key="YOUR_API_KEY")
|
||||
task = await skyvern.run_task(
|
||||
prompt="Find the top post on hackernews today",
|
||||
data_extraction_schema={
|
||||
@@ -159,7 +159,7 @@ When you are sending a run task request the Skyvern service, you can set the `wa
|
||||
```python
|
||||
from skyvern import Skyvern
|
||||
|
||||
skyvern = Skyvern()
|
||||
skyvern = Skyvern(api_key="YOUR_API_KEY")
|
||||
task = await skyvern.run_task(
|
||||
prompt="Find the top post on hackernews today",
|
||||
# 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
|
||||
from skyvern import Skyvern
|
||||
|
||||
skyvern = Skyvern()
|
||||
skyvern = Skyvern(api_key="YOUR_API_KEY")
|
||||
task = await skyvern.run_task(
|
||||
prompt="Find the top post on hackernews today",
|
||||
webhook_url="https://your-webhook-url.com",
|
||||
|
||||
@@ -15,7 +15,7 @@ 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()
|
||||
agent: Skyvern = Skyvern.local()
|
||||
|
||||
def _run(self, *args: Any, **kwargs: Any) -> None:
|
||||
raise NotImplementedError("skyvern task tool does not support sync")
|
||||
|
||||
@@ -13,7 +13,7 @@ from skyvern.schemas.runs import RunEngine
|
||||
class SkyvernTool:
|
||||
def __init__(self, agent: Skyvern | None = None):
|
||||
if agent is None:
|
||||
agent = Skyvern()
|
||||
agent = Skyvern.local()
|
||||
self.agent = agent
|
||||
|
||||
def run_task(self) -> FunctionTool:
|
||||
@@ -44,7 +44,7 @@ class SkyvernTaskToolSpec(BaseToolSpec):
|
||||
run_task_timeout_seconds: int = settings.run_task_timeout_seconds,
|
||||
) -> None:
|
||||
if agent is None:
|
||||
agent = Skyvern()
|
||||
agent = Skyvern.local()
|
||||
self.agent = agent
|
||||
self.engine = engine
|
||||
self.run_task_timeout_seconds = run_task_timeout_seconds
|
||||
|
||||
@@ -2,7 +2,7 @@ import asyncio
|
||||
import os
|
||||
import pathlib
|
||||
import tempfile
|
||||
from typing import Any, overload
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
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.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.embedded_server_factory import create_embedded_server
|
||||
from skyvern.library.skyvern_browser import SkyvernBrowser
|
||||
from skyvern.schemas.run_blocks import CredentialType
|
||||
from skyvern.schemas.runs import ProxyLocation, RunEngine, RunStatus
|
||||
@@ -33,13 +32,13 @@ class Skyvern(AsyncSkyvern):
|
||||
Example:
|
||||
```python
|
||||
|
||||
# Initialize with remote environment and API key
|
||||
skyvern = Skyvern(environment=SkyvernEnvironment.CLOUD, api_key="your-api-key")
|
||||
# Remote mode: Connect to Skyvern Cloud (API key required)
|
||||
skyvern = Skyvern(api_key="your-api-key")
|
||||
|
||||
# Or in embedded mode (run `skyvern quickstart` first):
|
||||
skyvern = Skyvern()
|
||||
# Local/embedded mode (run `skyvern quickstart` first):
|
||||
skyvern = Skyvern.local()
|
||||
|
||||
# Launch a local browser
|
||||
# Launch a local browser (works only in local environment)
|
||||
browser = await skyvern.launch_local_browser(headless=False)
|
||||
page = await browser.get_working_page()
|
||||
|
||||
@@ -81,12 +80,11 @@ class Skyvern(AsyncSkyvern):
|
||||
```
|
||||
"""
|
||||
|
||||
@overload
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
environment: SkyvernEnvironment,
|
||||
api_key: str,
|
||||
environment: SkyvernEnvironment = SkyvernEnvironment.CLOUD,
|
||||
base_url: str | None = None,
|
||||
timeout: float | None = None,
|
||||
follow_redirects: bool | None = True,
|
||||
@@ -95,11 +93,11 @@ class Skyvern(AsyncSkyvern):
|
||||
"""Remote mode: Connect to Skyvern Cloud or self-hosted instance.
|
||||
|
||||
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.
|
||||
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
|
||||
the specified environment.
|
||||
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.
|
||||
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__(
|
||||
base_url=base_url,
|
||||
environment=environment,
|
||||
@@ -213,10 +115,104 @@ class Skyvern(AsyncSkyvern):
|
||||
)
|
||||
|
||||
self._environment = environment
|
||||
self._api_key = api_key
|
||||
|
||||
self._api_key: str | None = api_key
|
||||
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(
|
||||
self,
|
||||
prompt: str,
|
||||
|
||||
@@ -18,7 +18,7 @@ class SkyvernBrowser(BrowserContext):
|
||||
|
||||
Example:
|
||||
```python
|
||||
skyvern = Skyvern()
|
||||
skyvern = Skyvern.local()
|
||||
browser = await skyvern.launch_local_browser()
|
||||
|
||||
# Get or create the working page
|
||||
@@ -32,7 +32,6 @@ class SkyvernBrowser(BrowserContext):
|
||||
_browser_context: The underlying Playwright BrowserContext.
|
||||
_browser_session_id: Optional session ID for persistent browser sessions.
|
||||
_browser_address: Optional address for remote browser connections.
|
||||
_client: The AsyncSkyvern client for API communication.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
|
||||
Reference in New Issue
Block a user