-
Notifications
You must be signed in to change notification settings - Fork 1
SDK 0.3.0: cloud workspace client (xagent_sdk.cloud.WorkspaceClient) #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
rogercloud
merged 9 commits into
xorbitsai:main
from
AlexLiu190625:feat/0.3.0-cloud-workspace
Jun 2, 2026
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
5c64d58
refactor(base): add _DEFAULT_BASE_URL hook for per-client default URL
AlexLiu190625 11cad38
feat(cloud): WorkspaceClient + workspace agents/templates namespaces
AlexLiu190625 236cfd3
test(cloud): unit tests + surface pin for the cloud module
AlexLiu190625 07ba4c4
chore: bump SDK to 0.3.0
AlexLiu190625 4ff064c
docs(readme): cloud/workspace quickstart + e2e cloud smoke
AlexLiu190625 6372003
fix(cloud): type list params as list[str], not Sequence[str]
AlexLiu190625 7a535af
fix(templates): url-encode template_id as a single path segment
AlexLiu190625 df179b1
fix(base): resolve credentials/URL through a single None-aware helper
AlexLiu190625 9ff4374
docs(readme): sync version to 0.3.0 and fix the cloud quickstart
AlexLiu190625 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| __version__ = "0.2.0" | ||
| __version__ = "0.3.0" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| from xagent_sdk.cloud.workspace_client import WorkspaceClient | ||
|
|
||
| __all__ = ["WorkspaceClient"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| """The ``workspace.agents`` namespace exposed on ``WorkspaceClient``. | ||
|
|
||
| Agent lifecycle for a workspace-key caller: list the workspace's agents, | ||
| create new ones (structured or from a template), and mint an agent's | ||
| runtime key. Reaches the workspace-scoped ``/v1/workspace/agents*`` | ||
| endpoints; the response shapes are the same as the personal-key surface, | ||
| so the shared parsers and dataclasses in ``xagent_sdk.types`` are reused. | ||
|
|
||
| ``create()`` and ``create_from_template()`` default to | ||
| ``generate_runtime_key=True``; the returned | ||
| ``AgentCreateResult.runtime_full_key`` is a one-time secret. They fail | ||
| closed (``MalformedResponse``) if a key was requested but the response | ||
| carried none, via the shared ``_require_runtime_key`` guard. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from typing import TYPE_CHECKING, Any | ||
|
|
||
| from xagent_sdk._agents import _require_runtime_key | ||
| from xagent_sdk.types import ( | ||
| AgentCreateResult, | ||
| AgentSummary, | ||
| RotateKeyResult, | ||
| _parse_agent_create, | ||
| _parse_agent_list, | ||
| _parse_rotate_key, | ||
| ) | ||
|
|
||
| if TYPE_CHECKING: | ||
| from xagent_sdk.cloud.workspace_client import WorkspaceClient | ||
|
|
||
| # The ``list()`` method below shadows the ``list`` builtin inside this | ||
| # class, so ``list[str]`` annotations on the create methods cannot resolve | ||
| # to the builtin type. Reference it through a module-scope alias instead. | ||
| # (Do not switch these to ``Sequence[str]``: a bare ``str`` satisfies | ||
| # ``Sequence[str]`` and would slip through type checking onto the wire.) | ||
| _StrList = list[str] | ||
|
|
||
|
|
||
| def _drop_none(values: dict[str, Any]) -> dict[str, Any]: | ||
| return {k: v for k, v in values.items() if v is not None} | ||
|
|
||
|
|
||
| class WorkspaceAgentsAPI: | ||
| """The ``workspace.agents`` namespace.""" | ||
|
|
||
| def __init__(self, client: WorkspaceClient) -> None: | ||
| self._client = client | ||
|
|
||
| def list(self) -> list[AgentSummary]: | ||
| """``GET /v1/workspace/agents`` -- list the workspace's agents. | ||
|
|
||
| Returns the agents the workspace key can manage, as slim summaries | ||
| (id + name + optional status). Returns an empty list for an empty | ||
| or non-list body. Standard error mapping applies. | ||
| """ | ||
| resp = self._client._request("GET", "/v1/workspace/agents") | ||
| return _parse_agent_list(resp.json()) | ||
|
|
||
| def create( | ||
| self, | ||
| *, | ||
| name: str, | ||
| instructions: str, | ||
| description: str | None = None, | ||
| execution_mode: str | None = None, | ||
| models: dict[str, Any] | None = None, | ||
| knowledge_bases: _StrList | None = None, | ||
| skills: _StrList | None = None, | ||
| tool_categories: _StrList | None = None, | ||
| suggested_prompts: _StrList | None = None, | ||
| generate_runtime_key: bool = True, | ||
| ) -> AgentCreateResult: | ||
| """``POST /v1/workspace/agents`` -- create an agent in the workspace. | ||
|
|
||
| ``name`` and ``instructions`` are required; the remaining | ||
| agent-config fields are optional and omitted from the wire when | ||
| left as None. When ``generate_runtime_key`` is True (default) the | ||
| backend provisions a runtime key in the same transaction and | ||
| returns it via ``AgentCreateResult.runtime_full_key`` (one-time; | ||
| store in a secret vault and never log). | ||
|
|
||
| Raises: | ||
| InvalidInput: 422 -- backend rejected the body. | ||
| InvalidAPIKey: 401 -- workspace key invalid / revoked. | ||
| MalformedResponse: ``generate_runtime_key=True`` but the | ||
| response carried no runtime key (fail closed). | ||
| """ | ||
| body: dict[str, Any] = { | ||
| "name": name, | ||
| "instructions": instructions, | ||
| "generate_runtime_key": generate_runtime_key, | ||
| } | ||
| body.update( | ||
| _drop_none( | ||
| { | ||
| "description": description, | ||
| "execution_mode": execution_mode, | ||
| "models": models, | ||
| "knowledge_bases": knowledge_bases, | ||
| "skills": skills, | ||
| "tool_categories": tool_categories, | ||
| "suggested_prompts": suggested_prompts, | ||
| } | ||
| ) | ||
| ) | ||
| resp = self._client._request("POST", "/v1/workspace/agents", json=body) | ||
| return _require_runtime_key( | ||
| _parse_agent_create(resp.json()), generate_runtime_key | ||
| ) | ||
|
|
||
| def create_from_template( | ||
| self, | ||
| template_id: str, | ||
| *, | ||
| name: str | None = None, | ||
| description: str | None = None, | ||
| instructions: str | None = None, | ||
| execution_mode: str | None = None, | ||
| models: dict[str, Any] | None = None, | ||
| knowledge_bases: _StrList | None = None, | ||
| skills: _StrList | None = None, | ||
| tool_categories: _StrList | None = None, | ||
| suggested_prompts: _StrList | None = None, | ||
| generate_runtime_key: bool = True, | ||
| ) -> AgentCreateResult: | ||
| """``POST /v1/workspace/agents/from-template`` -- create from a template. | ||
|
|
||
| The backend loads the template's config and overlays the supplied | ||
| fields. Override fields are spread flat into the request body | ||
| alongside ``template_id`` and ``generate_runtime_key``; each is | ||
| omitted from the wire when left as None. The template supplies any | ||
| field not overridden, so all override fields are optional here. | ||
|
|
||
| Raises: | ||
| TemplateNotFound: 404 ``template_not_found`` -- unknown | ||
| ``template_id``. | ||
| InvalidInput: 422 -- override fields malformed. | ||
| InvalidAPIKey: 401 -- workspace key invalid / revoked. | ||
| MalformedResponse: ``generate_runtime_key=True`` but the | ||
| response carried no runtime key (fail closed). | ||
| """ | ||
| body: dict[str, Any] = { | ||
| "template_id": template_id, | ||
| "generate_runtime_key": generate_runtime_key, | ||
| } | ||
| body.update( | ||
| _drop_none( | ||
| { | ||
| "name": name, | ||
| "description": description, | ||
| "instructions": instructions, | ||
| "execution_mode": execution_mode, | ||
| "models": models, | ||
| "knowledge_bases": knowledge_bases, | ||
| "skills": skills, | ||
| "tool_categories": tool_categories, | ||
| "suggested_prompts": suggested_prompts, | ||
| } | ||
| ) | ||
| ) | ||
| resp = self._client._request( | ||
| "POST", "/v1/workspace/agents/from-template", json=body | ||
| ) | ||
| return _require_runtime_key( | ||
| _parse_agent_create(resp.json()), generate_runtime_key | ||
| ) | ||
|
|
||
| def rotate_key(self, agent_id: int) -> RotateKeyResult: | ||
| """``POST /v1/workspace/agents/{agent_id}/api-key`` -- mint the | ||
| agent's runtime key. | ||
|
|
||
| Returns a ``RotateKeyResult`` whose ``full_key`` is a one-time | ||
| runtime key (``xag_<prefix>_<secret>``) used by ``AgentClient`` to | ||
| run the agent. Rotation revokes the agent's previous runtime key. | ||
|
|
||
| Raises: | ||
| AgentNotFound: 404 -- agent not found in this workspace. | ||
| InvalidAPIKey: 401 -- workspace key invalid / revoked. | ||
| """ | ||
| resp = self._client._request("POST", f"/v1/workspace/agents/{agent_id}/api-key") | ||
| return _parse_rotate_key(resp.json()) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bumps the package to 0.3.0, but
python/README.mdstill says the SDK status is 0.2.0 and the install command still pins@v0.2.0; the root README also still lists the Python client as 0.1.0. Anyone following the README will install a version that does not contain the newxagent_sdk.cloud.WorkspaceClientmodule, so the new example fails at import time. Please update the README status/install tag to v0.3.0 and sync the root README version as well.