zonix 0.2.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.
Files changed (37) hide show
  1. zonix-0.2.1/.gitignore +18 -0
  2. zonix-0.2.1/CHANGELOG.md +27 -0
  3. zonix-0.2.1/CONTRIBUTING.md +21 -0
  4. zonix-0.2.1/LICENSE +21 -0
  5. zonix-0.2.1/PKG-INFO +314 -0
  6. zonix-0.2.1/README.md +285 -0
  7. zonix-0.2.1/SECURITY.md +12 -0
  8. zonix-0.2.1/docs/tutorial.zh-CN.md +341 -0
  9. zonix-0.2.1/examples/real_provider_case.py +71 -0
  10. zonix-0.2.1/examples/single_agent.py +35 -0
  11. zonix-0.2.1/examples/workflow_team.py +38 -0
  12. zonix-0.2.1/logo.png +0 -0
  13. zonix-0.2.1/pyproject.toml +50 -0
  14. zonix-0.2.1/scripts/smoke_real_provider.py +419 -0
  15. zonix-0.2.1/src/zonix/__init__.py +44 -0
  16. zonix-0.2.1/src/zonix/engine.py +335 -0
  17. zonix-0.2.1/src/zonix/events.py +106 -0
  18. zonix-0.2.1/src/zonix/exceptions.py +43 -0
  19. zonix-0.2.1/src/zonix/hitl.py +47 -0
  20. zonix-0.2.1/src/zonix/memory/__init__.py +118 -0
  21. zonix-0.2.1/src/zonix/models/__init__.py +14 -0
  22. zonix-0.2.1/src/zonix/models/anthropic.py +154 -0
  23. zonix-0.2.1/src/zonix/models/base.py +77 -0
  24. zonix-0.2.1/src/zonix/models/fake.py +34 -0
  25. zonix-0.2.1/src/zonix/models/openai.py +222 -0
  26. zonix-0.2.1/src/zonix/multi/__init__.py +10 -0
  27. zonix-0.2.1/src/zonix/multi/team.py +96 -0
  28. zonix-0.2.1/src/zonix/multi/workflow.py +127 -0
  29. zonix-0.2.1/src/zonix/obs.py +18 -0
  30. zonix-0.2.1/src/zonix/py.typed +1 -0
  31. zonix-0.2.1/src/zonix/runtime.py +151 -0
  32. zonix-0.2.1/src/zonix/serialization.py +34 -0
  33. zonix-0.2.1/src/zonix/spec.py +171 -0
  34. zonix-0.2.1/src/zonix/tools.py +109 -0
  35. zonix-0.2.1/src/zonix/types.py +162 -0
  36. zonix-0.2.1/src/zonix/wire/__init__.py +3 -0
  37. zonix-0.2.1/src/zonix/wire/ai_sdk.py +86 -0
