modulex-python 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.
- modulex_python-0.1.0/.gitignore +30 -0
- modulex_python-0.1.0/CHANGELOG.md +21 -0
- modulex_python-0.1.0/CODE_OF_CONDUCT.md +54 -0
- modulex_python-0.1.0/CONTRIBUTING.md +139 -0
- modulex_python-0.1.0/LICENSE +21 -0
- modulex_python-0.1.0/PKG-INFO +435 -0
- modulex_python-0.1.0/README.md +398 -0
- modulex_python-0.1.0/SECURITY.md +26 -0
- modulex_python-0.1.0/pyproject.toml +75 -0
- modulex_python-0.1.0/src/modulex/__init__.py +39 -0
- modulex_python-0.1.0/src/modulex/_base.py +281 -0
- modulex_python-0.1.0/src/modulex/_client.py +237 -0
- modulex_python-0.1.0/src/modulex/_compat.py +39 -0
- modulex_python-0.1.0/src/modulex/_config.py +26 -0
- modulex_python-0.1.0/src/modulex/_exceptions.py +131 -0
- modulex_python-0.1.0/src/modulex/_streaming.py +118 -0
- modulex_python-0.1.0/src/modulex/py.typed +0 -0
- modulex_python-0.1.0/src/modulex/resources/__init__.py +1 -0
- modulex_python-0.1.0/src/modulex/resources/api_keys.py +39 -0
- modulex_python-0.1.0/src/modulex/resources/auth.py +38 -0
- modulex_python-0.1.0/src/modulex/resources/chats.py +62 -0
- modulex_python-0.1.0/src/modulex/resources/composer.py +134 -0
- modulex_python-0.1.0/src/modulex/resources/credentials.py +197 -0
- modulex_python-0.1.0/src/modulex/resources/dashboard.py +110 -0
- modulex_python-0.1.0/src/modulex/resources/deployments.py +92 -0
- modulex_python-0.1.0/src/modulex/resources/executions.py +97 -0
- modulex_python-0.1.0/src/modulex/resources/integrations.py +110 -0
- modulex_python-0.1.0/src/modulex/resources/knowledge.py +343 -0
- modulex_python-0.1.0/src/modulex/resources/notifications.py +39 -0
- modulex_python-0.1.0/src/modulex/resources/organizations.py +72 -0
- modulex_python-0.1.0/src/modulex/resources/schedules.py +172 -0
- modulex_python-0.1.0/src/modulex/resources/subscriptions.py +38 -0
- modulex_python-0.1.0/src/modulex/resources/system.py +28 -0
- modulex_python-0.1.0/src/modulex/resources/templates.py +115 -0
- modulex_python-0.1.0/src/modulex/resources/workflows.py +156 -0
- modulex_python-0.1.0/src/modulex/types/__init__.py +294 -0
- modulex_python-0.1.0/src/modulex/types/api_keys.py +19 -0
- modulex_python-0.1.0/src/modulex/types/auth.py +62 -0
- modulex_python-0.1.0/src/modulex/types/chats.py +55 -0
- modulex_python-0.1.0/src/modulex/types/composer.py +27 -0
- modulex_python-0.1.0/src/modulex/types/credentials.py +79 -0
- modulex_python-0.1.0/src/modulex/types/dashboard.py +54 -0
- modulex_python-0.1.0/src/modulex/types/executions.py +104 -0
- modulex_python-0.1.0/src/modulex/types/integrations.py +29 -0
- modulex_python-0.1.0/src/modulex/types/knowledge.py +75 -0
- modulex_python-0.1.0/src/modulex/types/notifications.py +16 -0
- modulex_python-0.1.0/src/modulex/types/organizations.py +43 -0
- modulex_python-0.1.0/src/modulex/types/schedules.py +48 -0
- modulex_python-0.1.0/src/modulex/types/shared.py +39 -0
- modulex_python-0.1.0/src/modulex/types/subscriptions.py +59 -0
- modulex_python-0.1.0/src/modulex/types/templates.py +50 -0
- modulex_python-0.1.0/src/modulex/types/workflows.py +253 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
*.egg-info/
|
|
8
|
+
*.egg
|
|
9
|
+
.eggs/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
.ruff_cache/
|
|
13
|
+
htmlcov/
|
|
14
|
+
.coverage
|
|
15
|
+
coverage.xml
|
|
16
|
+
*.cover
|
|
17
|
+
.env
|
|
18
|
+
.venv/
|
|
19
|
+
venv/
|
|
20
|
+
env/
|
|
21
|
+
.idea/
|
|
22
|
+
.vscode/
|
|
23
|
+
.DS_Store
|
|
24
|
+
coverage/
|
|
25
|
+
*.swp
|
|
26
|
+
*.swo
|
|
27
|
+
*~
|
|
28
|
+
PUBLISHING_GUIDE.md
|
|
29
|
+
SDK_PROMPT_PYTHON.md
|
|
30
|
+
SDK_REFERENCE.md
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the ModuleX Python SDK will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-03-09
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release of the ModuleX Python SDK
|
|
13
|
+
- Full coverage of all 125 ModuleX API endpoints
|
|
14
|
+
- Async-first client with `httpx`
|
|
15
|
+
- SSE streaming support for workflow execution, chat, and composer events
|
|
16
|
+
- Automatic retry with exponential backoff for transient errors
|
|
17
|
+
- Auto-pagination iterators for list endpoints
|
|
18
|
+
- File upload support for knowledge base documents
|
|
19
|
+
- Complete type definitions for all request/response schemas
|
|
20
|
+
- Exception hierarchy mapping all HTTP error codes
|
|
21
|
+
- Organization ID resolution (per-request override or client default)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity
|
|
10
|
+
and orientation.
|
|
11
|
+
|
|
12
|
+
## Our Standards
|
|
13
|
+
|
|
14
|
+
Examples of behavior that contributes to a positive environment:
|
|
15
|
+
|
|
16
|
+
- Using welcoming and inclusive language
|
|
17
|
+
- Being respectful of differing viewpoints and experiences
|
|
18
|
+
- Gracefully accepting constructive criticism
|
|
19
|
+
- Focusing on what is best for the community
|
|
20
|
+
- Showing empathy towards other community members
|
|
21
|
+
|
|
22
|
+
Examples of unacceptable behavior:
|
|
23
|
+
|
|
24
|
+
- The use of sexualized language or imagery and unwelcome sexual attention
|
|
25
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
26
|
+
- Public or private harassment
|
|
27
|
+
- Publishing others' private information without explicit permission
|
|
28
|
+
- Other conduct which could reasonably be considered inappropriate
|
|
29
|
+
|
|
30
|
+
## Enforcement Responsibilities
|
|
31
|
+
|
|
32
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
|
33
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
|
34
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
35
|
+
or harmful.
|
|
36
|
+
|
|
37
|
+
## Scope
|
|
38
|
+
|
|
39
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
40
|
+
an individual is officially representing the community in public spaces.
|
|
41
|
+
|
|
42
|
+
## Enforcement
|
|
43
|
+
|
|
44
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
45
|
+
reported to the community leaders responsible for enforcement at
|
|
46
|
+
**contact@modulex.dev**.
|
|
47
|
+
|
|
48
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
49
|
+
|
|
50
|
+
## Attribution
|
|
51
|
+
|
|
52
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
|
|
53
|
+
version 2.1, available at
|
|
54
|
+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html).
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Contributing to ModuleX Python SDK
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing! This guide will help you get started.
|
|
4
|
+
|
|
5
|
+
## Code of Conduct
|
|
6
|
+
|
|
7
|
+
This project follows the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
|
|
8
|
+
By participating, you are expected to uphold this code.
|
|
9
|
+
|
|
10
|
+
## Development Setup
|
|
11
|
+
|
|
12
|
+
### Prerequisites
|
|
13
|
+
|
|
14
|
+
- Python 3.9 or later
|
|
15
|
+
- [pip](https://pip.pypa.io/) package manager
|
|
16
|
+
|
|
17
|
+
### Getting Started
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Clone the repository
|
|
21
|
+
git clone https://github.com/ModuleXAI/modulex-python.git
|
|
22
|
+
cd modulex-python
|
|
23
|
+
|
|
24
|
+
# Install in editable mode with dev dependencies
|
|
25
|
+
pip install -e ".[dev]"
|
|
26
|
+
|
|
27
|
+
# Verify installation
|
|
28
|
+
python -c "from modulex import Modulex; print('OK')"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Development Workflow
|
|
32
|
+
|
|
33
|
+
### Running Tests
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Unit tests (no API key needed)
|
|
37
|
+
make test
|
|
38
|
+
|
|
39
|
+
# Integration tests (requires .env with real API credentials)
|
|
40
|
+
cp .env.example .env
|
|
41
|
+
# Edit .env with your credentials
|
|
42
|
+
make test-integration
|
|
43
|
+
|
|
44
|
+
# All quality checks (lint + typecheck + unit tests)
|
|
45
|
+
make check
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Code Style
|
|
49
|
+
|
|
50
|
+
We use [Ruff](https://docs.astral.sh/ruff/) for linting and formatting:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Check for lint errors
|
|
54
|
+
make lint
|
|
55
|
+
|
|
56
|
+
# Auto-format code
|
|
57
|
+
make format
|
|
58
|
+
|
|
59
|
+
# Type checking with mypy
|
|
60
|
+
make typecheck
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Style guidelines:**
|
|
64
|
+
- Line length: 120 characters
|
|
65
|
+
- Target: Python 3.9+
|
|
66
|
+
- Ruff rules: `E`, `F`, `I`, `N`, `W`, `UP`
|
|
67
|
+
- All public methods must have type annotations
|
|
68
|
+
- Use `async`/`await` throughout (async-first SDK)
|
|
69
|
+
|
|
70
|
+
### Branch Naming
|
|
71
|
+
|
|
72
|
+
Use descriptive branch names with a prefix:
|
|
73
|
+
|
|
74
|
+
- `feat/add-new-resource` — New features
|
|
75
|
+
- `fix/retry-logic-bug` — Bug fixes
|
|
76
|
+
- `docs/update-readme` — Documentation changes
|
|
77
|
+
- `chore/update-deps` — Maintenance tasks
|
|
78
|
+
|
|
79
|
+
### Commit Messages
|
|
80
|
+
|
|
81
|
+
Write clear, concise commit messages:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
feat: add bulk delete for credentials resource
|
|
85
|
+
|
|
86
|
+
fix: handle 204 No Content responses in _request
|
|
87
|
+
|
|
88
|
+
docs: add streaming usage examples to README
|
|
89
|
+
|
|
90
|
+
chore: update httpx to 0.28
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Use conventional prefixes: `feat:`, `fix:`, `docs:`, `chore:`, `test:`, `refactor:`.
|
|
94
|
+
|
|
95
|
+
## Pull Request Process
|
|
96
|
+
|
|
97
|
+
1. **Fork** the repository and create your branch from `main`
|
|
98
|
+
2. **Write tests** for any new functionality
|
|
99
|
+
3. **Ensure all checks pass**: `make check`
|
|
100
|
+
4. **Update documentation** if you changed public API
|
|
101
|
+
5. **Open a PR** with a clear description of the changes
|
|
102
|
+
|
|
103
|
+
### PR Checklist
|
|
104
|
+
|
|
105
|
+
- [ ] Tests pass (`make check`)
|
|
106
|
+
- [ ] New code has type annotations
|
|
107
|
+
- [ ] Public API changes are documented in README
|
|
108
|
+
- [ ] CHANGELOG.md updated (for user-facing changes)
|
|
109
|
+
|
|
110
|
+
### Review Process
|
|
111
|
+
|
|
112
|
+
- All PRs require at least one approving review
|
|
113
|
+
- CI must pass before merging
|
|
114
|
+
- Maintainers may request changes or suggest improvements
|
|
115
|
+
|
|
116
|
+
## Adding a New Resource
|
|
117
|
+
|
|
118
|
+
If you're adding support for a new API resource:
|
|
119
|
+
|
|
120
|
+
1. Create the type definitions in `src/modulex/types/<resource>.py`
|
|
121
|
+
2. Create the resource class in `src/modulex/resources/<resource>.py` (inherit from `_BaseResource`)
|
|
122
|
+
3. Register the resource as a lazy property in `src/modulex/_client.py`
|
|
123
|
+
4. Export new types in `src/modulex/types/__init__.py`
|
|
124
|
+
5. Add unit tests in `tests/test_<resource>.py`
|
|
125
|
+
6. Add integration tests in `tests/integration/test_<resource>.py`
|
|
126
|
+
7. Add usage examples to `README.md`
|
|
127
|
+
8. Add a documentation snippet in `docs/snippets/<resource>.mdx`
|
|
128
|
+
|
|
129
|
+
## Reporting Bugs
|
|
130
|
+
|
|
131
|
+
Use the [bug report template](https://github.com/ModuleXAI/modulex-python/issues/new?template=bug_report.yml) on GitHub Issues.
|
|
132
|
+
|
|
133
|
+
## Security Vulnerabilities
|
|
134
|
+
|
|
135
|
+
Please report security issues via email to **contact@modulex.dev** — do NOT use public issues. See [SECURITY.md](SECURITY.md) for details.
|
|
136
|
+
|
|
137
|
+
## Questions?
|
|
138
|
+
|
|
139
|
+
Open a [discussion](https://github.com/ModuleXAI/modulex-python/discussions) or reach out at contact@modulex.dev.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ModuleXAI
|
|
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,435 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modulex-python
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for the ModuleX AI workflow orchestration platform
|
|
5
|
+
Project-URL: Homepage, https://modulex.dev
|
|
6
|
+
Project-URL: Documentation, https://docs.modulex.dev
|
|
7
|
+
Project-URL: Repository, https://github.com/ModuleXAI/modulex-python
|
|
8
|
+
Project-URL: Issues, https://github.com/ModuleXAI/modulex-python/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/ModuleXAI/modulex-python/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: ModuleX <contact@modulex.dev>
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: ai,modulex,orchestration,sdk,workflow
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Framework :: AsyncIO
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Requires-Dist: httpx-sse>=0.4
|
|
27
|
+
Requires-Dist: httpx>=0.27
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: mypy>=1.13; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: python-dotenv>=1.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: respx>=0.22; extra == 'dev'
|
|
35
|
+
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
# ModuleX Python SDK
|
|
39
|
+
|
|
40
|
+
The official Python SDK for the [ModuleX](https://modulex.dev) AI workflow orchestration platform.
|
|
41
|
+
|
|
42
|
+
[](https://github.com/ModuleXAI/modulex-python/actions/workflows/ci.yml)
|
|
43
|
+
[](https://pypi.org/project/modulex-python/)
|
|
44
|
+
[](https://pypi.org/project/modulex-python/)
|
|
45
|
+
[](LICENSE)
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install modulex-python
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import asyncio
|
|
57
|
+
from modulex import Modulex
|
|
58
|
+
|
|
59
|
+
async def main():
|
|
60
|
+
async with Modulex(
|
|
61
|
+
api_key="mx_live_...",
|
|
62
|
+
organization_id="your-org-id",
|
|
63
|
+
) as client:
|
|
64
|
+
# Get current user
|
|
65
|
+
me = await client.auth.me()
|
|
66
|
+
print(f"Hello, {me['username']}!")
|
|
67
|
+
|
|
68
|
+
# List workflows
|
|
69
|
+
workflows = await client.workflows.list(status="active")
|
|
70
|
+
for wf in workflows["workflows"]:
|
|
71
|
+
print(f" {wf['name']}")
|
|
72
|
+
|
|
73
|
+
asyncio.run(main())
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Authentication
|
|
77
|
+
|
|
78
|
+
Get your API key from the [ModuleX Dashboard](https://app.modulex.dev). Keys use the `mx_live_` prefix.
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
from modulex import Modulex
|
|
82
|
+
|
|
83
|
+
# Pass API key directly
|
|
84
|
+
client = Modulex(api_key="mx_live_...")
|
|
85
|
+
|
|
86
|
+
# Or use environment variable
|
|
87
|
+
import os
|
|
88
|
+
client = Modulex(api_key=os.environ["MODULEX_API_KEY"])
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Organization Context
|
|
92
|
+
|
|
93
|
+
Most endpoints require an organization context. Set it at the client level or override per-request:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
# Set default org for all requests
|
|
97
|
+
client = Modulex(api_key="mx_live_...", organization_id="org-uuid")
|
|
98
|
+
|
|
99
|
+
# Override for a specific request
|
|
100
|
+
workflows = await client.workflows.list(organization_id="other-org-uuid")
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Configuration
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
client = Modulex(
|
|
107
|
+
api_key="mx_live_...",
|
|
108
|
+
organization_id="org-uuid", # Default organization
|
|
109
|
+
base_url="https://api.modulex.dev", # API base URL
|
|
110
|
+
timeout=30.0, # Request timeout (seconds)
|
|
111
|
+
max_retries=3, # Retry count for transient errors
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Resources
|
|
116
|
+
|
|
117
|
+
### Workflows
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
# List workflows
|
|
121
|
+
workflows = await client.workflows.list(status="active", search="email")
|
|
122
|
+
|
|
123
|
+
# Auto-paginate all workflows
|
|
124
|
+
async for wf in client.workflows.list_all(status="active"):
|
|
125
|
+
print(wf["name"])
|
|
126
|
+
|
|
127
|
+
# Create workflow
|
|
128
|
+
workflow = await client.workflows.create(
|
|
129
|
+
workflow_schema={
|
|
130
|
+
"metadata": {"name": "My Workflow", "version": "1.0"},
|
|
131
|
+
"config": {},
|
|
132
|
+
"state_schema": {"fields": {}},
|
|
133
|
+
"nodes": [],
|
|
134
|
+
"edges": [],
|
|
135
|
+
"entry_point": "start",
|
|
136
|
+
},
|
|
137
|
+
name="My Workflow",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Update & delete
|
|
141
|
+
await client.workflows.update("workflow-id", name="New Name", status="active")
|
|
142
|
+
await client.workflows.delete("workflow-id")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Executions
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
# Run a workflow
|
|
149
|
+
result = await client.executions.run(
|
|
150
|
+
workflow_id="workflow-uuid",
|
|
151
|
+
input={"messages": [{"role": "user", "content": "Hello!"}]},
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Direct LLM call
|
|
155
|
+
result = await client.executions.run(
|
|
156
|
+
llm={
|
|
157
|
+
"integration_name": "openai",
|
|
158
|
+
"provider_id": "openai",
|
|
159
|
+
"model_id": "gpt-4o-mini",
|
|
160
|
+
"temperature": 0.4,
|
|
161
|
+
},
|
|
162
|
+
input={"messages": [{"role": "user", "content": "Hello!"}]},
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Get execution state
|
|
166
|
+
state = await client.executions.get_state(thread_id="thread-uuid")
|
|
167
|
+
|
|
168
|
+
# Resume after interrupt
|
|
169
|
+
await client.executions.resume(
|
|
170
|
+
thread_id="thread-uuid",
|
|
171
|
+
run_id="run-uuid",
|
|
172
|
+
resume_value="user input",
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# Cancel execution
|
|
176
|
+
await client.executions.cancel(run_id="run-uuid", reason="No longer needed")
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### SSE Streaming
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
# Listen to workflow execution events
|
|
183
|
+
async for event in client.executions.listen(run_id="run-uuid"):
|
|
184
|
+
if event.event == "node_update":
|
|
185
|
+
print(f"Node {event.data['node_id']}: {event.data['status']}")
|
|
186
|
+
elif event.event == "done":
|
|
187
|
+
print(f"Completed in {event.data['total_execution_time_ms']}ms")
|
|
188
|
+
elif event.event == "error":
|
|
189
|
+
print(f"Error: {event.data['error_message']}")
|
|
190
|
+
|
|
191
|
+
# Listen to chat list updates
|
|
192
|
+
async for event in client.chats.stream():
|
|
193
|
+
if event.event == "chat_list_updated":
|
|
194
|
+
print(f"Chat list changed: {event.data}")
|
|
195
|
+
|
|
196
|
+
# Listen to composer events
|
|
197
|
+
async for event in client.composer.listen("chat-id", "run-id"):
|
|
198
|
+
print(f"{event.event}: {event.data}")
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Credentials
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
# Add an API key credential
|
|
205
|
+
cred = await client.credentials.create(
|
|
206
|
+
integration_name="openai",
|
|
207
|
+
auth_data={"api_key": "sk-..."},
|
|
208
|
+
display_name="Production OpenAI",
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# Test a credential
|
|
212
|
+
result = await client.credentials.test(cred["credential_id"])
|
|
213
|
+
print(f"Valid: {result['is_valid']}")
|
|
214
|
+
|
|
215
|
+
# List credentials
|
|
216
|
+
creds = await client.credentials.list(integration_name="openai")
|
|
217
|
+
|
|
218
|
+
# Add MCP server
|
|
219
|
+
mcp = await client.credentials.create_mcp_server(
|
|
220
|
+
server_url="https://mcp-server.example.com",
|
|
221
|
+
headers={"Authorization": "Bearer ..."},
|
|
222
|
+
)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Knowledge Bases
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
# Create a knowledge base
|
|
229
|
+
kb = await client.knowledge.create(
|
|
230
|
+
name="Docs",
|
|
231
|
+
embedding_config={"provider": "openai", "model": "text-embedding-3-small"},
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# Upload a document
|
|
235
|
+
doc = await client.knowledge.upload_document(
|
|
236
|
+
knowledge_base_id=kb["id"],
|
|
237
|
+
file_path="/path/to/doc.pdf",
|
|
238
|
+
metadata={"department": "engineering"},
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# Search
|
|
242
|
+
results = await client.knowledge.search(
|
|
243
|
+
knowledge_base_id=kb["id"],
|
|
244
|
+
query="How does deployment work?",
|
|
245
|
+
top_k=5,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# Retrieve RAG context
|
|
249
|
+
context = await client.knowledge.retrieve_context(
|
|
250
|
+
knowledge_base_id=kb["id"],
|
|
251
|
+
query="deployment steps",
|
|
252
|
+
max_tokens=2000,
|
|
253
|
+
)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Schedules
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
# Create a cron schedule
|
|
260
|
+
schedule = await client.schedules.create(
|
|
261
|
+
workflow_id="workflow-uuid",
|
|
262
|
+
name="Daily Report",
|
|
263
|
+
schedule_type="cron",
|
|
264
|
+
cron_expression="0 9 * * 1-5",
|
|
265
|
+
timezone="America/New_York",
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# Pause/resume
|
|
269
|
+
await client.schedules.pause(schedule["id"])
|
|
270
|
+
await client.schedules.resume(schedule["id"])
|
|
271
|
+
|
|
272
|
+
# View run history
|
|
273
|
+
runs = await client.schedules.list_runs(schedule["id"])
|
|
274
|
+
stats = await client.schedules.run_stats(schedule["id"], days=30)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Templates
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
# Browse templates
|
|
281
|
+
templates = await client.templates.list()
|
|
282
|
+
|
|
283
|
+
# Use a template
|
|
284
|
+
result = await client.templates.use("template-id")
|
|
285
|
+
print(f"Created workflow: {result['workflow']['id']}")
|
|
286
|
+
|
|
287
|
+
# Like a template
|
|
288
|
+
await client.templates.like("template-id")
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Deployments
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
# Deploy a workflow
|
|
295
|
+
deployment = await client.deployments.create(
|
|
296
|
+
workflow_id="workflow-uuid",
|
|
297
|
+
deployment_note="v1.0 release",
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
# Activate a deployment
|
|
301
|
+
await client.deployments.activate("workflow-uuid", deployment["id"])
|
|
302
|
+
|
|
303
|
+
# Deactivate live deployment
|
|
304
|
+
await client.deployments.deactivate("workflow-uuid")
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Composer
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
# Start a composer session
|
|
311
|
+
result = await client.composer.chat(
|
|
312
|
+
message="Add an LLM node that summarizes the input",
|
|
313
|
+
workflow_id="workflow-uuid",
|
|
314
|
+
llm={"integration_name": "anthropic", "model_id": "claude-sonnet-4-20250514"},
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
# Listen to composer events
|
|
318
|
+
async for event in client.composer.listen(result["composer_chat_id"], result["run_id"]):
|
|
319
|
+
if event.event == "workflow_change":
|
|
320
|
+
print(f"Workflow modified: {event.data}")
|
|
321
|
+
elif event.event == "done":
|
|
322
|
+
break
|
|
323
|
+
|
|
324
|
+
# Save or revert changes
|
|
325
|
+
await client.composer.save(result["composer_chat_id"])
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Other Resources
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
# Organizations
|
|
332
|
+
await client.organizations.create(name="My Org")
|
|
333
|
+
await client.organizations.invite("user@example.com", role="member")
|
|
334
|
+
llms = await client.organizations.llms()
|
|
335
|
+
|
|
336
|
+
# Dashboard
|
|
337
|
+
logs = await client.dashboard.logs(category="CREDENTIALS")
|
|
338
|
+
overview = await client.dashboard.analytics_overview()
|
|
339
|
+
users = await client.dashboard.users(search="john")
|
|
340
|
+
|
|
341
|
+
# Subscriptions
|
|
342
|
+
plans = await client.subscriptions.organization_plans()
|
|
343
|
+
billing = await client.subscriptions.organization_billing()
|
|
344
|
+
|
|
345
|
+
# Notifications
|
|
346
|
+
notifications = await client.notifications.list()
|
|
347
|
+
|
|
348
|
+
# Integrations
|
|
349
|
+
integrations = await client.integrations.browse(type="tool")
|
|
350
|
+
providers = await client.integrations.llm_providers()
|
|
351
|
+
|
|
352
|
+
# System
|
|
353
|
+
health = await client.system.health()
|
|
354
|
+
timezones = await client.system.timezones()
|
|
355
|
+
|
|
356
|
+
# API Keys
|
|
357
|
+
key = await client.api_keys.create(name="CI/CD Key")
|
|
358
|
+
await client.api_keys.revoke(key["id"])
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
## Error Handling
|
|
362
|
+
|
|
363
|
+
```python
|
|
364
|
+
from modulex import (
|
|
365
|
+
Modulex,
|
|
366
|
+
ModulexError,
|
|
367
|
+
AuthenticationError,
|
|
368
|
+
NotFoundError,
|
|
369
|
+
RateLimitError,
|
|
370
|
+
ValidationError,
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
try:
|
|
374
|
+
workflow = await client.workflows.get("invalid-id")
|
|
375
|
+
except NotFoundError:
|
|
376
|
+
print("Workflow not found")
|
|
377
|
+
except RateLimitError as e:
|
|
378
|
+
print(f"Rate limited. Retry after {e.retry_after}s")
|
|
379
|
+
except AuthenticationError:
|
|
380
|
+
print("Invalid API key")
|
|
381
|
+
except ValidationError as e:
|
|
382
|
+
print(f"Validation error: {e.message}")
|
|
383
|
+
except ModulexError as e:
|
|
384
|
+
print(f"API error ({e.status_code}): {e.message}")
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Exception Hierarchy
|
|
388
|
+
|
|
389
|
+
| Exception | HTTP Status | Description |
|
|
390
|
+
|-----------|-------------|-------------|
|
|
391
|
+
| `ModulexError` | — | Base exception |
|
|
392
|
+
| `BadRequestError` | 400 | Malformed request |
|
|
393
|
+
| `AuthenticationError` | 401 | Invalid/missing auth |
|
|
394
|
+
| `PermissionError` | 403 | Insufficient permissions |
|
|
395
|
+
| `NotFoundError` | 404 | Resource not found |
|
|
396
|
+
| `ConflictError` | 409 | Resource conflict |
|
|
397
|
+
| `ValidationError` | 422 | Validation error |
|
|
398
|
+
| `RateLimitError` | 429 | Rate limit exceeded |
|
|
399
|
+
| `InternalError` | 500 | Server error |
|
|
400
|
+
| `ExternalServiceError` | 502 | External service failure |
|
|
401
|
+
| `ServiceUnavailableError` | 503 | Service unavailable |
|
|
402
|
+
| `StreamError` | — | SSE stream error |
|
|
403
|
+
| `TimeoutError` | — | Request timeout |
|
|
404
|
+
|
|
405
|
+
## Type Hints
|
|
406
|
+
|
|
407
|
+
All types are available for import:
|
|
408
|
+
|
|
409
|
+
```python
|
|
410
|
+
from modulex.types import (
|
|
411
|
+
WorkflowDefinition,
|
|
412
|
+
NodeDefinition,
|
|
413
|
+
EdgeDefinition,
|
|
414
|
+
LLMConfig,
|
|
415
|
+
RunResponse,
|
|
416
|
+
SSEEvent,
|
|
417
|
+
)
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
## Documentation
|
|
421
|
+
|
|
422
|
+
For full API documentation, visit [docs.modulex.dev](https://docs.modulex.dev).
|
|
423
|
+
|
|
424
|
+
## Contributing
|
|
425
|
+
|
|
426
|
+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on:
|
|
427
|
+
|
|
428
|
+
- Setting up the development environment
|
|
429
|
+
- Running tests (unit and integration)
|
|
430
|
+
- Code style and commit conventions
|
|
431
|
+
- Pull request process
|
|
432
|
+
|
|
433
|
+
## License
|
|
434
|
+
|
|
435
|
+
This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
|