agent-runtime-client 0.1.0__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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Petr Tripolsky
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,239 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-runtime-client
3
+ Version: 0.1.0
4
+ Summary: Python client for agent-runtime over the standard library: generate_object() with answers validated against a full JSON Schema, generate_text(), and the admin API.
5
+ Author-email: Petr Tripolsky <tripolskypetr@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/tripolskypetr/agent-runtime/tree/master/packages/python-sdk#readme
8
+ Project-URL: Repository, https://github.com/tripolskypetr/agent-runtime
9
+ Project-URL: Issues, https://github.com/tripolskypetr/agent-runtime/issues
10
+ Project-URL: Server, https://github.com/tripolskypetr/agent-runtime
11
+ Keywords: agent-runtime,sdk,client,ai-agent,ollama,structured-output,json-schema,generateObject,generateText
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Provides-Extra: unicode
24
+ Requires-Dist: regex>=2024.4.16; extra == "unicode"
25
+ Dynamic: license-file
26
+
27
+ # agent-runtime-client
28
+
29
+ > Python client for [agent-runtime](https://github.com/tripolskypetr/agent-runtime) over the standard library. `generate_object()` returns an answer validated against your JSON Schema, `generate_text()` a plain text one, and the admin API gives you the transcripts.
30
+
31
+ agent-runtime is a REST harness for a [pi](https://github.com/earendil-works/pi)-based agent on Ollama: it runs the agent with `bash`, `read_file` and `provide_answer` tools in an isolated workspace and returns an answer that matches a JSON schema. This package is the Python counterpart of [agent-runtime-sdk](https://www.npmjs.com/package/agent-runtime-sdk) for Node.js: the same `generate_object()` / `generate_text()` pair, the same error model, the same admin API.
32
+
33
+ ## Features
34
+
35
+ - `generate_object()`: the answer as a `dict`, validated on the client with a port of the server's own validator; a mismatch runs the inference again
36
+ - `generate_text()`: plain text answers from the same agent
37
+ - `inference()` / `text()`: the full typed response (`status` is `"success"` or `"error"`) without raising
38
+ - `AgentRuntimeError` with the server's error code, per-attempt details and inference id
39
+ - Admin API: list and search inferences, read transcripts, download attachments, delete runs
40
+ - Zero dependencies, Python 3.9+, `urllib` underneath; the HTTP layer is replaceable for tests
41
+ - `format` is a full JSON Schema (draft 2020-12), enforced server-side by ajv
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ pip install agent-runtime-client
47
+ ```
48
+
49
+ Run the server first (see the [agent-runtime README](https://github.com/tripolskypetr/agent-runtime#quick-start-docker)):
50
+
51
+ ```bash
52
+ docker run -p 10050:10050 -e OLLAMA_API_KEY=... tripolskypetr/agent-runtime
53
+ ```
54
+
55
+ ## Quick start
56
+
57
+ ```python
58
+ from agent_runtime_client import encode_file, generate_object
59
+
60
+ report = generate_object(
61
+ [{"role": "user", "content": "sales.csv is in your working directory. Total the amount column and name the top city."}],
62
+ {
63
+ "type": "object",
64
+ "required": ["total", "topCity"],
65
+ "properties": {
66
+ "total": {"type": "number", "description": "Sum of the amount column"},
67
+ "topCity": {"type": "string", "enum": ["Berlin", "Paris"], "description": "City with the largest amount"},
68
+ "note": {"type": "string", "description": "Optional remark"},
69
+ },
70
+ },
71
+ files=[encode_file("sales.csv", "city,amount\nBerlin,120.5\nParis,340.25")],
72
+ )
73
+
74
+ report["total"] # 460.75
75
+ report["topCity"] # "Paris"
76
+ report.get("note") # None unless the model filled it
77
+ ```
78
+
79
+ The standalone functions create a client per call. Without `base_url` they talk to `AGENT_RUNTIME_URL` or `http://localhost:10050`:
80
+
81
+ ```python
82
+ from agent_runtime_client import generate_text
83
+
84
+ summary = generate_text(
85
+ [{"role": "user", "content": "Summarise notes.txt"}],
86
+ files=[encode_file("notes.txt", notes)],
87
+ base_url="http://agent-runtime:10050",
88
+ headers={"x-token": "…"},
89
+ timeout=600,
90
+ )
91
+ ```
92
+
93
+ Keyword arguments: `files`, `model`, `instructions`, `base_url`, `headers`, `timeout` (seconds, `None` waits as long as the inference takes), `validate_answer`, `max_attempts`, `transport`.
94
+
95
+ For many calls against one server, or for the admin API, keep a client:
96
+
97
+ ```python
98
+ from agent_runtime_client import create_client
99
+
100
+ client = create_client("http://localhost:10050")
101
+ report = client.generate_object(messages, format)
102
+ ```
103
+
104
+ ## Images
105
+
106
+ Images go into `messages[].images` as base64; the server shows them to the model in user messages and stores them in the history. They are not written to the workspace: to process a picture with bash or `read_file`, pass it in `files`.
107
+
108
+ ```python
109
+ from agent_runtime_client import generate_object, user_message
110
+
111
+ answer = generate_object(
112
+ [user_message("Describe the chart", [open("chart.png", "rb").read()])],
113
+ {"type": "object", "required": ["trend"], "properties": {"trend": {"type": "string", "enum": ["up", "down", "flat"]}}},
114
+ )
115
+ ```
116
+
117
+ Records of a `wwwroot.jsonl` file (`{"role", "content", "images"}`) can be passed as `messages` directly.
118
+
119
+ ## Client-side validation and retries
120
+
121
+ The package ships a port of the server's answer validator ([validation.py](https://github.com/tripolskypetr/agent-runtime/blob/master/packages/python-sdk/src/agent_runtime_client/validation.py): a dependency-free JSON Schema checker with the same messages as the TypeScript original; its tests pin them against the shared fixtures). The client runs it on every successful answer, and when the answer does not match `format` it runs the inference again, up to `max_attempts` (3) times in total, then fails with `schema_mismatch` and one detail line per rejected inference. This should never trigger against a current server, which validates with the same logic; it is the client's guarantee that the value you get really matches the schema.
122
+
123
+ ```python
124
+ client = create_client(validate_answer=True, max_attempts=3) # defaults
125
+ generate_object(messages, format, validate_answer=False) # trust the server, no retries
126
+ ```
127
+
128
+ The validator is also exported for answers that come from somewhere else, e.g. a cache on disk after a schema change:
129
+
130
+ ```python
131
+ from agent_runtime_client import assert_answer, validate_answer
132
+
133
+ result = validate_answer(json.loads(cached), Agent1Format)
134
+ if result.success:
135
+ result.data["verdict"]
136
+ else:
137
+ print(result.error) # 'Invalid arguments: signal.direction: must be exactly "long"'
138
+
139
+ answer = assert_answer(json.loads(cached), Agent1Format) # raises ValueError instead
140
+ ```
141
+
142
+ Supported keywords: `type` (string or list, `null` included), `enum`, `const`, `oneOf` / `anyOf` / `allOf` / `not`, `if` / `then` / `else`, local `$ref`, `properties` / `required` / `additionalProperties` / `patternProperties` / `propertyNames` / `dependentRequired` / `dependentSchemas` / `minProperties` / `maxProperties`, `items` / `prefixItems` / `contains` / `uniqueItems` / `minItems` / `maxItems`, `minLength` / `maxLength` / `pattern`, `minimum` / `maximum` / `exclusiveMinimum` / `exclusiveMaximum` / `multipleOf`. `format` and unknown keywords are ignored, so the client is never stricter than the server. `pattern` is matched with Python's `re`; a pattern it cannot compile, such as `\p{L}` classes, is skipped unless the optional `regex` package is installed: `pip install agent-runtime-client[unicode]`.
143
+
144
+ ## Responses and errors
145
+
146
+ `generate_object()` and `generate_text()` raise `AgentRuntimeError` when the agent fails. `inference()` and `text()` return the typed response instead:
147
+
148
+ ```python
149
+ from agent_runtime_client import inference
150
+
151
+ response = inference(messages, format)
152
+ if response["status"] == "success":
153
+ response["data"] # the answer
154
+ response["turns"] # model calls
155
+ else:
156
+ response["error"]["code"] # "schema_mismatch" | "empty_answer" | "max_turns" | "timeout" | "provider_error" | "internal_error"
157
+ response["error"]["details"] # one line per failed attempt
158
+ response["id"] # look the transcript up in the admin UI
159
+ ```
160
+
161
+ ```python
162
+ from agent_runtime_client import AgentRuntimeError, generate_object
163
+
164
+ try:
165
+ generate_object(messages, format)
166
+ except AgentRuntimeError as error:
167
+ error.status # HTTP status, 0 for network failures
168
+ error.code # InferenceErrorCode ("invalid_format" for a rejected schema) or None for other HTTP errors
169
+ error.details # per-attempt details
170
+ error.inference_id # id of the stored run
171
+ ```
172
+
173
+ The server rejects a schema that does not compile (a `$ref` to a missing `$defs` entry) with HTTP 400 and `error.code = "invalid_format"`; no inference is recorded.
174
+
175
+ ## Admin API
176
+
177
+ ```python
178
+ listed = client.list_inferences(status="error", mode="object", limit=20)
179
+ found = client.list_inferences(q="Hilda") # case-insensitive substring search
180
+ record = client.get_inference(listed["items"][0]["id"]) # request, transcript, result/error, attachments
181
+ file = client.get_attachment(record["id"], record["attachments"][0]["id"]) # {...meta, "data": bytes}
182
+ client.delete_inference(record["id"])
183
+ client.health()
184
+ ```
185
+
186
+ ## Long inferences
187
+
188
+ An inference can run for minutes. The default `timeout` is `None`, so the client waits as long as the server takes; set `timeout` in seconds to bound a call. The HTTP layer is a plain function and can be replaced, for a `requests` session or a mock in tests:
189
+
190
+ ```python
191
+ def transport(method, url, headers, body, timeout):
192
+ response = session.request(method, url, headers=headers, data=body, timeout=timeout)
193
+ return response.status_code, dict(response.headers), response.content
194
+
195
+ client = create_client(transport=transport)
196
+ ```
197
+
198
+ ## API
199
+
200
+ Standalone functions (create the client internally):
201
+
202
+ | Function | Returns |
203
+ |----------|---------|
204
+ | `generate_object(messages, format, **kw)` | `dict` |
205
+ | `generate_text(messages, **kw)` | `str` |
206
+ | `inference(messages, format, **kw)` | `InferenceResponse` |
207
+ | `text(messages, **kw)` | `TextResponse` |
208
+
209
+ Client:
210
+
211
+ | Method | Returns |
212
+ |--------|---------|
213
+ | `create_client(base_url=None, **options)` / `AgentRuntimeClient(...)` | options: `headers`, `timeout`, `validate_answer` (True), `max_attempts` (3), `transport` |
214
+ | `generate_object(messages, format, *, files, model, instructions, headers, timeout)` | `dict` |
215
+ | `generate_text(messages, *, ...)` | `str` |
216
+ | `inference(...)` / `text(...)` | typed response |
217
+ | `health()` | `Health` |
218
+ | `list_inferences(*, limit, offset, status, mode, q)` | `{"total", "items"}` |
219
+ | `get_inference(id)` | `InferenceRecord` |
220
+ | `get_attachment(id, attachment_id)` | `Attachment` with `data: bytes` |
221
+ | `delete_inference(id)` | `{"ok": bool}` |
222
+ | `validate_answer(value, format)`, `assert_answer(value, format)` | client-side validation |
223
+ | `validate_tool_arguments(value, format)`, `validate_value(value, schema, path)` | the raw validator |
224
+ | `encode_file(name, bytes_or_str)`, `encode_image(bytes)`, `user_message(text, images=None)` | request helpers |
225
+
226
+ The response shapes are `TypedDict`s in `agent_runtime_client.models`.
227
+
228
+ ## Development
229
+
230
+ ```bash
231
+ python3 -m venv .venv && .venv/bin/pip install build twine
232
+ .venv/bin/python -m unittest discover -s tests -v # validator and client, no server
233
+ BASE_URL=http://localhost:10151 .venv/bin/python -m unittest tests.test_runtime -v # against a test server
234
+ .venv/bin/python -m build && .venv/bin/twine check dist/*
235
+ ```
236
+
237
+ ## License
238
+
239
+ MIT
@@ -0,0 +1,213 @@
1
+ # agent-runtime-client
2
+
3
+ > Python client for [agent-runtime](https://github.com/tripolskypetr/agent-runtime) over the standard library. `generate_object()` returns an answer validated against your JSON Schema, `generate_text()` a plain text one, and the admin API gives you the transcripts.
4
+
5
+ agent-runtime is a REST harness for a [pi](https://github.com/earendil-works/pi)-based agent on Ollama: it runs the agent with `bash`, `read_file` and `provide_answer` tools in an isolated workspace and returns an answer that matches a JSON schema. This package is the Python counterpart of [agent-runtime-sdk](https://www.npmjs.com/package/agent-runtime-sdk) for Node.js: the same `generate_object()` / `generate_text()` pair, the same error model, the same admin API.
6
+
7
+ ## Features
8
+
9
+ - `generate_object()`: the answer as a `dict`, validated on the client with a port of the server's own validator; a mismatch runs the inference again
10
+ - `generate_text()`: plain text answers from the same agent
11
+ - `inference()` / `text()`: the full typed response (`status` is `"success"` or `"error"`) without raising
12
+ - `AgentRuntimeError` with the server's error code, per-attempt details and inference id
13
+ - Admin API: list and search inferences, read transcripts, download attachments, delete runs
14
+ - Zero dependencies, Python 3.9+, `urllib` underneath; the HTTP layer is replaceable for tests
15
+ - `format` is a full JSON Schema (draft 2020-12), enforced server-side by ajv
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install agent-runtime-client
21
+ ```
22
+
23
+ Run the server first (see the [agent-runtime README](https://github.com/tripolskypetr/agent-runtime#quick-start-docker)):
24
+
25
+ ```bash
26
+ docker run -p 10050:10050 -e OLLAMA_API_KEY=... tripolskypetr/agent-runtime
27
+ ```
28
+
29
+ ## Quick start
30
+
31
+ ```python
32
+ from agent_runtime_client import encode_file, generate_object
33
+
34
+ report = generate_object(
35
+ [{"role": "user", "content": "sales.csv is in your working directory. Total the amount column and name the top city."}],
36
+ {
37
+ "type": "object",
38
+ "required": ["total", "topCity"],
39
+ "properties": {
40
+ "total": {"type": "number", "description": "Sum of the amount column"},
41
+ "topCity": {"type": "string", "enum": ["Berlin", "Paris"], "description": "City with the largest amount"},
42
+ "note": {"type": "string", "description": "Optional remark"},
43
+ },
44
+ },
45
+ files=[encode_file("sales.csv", "city,amount\nBerlin,120.5\nParis,340.25")],
46
+ )
47
+
48
+ report["total"] # 460.75
49
+ report["topCity"] # "Paris"
50
+ report.get("note") # None unless the model filled it
51
+ ```
52
+
53
+ The standalone functions create a client per call. Without `base_url` they talk to `AGENT_RUNTIME_URL` or `http://localhost:10050`:
54
+
55
+ ```python
56
+ from agent_runtime_client import generate_text
57
+
58
+ summary = generate_text(
59
+ [{"role": "user", "content": "Summarise notes.txt"}],
60
+ files=[encode_file("notes.txt", notes)],
61
+ base_url="http://agent-runtime:10050",
62
+ headers={"x-token": "…"},
63
+ timeout=600,
64
+ )
65
+ ```
66
+
67
+ Keyword arguments: `files`, `model`, `instructions`, `base_url`, `headers`, `timeout` (seconds, `None` waits as long as the inference takes), `validate_answer`, `max_attempts`, `transport`.
68
+
69
+ For many calls against one server, or for the admin API, keep a client:
70
+
71
+ ```python
72
+ from agent_runtime_client import create_client
73
+
74
+ client = create_client("http://localhost:10050")
75
+ report = client.generate_object(messages, format)
76
+ ```
77
+
78
+ ## Images
79
+
80
+ Images go into `messages[].images` as base64; the server shows them to the model in user messages and stores them in the history. They are not written to the workspace: to process a picture with bash or `read_file`, pass it in `files`.
81
+
82
+ ```python
83
+ from agent_runtime_client import generate_object, user_message
84
+
85
+ answer = generate_object(
86
+ [user_message("Describe the chart", [open("chart.png", "rb").read()])],
87
+ {"type": "object", "required": ["trend"], "properties": {"trend": {"type": "string", "enum": ["up", "down", "flat"]}}},
88
+ )
89
+ ```
90
+
91
+ Records of a `wwwroot.jsonl` file (`{"role", "content", "images"}`) can be passed as `messages` directly.
92
+
93
+ ## Client-side validation and retries
94
+
95
+ The package ships a port of the server's answer validator ([validation.py](https://github.com/tripolskypetr/agent-runtime/blob/master/packages/python-sdk/src/agent_runtime_client/validation.py): a dependency-free JSON Schema checker with the same messages as the TypeScript original; its tests pin them against the shared fixtures). The client runs it on every successful answer, and when the answer does not match `format` it runs the inference again, up to `max_attempts` (3) times in total, then fails with `schema_mismatch` and one detail line per rejected inference. This should never trigger against a current server, which validates with the same logic; it is the client's guarantee that the value you get really matches the schema.
96
+
97
+ ```python
98
+ client = create_client(validate_answer=True, max_attempts=3) # defaults
99
+ generate_object(messages, format, validate_answer=False) # trust the server, no retries
100
+ ```
101
+
102
+ The validator is also exported for answers that come from somewhere else, e.g. a cache on disk after a schema change:
103
+
104
+ ```python
105
+ from agent_runtime_client import assert_answer, validate_answer
106
+
107
+ result = validate_answer(json.loads(cached), Agent1Format)
108
+ if result.success:
109
+ result.data["verdict"]
110
+ else:
111
+ print(result.error) # 'Invalid arguments: signal.direction: must be exactly "long"'
112
+
113
+ answer = assert_answer(json.loads(cached), Agent1Format) # raises ValueError instead
114
+ ```
115
+
116
+ Supported keywords: `type` (string or list, `null` included), `enum`, `const`, `oneOf` / `anyOf` / `allOf` / `not`, `if` / `then` / `else`, local `$ref`, `properties` / `required` / `additionalProperties` / `patternProperties` / `propertyNames` / `dependentRequired` / `dependentSchemas` / `minProperties` / `maxProperties`, `items` / `prefixItems` / `contains` / `uniqueItems` / `minItems` / `maxItems`, `minLength` / `maxLength` / `pattern`, `minimum` / `maximum` / `exclusiveMinimum` / `exclusiveMaximum` / `multipleOf`. `format` and unknown keywords are ignored, so the client is never stricter than the server. `pattern` is matched with Python's `re`; a pattern it cannot compile, such as `\p{L}` classes, is skipped unless the optional `regex` package is installed: `pip install agent-runtime-client[unicode]`.
117
+
118
+ ## Responses and errors
119
+
120
+ `generate_object()` and `generate_text()` raise `AgentRuntimeError` when the agent fails. `inference()` and `text()` return the typed response instead:
121
+
122
+ ```python
123
+ from agent_runtime_client import inference
124
+
125
+ response = inference(messages, format)
126
+ if response["status"] == "success":
127
+ response["data"] # the answer
128
+ response["turns"] # model calls
129
+ else:
130
+ response["error"]["code"] # "schema_mismatch" | "empty_answer" | "max_turns" | "timeout" | "provider_error" | "internal_error"
131
+ response["error"]["details"] # one line per failed attempt
132
+ response["id"] # look the transcript up in the admin UI
133
+ ```
134
+
135
+ ```python
136
+ from agent_runtime_client import AgentRuntimeError, generate_object
137
+
138
+ try:
139
+ generate_object(messages, format)
140
+ except AgentRuntimeError as error:
141
+ error.status # HTTP status, 0 for network failures
142
+ error.code # InferenceErrorCode ("invalid_format" for a rejected schema) or None for other HTTP errors
143
+ error.details # per-attempt details
144
+ error.inference_id # id of the stored run
145
+ ```
146
+
147
+ The server rejects a schema that does not compile (a `$ref` to a missing `$defs` entry) with HTTP 400 and `error.code = "invalid_format"`; no inference is recorded.
148
+
149
+ ## Admin API
150
+
151
+ ```python
152
+ listed = client.list_inferences(status="error", mode="object", limit=20)
153
+ found = client.list_inferences(q="Hilda") # case-insensitive substring search
154
+ record = client.get_inference(listed["items"][0]["id"]) # request, transcript, result/error, attachments
155
+ file = client.get_attachment(record["id"], record["attachments"][0]["id"]) # {...meta, "data": bytes}
156
+ client.delete_inference(record["id"])
157
+ client.health()
158
+ ```
159
+
160
+ ## Long inferences
161
+
162
+ An inference can run for minutes. The default `timeout` is `None`, so the client waits as long as the server takes; set `timeout` in seconds to bound a call. The HTTP layer is a plain function and can be replaced, for a `requests` session or a mock in tests:
163
+
164
+ ```python
165
+ def transport(method, url, headers, body, timeout):
166
+ response = session.request(method, url, headers=headers, data=body, timeout=timeout)
167
+ return response.status_code, dict(response.headers), response.content
168
+
169
+ client = create_client(transport=transport)
170
+ ```
171
+
172
+ ## API
173
+
174
+ Standalone functions (create the client internally):
175
+
176
+ | Function | Returns |
177
+ |----------|---------|
178
+ | `generate_object(messages, format, **kw)` | `dict` |
179
+ | `generate_text(messages, **kw)` | `str` |
180
+ | `inference(messages, format, **kw)` | `InferenceResponse` |
181
+ | `text(messages, **kw)` | `TextResponse` |
182
+
183
+ Client:
184
+
185
+ | Method | Returns |
186
+ |--------|---------|
187
+ | `create_client(base_url=None, **options)` / `AgentRuntimeClient(...)` | options: `headers`, `timeout`, `validate_answer` (True), `max_attempts` (3), `transport` |
188
+ | `generate_object(messages, format, *, files, model, instructions, headers, timeout)` | `dict` |
189
+ | `generate_text(messages, *, ...)` | `str` |
190
+ | `inference(...)` / `text(...)` | typed response |
191
+ | `health()` | `Health` |
192
+ | `list_inferences(*, limit, offset, status, mode, q)` | `{"total", "items"}` |
193
+ | `get_inference(id)` | `InferenceRecord` |
194
+ | `get_attachment(id, attachment_id)` | `Attachment` with `data: bytes` |
195
+ | `delete_inference(id)` | `{"ok": bool}` |
196
+ | `validate_answer(value, format)`, `assert_answer(value, format)` | client-side validation |
197
+ | `validate_tool_arguments(value, format)`, `validate_value(value, schema, path)` | the raw validator |
198
+ | `encode_file(name, bytes_or_str)`, `encode_image(bytes)`, `user_message(text, images=None)` | request helpers |
199
+
200
+ The response shapes are `TypedDict`s in `agent_runtime_client.models`.
201
+
202
+ ## Development
203
+
204
+ ```bash
205
+ python3 -m venv .venv && .venv/bin/pip install build twine
206
+ .venv/bin/python -m unittest discover -s tests -v # validator and client, no server
207
+ BASE_URL=http://localhost:10151 .venv/bin/python -m unittest tests.test_runtime -v # against a test server
208
+ .venv/bin/python -m build && .venv/bin/twine check dist/*
209
+ ```
210
+
211
+ ## License
212
+
213
+ MIT
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "agent-runtime-client"
7
+ version = "0.1.0"
8
+ description = "Python client for agent-runtime over the standard library: generate_object() with answers validated against a full JSON Schema, generate_text(), and the admin API."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.9"
12
+ authors = [{ name = "Petr Tripolsky", email = "tripolskypetr@gmail.com" }]
13
+ keywords = ["agent-runtime", "sdk", "client", "ai-agent", "ollama", "structured-output", "json-schema", "generateObject", "generateText"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Topic :: Software Development :: Libraries",
22
+ "Typing :: Typed",
23
+ ]
24
+ dependencies = []
25
+
26
+ [project.optional-dependencies]
27
+ unicode = ["regex>=2024.4.16"]
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/tripolskypetr/agent-runtime/tree/master/packages/python-sdk#readme"
31
+ Repository = "https://github.com/tripolskypetr/agent-runtime"
32
+ Issues = "https://github.com/tripolskypetr/agent-runtime/issues"
33
+ Server = "https://github.com/tripolskypetr/agent-runtime"
34
+
35
+ [tool.setuptools.packages.find]
36
+ where = ["src"]
37
+
38
+ [tool.setuptools.package-data]
39
+ agent_runtime_client = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,84 @@
1
+ """Python client for agent-runtime: generate_object() / generate_text() over the REST API, plus the admin API.
2
+
3
+ Import name ``agent_runtime_client``, distribution ``agent-runtime-client``. Zero dependencies, Python 3.9+.
4
+ """
5
+ from .client import DEFAULT_BASE_URL, DEFAULT_MAX_ATTEMPTS, AgentRuntimeClient, Transport, create_client, resolve_base_url, urllib_transport
6
+ from .errors import AgentRuntimeError, is_inference_failure, is_invalid_format
7
+ from .functions import generate_object, generate_text, inference, text
8
+ from .helpers import encode_file, encode_image, user_message
9
+ from .models import (
10
+ Attachment,
11
+ AttachmentKind,
12
+ AttachmentMeta,
13
+ FormatModel,
14
+ Health,
15
+ InferenceError,
16
+ InferenceErrorCode,
17
+ InferenceFailure,
18
+ InferenceMode,
19
+ InferenceRecord,
20
+ InferenceResponse,
21
+ InferenceStatus,
22
+ InferenceSuccess,
23
+ InferenceSummary,
24
+ ListInferencesResponse,
25
+ RequestFile,
26
+ RequestMessage,
27
+ RequestRole,
28
+ RunInfo,
29
+ StoredRequest,
30
+ TextResponse,
31
+ TextSuccess,
32
+ )
33
+ from .validation import ValidationResult, assert_answer, resolve_ref, type_of, validate_answer, validate_tool_arguments, validate_value
34
+
35
+ __version__ = "0.1.0"
36
+
37
+ __all__ = [
38
+ "AgentRuntimeClient",
39
+ "AgentRuntimeError",
40
+ "Attachment",
41
+ "AttachmentKind",
42
+ "AttachmentMeta",
43
+ "DEFAULT_BASE_URL",
44
+ "DEFAULT_MAX_ATTEMPTS",
45
+ "FormatModel",
46
+ "Health",
47
+ "InferenceError",
48
+ "InferenceErrorCode",
49
+ "InferenceFailure",
50
+ "InferenceMode",
51
+ "InferenceRecord",
52
+ "InferenceResponse",
53
+ "InferenceStatus",
54
+ "InferenceSuccess",
55
+ "InferenceSummary",
56
+ "ListInferencesResponse",
57
+ "RequestFile",
58
+ "RequestMessage",
59
+ "RequestRole",
60
+ "RunInfo",
61
+ "StoredRequest",
62
+ "TextResponse",
63
+ "TextSuccess",
64
+ "Transport",
65
+ "ValidationResult",
66
+ "assert_answer",
67
+ "create_client",
68
+ "encode_file",
69
+ "encode_image",
70
+ "generate_object",
71
+ "generate_text",
72
+ "inference",
73
+ "is_inference_failure",
74
+ "is_invalid_format",
75
+ "resolve_base_url",
76
+ "resolve_ref",
77
+ "text",
78
+ "type_of",
79
+ "urllib_transport",
80
+ "user_message",
81
+ "validate_answer",
82
+ "validate_tool_arguments",
83
+ "validate_value",
84
+ ]