lipas 0.3.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.
lipas-0.3.0/.gitignore ADDED
@@ -0,0 +1,210 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+ lipas/__pycache__/
6
+ examples/__pycache__/
7
+ tests/__pycache__/
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py.cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+ cover/
56
+
57
+ # Translations
58
+ *.mo
59
+ *.pot
60
+
61
+ # Django stuff:
62
+ *.log
63
+ local_settings.py
64
+ db.sqlite3
65
+ db.sqlite3-journal
66
+
67
+ # Flask stuff:
68
+ instance/
69
+ .webassets-cache
70
+
71
+ # Scrapy stuff:
72
+ .scrapy
73
+
74
+ # Sphinx documentation
75
+ docs/_build/
76
+
77
+ # PyBuilder
78
+ .pybuilder/
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ # For a library or package, you might want to ignore these files since the code is
90
+ # intended to run in multiple environments; otherwise, check them in:
91
+ # .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ #Pipfile.lock
99
+
100
+ # UV
101
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
102
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
103
+ # commonly ignored for libraries.
104
+ #uv.lock
105
+
106
+ # poetry
107
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
108
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
109
+ # commonly ignored for libraries.
110
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
111
+ #poetry.lock
112
+ #poetry.toml
113
+
114
+ # pdm
115
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
116
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
117
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
118
+ #pdm.lock
119
+ #pdm.toml
120
+ .pdm-python
121
+ .pdm-build/
122
+
123
+ # pixi
124
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
125
+ #pixi.lock
126
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
127
+ # in the .venv directory. It is recommended not to include this directory in version control.
128
+ .pixi
129
+
130
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
131
+ __pypackages__/
132
+
133
+ # Celery stuff
134
+ celerybeat-schedule
135
+ celerybeat.pid
136
+
137
+ # SageMath parsed files
138
+ *.sage.py
139
+
140
+ # Environments
141
+ .env
142
+ .envrc
143
+ .venv
144
+ env/
145
+ venv/
146
+ ENV/
147
+ env.bak/
148
+ venv.bak/
149
+
150
+ # Spyder project settings
151
+ .spyderproject
152
+ .spyproject
153
+
154
+ # Rope project settings
155
+ .ropeproject
156
+
157
+ # mkdocs documentation
158
+ /site
159
+
160
+ # mypy
161
+ .mypy_cache/
162
+ .dmypy.json
163
+ dmypy.json
164
+
165
+ # Pyre type checker
166
+ .pyre/
167
+
168
+ # pytype static type analyzer
169
+ .pytype/
170
+
171
+ # Cython debug symbols
172
+ cython_debug/
173
+
174
+ # PyCharm
175
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
176
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
177
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
178
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
179
+ #.idea/
180
+
181
+ # Abstra
182
+ # Abstra is an AI-powered process automation framework.
183
+ # Ignore directories containing user credentials, local state, and settings.
184
+ # Learn more at https://abstra.io/docs
185
+ .abstra/
186
+
187
+ # Visual Studio Code
188
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
189
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
190
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
191
+ # you could uncomment the following to ignore the entire vscode folder
192
+ # .vscode/
193
+
194
+ # Ruff stuff:
195
+ .ruff_cache/
196
+
197
+ # PyPI configuration file
198
+ .pypirc
199
+
200
+ # Cursor
201
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
202
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
203
+ # refer to https://docs.cursor.com/context/ignore-files
204
+ .cursorignore
205
+ .cursorindexingignore
206
+
207
+ # Marimo
208
+ marimo/_static/
209
+ marimo/_lsp/
210
+ __marimo__/
lipas-0.3.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 @MetataoOfficial
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.
lipas-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,230 @@
1
+ Metadata-Version: 2.4
2
+ Name: lipas
3
+ Version: 0.3.0
4
+ Summary: Layered Invariant-Preserving Agent System
5
+ Project-URL: Homepage, https://github.com/lipworld/lipas
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+
11
+ # LIPAS
12
+
13
+ **An agent framework built on algebra, not architecture.**
14
+
15
+ > Everything is a Claim. One operation -- ⊕ -- derives the rest.
16
+ >
17
+ > Monotonicity, recording, and convergence are consequences -- not axioms.
18
+
19
+ ---
20
+
21
+ ## What You Actually Write
22
+
23
+ Most of the algebra stays below the surface. The programming interface you touch daily is `lipas.flow` — a declarative pipeline where you describe **what each step needs** and **what it produces**, and the framework handles execution, failure, retries, and context threading.
24
+
25
+ ```python
26
+ ```
27
+
28
+ That is a complete, runnable agent. There is no state machine, no edge list, no router config.
29
+
30
+ You write one function per capability, declare its inputs and outputs, and `Pipeline` threads the context through ⊕ for you.
31
+
32
+ The cognitive load is minimal: each function is a plain Python function whose signature names the context keys it reads, and whose return dict names the keys it writes.
33
+
34
+ **You never manually route data, catch retry loops, or wire failure handlers — ⊕ absorbs every outcome and the pipeline converges.**
35
+
36
+ ---
37
+
38
+ ## What is LIPAS?
39
+
40
+ Most agent frameworks give you a box of components — planners, memory stores, tool routers — and ask you to wire them together.
41
+
42
+ LIPAS starts from a different place: a single algebraic operation.
43
+
44
+ The practical consequence is that you _**stop writing glue**_ and start writing intent:
45
+
46
+ - **You declare what the agent wants, not how it gets there.** A policy is a flow, which can be described as a YAML file of priorities and conditions. There is no control flow to wire, no state machine to draw, no edge cases to enumerate.
47
+ - **Failure handling writes itself.** Every outcome — success or failure — is a Claim that merges into belief via ⊕. The agent accumulates experience monotonically: it cannot forget a lesson, and it provably stops repeating the same mistake.
48
+ - **Complexity stays flat.** Adding a new capability is one handler function and one commitment entry. The algebra composes them; you don't have to reason about interactions.
49
+ - **The LLM is just another claim source.** Its output is unreliable — fine. ⊕ treats an LLM response exactly like a sensor reading or a user input: a Claim with a priority. The algebra absorbs hallucinations the same way it absorbs any other low-confidence signal.
50
+
51
+ ---
52
+
53
+ **⊕ (claim merge)** is a join on a field-indexed product semilattice.
54
+
55
+ ```
56
+ You supply: deliberation (strategy)
57
+ ⊕ supplies: everything else
58
+ ```
59
+
60
+ ---
61
+
62
+ From this one operation, the entire agent architecture is *derived*, not designed:
63
+
64
+ - **Belief** is the cumulative fold of epistemic claims under ⊕. Monotonicity is a theorem, not an assumption.
65
+ - **Commitment** is a conative claim with a priority field. Arbitration falls out of the semilattice order.
66
+ - **Effect** is an action that, when executed, produces new claims — closing the perception-action loop.
67
+
68
+ - **Learning** is what happens when effectual claims (failure records, outcome observations) are folded back into belief via ⊕. Every failed effect produces a (commitment_kind, OutcomeTag) record. When failures for a given kind exceed the caution threshold, the agent expects that failure and stops committing to it. This is not hard-coded retry logic — it is a threshold on a monotone counter that ⊕ maintains. Convergence toward competence is a consequence of belief monotonicity. Other frameworks either lack adaptation entirely or bolt on a learning module long after the fact. In LIPAS, learning is not a pluggable component, not a separate pipeline stage, not an external memory store — it is a mathematical consequence of Claim merging. You cannot "turn off" learning any more than you can remove addition from arithmetic; it is belief accumulation.
69
+ - **Adaptation** is gradient: the agent progresses through adaptation levels (REACTIVE → CAUTIOUS → STRATEGIC → REFLECTIVE) as belief accumulates. A fresh agent is REACTIVE; after enough observations it becomes CAUTIOUS; with learned expectations it reaches STRATEGIC; with sufficient history for meta-reasoning it becomes REFLECTIVE. Each level unlocks richer deliberation, but all levels share the same ⊕ machinery.
70
+ - **Multi-agent** requires no new algebra — coordination *is* claim merging across agent boundaries. Agents communicate via **Channels** (named ⊕-accumulators), and when two agents commit to the same goal type, a **CommitmentArbiter** selects one winner by priority and competence; losers skip that cycle but still update from channel claims, so they naturally adjust.
71
+
72
+ The only thing ⊕ does *not* give you is **deliberation** — the strategic, creative, non-monotonic act of deciding what to want. That is the one true primitive you must provide. It is where your agent's intelligence lives, and it is correctly outside the algebra.
73
+
74
+ ## Design Philosophy
75
+
76
+ | Framework | Core metaphor | Asks |
77
+ |-----------|--------------|------|
78
+ | LangGraph | Control flow — the world can be orchestrated | *How do I wire steps correctly?* |
79
+ | CrewAI | Social structure — intelligence from collaboration | *How do I assign roles?* |
80
+ | AutoGen | Conversation — intelligence lives in dialogue | *How do I design dialogue?* |
81
+ | **LIPAS** | **Algebra — intelligence is convergence under ⊕** | ***Under what conditions must a system become competent?*** |
82
+
83
+ LIPAS believes: you will make mistakes, your agents will make mistakes, and the world will respond unpredictably.
84
+ The only reliable path is to accumulate experience monotonically, never repeat the same failure blindly, and let convergence do the rest.
85
+
86
+ ## Documentation
87
+
88
+ - **[The Reference Specification](docs/lipas-reference.md)** — operational definition: belief spaces, commitments, effects, morphisms, axioms, execution cycle.
89
+ - **[Algebraic Calculus of Claim](docs/lipas-calculus.md)** — the algebraic foundation: how ⊕ derives the specification from first principles.
90
+
91
+
92
+
93
+ # LIPAS
94
+
95
+ **An agent framework built on algebra, not architecture.**
96
+
97
+ > Most frameworks ask you to wire components together.
98
+ >
99
+ > LIPAS asks you to declare intent — and lets one operation, **⊕**, handle the rest.
100
+
101
+ ---
102
+
103
+ ## The 30-second version
104
+
105
+ ```python
106
+ import asyncio
107
+ from lipas.flow import Step, Pipeline
108
+ from lipas.llm import LLMAdapter, OllamaBackend
109
+
110
+ llm = LLMAdapter(OllamaBackend(model="gemma4", timeout=300.0), verbose=True)
111
+ the_text = "AI will not replace humans, but humans who use AI will replace those who don't."
112
+
113
+ @Step(needs=['english_text'], produces=['chinese_draft'])
114
+ async def translate(english_text: str) -> str:
115
+ return await llm.ask(
116
+ f'topic: Please translate it into Chinese naturally: "{english_text}"',
117
+ system="You are a translator providing only the most appropriate translation."
118
+ "Produce a focused, accurate translation. Every sentence must be relevant.",
119
+ )
120
+
121
+ @Step(needs=['chinese_draft'], produces=['polished'])
122
+ async def polish(chinese_draft: str) -> str:
123
+ return await llm.ask(
124
+ f'topic: Please polish this Chinese naturally: "{chinese_draft}"',
125
+ system="You are a polishing editor providing only the most appropriate polishment."
126
+ "Produce a focused, accurate polishment. Every sentence must be relevant.",
127
+ )
128
+
129
+ pipeline = Pipeline(steps=[translate, polish], done_when='polished',)
130
+ asyncio.run(pipeline.run(english_text=the_text))
131
+ ```
132
+
133
+ That is a real, complete, runnable agent. No state machine. No edge list. No router config.
134
+
135
+ Each function declares what it reads and what it writes.
136
+
137
+ `Pipeline` threads context through, handles retries, and converges.
138
+
139
+ ---
140
+
141
+ ## Why another framework?
142
+
143
+ Most agent frameworks give you a box of components — planners, memory stores, tool routers — and ask you to wire them together.
144
+
145
+ The wiring is where bugs live.
146
+
147
+ LIPAS starts from a different place: a single algebraic operation, **⊕** (claim merge).
148
+
149
+ The practical consequences:
150
+
151
+ - **You declare what the agent wants, not how it gets there.**
152
+ A pipeline is a set of steps with declared inputs and outputs. There is no control flow to wire, no state machine to draw.
153
+
154
+ - **Failure handling writes itself.**
155
+ Every outcome — success or failure — is a Claim that merges into belief via ⊕. The agent cannot forget a lesson, and it provably stops repeating the same mistake.
156
+
157
+ - **Complexity stays flat.**
158
+ Adding a new capability is one function and one `@Step` decorator. The algebra composes them; you don't reason about interactions.
159
+
160
+ - **The LLM is just another claim source.**
161
+ Its output is unreliable — that's fine. ⊕ treats an LLM response exactly like a sensor reading: a Claim with a priority. Hallucinations are absorbed the same way as any other low-confidence signal.
162
+
163
+ ---
164
+
165
+ ## A fuller example — research pipeline with quality gate
166
+
167
+ See [`examples/research_flow/research_app.py`](examples/research_flow/research_app.py)
168
+ — a search → summarise → validate → refine pipeline with conditional branching via `when=` guards.
169
+ — two plain functions, one line each. There is no router, no conditional edge, no explicit branch node.
170
+
171
+ ---
172
+
173
+ ## How it works — the algebra in brief
174
+
175
+ **⊕ (claim merge)** is a join on a field-indexed product semilattice.
176
+
177
+ ```
178
+ You supply: deliberation (what to want — your strategy, your intelligence)
179
+ ⊕ supplies: everything else
180
+ ```
181
+
182
+ From this one operation, the entire architecture is *derived*, not designed:
183
+
184
+ | Concept | What it is |
185
+ |---|---|
186
+ | **Belief** | The cumulative fold of all Claims under ⊕. Monotonicity is a theorem. |
187
+ | **Commitment** | A conative Claim with a priority field. Arbitration falls out of the semilattice order. |
188
+ | **Effect** | An action that, when executed, produces new Claims — closing the perception-action loop. |
189
+ | **Learning** | What happens when failure records fold back into belief via ⊕. Not a module — a consequence. |
190
+ | **Adaptation** | The agent progresses through levels (REACTIVE → CAUTIOUS → STRATEGIC → REFLECTIVE) as belief accumulates. Each level unlocks richer deliberation; all share the same ⊕ machinery. |
191
+ | **Multi-agent** | Coordination *is* claim merging across agent boundaries. No new algebra required. |
192
+
193
+ The one thing ⊕ does *not* give you is **deliberation** — the creative act of deciding what to want. That is the true primitive you supply.
194
+
195
+ It is where your agent's intelligence lives, and it belongs outside the algebra.
196
+
197
+ ---
198
+
199
+ ## Design philosophy
200
+
201
+ | Framework | Core metaphor | The question it asks |
202
+ |---|---|---|
203
+ | LangGraph | Control flow — orchestrate the world | *How do I wire steps correctly?* |
204
+ | CrewAI | Social structure — roles and crews | *How do I assign roles?* |
205
+ | AutoGen | Conversation — dialogue as intelligence | *How do I design the dialogue?* |
206
+ | **LIPAS** | **Algebra — intelligence is convergence under ⊕** | ***Under what conditions must a system become competent?*** |
207
+
208
+ LIPAS is built on a single assumption: you will make mistakes, your agents will make mistakes, and the world will respond unpredictably. The only reliable path is to accumulate experience monotonically, never repeat the same failure blindly, and let convergence do the rest.
209
+
210
+ You cannot "turn off" learning in LIPAS any more than you can remove addition from arithmetic — it is belief accumulation, and belief accumulation is what ⊕ does.
211
+
212
+ ---
213
+
214
+ ## Installation
215
+
216
+ ```bash
217
+ pip install lipas
218
+ ```
219
+
220
+ Requires Python 3.10. For local LLM support, install [Ollama](https://ollama.com) and pull a model:
221
+
222
+ ```bash
223
+ ollama pull gemma4
224
+ ```
225
+
226
+ ---
227
+
228
+ ## License
229
+
230
+ MIT
lipas-0.3.0/README.md ADDED
@@ -0,0 +1,220 @@
1
+ # LIPAS
2
+
3
+ **An agent framework built on algebra, not architecture.**
4
+
5
+ > Everything is a Claim. One operation -- ⊕ -- derives the rest.
6
+ >
7
+ > Monotonicity, recording, and convergence are consequences -- not axioms.
8
+
9
+ ---
10
+
11
+ ## What You Actually Write
12
+
13
+ Most of the algebra stays below the surface. The programming interface you touch daily is `lipas.flow` — a declarative pipeline where you describe **what each step needs** and **what it produces**, and the framework handles execution, failure, retries, and context threading.
14
+
15
+ ```python
16
+ ```
17
+
18
+ That is a complete, runnable agent. There is no state machine, no edge list, no router config.
19
+
20
+ You write one function per capability, declare its inputs and outputs, and `Pipeline` threads the context through ⊕ for you.
21
+
22
+ The cognitive load is minimal: each function is a plain Python function whose signature names the context keys it reads, and whose return dict names the keys it writes.
23
+
24
+ **You never manually route data, catch retry loops, or wire failure handlers — ⊕ absorbs every outcome and the pipeline converges.**
25
+
26
+ ---
27
+
28
+ ## What is LIPAS?
29
+
30
+ Most agent frameworks give you a box of components — planners, memory stores, tool routers — and ask you to wire them together.
31
+
32
+ LIPAS starts from a different place: a single algebraic operation.
33
+
34
+ The practical consequence is that you _**stop writing glue**_ and start writing intent:
35
+
36
+ - **You declare what the agent wants, not how it gets there.** A policy is a flow, which can be described as a YAML file of priorities and conditions. There is no control flow to wire, no state machine to draw, no edge cases to enumerate.
37
+ - **Failure handling writes itself.** Every outcome — success or failure — is a Claim that merges into belief via ⊕. The agent accumulates experience monotonically: it cannot forget a lesson, and it provably stops repeating the same mistake.
38
+ - **Complexity stays flat.** Adding a new capability is one handler function and one commitment entry. The algebra composes them; you don't have to reason about interactions.
39
+ - **The LLM is just another claim source.** Its output is unreliable — fine. ⊕ treats an LLM response exactly like a sensor reading or a user input: a Claim with a priority. The algebra absorbs hallucinations the same way it absorbs any other low-confidence signal.
40
+
41
+ ---
42
+
43
+ **⊕ (claim merge)** is a join on a field-indexed product semilattice.
44
+
45
+ ```
46
+ You supply: deliberation (strategy)
47
+ ⊕ supplies: everything else
48
+ ```
49
+
50
+ ---
51
+
52
+ From this one operation, the entire agent architecture is *derived*, not designed:
53
+
54
+ - **Belief** is the cumulative fold of epistemic claims under ⊕. Monotonicity is a theorem, not an assumption.
55
+ - **Commitment** is a conative claim with a priority field. Arbitration falls out of the semilattice order.
56
+ - **Effect** is an action that, when executed, produces new claims — closing the perception-action loop.
57
+
58
+ - **Learning** is what happens when effectual claims (failure records, outcome observations) are folded back into belief via ⊕. Every failed effect produces a (commitment_kind, OutcomeTag) record. When failures for a given kind exceed the caution threshold, the agent expects that failure and stops committing to it. This is not hard-coded retry logic — it is a threshold on a monotone counter that ⊕ maintains. Convergence toward competence is a consequence of belief monotonicity. Other frameworks either lack adaptation entirely or bolt on a learning module long after the fact. In LIPAS, learning is not a pluggable component, not a separate pipeline stage, not an external memory store — it is a mathematical consequence of Claim merging. You cannot "turn off" learning any more than you can remove addition from arithmetic; it is belief accumulation.
59
+ - **Adaptation** is gradient: the agent progresses through adaptation levels (REACTIVE → CAUTIOUS → STRATEGIC → REFLECTIVE) as belief accumulates. A fresh agent is REACTIVE; after enough observations it becomes CAUTIOUS; with learned expectations it reaches STRATEGIC; with sufficient history for meta-reasoning it becomes REFLECTIVE. Each level unlocks richer deliberation, but all levels share the same ⊕ machinery.
60
+ - **Multi-agent** requires no new algebra — coordination *is* claim merging across agent boundaries. Agents communicate via **Channels** (named ⊕-accumulators), and when two agents commit to the same goal type, a **CommitmentArbiter** selects one winner by priority and competence; losers skip that cycle but still update from channel claims, so they naturally adjust.
61
+
62
+ The only thing ⊕ does *not* give you is **deliberation** — the strategic, creative, non-monotonic act of deciding what to want. That is the one true primitive you must provide. It is where your agent's intelligence lives, and it is correctly outside the algebra.
63
+
64
+ ## Design Philosophy
65
+
66
+ | Framework | Core metaphor | Asks |
67
+ |-----------|--------------|------|
68
+ | LangGraph | Control flow — the world can be orchestrated | *How do I wire steps correctly?* |
69
+ | CrewAI | Social structure — intelligence from collaboration | *How do I assign roles?* |
70
+ | AutoGen | Conversation — intelligence lives in dialogue | *How do I design dialogue?* |
71
+ | **LIPAS** | **Algebra — intelligence is convergence under ⊕** | ***Under what conditions must a system become competent?*** |
72
+
73
+ LIPAS believes: you will make mistakes, your agents will make mistakes, and the world will respond unpredictably.
74
+ The only reliable path is to accumulate experience monotonically, never repeat the same failure blindly, and let convergence do the rest.
75
+
76
+ ## Documentation
77
+
78
+ - **[The Reference Specification](docs/lipas-reference.md)** — operational definition: belief spaces, commitments, effects, morphisms, axioms, execution cycle.
79
+ - **[Algebraic Calculus of Claim](docs/lipas-calculus.md)** — the algebraic foundation: how ⊕ derives the specification from first principles.
80
+
81
+
82
+
83
+ # LIPAS
84
+
85
+ **An agent framework built on algebra, not architecture.**
86
+
87
+ > Most frameworks ask you to wire components together.
88
+ >
89
+ > LIPAS asks you to declare intent — and lets one operation, **⊕**, handle the rest.
90
+
91
+ ---
92
+
93
+ ## The 30-second version
94
+
95
+ ```python
96
+ import asyncio
97
+ from lipas.flow import Step, Pipeline
98
+ from lipas.llm import LLMAdapter, OllamaBackend
99
+
100
+ llm = LLMAdapter(OllamaBackend(model="gemma4", timeout=300.0), verbose=True)
101
+ the_text = "AI will not replace humans, but humans who use AI will replace those who don't."
102
+
103
+ @Step(needs=['english_text'], produces=['chinese_draft'])
104
+ async def translate(english_text: str) -> str:
105
+ return await llm.ask(
106
+ f'topic: Please translate it into Chinese naturally: "{english_text}"',
107
+ system="You are a translator providing only the most appropriate translation."
108
+ "Produce a focused, accurate translation. Every sentence must be relevant.",
109
+ )
110
+
111
+ @Step(needs=['chinese_draft'], produces=['polished'])
112
+ async def polish(chinese_draft: str) -> str:
113
+ return await llm.ask(
114
+ f'topic: Please polish this Chinese naturally: "{chinese_draft}"',
115
+ system="You are a polishing editor providing only the most appropriate polishment."
116
+ "Produce a focused, accurate polishment. Every sentence must be relevant.",
117
+ )
118
+
119
+ pipeline = Pipeline(steps=[translate, polish], done_when='polished',)
120
+ asyncio.run(pipeline.run(english_text=the_text))
121
+ ```
122
+
123
+ That is a real, complete, runnable agent. No state machine. No edge list. No router config.
124
+
125
+ Each function declares what it reads and what it writes.
126
+
127
+ `Pipeline` threads context through, handles retries, and converges.
128
+
129
+ ---
130
+
131
+ ## Why another framework?
132
+
133
+ Most agent frameworks give you a box of components — planners, memory stores, tool routers — and ask you to wire them together.
134
+
135
+ The wiring is where bugs live.
136
+
137
+ LIPAS starts from a different place: a single algebraic operation, **⊕** (claim merge).
138
+
139
+ The practical consequences:
140
+
141
+ - **You declare what the agent wants, not how it gets there.**
142
+ A pipeline is a set of steps with declared inputs and outputs. There is no control flow to wire, no state machine to draw.
143
+
144
+ - **Failure handling writes itself.**
145
+ Every outcome — success or failure — is a Claim that merges into belief via ⊕. The agent cannot forget a lesson, and it provably stops repeating the same mistake.
146
+
147
+ - **Complexity stays flat.**
148
+ Adding a new capability is one function and one `@Step` decorator. The algebra composes them; you don't reason about interactions.
149
+
150
+ - **The LLM is just another claim source.**
151
+ Its output is unreliable — that's fine. ⊕ treats an LLM response exactly like a sensor reading: a Claim with a priority. Hallucinations are absorbed the same way as any other low-confidence signal.
152
+
153
+ ---
154
+
155
+ ## A fuller example — research pipeline with quality gate
156
+
157
+ See [`examples/research_flow/research_app.py`](examples/research_flow/research_app.py)
158
+ — a search → summarise → validate → refine pipeline with conditional branching via `when=` guards.
159
+ — two plain functions, one line each. There is no router, no conditional edge, no explicit branch node.
160
+
161
+ ---
162
+
163
+ ## How it works — the algebra in brief
164
+
165
+ **⊕ (claim merge)** is a join on a field-indexed product semilattice.
166
+
167
+ ```
168
+ You supply: deliberation (what to want — your strategy, your intelligence)
169
+ ⊕ supplies: everything else
170
+ ```
171
+
172
+ From this one operation, the entire architecture is *derived*, not designed:
173
+
174
+ | Concept | What it is |
175
+ |---|---|
176
+ | **Belief** | The cumulative fold of all Claims under ⊕. Monotonicity is a theorem. |
177
+ | **Commitment** | A conative Claim with a priority field. Arbitration falls out of the semilattice order. |
178
+ | **Effect** | An action that, when executed, produces new Claims — closing the perception-action loop. |
179
+ | **Learning** | What happens when failure records fold back into belief via ⊕. Not a module — a consequence. |
180
+ | **Adaptation** | The agent progresses through levels (REACTIVE → CAUTIOUS → STRATEGIC → REFLECTIVE) as belief accumulates. Each level unlocks richer deliberation; all share the same ⊕ machinery. |
181
+ | **Multi-agent** | Coordination *is* claim merging across agent boundaries. No new algebra required. |
182
+
183
+ The one thing ⊕ does *not* give you is **deliberation** — the creative act of deciding what to want. That is the true primitive you supply.
184
+
185
+ It is where your agent's intelligence lives, and it belongs outside the algebra.
186
+
187
+ ---
188
+
189
+ ## Design philosophy
190
+
191
+ | Framework | Core metaphor | The question it asks |
192
+ |---|---|---|
193
+ | LangGraph | Control flow — orchestrate the world | *How do I wire steps correctly?* |
194
+ | CrewAI | Social structure — roles and crews | *How do I assign roles?* |
195
+ | AutoGen | Conversation — dialogue as intelligence | *How do I design the dialogue?* |
196
+ | **LIPAS** | **Algebra — intelligence is convergence under ⊕** | ***Under what conditions must a system become competent?*** |
197
+
198
+ LIPAS is built on a single assumption: you will make mistakes, your agents will make mistakes, and the world will respond unpredictably. The only reliable path is to accumulate experience monotonically, never repeat the same failure blindly, and let convergence do the rest.
199
+
200
+ You cannot "turn off" learning in LIPAS any more than you can remove addition from arithmetic — it is belief accumulation, and belief accumulation is what ⊕ does.
201
+
202
+ ---
203
+
204
+ ## Installation
205
+
206
+ ```bash
207
+ pip install lipas
208
+ ```
209
+
210
+ Requires Python 3.10. For local LLM support, install [Ollama](https://ollama.com) and pull a model:
211
+
212
+ ```bash
213
+ ollama pull gemma4
214
+ ```
215
+
216
+ ---
217
+
218
+ ## License
219
+
220
+ MIT