maki-framework 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.
Files changed (170) hide show
  1. maki_framework-0.3.0/LICENSE +21 -0
  2. maki_framework-0.3.0/PKG-INFO +582 -0
  3. maki_framework-0.3.0/README.md +521 -0
  4. maki_framework-0.3.0/maki/__init__.py +57 -0
  5. maki_framework-0.3.0/maki/__main__.py +104 -0
  6. maki_framework-0.3.0/maki/agents/__init__.py +27 -0
  7. maki_framework-0.3.0/maki/agents/agent.py +388 -0
  8. maki_framework-0.3.0/maki/agents/agent_manager.py +791 -0
  9. maki_framework-0.3.0/maki/agents/agents.py +16 -0
  10. maki_framework-0.3.0/maki/agents/approvals.py +209 -0
  11. maki_framework-0.3.0/maki/agents/plugin_handler.py +582 -0
  12. maki_framework-0.3.0/maki/agents/protocols.py +49 -0
  13. maki_framework-0.3.0/maki/agents/reasoning.py +267 -0
  14. maki_framework-0.3.0/maki/agents/verification.py +174 -0
  15. maki_framework-0.3.0/maki/agents/workflow.py +271 -0
  16. maki_framework-0.3.0/maki/backend.py +155 -0
  17. maki_framework-0.3.0/maki/config.py +123 -0
  18. maki_framework-0.3.0/maki/connector.py +446 -0
  19. maki_framework-0.3.0/maki/distributed/__init__.py +16 -0
  20. maki_framework-0.3.0/maki/distributed/circuit_breaker.py +117 -0
  21. maki_framework-0.3.0/maki/distributed/config_loader.py +135 -0
  22. maki_framework-0.3.0/maki/distributed/proxy.py +346 -0
  23. maki_framework-0.3.0/maki/distributed/registry.py +89 -0
  24. maki_framework-0.3.0/maki/distributed/server.py +254 -0
  25. maki_framework-0.3.0/maki/distributed/state_store.py +230 -0
  26. maki_framework-0.3.0/maki/exceptions.py +30 -0
  27. maki_framework-0.3.0/maki/logging_config.py +39 -0
  28. maki_framework-0.3.0/maki/makiAnthropic.py +384 -0
  29. maki_framework-0.3.0/maki/makiHG.py +237 -0
  30. maki_framework-0.3.0/maki/makiLLama.py +580 -0
  31. maki_framework-0.3.0/maki/makiLlamaCpp.py +274 -0
  32. maki_framework-0.3.0/maki/makiOpenAI.py +383 -0
  33. maki_framework-0.3.0/maki/makiOpenRouter.py +147 -0
  34. maki_framework-0.3.0/maki/objects.py +389 -0
  35. maki_framework-0.3.0/maki/plugins/__init__.py +47 -0
  36. maki_framework-0.3.0/maki/plugins/_web_utils.py +100 -0
  37. maki_framework-0.3.0/maki/plugins/alpaca_data/__init__.py +3 -0
  38. maki_framework-0.3.0/maki/plugins/alpaca_data/alpaca_data.py +271 -0
  39. maki_framework-0.3.0/maki/plugins/alpaca_data/example_usage.py +34 -0
  40. maki_framework-0.3.0/maki/plugins/alpaca_data/test_alpaca_data.py +141 -0
  41. maki_framework-0.3.0/maki/plugins/alpaca_news/__init__.py +3 -0
  42. maki_framework-0.3.0/maki/plugins/alpaca_news/alpaca_news.py +184 -0
  43. maki_framework-0.3.0/maki/plugins/alpaca_news/example_usage.py +37 -0
  44. maki_framework-0.3.0/maki/plugins/alpaca_news/test_alpaca_news.py +96 -0
  45. maki_framework-0.3.0/maki/plugins/alpaca_stream/__init__.py +3 -0
  46. maki_framework-0.3.0/maki/plugins/alpaca_stream/alpaca_stream.py +152 -0
  47. maki_framework-0.3.0/maki/plugins/alpaca_stream/example_usage.py +42 -0
  48. maki_framework-0.3.0/maki/plugins/alpaca_stream/test_alpaca_stream.py +84 -0
  49. maki_framework-0.3.0/maki/plugins/alpaca_trading/__init__.py +3 -0
  50. maki_framework-0.3.0/maki/plugins/alpaca_trading/alpaca_trading.py +189 -0
  51. maki_framework-0.3.0/maki/plugins/alpaca_trading/example_usage.py +44 -0
  52. maki_framework-0.3.0/maki/plugins/alpaca_trading/test_alpaca_trading.py +24 -0
  53. maki_framework-0.3.0/maki/plugins/directory_reader/__init__.py +10 -0
  54. maki_framework-0.3.0/maki/plugins/directory_reader/directory_reader.py +239 -0
  55. maki_framework-0.3.0/maki/plugins/directory_reader/example_usage.py +41 -0
  56. maki_framework-0.3.0/maki/plugins/directory_reader/test_directory_reader.py +94 -0
  57. maki_framework-0.3.0/maki/plugins/file_reader/__init__.py +10 -0
  58. maki_framework-0.3.0/maki/plugins/file_reader/example_usage.py +58 -0
  59. maki_framework-0.3.0/maki/plugins/file_reader/file_reader.py +272 -0
  60. maki_framework-0.3.0/maki/plugins/file_reader/test_file_reader.py +74 -0
  61. maki_framework-0.3.0/maki/plugins/file_writer/__init__.py +10 -0
  62. maki_framework-0.3.0/maki/plugins/file_writer/example_usage.py +47 -0
  63. maki_framework-0.3.0/maki/plugins/file_writer/file_writer.py +332 -0
  64. maki_framework-0.3.0/maki/plugins/file_writer/test_file_writer.py +96 -0
  65. maki_framework-0.3.0/maki/plugins/ftp_client/__init__.py +10 -0
  66. maki_framework-0.3.0/maki/plugins/ftp_client/example_usage.py +116 -0
  67. maki_framework-0.3.0/maki/plugins/ftp_client/ftp_client.py +845 -0
  68. maki_framework-0.3.0/maki/plugins/ftp_client/test_ftp_client.py +251 -0
  69. maki_framework-0.3.0/maki/plugins/image_classifier/__init__.py +11 -0
  70. maki_framework-0.3.0/maki/plugins/image_classifier/example_usage.py +83 -0
  71. maki_framework-0.3.0/maki/plugins/image_classifier/image_classifier.py +116 -0
  72. maki_framework-0.3.0/maki/plugins/image_classifier/test_image_classifier.py +182 -0
  73. maki_framework-0.3.0/maki/plugins/json_reader/__init__.py +7 -0
  74. maki_framework-0.3.0/maki/plugins/json_reader/example_usage.py +18 -0
  75. maki_framework-0.3.0/maki/plugins/json_reader/json_reader.py +113 -0
  76. maki_framework-0.3.0/maki/plugins/json_reader/test_json_reader.py +37 -0
  77. maki_framework-0.3.0/maki/plugins/obsidian_memory/__init__.py +3 -0
  78. maki_framework-0.3.0/maki/plugins/obsidian_memory/example_usage.py +54 -0
  79. maki_framework-0.3.0/maki/plugins/obsidian_memory/obsidian_memory.py +221 -0
  80. maki_framework-0.3.0/maki/plugins/obsidian_memory/test_obsidian_memory.py +83 -0
  81. maki_framework-0.3.0/maki/plugins/ocr/__init__.py +10 -0
  82. maki_framework-0.3.0/maki/plugins/ocr/backends/__init__.py +17 -0
  83. maki_framework-0.3.0/maki/plugins/ocr/backends/base.py +48 -0
  84. maki_framework-0.3.0/maki/plugins/ocr/backends/docx_backend.py +69 -0
  85. maki_framework-0.3.0/maki/plugins/ocr/backends/image_backend.py +49 -0
  86. maki_framework-0.3.0/maki/plugins/ocr/backends/llm_backend.py +164 -0
  87. maki_framework-0.3.0/maki/plugins/ocr/backends/pdf_backend.py +73 -0
  88. maki_framework-0.3.0/maki/plugins/ocr/backends/xlsx_backend.py +59 -0
  89. maki_framework-0.3.0/maki/plugins/ocr/example_usage.py +79 -0
  90. maki_framework-0.3.0/maki/plugins/ocr/ocr.py +242 -0
  91. maki_framework-0.3.0/maki/plugins/ocr/test_ocr.py +273 -0
  92. maki_framework-0.3.0/maki/plugins/postgres_store/__init__.py +10 -0
  93. maki_framework-0.3.0/maki/plugins/postgres_store/example_usage.py +35 -0
  94. maki_framework-0.3.0/maki/plugins/postgres_store/postgres_store.py +271 -0
  95. maki_framework-0.3.0/maki/plugins/postgres_store/test_postgres_store.py +133 -0
  96. maki_framework-0.3.0/maki/plugins/provider_updates/__init__.py +7 -0
  97. maki_framework-0.3.0/maki/plugins/provider_updates/example_usage.py +14 -0
  98. maki_framework-0.3.0/maki/plugins/provider_updates/provider_updates.py +101 -0
  99. maki_framework-0.3.0/maki/plugins/provider_updates/test_provider_updates.py +51 -0
  100. maki_framework-0.3.0/maki/plugins/rag_memory/__init__.py +3 -0
  101. maki_framework-0.3.0/maki/plugins/rag_memory/backends/__init__.py +57 -0
  102. maki_framework-0.3.0/maki/plugins/rag_memory/backends/base.py +70 -0
  103. maki_framework-0.3.0/maki/plugins/rag_memory/backends/chroma.py +95 -0
  104. maki_framework-0.3.0/maki/plugins/rag_memory/backends/faiss_local.py +123 -0
  105. maki_framework-0.3.0/maki/plugins/rag_memory/backends/memory_numpy.py +101 -0
  106. maki_framework-0.3.0/maki/plugins/rag_memory/backends/pgvector.py +137 -0
  107. maki_framework-0.3.0/maki/plugins/rag_memory/backends/qdrant.py +108 -0
  108. maki_framework-0.3.0/maki/plugins/rag_memory/example_usage.py +71 -0
  109. maki_framework-0.3.0/maki/plugins/rag_memory/rag_memory.py +383 -0
  110. maki_framework-0.3.0/maki/plugins/rag_memory/test_rag_memory.py +275 -0
  111. maki_framework-0.3.0/maki/plugins/trend_search/__init__.py +7 -0
  112. maki_framework-0.3.0/maki/plugins/trend_search/example_usage.py +14 -0
  113. maki_framework-0.3.0/maki/plugins/trend_search/test_trend_search.py +81 -0
  114. maki_framework-0.3.0/maki/plugins/trend_search/trend_search.py +115 -0
  115. maki_framework-0.3.0/maki/plugins/web_search/__init__.py +11 -0
  116. maki_framework-0.3.0/maki/plugins/web_search/example_usage.py +48 -0
  117. maki_framework-0.3.0/maki/plugins/web_search/test_web_search.py +539 -0
  118. maki_framework-0.3.0/maki/plugins/web_search/web_search.py +699 -0
  119. maki_framework-0.3.0/maki/plugins/web_to_md/__init__.py +9 -0
  120. maki_framework-0.3.0/maki/plugins/web_to_md/example_usage.py +47 -0
  121. maki_framework-0.3.0/maki/plugins/web_to_md/test_web_to_md.py +159 -0
  122. maki_framework-0.3.0/maki/plugins/web_to_md/web_to_md.py +296 -0
  123. maki_framework-0.3.0/maki/py.typed +0 -0
  124. maki_framework-0.3.0/maki/session.py +88 -0
  125. maki_framework-0.3.0/maki/structured.py +148 -0
  126. maki_framework-0.3.0/maki/test/__init__.py +3 -0
  127. maki_framework-0.3.0/maki/test/test_agent_fixes.py +567 -0
  128. maki_framework-0.3.0/maki/test/test_agent_functionality.py +177 -0
  129. maki_framework-0.3.0/maki/test/test_agent_proxy.py +478 -0
  130. maki_framework-0.3.0/maki/test/test_agent_server.py +313 -0
  131. maki_framework-0.3.0/maki/test/test_async_rate_limiter.py +341 -0
  132. maki_framework-0.3.0/maki/test/test_backend_hierarchy.py +327 -0
  133. maki_framework-0.3.0/maki/test/test_backend_interface.py +402 -0
  134. maki_framework-0.3.0/maki/test/test_concurrency.py +509 -0
  135. maki_framework-0.3.0/maki/test/test_config_loader.py +98 -0
  136. maki_framework-0.3.0/maki/test/test_connector.py +429 -0
  137. maki_framework-0.3.0/maki/test/test_consistency_sweep.py +349 -0
  138. maki_framework-0.3.0/maki/test/test_conversation_memory.py +398 -0
  139. maki_framework-0.3.0/maki/test/test_distributed_workflow.py +560 -0
  140. maki_framework-0.3.0/maki/test/test_enhanced_workflow.py +153 -0
  141. maki_framework-0.3.0/maki/test/test_error_handling.py +171 -0
  142. maki_framework-0.3.0/maki/test/test_hardening.py +503 -0
  143. maki_framework-0.3.0/maki/test/test_history_cleanup.py +114 -0
  144. maki_framework-0.3.0/maki/test/test_logging.py +32 -0
  145. maki_framework-0.3.0/maki/test/test_makiAnthropic.py +267 -0
  146. maki_framework-0.3.0/maki/test/test_makiLLama.py +297 -0
  147. maki_framework-0.3.0/maki/test/test_makiLLama_unittest.py +252 -0
  148. maki_framework-0.3.0/maki/test/test_makiLlamaCpp.py +291 -0
  149. maki_framework-0.3.0/maki/test/test_makiOpenAI.py +255 -0
  150. maki_framework-0.3.0/maki/test/test_makiOpenRouter.py +270 -0
  151. maki_framework-0.3.0/maki/test/test_mixin_contracts.py +384 -0
  152. maki_framework-0.3.0/maki/test/test_native_tools.py +652 -0
  153. maki_framework-0.3.0/maki/test/test_plugin_structure.py +50 -0
  154. maki_framework-0.3.0/maki/test/test_security.py +705 -0
  155. maki_framework-0.3.0/maki/test/test_serialization.py +313 -0
  156. maki_framework-0.3.0/maki/test/test_session.py +65 -0
  157. maki_framework-0.3.0/maki/test/test_ssrp_protection.py +105 -0
  158. maki_framework-0.3.0/maki/test/test_structured_output.py +128 -0
  159. maki_framework-0.3.0/maki/test/test_verification_types.py +97 -0
  160. maki_framework-0.3.0/maki/test/test_verified_workflow.py +281 -0
  161. maki_framework-0.3.0/maki/test/test_workflow_approval.py +205 -0
  162. maki_framework-0.3.0/maki/utils.py +250 -0
  163. maki_framework-0.3.0/maki_framework.egg-info/PKG-INFO +582 -0
  164. maki_framework-0.3.0/maki_framework.egg-info/SOURCES.txt +168 -0
  165. maki_framework-0.3.0/maki_framework.egg-info/dependency_links.txt +1 -0
  166. maki_framework-0.3.0/maki_framework.egg-info/entry_points.txt +3 -0
  167. maki_framework-0.3.0/maki_framework.egg-info/requires.txt +58 -0
  168. maki_framework-0.3.0/maki_framework.egg-info/top_level.txt +1 -0
  169. maki_framework-0.3.0/pyproject.toml +104 -0
  170. maki_framework-0.3.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bowl of Data
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,582 @@
1
+ Metadata-Version: 2.4
2
+ Name: maki-framework
3
+ Version: 0.3.0
4
+ Summary: A Python framework for multi-agent LLM interactions
5
+ Author-email: Bowl of Data <bowlofdata@gmail.com>
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: requests>=2.25.0
18
+ Requires-Dist: httpx>=0.23.0
19
+ Requires-Dist: python-dotenv>=1.0.0
20
+ Provides-Extra: postgres
21
+ Requires-Dist: psycopg[binary]>=3.1; extra == "postgres"
22
+ Requires-Dist: psycopg_pool>=3.2; extra == "postgres"
23
+ Provides-Extra: structured
24
+ Requires-Dist: pydantic>=2.0; extra == "structured"
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=6.0; extra == "dev"
27
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
28
+ Requires-Dist: black>=21.0; extra == "dev"
29
+ Requires-Dist: flake8>=3.8; extra == "dev"
30
+ Provides-Extra: openai
31
+ Requires-Dist: openai>=1.0; extra == "openai"
32
+ Provides-Extra: anthropic
33
+ Requires-Dist: anthropic>=0.20; extra == "anthropic"
34
+ Provides-Extra: openrouter
35
+ Requires-Dist: openai>=1.0; extra == "openrouter"
36
+ Provides-Extra: llamacpp
37
+ Requires-Dist: openai>=1.0; extra == "llamacpp"
38
+ Provides-Extra: distributed
39
+ Requires-Dist: fastapi>=0.100.0; extra == "distributed"
40
+ Requires-Dist: uvicorn>=0.20.0; extra == "distributed"
41
+ Requires-Dist: pyyaml>=6.0; extra == "distributed"
42
+ Provides-Extra: distributed-redis
43
+ Requires-Dist: redis>=4.5; extra == "distributed-redis"
44
+ Provides-Extra: gui
45
+ Requires-Dist: PySide6>=6.7.0; extra == "gui"
46
+ Provides-Extra: ftp
47
+ Requires-Dist: paramiko>=2.11.0; extra == "ftp"
48
+ Provides-Extra: web
49
+ Requires-Dist: feedparser>=6.0; extra == "web"
50
+ Requires-Dist: readability-lxml>=0.8; extra == "web"
51
+ Requires-Dist: html2text>=2020.1.16; extra == "web"
52
+ Provides-Extra: trends
53
+ Requires-Dist: pytrends>=4.9.0; extra == "trends"
54
+ Provides-Extra: alpaca
55
+ Requires-Dist: alpaca-py>=0.43.0; extra == "alpaca"
56
+ Requires-Dist: feedparser>=6.0; extra == "alpaca"
57
+ Requires-Dist: yfinance>=0.2.40; extra == "alpaca"
58
+ Provides-Extra: all
59
+ Requires-Dist: maki-framework[alpaca,anthropic,distributed,distributed-redis,ftp,gui,llamacpp,openai,openrouter,structured,trends,web]; extra == "all"
60
+ Dynamic: license-file
61
+
62
+ <p align="center">
63
+ <img src="img/logo.png" alt="Maki Logo" width="200" />
64
+ </p>
65
+
66
+ # Maki
67
+
68
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue?logo=python&logoColor=white)](https://www.python.org/)
69
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
70
+ [![CI](https://github.com/BowlOfData/maki/actions/workflows/python-package.yml/badge.svg)](https://github.com/BowlOfData/maki/actions/workflows/python-package.yml)
71
+ [![Ollama](https://img.shields.io/badge/LLM-Ollama%20local-lightgrey?logo=ollama)](https://ollama.ai/)
72
+ [![HuggingFace](https://img.shields.io/badge/LLM-HuggingFace-yellow?logo=huggingface)](https://huggingface.co/)
73
+ [![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey)](https://github.com/)
74
+
75
+ **Maki is a Python framework for multi-agent LLM applications that run wherever your models do: on your own hardware (through Ollama or llama.cpp), on a hosted API (OpenAI, Anthropic, OpenRouter), or a mix of both, with the same agent code.**
76
+
77
+ It is for developers who want to build and run tool-using agents on local models first, keep the option of moving any task to a hosted model by swapping one object, and have guardrails switched on by default while those agents touch files, the web, or a broker account.
78
+
79
+ ---
80
+
81
+ ## Why Maki
82
+
83
+ - **Local and hosted models are equals.** Ollama and llama.cpp are built-in backends, not add-ons, and sit next to OpenAI, Anthropic, and OpenRouter behind the same `LLMBackend` contract. Agents, workflows, and plugins never know which one they are talking to. An in-process HuggingFace Transformers backend is also included (manual install, see [below](#huggingface-backend)).
84
+ - **Guardrails on by default.** Requests Maki makes itself (Ollama, remote agents, web plugins) go through a hardened connector. URLs that come from content, such as pages and feeds, are checked against private and reserved address ranges at connect time (redirect hops included); operator-configured endpoints like a LAN Ollama host are allowed. Plugins are fail-closed: a model can only call methods a plugin explicitly lists, and destructive ones (file writes, FTP transfers, trades) stay disabled until you pass `Agent(allow_dangerous_tools=True)`. The trading plugin runs in paper mode unless you opt in to live.
85
+ - **Small core.** The base install has three dependencies (`requests`, `httpx`, `python-dotenv`). Everything else is an opt-in extra.
86
+ - **Agents as services.** `maki serve` exposes any agent over HTTP, and `AgentProxy` lets another process use it as if it were local, with a circuit breaker and optional bearer-token auth.
87
+ - **Batteries included.** 16 built-in plugins (files, web, market data, memory) and a workflow engine with dependency resolution, retries, parallel execution, and checkpoint/resume.
88
+
89
+ ### Who it is not for
90
+
91
+ Maki is young (0.x) and deliberately small. If you need a large catalog of third-party integrations, hosted tracing and observability, or a big community and ecosystem around your framework, one of the larger agent frameworks will serve you better.
92
+
93
+ ---
94
+
95
+ ## Backends
96
+
97
+ | Backend | Where inference runs | Class | Requires |
98
+ |---|---|---|---|
99
+ | Ollama | Your machine or LAN | `MakiLLama` | a running Ollama server |
100
+ | llama.cpp | Your machine or LAN | `MakiLlamaCpp` | `maki-framework[llamacpp]` and a running `llama serve` |
101
+ | HuggingFace Transformers | In-process, on your CPU/GPU | `HFBackend` | `torch`, `transformers`, `accelerate` (manual install, see [HuggingFace Backend](#huggingface-backend)) |
102
+ | OpenAI | Hosted | `MakiOpenAI` | `maki-framework[openai]` |
103
+ | Anthropic | Hosted | `MakiAnthropic` | `maki-framework[anthropic]` |
104
+ | OpenRouter | Hosted, any vendor-namespaced model | `MakiOpenRouter` | `maki-framework[openrouter]` |
105
+
106
+ The same agent runs on any of them; only the backend object changes:
107
+
108
+ ```python
109
+ from maki import MakiLLama, MakiLlamaCpp, MakiOpenAI, MakiAnthropic
110
+ from maki.agents import Agent
111
+
112
+ def reviewer(llm):
113
+ return Agent(
114
+ name="Reviewer",
115
+ maki_instance=llm,
116
+ role="code reviewer",
117
+ instructions="Focus on bugs, regressions, and missing validation.",
118
+ )
119
+
120
+ agent = reviewer(MakiLLama(model="gemma4:26b")) # local, via Ollama
121
+ # agent = reviewer(MakiLlamaCpp()) # local, via llama.cpp
122
+ # agent = reviewer(MakiOpenAI(model="gpt-4o")) # hosted
123
+ # agent = reviewer(MakiAnthropic(model="claude-sonnet-4-5")) # hosted
124
+
125
+ print(agent.execute_task("Review this design: a plugin system with file access."))
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Features
131
+
132
+ - `MakiLLama` — Ollama chat API with synchronous, streaming, async, and vision-capable workflows
133
+ - `MakiLlamaCpp` — llama.cpp `llama serve` (GGUF models) with streaming, async, vision, tool calling, separate reasoning output, embeddings, and reranking
134
+ - `MakiOpenAI` — OpenAI chat completions, including reasoning models (o3/o4)
135
+ - `MakiAnthropic` — Anthropic messages API (Claude Sonnet, Haiku, Opus)
136
+ - `HFBackend` — direct HuggingFace Transformers integration with quantization and device selection
137
+ - `Agent` — role-based agents with task execution, memory, reasoning, and plugin support; per-agent execution lock for concurrent safety
138
+ - `AgentManager` — multi-agent orchestration: sequential pipelines, collaborative tasks, and dependency-aware workflows with parallel batching and checkpoint/resume
139
+ - `ConversationMemory` — token-budgeted, pair-based conversation history shared by `Agent` (stateful mode) and `ChatSession`
140
+ - Native tool-calling for all backends (Ollama `tools=`, llama.cpp, OpenAI, Anthropic tool use) with multi-round execution and self-correction
141
+ - 16 built-in plugins covering files, web content, search, trading, and memory
142
+ - Distributed agent serving: `maki serve` exposes any agent over HTTP; `AgentProxy` consumes remote agents transparently
143
+ - Hardened HTTP connector: URL validation, private-address blocking, DNS pinning on the default path, typed error classification, and configurable timeouts (hosted-model traffic goes through the vendors' own SDKs)
144
+ - Fail-closed plugin security: every plugin declares `ALLOWED_METHODS`; destructive methods require explicit opt-in
145
+ - Explicit logging setup and a typed exception hierarchy
146
+
147
+ ---
148
+
149
+ ## Installation
150
+
151
+ ```bash
152
+ curl -fsSL https://raw.githubusercontent.com/BowlOfData/maki/main/install.sh | bash
153
+ ```
154
+
155
+ This clones the repo into `~/.maki`, installs it into an isolated virtual environment, and symlinks the `maki` command into `~/.local/bin` (override with the `MAKI_INSTALL_DIR` / `MAKI_BIN_DIR` env vars). Re-run it any time to update to the latest `main`.
156
+
157
+ ### From source
158
+
159
+ ```bash
160
+ pip install -e .
161
+ ```
162
+
163
+ For development tools:
164
+
165
+ ```bash
166
+ pip install -e ".[dev]"
167
+ ```
168
+
169
+ Some built-in plugins and backends rely on optional extras (defined in [pyproject.toml](pyproject.toml)):
170
+
171
+ - `maki-framework[web]` — `feedparser`, `readability-lxml`, `html2text` (web search / web-to-Markdown)
172
+ - `maki-framework[trends]` — `pytrends` (Google Trends)
173
+ - `maki-framework[alpaca]` — `alpaca-py` (market data, news, trading, streaming)
174
+ - `maki-framework[ftp]` — `paramiko` (FTP/SFTP)
175
+ - `maki-framework[gui]` — `PySide6` (desktop GUI)
176
+ - `maki-framework[openai]` — `openai` (OpenAI backend)
177
+ - `maki-framework[anthropic]` — `anthropic` (Anthropic backend)
178
+ - `maki-framework[openrouter]` — `openai` (OpenRouter backend, via its OpenAI-compatible API)
179
+ - `maki-framework[llamacpp]` — `openai` (llama.cpp backend, via the `llama serve` OpenAI-compatible API)
180
+ - `maki-framework[distributed]` — `fastapi`, `uvicorn`, `pyyaml` (agent server and proxies)
181
+ - `maki-framework[distributed-redis]` — `redis` (Redis workflow checkpoints)
182
+
183
+ Install everything with `pip install -e ".[all]"`.
184
+
185
+ ---
186
+
187
+ ## Configuration
188
+
189
+ Shared runtime defaults live in [maki/config.py](maki/config.py). All values are overridable via environment variables or a `.env` file (`python-dotenv` is supported).
190
+
191
+ | Variable | Description |
192
+ |---|---|
193
+ | `MAKI_OLLAMA_BASE_URL` | Full Ollama base URL |
194
+ | `MAKI_OLLAMA_HOST` | Ollama hostname |
195
+ | `MAKI_OLLAMA_PORT` | Ollama port |
196
+ | `MAKI_LLAMACPP_BASE_URL` | llama.cpp server URL (default `http://127.0.0.1:8080/v1`) |
197
+ | `MAKI_LLAMACPP_MODEL` | llama.cpp model name (default `local-model`; set it in router mode) |
198
+ | `LLAMACPP_API_KEY` | llama.cpp API key, only if the server was started with `--api-key` |
199
+ | `MAKI_DEFAULT_MODEL` | Default model name |
200
+ | `MAKI_DEFAULT_TEMPERATURE` | Sampling temperature |
201
+ | `MAKI_REQUEST_TIMEOUT` | Per-request timeout (seconds) |
202
+ | `MAKI_HTTP_TIMEOUT` | Low-level HTTP timeout |
203
+ | `MAKI_LOG_LEVEL` | Logging level |
204
+ | `MAKI_WEB_USER_AGENT` | User-agent string for web plugins |
205
+
206
+ ---
207
+
208
+ ## Quick Start
209
+
210
+ ### Basic request
211
+
212
+ ```python
213
+ from maki import MakiLLama
214
+
215
+ llm = MakiLLama(model="gemma4:26b")
216
+ response = llm.chat("Explain recursion in one sentence.")
217
+ print(response.content)
218
+ ```
219
+
220
+ ### Chat, streaming, and async
221
+
222
+ ```python
223
+ import asyncio
224
+ from maki import MakiLLama
225
+ from maki.objects import GenerationConfig
226
+
227
+ config = GenerationConfig(temperature=0.7, max_tokens=512)
228
+ llm = MakiLLama(model="gemma4:26b", config=config)
229
+
230
+ reply = llm.chat("Give me three project naming ideas.")
231
+ print(reply.content)
232
+
233
+ for chunk in llm.stream("Write a short haiku about testing"):
234
+ print(chunk, end="", flush=True)
235
+
236
+ async def main():
237
+ response = await llm.async_chat("Summarize the benefits of type hints.")
238
+ print(response.content)
239
+
240
+ asyncio.run(main())
241
+ ```
242
+
243
+ ### Stateful session
244
+
245
+ ```python
246
+ from maki import MakiLLama
247
+
248
+ llm = MakiLLama(model="gemma4:26b")
249
+ session = llm.session(system="You are a concise engineering assistant.")
250
+
251
+ session.say("We are building a release checklist.")
252
+ response = session.say("What should we verify before publishing a Python package?")
253
+ print(response.content)
254
+ ```
255
+
256
+ ### Hosted backends
257
+
258
+ ```python
259
+ from maki import MakiOpenAI, MakiAnthropic
260
+
261
+ # OpenAI
262
+ llm = MakiOpenAI(model="gpt-4o")
263
+ response = llm.chat("What is the capital of France?")
264
+
265
+ # Anthropic
266
+ llm = MakiAnthropic(model="claude-sonnet-4-5")
267
+ response = llm.chat("Summarize this code in one sentence.")
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Agents
273
+
274
+ ### Basic agent
275
+
276
+ ```python
277
+ from maki import MakiLLama
278
+ from maki.agents import Agent
279
+
280
+ llm = MakiLLama(model="gemma4:26b")
281
+ agent = Agent(
282
+ name="Reviewer",
283
+ maki_instance=llm,
284
+ role="code reviewer",
285
+ instructions="Focus on bugs, regressions, and missing validation.",
286
+ stateful=True,
287
+ )
288
+
289
+ result = agent.execute_task("Review this design: a plugin system with file access.")
290
+ print(result)
291
+ ```
292
+
293
+ ### Memory and reasoning helpers
294
+
295
+ ```python
296
+ agent.remember("repo", "maki")
297
+ print(agent.recall("repo"))
298
+
299
+ steps = agent.think_step_by_step("How should we structure plugin validation?")
300
+ subtasks = agent.decompose_task("Prepare this repository for a public release")
301
+ ```
302
+
303
+ ### Streaming task execution
304
+
305
+ ```python
306
+ for chunk in agent.stream_task("Draft a short changelog entry."):
307
+ print(chunk, end="", flush=True)
308
+ ```
309
+
310
+ ### Long-running tasks with `use_streaming`
311
+
312
+ By default, `execute_task` sends one blocking HTTP request. For tasks that exceed the configured timeout (default 120 s), set `use_streaming=True` — the timeout then applies per chunk rather than to the whole response.
313
+
314
+ ```python
315
+ agent = Agent(
316
+ name="Ranker",
317
+ maki_instance=llm,
318
+ role="content ranker",
319
+ use_streaming=True,
320
+ )
321
+
322
+ result = agent.execute_task("Rank these 50 articles by relevance: ...")
323
+ print(result)
324
+ ```
325
+
326
+ ---
327
+
328
+ ## Agent Manager and Workflows
329
+
330
+ `AgentManager` coordinates multiple agents and can run collaborative or dependency-aware workflows.
331
+
332
+ ```python
333
+ from maki import MakiLLama
334
+ from maki.agents import AgentManager, WorkflowTask
335
+
336
+ llm = MakiLLama(model="gemma4:26b")
337
+ manager = AgentManager(llm)
338
+
339
+ manager.add_agent("Researcher", role="researcher")
340
+ manager.add_agent("Writer", role="writer")
341
+
342
+ workflow = [
343
+ WorkflowTask(
344
+ name="research",
345
+ agent="Researcher",
346
+ task="Find the main public-release risks for this repository.",
347
+ ),
348
+ WorkflowTask(
349
+ name="summary",
350
+ agent="Writer",
351
+ task="Summarize the research into a release checklist.",
352
+ dependencies=["research"],
353
+ ),
354
+ ]
355
+
356
+ results = manager.run_workflow(workflow)
357
+ print(results["summary"]["result"])
358
+ ```
359
+
360
+ Supported manager patterns:
361
+
362
+ | Method | Behaviour |
363
+ |---|---|
364
+ | `assign_task()` | Route a single task to one named agent |
365
+ | `coordinate_agents()` | Sequential multi-agent pipeline with optional synthesis step |
366
+ | `collaborative_task()` | All agents work on the same task independently |
367
+ | `run_workflow()` | Dependency-aware execution with retries and optional parallel batches |
368
+
369
+ ---
370
+
371
+ ## Distributed Layer
372
+
373
+ Serve any agent over HTTP with `maki serve`:
374
+
375
+ ```bash
376
+ maki serve --config agent.yaml --host 127.0.0.1 --port 8100
377
+ ```
378
+
379
+ ```yaml
380
+ # agent.yaml
381
+ name: MyAgent
382
+ model: gemma4:26b
383
+ role: assistant
384
+ # backend: ollama | llamacpp | openai | anthropic | openrouter (default: ollama)
385
+ # base_url: http://127.0.0.1:8080/v1 # llamacpp only
386
+ plugins:
387
+ - web_search
388
+ - file_reader
389
+ ```
390
+
391
+ Connect to a remote agent from another process:
392
+
393
+ ```python
394
+ from maki.distributed.proxy import AgentProxy
395
+
396
+ agent = AgentProxy(name="MyAgent", base_url="http://127.0.0.1:8100")
397
+ result = agent.execute_task("Summarize the latest AI news.")
398
+ ```
399
+
400
+ `DistributedAgentManager` lets you mix local and remote agents in the same workflow.
401
+
402
+ ---
403
+
404
+ ## Plugins
405
+
406
+ Built-in plugins are registered in [maki/plugins/\_\_init\_\_.py](maki/plugins/__init__.py):
407
+
408
+ | Plugin | Description | Extra |
409
+ |---|---|---|
410
+ | `directory_reader` | List and inspect directory contents | — |
411
+ | `file_reader` | Read files from disk | — |
412
+ | `file_writer` | Write files to disk | — |
413
+ | `json_reader` | Parse and query JSON files | — |
414
+ | `image_classifier` | Classify images via a local model | — |
415
+ | `ocr` | Extract text from images (not in the default registry; load via `plugin_path`) | — |
416
+ | `web_search` | RSS, HackerNews, Reddit, GitHub Trending, Lobste.rs | `web` |
417
+ | `web_to_md` | Fetch a URL and convert to Markdown | `web` |
418
+ | `provider_updates` | Fetch LLM provider release notes | `web` |
419
+ | `trend_search` | Google Trends queries | `trends` |
420
+ | `ftp_client` | FTP/SFTP file transfers | `ftp` |
421
+ | `alpaca_data` | Crypto, equity, and forex bar and quote data | `alpaca` |
422
+ | `alpaca_news` | Financial news from Alpaca and RSS | `alpaca` |
423
+ | `alpaca_trading` | Submit and manage Alpaca trades | `alpaca` |
424
+ | `alpaca_stream` | Live crypto data stream | `alpaca` |
425
+ | `obsidian_memory` | Persistent note-based memory (Obsidian vault) | — |
426
+ | `rag_memory` | Retrieval-augmented memory with pluggable vector backends | — |
427
+
428
+ ### Loading a plugin in an agent
429
+
430
+ ```python
431
+ from maki import MakiLLama
432
+ from maki.agents import Agent
433
+
434
+ llm = MakiLLama(model="gemma4:26b")
435
+ agent = Agent(name="ToolUser", maki_instance=llm, role="assistant")
436
+ agent.load_plugin("file_reader")
437
+
438
+ result = agent.execute_task(
439
+ "Read the first lines of README.md and summarize them.",
440
+ use_plugins=True,
441
+ )
442
+ print(result)
443
+ ```
444
+
445
+ When `use_plugins=True` (or the backend supports native tool-calling), available plugin methods are advertised to the model and executed automatically. Destructive methods (file writes, trades, FTP deletes) require `Agent(allow_dangerous_tools=True)`.
446
+
447
+ ---
448
+
449
+ ## llama.cpp Backend
450
+
451
+ `MakiLlamaCpp` talks to a [llama.cpp](https://llama.app/docs/introduction) server, which runs GGUF models from Hugging Face or a local file. Install the extra and start a server:
452
+
453
+ ```bash
454
+ pip install "maki-framework[llamacpp]"
455
+ llama serve -hf ggml-org/gemma-4-e4b-it-GGUF:Q4_0 # listens on http://127.0.0.1:8080
456
+ ```
457
+
458
+ ```python
459
+ from maki import MakiLlamaCpp
460
+ from maki.objects import GenerationConfig
461
+
462
+ llm = MakiLlamaCpp(config=GenerationConfig(temperature=0.7, top_k=40))
463
+ print(llm.health()) # False while the model is still loading
464
+
465
+ response = llm.chat("What is the capital of France?")
466
+ print(response.content)
467
+ print(response.reasoning) # thinking text from reasoning models, else None
468
+
469
+ for chunk in llm.stream("Tell me a joke"):
470
+ print(chunk, end="", flush=True)
471
+ ```
472
+
473
+ - **Everything `MakiOpenAI` does** works unchanged: chat, streaming, async, vision (images as base64), sessions, and native tool calling with agents and plugins.
474
+ - **llama.cpp sampling settings** `top_k` and `repeat_penalty` from `GenerationConfig` are sent to the server.
475
+ - **Long generations:** `chat_collect()` (used by `Agent(use_streaming=True)`) streams internally, so the timeout applies per chunk instead of to the whole answer.
476
+ - **Router mode:** start `llama serve` without a model and pass the model name, e.g. `MakiLlamaCpp(model="ggml-org/gemma-3-4b-it-qat-GGUF:Q4_0")`. The server loads it on demand.
477
+ - **Other servers:** pass `base_url="http://192.168.1.20:8080/v1"` for a LAN host, and `api_key=` (or `LLAMACPP_API_KEY`) if it was started with `--api-key`.
478
+
479
+ Embeddings and reranking need a server started with `--embedding` or `--rerank`:
480
+
481
+ ```python
482
+ from maki.plugins.rag_memory import RagMemory
483
+
484
+ embedder = MakiLlamaCpp() # llama serve -hf unsloth/embeddinggemma-300m-GGUF --embedding
485
+ rag = RagMemory(dsn="memory://", embedder=embedder.embed)
486
+
487
+ reranker = MakiLlamaCpp() # llama serve -m reranker.gguf --rerank
488
+ for hit in reranker.rerank("What is a panda?", ["hi", "The giant panda is a bear."], top_n=1):
489
+ print(hit["relevance_score"], hit["document"])
490
+ ```
491
+
492
+ Chat requests go through the `openai` SDK; `health()`, `embed()` and `rerank()` go through Maki's connector, which allows loopback and LAN addresses for this operator-configured endpoint.
493
+
494
+ ---
495
+
496
+ ## HuggingFace Backend
497
+
498
+ `HFBackend` runs models directly via HuggingFace Transformers — no Ollama required.
499
+
500
+ `torch`, `transformers`, and `accelerate` are not installed with Maki (they are large and platform-specific), so install them first:
501
+
502
+ ```bash
503
+ pip install torch transformers accelerate # add bitsandbytes for 4/8-bit quantization
504
+ ```
505
+
506
+ ```python
507
+ from maki import HFBackend
508
+
509
+ llm = HFBackend(model_id="mistralai/Mistral-7B-Instruct-v0.3", device="cuda")
510
+ response = llm.chat("Explain attention mechanisms.")
511
+ print(response.content)
512
+ ```
513
+
514
+ Supports quantization (`load_in_4bit`, `load_in_8bit`) and device selection (`cpu`, `cuda`, `mps`; auto-detected when omitted). Remote model code is not executed unless you pass `trust_remote_code=True`.
515
+
516
+ ---
517
+
518
+ ## Architecture
519
+
520
+ <p align="center">
521
+ <img src="img/diagram.png" alt="Maki Architecture Diagram" width="900" />
522
+ </p>
523
+
524
+ The framework is organized into four layers on top of a shared infrastructure layer:
525
+
526
+ - **Public API** — `maki/__init__.py` lazy-loads all exports on first access
527
+ - **LLM Backends** — `MakiLLama`, `MakiOpenAI`, `MakiAnthropic`, `MakiOpenRouter`, `MakiLlamaCpp`, and `HFBackend` all implement the abstract `LLMBackend` contract
528
+ - **Agent System** — `Agent` composes `PluginHandler` and `ReasoningEngine` mixins; `AgentManager` orchestrates agents via `WorkflowTask` and `WorkflowState`
529
+ - **Distributed Layer** — `AgentServer` (FastAPI) exposes agents over HTTP; `AgentProxy` provides a remote-agent client with circuit-breaking; `DistributedAgentManager` mixes local and remote agents
530
+ - **Infrastructure** — `Connector` (hardened HTTP: URL validation, connect-time IP pinning by default), shared data classes, typed exceptions, runtime config, and structured logging
531
+
532
+ The Plugin System sits alongside the Agent layer: plugins are loaded on demand and invoked automatically when the LLM emits a `TOOL:` directive or via native tool-calling APIs (Ollama, OpenAI, Anthropic).
533
+
534
+ ---
535
+
536
+ ## Public API
537
+
538
+ Top-level imports exposed by `maki`:
539
+
540
+ - `MakiLLama`, `MakiOpenAI`, `MakiAnthropic`, `MakiOpenRouter`, `MakiLlamaCpp`, `HFBackend`
541
+ - `LLMBackend`, `BackendType`
542
+ - `Agent`, `AgentManager`
543
+ - `GenerationConfig`, `LLMResponse`, `Message`, `ToolCall`
544
+ - `ConversationMemory`, `RateLimiter`
545
+ - `Connector`, `Utils`
546
+ - `config`
547
+
548
+ All exports are lazy-loaded on first access.
549
+
550
+ ---
551
+
552
+ ## Desktop App
553
+
554
+ The repository includes a PySide6/QML desktop shell (requires `maki-framework[gui]`):
555
+
556
+ ```bash
557
+ maki-gui
558
+ ```
559
+
560
+ ---
561
+
562
+ ## Testing
563
+
564
+ ```bash
565
+ pytest
566
+ ```
567
+
568
+ 900+ tests covering backends, agents, workflows, plugins, connectors, distributed layer, and security-related behaviour. Tests marked `@pytest.mark.network` (requiring live external services) are excluded by default; run them explicitly with `pytest -m network`.
569
+
570
+ ---
571
+
572
+ ## Contributing
573
+
574
+ Contributions are welcome: bug fixes, documentation improvements, new plugins, and feature suggestions all help move the project forward. Open an issue or submit a pull request on GitHub.
575
+
576
+ If you are interested in this line of research, consider joining [Bowl of Data](https://bowlofdata.net/), an open-source AI research community.
577
+
578
+ ---
579
+
580
+ ## License
581
+
582
+ [MIT](LICENSE)