Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/skills/airbyte-sdk-reference/sdk-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
```python
import airbyte_agent_sdk

# Set global credentials (used as defaults by connect(), Workspace, ask())
# Set global credentials (used as defaults by connect() and Workspace)
airbyte_agent_sdk.configure(
*,
client_id: str, # Airbyte OAuth client ID
Expand Down
2 changes: 1 addition & 1 deletion .codex/skills/airbyte-sdk-reference/sdk-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
```python
import airbyte_agent_sdk

# Set global credentials (used as defaults by connect(), Workspace, ask())
# Set global credentials (used as defaults by connect() and Workspace)
airbyte_agent_sdk.configure(
*,
client_id: str, # Airbyte OAuth client ID
Expand Down
18 changes: 5 additions & 13 deletions airbyte_agent_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
automatically when their `client_id`/`client_secret` kwargs are
omitted.
2. **Explicit kwargs**: pass `client_id=` and `client_secret=` directly
to [`connect()`](#connect), [`Workspace`](#Workspace),
[`ask()`](#ask), or [`ask_sync()`](#ask_sync).
to [`connect()`](#connect) or [`Workspace`](#Workspace).
3. **Programmatic**: call [`configure()`](#configure) once at startup to
set process-wide defaults (useful in notebooks).

Expand All @@ -40,18 +39,15 @@ async def main():
asyncio.run(main())
```

Use [`ask_sync`](#ask_sync) and direct [`connect()`](#connect) for scripts
and notebooks; use [`ask`](#ask) and [`Workspace`](#Workspace) for async
applications.
Use direct [`connect()`](#connect) for scripts and notebooks; use
[`Workspace`](#Workspace) for async applications.

## Entry points

- [`connect`](#connect) — one-call factory that returns a typed connector
or a [`HostedExecutor`](#HostedExecutor).
- [`list_connectors`](#list_connectors) — enumerate connectors bundled
with this SDK.
- [`ask`](#ask) / [`ask_sync`](#ask_sync) — natural-language query across
an entire workspace.

## Workspace operations

Expand All @@ -62,7 +58,7 @@ async def main():

## Results & info

- [`AskResult`](#AskResult), [`ConnectorInfo`](#ConnectorInfo),
- [`ConnectorInfo`](#ConnectorInfo),
[`WorkflowInfo`](#WorkflowInfo), [`AutomationInfo`](#AutomationInfo),
[`ExecutionConfig`](#ExecutionConfig),
[`ExecutionResult`](#ExecutionResult),
Expand Down Expand Up @@ -114,7 +110,6 @@ async def main():

from __future__ import annotations

from .ask import ask, ask_sync
from .config import configure
from .connect import connect
from .constants import SDK_VERSION
Expand All @@ -129,7 +124,7 @@ async def main():
InvalidParameterError,
MissingParameterError,
)
from .executor.models import AskResult, AutomationInfo, ConnectorInfo, WorkflowInfo
from .executor.models import AutomationInfo, ConnectorInfo, WorkflowInfo
from .http.exceptions import (
AuthenticationError,
ConnectorValidationError,
Expand All @@ -151,12 +146,9 @@ async def main():
"connect",
"list_connectors",
"Workspace",
"ask",
"ask_sync",
# Hosted execution
"HostedExecutor",
# Results / info types
"AskResult",
"ConnectorInfo",
"WorkflowInfo",
"AutomationInfo",
Expand Down
136 changes: 0 additions & 136 deletions airbyte_agent_sdk/ask.py

This file was deleted.

22 changes: 0 additions & 22 deletions airbyte_agent_sdk/cloud_utils/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,28 +513,6 @@ async def execute_connector(

return response.json()

async def ask_workspace(self, workspace_name: str, prompt: str) -> dict[str, Any]:
"""Ask a natural-language question across all connectors in a workspace.

Raises:
AuthenticationError: If API returns 401/403
RateLimitError: If API returns 429
ConnectorValidationError: If API returns 400/422
HTTPStatusError: If API returns any other 4xx/5xx status code
httpx.RequestError: If network request fails
"""
token = await self.get_bearer_token()
url = f"{self.API_BASE_URL}/api/v1/workspaces/query/structured"
headers = self._build_headers(token=token)
response = await self._http_client.post(
url,
params={"workspace_name": workspace_name},
json={"prompt": prompt},
headers=headers,
)
_raise_with_body(response)
return response.json()

async def list_workspace_connectors(self, customer_name: str) -> list[dict[str, Any]]:
"""List connector instances for a workspace.

Expand Down
4 changes: 2 additions & 2 deletions airbyte_agent_sdk/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ def configure(
organization_id: str | None = None,
workspace_name: str = "default",
) -> None:
"""Set global SDK credentials. These are used as defaults by connect(), Workspace, and ask().
"""Set global SDK credentials. These are used as defaults by connect() and Workspace.

Calling configure() again overwrites the previous configuration.
Explicit kwargs passed to connect()/Workspace()/ask() always take priority.
Explicit kwargs passed to connect()/Workspace() always take priority.
"""
global _config
with _lock:
Expand Down
4 changes: 2 additions & 2 deletions airbyte_agent_sdk/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class AirbyteError(Exception):
Not caught by ``AirbyteError``:

* ``ValueError`` from argument validation at ``connect()``,
``Workspace(...)``, ``ask()``/``ask_sync()`` (via
``resolve_credentials()``), and ``HostedExecutor(...)``.
``Workspace(...)`` (via ``resolve_credentials()``), and
``HostedExecutor(...)``.
* ``httpx.HTTPStatusError`` / ``httpx.RequestError`` propagated
unwrapped from the hosted path (``HostedExecutor.execute()`` and
``AirbyteCloudClient``).
Expand Down
48 changes: 0 additions & 48 deletions airbyte_agent_sdk/executor/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,54 +107,6 @@ class ExecutionResult:
meta: dict[str, Any] | None = None


@dataclass
class AskToolCallResult:
"""A single tool call result from a structured query.

Fields match backend StructuredQueryToolCallResult (customer_query/schemas.py:36-44).
"""

source_id: str | None = None
entity: str | None = None
action: str | None = None
params: dict[str, Any] = field(default_factory=dict)
status: str | None = None
data: Any = None
connector_metadata: Any = None
execution_time_ms: int | None = None


@dataclass
class AskResult:
"""Result of a workspace-level natural language query.

Fields match backend StructuredQueryResponse (customer_query/schemas.py:53-59).
Note: execution_metadata is required in backend but made optional here for
forward-compatibility -- the SDK should not break if the backend omits it.
"""

outcome: str
outcome_reason: str | None = None
answer: str | None = None
results: list[AskToolCallResult] = field(default_factory=list)
query_id: str | None = None
execution_metadata: dict[str, Any] = field(default_factory=dict)

@classmethod
def from_response(cls, response: dict[str, Any]) -> AskResult:
"""Parse a raw structured query API response into AskResult."""
_fields = set(AskToolCallResult.__dataclass_fields__)
results = [AskToolCallResult(**{k: v for k, v in r.items() if k in _fields}) for r in response.get("results", [])]
return cls(
outcome=response.get("outcome", "error"),
outcome_reason=response.get("outcome_reason"),
answer=response.get("answer"),
results=results,
query_id=response.get("query_id"),
execution_metadata=response.get("execution_metadata") or {},
)


@dataclass
class ConnectorInfo:
"""A connector instance in a workspace."""
Expand Down
16 changes: 5 additions & 11 deletions airbyte_agent_sdk/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
from airbyte_agent_sdk.config import resolve_credentials
from airbyte_agent_sdk.connector_model_loader import load_connector_model
from airbyte_agent_sdk.executor.hosted_executor import HostedExecutor
from airbyte_agent_sdk.executor.models import AskResult, AutomationInfo, ConnectorInfo, WorkflowInfo
from airbyte_agent_sdk.executor.models import AutomationInfo, ConnectorInfo, WorkflowInfo


class Workspace:
"""Top-level entry point for Airbyte hosted-mode workspace operations.

Provides workspace-level methods: `ask`, list/create/delete connectors,
get a connector executor, and workflow/automation CRUD. Use `Workspace`
when you want to operate against a whole workspace (many connectors,
Provides workspace-level methods: list/create/delete connectors, get a
connector executor, and workflow/automation CRUD. Use `Workspace` when
you want to operate against a whole workspace (many connectors,
workflows, automations); use [`connect()`](#connect) when you already
know which connector you want to execute.

Expand All @@ -32,9 +32,8 @@ async def main():
client_secret="your_client_secret",
workspace_name="my-workspace",
) as ws:
result = await ws.ask("list my recent customers")
connectors = await ws.list_connectors()
print(result.outcome, len(connectors))
print(len(connectors))

asyncio.run(main())
```
Expand Down Expand Up @@ -77,11 +76,6 @@ def __init__(
organization_id=self._organization_id,
)

async def ask(self, prompt: str) -> AskResult:
"""Ask a natural-language question across all connectors."""
response = await self._cloud_client.ask_workspace(self._workspace_name, prompt)
return AskResult.from_response(response)

async def list_connectors(self) -> list[ConnectorInfo]:
"""List connector instances in this workspace."""
data = await self._cloud_client.list_workspace_connectors(self._workspace_name)
Expand Down
Loading