zonix-0.2.1/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.pyo
4
+ *.pyd
5
+ .Python
6
+ .coverage
7
+ .mypy_cache/
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ .venv/
11
+ venv/
12
+ dist/
13
+ build/
14
+ *.egg-info/
15
+ .env
16
+ .env.*
17
+ !.env.example
18
+ .DS_Store
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ ## 0.2.1
4
+
5
+ - Fixed the README logo URL so PyPI can render it from GitHub.
6
+ - Prepared the first PyPI distribution.
7
+
8
+ ## 0.2.0
9
+
10
+ - Added provider-level structured output control:
11
+ - OpenAI-compatible models now prefer strict JSON Schema response formats.
12
+ - Anthropic-compatible models now use a final-output tool with `input_schema`.
13
+ - Pydantic validation can request one output repair pass by default.
14
+ - Added Anthropic-compatible provider support.
15
+ - Fixed OpenAI-compatible streaming providers that send empty terminal chunks.
16
+ - Preserved assistant tool-call messages so tool results round-trip correctly.
17
+ - Added real provider examples and a full smoke script covering agents, streams,
18
+ tools, HITL, resume, retry, timeout, fallback, workflow, team, router, memory,
19
+ and wire adapters.
20
+ - Added a Chinese multi-chapter tutorial.
21
+
22
+ ## 0.1.0
23
+
24
+ - Initial standalone repository.
25
+ - Added explicit `agent`, `workflow`, `team`, and `router` primitives.
26
+ - Added serializable run results, spans, usage, typed stream events, tool schemas,
27
+ memory strategies, HITL checkpoints, and an AI SDK data stream adapter.
@@ -0,0 +1,21 @@
1
+ # Contributing
2
+
3
+ Zonix is intentionally small and explicit. Contributions should keep these
4
+ constraints intact:
5
+
6
+ - Prefer typed objects over magic strings.
7
+ - Keep run state serializable at node boundaries.
8
+ - Keep `__call__`, `.run()`, and `.stream()` on the same execution path.
9
+ - Add new model providers through `zonix.models.BaseChatModel`.
10
+ - Add new frontend protocols under `zonix.wire`.
11
+
12
+ Local development:
13
+
14
+ ```bash
15
+ python -m venv .venv
16
+ . .venv/bin/activate
17
+ pip install -e ".[dev]"
18
+ python -m compileall src
19
+ ```
20
+
21
+ Do not commit generated build artifacts.
zonix-0.2.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zonix contributors
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.
zonix-0.2.1/PKG-INFO ADDED
@@ -0,0 +1,314 @@
1
+ Metadata-Version: 2.4
2
+ Name: zonix
3
+ Version: 0.2.1
4
+ Summary: Explicit, serializable AI workflow primitives inspired by pydantic-ai.
5
+ Project-URL: Homepage, https://github.com/zongxi1115/zonix
6
+ Project-URL: Repository, https://github.com/zongxi1115/zonix
7
+ Project-URL: Issues, https://github.com/zongxi1115/zonix/issues
8
+ Author-email: zongxi1115 <zxwang1234321@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,ai,llm,pydantic,workflow
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: pydantic<3,>=2.8
21
+ Provides-Extra: anthropic
22
+ Requires-Dist: anthropic>=0.45; extra == 'anthropic'
23
+ Provides-Extra: dev
24
+ Requires-Dist: mypy>=1.13; extra == 'dev'
25
+ Requires-Dist: ruff>=0.8; extra == 'dev'
26
+ Provides-Extra: openai
27
+ Requires-Dist: openai>=1.68; extra == 'openai'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # Zonix
31
+
32
+ ![Zonix logo](https://raw.githubusercontent.com/zongxi1115/zonix/main/logo.png)
33
+
34
+ Zonix is a Python AI workflow framework with explicit agents and a serializable
35
+ run engine. It borrows the clarity of pydantic-ai's `Agent`, then adds first
36
+ class `workflow`, `team`, and `router` primitives on top of one execution model.
37
+
38
+ The core idea:
39
+
40
+ ```python
41
+ plan = await planner("add captcha to the login page", ctx=ctx)
42
+ result = await planner.run("add captcha to the login page", ctx=ctx)
43
+
44
+ async for event in planner.stream("add captcha to the login page", ctx=ctx):
45
+ print(event)
46
+ ```
47
+
48
+ `__call__` returns the structured output. `.run()` returns the full trace, usage,
49
+ messages, and checkpoint metadata. `.stream()` returns typed events that can be
50
+ mapped to frontend protocols such as the Vercel AI SDK data stream.
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ pip install zonix
56
+ ```
57
+
58
+ For local development from this repository:
59
+
60
+ ```bash
61
+ pip install -e .
62
+ ```
63
+
64
+ Optional model providers:
65
+
66
+ ```bash
67
+ pip install "zonix[openai]"
68
+ pip install "zonix[anthropic]"
69
+ ```
70
+
71
+ ## OpenAI-compatible and Anthropic-compatible endpoints
72
+
73
+ Provider objects accept `base_url`, so OpenAI-compatible gateways and
74
+ Anthropic-compatible gateways stay explicit and typed:
75
+
76
+ ```python
77
+ import os
78
+
79
+ from zonix.models import Anthropic, OpenAI
80
+
81
+ openai_model = OpenAI(
82
+ model=os.environ["ZONIX_MODEL"],
83
+ api_key=os.environ["ZONIX_API_KEY"],
84
+ base_url=os.environ["ZONIX_BASE_URL"],
85
+ )
86
+
87
+ anthropic_model = Anthropic(
88
+ model=os.environ["ZONIX_MODEL"],
89
+ api_key=os.environ["ZONIX_API_KEY"],
90
+ base_url=os.environ["ZONIX_BASE_URL"],
91
+ )
92
+ ```
93
+
94
+ Run the real provider example:
95
+
96
+ ```bash
97
+ export ZONIX_API_KEY="..."
98
+ export ZONIX_PROVIDER="openai"
99
+ export ZONIX_BASE_URL="https://your-openai-compatible-host/v1"
100
+ export ZONIX_MODEL="your-model"
101
+ python examples/real_provider_case.py
102
+ ```
103
+
104
+ ## Single agent
105
+
106
+ ```python
107
+ from pydantic import BaseModel
108
+
109
+ from zonix import agent
110
+ from zonix.models import OpenAI
111
+
112
+
113
+ class Plan(BaseModel):
114
+ goal: str
115
+ files: list[str]
116
+ steps: list[str]
117
+
118
+
119
+ planner = (
120
+ agent(
121
+ "planner",
122
+ role="Plan code work",
123
+ model=OpenAI("gpt-5.2", temperature=0.2),
124
+ output=Plan,
125
+ )
126
+ .use(read_tree, search_code)
127
+ .prompt(
128
+ "Split the user request into a code plan. "
129
+ "Return only JSON that matches the Plan schema."
130
+ )
131
+ )
132
+
133
+ plan = await planner("add captcha to the login page", ctx=project_ctx)
134
+ ```
135
+
136
+ An agent definition keeps the important pieces in one place:
137
+
138
+ - `name` and `role` for trace readability.
139
+ - `model` as a typed object, not a provider string.
140
+ - `output` as a Pydantic model or Python type.
141
+ - `deps` through `ctx`.
142
+ - tools via `.use(...)` or `@agent.tool`.
143
+ - static or dynamic prompts via `.prompt(...)`.
144
+
145
+ ## Tools
146
+
147
+ Tool schemas are generated from type hints and docstrings.
148
+
149
+ ```python
150
+ coder = agent("coder", output=Patch, deps=ProjectCtx).use(read_file)
151
+
152
+
153
+ @coder.tool(approval=True)
154
+ async def write_file(ctx, path: str, content: str) -> bool:
155
+ """Write content to a repository file."""
156
+ return ctx.deps.repo.write(path, content)
157
+ ```
158
+
159
+ If a tool takes `ctx` as its first parameter, Zonix passes a `ToolContext` with
160
+ `deps`, shared usage, the current run state, and the owning agent.
161
+
162
+ ## Three call levels
163
+
164
+ ```python
165
+ output = await planner(task, ctx=ctx)
166
+ run = await planner.run(task, ctx=ctx)
167
+
168
+ async for event in planner.stream(task, ctx=ctx):
169
+ ...
170
+ ```
171
+
172
+ All three calls use the same run engine. The engine owns prompt assembly, model
173
+ calls, tool execution, output validation, usage aggregation, spans, checkpoints,
174
+ and event emission.
175
+
176
+ ## Workflow
177
+
178
+ ```python
179
+ from zonix import workflow
180
+
181
+ code_flow = (
182
+ workflow("code_team")
183
+ .start(planner)
184
+ .then(coder)
185
+ .then(reviewer)
186
+ .build()
187
+ )
188
+
189
+ review = await code_flow.solve("add captcha to login", ctx=ctx)
190
+ ```
191
+
192
+ `workflow` compiles ordered steps into a node. The output of one node becomes
193
+ the input of the next node, while `ctx`, usage, trace, scratch, and stream events
194
+ are automatically carried through the run.
195
+
196
+ The builder also supports `parallel`, `join`, `branch`, and `loop`:
197
+
198
+ ```python
199
+ flow = (
200
+ workflow("review")
201
+ .start(planner)
202
+ .parallel(security_review, perf_review)
203
+ .join(merge_reviews)
204
+ .branch(lambda review: review.risk == "high", then=human_gate, else_=auto_apply)
205
+ .loop(coder, until=lambda patch: patch.tests_pass, max_iters=3)
206
+ .build()
207
+ )
208
+ ```
209
+
210
+ ## Team and router
211
+
212
+ ```python
213
+ from zonix import router, team
214
+ from zonix.types import Route
215
+
216
+
217
+ def choose(task, state) -> Route:
218
+ if "review" in str(task).lower():
219
+ return Route(next="reviewer")
220
+ return Route(next="coder")
221
+
222
+
223
+ code_team = (
224
+ team("code_team")
225
+ .add(planner, coder, reviewer)
226
+ .route(router("rule_router", choose))
227
+ .build(max_steps=6)
228
+ )
229
+
230
+ answer = await code_team.solve("review the auth changes", ctx=ctx)
231
+ ```
232
+
233
+ A router can be a rule function, another agent, or any node that returns
234
+ `Route(next=..., done=..., input=...)`.
235
+
236
+ ## Memory
237
+
238
+ ```python
239
+ from zonix.memory import Session, Summarize, Vector, Window
240
+
241
+ session = Session(memory=[Window(size=20), Vector(store=my_store)])
242
+ assistant = agent("assistant", memory=[Summarize(over=170_000, keep=20)])
243
+
244
+ answer = await assistant("continue from last time", ctx=ctx, session=session)
245
+ ```
246
+
247
+ Memory strategies are typed and composable. They transform prior session history
248
+ before the current run is assembled.
249
+
250
+ ## Streaming events
251
+
252
+ Zonix streams typed Python events:
253
+
254
+ - `TextStart`, `TextDelta`, `TextEnd`
255
+ - `ReasoningDelta`
256
+ - `ToolInputStart`, `ToolInputDelta`, `ToolInputAvailable`
257
+ - `ToolOutputAvailable`
258
+ - `ApprovalRequired`
259
+ - `ErrorEvent`, `Finish`
260
+
261
+ Frontend protocols are adapters. For Vercel AI SDK data streams:
262
+
263
+ ```python
264
+ from zonix.wire.ai_sdk import to_ai_sdk
265
+
266
+ async for chunk in to_ai_sdk(agent.stream(task, ctx=ctx)):
267
+ yield chunk
268
+ ```
269
+
270
+ HTTP responses should include:
271
+
272
+ ```text
273
+ x-vercel-ai-ui-message-stream: v1
274
+ content-type: text/event-stream
275
+ ```
276
+
277
+ ## Human approval and resume
278
+
279
+ Tools can pause the run before execution:
280
+
281
+ ```python
282
+ run = await coder.run("edit the login page", ctx=ctx)
283
+
284
+ if run.paused:
285
+ print(run.pending)
286
+ run = await run.resume(approve=True)
287
+ ```
288
+
289
+ `run.dump()` returns a JSON-safe snapshot with output, usage, trace, messages,
290
+ scratch, and pending approval metadata. `CheckpointStore` can persist snapshots
291
+ to disk.
292
+
293
+ ## Architecture
294
+
295
+ ```text
296
+ zonix/
297
+ spec.py agent()/team()/workflow()/router() factories
298
+ engine.py serializable Run engine and Agent execution
299
+ runtime.py __call__/run/stream driver shared by every node
300
+ memory/ Window, Summarize, Vector, Session
301
+ multi/ Workflow, Team, Router nodes
302
+ hitl.py checkpoint save/load and approval keys
303
+ models/ complete/stream model adapters
304
+ wire/ event-to-wire protocol adapters
305
+ obs.py lightweight observability hooks
306
+ ```
307
+
308
+ Zonix is intentionally explicit: business code should say what it means, and
309
+ the run engine should make every step inspectable.
310
+
311
+ ## Tutorials
312
+
313
+ - [中文多章节教程](https://github.com/zongxi1115/zonix/blob/main/docs/tutorial.zh-CN.md)
314
+ - [Real provider smoke script](https://github.com/zongxi1115/zonix/blob/main/scripts/smoke_real_provider.py)
zonix-0.2.1/README.md ADDED
@@ -0,0 +1,285 @@
1
+ # Zonix
2
+
3
+ ![Zonix logo](https://raw.githubusercontent.com/zongxi1115/zonix/main/logo.png)
4
+
5
+ Zonix is a Python AI workflow framework with explicit agents and a serializable
6
+ run engine. It borrows the clarity of pydantic-ai's `Agent`, then adds first
7
+ class `workflow`, `team`, and `router` primitives on top of one execution model.
8
+
9
+ The core idea:
10
+
11
+ ```python
12
+ plan = await planner("add captcha to the login page", ctx=ctx)
13
+ result = await planner.run("add captcha to the login page", ctx=ctx)
14
+
15
+ async for event in planner.stream("add captcha to the login page", ctx=ctx):
16
+ print(event)
17
+ ```
18
+
19
+ `__call__` returns the structured output. `.run()` returns the full trace, usage,
20
+ messages, and checkpoint metadata. `.stream()` returns typed events that can be
21
+ mapped to frontend protocols such as the Vercel AI SDK data stream.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ pip install zonix
27
+ ```
28
+
29
+ For local development from this repository:
30
+
31
+ ```bash
32
+ pip install -e .
33
+ ```
34
+
35
+ Optional model providers:
36
+
37
+ ```bash
38
+ pip install "zonix[openai]"
39
+ pip install "zonix[anthropic]"
40
+ ```
41
+
42
+ ## OpenAI-compatible and Anthropic-compatible endpoints
43
+
44
+ Provider objects accept `base_url`, so OpenAI-compatible gateways and
45
+ Anthropic-compatible gateways stay explicit and typed:
46
+
47
+ ```python
48
+ import os
49
+
50
+ from zonix.models import Anthropic, OpenAI
51
+
52
+ openai_model = OpenAI(
53
+ model=os.environ["ZONIX_MODEL"],
54
+ api_key=os.environ["ZONIX_API_KEY"],
55
+ base_url=os.environ["ZONIX_BASE_URL"],
56
+ )
57
+
58
+ anthropic_model = Anthropic(
59
+ model=os.environ["ZONIX_MODEL"],
60
+ api_key=os.environ["ZONIX_API_KEY"],
61
+ base_url=os.environ["ZONIX_BASE_URL"],
62
+ )
63
+ ```
64
+
65
+ Run the real provider example:
66
+
67
+ ```bash
68
+ export ZONIX_API_KEY="..."
69
+ export ZONIX_PROVIDER="openai"
70
+ export ZONIX_BASE_URL="https://your-openai-compatible-host/v1"
71
+ export ZONIX_MODEL="your-model"
72
+ python examples/real_provider_case.py
73
+ ```
74
+
75
+ ## Single agent
76
+
77
+ ```python
78
+ from pydantic import BaseModel
79
+
80
+ from zonix import agent
81
+ from zonix.models import OpenAI
82
+
83
+
84
+ class Plan(BaseModel):
85
+ goal: str
86
+ files: list[str]
87
+ steps: list[str]
88
+
89
+
90
+ planner = (
91
+ agent(
92
+ "planner",
93
+ role="Plan code work",
94
+ model=OpenAI("gpt-5.2", temperature=0.2),
95
+ output=Plan,
96
+ )
97
+ .use(read_tree, search_code)
98
+ .prompt(
99
+ "Split the user request into a code plan. "
100
+ "Return only JSON that matches the Plan schema."
101
+ )
102
+ )
103
+
104
+ plan = await planner("add captcha to the login page", ctx=project_ctx)
105
+ ```
106
+
107
+ An agent definition keeps the important pieces in one place:
108
+
109
+ - `name` and `role` for trace readability.
110
+ - `model` as a typed object, not a provider string.
111
+ - `output` as a Pydantic model or Python type.
112
+ - `deps` through `ctx`.
113
+ - tools via `.use(...)` or `@agent.tool`.
114
+ - static or dynamic prompts via `.prompt(...)`.
115
+
116
+ ## Tools
117
+
118
+ Tool schemas are generated from type hints and docstrings.
119
+
120
+ ```python
121
+ coder = agent("coder", output=Patch, deps=ProjectCtx).use(read_file)
122
+
123
+
124
+ @coder.tool(approval=True)
125
+ async def write_file(ctx, path: str, content: str) -> bool:
126
+ """Write content to a repository file."""
127
+ return ctx.deps.repo.write(path, content)
128
+ ```
129
+
130
+ If a tool takes `ctx` as its first parameter, Zonix passes a `ToolContext` with
131
+ `deps`, shared usage, the current run state, and the owning agent.
132
+
133
+ ## Three call levels
134
+
135
+ ```python
136
+ output = await planner(task, ctx=ctx)
137
+ run = await planner.run(task, ctx=ctx)
138
+
139
+ async for event in planner.stream(task, ctx=ctx):
140
+ ...
141
+ ```
142
+
143
+ All three calls use the same run engine. The engine owns prompt assembly, model
144
+ calls, tool execution, output validation, usage aggregation, spans, checkpoints,
145
+ and event emission.
146
+
147
+ ## Workflow
148
+
149
+ ```python
150
+ from zonix import workflow
151
+
152
+ code_flow = (
153
+ workflow("code_team")
154
+ .start(planner)
155
+ .then(coder)
156
+ .then(reviewer)
157
+ .build()
158
+ )
159
+
160
+ review = await code_flow.solve("add captcha to login", ctx=ctx)
161
+ ```
162
+
163
+ `workflow` compiles ordered steps into a node. The output of one node becomes
164
+ the input of the next node, while `ctx`, usage, trace, scratch, and stream events
165
+ are automatically carried through the run.
166
+
167
+ The builder also supports `parallel`, `join`, `branch`, and `loop`:
168
+
169
+ ```python
170
+ flow = (
171
+ workflow("review")
172
+ .start(planner)
173
+ .parallel(security_review, perf_review)
174
+ .join(merge_reviews)
175
+ .branch(lambda review: review.risk == "high", then=human_gate, else_=auto_apply)
176
+ .loop(coder, until=lambda patch: patch.tests_pass, max_iters=3)
177
+ .build()
178
+ )
179
+ ```
180
+
181
+ ## Team and router
182
+
183
+ ```python
184
+ from zonix import router, team
185
+ from zonix.types import Route
186
+
187
+
188
+ def choose(task, state) -> Route:
189
+ if "review" in str(task).lower():
190
+ return Route(next="reviewer")
191
+ return Route(next="coder")
192
+
193
+
194
+ code_team = (
195
+ team("code_team")
196
+ .add(planner, coder, reviewer)
197
+ .route(router("rule_router", choose))
198
+ .build(max_steps=6)
199
+ )
200
+
201
+ answer = await code_team.solve("review the auth changes", ctx=ctx)
202
+ ```
203
+
204
+ A router can be a rule function, another agent, or any node that returns
205
+ `Route(next=..., done=..., input=...)`.
206
+
207
+ ## Memory
208
+
209
+ ```python
210
+ from zonix.memory import Session, Summarize, Vector, Window
211
+
212
+ session = Session(memory=[Window(size=20), Vector(store=my_store)])
213
+ assistant = agent("assistant", memory=[Summarize(over=170_000, keep=20)])
214
+
215
+ answer = await assistant("continue from last time", ctx=ctx, session=session)
216
+ ```
217
+
218
+ Memory strategies are typed and composable. They transform prior session history
219
+ before the current run is assembled.
220
+
221
+ ## Streaming events
222
+
223
+ Zonix streams typed Python events:
224
+
225
+ - `TextStart`, `TextDelta`, `TextEnd`
226
+ - `ReasoningDelta`
227
+ - `ToolInputStart`, `ToolInputDelta`, `ToolInputAvailable`
228
+ - `ToolOutputAvailable`
229
+ - `ApprovalRequired`
230
+ - `ErrorEvent`, `Finish`
231
+
232
+ Frontend protocols are adapters. For Vercel AI SDK data streams:
233
+
234
+ ```python
235
+ from zonix.wire.ai_sdk import to_ai_sdk
236
+
237
+ async for chunk in to_ai_sdk(agent.stream(task, ctx=ctx)):
238
+ yield chunk
239
+ ```
240
+
241
+ HTTP responses should include:
242
+
243
+ ```text
244
+ x-vercel-ai-ui-message-stream: v1
245
+ content-type: text/event-stream
246
+ ```
247
+
248
+ ## Human approval and resume
249
+
250
+ Tools can pause the run before execution:
251
+
252
+ ```python
253
+ run = await coder.run("edit the login page", ctx=ctx)
254
+
255
+ if run.paused:
256
+ print(run.pending)
257
+ run = await run.resume(approve=True)
258
+ ```
259
+
260
+ `run.dump()` returns a JSON-safe snapshot with output, usage, trace, messages,
261
+ scratch, and pending approval metadata. `CheckpointStore` can persist snapshots
262
+ to disk.
263
+
264
+ ## Architecture
265
+
266
+ ```text
267
+ zonix/
268
+ spec.py agent()/team()/workflow()/router() factories
269
+ engine.py serializable Run engine and Agent execution
270
+ runtime.py __call__/run/stream driver shared by every node
271
+ memory/ Window, Summarize, Vector, Session
272
+ multi/ Workflow, Team, Router nodes
273
+ hitl.py checkpoint save/load and approval keys
274
+ models/ complete/stream model adapters
275
+ wire/ event-to-wire protocol adapters
276
+ obs.py lightweight observability hooks
277
+ ```
278
+
279
+ Zonix is intentionally explicit: business code should say what it means, and
280
+ the run engine should make every step inspectable.
281
+
282
+ ## Tutorials
283
+
284
+ - [中文多章节教程](https://github.com/zongxi1115/zonix/blob/main/docs/tutorial.zh-CN.md)
285
+ - [Real provider smoke script](https://github.com/zongxi1115/zonix/blob/main/scripts/smoke_real_provider.py)
@@ -0,0 +1,12 @@
1
+ # Security Policy
2
+
3
+ Zonix can execute user-defined tools. Treat tool registration as code execution:
4
+
5
+ - Never register untrusted callables.
6
+ - Use `approval=True` for tools that mutate files, databases, cloud resources,
7
+ or external systems.
8
+ - Persist checkpoints outside public directories.
9
+ - Redact secrets from prompts, trace attributes, and tool outputs before sharing
10
+ run dumps.
11
+
12
+ Please report security issues privately to the repository owner.