Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
eb8dbfa
codegen metadata
stainless-app[bot] Mar 26, 2026
d7b298d
feat: Use correct branch for Stainless PRs
stainless-app[bot] Mar 26, 2026
c518876
feat(internal): implement indices array format for query and form ser…
stainless-app[bot] Mar 26, 2026
7fc79ef
feat(api): api update
stainless-app[bot] Mar 27, 2026
31b5a63
feat: Add VMIdleTimeoutMinutes param to API
stainless-app[bot] Mar 27, 2026
9fe02aa
feat(api): api update
stainless-app[bot] Mar 27, 2026
2f71989
feat: Endpoint to upload third-party harness block snapshots
stainless-app[bot] Mar 31, 2026
3ab37f7
codegen metadata
stainless-app[bot] Mar 31, 2026
99808a5
codegen metadata
stainless-app[bot] Mar 31, 2026
58d59e3
feat: Address Stainless diagnostics
stainless-app[bot] Apr 1, 2026
aac84c5
feat: Create run for every local conversation and add filter
stainless-app[bot] Apr 1, 2026
e63c7df
codegen metadata
stainless-app[bot] Apr 1, 2026
5514980
feat: Orchestrations V2: Public API endpoints
stainless-app[bot] Apr 2, 2026
71d7204
feat: Fix the harness type in the openAPI spec
stainless-app[bot] Apr 2, 2026
c8b44e5
feat: Add harness enum to openAPI spec
stainless-app[bot] Apr 2, 2026
4b777eb
feat(api): api update
stainless-app[bot] Apr 2, 2026
7c92cb3
codegen metadata
stainless-app[bot] Apr 2, 2026
01721aa
codegen metadata
stainless-app[bot] Apr 2, 2026
d9446da
codegen metadata
stainless-app[bot] Apr 2, 2026
cdcbe53
codegen metadata
stainless-app[bot] Apr 2, 2026
f90d3fb
codegen metadata
stainless-app[bot] Apr 2, 2026
658c50b
feat: ian/fix_conversation_id_nameing
stainless-app[bot] Apr 2, 2026
1bcaee3
codegen metadata
stainless-app[bot] Apr 2, 2026
75b1c92
feat(api): api update
stainless-app[bot] Apr 2, 2026
e52643f
feat(api): manual updates
stainless-app[bot] Apr 3, 2026
1238769
feat(api): api update
stainless-app[bot] Apr 3, 2026
ed9f4cf
feat(api): manual updates
stainless-app[bot] Apr 3, 2026
5e2d3ee
feat(api): api update
stainless-app[bot] Apr 3, 2026
204505c
feat(api): api update
stainless-app[bot] Apr 7, 2026
c5752fb
feat: Add parent_run_id to retrieve/list runs API response
stainless-app[bot] Apr 7, 2026
5da3150
fix(client): preserve hardcoded query params when merging with user p…
stainless-app[bot] Apr 7, 2026
5103fc2
codegen metadata
stainless-app[bot] Apr 7, 2026
54c505b
feat: Define auth secrets and inject them into the environment.
stainless-app[bot] Apr 8, 2026
1d2007e
feat: [Artifacts] public API file artifact downloads
stainless-app[bot] Apr 9, 2026
9eccdc4
codegen metadata
stainless-app[bot] Apr 9, 2026
cb86677
codegen metadata
stainless-app[bot] Apr 9, 2026
4ad8119
codegen metadata
stainless-app[bot] Apr 9, 2026
9140132
feat(api): api update
stainless-app[bot] Apr 9, 2026
fd35b1f
release: 0.11.0
stainless-app[bot] Apr 9, 2026
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 .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.10.1"
".": "0.11.0"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 14
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-a912e2533a6f1fbeee38d4b7739b771ed5711c648a6a7f3d8769b8b2cb4f31fb.yml
openapi_spec_hash: ef48f8fcc46a51b00893505e9b52c95d
config_hash: e894152aaebba5a2e65e27efaf2712e2
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta%2Fwarp-api-8f9c749573846b07a55a3131b66456f0a592838c6bfc986ab30948df66cd6f11.yml
openapi_spec_hash: 59f1ac98ad6cf13b12c59196bcecffd7
config_hash: 60052b2c1c0862014416821aba875574
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,40 @@
# Changelog

