diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e2f90fb..700c64d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: lint: timeout-minutes: 10 name: lint - runs-on: ${{ github.repository == 'stainless-sdks/warp-api-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: 'ubuntu-latest' if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -41,7 +41,7 @@ jobs: permissions: contents: read id-token: write - runs-on: ${{ github.repository == 'stainless-sdks/warp-api-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: 'ubuntu-latest' steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -58,7 +58,7 @@ jobs: - name: Get GitHub OIDC Token if: |- - github.repository == 'stainless-sdks/warp-api-python' && + github.repository == 'warpdotdev/oz-sdk-python-staging' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -67,7 +67,7 @@ jobs: - name: Upload tarball if: |- - github.repository == 'stainless-sdks/warp-api-python' && + github.repository == 'warpdotdev/oz-sdk-python-staging' && !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s @@ -78,7 +78,7 @@ jobs: test: timeout-minutes: 10 name: test - runs-on: ${{ github.repository == 'stainless-sdks/warp-api-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: 'ubuntu-latest' if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d52d2b9..a26ebfc 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.13.0" + ".": "0.14.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index e679286..1b273bd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 23 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-964f646a32c318735de7673531a12788aede1840f7ab4893f2efa31c83440837.yml -openapi_spec_hash: 30f07ff0bfb491efb11cd88fce79968a -config_hash: 236823a4936c76818117c16aa5c188df +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/warp-bnavetta/warp-api-9b4270e56f0c240d415e68959e2e6d4ce00021d6fc0f8d5634fd0f6b0c875036.yml +openapi_spec_hash: 784089d01927148351a5c4f3fbe41d50 +config_hash: e52e930a60998be461fd4af99a2c9f1a diff --git a/CHANGELOG.md b/CHANGELOG.md index e741eb1..125001c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 0.14.0 (2026-06-17) + +Full Changelog: [v0.13.0...v0.14.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.13.0...v0.14.0) + +### Features + +* Add server run runtime to agent API ([85d7ef8](https://github.com/warpdotdev/oz-sdk-python/commit/85d7ef8e6cc1380deed30f8efd6e75f062b3fa53)) +* Allow for empty-prompt cloud-agent handoff ([2542fa3](https://github.com/warpdotdev/oz-sdk-python/commit/2542fa3058b5feead7f46fe5255665ef5c36528e)) +* **api:** api update ([73a49ad](https://github.com/warpdotdev/oz-sdk-python/commit/73a49ad055f94883b17b03b8a2c328881d1fe859)) +* **api:** api update ([8d4b77c](https://github.com/warpdotdev/oz-sdk-python/commit/8d4b77c936054c5c125fa0747a298a64ed349a48)) +* **api:** api update ([a03690f](https://github.com/warpdotdev/oz-sdk-python/commit/a03690f7a25a0887c60981a53a2224c5ba1cc26a)) +* **api:** api update ([7ef54cc](https://github.com/warpdotdev/oz-sdk-python/commit/7ef54ccc0ad281b27a2e0db5cac2956bef2b93e1)) +* **api:** api update ([d25946f](https://github.com/warpdotdev/oz-sdk-python/commit/d25946f832fe901339b42dcf8842a17d20b57634)) +* **api:** api update ([d59deee](https://github.com/warpdotdev/oz-sdk-python/commit/d59deee2f15baa213eaa694b1bf71f94330b9d89)) +* Followups for docs-syncing workflow ([4697ddc](https://github.com/warpdotdev/oz-sdk-python/commit/4697ddc9625dd3bcdcc756af1da2e2ba0fc5fff0)) + + +### Bug Fixes + +* **auth:** prioritize first auth header ([bcf94f5](https://github.com/warpdotdev/oz-sdk-python/commit/bcf94f549cd8109ac30d87f3922e5772238183b3)) +* update aiohttp to resolve CVE-2026-22815 ([#25](https://github.com/warpdotdev/oz-sdk-python/issues/25)) ([03d6bc4](https://github.com/warpdotdev/oz-sdk-python/commit/03d6bc4d2253f820aa5b1fa842d382b20f2d681d)) + ## 0.13.0 (2026-05-21) Full Changelog: [v0.12.0...v0.13.0](https://github.com/warpdotdev/oz-sdk-python/compare/v0.12.0...v0.13.0) diff --git a/pyproject.toml b/pyproject.toml index 533a8e4..e798041 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "oz-agent-sdk" -version = "0.13.0" +version = "0.14.0" description = "The official Python library for the oz-api API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 9f6eb1f..4ce1bc0 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -20,7 +20,7 @@ UPLOAD_RESPONSE=$(curl -v -X PUT \ if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then echo -e "\033[32mUploaded build to Stainless storage.\033[0m" - echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/warp-api-python/$SHA/$FILENAME'\033[0m" + echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/oz-sdk-python-staging/$SHA/$FILENAME'\033[0m" else echo -e "\033[31mFailed to upload artifact.\033[0m" exit 1 diff --git a/src/oz_agent_sdk/_client.py b/src/oz_agent_sdk/_client.py index 949709b..bf2c677 100644 --- a/src/oz_agent_sdk/_client.py +++ b/src/oz_agent_sdk/_client.py @@ -128,9 +128,11 @@ def qs(self) -> Querystring: @override def _auth_headers(self, security: SecurityOptions) -> dict[str, str]: - return { - **(self._bearer_auth if security.get("bearer_auth", False) else {}), - } + headers: dict[str, str] = {} + if security.get("bearer_auth", False): + for key, value in self._bearer_auth.items(): + headers.setdefault(key, value) + return headers @property def _bearer_auth(self) -> dict[str, str]: @@ -317,9 +319,11 @@ def qs(self) -> Querystring: @override def _auth_headers(self, security: SecurityOptions) -> dict[str, str]: - return { - **(self._bearer_auth if security.get("bearer_auth", False) else {}), - } + headers: dict[str, str] = {} + if security.get("bearer_auth", False): + for key, value in self._bearer_auth.items(): + headers.setdefault(key, value) + return headers @property def _bearer_auth(self) -> dict[str, str]: diff --git a/src/oz_agent_sdk/_version.py b/src/oz_agent_sdk/_version.py index 1762ab1..0909eaa 100644 --- a/src/oz_agent_sdk/_version.py +++ b/src/oz_agent_sdk/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "oz_agent_sdk" -__version__ = "0.13.0" # x-release-please-version +__version__ = "0.14.0" # x-release-please-version diff --git a/src/oz_agent_sdk/resources/agent/agent.py b/src/oz_agent_sdk/resources/agent/agent.py index af2411c..6910539 100644 --- a/src/oz_agent_sdk/resources/agent/agent.py +++ b/src/oz_agent_sdk/resources/agent/agent.py @@ -275,10 +275,10 @@ def run( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentRunResponse: - """Alias for POST /agent/run. + """Spawn a cloud agent with a prompt and optional configuration. - This is the preferred endpoint for creating new agent - runs. Behavior is identical to POST /agent/run. + The agent will be + queued for execution and assigned a unique run ID. Args: agent_identity_uid: Optional agent identity UID to use as the execution principal for the run. This @@ -302,7 +302,8 @@ def run( hierarchies. prompt: The prompt/instruction for the agent to execute. Required unless a skill is - specified via the skill field, config.skill_spec, or config.skills. + specified via the skill field, config.skill_spec, or config.skills. Handoff + requests may omit prompt when conversation_id is set. skill: Skill specification to use as the base prompt for the agent. Supported formats: @@ -566,10 +567,10 @@ async def run( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AgentRunResponse: - """Alias for POST /agent/run. + """Spawn a cloud agent with a prompt and optional configuration. - This is the preferred endpoint for creating new agent - runs. Behavior is identical to POST /agent/run. + The agent will be + queued for execution and assigned a unique run ID. Args: agent_identity_uid: Optional agent identity UID to use as the execution principal for the run. This @@ -593,7 +594,8 @@ async def run( hierarchies. prompt: The prompt/instruction for the agent to execute. Required unless a skill is - specified via the skill field, config.skill_spec, or config.skills. + specified via the skill field, config.skill_spec, or config.skills. Handoff + requests may omit prompt when conversation_id is set. skill: Skill specification to use as the base prompt for the agent. Supported formats: diff --git a/src/oz_agent_sdk/resources/agent/agent_.py b/src/oz_agent_sdk/resources/agent/agent_.py index f79333c..7294d3b 100644 --- a/src/oz_agent_sdk/resources/agent/agent_.py +++ b/src/oz_agent_sdk/resources/agent/agent_.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Iterable, Optional +from typing import Dict, Iterable, Optional import httpx @@ -19,6 +19,7 @@ from ...types.agent import agent_create_params, agent_update_params from ..._base_client import make_request_options from ...types.agent.agent_response import AgentResponse +from ...types.mcp_server_config_param import McpServerConfigParam from ...types.agent.list_agent_identities_response import ListAgentIdentitiesResponse __all__ = ["AgentResource", "AsyncAgentResource"] @@ -56,7 +57,8 @@ def create( environment_id: Optional[str] | Omit = omit, harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, inference_providers: agent_create_params.InferenceProviders | Omit = omit, - memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory: agent_create_params.Memory | Omit = omit, prompt: Optional[str] | Omit = omit, secrets: Iterable[agent_create_params.Secret] | Omit = omit, skills: SequenceNotStr[str] | Omit = omit, @@ -89,9 +91,10 @@ def create( inference_providers: Inference provider settings used for LLM calls. - memory_stores: Optional list of memory stores to attach to the agent. Each store must be - team-owned by the same team as the agent. Duplicate UIDs within a single request - are rejected. + mcp_servers: Optional map of MCP server configurations by name to attach to runs executed by + this agent. Run-level MCP config takes precedence over this agent-level default. + + memory: Memory settings for creating an agent. prompt: Optional base prompt for this agent @@ -125,7 +128,8 @@ def create( "environment_id": environment_id, "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, - "memory_stores": memory_stores, + "mcp_servers": mcp_servers, + "memory": memory, "prompt": prompt, "secrets": secrets, "skills": skills, @@ -148,7 +152,8 @@ def update( environment_id: Optional[str] | Omit = omit, harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, - memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory: Optional[agent_update_params.Memory] | Omit = omit, name: str | Omit = omit, prompt: Optional[str] | Omit = omit, secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, @@ -182,8 +187,11 @@ def update( inference_providers: Inference provider settings used for LLM calls. - memory_stores: Replacement list of memory stores. Omit to leave unchanged, pass an empty array - to clear, or pass a non-empty array to replace. + mcp_servers: Replacement map of MCP server configurations by name. Omit to leave unchanged, + pass an empty object to clear, or pass a non-empty object to replace. Run-level + MCP config takes precedence over this agent-level default. + + memory: Memory settings for updating an agent. name: The new name for the agent @@ -216,7 +224,8 @@ def update( "environment_id": environment_id, "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, - "memory_stores": memory_stores, + "mcp_servers": mcp_servers, + "memory": memory, "name": name, "prompt": prompt, "secrets": secrets, @@ -357,7 +366,8 @@ async def create( environment_id: Optional[str] | Omit = omit, harness_auth_secrets: agent_create_params.HarnessAuthSecrets | Omit = omit, inference_providers: agent_create_params.InferenceProviders | Omit = omit, - memory_stores: Iterable[agent_create_params.MemoryStore] | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory: agent_create_params.Memory | Omit = omit, prompt: Optional[str] | Omit = omit, secrets: Iterable[agent_create_params.Secret] | Omit = omit, skills: SequenceNotStr[str] | Omit = omit, @@ -390,9 +400,10 @@ async def create( inference_providers: Inference provider settings used for LLM calls. - memory_stores: Optional list of memory stores to attach to the agent. Each store must be - team-owned by the same team as the agent. Duplicate UIDs within a single request - are rejected. + mcp_servers: Optional map of MCP server configurations by name to attach to runs executed by + this agent. Run-level MCP config takes precedence over this agent-level default. + + memory: Memory settings for creating an agent. prompt: Optional base prompt for this agent @@ -426,7 +437,8 @@ async def create( "environment_id": environment_id, "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, - "memory_stores": memory_stores, + "mcp_servers": mcp_servers, + "memory": memory, "prompt": prompt, "secrets": secrets, "skills": skills, @@ -449,7 +461,8 @@ async def update( environment_id: Optional[str] | Omit = omit, harness_auth_secrets: Optional[agent_update_params.HarnessAuthSecrets] | Omit = omit, inference_providers: Optional[agent_update_params.InferenceProviders] | Omit = omit, - memory_stores: Optional[Iterable[agent_update_params.MemoryStore]] | Omit = omit, + mcp_servers: Dict[str, McpServerConfigParam] | Omit = omit, + memory: Optional[agent_update_params.Memory] | Omit = omit, name: str | Omit = omit, prompt: Optional[str] | Omit = omit, secrets: Optional[Iterable[agent_update_params.Secret]] | Omit = omit, @@ -483,8 +496,11 @@ async def update( inference_providers: Inference provider settings used for LLM calls. - memory_stores: Replacement list of memory stores. Omit to leave unchanged, pass an empty array - to clear, or pass a non-empty array to replace. + mcp_servers: Replacement map of MCP server configurations by name. Omit to leave unchanged, + pass an empty object to clear, or pass a non-empty object to replace. Run-level + MCP config takes precedence over this agent-level default. + + memory: Memory settings for updating an agent. name: The new name for the agent @@ -517,7 +533,8 @@ async def update( "environment_id": environment_id, "harness_auth_secrets": harness_auth_secrets, "inference_providers": inference_providers, - "memory_stores": memory_stores, + "mcp_servers": mcp_servers, + "memory": memory, "name": name, "prompt": prompt, "secrets": secrets, diff --git a/src/oz_agent_sdk/resources/agent/runs.py b/src/oz_agent_sdk/resources/agent/runs.py index c2d5075..fa745d3 100644 --- a/src/oz_agent_sdk/resources/agent/runs.py +++ b/src/oz_agent_sdk/resources/agent/runs.py @@ -301,7 +301,7 @@ def submit_followup( self, run_id: str, *, - message: str, + message: str | Omit = omit, mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -621,7 +621,7 @@ async def submit_followup( self, run_id: str, *, - message: str, + message: str | Omit = omit, mode: Literal["normal", "plan", "orchestrate"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. diff --git a/src/oz_agent_sdk/types/agent/agent_create_params.py b/src/oz_agent_sdk/types/agent/agent_create_params.py index 9de0a64..c69586c 100644 --- a/src/oz_agent_sdk/types/agent/agent_create_params.py +++ b/src/oz_agent_sdk/types/agent/agent_create_params.py @@ -2,17 +2,20 @@ from __future__ import annotations -from typing import Iterable, Optional +from typing import Dict, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr +from ..mcp_server_config_param import McpServerConfigParam __all__ = [ "AgentCreateParams", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", - "MemoryStore", + "Memory", + "MemoryAttachedStore", + "MemoryAutoMemory", "Secret", ] @@ -45,13 +48,15 @@ class AgentCreateParams(TypedDict, total=False): inference_providers: InferenceProviders """Inference provider settings used for LLM calls.""" - memory_stores: Iterable[MemoryStore] + mcp_servers: Dict[str, McpServerConfigParam] """ - Optional list of memory stores to attach to the agent. Each store must be - team-owned by the same team as the agent. Duplicate UIDs within a single request - are rejected. + Optional map of MCP server configurations by name to attach to runs executed by + this agent. Run-level MCP config takes precedence over this agent-level default. """ + memory: Memory + """Memory settings for creating an agent.""" + prompt: Optional[str] """Optional base prompt for this agent""" @@ -116,7 +121,7 @@ class InferenceProviders(TypedDict, total=False): """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" -class MemoryStore(TypedDict, total=False): +class MemoryAttachedStore(TypedDict, total=False): """Reference to a memory store to attach to an agent.""" access: Required[Literal["read_write", "read_only"]] @@ -129,6 +134,29 @@ class MemoryStore(TypedDict, total=False): """UID of the memory store.""" +class MemoryAutoMemory(TypedDict, total=False): + """Auto-memory settings for creating an agent.""" + + enabled: bool + """ + Whether to create and attach a default service-account-owned memory store for + this agent. Defaults to true when omitted. + """ + + +class Memory(TypedDict, total=False): + """Memory settings for creating an agent.""" + + attached_stores: Iterable[MemoryAttachedStore] + """ + Existing team memory stores to attach to the agent. Duplicate UIDs within a + single request are rejected. + """ + + auto_memory: MemoryAutoMemory + """Auto-memory settings for creating an agent.""" + + class Secret(TypedDict, total=False): """Reference to a managed secret by name.""" diff --git a/src/oz_agent_sdk/types/agent/agent_response.py b/src/oz_agent_sdk/types/agent/agent_response.py index db0b1bf..1ad9a40 100644 --- a/src/oz_agent_sdk/types/agent/agent_response.py +++ b/src/oz_agent_sdk/types/agent/agent_response.py @@ -1,14 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel +from ..mcp_server_config import McpServerConfig __all__ = [ "AgentResponse", - "MemoryStore", + "Memory", + "MemoryAttachedStore", + "MemoryAutoMemory", + "MemoryAutoMemoryStore", "Secret", "HarnessAuthSecrets", "InferenceProviders", @@ -16,7 +20,7 @@ ] -class MemoryStore(BaseModel): +class MemoryAttachedStore(BaseModel): """Reference to a memory store to attach to an agent.""" access: Literal["read_write", "read_only"] @@ -29,6 +33,48 @@ class MemoryStore(BaseModel): """UID of the memory store.""" +class MemoryAutoMemoryStore(BaseModel): + """Memory store attached to an agent.""" + + access: Literal["read_write", "read_only"] + """Access level for the store.""" + + instructions: str + """Instructions for how the agent should use this memory store.""" + + owner_type: Literal["user", "service_account", "team"] + """Public owner type.""" + + owner_uid: str + """Public UID of the user, service account, or team that owns the memory store.""" + + uid: str + """UID of the memory store.""" + + description: Optional[str] = None + """Optional description for the memory store.""" + + +class MemoryAutoMemory(BaseModel): + """Auto-memory state for an agent.""" + + enabled: bool + """Whether this agent has an agent-owned memory store.""" + + store: Optional[MemoryAutoMemoryStore] = None + """Memory store attached to an agent.""" + + +class Memory(BaseModel): + """Memory settings for an agent.""" + + attached_stores: List[MemoryAttachedStore] + """Team memory stores attached to the agent.""" + + auto_memory: MemoryAutoMemory + """Auto-memory state for an agent.""" + + class Secret(BaseModel): """Reference to a managed secret by name.""" @@ -87,11 +133,8 @@ class AgentResponse(BaseModel): created_at: datetime """When the agent was created (RFC3339)""" - memory_stores: List[MemoryStore] - """ - Memory stores attached to this agent. Always present; empty when no stores are - attached. - """ + memory: Memory + """Memory settings for an agent.""" name: str """Name of the agent""" @@ -108,6 +151,9 @@ class AgentResponse(BaseModel): uid: str """Unique identifier for the agent""" + updated_at: datetime + """When the agent was last updated (RFC3339)""" + base_harness: Optional[str] = None """Default harness for runs executed by this agent. @@ -150,5 +196,11 @@ class AgentResponse(BaseModel): inference_providers: Optional[InferenceProviders] = None """Inference provider settings used for LLM calls.""" + mcp_servers: Optional[Dict[str, McpServerConfig]] = None + """ + MCP server configurations attached to this agent by default. Run-level MCP + config takes precedence over this agent-level default. + """ + prompt: Optional[str] = None """Optional base prompt for this agent""" diff --git a/src/oz_agent_sdk/types/agent/agent_update_params.py b/src/oz_agent_sdk/types/agent/agent_update_params.py index fb1e36c..0d4c4d7 100644 --- a/src/oz_agent_sdk/types/agent/agent_update_params.py +++ b/src/oz_agent_sdk/types/agent/agent_update_params.py @@ -2,17 +2,19 @@ from __future__ import annotations -from typing import Iterable, Optional +from typing import Dict, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr +from ..mcp_server_config_param import McpServerConfigParam __all__ = [ "AgentUpdateParams", "HarnessAuthSecrets", "InferenceProviders", "InferenceProvidersAws", - "MemoryStore", + "Memory", + "MemoryAttachedStore", "Secret", ] @@ -51,13 +53,17 @@ class AgentUpdateParams(TypedDict, total=False): inference_providers: Optional[InferenceProviders] """Inference provider settings used for LLM calls.""" - memory_stores: Optional[Iterable[MemoryStore]] - """Replacement list of memory stores. + mcp_servers: Dict[str, McpServerConfigParam] + """Replacement map of MCP server configurations by name. - Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array - to replace. + Omit to leave unchanged, pass an empty object to clear, or pass a non-empty + object to replace. Run-level MCP config takes precedence over this agent-level + default. """ + memory: Optional[Memory] + """Memory settings for updating an agent.""" + name: str """The new name for the agent""" @@ -126,7 +132,7 @@ class InferenceProviders(TypedDict, total=False): """Configures AWS Bedrock as the LLM inference provider for this agent or run.""" -class MemoryStore(TypedDict, total=False): +class MemoryAttachedStore(TypedDict, total=False): """Reference to a memory store to attach to an agent.""" access: Required[Literal["read_write", "read_only"]] @@ -139,6 +145,17 @@ class MemoryStore(TypedDict, total=False): """UID of the memory store.""" +class Memory(TypedDict, total=False): + """Memory settings for updating an agent.""" + + attached_stores: Optional[Iterable[MemoryAttachedStore]] + """Replacement list of attached team memory stores. + + Omit to leave unchanged, pass an empty array to clear, or pass a non-empty array + to replace. + """ + + class Secret(TypedDict, total=False): """Reference to a managed secret by name.""" diff --git a/src/oz_agent_sdk/types/agent/run_item.py b/src/oz_agent_sdk/types/agent/run_item.py index 4293ce2..47231a1 100644 --- a/src/oz_agent_sdk/types/agent/run_item.py +++ b/src/oz_agent_sdk/types/agent/run_item.py @@ -173,6 +173,14 @@ class RunItem(BaseModel): executor: Optional[UserProfile] = None + is_run_type_cancellable: Optional[bool] = None + """Whether the run's type is eligible for cancellation via the API. + + State-independent: false for GitHub Action and local runs; true for all other + run types (including self-hosted). Clients should still gate the control on the + run's current state. + """ + is_sandbox_running: Optional[bool] = None """Whether the sandbox environment is currently running""" @@ -182,6 +190,12 @@ class RunItem(BaseModel): request_usage: Optional[RequestUsage] = None """Resource usage information for the run""" + run_time: Optional[str] = None + """Total runtime as an ISO 8601 duration (e.g. + + "PT2M30S"), computed server-side from run executions. + """ + schedule: Optional[Schedule] = None """ Information about the schedule that triggered this run (only present for diff --git a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py index 004341f..abc435b 100644 --- a/src/oz_agent_sdk/types/agent/run_submit_followup_params.py +++ b/src/oz_agent_sdk/types/agent/run_submit_followup_params.py @@ -2,13 +2,13 @@ from __future__ import annotations -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import Literal, TypedDict __all__ = ["RunSubmitFollowupParams"] class RunSubmitFollowupParams(TypedDict, total=False): - message: Required[str] + message: str """The follow-up message to send to the run.""" mode: Literal["normal", "plan", "orchestrate"] diff --git a/src/oz_agent_sdk/types/agent_run_params.py b/src/oz_agent_sdk/types/agent_run_params.py index fa34de8..870c2de 100644 --- a/src/oz_agent_sdk/types/agent_run_params.py +++ b/src/oz_agent_sdk/types/agent_run_params.py @@ -55,7 +55,8 @@ class AgentRunParams(TypedDict, total=False): prompt: str """ The prompt/instruction for the agent to execute. Required unless a skill is - specified via the skill field, config.skill_spec, or config.skills. + specified via the skill field, config.skill_spec, or config.skills. Handoff + requests may omit prompt when conversation_id is set. """ skill: str diff --git a/tests/api_resources/agent/test_agent_.py b/tests/api_resources/agent/test_agent_.py index d6819c5..cec38f5 100644 --- a/tests/api_resources/agent/test_agent_.py +++ b/tests/api_resources/agent/test_agent_.py @@ -48,13 +48,26 @@ def test_method_create_with_all_params(self, client: OzAPI) -> None: "role_arn": "role_arn", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", + mcp_servers={ + "foo": { + "args": ["string"], + "command": "command", + "env": {"foo": "string"}, + "headers": {"foo": "string"}, + "url": "https://example.com", + "warp_id": "warp_id", } - ], + }, + memory={ + "attached_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], + "auto_memory": {"enabled": True}, + }, prompt="prompt", secrets=[{"name": "name"}], skills=["string"], @@ -115,13 +128,25 @@ def test_method_update_with_all_params(self, client: OzAPI) -> None: "role_arn": "role_arn", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", + mcp_servers={ + "foo": { + "args": ["string"], + "command": "command", + "env": {"foo": "string"}, + "headers": {"foo": "string"}, + "url": "https://example.com", + "warp_id": "warp_id", } - ], + }, + memory={ + "attached_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ] + }, name="name", prompt="prompt", secrets=[{"name": "name"}], @@ -309,13 +334,26 @@ async def test_method_create_with_all_params(self, async_client: AsyncOzAPI) -> "role_arn": "role_arn", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", + mcp_servers={ + "foo": { + "args": ["string"], + "command": "command", + "env": {"foo": "string"}, + "headers": {"foo": "string"}, + "url": "https://example.com", + "warp_id": "warp_id", } - ], + }, + memory={ + "attached_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ], + "auto_memory": {"enabled": True}, + }, prompt="prompt", secrets=[{"name": "name"}], skills=["string"], @@ -376,13 +414,25 @@ async def test_method_update_with_all_params(self, async_client: AsyncOzAPI) -> "role_arn": "role_arn", } }, - memory_stores=[ - { - "access": "read_write", - "instructions": "instructions", - "uid": "uid", + mcp_servers={ + "foo": { + "args": ["string"], + "command": "command", + "env": {"foo": "string"}, + "headers": {"foo": "string"}, + "url": "https://example.com", + "warp_id": "warp_id", } - ], + }, + memory={ + "attached_stores": [ + { + "access": "read_write", + "instructions": "instructions", + "uid": "uid", + } + ] + }, name="name", prompt="prompt", secrets=[{"name": "name"}], diff --git a/tests/api_resources/agent/test_runs.py b/tests/api_resources/agent/test_runs.py index 6af094f..54bb08c 100644 --- a/tests/api_resources/agent/test_runs.py +++ b/tests/api_resources/agent/test_runs.py @@ -209,7 +209,6 @@ def test_path_params_list_handoff_attachments(self, client: OzAPI) -> None: def test_method_submit_followup(self, client: OzAPI) -> None: run = client.agent.runs.submit_followup( run_id="runId", - message="message", ) assert_matches_type(object, run, path=["response"]) @@ -228,7 +227,6 @@ def test_method_submit_followup_with_all_params(self, client: OzAPI) -> None: def test_raw_response_submit_followup(self, client: OzAPI) -> None: response = client.agent.runs.with_raw_response.submit_followup( run_id="runId", - message="message", ) assert response.is_closed is True @@ -241,7 +239,6 @@ def test_raw_response_submit_followup(self, client: OzAPI) -> None: def test_streaming_response_submit_followup(self, client: OzAPI) -> None: with client.agent.runs.with_streaming_response.submit_followup( run_id="runId", - message="message", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -257,7 +254,6 @@ def test_path_params_submit_followup(self, client: OzAPI) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): client.agent.runs.with_raw_response.submit_followup( run_id="", - message="message", ) @@ -453,7 +449,6 @@ async def test_path_params_list_handoff_attachments(self, async_client: AsyncOzA async def test_method_submit_followup(self, async_client: AsyncOzAPI) -> None: run = await async_client.agent.runs.submit_followup( run_id="runId", - message="message", ) assert_matches_type(object, run, path=["response"]) @@ -472,7 +467,6 @@ async def test_method_submit_followup_with_all_params(self, async_client: AsyncO async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> None: response = await async_client.agent.runs.with_raw_response.submit_followup( run_id="runId", - message="message", ) assert response.is_closed is True @@ -485,7 +479,6 @@ async def test_raw_response_submit_followup(self, async_client: AsyncOzAPI) -> N async def test_streaming_response_submit_followup(self, async_client: AsyncOzAPI) -> None: async with async_client.agent.runs.with_streaming_response.submit_followup( run_id="runId", - message="message", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -501,5 +494,4 @@ async def test_path_params_submit_followup(self, async_client: AsyncOzAPI) -> No with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"): await async_client.agent.runs.with_raw_response.submit_followup( run_id="", - message="message", )