aixon 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aixon-0.1.0/.github/workflows/publish.yml +92 -0
- aixon-0.1.0/.gitignore +44 -0
- aixon-0.1.0/LICENSE +21 -0
- aixon-0.1.0/PKG-INFO +421 -0
- aixon-0.1.0/README.md +343 -0
- aixon-0.1.0/aixon/__init__.py +90 -0
- aixon-0.1.0/aixon/_interop/__init__.py +18 -0
- aixon-0.1.0/aixon/_interop/messages.py +98 -0
- aixon-0.1.0/aixon/_interop/tools.py +80 -0
- aixon-0.1.0/aixon/agent.py +163 -0
- aixon-0.1.0/aixon/agents/__init__.py +5 -0
- aixon-0.1.0/aixon/agents/llm_agent.py +75 -0
- aixon-0.1.0/aixon/agents/orchestrator.py +457 -0
- aixon-0.1.0/aixon/agents/tool_agent.py +245 -0
- aixon-0.1.0/aixon/cli.py +433 -0
- aixon-0.1.0/aixon/connector.py +209 -0
- aixon-0.1.0/aixon/discovery.py +27 -0
- aixon-0.1.0/aixon/embedding.py +71 -0
- aixon-0.1.0/aixon/exceptions.py +27 -0
- aixon-0.1.0/aixon/llm.py +91 -0
- aixon-0.1.0/aixon/logging.py +38 -0
- aixon-0.1.0/aixon/message.py +46 -0
- aixon-0.1.0/aixon/providers/__init__.py +25 -0
- aixon-0.1.0/aixon/providers/anthropic.py +30 -0
- aixon-0.1.0/aixon/providers/base.py +103 -0
- aixon-0.1.0/aixon/providers/google.py +30 -0
- aixon-0.1.0/aixon/providers/openai.py +30 -0
- aixon-0.1.0/aixon/py.typed +0 -0
- aixon-0.1.0/aixon/reasoning.py +83 -0
- aixon-0.1.0/aixon/registry.py +95 -0
- aixon-0.1.0/aixon/retriever.py +147 -0
- aixon-0.1.0/aixon/retrievers/__init__.py +5 -0
- aixon-0.1.0/aixon/retrievers/ragie.py +114 -0
- aixon-0.1.0/aixon/retrievers/tavily.py +109 -0
- aixon-0.1.0/aixon/retrievers/weaviate.py +198 -0
- aixon-0.1.0/aixon/runtime.py +42 -0
- aixon-0.1.0/aixon/server/__init__.py +6 -0
- aixon-0.1.0/aixon/server/adapters/__init__.py +3 -0
- aixon-0.1.0/aixon/server/adapters/anthropic.py +119 -0
- aixon-0.1.0/aixon/server/adapters/openai.py +197 -0
- aixon-0.1.0/aixon/server/protocol.py +109 -0
- aixon-0.1.0/aixon/server/server.py +250 -0
- aixon-0.1.0/aixon/server/usage.py +43 -0
- aixon-0.1.0/aixon/state.py +43 -0
- aixon-0.1.0/docs/agents.md +301 -0
- aixon-0.1.0/docs/architecture.md +171 -0
- aixon-0.1.0/docs/cli.md +212 -0
- aixon-0.1.0/docs/orchestrator.md +242 -0
- aixon-0.1.0/docs/quickstart.md +218 -0
- aixon-0.1.0/docs/retrieval.md +291 -0
- aixon-0.1.0/docs/retrievers.md +74 -0
- aixon-0.1.0/docs/server.md +318 -0
- aixon-0.1.0/examples/support_assistant/.env.example +18 -0
- aixon-0.1.0/examples/support_assistant/README.md +164 -0
- aixon-0.1.0/examples/support_assistant/agents/__init__.py +3 -0
- aixon-0.1.0/examples/support_assistant/agents/knowledge_agent.py +32 -0
- aixon-0.1.0/examples/support_assistant/agents/orders_agent.py +45 -0
- aixon-0.1.0/examples/support_assistant/agents/support.py +44 -0
- aixon-0.1.0/examples/support_assistant/agents/triage.py +28 -0
- aixon-0.1.0/examples/support_assistant/connectors/__init__.py +1 -0
- aixon-0.1.0/examples/support_assistant/connectors/orders.py +61 -0
- aixon-0.1.0/examples/support_assistant/knowledge/__init__.py +1 -0
- aixon-0.1.0/examples/support_assistant/knowledge/corpus.py +52 -0
- aixon-0.1.0/examples/support_assistant/knowledge/faq_retriever.py +67 -0
- aixon-0.1.0/examples/support_assistant/llm_config.py +30 -0
- aixon-0.1.0/examples/support_assistant/main.py +43 -0
- aixon-0.1.0/examples/support_assistant/providers/__init__.py +2 -0
- aixon-0.1.0/examples/support_assistant/providers/demo.py +152 -0
- aixon-0.1.0/examples/support_assistant/requirements.txt +12 -0
- aixon-0.1.0/pyproject.toml +81 -0
- aixon-0.1.0/tests/_cli_fakes.py +63 -0
- aixon-0.1.0/tests/_fakes.py +135 -0
- aixon-0.1.0/tests/_server_fakes.py +77 -0
- aixon-0.1.0/tests/conftest.py +10 -0
- aixon-0.1.0/tests/test_adapter_anthropic.py +124 -0
- aixon-0.1.0/tests/test_adapter_openai.py +129 -0
- aixon-0.1.0/tests/test_adapter_stream_multifield.py +70 -0
- aixon-0.1.0/tests/test_agent.py +71 -0
- aixon-0.1.0/tests/test_as_tool.py +46 -0
- aixon-0.1.0/tests/test_as_tool_neutral.py +38 -0
- aixon-0.1.0/tests/test_async_agents.py +144 -0
- aixon-0.1.0/tests/test_async_cancellation.py +90 -0
- aixon-0.1.0/tests/test_async_retriever.py +115 -0
- aixon-0.1.0/tests/test_async_tools.py +80 -0
- aixon-0.1.0/tests/test_cli_chat_inprocess.py +105 -0
- aixon-0.1.0/tests/test_cli_chat_remote.py +108 -0
- aixon-0.1.0/tests/test_cli_fakes.py +37 -0
- aixon-0.1.0/tests/test_cli_integration.py +91 -0
- aixon-0.1.0/tests/test_cli_list.py +64 -0
- aixon-0.1.0/tests/test_cli_new.py +90 -0
- aixon-0.1.0/tests/test_cli_serve.py +127 -0
- aixon-0.1.0/tests/test_cli_version.py +24 -0
- aixon-0.1.0/tests/test_connector.py +135 -0
- aixon-0.1.0/tests/test_connector_async.py +64 -0
- aixon-0.1.0/tests/test_coverage_extra.py +89 -0
- aixon-0.1.0/tests/test_discovery.py +50 -0
- aixon-0.1.0/tests/test_embedding.py +54 -0
- aixon-0.1.0/tests/test_exceptions.py +22 -0
- aixon-0.1.0/tests/test_exports.py +48 -0
- aixon-0.1.0/tests/test_fake_drives_create_agent.py +68 -0
- aixon-0.1.0/tests/test_http_tool_connector.py +139 -0
- aixon-0.1.0/tests/test_interop_tool_roundtrip.py +39 -0
- aixon-0.1.0/tests/test_langchain.py +107 -0
- aixon-0.1.0/tests/test_llm.py +75 -0
- aixon-0.1.0/tests/test_llm_agent.py +136 -0
- aixon-0.1.0/tests/test_logging.py +64 -0
- aixon-0.1.0/tests/test_message.py +35 -0
- aixon-0.1.0/tests/test_nested_reasoning.py +96 -0
- aixon-0.1.0/tests/test_openai_embedding.py +76 -0
- aixon-0.1.0/tests/test_orchestration_packaging.py +42 -0
- aixon-0.1.0/tests/test_orchestrator_cycle.py +62 -0
- aixon-0.1.0/tests/test_orchestrator_fakes_smoke.py +43 -0
- aixon-0.1.0/tests/test_orchestrator_guards.py +79 -0
- aixon-0.1.0/tests/test_orchestrator_reasoning.py +42 -0
- aixon-0.1.0/tests/test_orchestrator_tier1.py +82 -0
- aixon-0.1.0/tests/test_orchestrator_tier1_routing.py +133 -0
- aixon-0.1.0/tests/test_orchestrator_tier2.py +117 -0
- aixon-0.1.0/tests/test_orchestrator_tier3.py +48 -0
- aixon-0.1.0/tests/test_plan7_integration.py +79 -0
- aixon-0.1.0/tests/test_protocol.py +75 -0
- aixon-0.1.0/tests/test_providers.py +86 -0
- aixon-0.1.0/tests/test_reasoning.py +67 -0
- aixon-0.1.0/tests/test_registry.py +73 -0
- aixon-0.1.0/tests/test_registry_reset_reregisters.py +37 -0
- aixon-0.1.0/tests/test_retriever.py +116 -0
- aixon-0.1.0/tests/test_retriever_as_tool.py +103 -0
- aixon-0.1.0/tests/test_retriever_live_smoke.py +62 -0
- aixon-0.1.0/tests/test_retriever_ragie.py +132 -0
- aixon-0.1.0/tests/test_retriever_tavily.py +77 -0
- aixon-0.1.0/tests/test_retriever_weaviate.py +152 -0
- aixon-0.1.0/tests/test_server.py +179 -0
- aixon-0.1.0/tests/test_server_async_nonblocking.py +65 -0
- aixon-0.1.0/tests/test_server_fakes.py +47 -0
- aixon-0.1.0/tests/test_server_multi_adapter.py +126 -0
- aixon-0.1.0/tests/test_sp1_genparams.py +51 -0
- aixon-0.1.0/tests/test_sp1_pyproject.py +12 -0
- aixon-0.1.0/tests/test_sp1_routes.py +42 -0
- aixon-0.1.0/tests/test_sp1_stream_modes.py +94 -0
- aixon-0.1.0/tests/test_sp1_usage.py +45 -0
- aixon-0.1.0/tests/test_state.py +49 -0
- aixon-0.1.0/tests/test_tool_agent_deadline.py +42 -0
- aixon-0.1.0/tests/test_tool_agent_invoke.py +109 -0
- aixon-0.1.0/tests/test_tool_agent_stream.py +66 -0
- aixon-0.1.0/tests/test_tools.py +65 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
name: Test & Publish
|
|
2
|
+
|
|
3
|
+
# Fully automated pipeline (mirrors restmcp): every push to main runs the suite
|
|
4
|
+
# with coverage, uploads to Codecov, then publishes to TestPyPI and PyPI via
|
|
5
|
+
# Trusted Publishing (OIDC — no API token), and tags a GitHub Release.
|
|
6
|
+
# One-time setup:
|
|
7
|
+
# - PyPI: trusted publisher → project `aixon`, owner `JorgeHSantana`,
|
|
8
|
+
# repo `aixon`, workflow `publish.yml`, environment `pypi`.
|
|
9
|
+
# - TestPyPI: trusted publisher → same, workflow `publish.yml`, env `testpypi`.
|
|
10
|
+
# - Repo secret CODECOV_TOKEN (Settings → Secrets → Actions).
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
push:
|
|
14
|
+
branches: [main]
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v5
|
|
21
|
+
- uses: actions/setup-python@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.13"
|
|
24
|
+
cache: pip
|
|
25
|
+
- run: python -m pip install --upgrade pip
|
|
26
|
+
- run: pip install -e ".[all,dev]"
|
|
27
|
+
- run: pytest --cov=aixon --cov-report=xml
|
|
28
|
+
- uses: codecov/codecov-action@v5
|
|
29
|
+
with:
|
|
30
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
31
|
+
files: coverage.xml
|
|
32
|
+
|
|
33
|
+
publish-testpypi:
|
|
34
|
+
needs: test
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
environment: testpypi
|
|
37
|
+
permissions:
|
|
38
|
+
id-token: write # required for Trusted Publishing
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v5
|
|
41
|
+
- uses: actions/setup-python@v6
|
|
42
|
+
with:
|
|
43
|
+
python-version: "3.13"
|
|
44
|
+
- run: python -m pip install --upgrade build
|
|
45
|
+
- run: python -m build
|
|
46
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
47
|
+
with:
|
|
48
|
+
repository-url: https://test.pypi.org/legacy/
|
|
49
|
+
skip-existing: true
|
|
50
|
+
|
|
51
|
+
publish-pypi:
|
|
52
|
+
needs: publish-testpypi
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
environment: pypi
|
|
55
|
+
permissions:
|
|
56
|
+
id-token: write # required for Trusted Publishing
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v5
|
|
59
|
+
- uses: actions/setup-python@v6
|
|
60
|
+
with:
|
|
61
|
+
python-version: "3.13"
|
|
62
|
+
- run: python -m pip install --upgrade build
|
|
63
|
+
- run: python -m build
|
|
64
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
65
|
+
with:
|
|
66
|
+
skip-existing: true # no-op when the version already exists — keeps pushes green
|
|
67
|
+
|
|
68
|
+
github-release:
|
|
69
|
+
needs: publish-pypi
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
permissions:
|
|
72
|
+
contents: write
|
|
73
|
+
steps:
|
|
74
|
+
- uses: actions/checkout@v5
|
|
75
|
+
with:
|
|
76
|
+
fetch-depth: 0
|
|
77
|
+
- name: Read version
|
|
78
|
+
id: ver
|
|
79
|
+
run: echo "version=$(grep -m1 '^version' pyproject.toml | sed -E 's/.*"(.*)".*/\1/')" >> "$GITHUB_OUTPUT"
|
|
80
|
+
- name: Tag and publish a GitHub Release (idempotent)
|
|
81
|
+
env:
|
|
82
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
83
|
+
run: |
|
|
84
|
+
tag="v${{ steps.ver.outputs.version }}"
|
|
85
|
+
if gh release view "$tag" >/dev/null 2>&1; then
|
|
86
|
+
echo "Release $tag already exists — skipping."
|
|
87
|
+
else
|
|
88
|
+
gh release create "$tag" \
|
|
89
|
+
--title "$tag" \
|
|
90
|
+
--generate-notes \
|
|
91
|
+
--target "$GITHUB_SHA"
|
|
92
|
+
fi
|
aixon-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Byte-compiled / optimized
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
*.so
|
|
7
|
+
.Python
|
|
8
|
+
|
|
9
|
+
# Packaging / build
|
|
10
|
+
*.egg
|
|
11
|
+
*.egg-info/
|
|
12
|
+
.eggs/
|
|
13
|
+
dist/
|
|
14
|
+
build/
|
|
15
|
+
|
|
16
|
+
# Virtualenvs
|
|
17
|
+
env/
|
|
18
|
+
venv/
|
|
19
|
+
.venv/
|
|
20
|
+
|
|
21
|
+
# Env / secrets
|
|
22
|
+
.env
|
|
23
|
+
.env.*
|
|
24
|
+
!.env.example
|
|
25
|
+
|
|
26
|
+
# Tests / coverage
|
|
27
|
+
.pytest_cache/
|
|
28
|
+
.coverage
|
|
29
|
+
coverage.xml
|
|
30
|
+
htmlcov/
|
|
31
|
+
*.cover
|
|
32
|
+
.tox/
|
|
33
|
+
|
|
34
|
+
# Tooling caches
|
|
35
|
+
.ruff_cache/
|
|
36
|
+
.mypy_cache/
|
|
37
|
+
|
|
38
|
+
# Internal scratch (SDD journal — not part of the package)
|
|
39
|
+
.superpowers/
|
|
40
|
+
|
|
41
|
+
# Editors / OS
|
|
42
|
+
.vscode/
|
|
43
|
+
.idea/
|
|
44
|
+
.DS_Store
|
aixon-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JorgeHSantana
|
|
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.
|
aixon-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aixon
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Declarative AI-agent framework — composable agents, multi-agent orchestration, and a protocol-decoupled server
|
|
5
|
+
Project-URL: Homepage, https://github.com/JorgeHSantana/aixon
|
|
6
|
+
Project-URL: Repository, https://github.com/JorgeHSantana/aixon
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/JorgeHSantana/aixon/issues
|
|
8
|
+
Author-email: Jorge Henrique Moreira Santana <jorge.henrique.moreira.santana@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agents,ai,framework,langgraph,llm,openai,orchestration
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Requires-Dist: langchain-core>=1.0
|
|
25
|
+
Requires-Dist: langchain>=1.0
|
|
26
|
+
Requires-Dist: langgraph>=1.0
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: click>=8.0; extra == 'all'
|
|
29
|
+
Requires-Dist: fastapi>=0.100; extra == 'all'
|
|
30
|
+
Requires-Dist: flashrank>=0.2; extra == 'all'
|
|
31
|
+
Requires-Dist: httpx>=0.27; extra == 'all'
|
|
32
|
+
Requires-Dist: langchain-anthropic>=0.2; extra == 'all'
|
|
33
|
+
Requires-Dist: langchain-google-genai>=2.0; extra == 'all'
|
|
34
|
+
Requires-Dist: langchain-openai>=0.2; extra == 'all'
|
|
35
|
+
Requires-Dist: langchain-text-splitters>=1; extra == 'all'
|
|
36
|
+
Requires-Dist: langchain-weaviate>=0.0.7; extra == 'all'
|
|
37
|
+
Requires-Dist: openai>=1.0; extra == 'all'
|
|
38
|
+
Requires-Dist: pydantic>=2.0; extra == 'all'
|
|
39
|
+
Requires-Dist: ragie>=2; extra == 'all'
|
|
40
|
+
Requires-Dist: tavily-python>=0.7; extra == 'all'
|
|
41
|
+
Requires-Dist: tiktoken>=0.7; extra == 'all'
|
|
42
|
+
Requires-Dist: uvicorn[standard]>=0.20; extra == 'all'
|
|
43
|
+
Requires-Dist: weaviate-client>=4; extra == 'all'
|
|
44
|
+
Provides-Extra: anthropic
|
|
45
|
+
Requires-Dist: langchain-anthropic>=0.2; extra == 'anthropic'
|
|
46
|
+
Provides-Extra: cli
|
|
47
|
+
Requires-Dist: click>=8.0; extra == 'cli'
|
|
48
|
+
Requires-Dist: openai>=1.0; extra == 'cli'
|
|
49
|
+
Provides-Extra: dev
|
|
50
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
51
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
52
|
+
Provides-Extra: google
|
|
53
|
+
Requires-Dist: langchain-google-genai>=2.0; extra == 'google'
|
|
54
|
+
Provides-Extra: openai
|
|
55
|
+
Requires-Dist: langchain-openai>=0.2; extra == 'openai'
|
|
56
|
+
Provides-Extra: openai-embedding
|
|
57
|
+
Requires-Dist: langchain-openai>=0.2; extra == 'openai-embedding'
|
|
58
|
+
Provides-Extra: ragie
|
|
59
|
+
Requires-Dist: ragie>=2; extra == 'ragie'
|
|
60
|
+
Provides-Extra: rerank
|
|
61
|
+
Requires-Dist: flashrank>=0.2; extra == 'rerank'
|
|
62
|
+
Provides-Extra: retrieval
|
|
63
|
+
Requires-Dist: httpx>=0.27; extra == 'retrieval'
|
|
64
|
+
Provides-Extra: server
|
|
65
|
+
Requires-Dist: fastapi>=0.100; extra == 'server'
|
|
66
|
+
Requires-Dist: httpx>=0.27; extra == 'server'
|
|
67
|
+
Requires-Dist: pydantic>=2.0; extra == 'server'
|
|
68
|
+
Requires-Dist: uvicorn[standard]>=0.20; extra == 'server'
|
|
69
|
+
Provides-Extra: tavily
|
|
70
|
+
Requires-Dist: tavily-python>=0.7; extra == 'tavily'
|
|
71
|
+
Provides-Extra: tiktoken
|
|
72
|
+
Requires-Dist: tiktoken>=0.7; extra == 'tiktoken'
|
|
73
|
+
Provides-Extra: weaviate
|
|
74
|
+
Requires-Dist: langchain-text-splitters>=1; extra == 'weaviate'
|
|
75
|
+
Requires-Dist: langchain-weaviate>=0.0.7; extra == 'weaviate'
|
|
76
|
+
Requires-Dist: weaviate-client>=4; extra == 'weaviate'
|
|
77
|
+
Description-Content-Type: text/markdown
|
|
78
|
+
|
|
79
|
+
# aixon
|
|
80
|
+
|
|
81
|
+
> One framework. Declarative agents, multi-agent orchestration, and a protocol-decoupled server.
|
|
82
|
+
|
|
83
|
+
[](https://github.com/JorgeHSantana/aixon/actions/workflows/publish.yml)
|
|
84
|
+
[](https://codecov.io/gh/JorgeHSantana/aixon)
|
|
85
|
+
[](https://pypi.org/project/aixon/)
|
|
86
|
+
[](https://pypi.org/project/aixon/)
|
|
87
|
+
[](LICENSE)
|
|
88
|
+
|
|
89
|
+
`aixon` is a Python framework for building AI-agent systems. Subclass an agent type,
|
|
90
|
+
declare your LLM and tools as class attributes, and the agent self-registers — no
|
|
91
|
+
wiring, no routing table. Connect agents into multi-agent graphs with
|
|
92
|
+
`Orchestrator`. Serve them over any wire format through a pluggable
|
|
93
|
+
`ProtocolAdapter`. Run the whole thing locally or expose it as an API that any
|
|
94
|
+
OpenAI-compatible client can reach.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Architecture
|
|
99
|
+
|
|
100
|
+
```mermaid
|
|
101
|
+
graph LR
|
|
102
|
+
Client["🤖 Client / LLM"] -->|"HTTP · SSE"| SA["Server<br/>(ProtocolAdapter)"]
|
|
103
|
+
SA --> R["Registry"]
|
|
104
|
+
R --> A["Agent<br/>(LLMAgent · ToolAgent · Orchestrator)"]
|
|
105
|
+
A --> LLM["LLM<br/>(Provider)"]
|
|
106
|
+
A --> T["Tools<br/>(Retriever · Connector · Agent)"]
|
|
107
|
+
A --> O["Orchestrator<br/>→ nodes (Agents)"]
|
|
108
|
+
|
|
109
|
+
style SA fill:#4f46e5,color:#fff,stroke:none
|
|
110
|
+
style A fill:#7c3aed,color:#fff,stroke:none
|
|
111
|
+
style LLM fill:#9333ea,color:#fff,stroke:none
|
|
112
|
+
style T fill:#a855f7,color:#fff,stroke:none
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The **neutral boundary** is the key design principle: every agent speaks only
|
|
116
|
+
`Message[]` in and `Message`/`Chunk` out — no provider type, no wire type ever
|
|
117
|
+
crosses into the agent runtime. Protocol adapters translate on the outside;
|
|
118
|
+
provider SDKs stay hidden inside `LLM`.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Installation
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
pip install aixon # core: langchain + langgraph — agents work out of the box
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`langchain`/`langchain-core`/`langgraph` are mandatory core dependencies. The
|
|
129
|
+
optional extras add the outer layers:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
pip install "aixon[server]" # FastAPI + uvicorn + httpx — serve agents as an API
|
|
133
|
+
pip install "aixon[cli]" # click + openai — the `aixon` command + remote chat
|
|
134
|
+
pip install "aixon[openai]" # OpenAI provider binding (langchain-openai)
|
|
135
|
+
pip install "aixon[anthropic]" # Anthropic provider binding
|
|
136
|
+
pip install "aixon[google]" # Google provider binding
|
|
137
|
+
pip install "aixon[retrieval]" # httpx — Connector / HttpToolConnector
|
|
138
|
+
pip install "aixon[openai-embedding]" # langchain-openai — OpenAIEmbedding
|
|
139
|
+
pip install "aixon[weaviate]" # Weaviate vector-store Retriever
|
|
140
|
+
pip install "aixon[ragie]" # Ragie managed-RAG Retriever
|
|
141
|
+
pip install "aixon[tavily]" # Tavily web-search Retriever
|
|
142
|
+
pip install "aixon[rerank]" # flashrank reranking (for Weaviate)
|
|
143
|
+
pip install "aixon[tiktoken]" # token counting for the server `usage` field
|
|
144
|
+
pip install "aixon[all]" # everything above
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 60-second quickstart
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# 1. Scaffold a consumer project
|
|
153
|
+
aixon new my-agents
|
|
154
|
+
cd my-agents
|
|
155
|
+
pip install -e ".[all]"
|
|
156
|
+
|
|
157
|
+
# 2. Start the interactive chat
|
|
158
|
+
aixon chat
|
|
159
|
+
|
|
160
|
+
# 3. Or serve the OpenAI-compatible API
|
|
161
|
+
aixon serve
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Or inline — no scaffolding needed:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
# agents/hello.py
|
|
168
|
+
from aixon import LLMAgent, LLM
|
|
169
|
+
|
|
170
|
+
class HelloAgent(LLMAgent):
|
|
171
|
+
llm = LLM("gpt-4o-mini", temperature=0.2)
|
|
172
|
+
description = "Greets the user"
|
|
173
|
+
prompt = "You are a concise greeter. Reply in one sentence."
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
# main.py
|
|
178
|
+
from aixon import autodiscover, Message
|
|
179
|
+
from aixon.registry import get_registry
|
|
180
|
+
|
|
181
|
+
autodiscover("agents")
|
|
182
|
+
agent = get_registry().resolve("helloagent")
|
|
183
|
+
reply = agent.invoke([Message(role="user", content="Hi!")])
|
|
184
|
+
print(reply.content)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
python main.py
|
|
189
|
+
# → Hi there! How can I help you today?
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## The Agent model
|
|
195
|
+
|
|
196
|
+
Everything in `aixon` is an `Agent` — a single callable unit with a uniform
|
|
197
|
+
interface:
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
agent.invoke(messages: list[Message]) -> Message
|
|
201
|
+
agent.stream(messages: list[Message]) -> Iterator[Chunk]
|
|
202
|
+
agent.ainvoke(messages: list[Message]) -> Message # async
|
|
203
|
+
agent.astream(messages: list[Message]) -> AsyncIterator[Chunk]
|
|
204
|
+
agent.as_tool(name=None, description=None) -> AgentTool
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Sync is the default; `ainvoke`/`astream` are **additive** and run non-blocking
|
|
208
|
+
(native for `LLMAgent`/`ToolAgent`/`Orchestrator`, a thread-bridge for custom
|
|
209
|
+
sync agents). The server `await`s them, so concurrent requests don't serialize.
|
|
210
|
+
|
|
211
|
+
Three concrete subtypes cover the common cases. Pick the one that matches what
|
|
212
|
+
you need:
|
|
213
|
+
|
|
214
|
+
| Subtype | When to use | Suffix required |
|
|
215
|
+
|---|---|---|
|
|
216
|
+
| `LLMAgent` | Direct LLM call — no tools, no loop | `*Agent` |
|
|
217
|
+
| `ToolAgent` | LLM + tool-calling loop (LangGraph `create_agent`) | `*Agent` |
|
|
218
|
+
| `Orchestrator` | Multiple agents coordinated by a graph | `*Orchestrator` |
|
|
219
|
+
|
|
220
|
+
**Suffix rule:** every concrete subclass name must end with its declared suffix.
|
|
221
|
+
Violating it raises `NamingError` at import time — before the server starts.
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
class Greeter(LLMAgent): # ← raises NamingError: missing 'Agent' suffix
|
|
225
|
+
...
|
|
226
|
+
|
|
227
|
+
class GreeterAgent(LLMAgent): # ← correct
|
|
228
|
+
...
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## LLMAgent — direct LLM call
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
from aixon import LLMAgent, LLM
|
|
237
|
+
|
|
238
|
+
class PlannerAgent(LLMAgent):
|
|
239
|
+
llm = LLM("gpt-4o-mini", temperature=0.2)
|
|
240
|
+
description = "Strategic planner"
|
|
241
|
+
prompt = "You plan step-by-step actions for complex goals."
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Attributes:
|
|
245
|
+
|
|
246
|
+
| Attribute | Type | Description |
|
|
247
|
+
|---|---|---|
|
|
248
|
+
| `llm` | `LLM` | **Required.** The language model to use. |
|
|
249
|
+
| `prompt` | `str` | Optional system prompt prepended to every conversation. |
|
|
250
|
+
| `description` | `str` | Human-readable purpose (shown in `aixon list`). |
|
|
251
|
+
| `name` | `str` | Registry name (defaults to lowercased class name). |
|
|
252
|
+
| `aliases` | `list[str]` | Alternate names for registry resolution. |
|
|
253
|
+
| `hidden` | `bool` | Exclude from `aixon chat` menu and `public()` listing. |
|
|
254
|
+
|
|
255
|
+
`aixon list` output (no header, one agent per line):
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
greeteragent [LLMAgent] Friendly greeter
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
See [docs/agents.md](docs/agents.md) for `ToolAgent` and full API reference.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Orchestrator — multi-agent graphs
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
from aixon import Orchestrator, LLM
|
|
269
|
+
|
|
270
|
+
class SupportOrchestrator(Orchestrator):
|
|
271
|
+
supervisor = LLM("gpt-4o-mini") # routes each turn to a worker
|
|
272
|
+
agents = [BillingAgent, TechAgent, PlannerAgent] # your own LLMAgent/ToolAgent classes
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Three tiers — pick by complexity. See [docs/orchestrator.md](docs/orchestrator.md).
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Retrieval — Retriever, Connector, Embedding
|
|
280
|
+
|
|
281
|
+
`Retriever` is the base class for any agent that fetches context. Name it with a
|
|
282
|
+
`*Retriever` suffix and declare `type_access` to control read/write permissions
|
|
283
|
+
(`TypeAccess.READ`, `TypeAccess.WRITE`, or `TypeAccess.ALL`).
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from aixon import Retriever, TypeAccess
|
|
287
|
+
|
|
288
|
+
class LibraryRetriever(Retriever):
|
|
289
|
+
description = "Fetches relevant documents from the knowledge base"
|
|
290
|
+
type_access = TypeAccess.READ
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Every `Retriever` has a sync `search` and a native async `asearch`; `as_tool()`
|
|
294
|
+
returns a dual tool that works on both the sync and async agent paths.
|
|
295
|
+
|
|
296
|
+
`Connector` is an HTTP base class for wrapping external APIs (`base_url_env` /
|
|
297
|
+
`auth_token_env`, sync `get`/`post` and async `aget`/`apost`). `HttpToolConnector`
|
|
298
|
+
builds on it for HTTP-JSON tool servers.
|
|
299
|
+
|
|
300
|
+
`Embedding` is the vector-embedding ABC; the built-in implementation is
|
|
301
|
+
`OpenAIEmbedding`.
|
|
302
|
+
|
|
303
|
+
**Vendor retrievers** ship behind optional extras — each a neutral `Retriever`,
|
|
304
|
+
lazy (the vendor SDK is imported only on use) and async-native:
|
|
305
|
+
|
|
306
|
+
| Retriever | Extra | Backend |
|
|
307
|
+
|---|---|---|
|
|
308
|
+
| `WeaviateRetriever` | `aixon[weaviate]` | Weaviate vector store (+ `aixon[rerank]` for flashrank) |
|
|
309
|
+
| `RagieRetriever` | `aixon[ragie]` | Ragie managed RAG |
|
|
310
|
+
| `TavilyRetriever` | `aixon[tavily]` | Tavily web search |
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
from aixon import Retriever, TypeAccess, Connector, Embedding, OpenAIEmbedding
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
See [docs/retrieval.md](docs/retrieval.md) (ABCs) and
|
|
317
|
+
[docs/retrievers.md](docs/retrievers.md) (vendor backends).
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Server
|
|
322
|
+
|
|
323
|
+
```python
|
|
324
|
+
from aixon import Server, autodiscover
|
|
325
|
+
|
|
326
|
+
autodiscover("agents")
|
|
327
|
+
server = Server()
|
|
328
|
+
server.serve(host="0.0.0.0", port=8000)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Any OpenAI-compatible client works out of the box:
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
from openai import OpenAI
|
|
335
|
+
client = OpenAI(base_url="http://localhost:8000/v1", api_key="test")
|
|
336
|
+
response = client.chat.completions.create(
|
|
337
|
+
model="planneragent",
|
|
338
|
+
messages=[{"role": "user", "content": "Plan a trip to Tokyo."}],
|
|
339
|
+
)
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
See [docs/server.md](docs/server.md) for Anthropic adapter, auth, and SSE streaming.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Environment variables
|
|
347
|
+
|
|
348
|
+
| Variable | Default | Description |
|
|
349
|
+
|---|---|---|
|
|
350
|
+
| `LOG_LEVEL` | `INFO` | Framework log level: `DEBUG`, `INFO`, `WARNING`, `ERROR`. |
|
|
351
|
+
| `AUTH_API_KEY` | _(disabled)_ | Bearer token for the server. Unset = no auth. Multiple keys comma-separated. |
|
|
352
|
+
| `OPENAI_API_KEY` | _(required for OpenAI)_ | API key for the OpenAI provider. |
|
|
353
|
+
| `ANTHROPIC_API_KEY` | _(required for Anthropic)_ | API key for the Anthropic provider. |
|
|
354
|
+
| `GOOGLE_API_KEY` | _(required for Google)_ | API key for the Google provider. |
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Naming conventions
|
|
359
|
+
|
|
360
|
+
Suffix violations raise `NamingError` at import time — the server never starts
|
|
361
|
+
with a mis-named class.
|
|
362
|
+
|
|
363
|
+
| Base class | Required suffix | Example |
|
|
364
|
+
|---|---|---|
|
|
365
|
+
| `LLMAgent` | `*Agent` | `PlannerAgent` |
|
|
366
|
+
| `ToolAgent` | `*Agent` | `DiagnosisAgent` |
|
|
367
|
+
| `Orchestrator` | `*Orchestrator` | `SupportOrchestrator` |
|
|
368
|
+
| `Retriever` | `*Retriever` | `LibraryRetriever` |
|
|
369
|
+
| `Connector` | `*Connector` | `CRMConnector` |
|
|
370
|
+
|
|
371
|
+
Abstract intermediate classes (declared with `abstract=True`) are exempt and
|
|
372
|
+
never registered.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Documentation
|
|
377
|
+
|
|
378
|
+
- [Architecture](docs/architecture.md) — layers, neutral boundary, protocol decoupling
|
|
379
|
+
- [Agents](docs/agents.md) — `LLMAgent`, `ToolAgent`, declarative API, `as_tool`, async
|
|
380
|
+
- [Orchestrator](docs/orchestrator.md) — three tiers, entry/topology, branching, recursion guards
|
|
381
|
+
- [Server](docs/server.md) — `ProtocolAdapter`, adapters, auth, SSE
|
|
382
|
+
- [Retrieval](docs/retrieval.md) — `Retriever`, `Embedding`, `Connector`
|
|
383
|
+
- [Vendor retrievers](docs/retrievers.md) — `Weaviate`, `Ragie`, `Tavily`
|
|
384
|
+
- [CLI](docs/cli.md) — `chat`, `new`, `serve`, `list`
|
|
385
|
+
- [Quickstart](docs/quickstart.md) — consumer project walkthrough
|
|
386
|
+
- [Example](examples/support_assistant) — a complete multi-agent support assistant, runnable offline
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Dependencies
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
langchain >= 1.0 (core)
|
|
394
|
+
langchain-core >= 1.0 (core)
|
|
395
|
+
langgraph >= 1.0 (core)
|
|
396
|
+
fastapi / uvicorn / pydantic (server extra)
|
|
397
|
+
httpx >= 0.27 (server / retrieval extra)
|
|
398
|
+
click / openai (cli extra — `aixon` command + remote chat)
|
|
399
|
+
langchain-openai >= 0.2 (openai / openai-embedding extra)
|
|
400
|
+
langchain-anthropic >= 0.2 (anthropic extra)
|
|
401
|
+
langchain-google-genai >= 2.0 (google extra)
|
|
402
|
+
weaviate-client / langchain-weaviate (weaviate extra)
|
|
403
|
+
ragie >= 2 (ragie extra)
|
|
404
|
+
tavily-python >= 0.7 (tavily extra)
|
|
405
|
+
flashrank >= 0.2 (rerank extra)
|
|
406
|
+
tiktoken >= 0.7 (tiktoken extra)
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Author
|
|
412
|
+
|
|
413
|
+
**Jorge Henrique Moreira Santana**
|
|
414
|
+
Electrical Engineer, Postgraduate in Artificial Intelligence
|
|
415
|
+
[LinkedIn](https://www.linkedin.com/in/jorge-santana-b246874a/) · ti@zeusagro.com
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## License
|
|
420
|
+
|
|
421
|
+
[MIT](LICENSE)
|