## 0.11.0 (2026-04-09)

Full Changelog: [v0.10.1...v0.11.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.10.1...v0.11.0)

### Features

* [Artifacts] public API file artifact downloads ([1d2007e](https://github.com/warpdotdev/oz-sdk-python/commit/1d2007eaa692679fdcc56a6092ffdf9ad09de6ca))
* Add harness enum to openAPI spec ([c8b44e5](https://github.com/warpdotdev/oz-sdk-python/commit/c8b44e532885d53f406babf8c0463f62d86a1fbe))
* Add parent_run_id to retrieve/list runs API response ([c5752fb](https://github.com/warpdotdev/oz-sdk-python/commit/c5752fbbceffbc322cee5dd8b111aa0ce84ce615))
* Add VMIdleTimeoutMinutes param to API ([31b5a63](https://github.com/warpdotdev/oz-sdk-python/commit/31b5a63204a2baca1a41f0b4124408d2d2b7e6a4))
* Address Stainless diagnostics ([58d59e3](https://github.com/warpdotdev/oz-sdk-python/commit/58d59e3593d27ad4bb17e340c384d9709f650806))
* **api:** api update ([9140132](https://github.com/warpdotdev/oz-sdk-python/commit/9140132ca22861c78365898e250a5c613af454a8))
* **api:** api update ([204505c](https://github.com/warpdotdev/oz-sdk-python/commit/204505c1472d5af4b9463a975fd919c5fc4dbe78))
* **api:** api update ([5e2d3ee](https://github.com/warpdotdev/oz-sdk-python/commit/5e2d3ee9400130c5a8dc2d51d1618ad292c051ab))
* **api:** api update ([1238769](https://github.com/warpdotdev/oz-sdk-python/commit/12387694506b5d0d53e527db1dcdb2ca02ae2f71))
* **api:** api update ([75b1c92](https://github.com/warpdotdev/oz-sdk-python/commit/75b1c92550babef5b0cf19689613f95131df08d7))
* **api:** api update ([4b777eb](https://github.com/warpdotdev/oz-sdk-python/commit/4b777ebbe2483c2d882597bd0ab593128f5355d9))
* **api:** api update ([9fe02aa](https://github.com/warpdotdev/oz-sdk-python/commit/9fe02aad21c71cbab837f7d335e5234e1974bb90))
* **api:** api update ([7fc79ef](https://github.com/warpdotdev/oz-sdk-python/commit/7fc79efe0897451670cb44cf29c0f99b06ffe821))
* **api:** manual updates ([ed9f4cf](https://github.com/warpdotdev/oz-sdk-python/commit/ed9f4cfa6a0db58dc3ca5564f83b09ef1a19e3a9))
* **api:** manual updates ([e52643f](https://github.com/warpdotdev/oz-sdk-python/commit/e52643fcb1408ac9f8dd6a284b9cb818f3f468ac))
* Create run for every local conversation and add filter ([aac84c5](https://github.com/warpdotdev/oz-sdk-python/commit/aac84c585eb3b0ed5262d683e544960a82eec2a2))
* Define auth secrets and inject them into the environment. ([54c505b](https://github.com/warpdotdev/oz-sdk-python/commit/54c505b2d58246abab42cda52d79df3ddbfed083))
* Endpoint to upload third-party harness block snapshots ([2f71989](https://github.com/warpdotdev/oz-sdk-python/commit/2f7198972cec56e72b802c7505fb445d10304bf4))
* Fix the harness type in the openAPI spec ([71d7204](https://github.com/warpdotdev/oz-sdk-python/commit/71d72043f6cb8d8ae6af4c01936967059936c7b0))
* ian/fix_conversation_id_nameing ([658c50b](https://github.com/warpdotdev/oz-sdk-python/commit/658c50b6b3937249034ad9e6993e598705d0c3c6))
* **internal:** implement indices array format for query and form serialization ([c518876](https://github.com/warpdotdev/oz-sdk-python/commit/c518876f3da1129d3c351982ed4a06590fd15f2e))
* Orchestrations V2: Public API endpoints ([5514980](https://github.com/warpdotdev/oz-sdk-python/commit/551498004c85dd4277069b0c059c17c7504bc18b))
* Use correct branch for Stainless PRs ([d7b298d](https://github.com/warpdotdev/oz-sdk-python/commit/d7b298d99c5dcb5e02530329fef222de92f3e9d6))


### Bug Fixes

* **client:** preserve hardcoded query params when merging with user params ([5da3150](https://github.com/warpdotdev/oz-sdk-python/commit/5da315075e053b1a6cef709439f9972f6fd0f70f))

## 0.10.1 (2026-03-24)

Full Changelog: [v0.10.0...v0.10.1](https://github.com/warpdotdev/oz-sdk-python/compare/v0.10.0...v0.10.1)
Expand Down
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,69 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ

Typed requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.

## Pagination

List methods in the Oz API API are paginated.

This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:

```python
from oz_agent_sdk import OzAPI

client = OzAPI()

all_runs = []
# Automatically fetches more pages as needed.
for run in client.agent.runs.list():
# Do something with run here
all_runs.append(run)
print(all_runs)
```

Or, asynchronously:

```python
import asyncio
from oz_agent_sdk import AsyncOzAPI

client = AsyncOzAPI()


async def main() -> None:
all_runs = []
# Iterate through items across all pages, issuing requests as needed.
async for run in client.agent.runs.list():
all_runs.append(run)
print(all_runs)


asyncio.run(main())
```

Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:

```python
first_page = await client.agent.runs.list()
if first_page.has_next_page():
print(f"will fetch next page using these details: {first_page.next_page_info()}")
next_page = await first_page.get_next_page()
print(f"number of items we just fetched: {len(next_page.runs)}")

# Remove `await` for non-async usage.
```

Or just work directly with the returned data:

```python
first_page = await client.agent.runs.list()

print(f"next page cursor: {first_page.page_info.next_cursor}") # => "next page cursor: ..."
for run in first_page.runs:
print(run.run_id)

# Remove `await` for non-async usage.
```

## Nested params

Nested parameters are dictionaries, typed using `TypedDict`, for example:
Expand Down
7 changes: 4 additions & 3 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ Types:
from oz_agent_sdk.types import (
AgentSkill,
AmbientAgentConfig,
AwsProviderConfig,
CloudEnvironmentConfig,
Error,
ErrorCode,
GcpProviderConfig,
McpServerConfig,
Scope,
UserProfile,
Expand All @@ -22,7 +24,7 @@ Methods:

- <code title="get /agent">client.agent.<a href="./src/oz_agent_sdk/resources/agent/agent.py">list</a>(\*\*<a href="src/oz_agent_sdk/types/agent_list_params.py">params</a>) -> <a href="./src/oz_agent_sdk/types/agent_list_response.py">AgentListResponse</a></code>
- <code title="get /agent/artifacts/{artifactUid}">client.agent.<a href="./src/oz_agent_sdk/resources/agent/agent.py">get_artifact</a>(artifact_uid) -> <a href="./src/oz_agent_sdk/types/agent_get_artifact_response.py">AgentGetArtifactResponse</a></code>
- <code title="post /agent/run">client.agent.<a href="./src/oz_agent_sdk/resources/agent/agent.py">run</a>(\*\*<a href="src/oz_agent_sdk/types/agent_run_params.py">params</a>) -> <a href="./src/oz_agent_sdk/types/agent_run_response.py">AgentRunResponse</a></code>
- <code title="post /agent/runs">client.agent.<a href="./src/oz_agent_sdk/resources/agent/agent.py">run</a>(\*\*<a href="src/oz_agent_sdk/types/agent_run_params.py">params</a>) -> <a href="./src/oz_agent_sdk/types/agent_run_response.py">AgentRunResponse</a></code>

## Runs

Expand All @@ -34,15 +36,14 @@ from oz_agent_sdk.types.agent import (
RunItem,
RunSourceType,
RunState,
RunListResponse,
RunCancelResponse,
)
```

Methods:

- <code title="get /agent/runs/{runId}">client.agent.runs.<a href="./src/oz_agent_sdk/resources/agent/runs.py">retrieve</a>(run_id) -> <a href="./src/oz_agent_sdk/types/agent/run_item.py">RunItem</a></code>
- <code title="get /agent/runs">client.agent.runs.<a href="./src/oz_agent_sdk/resources/agent/runs.py">list</a>(\*\*<a href="src/oz_agent_sdk/types/agent/run_list_params.py">params</a>) -> <a href="./src/oz_agent_sdk/types/agent/run_list_response.py">RunListResponse</a></code>
- <code title="get /agent/runs">client.agent.runs.<a href="./src/oz_agent_sdk/resources/agent/runs.py">list</a>(\*\*<a href="src/oz_agent_sdk/types/agent/run_list_params.py">params</a>) -> <a href="./src/oz_agent_sdk/types/agent/run_item.py">SyncRunsCursorPage[RunItem]</a></code>
- <code title="post /agent/runs/{runId}/cancel">client.agent.runs.<a href="./src/oz_agent_sdk/resources/agent/runs.py">cancel</a>(run_id) -> str</code>

## Schedules
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "oz-agent-sdk"
version = "0.10.1"
version = "0.11.0"
description = "The official Python library for the oz-api API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
38 changes: 32 additions & 6 deletions src/oz_agent_sdk/_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
)
from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping
from ._compat import PYDANTIC_V1, model_copy, model_dump
from ._models import GenericModel, FinalRequestOptions, validate_type, construct_type
from ._models import GenericModel, SecurityOptions, FinalRequestOptions, validate_type, construct_type
from ._response import (
APIResponse,
BaseAPIResponse,
Expand Down Expand Up @@ -432,9 +432,27 @@ def _make_status_error(
) -> _exceptions.APIStatusError:
raise NotImplementedError()

def _auth_headers(
self,
security: SecurityOptions, # noqa: ARG002
) -> dict[str, str]:
return {}

def _auth_query(
self,
security: SecurityOptions, # noqa: ARG002
) -> dict[str, str]:
return {}

def _custom_auth(
self,
security: SecurityOptions, # noqa: ARG002
) -> httpx.Auth | None:
return None

def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0) -> httpx.Headers:
custom_headers = options.headers or {}
headers_dict = _merge_mappings(self.default_headers, custom_headers)
headers_dict = _merge_mappings({**self._auth_headers(options.security), **self.default_headers}, custom_headers)
self._validate_headers(headers_dict, custom_headers)

# headers are case-insensitive while dictionaries are not.
Expand Down Expand Up @@ -506,7 +524,7 @@ def _build_request(
raise RuntimeError(f"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`")

headers = self._build_headers(options, retries_taken=retries_taken)
params = _merge_mappings(self.default_query, options.params)
params = _merge_mappings({**self._auth_query(options.security), **self.default_query}, options.params)
content_type = headers.get("Content-Type")
files = options.files

Expand Down Expand Up @@ -540,6 +558,10 @@ def _build_request(
files = cast(HttpxRequestFiles, ForceMultipartDict())

prepared_url = self._prepare_url(options.url)
# preserve hard-coded query params from the url
if params and prepared_url.query:
params = {**dict(prepared_url.params.items()), **params}
prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b"?", 1)[0])
if "_" in prepared_url.host:
# work around https://github.com/encode/httpx/discussions/2880
kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")}
Expand Down Expand Up @@ -671,7 +693,6 @@ def default_headers(self) -> dict[str, str | Omit]:
"Content-Type": "application/json",
"User-Agent": self.user_agent,
**self.platform_headers(),
**self.auth_headers,
**self._custom_headers,
}

Expand Down Expand Up @@ -990,8 +1011,9 @@ def request(
self._prepare_request(request)

kwargs: HttpxSendArgs = {}
if self.custom_auth is not None:
kwargs["auth"] = self.custom_auth
custom_auth = self._custom_auth(options.security)
if custom_auth is not None:
kwargs["auth"] = custom_auth

if options.follow_redirects is not None:
kwargs["follow_redirects"] = options.follow_redirects
Expand Down Expand Up @@ -1952,6 +1974,7 @@ def make_request_options(
idempotency_key: str | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
post_parser: PostParser | NotGiven = not_given,
security: SecurityOptions | None = None,
) -> RequestOptions:
"""Create a dict of type RequestOptions without keys of NotGiven values."""
options: RequestOptions = {}
Expand All @@ -1977,6 +2000,9 @@ def make_request_options(
# internal
options["post_parser"] = post_parser # type: ignore

if security is not None:
options["security"] = security

return options


Expand Down
19 changes: 15 additions & 4 deletions src/oz_agent_sdk/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
)
from ._utils import is_given, get_async_library
from ._compat import cached_property
from ._models import SecurityOptions
from ._version import __version__
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
from ._exceptions import OzAPIError, APIStatusError
Expand Down Expand Up @@ -112,9 +113,14 @@ def with_streaming_response(self) -> OzAPIWithStreamedResponse:
def qs(self) -> Querystring:
return Querystring(array_format="repeat")

@property
@override
def auth_headers(self) -> dict[str, str]:
def _auth_headers(self, security: SecurityOptions) -> dict[str, str]:
return {
**(self._bearer_auth if security.get("bearer_auth", False) else {}),
}

@property
def _bearer_auth(self) -> dict[str, str]:
api_key = self.api_key
return {"Authorization": f"Bearer {api_key}"}

Expand Down Expand Up @@ -287,9 +293,14 @@ def with_streaming_response(self) -> AsyncOzAPIWithStreamedResponse:
def qs(self) -> Querystring:
return Querystring(array_format="repeat")

@property
@override
def auth_headers(self) -> dict[str, str]:
def _auth_headers(self, security: SecurityOptions) -> dict[str, str]:
return {
**(self._bearer_auth if security.get("bearer_auth", False) else {}),
}

@property
def _bearer_auth(self) -> dict[str, str]:
api_key = self.api_key
return {"Authorization": f"Bearer {api_key}"}

Expand Down
6 changes: 6 additions & 0 deletions src/oz_agent_sdk/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,10 @@ def _create_pydantic_model(type_: _T) -> Type[RootModel[_T]]:
return RootModel[type_] # type: ignore


class SecurityOptions(TypedDict, total=False):
bearer_auth: bool


class FinalRequestOptionsInput(TypedDict, total=False):
method: Required[str]
url: Required[str]
Expand All @@ -804,6 +808,7 @@ class FinalRequestOptionsInput(TypedDict, total=False):
json_data: Body
extra_json: AnyMapping
follow_redirects: bool
security: SecurityOptions


@final
Expand All @@ -818,6 +823,7 @@ class FinalRequestOptions(pydantic.BaseModel):
idempotency_key: Union[str, None] = None
post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven()
follow_redirects: Union[bool, None] = None
security: SecurityOptions = {"bearer_auth": True}

content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] = None
# It should be noted that we cannot use `json` here as that would override
Expand Down
5 changes: 4 additions & 1 deletion src/oz_agent_sdk/_qs.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ def _stringify_item(
items.extend(self._stringify_item(key, item, opts))
return items
elif array_format == "indices":
raise NotImplementedError("The array indices format is not supported yet")
items = []
for i, item in enumerate(value):
items.extend(self._stringify_item(f"{key}[{i}]", item, opts))
return items
elif array_format == "brackets":
items = []
key = key + "[]"
Expand Down
3 changes: 2 additions & 1 deletion src/oz_agent_sdk/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from httpx import URL, Proxy, Timeout, Response, BaseTransport, AsyncBaseTransport

if TYPE_CHECKING:
from ._models import BaseModel
from ._models import BaseModel, SecurityOptions
from ._response import APIResponse, AsyncAPIResponse

Transport = BaseTransport
Expand Down Expand Up @@ -121,6 +121,7 @@ class RequestOptions(TypedDict, total=False):
extra_json: AnyMapping
idempotency_key: str
follow_redirects: bool
security: SecurityOptions


# Sentinel class used until PEP 0661 is accepted
Expand Down
2 changes: 1 addition & 1 deletion src/oz_agent_sdk/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "oz_agent_sdk"
__version__ = "0.10.1" # x-release-please-version
__version__ = "0.11.0" # x-release-please-version
Loading
Loading