agenttier 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,78 @@
1
+ # Go
2
+ bin/
3
+ _output/
4
+ vendor/
5
+ *.exe
6
+ *.exe~
7
+ *.dll
8
+ *.so
9
+ *.dylib
10
+ *.test
11
+ *.out
12
+ coverage.out
13
+ coverage.html
14
+
15
+ # Compiled binaries
16
+ /controller
17
+ /router
18
+
19
+ # IDE
20
+ .idea/
21
+ .vscode/
22
+ *.swp
23
+ *.swo
24
+ *~
25
+ .DS_Store
26
+
27
+ # Kiro (internal development tooling)
28
+ .kiro/
29
+
30
+ # Local working todo (not shipped)
31
+ /todo.md
32
+
33
+ # Node.js (web-ui)
34
+ web-ui/node_modules/
35
+ web-ui/dist/
36
+ web-ui/.env.local
37
+ web-ui/.env.*.local
38
+
39
+ # Python (SDK)
40
+ python-sdk/**/__pycache__/
41
+ python-sdk/*.egg-info/
42
+ python-sdk/dist/
43
+ python-sdk/build/
44
+ python-sdk/.venv/
45
+ python-sdk/.env
46
+ python-sdk/.pytest_cache/
47
+ python-sdk/.mypy_cache/
48
+ python-sdk/.ruff_cache/
49
+
50
+ # Environment
51
+ .env
52
+ .env.local
53
+ *.log
54
+
55
+ # Kubernetes
56
+ kubeconfig
57
+ *.kubeconfig
58
+
59
+ # Terraform
60
+ terraform/**/.terraform/
61
+ terraform/**/*.tfstate
62
+ terraform/**/*.tfstate.backup
63
+ terraform/**/*.tfvars
64
+ !terraform/**/*.tfvars.example
65
+ terraform/**/tfplan
66
+
67
+ # Helm
68
+ helm/agenttier/charts/
69
+
70
+ # Build artifacts
71
+ dist/
72
+ tmp/
73
+
74
+ # Test
75
+ testbin/
76
+
77
+ # OS files
78
+ Thumbs.db
@@ -0,0 +1,137 @@
1
+ Metadata-Version: 2.4
2
+ Name: agenttier
3
+ Version: 0.1.1
4
+ Summary: Python SDK for AgentTier — manage isolated AI agent sandboxes on Kubernetes
5
+ Project-URL: Homepage, https://github.com/agenttier/agenttier
6
+ Project-URL: Documentation, https://agenttier.github.io/agenttier/sdk/
7
+ Project-URL: Repository, https://github.com/agenttier/agenttier
8
+ Project-URL: Issues, https://github.com/agenttier/agenttier/issues
9
+ Project-URL: Changelog, https://github.com/agenttier/agenttier/blob/main/CHANGELOG.md
10
+ Author: AgentTier Authors
11
+ License-Expression: Apache-2.0
12
+ Keywords: agents,ai-agents,developer-tools,kubernetes,sandbox
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Software Development :: Libraries
23
+ Classifier: Topic :: System :: Clustering
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.10
26
+ Requires-Dist: httpx<1.0,>=0.27.0
27
+ Requires-Dist: pydantic<3.0,>=2.0.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: mypy>=1.10; extra == 'dev'
30
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
31
+ Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.5; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # AgentTier Python SDK
37
+
38
+ Programmatic client for [AgentTier](https://github.com/agenttier/agenttier) —
39
+ manage isolated, persistent Kubernetes sandboxes for AI agents from Python.
40
+
41
+ ```
42
+ pip install agenttier
43
+ ```
44
+
45
+ ## Synchronous quick start
46
+
47
+ ```python
48
+ from agenttier import AgentTierClient
49
+
50
+ with AgentTierClient(api_url="https://agenttier.company.com") as client:
51
+ sandbox = client.create_sandbox(template="general-coding", name="demo")
52
+ sandbox.wait_until_running()
53
+
54
+ result = sandbox.exec("echo 'hello from AgentTier'")
55
+ print(result.stdout, "exit", result.exit_code)
56
+
57
+ port = sandbox.forward_port(8080)
58
+ print("Forwarded:", port.preview_url or port.internal_url)
59
+
60
+ sandbox.terminate()
61
+ ```
62
+
63
+ ## Async
64
+
65
+ ```python
66
+ import asyncio
67
+ from agenttier import AsyncAgentTierClient
68
+
69
+ async def main():
70
+ async with AsyncAgentTierClient(api_url="https://agenttier.company.com") as client:
71
+ sandbox = await client.create_sandbox(template="general-coding", name="demo")
72
+ await sandbox.wait_until_running()
73
+ result = await sandbox.exec("uname -a")
74
+ print(result.stdout)
75
+ await sandbox.terminate()
76
+
77
+ asyncio.run(main())
78
+ ```
79
+
80
+ ## Authentication
81
+
82
+ The SDK auto-detects credentials in this order:
83
+
84
+ 1. `AGENTTIER_API_KEY` — sent as `X-API-Key`.
85
+ 2. `AGENTTIER_TOKEN` — sent as `Authorization: Bearer <token>` (OIDC JWT).
86
+ 3. In-cluster ServiceAccount token at `/var/run/secrets/kubernetes.io/serviceaccount/token`.
87
+ 4. Unauthenticated (accepted only in the Router's dev mode).
88
+
89
+ Or pass an explicit provider:
90
+
91
+ ```python
92
+ from agenttier import AgentTierClient, APIKeyAuth, BearerTokenAuth
93
+
94
+ client = AgentTierClient(
95
+ api_url="https://agenttier.company.com",
96
+ auth=APIKeyAuth("sk_live_..."),
97
+ )
98
+ ```
99
+
100
+ ## Error handling
101
+
102
+ Every error inherits from `AgentTierError` so you can catch them all at once.
103
+ The common subclasses you'll want to handle individually:
104
+
105
+ | Exception | When |
106
+ | --- | --- |
107
+ | `AuthenticationError` | 401 — token / API key missing or invalid |
108
+ | `AuthorizationError` | 403 — authenticated but not permitted |
109
+ | `PolicyViolationError` | 403 with governance body; exposes `.violations` |
110
+ | `NotFoundError` | 404 — resource doesn't exist |
111
+ | `ConflictError` | 409 — operation invalid for current state |
112
+ | `SandboxTimeoutError` | `wait_until_running` timed out |
113
+ | `SandboxErrorState` | sandbox entered the `Error` phase while waiting |
114
+ | `APIError` | anything else; carries `.status_code` and `.body` |
115
+
116
+ ## Supported API surface (v0.1.1)
117
+
118
+ Only endpoints that the Router server implements in v0.1.0 are exposed:
119
+
120
+ - **Sandboxes** — `create_sandbox`, `list_sandboxes`, `get_sandbox`, `stop`,
121
+ `resume`, `terminate`, `exec`, `wait_until_running`, `status`.
122
+ - **Port forwarding** — `forward_port`, `list_ports`, `remove_port`.
123
+ - **Templates** — `list_templates`, `get_template`.
124
+ - **Identity** — `current_user`.
125
+
126
+ Endpoints that are not yet implemented on the server (file transfer, sharing,
127
+ cloning, WebSocket terminal from Python) are **not exposed** by the SDK and
128
+ will be added in a future release once the server ships them.
129
+
130
+ ## Supported Python versions
131
+
132
+ 3.10, 3.11, 3.12, 3.13. Runtime dependencies: `httpx` and `pydantic`.
133
+
134
+ ## License
135
+
136
+ Apache-2.0. Source at
137
+ [github.com/agenttier/agenttier/tree/main/python-sdk](https://github.com/agenttier/agenttier/tree/main/python-sdk).
@@ -0,0 +1,102 @@
1
+ # AgentTier Python SDK
2
+
3
+ Programmatic client for [AgentTier](https://github.com/agenttier/agenttier) —
4
+ manage isolated, persistent Kubernetes sandboxes for AI agents from Python.
5
+
6
+ ```
7
+ pip install agenttier
8
+ ```
9
+
10
+ ## Synchronous quick start
11
+
12
+ ```python
13
+ from agenttier import AgentTierClient
14
+
15
+ with AgentTierClient(api_url="https://agenttier.company.com") as client:
16
+ sandbox = client.create_sandbox(template="general-coding", name="demo")
17
+ sandbox.wait_until_running()
18
+
19
+ result = sandbox.exec("echo 'hello from AgentTier'")
20
+ print(result.stdout, "exit", result.exit_code)
21
+
22
+ port = sandbox.forward_port(8080)
23
+ print("Forwarded:", port.preview_url or port.internal_url)
24
+
25
+ sandbox.terminate()
26
+ ```
27
+
28
+ ## Async
29
+
30
+ ```python
31
+ import asyncio
32
+ from agenttier import AsyncAgentTierClient
33
+
34
+ async def main():
35
+ async with AsyncAgentTierClient(api_url="https://agenttier.company.com") as client:
36
+ sandbox = await client.create_sandbox(template="general-coding", name="demo")
37
+ await sandbox.wait_until_running()
38
+ result = await sandbox.exec("uname -a")
39
+ print(result.stdout)
40
+ await sandbox.terminate()
41
+
42
+ asyncio.run(main())
43
+ ```
44
+
45
+ ## Authentication
46
+
47
+ The SDK auto-detects credentials in this order:
48
+
49
+ 1. `AGENTTIER_API_KEY` — sent as `X-API-Key`.
50
+ 2. `AGENTTIER_TOKEN` — sent as `Authorization: Bearer <token>` (OIDC JWT).
51
+ 3. In-cluster ServiceAccount token at `/var/run/secrets/kubernetes.io/serviceaccount/token`.
52
+ 4. Unauthenticated (accepted only in the Router's dev mode).
53
+
54
+ Or pass an explicit provider:
55
+
56
+ ```python
57
+ from agenttier import AgentTierClient, APIKeyAuth, BearerTokenAuth
58
+
59
+ client = AgentTierClient(
60
+ api_url="https://agenttier.company.com",
61
+ auth=APIKeyAuth("sk_live_..."),
62
+ )
63
+ ```
64
+
65
+ ## Error handling
66
+
67
+ Every error inherits from `AgentTierError` so you can catch them all at once.
68
+ The common subclasses you'll want to handle individually:
69
+
70
+ | Exception | When |
71
+ | --- | --- |
72
+ | `AuthenticationError` | 401 — token / API key missing or invalid |
73
+ | `AuthorizationError` | 403 — authenticated but not permitted |
74
+ | `PolicyViolationError` | 403 with governance body; exposes `.violations` |
75
+ | `NotFoundError` | 404 — resource doesn't exist |
76
+ | `ConflictError` | 409 — operation invalid for current state |
77
+ | `SandboxTimeoutError` | `wait_until_running` timed out |
78
+ | `SandboxErrorState` | sandbox entered the `Error` phase while waiting |
79
+ | `APIError` | anything else; carries `.status_code` and `.body` |
80
+
81
+ ## Supported API surface (v0.1.1)
82
+
83
+ Only endpoints that the Router server implements in v0.1.0 are exposed:
84
+
85
+ - **Sandboxes** — `create_sandbox`, `list_sandboxes`, `get_sandbox`, `stop`,
86
+ `resume`, `terminate`, `exec`, `wait_until_running`, `status`.
87
+ - **Port forwarding** — `forward_port`, `list_ports`, `remove_port`.
88
+ - **Templates** — `list_templates`, `get_template`.
89
+ - **Identity** — `current_user`.
90
+
91
+ Endpoints that are not yet implemented on the server (file transfer, sharing,
92
+ cloning, WebSocket terminal from Python) are **not exposed** by the SDK and
93
+ will be added in a future release once the server ships them.
94
+
95
+ ## Supported Python versions
96
+
97
+ 3.10, 3.11, 3.12, 3.13. Runtime dependencies: `httpx` and `pydantic`.
98
+
99
+ ## License
100
+
101
+ Apache-2.0. Source at
102
+ [github.com/agenttier/agenttier/tree/main/python-sdk](https://github.com/agenttier/agenttier/tree/main/python-sdk).
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright 2024 AgentTier Authors.
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """Basic usage example for the AgentTier Python SDK.
6
+
7
+ Before running: set ``AGENTTIER_API_KEY`` or ``AGENTTIER_TOKEN`` (or run the
8
+ Router in dev mode locally) and update ``API_URL`` below.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from agenttier import AgentTierClient
14
+
15
+ API_URL = "http://localhost:8080" # or https://agenttier.company.com in production
16
+
17
+
18
+ def main() -> None:
19
+ with AgentTierClient(api_url=API_URL) as client:
20
+ print("Authenticated as:", client.current_user())
21
+
22
+ print("Available templates:")
23
+ for template in client.list_templates():
24
+ print(f" - {template.name}: {template.description or '(no description)'}")
25
+
26
+ sandbox = client.create_sandbox(template="general-coding", name="sdk-demo")
27
+ print(f"Created sandbox {sandbox.id}; waiting for Running…")
28
+ sandbox.wait_until_running()
29
+
30
+ result = sandbox.exec("echo 'Hello from AgentTier!'")
31
+ print(f"stdout: {result.stdout.strip()}")
32
+ print(f"exit: {result.exit_code}")
33
+
34
+ sandbox.terminate()
35
+ print("Terminated.")
36
+
37
+
38
+ if __name__ == "__main__":
39
+ main()
@@ -0,0 +1,68 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "agenttier"
7
+ # Source of truth is src/agenttier/_version.py — keep both in sync on release.
8
+ version = "0.1.1"
9
+ description = "Python SDK for AgentTier — manage isolated AI agent sandboxes on Kubernetes"
10
+ readme = "README.md"
11
+ license = "Apache-2.0"
12
+ requires-python = ">=3.10"
13
+ authors = [
14
+ { name = "AgentTier Authors" },
15
+ ]
16
+ keywords = ["kubernetes", "sandbox", "ai-agents", "developer-tools", "agents"]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Intended Audience :: Developers",
20
+ "License :: OSI Approved :: Apache Software License",
21
+ "Operating System :: OS Independent",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Topic :: Software Development :: Libraries",
28
+ "Topic :: System :: Clustering",
29
+ "Typing :: Typed",
30
+ ]
31
+ dependencies = [
32
+ "httpx>=0.27.0,<1.0",
33
+ "pydantic>=2.0.0,<3.0",
34
+ ]
35
+
36
+ [project.optional-dependencies]
37
+ dev = [
38
+ "pytest>=8.0",
39
+ "pytest-asyncio>=0.23",
40
+ "pytest-httpx>=0.30",
41
+ "ruff>=0.5",
42
+ "mypy>=1.10",
43
+ ]
44
+
45
+ [project.urls]
46
+ Homepage = "https://github.com/agenttier/agenttier"
47
+ Documentation = "https://agenttier.github.io/agenttier/sdk/"
48
+ Repository = "https://github.com/agenttier/agenttier"
49
+ Issues = "https://github.com/agenttier/agenttier/issues"
50
+ Changelog = "https://github.com/agenttier/agenttier/blob/main/CHANGELOG.md"
51
+
52
+ [tool.hatch.build.targets.wheel]
53
+ packages = ["src/agenttier"]
54
+
55
+ [tool.hatch.build.targets.wheel.force-include]
56
+ "src/agenttier/py.typed" = "agenttier/py.typed"
57
+
58
+ [tool.ruff]
59
+ target-version = "py310"
60
+ line-length = 100
61
+
62
+ [tool.mypy]
63
+ python_version = "3.10"
64
+ strict = true
65
+
66
+ [tool.pytest.ini_options]
67
+ testpaths = ["tests"]
68
+ asyncio_mode = "auto"
@@ -0,0 +1,83 @@
1
+ # Copyright 2024 AgentTier Authors.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """AgentTier Python SDK.
5
+
6
+ Manage isolated AI agent sandboxes on Kubernetes from Python.
7
+
8
+ Typical usage::
9
+
10
+ from agenttier import AgentTierClient
11
+
12
+ with AgentTierClient(api_url="https://agenttier.company.com") as client:
13
+ sandbox = client.create_sandbox(template="general-coding", name="demo")
14
+ sandbox.wait_until_running()
15
+ print(sandbox.exec("uname -a").stdout)
16
+ sandbox.terminate()
17
+
18
+ See :mod:`agenttier.async_client` for the ``async/await`` variant.
19
+ """
20
+
21
+ from agenttier._version import __version__
22
+ from agenttier.async_client import AsyncAgentTierClient
23
+ from agenttier.async_sandbox import AsyncSandbox
24
+ from agenttier.auth import APIKeyAuth, AuthProvider, BearerTokenAuth, KubeconfigAuth
25
+ from agenttier.client import AgentTierClient
26
+ from agenttier.exceptions import (
27
+ AgentTierError,
28
+ APIError,
29
+ AuthenticationError,
30
+ AuthorizationError,
31
+ ConflictError,
32
+ NotFoundError,
33
+ PolicyViolationError,
34
+ SandboxErrorState,
35
+ SandboxTimeoutError,
36
+ )
37
+ from agenttier.models import (
38
+ AuditEvent,
39
+ CommandResult,
40
+ CreatedBy,
41
+ CurrentUser,
42
+ ForwardedPort,
43
+ SandboxPhase,
44
+ SandboxSummary,
45
+ Template,
46
+ UsageAnalytics,
47
+ )
48
+ from agenttier.sandbox import Sandbox
49
+
50
+ __all__ = [
51
+ "__version__",
52
+ # Clients
53
+ "AgentTierClient",
54
+ "AsyncAgentTierClient",
55
+ # Handles
56
+ "Sandbox",
57
+ "AsyncSandbox",
58
+ # Auth
59
+ "AuthProvider",
60
+ "APIKeyAuth",
61
+ "BearerTokenAuth",
62
+ "KubeconfigAuth",
63
+ # Models
64
+ "AuditEvent",
65
+ "CommandResult",
66
+ "CreatedBy",
67
+ "CurrentUser",
68
+ "ForwardedPort",
69
+ "SandboxPhase",
70
+ "SandboxSummary",
71
+ "Template",
72
+ "UsageAnalytics",
73
+ # Exceptions
74
+ "AgentTierError",
75
+ "APIError",
76
+ "AuthenticationError",
77
+ "AuthorizationError",
78
+ "ConflictError",
79
+ "NotFoundError",
80
+ "PolicyViolationError",
81
+ "SandboxErrorState",
82
+ "SandboxTimeoutError",
83
+ ]
@@ -0,0 +1,74 @@
1
+ # Copyright 2024 AgentTier Authors.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """Internal HTTP utilities.
5
+
6
+ Kept private (underscore prefix) so we can change the shape freely without a
7
+ compat guarantee. The public clients are the only consumers.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import Any
13
+
14
+ import httpx
15
+
16
+ from agenttier.exceptions import (
17
+ APIError,
18
+ AuthenticationError,
19
+ AuthorizationError,
20
+ ConflictError,
21
+ NotFoundError,
22
+ PolicyViolationError,
23
+ )
24
+
25
+
26
+ def _decode_body(response: httpx.Response) -> Any:
27
+ """Return a JSON body, a text body, or None, whichever succeeds."""
28
+ if not response.content:
29
+ return None
30
+ try:
31
+ return response.json()
32
+ except ValueError:
33
+ return response.text or None
34
+
35
+
36
+ def raise_for_status(response: httpx.Response) -> None:
37
+ """Translate non-2xx responses into typed SDK exceptions.
38
+
39
+ The Router returns structured JSON error bodies (``{"error": ..., ...}``)
40
+ so we can offer crisp exception types without parsing error strings.
41
+ """
42
+ if response.is_success:
43
+ return
44
+
45
+ body = _decode_body(response)
46
+ status = response.status_code
47
+ message = _extract_message(body, response.reason_phrase)
48
+
49
+ if status == 401:
50
+ raise AuthenticationError(message)
51
+ if status == 403:
52
+ if isinstance(body, dict) and body.get("error") == "policy_violation":
53
+ raise PolicyViolationError(message, list(body.get("violations", [])))
54
+ raise AuthorizationError(message)
55
+ if status == 404:
56
+ raise NotFoundError(message)
57
+ if status == 409:
58
+ raise ConflictError(message)
59
+ raise APIError(status, message, body)
60
+
61
+
62
+ def _extract_message(body: Any, fallback: str) -> str:
63
+ if isinstance(body, dict):
64
+ for key in ("error", "message"):
65
+ v = body.get(key)
66
+ if isinstance(v, str) and v:
67
+ return v
68
+ if isinstance(body, str) and body:
69
+ return body
70
+ return fallback or "request failed"
71
+
72
+
73
+ def default_user_agent(version: str) -> str:
74
+ return f"agenttier-python-sdk/{version}"
@@ -0,0 +1,11 @@
1
+ # Copyright 2024 AgentTier Authors.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """Single source of truth for the SDK version string.
5
+
6
+ Kept in a separate module so ``pyproject.toml`` and :mod:`agenttier` can both
7
+ import it without circular dependencies. Release tooling reads this file when
8
+ bumping versions; keep the identifier named ``__version__``.
9
+ """
10
+
11
+ __version__ = "0.1.1"