akribes 0.21.17__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.
Files changed (69) hide show
  1. akribes-0.21.17/LICENSE +21 -0
  2. akribes-0.21.17/PKG-INFO +236 -0
  3. akribes-0.21.17/README.md +195 -0
  4. akribes-0.21.17/akribes.egg-info/PKG-INFO +236 -0
  5. akribes-0.21.17/akribes.egg-info/SOURCES.txt +67 -0
  6. akribes-0.21.17/akribes.egg-info/dependency_links.txt +1 -0
  7. akribes-0.21.17/akribes.egg-info/requires.txt +15 -0
  8. akribes-0.21.17/akribes.egg-info/top_level.txt +1 -0
  9. akribes-0.21.17/akribes_sdk/__init__.py +365 -0
  10. akribes-0.21.17/akribes_sdk/_handles.py +279 -0
  11. akribes-0.21.17/akribes_sdk/_otel.py +54 -0
  12. akribes-0.21.17/akribes_sdk/_pagination.py +70 -0
  13. akribes-0.21.17/akribes_sdk/_parsers.py +690 -0
  14. akribes-0.21.17/akribes_sdk/_retry.py +138 -0
  15. akribes-0.21.17/akribes_sdk/_timing.py +23 -0
  16. akribes-0.21.17/akribes_sdk/_token_safety.py +32 -0
  17. akribes-0.21.17/akribes_sdk/_transport.py +333 -0
  18. akribes-0.21.17/akribes_sdk/client.py +540 -0
  19. akribes-0.21.17/akribes_sdk/errors.py +438 -0
  20. akribes-0.21.17/akribes_sdk/ingest_handle.py +109 -0
  21. akribes-0.21.17/akribes_sdk/models.py +1392 -0
  22. akribes-0.21.17/akribes_sdk/py.typed +0 -0
  23. akribes-0.21.17/akribes_sdk/resources/__init__.py +34 -0
  24. akribes-0.21.17/akribes_sdk/resources/_base.py +95 -0
  25. akribes-0.21.17/akribes_sdk/resources/_sentinel.py +23 -0
  26. akribes-0.21.17/akribes_sdk/resources/channels.py +46 -0
  27. akribes-0.21.17/akribes_sdk/resources/clients.py +78 -0
  28. akribes-0.21.17/akribes_sdk/resources/documents.py +423 -0
  29. akribes-0.21.17/akribes_sdk/resources/drafts.py +32 -0
  30. akribes-0.21.17/akribes_sdk/resources/evals.py +226 -0
  31. akribes-0.21.17/akribes_sdk/resources/events.py +782 -0
  32. akribes-0.21.17/akribes_sdk/resources/executions.py +560 -0
  33. akribes-0.21.17/akribes_sdk/resources/mcp.py +57 -0
  34. akribes-0.21.17/akribes_sdk/resources/me.py +26 -0
  35. akribes-0.21.17/akribes_sdk/resources/projects.py +164 -0
  36. akribes-0.21.17/akribes_sdk/resources/scripts.py +88 -0
  37. akribes-0.21.17/akribes_sdk/resources/tokens.py +86 -0
  38. akribes-0.21.17/akribes_sdk/resources/versions.py +88 -0
  39. akribes-0.21.17/akribes_sdk/run_stream.py +492 -0
  40. akribes-0.21.17/akribes_sdk/script_type.py +51 -0
  41. akribes-0.21.17/akribes_sdk/types.py +78 -0
  42. akribes-0.21.17/akribes_sdk/workflow_events.py +1079 -0
  43. akribes-0.21.17/pyproject.toml +63 -0
  44. akribes-0.21.17/setup.cfg +4 -0
  45. akribes-0.21.17/tests/test_backoff.py +42 -0
  46. akribes-0.21.17/tests/test_client.py +1688 -0
  47. akribes-0.21.17/tests/test_documents.py +519 -0
  48. akribes-0.21.17/tests/test_dx_improvements.py +726 -0
  49. akribes-0.21.17/tests/test_errors.py +110 -0
  50. akribes-0.21.17/tests/test_evals.py +69 -0
  51. akribes-0.21.17/tests/test_events.py +340 -0
  52. akribes-0.21.17/tests/test_execution_ergonomics.py +333 -0
  53. akribes-0.21.17/tests/test_ingest_handle.py +226 -0
  54. akribes-0.21.17/tests/test_mcp.py +174 -0
  55. akribes-0.21.17/tests/test_models_dataclass.py +713 -0
  56. akribes-0.21.17/tests/test_otel.py +164 -0
  57. akribes-0.21.17/tests/test_pagination.py +260 -0
  58. akribes-0.21.17/tests/test_retry_policy.py +336 -0
  59. akribes-0.21.17/tests/test_run_stream.py +312 -0
  60. akribes-0.21.17/tests/test_runtime_events.py +545 -0
  61. akribes-0.21.17/tests/test_sandbox.py +137 -0
  62. akribes-0.21.17/tests/test_script_type.py +289 -0
  63. akribes-0.21.17/tests/test_smoke_integration.py +136 -0
  64. akribes-0.21.17/tests/test_suspend_trigger.py +363 -0
  65. akribes-0.21.17/tests/test_token_safety.py +27 -0
  66. akribes-0.21.17/tests/test_validation_failure.py +130 -0
  67. akribes-0.21.17/tests/test_workflow_events.py +379 -0
  68. akribes-0.21.17/tests/test_workflow_events_dataclass.py +383 -0
  69. akribes-0.21.17/tests/test_ws_transport.py +354 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Podesta
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: akribes
3
+ Version: 0.21.17
4
+ Summary: Pythonic async client for the Akribes workflow server
5
+ Author-email: Podesta <info@podesta.ai>
6
+ License: MIT
7
+ Project-URL: Homepage, https://akribes.ai
8
+ Project-URL: Repository, https://github.com/PodestaAI/akribes-sdks
9
+ Project-URL: Documentation, https://akribes.ai
10
+ Project-URL: Issues, https://github.com/PodestaAI/akribes-sdks/issues
11
+ Project-URL: Changelog, https://github.com/PodestaAI/akribes-sdks/blob/main/packages/akribes-sdk-python/CHANGELOG.md
12
+ Keywords: akribes,llm,ai-workflows,agent,dsl,sdk
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT 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 :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: httpx>=0.27.0
28
+ Requires-Dist: httpx-sse>=0.4.0
29
+ Requires-Dist: pydantic>=2.6
30
+ Requires-Dist: typing-extensions>=4.10
31
+ Requires-Dist: websockets>=12.0
32
+ Provides-Extra: otel
33
+ Requires-Dist: opentelemetry-api>=1.20; extra == "otel"
34
+ Provides-Extra: test
35
+ Requires-Dist: pytest>=8.0.0; extra == "test"
36
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "test"
37
+ Requires-Dist: respx>=0.21.0; extra == "test"
38
+ Requires-Dist: opentelemetry-api>=1.20; extra == "test"
39
+ Requires-Dist: opentelemetry-sdk>=1.20; extra == "test"
40
+ Dynamic: license-file
41
+
42
+ # akribes
43
+
44
+ Pythonic async client for the [Akribes](https://akribes.ai) workflow server.
45
+
46
+ Requires Python 3.10+.
47
+
48
+ ## Install
49
+
50
+ ```bash
51
+ pip install akribes
52
+ # or with optional OpenTelemetry support:
53
+ pip install 'akribes[otel]'
54
+ ```
55
+
56
+ ## Quick start
57
+
58
+ ```python
59
+ import asyncio
60
+ from akribes_sdk import AkribesClient
61
+
62
+ async def main():
63
+ async with AkribesClient("https://akribes.example.com", token="akribes_tk_...") as client:
64
+ proj = client.project(2)
65
+ output = await proj.script("summarize").run_and_await(brief="explain quantum")
66
+ print(output.execution_id, output.result)
67
+
68
+ asyncio.run(main())
69
+ ```
70
+
71
+ ## Construction
72
+
73
+ ```python
74
+ import os
75
+ from datetime import timedelta
76
+ from akribes_sdk import AkribesClient, RetryPolicy
77
+
78
+ client = AkribesClient(
79
+ "https://akribes.example.com",
80
+ token=os.environ["AKRIBES_TOKEN"],
81
+ timeout=timedelta(seconds=30),
82
+ retry=RetryPolicy(max_attempts=4), # retries transients + 429 by default
83
+ otel=True, # opt-in OTel auto-instrumentation
84
+ )
85
+ ```
86
+
87
+ ## Project handles
88
+
89
+ ```python
90
+ proj = client.project(2) # sync, lazy
91
+ proj = await client.get_project("podesta-staging") # async, resolves name → id
92
+ sandbox = await client.sandbox() # per-user sandbox project
93
+ ```
94
+
95
+ ## Typed inputs (codegen)
96
+
97
+ Generate typed `ScriptType[I, O]` stubs from a live server:
98
+
99
+ ```bash
100
+ akribes types pull --project podesta --lang python --out src/akribes_types/
101
+ ```
102
+
103
+ Then:
104
+
105
+ ```python
106
+ from akribes_types.podesta import summarize # ScriptType[I, O] with typed input/output
107
+
108
+ out = await proj.run(summarize, brief="hi", tone="formal")
109
+ # IDE knows brief: str, tone: Literal["formal","casual"]
110
+ print(out.execution_id, out.result)
111
+ ```
112
+
113
+ ## Streaming
114
+
115
+ ```python
116
+ run = await proj.executions.run_stream("summarize", brief="hi")
117
+ async for evt in run:
118
+ match evt.kind:
119
+ case "agent_chunk": print(evt.chunk, end="")
120
+ case "task_end": print(f"\n[task {evt.task!r} done]")
121
+ case "error": print(f"\n[error {evt.message}]")
122
+ output = await run.output()
123
+ ```
124
+
125
+ ## Document ingest
126
+
127
+ ```python
128
+ from pathlib import Path
129
+
130
+ # One-liner
131
+ result = await proj.documents.ingest_and_wait(Path("invoice.pdf"))
132
+
133
+ # With progress
134
+ handle = proj.documents.ingest(Path("invoice.pdf"))
135
+ async for evt in handle:
136
+ print(evt)
137
+ result = await handle.result()
138
+ ```
139
+
140
+ ## Subscribe (long-lived events)
141
+
142
+ ```python
143
+ async with proj.events.subscribe(interests=[{"script_name": "summarize"}]) as sub:
144
+ async for evt in sub:
145
+ print(evt)
146
+ ```
147
+
148
+ Heartbeat runs for the lifetime of the subscription only — not automatically on client construction.
149
+
150
+ ## Pagination
151
+
152
+ ```python
153
+ async for script in proj.scripts.list():
154
+ print(script.name)
155
+
156
+ # Or materialise
157
+ scripts = await proj.scripts.list().to_list()
158
+ first = await proj.scripts.list().first()
159
+ top10 = await proj.scripts.list().take(10)
160
+ ```
161
+
162
+ ## Error handling
163
+
164
+ ```python
165
+ from akribes_sdk import (
166
+ AkribesError, AuthError, NotFoundError, TransientError,
167
+ RateLimitError, ScriptError, AkribesTimeoutError,
168
+ )
169
+
170
+ try:
171
+ output = await proj.run_and_await("summarize", brief="hi")
172
+ except AuthError: # 401/403
173
+ ...
174
+ except NotFoundError: # 404
175
+ ...
176
+ except TransientError: # 502/503 (retried by default)
177
+ ...
178
+ except RateLimitError: # 429 (retried by default, respects Retry-After)
179
+ ...
180
+ except ScriptError as e: # workflow failed; e.error_kind, e.execution_id
181
+ ...
182
+ ```
183
+
184
+ ## Tokens
185
+
186
+ ```python
187
+ from datetime import timedelta
188
+ minted = await client.tokens.mint(
189
+ scopes={"projects": "*", "role": "admin"},
190
+ expires_in=timedelta(hours=8),
191
+ label="web-session",
192
+ user_email="alice@acme.com",
193
+ )
194
+ print(minted.token) # ship to the browser
195
+ ```
196
+
197
+ ## Authentication
198
+
199
+ `AkribesClient` accepts either a **service token** (long-lived, set via
200
+ `AKRIBES_SERVICE_TOKEN_<NAME>=<scope>:<secret>` on the server) or a **scoped
201
+ token** (`akribes_tk_...` — legacy `aura_tk_...` still accepted — minted
202
+ via `client.tokens.mint(...)`).
203
+
204
+ ### Prefer `Authorization: Bearer` over `?token=…` (#789)
205
+
206
+ `AkribesClient` always sends the token in the `Authorization` header
207
+ for HTTP requests and WebSocket upgrades. The `?token=…` query-string
208
+ form exists only because browser `EventSource` / `WebSocket`
209
+ constructors cannot set arbitrary headers — treat it as a browser-only
210
+ escape hatch.
211
+
212
+ For CLIs, scripts, and backend services, avoid `?token=…` because:
213
+
214
+ - Reverse proxies, ingress controllers, and CDNs log the full URL
215
+ (including the token) in access logs by default.
216
+ - CI runners (Forgejo Actions, GitHub Actions) echo `curl` commands
217
+ into job logs.
218
+ - Browsers leak `?token=` in the `Referer` header on cross-origin
219
+ sub-resource requests.
220
+
221
+ The server stamps `X-Token-Source: query-param` on responses to any
222
+ request that used the query fallback so operators can chart adoption.
223
+
224
+ ---
225
+
226
+ See `examples/` for runnable end-to-end demos.
227
+
228
+ Upgrading from v0.20.x? See [MIGRATION-0.21.md](./MIGRATION-0.21.md).
229
+
230
+ - Source mirror: <https://github.com/PodestaAI/akribes-sdks>
231
+ - Language guide: <https://akribes.ai/docs>
232
+ - Issues: <https://github.com/PodestaAI/akribes-sdks/issues>
233
+
234
+ ## License
235
+
236
+ MIT
@@ -0,0 +1,195 @@
1
+ # akribes
2
+
3
+ Pythonic async client for the [Akribes](https://akribes.ai) workflow server.
4
+
5
+ Requires Python 3.10+.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install akribes
11
+ # or with optional OpenTelemetry support:
12
+ pip install 'akribes[otel]'
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```python
18
+ import asyncio
19
+ from akribes_sdk import AkribesClient
20
+
21
+ async def main():
22
+ async with AkribesClient("https://akribes.example.com", token="akribes_tk_...") as client:
23
+ proj = client.project(2)
24
+ output = await proj.script("summarize").run_and_await(brief="explain quantum")
25
+ print(output.execution_id, output.result)
26
+
27
+ asyncio.run(main())
28
+ ```
29
+
30
+ ## Construction
31
+
32
+ ```python
33
+ import os
34
+ from datetime import timedelta
35
+ from akribes_sdk import AkribesClient, RetryPolicy
36
+
37
+ client = AkribesClient(
38
+ "https://akribes.example.com",
39
+ token=os.environ["AKRIBES_TOKEN"],
40
+ timeout=timedelta(seconds=30),
41
+ retry=RetryPolicy(max_attempts=4), # retries transients + 429 by default
42
+ otel=True, # opt-in OTel auto-instrumentation
43
+ )
44
+ ```
45
+
46
+ ## Project handles
47
+
48
+ ```python
49
+ proj = client.project(2) # sync, lazy
50
+ proj = await client.get_project("podesta-staging") # async, resolves name → id
51
+ sandbox = await client.sandbox() # per-user sandbox project
52
+ ```
53
+
54
+ ## Typed inputs (codegen)
55
+
56
+ Generate typed `ScriptType[I, O]` stubs from a live server:
57
+
58
+ ```bash
59
+ akribes types pull --project podesta --lang python --out src/akribes_types/
60
+ ```
61
+
62
+ Then:
63
+
64
+ ```python
65
+ from akribes_types.podesta import summarize # ScriptType[I, O] with typed input/output
66
+
67
+ out = await proj.run(summarize, brief="hi", tone="formal")
68
+ # IDE knows brief: str, tone: Literal["formal","casual"]
69
+ print(out.execution_id, out.result)
70
+ ```
71
+
72
+ ## Streaming
73
+
74
+ ```python
75
+ run = await proj.executions.run_stream("summarize", brief="hi")
76
+ async for evt in run:
77
+ match evt.kind:
78
+ case "agent_chunk": print(evt.chunk, end="")
79
+ case "task_end": print(f"\n[task {evt.task!r} done]")
80
+ case "error": print(f"\n[error {evt.message}]")
81
+ output = await run.output()
82
+ ```
83
+
84
+ ## Document ingest
85
+
86
+ ```python
87
+ from pathlib import Path
88
+
89
+ # One-liner
90
+ result = await proj.documents.ingest_and_wait(Path("invoice.pdf"))
91
+
92
+ # With progress
93
+ handle = proj.documents.ingest(Path("invoice.pdf"))
94
+ async for evt in handle:
95
+ print(evt)
96
+ result = await handle.result()
97
+ ```
98
+
99
+ ## Subscribe (long-lived events)
100
+
101
+ ```python
102
+ async with proj.events.subscribe(interests=[{"script_name": "summarize"}]) as sub:
103
+ async for evt in sub:
104
+ print(evt)
105
+ ```
106
+
107
+ Heartbeat runs for the lifetime of the subscription only — not automatically on client construction.
108
+
109
+ ## Pagination
110
+
111
+ ```python
112
+ async for script in proj.scripts.list():
113
+ print(script.name)
114
+
115
+ # Or materialise
116
+ scripts = await proj.scripts.list().to_list()
117
+ first = await proj.scripts.list().first()
118
+ top10 = await proj.scripts.list().take(10)
119
+ ```
120
+
121
+ ## Error handling
122
+
123
+ ```python
124
+ from akribes_sdk import (
125
+ AkribesError, AuthError, NotFoundError, TransientError,
126
+ RateLimitError, ScriptError, AkribesTimeoutError,
127
+ )
128
+
129
+ try:
130
+ output = await proj.run_and_await("summarize", brief="hi")
131
+ except AuthError: # 401/403
132
+ ...
133
+ except NotFoundError: # 404
134
+ ...
135
+ except TransientError: # 502/503 (retried by default)
136
+ ...
137
+ except RateLimitError: # 429 (retried by default, respects Retry-After)
138
+ ...
139
+ except ScriptError as e: # workflow failed; e.error_kind, e.execution_id
140
+ ...
141
+ ```
142
+
143
+ ## Tokens
144
+
145
+ ```python
146
+ from datetime import timedelta
147
+ minted = await client.tokens.mint(
148
+ scopes={"projects": "*", "role": "admin"},
149
+ expires_in=timedelta(hours=8),
150
+ label="web-session",
151
+ user_email="alice@acme.com",
152
+ )
153
+ print(minted.token) # ship to the browser
154
+ ```
155
+
156
+ ## Authentication
157
+
158
+ `AkribesClient` accepts either a **service token** (long-lived, set via
159
+ `AKRIBES_SERVICE_TOKEN_<NAME>=<scope>:<secret>` on the server) or a **scoped
160
+ token** (`akribes_tk_...` — legacy `aura_tk_...` still accepted — minted
161
+ via `client.tokens.mint(...)`).
162
+
163
+ ### Prefer `Authorization: Bearer` over `?token=…` (#789)
164
+
165
+ `AkribesClient` always sends the token in the `Authorization` header
166
+ for HTTP requests and WebSocket upgrades. The `?token=…` query-string
167
+ form exists only because browser `EventSource` / `WebSocket`
168
+ constructors cannot set arbitrary headers — treat it as a browser-only
169
+ escape hatch.
170
+
171
+ For CLIs, scripts, and backend services, avoid `?token=…` because:
172
+
173
+ - Reverse proxies, ingress controllers, and CDNs log the full URL
174
+ (including the token) in access logs by default.
175
+ - CI runners (Forgejo Actions, GitHub Actions) echo `curl` commands
176
+ into job logs.
177
+ - Browsers leak `?token=` in the `Referer` header on cross-origin
178
+ sub-resource requests.
179
+
180
+ The server stamps `X-Token-Source: query-param` on responses to any
181
+ request that used the query fallback so operators can chart adoption.
182
+
183
+ ---
184
+
185
+ See `examples/` for runnable end-to-end demos.
186
+
187
+ Upgrading from v0.20.x? See [MIGRATION-0.21.md](./MIGRATION-0.21.md).
188
+
189
+ - Source mirror: <https://github.com/PodestaAI/akribes-sdks>
190
+ - Language guide: <https://akribes.ai/docs>
191
+ - Issues: <https://github.com/PodestaAI/akribes-sdks/issues>
192
+
193
+ ## License
194
+
195
+ MIT
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: akribes
3
+ Version: 0.21.17
4
+ Summary: Pythonic async client for the Akribes workflow server
5
+ Author-email: Podesta <info@podesta.ai>
6
+ License: MIT
7
+ Project-URL: Homepage, https://akribes.ai
8
+ Project-URL: Repository, https://github.com/PodestaAI/akribes-sdks
9
+ Project-URL: Documentation, https://akribes.ai
10
+ Project-URL: Issues, https://github.com/PodestaAI/akribes-sdks/issues
11
+ Project-URL: Changelog, https://github.com/PodestaAI/akribes-sdks/blob/main/packages/akribes-sdk-python/CHANGELOG.md
12
+ Keywords: akribes,llm,ai-workflows,agent,dsl,sdk
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT 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 :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: httpx>=0.27.0
28
+ Requires-Dist: httpx-sse>=0.4.0
29
+ Requires-Dist: pydantic>=2.6
30
+ Requires-Dist: typing-extensions>=4.10
31
+ Requires-Dist: websockets>=12.0
32
+ Provides-Extra: otel
33
+ Requires-Dist: opentelemetry-api>=1.20; extra == "otel"
34
+ Provides-Extra: test
35
+ Requires-Dist: pytest>=8.0.0; extra == "test"
36
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "test"
37
+ Requires-Dist: respx>=0.21.0; extra == "test"
38
+ Requires-Dist: opentelemetry-api>=1.20; extra == "test"
39
+ Requires-Dist: opentelemetry-sdk>=1.20; extra == "test"
40
+ Dynamic: license-file
41
+
42
+ # akribes
43
+
44
+ Pythonic async client for the [Akribes](https://akribes.ai) workflow server.
45
+
46
+ Requires Python 3.10+.
47
+
48
+ ## Install
49
+
50
+ ```bash
51
+ pip install akribes
52
+ # or with optional OpenTelemetry support:
53
+ pip install 'akribes[otel]'
54
+ ```
55
+
56
+ ## Quick start
57
+
58
+ ```python
59
+ import asyncio
60
+ from akribes_sdk import AkribesClient
61
+
62
+ async def main():
63
+ async with AkribesClient("https://akribes.example.com", token="akribes_tk_...") as client:
64
+ proj = client.project(2)
65
+ output = await proj.script("summarize").run_and_await(brief="explain quantum")
66
+ print(output.execution_id, output.result)
67
+
68
+ asyncio.run(main())
69
+ ```
70
+
71
+ ## Construction
72
+
73
+ ```python
74
+ import os
75
+ from datetime import timedelta
76
+ from akribes_sdk import AkribesClient, RetryPolicy
77
+
78
+ client = AkribesClient(
79
+ "https://akribes.example.com",
80
+ token=os.environ["AKRIBES_TOKEN"],
81
+ timeout=timedelta(seconds=30),
82
+ retry=RetryPolicy(max_attempts=4), # retries transients + 429 by default
83
+ otel=True, # opt-in OTel auto-instrumentation
84
+ )
85
+ ```
86
+
87
+ ## Project handles
88
+
89
+ ```python
90
+ proj = client.project(2) # sync, lazy
91
+ proj = await client.get_project("podesta-staging") # async, resolves name → id
92
+ sandbox = await client.sandbox() # per-user sandbox project
93
+ ```
94
+
95
+ ## Typed inputs (codegen)
96
+
97
+ Generate typed `ScriptType[I, O]` stubs from a live server:
98
+
99
+ ```bash
100
+ akribes types pull --project podesta --lang python --out src/akribes_types/
101
+ ```
102
+
103
+ Then:
104
+
105
+ ```python
106
+ from akribes_types.podesta import summarize # ScriptType[I, O] with typed input/output
107
+
108
+ out = await proj.run(summarize, brief="hi", tone="formal")
109
+ # IDE knows brief: str, tone: Literal["formal","casual"]
110
+ print(out.execution_id, out.result)
111
+ ```
112
+
113
+ ## Streaming
114
+
115
+ ```python
116
+ run = await proj.executions.run_stream("summarize", brief="hi")
117
+ async for evt in run:
118
+ match evt.kind:
119
+ case "agent_chunk": print(evt.chunk, end="")
120
+ case "task_end": print(f"\n[task {evt.task!r} done]")
121
+ case "error": print(f"\n[error {evt.message}]")
122
+ output = await run.output()
123
+ ```
124
+
125
+ ## Document ingest
126
+
127
+ ```python
128
+ from pathlib import Path
129
+
130
+ # One-liner
131
+ result = await proj.documents.ingest_and_wait(Path("invoice.pdf"))
132
+
133
+ # With progress
134
+ handle = proj.documents.ingest(Path("invoice.pdf"))
135
+ async for evt in handle:
136
+ print(evt)
137
+ result = await handle.result()
138
+ ```
139
+
140
+ ## Subscribe (long-lived events)
141
+
142
+ ```python
143
+ async with proj.events.subscribe(interests=[{"script_name": "summarize"}]) as sub:
144
+ async for evt in sub:
145
+ print(evt)
146
+ ```
147
+
148
+ Heartbeat runs for the lifetime of the subscription only — not automatically on client construction.
149
+
150
+ ## Pagination
151
+
152
+ ```python
153
+ async for script in proj.scripts.list():
154
+ print(script.name)
155
+
156
+ # Or materialise
157
+ scripts = await proj.scripts.list().to_list()
158
+ first = await proj.scripts.list().first()
159
+ top10 = await proj.scripts.list().take(10)
160
+ ```
161
+
162
+ ## Error handling
163
+
164
+ ```python
165
+ from akribes_sdk import (
166
+ AkribesError, AuthError, NotFoundError, TransientError,
167
+ RateLimitError, ScriptError, AkribesTimeoutError,
168
+ )
169
+
170
+ try:
171
+ output = await proj.run_and_await("summarize", brief="hi")
172
+ except AuthError: # 401/403
173
+ ...
174
+ except NotFoundError: # 404
175
+ ...
176
+ except TransientError: # 502/503 (retried by default)
177
+ ...
178
+ except RateLimitError: # 429 (retried by default, respects Retry-After)
179
+ ...
180
+ except ScriptError as e: # workflow failed; e.error_kind, e.execution_id
181
+ ...
182
+ ```
183
+
184
+ ## Tokens
185
+
186
+ ```python
187
+ from datetime import timedelta
188
+ minted = await client.tokens.mint(
189
+ scopes={"projects": "*", "role": "admin"},
190
+ expires_in=timedelta(hours=8),
191
+ label="web-session",
192
+ user_email="alice@acme.com",
193
+ )
194
+ print(minted.token) # ship to the browser
195
+ ```
196
+
197
+ ## Authentication
198
+
199
+ `AkribesClient` accepts either a **service token** (long-lived, set via
200
+ `AKRIBES_SERVICE_TOKEN_<NAME>=<scope>:<secret>` on the server) or a **scoped
201
+ token** (`akribes_tk_...` — legacy `aura_tk_...` still accepted — minted
202
+ via `client.tokens.mint(...)`).
203
+
204
+ ### Prefer `Authorization: Bearer` over `?token=…` (#789)
205
+
206
+ `AkribesClient` always sends the token in the `Authorization` header
207
+ for HTTP requests and WebSocket upgrades. The `?token=…` query-string
208
+ form exists only because browser `EventSource` / `WebSocket`
209
+ constructors cannot set arbitrary headers — treat it as a browser-only
210
+ escape hatch.
211
+
212
+ For CLIs, scripts, and backend services, avoid `?token=…` because:
213
+
214
+ - Reverse proxies, ingress controllers, and CDNs log the full URL
215
+ (including the token) in access logs by default.
216
+ - CI runners (Forgejo Actions, GitHub Actions) echo `curl` commands
217
+ into job logs.
218
+ - Browsers leak `?token=` in the `Referer` header on cross-origin
219
+ sub-resource requests.
220
+
221
+ The server stamps `X-Token-Source: query-param` on responses to any
222
+ request that used the query fallback so operators can chart adoption.
223
+
224
+ ---
225
+
226
+ See `examples/` for runnable end-to-end demos.
227
+
228
+ Upgrading from v0.20.x? See [MIGRATION-0.21.md](./MIGRATION-0.21.md).
229
+
230
+ - Source mirror: <https://github.com/PodestaAI/akribes-sdks>
231
+ - Language guide: <https://akribes.ai/docs>
232
+ - Issues: <https://github.com/PodestaAI/akribes-sdks/issues>
233
+
234
+ ## License
235
+
236
+ MIT