modus-sdk 0.2.3__tar.gz → 0.4.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 (145) hide show
  1. modus_sdk-0.4.0/CHANGELOG.md +18 -0
  2. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/PKG-INFO +5 -1
  3. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/README.md +4 -0
  4. modus_sdk-0.4.0/docs/sphinx/conf.py +32 -0
  5. modus_sdk-0.4.0/docs/sphinx/exceptions.rst +8 -0
  6. modus_sdk-0.4.0/docs/sphinx/index.rst +21 -0
  7. modus_sdk-0.4.0/docs/sphinx/management/context.rst +20 -0
  8. modus_sdk-0.4.0/docs/sphinx/management/index.rst +31 -0
  9. modus_sdk-0.4.0/docs/sphinx/management/scopes.rst +28 -0
  10. modus_sdk-0.4.0/docs/sphinx/management/tools.rst +12 -0
  11. modus_sdk-0.4.0/docs/sphinx/management/usage.rst +12 -0
  12. modus_sdk-0.4.0/docs/sphinx/management/users.rst +12 -0
  13. modus_sdk-0.4.0/docs/sphinx/management/workflows.rst +20 -0
  14. modus_sdk-0.4.0/docs/sphinx/modus/chat.rst +12 -0
  15. modus_sdk-0.4.0/docs/sphinx/modus/connections.rst +12 -0
  16. modus_sdk-0.4.0/docs/sphinx/modus/context.rst +12 -0
  17. modus_sdk-0.4.0/docs/sphinx/modus/index.rst +33 -0
  18. modus_sdk-0.4.0/docs/sphinx/modus/scopes.rst +12 -0
  19. modus_sdk-0.4.0/docs/sphinx/modus/suggestions.rst +12 -0
  20. modus_sdk-0.4.0/docs/sphinx/modus/workflows.rst +20 -0
  21. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/examples/apps/modus_skill_chat/README.md +1 -1
  22. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/examples/apps/modus_skill_chat/app.py +3 -3
  23. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/__init__.py +21 -3
  24. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_auth.py +26 -0
  25. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_chat.py +10 -0
  26. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_client.py +5 -40
  27. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_deprecation.py +4 -3
  28. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_generated/__init__.py +16 -4
  29. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_generated/models.py +319 -169
  30. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_generated/operations.py +41 -31
  31. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_pagination.py +21 -1
  32. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_version.py +2 -2
  33. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/__init__.py +15 -1
  34. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/_client.py +4 -24
  35. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/__init__.py +3 -3
  36. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/context/context.py +34 -3
  37. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/context/custom_items.py +16 -4
  38. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/context/items.py +35 -0
  39. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/scopes/evaluations.py +33 -0
  40. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/scopes/memories.py +4 -0
  41. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/scopes/scopes.py +40 -17
  42. modus_sdk-0.4.0/modus/management/resources/tools.py +91 -0
  43. modus_sdk-0.4.0/modus/management/resources/usage.py +142 -0
  44. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/workflows/interfaces.py +20 -7
  45. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/workflows/workflows.py +33 -10
  46. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/__init__.py +9 -0
  47. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/agent_selection.py +12 -0
  48. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/agents.py +1 -1
  49. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/memories.py +5 -0
  50. modus_sdk-0.4.0/modus/management/types/scopes.py +5 -0
  51. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/skills.py +1 -1
  52. modus_sdk-0.4.0/modus/management/types/tools.py +13 -0
  53. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/toolset.py +1 -1
  54. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/triggers.py +37 -0
  55. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/usage.py +11 -1
  56. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/workflow.py +8 -0
  57. modus_sdk-0.4.0/modus/management/types/workflows.py +5 -0
  58. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/context/items.py +2 -0
  59. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/modus/conversations.py +7 -5
  60. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/modus/modus.py +3 -0
  61. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/scopes/scopes.py +7 -4
  62. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/suggestions/suggestions.py +39 -25
  63. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/workflows/workflows.py +4 -4
  64. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/__init__.py +18 -1
  65. modus_sdk-0.4.0/modus/types/agents.py +23 -0
  66. modus_sdk-0.4.0/modus/types/chat.py +30 -0
  67. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/compose.py +1 -0
  68. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/context.py +1 -0
  69. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/context_values.py +1 -0
  70. modus_sdk-0.4.0/modus/types/conversations.py +43 -0
  71. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/json_blob.py +1 -0
  72. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/pagination.py +3 -3
  73. modus_sdk-0.4.0/modus/types/scopes.py +25 -0
  74. modus_sdk-0.4.0/modus/types/skills.py +22 -0
  75. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/tool_calls.py +1 -0
  76. modus_sdk-0.4.0/modus/types/workflows.py +26 -0
  77. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/project.json +3 -2
  78. modus_sdk-0.2.3/CHANGELOG.md +0 -42
  79. modus_sdk-0.2.3/modus/management/resources/organization.py +0 -52
  80. modus_sdk-0.2.3/modus/management/resources/usage.py +0 -92
  81. modus_sdk-0.2.3/modus/types/agents.py +0 -17
  82. modus_sdk-0.2.3/modus/types/chat.py +0 -9
  83. modus_sdk-0.2.3/modus/types/conversations.py +0 -30
  84. modus_sdk-0.2.3/modus/types/skills.py +0 -16
  85. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/.gitignore +0 -0
  86. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/CONTRIBUTING.md +0 -0
  87. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/LICENSE +0 -0
  88. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/assets/modus-logo.png +0 -0
  89. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/assets/modus-logo.svg +0 -0
  90. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/examples/apps/modus_skill_chat/.streamlit/config.toml +0 -0
  91. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/examples/apps/modus_skill_chat/pyproject.toml +0 -0
  92. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/examples/scripts/chat.py +0 -0
  93. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/examples/scripts/manage_skill.py +0 -0
  94. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/examples/scripts/modus_chat.py +0 -0
  95. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/examples/scripts/quickstart.py +0 -0
  96. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_agent_run_request.py +0 -0
  97. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_config.py +0 -0
  98. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_exceptions.py +0 -0
  99. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_http.py +0 -0
  100. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_openapi_invoke.py +0 -0
  101. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_query.py +0 -0
  102. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_retry.py +0 -0
  103. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_streaming.py +0 -0
  104. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/_validation.py +0 -0
  105. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/_access_config_write.py +0 -0
  106. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/context/__init__.py +0 -0
  107. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/context/_content_merge.py +0 -0
  108. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/scopes/__init__.py +0 -0
  109. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/scopes/_update_body.py +0 -0
  110. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/scopes/conversations.py +0 -0
  111. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/scopes/supervision.py +0 -0
  112. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/users.py +0 -0
  113. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/workflows/__init__.py +0 -0
  114. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/resources/workflows/_update_body.py +0 -0
  115. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/_guardrails_access.py +0 -0
  116. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/_serialize.py +0 -0
  117. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/context.py +0 -0
  118. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/conversations.py +0 -0
  119. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/evaluations.py +0 -0
  120. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/json_blob.py +0 -0
  121. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/management/types/ownership.py +0 -0
  122. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/py.typed +0 -0
  123. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/__init__.py +0 -0
  124. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/connections/__init__.py +0 -0
  125. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/connections/connections.py +0 -0
  126. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/context/__init__.py +0 -0
  127. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/context/context.py +0 -0
  128. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/modus/__init__.py +0 -0
  129. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/scopes/__init__.py +0 -0
  130. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/scopes/conversations.py +0 -0
  131. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/suggestions/__init__.py +0 -0
  132. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/workflows/__init__.py +0 -0
  133. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/workflows/runs.py +0 -0
  134. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/resources/workflows/workflow_actions.py +0 -0
  135. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/agent_runs.py +0 -0
  136. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/connections.py +0 -0
  137. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/context_accessors.py +0 -0
  138. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/context_compose.py +0 -0
  139. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/runs.py +0 -0
  140. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/suggestions.py +0 -0
  141. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/modus/types/views.py +0 -0
  142. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/pyproject.toml +0 -0
  143. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/pyrightconfig.json +0 -0
  144. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/requirements.txt +0 -0
  145. {modus_sdk-0.2.3 → modus_sdk-0.4.0}/uv.lock +0 -0
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ **Current release:** [`0.4.0`](https://pypi.org/project/modus-sdk/0.4.0/).
4
+
5
+ Pre-1.0 (`0.x`) releases are internal. Detailed release notes are not maintained
6
+ until `1.0.0` — keep `[Unreleased]` empty while the package stays on `0.x`.
7
+
8
+ ## [0.4.0] — 2026-08-01
9
+
10
+
11
+ ### Changed
12
+
13
+ - Public OpenAPI updates from production release.
14
+
15
+
16
+ ## [Unreleased]
17
+
18
+ ## [0.3.0] — 2026-07-26
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modus-sdk
3
- Version: 0.2.3
3
+ Version: 0.4.0
4
4
  Summary: Official Python client for Modus — your organization's context layer for AI
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -227,3 +227,7 @@ Runnable scripts ship with the package:
227
227
  - `examples/scripts/manage_skill.py` — create and deploy a scope (`ModusManagement`, `--write` optional)
228
228
 
229
229
  Optional Streamlit demo: `examples/apps/modus_skill_chat/` (streaming vs buffered scope chat side by side).
230
+
231
+ ## Docs
232
+
233
+ Full guides: [docs.getmodus.com/guides/sdk](https://docs.getmodus.com/guides/sdk) (Python page: [sdk-python](https://docs.getmodus.com/guides/sdk-python)).
@@ -207,3 +207,7 @@ Runnable scripts ship with the package:
207
207
  - `examples/scripts/manage_skill.py` — create and deploy a scope (`ModusManagement`, `--write` optional)
208
208
 
209
209
  Optional Streamlit demo: `examples/apps/modus_skill_chat/` (streaming vs buffered scope chat side by side).
210
+
211
+ ## Docs
212
+
213
+ Full guides: [docs.getmodus.com/guides/sdk](https://docs.getmodus.com/guides/sdk) (Python page: [sdk-python](https://docs.getmodus.com/guides/sdk-python)).
@@ -0,0 +1,32 @@
1
+ """Sphinx config for Mintlify SDK reference (JSON builder)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import sys
7
+
8
+ # Package root: distribution/clients/python/modus-sdk/
9
+ sys.path.insert(0, os.path.abspath("../.."))
10
+
11
+ project = "Python SDK"
12
+ author = "Modus"
13
+ extensions = [
14
+ "sphinx.ext.autodoc",
15
+ "sphinx.ext.napoleon",
16
+ ]
17
+ # Keep types in the signature code fence only — putting [str] in prose breaks Mintlify MDX.
18
+ autodoc_typehints = "signature"
19
+ autodoc_default_options = {
20
+ "members": True,
21
+ "undoc-members": False,
22
+ "show-inheritance": False,
23
+ "member-order": "bysource",
24
+ }
25
+ add_module_names = False
26
+ napoleon_google_docstrings = True
27
+ napoleon_numpy_docstrings = False
28
+ napoleon_use_param = True
29
+ napoleon_use_rtype = True
30
+ exclude_patterns = ["_build"]
31
+ html_theme = "alabaster"
32
+ nitpicky = False
@@ -0,0 +1,8 @@
1
+ Exceptions
2
+ ==========
3
+
4
+ Shared error types raised by both clients.
5
+
6
+ .. automodule:: modus._exceptions
7
+ :members:
8
+ :exclude-members: __init__
@@ -0,0 +1,21 @@
1
+ Python SDK
2
+ ==========
3
+
4
+ Official Python client for Modus.
5
+
6
+ * **Modus** — day-to-day reads and chat
7
+ * **ModusManagement** — create, update, and deploy
8
+
9
+ Install::
10
+
11
+ pip install modus-sdk
12
+
13
+ Authenticate with ``MODUS_API_KEY`` (create a token in the Modus app under
14
+ **Settings → API Tokens**).
15
+
16
+ .. toctree::
17
+ :maxdepth: 2
18
+
19
+ modus/index
20
+ management/index
21
+ exceptions
@@ -0,0 +1,20 @@
1
+ Context
2
+ =======
3
+
4
+ Create and update context items (``mgmt.context``).
5
+
6
+ .. autoclass:: modus.management.resources.context.context.ContextResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.management.resources.context.context.AsyncContextResource
11
+ :members:
12
+ :exclude-members: __init__
13
+
14
+ .. autoclass:: modus.management.resources.context.items.ContextItemsResource
15
+ :members:
16
+ :exclude-members: __init__
17
+
18
+ .. autoclass:: modus.management.resources.context.custom_items.CustomContextItemsResource
19
+ :members:
20
+ :exclude-members: __init__
@@ -0,0 +1,31 @@
1
+ ModusManagement
2
+ ===============
3
+
4
+ Create, update, and deploy scopes, workflows, and context.
5
+
6
+ .. code-block:: python
7
+
8
+ from modus.management import ModusManagement
9
+
10
+ mgmt = ModusManagement(api_key="modus_xxx")
11
+ scope = mgmt.scopes.create(name="Analyst", model="gpt-4o")
12
+ mgmt.scopes.deploy(scope.id)
13
+
14
+ .. toctree::
15
+ :maxdepth: 1
16
+ :hidden:
17
+
18
+ scopes
19
+ workflows
20
+ context
21
+ tools
22
+ usage
23
+ users
24
+
25
+ .. autoclass:: modus.management.ModusManagement
26
+ :members:
27
+ :exclude-members: __init__, __enter__, __exit__, __repr__
28
+
29
+ .. autoclass:: modus.management.AsyncModusManagement
30
+ :members:
31
+ :exclude-members: __init__, __aenter__, __aexit__, __repr__
@@ -0,0 +1,28 @@
1
+ Scopes
2
+ ======
3
+
4
+ Create, update, deploy, and configure scopes (``mgmt.scopes``).
5
+
6
+ .. autoclass:: modus.management.resources.scopes.scopes.ScopesResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.management.resources.scopes.scopes.AsyncScopesResource
11
+ :members:
12
+ :exclude-members: __init__
13
+
14
+ .. autoclass:: modus.management.resources.scopes.conversations.ScopeConversationsResource
15
+ :members:
16
+ :exclude-members: __init__
17
+
18
+ .. autoclass:: modus.management.resources.scopes.memories.ScopeMemoriesResource
19
+ :members:
20
+ :exclude-members: __init__
21
+
22
+ .. autoclass:: modus.management.resources.scopes.evaluations.ScopeEvaluationsResource
23
+ :members:
24
+ :exclude-members: __init__
25
+
26
+ .. autoclass:: modus.management.resources.scopes.supervision.ScopeSupervisionResource
27
+ :members:
28
+ :exclude-members: __init__
@@ -0,0 +1,12 @@
1
+ Tools
2
+ =====
3
+
4
+ Browse tool / integration surfaces (``mgmt.tools``).
5
+
6
+ .. autoclass:: modus.management.resources.tools.ToolsResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.management.resources.tools.AsyncToolsResource
11
+ :members:
12
+ :exclude-members: __init__
@@ -0,0 +1,12 @@
1
+ Usage
2
+ =====
3
+
4
+ Organisation usage metrics (``mgmt.usage``).
5
+
6
+ .. autoclass:: modus.management.resources.usage.UsageResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.management.resources.usage.AsyncUsageResource
11
+ :members:
12
+ :exclude-members: __init__
@@ -0,0 +1,12 @@
1
+ Users
2
+ =====
3
+
4
+ Organisation members and member groups (``mgmt.users``).
5
+
6
+ .. autoclass:: modus.management.resources.users.UsersResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.management.resources.users.AsyncUsersResource
11
+ :members:
12
+ :exclude-members: __init__
@@ -0,0 +1,20 @@
1
+ Workflows
2
+ =========
3
+
4
+ Create, update, and deploy workflows (``mgmt.workflows``).
5
+
6
+ .. autoclass:: modus.management.resources.workflows.workflows.WorkflowsResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.management.resources.workflows.workflows.AsyncWorkflowsResource
11
+ :members:
12
+ :exclude-members: __init__
13
+
14
+ .. autoclass:: modus.management.resources.workflows.interfaces.WorkflowInterfacesResource
15
+ :members:
16
+ :exclude-members: __init__
17
+
18
+ .. autoclass:: modus.management.resources.workflows.interfaces.AsyncWorkflowInterfacesResource
19
+ :members:
20
+ :exclude-members: __init__
@@ -0,0 +1,12 @@
1
+ Chat
2
+ ====
3
+
4
+ Org-wide Modus assistant (``client.modus``).
5
+
6
+ .. autoclass:: modus.resources.modus.ModusResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.resources.modus.AsyncModusResource
11
+ :members:
12
+ :exclude-members: __init__
@@ -0,0 +1,12 @@
1
+ Connections
2
+ ===========
3
+
4
+ List and find integration connections (``client.connections``).
5
+
6
+ .. autoclass:: modus.resources.connections.ConnectionsResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.resources.connections.AsyncConnectionsResource
11
+ :members:
12
+ :exclude-members: __init__
@@ -0,0 +1,12 @@
1
+ Context
2
+ =======
3
+
4
+ Read the knowledge base (``client.context``).
5
+
6
+ .. autoclass:: modus.resources.context.ContextResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.resources.context.AsyncContextResource
11
+ :members:
12
+ :exclude-members: __init__
@@ -0,0 +1,33 @@
1
+ Modus
2
+ =====
3
+
4
+ Day-to-day client: read scopes, chat, browse context, stream workflow runs.
5
+
6
+ .. code-block:: python
7
+
8
+ import modus
9
+
10
+ client = modus.Modus(api_key="modus_xxx")
11
+ for scope in client.scopes.list():
12
+ print(scope.name)
13
+
14
+ Write operations use ``ModusManagement`` (Management section).
15
+
16
+ .. toctree::
17
+ :maxdepth: 1
18
+ :hidden:
19
+
20
+ scopes
21
+ workflows
22
+ context
23
+ connections
24
+ chat
25
+ suggestions
26
+
27
+ .. autoclass:: modus.Modus
28
+ :members:
29
+ :exclude-members: __init__, __enter__, __exit__, __repr__
30
+
31
+ .. autoclass:: modus.AsyncModus
32
+ :members:
33
+ :exclude-members: __init__, __aenter__, __aexit__, __repr__
@@ -0,0 +1,12 @@
1
+ Scopes
2
+ ======
3
+
4
+ Read and chat with scopes (``client.scopes``).
5
+
6
+ .. autoclass:: modus.resources.scopes.ScopesResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.resources.scopes.AsyncScopesResource
11
+ :members:
12
+ :exclude-members: __init__
@@ -0,0 +1,12 @@
1
+ Suggestions
2
+ ===========
3
+
4
+ Suggested questions (``client.suggestions``).
5
+
6
+ .. autoclass:: modus.resources.suggestions.SuggestionsResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.resources.suggestions.AsyncSuggestionsResource
11
+ :members:
12
+ :exclude-members: __init__
@@ -0,0 +1,20 @@
1
+ Workflows
2
+ =========
3
+
4
+ Read workflows and stream runs (``client.workflows``).
5
+
6
+ .. autoclass:: modus.resources.workflows.WorkflowsResource
7
+ :members:
8
+ :exclude-members: __init__
9
+
10
+ .. autoclass:: modus.resources.workflows.AsyncWorkflowsResource
11
+ :members:
12
+ :exclude-members: __init__
13
+
14
+ .. autoclass:: modus.resources.workflows.WorkflowRunsResource
15
+ :members:
16
+ :exclude-members: __init__
17
+
18
+ .. autoclass:: modus.resources.workflows.AsyncWorkflowRunsResource
19
+ :members:
20
+ :exclude-members: __init__
@@ -1,6 +1,6 @@
1
1
  # Modus Skill Chat (Streamlit)
2
2
 
3
- Optional interactive demo: compare **streaming** (`client.skills.chat_stream()`) vs **buffered** (`client.skills.chat()`) skill chat side by side.
3
+ Optional interactive demo: compare **streaming** (`client.scopes.chat_stream()`) vs **buffered** (`client.scopes.chat()`) scope chat side by side.
4
4
 
5
5
  ## Setup
6
6
 
@@ -80,7 +80,7 @@ def get_buffered_client() -> modus.Modus:
80
80
  def load_active_skills() -> list[dict[str, Any]]:
81
81
  client = get_list_client()
82
82
  skills = []
83
- for skill in client.skills.list().auto_paging_iter():
83
+ for skill in client.scopes.list().auto_paging_iter():
84
84
  if skill.status == "active":
85
85
  skills.append(
86
86
  {
@@ -105,7 +105,7 @@ def _run_buffered_chat(
105
105
  thread_id: str | None,
106
106
  ) -> ChatResult | BaseException:
107
107
  try:
108
- return get_buffered_client().skills.chat(
108
+ return get_buffered_client().scopes.chat(
109
109
  skill_id,
110
110
  message,
111
111
  model=model,
@@ -178,7 +178,7 @@ def _handle_parallel_send(
178
178
  stream_placeholder = st.empty()
179
179
  accumulated = ""
180
180
  try:
181
- with get_stream_client().skills.chat_stream(
181
+ with get_stream_client().scopes.chat_stream(
182
182
  skill_id,
183
183
  prompt,
184
184
  model=model,
@@ -6,13 +6,13 @@ Quick start:
6
6
 
7
7
  client = modus.Modus(api_key="modus_xxx")
8
8
 
9
- for skill in client.skills.list():
10
- print(skill.name, skill.status)
9
+ for scope in client.scopes.list():
10
+ print(scope.name, scope.status)
11
11
 
12
12
  for item in client.context.items.list():
13
13
  print(modus.context_item_label(item))
14
14
 
15
- To create or configure skills, use modus.management.ModusManagement.
15
+ To create or configure scopes, use modus.management.ModusManagement.
16
16
  """
17
17
 
18
18
  from importlib.metadata import PackageNotFoundError
@@ -53,6 +53,9 @@ from .types import (
53
53
  ModusRunCreateRequest,
54
54
  Page,
55
55
  ResumeRunRequest,
56
+ Scope,
57
+ ScopeStatus,
58
+ ScopeVariation,
56
59
  Skill,
57
60
  SkillContextComposition,
58
61
  SkillRunCreateRequest,
@@ -60,8 +63,14 @@ from .types import (
60
63
  SuggestionEventSource,
61
64
  SuggestionEventType,
62
65
  SuggestionQuestion,
66
+ Workflow,
63
67
  WorkflowActionRequest,
68
+ WorkflowStatus,
69
+ WorkflowType,
70
+ WorkflowVariation,
64
71
  context_item_label,
72
+ conversation_scope_id,
73
+ conversation_skill_id,
65
74
  is_verified,
66
75
  link_title,
67
76
  link_url,
@@ -128,6 +137,9 @@ __all__ = [
128
137
  "RateLimitError",
129
138
  "ResumeRunRequest",
130
139
  "RunCancelledError",
140
+ "Scope",
141
+ "ScopeStatus",
142
+ "ScopeVariation",
131
143
  "Skill",
132
144
  "SkillContextComposition",
133
145
  "SkillRunCreateRequest",
@@ -139,6 +151,12 @@ __all__ = [
139
151
  "StreamTimeoutEvent",
140
152
  "TokenEvent",
141
153
  "UnprocessableError",
154
+ "Workflow",
142
155
  "WorkflowActionRequest",
156
+ "WorkflowStatus",
157
+ "WorkflowType",
158
+ "WorkflowVariation",
159
+ "conversation_scope_id",
160
+ "conversation_skill_id",
143
161
  "__version__",
144
162
  ]
@@ -68,6 +68,32 @@ def resolve_agent_host(agent_host: Optional[str]) -> Optional[str]:
68
68
  return agent_host or os.environ.get(_AGENT_HOST_ENV_VAR) or None
69
69
 
70
70
 
71
+ def _is_modus_api_hostname(hostname: str) -> bool:
72
+ """Modus-owned API hosts only: ``api.getmodus.com`` or ``api.<env>.getmodus.com``."""
73
+ import re
74
+
75
+ if hostname == "api.getmodus.com":
76
+ return True
77
+ return re.fullmatch(r"api\.[a-z0-9-]+\.getmodus\.com", hostname, flags=re.IGNORECASE) is not None
78
+
79
+
80
+ def derive_agent_host_from_base_url(base_url: str) -> Optional[str]:
81
+ """
82
+ Map ``https://api.<env>.getmodus.com`` → ``https://agent.<env>.getmodus.com``
83
+ (and prod ``api.getmodus.com`` → ``agent.getmodus.com``). Returns ``None``
84
+ for localhost / custom / non-Modus origins so callers set agent host explicitly.
85
+ """
86
+ from urllib.parse import urlsplit, urlunsplit
87
+
88
+ parts = urlsplit(base_url)
89
+ host = parts.hostname
90
+ if not host or not _is_modus_api_hostname(host):
91
+ return None
92
+ agent_host = f"agent.{host[len('api.') :]}"
93
+ netloc = f"{agent_host}:{parts.port}" if parts.port is not None else agent_host
94
+ return urlunsplit((parts.scheme, netloc, "", "", ""))
95
+
96
+
71
97
  def resolve_organization_id(organization_id: Optional[str]) -> Optional[str]:
72
98
  """
73
99
  Resolve an optional Clerk organization id for agent-host run bodies.
@@ -150,12 +150,14 @@ class ChatStream:
150
150
 
151
151
  @property
152
152
  def text_stream(self) -> Iterator[str]:
153
+ """Yield assistant reply text as it arrives, one token at a time."""
153
154
  for event in self._event_stream_impl(supports_reset=False):
154
155
  if isinstance(event, TokenEvent):
155
156
  yield event.content
156
157
 
157
158
  @property
158
159
  def event_stream(self) -> Iterator[RunEvent]:
160
+ """Yield typed stream events (tokens, tool calls, done, errors)."""
159
161
  return self._event_stream_impl(supports_reset=True)
160
162
 
161
163
  def _event_stream_impl(self, *, supports_reset: bool) -> Iterator[RunEvent]:
@@ -181,6 +183,11 @@ class ChatStream:
181
183
  yield event
182
184
 
183
185
  def get_final_result(self) -> ChatResult:
186
+ """Return the assembled reply after the stream finishes.
187
+
188
+ Raises:
189
+ ModusError: if called before the stream emits a done event.
190
+ """
184
191
  if self._final is None:
185
192
  raise ModusError(
186
193
  "Stream ended without a done event; call get_final_result() only after "
@@ -212,6 +219,7 @@ class AsyncChatStream:
212
219
 
213
220
  @property
214
221
  def text_stream(self) -> AsyncIterator[str]:
222
+ """Yield assistant reply text as it arrives. See sync ``text_stream`` for details."""
215
223
  return self._text_stream_impl()
216
224
 
217
225
  async def _text_stream_impl(self) -> AsyncIterator[str]:
@@ -221,6 +229,7 @@ class AsyncChatStream:
221
229
 
222
230
  @property
223
231
  def event_stream(self) -> AsyncIterator[RunEvent]:
232
+ """Yield typed stream events as they arrive. See sync ``event_stream`` for details."""
224
233
  return self._event_stream_impl(supports_reset=True)
225
234
 
226
235
  async def _event_stream_impl(self, *, supports_reset: bool) -> AsyncIterator[RunEvent]:
@@ -246,6 +255,7 @@ class AsyncChatStream:
246
255
  yield event
247
256
 
248
257
  def get_final_result(self) -> ChatResult:
258
+ """Return the assembled reply after the stream finishes. See sync ``get_final_result``."""
249
259
  if self._final is None:
250
260
  raise ModusError(
251
261
  "Stream ended without a done event; call get_final_result() only after "
@@ -12,6 +12,7 @@ from typing import Mapping, Optional, Union
12
12
  import httpx
13
13
 
14
14
  from ._auth import (
15
+ derive_agent_host_from_base_url,
15
16
  resolve_agent_host,
16
17
  resolve_api_key,
17
18
  resolve_base_url,
@@ -55,33 +56,9 @@ class Modus:
55
56
  MODUS_API_KEY environment variable.
56
57
  base_url: API origin without a path suffix (default
57
58
  https://api.getmodus.com).
58
- agent_host: Agent host origin for streaming runs (default
59
- https://agent.getmodus.com). Override via argument or
60
- MODUS_AGENT_HOST.
61
- organization_id: Optional Clerk org id for agent-host run bodies.
62
- Usually omit — agent-service uses the PAT principal org.
63
- Override via MODUS_ORGANIZATION_ID when needed.
64
- base_urls: Optional service-specific API origins.
65
59
  timeout: Request timeout as seconds or httpx.Timeout. Default is
66
60
  5s connect and 300s read.
67
61
  max_retries: Number of automatic retries on 429/5xx (default 2).
68
-
69
- Example:
70
- import modus
71
-
72
- client = modus.Modus(api_key="modus_xxx")
73
-
74
- for scope in client.scopes.list():
75
- print(scope.name)
76
-
77
- # Write operations use the management client in the same package:
78
- from modus.management import ModusManagement
79
-
80
- mgmt = ModusManagement(api_key="modus_xxx")
81
- mgmt.context.create_note(
82
- title="Fiscal Year",
83
- content="Runs Feb 1 – Jan 31.",
84
- )
85
62
  """
86
63
 
87
64
  def __init__(
@@ -98,9 +75,11 @@ class Modus:
98
75
  resolved_key = resolve_api_key(api_key)
99
76
  resolved_url = resolve_base_url(base_url) or DEFAULT_BASE_URL
100
77
  # Same precedence as TS: base_urls['agent-service'] drives streaming too.
78
+ # Derive agent.<rest> from api.<rest> so staging works with only the API origin.
101
79
  resolved_agent_host = (
102
80
  (base_urls or {}).get("agent-service")
103
81
  or resolve_agent_host(agent_host)
82
+ or derive_agent_host_from_base_url(resolved_url)
104
83
  or DEFAULT_AGENT_HOST
105
84
  )
106
85
  resolved_org = resolve_organization_id(organization_id)
@@ -163,25 +142,9 @@ class AsyncModus:
163
142
  api_key: Your Modus API key. If omitted, reads from MODUS_API_KEY.
164
143
  base_url: API origin without a path suffix (default
165
144
  https://api.getmodus.com).
166
- agent_host: Agent host origin for streaming runs (default
167
- https://agent.getmodus.com). Override via argument or
168
- MODUS_AGENT_HOST.
169
- organization_id: Optional Clerk org id for agent-host run bodies.
170
- base_urls: Optional service-specific API origins.
171
145
  timeout: Request timeout as seconds or httpx.Timeout. Default is
172
146
  5s connect and 300s read.
173
147
  max_retries: Retries on 429/5xx (default 2).
174
-
175
- Example:
176
- import modus
177
-
178
- client = modus.AsyncModus(api_key="modus_xxx")
179
-
180
- async def main():
181
- page = await client.scopes.list()
182
- for scope in page:
183
- print(scope.name)
184
- await client.aclose()
185
148
  """
186
149
 
187
150
  def __init__(
@@ -198,9 +161,11 @@ class AsyncModus:
198
161
  resolved_key = resolve_api_key(api_key)
199
162
  resolved_url = resolve_base_url(base_url) or DEFAULT_BASE_URL
200
163
  # Same precedence as TS: base_urls['agent-service'] drives streaming too.
164
+ # Derive agent.<rest> from api.<rest> so staging works with only the API origin.
201
165
  resolved_agent_host = (
202
166
  (base_urls or {}).get("agent-service")
203
167
  or resolve_agent_host(agent_host)
168
+ or derive_agent_host_from_base_url(resolved_url)
204
169
  or DEFAULT_AGENT_HOST
205
170
  )
206
171
  resolved_org = resolve_organization_id(organization_id)
@@ -1,8 +1,9 @@
1
1
  """Shared deprecation warnings for public SDK surfaces.
2
2
 
3
3
  Call :func:`warn_deprecated` at the start of any public method that still
4
- invokes an OpenAPI operation marked ``deprecated: true``. Release N keeps the
5
- method working and warns; release N+1 removes the operation and the method.
4
+ invokes an OpenAPI operation marked ``deprecated: true``. Soft deprecation is
5
+ optional — keep the method working and warn; remove it in a later **MAJOR**
6
+ when the operation leaves the public spec.
6
7
  """
7
8
 
8
9
  from __future__ import annotations
@@ -23,7 +24,7 @@ def warn_deprecated(*, old: str, new: str, stacklevel: int = 2) -> None:
23
24
  Passed to :func:`warnings.warn` (default 2 points at the caller).
24
25
  """
25
26
  warnings.warn(
26
- f"{old} is deprecated and will be removed in the next release; use {new} instead.",
27
+ f"{old} is deprecated and may be removed in a future MAJOR release; use {new} instead.",
27
28
  DeprecationWarning,
28
29
  stacklevel=stacklevel,
29
30
  )