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.
Files changed (52) hide show
  1. modulex_python-0.1.0/.gitignore +30 -0
  2. modulex_python-0.1.0/CHANGELOG.md +21 -0
  3. modulex_python-0.1.0/CODE_OF_CONDUCT.md +54 -0
  4. modulex_python-0.1.0/CONTRIBUTING.md +139 -0
  5. modulex_python-0.1.0/LICENSE +21 -0
  6. modulex_python-0.1.0/PKG-INFO +435 -0
  7. modulex_python-0.1.0/README.md +398 -0
  8. modulex_python-0.1.0/SECURITY.md +26 -0
  9. modulex_python-0.1.0/pyproject.toml +75 -0
  10. modulex_python-0.1.0/src/modulex/__init__.py +39 -0
  11. modulex_python-0.1.0/src/modulex/_base.py +281 -0
  12. modulex_python-0.1.0/src/modulex/_client.py +237 -0
  13. modulex_python-0.1.0/src/modulex/_compat.py +39 -0
  14. modulex_python-0.1.0/src/modulex/_config.py +26 -0
  15. modulex_python-0.1.0/src/modulex/_exceptions.py +131 -0
  16. modulex_python-0.1.0/src/modulex/_streaming.py +118 -0
  17. modulex_python-0.1.0/src/modulex/py.typed +0 -0
  18. modulex_python-0.1.0/src/modulex/resources/__init__.py +1 -0
  19. modulex_python-0.1.0/src/modulex/resources/api_keys.py +39 -0
  20. modulex_python-0.1.0/src/modulex/resources/auth.py +38 -0
  21. modulex_python-0.1.0/src/modulex/resources/chats.py +62 -0
  22. modulex_python-0.1.0/src/modulex/resources/composer.py +134 -0
  23. modulex_python-0.1.0/src/modulex/resources/credentials.py +197 -0
  24. modulex_python-0.1.0/src/modulex/resources/dashboard.py +110 -0
  25. modulex_python-0.1.0/src/modulex/resources/deployments.py +92 -0
  26. modulex_python-0.1.0/src/modulex/resources/executions.py +97 -0
  27. modulex_python-0.1.0/src/modulex/resources/integrations.py +110 -0
  28. modulex_python-0.1.0/src/modulex/resources/knowledge.py +343 -0
  29. modulex_python-0.1.0/src/modulex/resources/notifications.py +39 -0
  30. modulex_python-0.1.0/src/modulex/resources/organizations.py +72 -0
  31. modulex_python-0.1.0/src/modulex/resources/schedules.py +172 -0
  32. modulex_python-0.1.0/src/modulex/resources/subscriptions.py +38 -0
  33. modulex_python-0.1.0/src/modulex/resources/system.py +28 -0
  34. modulex_python-0.1.0/src/modulex/resources/templates.py +115 -0
  35. modulex_python-0.1.0/src/modulex/resources/workflows.py +156 -0
  36. modulex_python-0.1.0/src/modulex/types/__init__.py +294 -0
  37. modulex_python-0.1.0/src/modulex/types/api_keys.py +19 -0
  38. modulex_python-0.1.0/src/modulex/types/auth.py +62 -0
  39. modulex_python-0.1.0/src/modulex/types/chats.py +55 -0
  40. modulex_python-0.1.0/src/modulex/types/composer.py +27 -0
  41. modulex_python-0.1.0/src/modulex/types/credentials.py +79 -0
  42. modulex_python-0.1.0/src/modulex/types/dashboard.py +54 -0
  43. modulex_python-0.1.0/src/modulex/types/executions.py +104 -0
  44. modulex_python-0.1.0/src/modulex/types/integrations.py +29 -0
  45. modulex_python-0.1.0/src/modulex/types/knowledge.py +75 -0
  46. modulex_python-0.1.0/src/modulex/types/notifications.py +16 -0
  47. modulex_python-0.1.0/src/modulex/types/organizations.py +43 -0
  48. modulex_python-0.1.0/src/modulex/types/schedules.py +48 -0
  49. modulex_python-0.1.0/src/modulex/types/shared.py +39 -0
  50. modulex_python-0.1.0/src/modulex/types/subscriptions.py +59 -0
  51. modulex_python-0.1.0/src/modulex/types/templates.py +50 -0
  52. 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
+ [![CI](https://github.com/ModuleXAI/modulex-python/actions/workflows/ci.yml/badge.svg)](https://github.com/ModuleXAI/modulex-python/actions/workflows/ci.yml)
43
+ [![PyPI](https://img.shields.io/pypi/v/modulex-python)](https://pypi.org/project/modulex-python/)
44
+ [![Python](https://img.shields.io/pypi/pyversions/modulex-python)](https://pypi.org/project/modulex-python/)
45
+ [![License](https://img.shields.io/github/license/ModuleXAI/modulex-python)](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.