mistralai-workflows-cli 1.2.2__tar.gz → 1.2.3__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 (102) hide show
  1. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/Makefile +6 -0
  2. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/PKG-INFO +1 -1
  3. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/SKILL.md +12 -3
  4. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/limitations.mdx +11 -0
  5. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/rate-limiting.mdx +3 -2
  6. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/workflows-plugins.mdx +66 -0
  7. mistralai_workflows_cli-1.2.3/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/scripts/linting/rules/determinism.yaml +217 -0
  8. mistralai_workflows_cli-1.2.3/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/scripts/linting/rules/imports.yaml +114 -0
  9. mistralai_workflows_cli-1.2.3/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/scripts/linting/rules/io.yaml +116 -0
  10. mistralai_workflows_cli-1.2.3/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/scripts/linting/rules/structure.yaml +120 -0
  11. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/scripts/test_workflow.py +62 -19
  12. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/Makefile +22 -1
  13. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/pyproject.toml.jinja +1 -0
  14. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/.gitignore +0 -0
  15. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/README.md +0 -0
  16. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/pyproject.toml +0 -0
  17. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/__init__.py +0 -0
  18. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/copier.yml +0 -0
  19. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/execution_ids.md +0 -0
  20. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/core-concepts.mdx +0 -0
  21. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/installation.mdx +0 -0
  22. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/introduction.mdx +0 -0
  23. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/python-sdk.mdx +0 -0
  24. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/value-proposition.mdx +0 -0
  25. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/your-first-workflow.mdx +0 -0
  26. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/_deployment-patterns.mdx +0 -0
  27. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/activities.mdx +0 -0
  28. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/assist-workflows.mdx +0 -0
  29. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/concurrency.mdx +0 -0
  30. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/connectors.mdx +0 -0
  31. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/dependency-injection.mdx +0 -0
  32. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/diagnostics.md +0 -0
  33. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/durable-agents.mdx +0 -0
  34. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/error-codes.mdx +0 -0
  35. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/handling-large-data.mdx +0 -0
  36. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/local-execution.mdx +0 -0
  37. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/migration-v2-to-v3.mdx +0 -0
  38. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/observability.mdx +0 -0
  39. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/payload-encoding.mdx +0 -0
  40. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/scheduling.mdx +0 -0
  41. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/signals-queries-updates.mdx +0 -0
  42. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/streaming-consumption.mdx +0 -0
  43. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/streaming.mdx +0 -0
  44. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/testing.md +0 -0
  45. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/workflows-exception.mdx +0 -0
  46. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/workflows.mdx +0 -0
  47. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/pipeline_pattern.md +0 -0
  48. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/workflow_testing.md +0 -0
  49. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.env.jinja +0 -0
  50. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/.gitignore +0 -0
  51. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/README.md.jinja +0 -0
  52. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/entrypoints/__init__.py +0 -0
  53. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/entrypoints/dev.py +0 -0
  54. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/entrypoints/start.py +0 -0
  55. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/entrypoints/worker.py +0 -0
  56. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/__init__.py +0 -0
  57. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/README.md +0 -0
  58. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/__init__.py +0 -0
  59. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/activities.py +0 -0
  60. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/models.py +0 -0
  61. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/sample_data/shipping_doc_anomaly.png +0 -0
  62. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/sample_data/shipping_doc_normal.png +0 -0
  63. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/workflow.py +0 -0
  64. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/README.md +0 -0
  65. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/__init__.py +0 -0
  66. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/activities.py +0 -0
  67. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/models.py +0 -0
  68. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/sample_data/legacy_repo/__init__.py +0 -0
  69. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/sample_data/legacy_repo/api_client.py +0 -0
  70. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/sample_data/legacy_repo/processor.py +0 -0
  71. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/sample_data/legacy_repo/utils.py +0 -0
  72. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/sub_workflow.py +0 -0
  73. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/workflow.py +0 -0
  74. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/README.md +0 -0
  75. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/__init__.py +0 -0
  76. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/activities.py +0 -0
  77. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/models.py +0 -0
  78. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/claim_high_severity.json +0 -0
  79. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/claim_low_severity.json +0 -0
  80. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/claim_medium_severity.json +0 -0
  81. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/photos/CREDITS.md +0 -0
  82. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/photos/claim_high_totaled_front.jpg +0 -0
  83. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/photos/claim_high_totaled_side.jpg +0 -0
  84. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/photos/claim_low_scratch_door.jpg +0 -0
  85. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/photos/claim_medium_dent_rear.jpg +0 -0
  86. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/workflow.py +0 -0
  87. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/linear_summarization/README.md +0 -0
  88. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/linear_summarization/__init__.py +0 -0
  89. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/linear_summarization/linear_activities.py +0 -0
  90. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/linear_summarization/summary_activity.py +0 -0
  91. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/linear_summarization/workflow.py +0 -0
  92. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/examples/worker.py +0 -0
  93. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/worker.py +0 -0
  94. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/workflows/__init__.py +0 -0
  95. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/src/workflows/hello.py +0 -0
  96. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_template/template/worker.py +0 -0
  97. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/_version.py +0 -0
  98. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/main.py +0 -0
  99. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/src/mistral_workflows_cli/setup.py +0 -0
  100. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/tests/__init__.py +0 -0
  101. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/tests/test_setup.py +0 -0
  102. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.2.3}/uv.lock +0 -0
@@ -42,6 +42,7 @@ integration-test:
42
42
  $(MAKE) _test-start-examples
43
43
  $(MAKE) _test-execute-help
44
44
  $(MAKE) _test-execute-bad-json
45
+ $(MAKE) _test-make-check
45
46
  $(MAKE) _test-wheel-contents
46
47
  @echo ""
47
48
  @echo "All integration tests passed."
@@ -124,3 +125,8 @@ _test-wheel-contents:
124
125
  | grep -q "entrypoints/worker.py" \
125
126
  && echo "OK: wheel contains entrypoints package" \
126
127
  || (echo "FAIL: wheel is missing the entrypoints package" && exit 1)
128
+
129
+ _test-make-check:
130
+ @echo "--- test: 'make check' (ruff, mypy, workflow lint) passes on the generated project"
131
+ cd $(GENERATED_PROJECT) && $(MAKE) check
132
+ @echo "OK: make check passes on the generated project"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mistralai-workflows-cli
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: CLI to bootstrap Mistral Workflows projects
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: click>=8.0
@@ -76,8 +76,8 @@ The documentation is organized into several categories:
76
76
  - **[Connectors](references/guides/connectors.mdx)**: Call third-party tools (GitHub, Notion, Slack, ...) from a workflow or give them to an agent, without holding the service's credentials
77
77
  - **[Conversational Workflows](references/guides/assist-workflows.mdx)**: InteractiveWorkflow, HITL, ChatInput/FormInput, Canvas editing, Rich UI components, Tool UI states
78
78
  - **[Local Execution](references/guides/local-execution.mdx)**: No-infra dev mode with Pydantic model params
79
- - **[Limitations](references/guides/limitations.mdx)**: System constraints and limits
80
- - **[Workflows Plugins](references/guides/workflows-plugins.mdx)**: Mistral AI plugin, Webhook plugin, Nuage plugin, custom plugins
79
+ - **[Limitations](references/guides/limitations.mdx)**: System constraints, determinism rules, sandbox import restrictions (module-level non-deterministic imports + `imports_passed_through`), I/O and heavy work belongs in activities, execution-history limits
80
+ - **[Workflows Plugins](references/guides/workflows-plugins.mdx)**: Mistral AI plugin (calling chat / structured-output / embeddings / OCR models), Webhook plugin, Nuage plugin, custom plugins
81
81
  - **[Deployment Patterns](references/guides/_deployment-patterns.mdx)**: Best practices for deploying workflows
82
82
  - **[Migration v2 to v3](references/guides/migration-v2-to-v3.mdx)**: Breaking changes and upgrade steps from SDK v2 through v3.4.0
83
83
 
@@ -101,6 +101,16 @@ python .agents/skills/workflows/scripts/test_workflow.py <workflow_file> --input
101
101
 
102
102
  If a workflow is known to be long-running (e.g. multi-step agent, large data processing), increase timeouts proportionally — but start short and only raise them when you see legitimate timeout failures, not preemptively.
103
103
 
104
+ **Lint & check** — validate your code before running it. Three checks are available:
105
+ - `make lint` — Ruff: style, imports, and common errors (`make format` auto-fixes most)
106
+ - `make typecheck` — mypy static type checking
107
+ - `make lint-workflows` — Semgrep workflow rules: determinism violations, I/O outside activities, missing return-type annotations, unsafe imports (advisory — reports but does not block)
108
+
109
+ Run all three at once after writing or editing a workflow, and address any findings:
110
+ ```bash
111
+ make check
112
+ ```
113
+
104
114
  ### Internal References
105
115
 
106
116
  These are additional patterns and utilities not covered in the official docs:
@@ -139,4 +149,3 @@ Use this skill when you need to:
139
149
  - **Durable agents**: AI agents with MCP support, multi-agent handoffs, and persistent state
140
150
  - **Connectors**: Call external services with platform-managed credentials avoiding secrets in the workflow code
141
151
  - **Scalability**: Designed to handle complex, distributed applications
142
-
@@ -144,6 +144,17 @@ if os.getenv("ENV") == "prod":
144
144
 
145
145
  must be performed in activities. While activities themselves can produce different outputs for the same inputs (as they might contain non-deterministic operations), the workflow code must behave deterministically based on the activity results it receives.
146
146
 
147
+ ### Imports must be deterministic too
148
+
149
+ The sandbox also validates **imports**. A module-level `import` of a non-deterministic library (`httpx`, `requests`, `aiohttp`, the raw `mistralai` client, etc.) in a workflow file won't work in the sandbox — the worker rejects it while validating the workflow at startup, so the workflow never becomes runnable. Keep such imports **inside the activity** that uses them, or — when a top-level import is unavoidable (e.g. shared type hints) — wrap it so the sandbox lets it through:
150
+
151
+ ```python
152
+ with workflows.workflow.unsafe.imports_passed_through():
153
+ import httpx
154
+ ```
155
+
156
+ Only pass through imports you know are side-effect-free (no import-time I/O or global-state mutation).
157
+
147
158
  ### Maximum Execution History
148
159
 
149
160
  The execution history for each workflow is capped at 51,200 events or 50MB per workflow execution. This is a hard limit of the durable execution engine. In order to avoid hitting this limit, we recommend using `workflows.execute_activities_in_parallel`, that allows you to execute large amounts of activities in parallel, while having the lowest footprint on the execution history. [Learn more about concurrency patterns](concurrency).
@@ -28,7 +28,8 @@ When **a key is provided**, multiple different activities that use the same key
28
28
 
29
29
  ```python
30
30
  import mistralai.workflows as workflows
31
- from mistralai import Mistral, Messages
31
+ from mistralai.client import Mistral
32
+ from mistralai.client.models import ChatCompletionRequestMessage
32
33
  from mistralai.workflows import Depends
33
34
  from pydantic import BaseModel
34
35
 
@@ -41,7 +42,7 @@ def get_mistral_client() -> Mistral:
41
42
 
42
43
  class CompletionParams(BaseModel):
43
44
  model: str
44
- messages: Messages
45
+ messages: list[ChatCompletionRequestMessage]
45
46
 
46
47
  @workflows.activity(rate_limit=workflows.RateLimit(time_window_in_sec=1, max_calls=100))
47
48
  async def generate_chat_response(
@@ -78,6 +78,72 @@ class SummarizeWorkflow:
78
78
  return result.choices[0].message.content
79
79
  ```
80
80
 
81
+ **Example — structured output:** to get a validated Pydantic object back instead of a string, define a model and build the same `ChatCompletionRequest` as above, then swap the final call for `chat_parse_to_model`:
82
+
83
+ ```python
84
+ from pydantic import BaseModel
85
+ from mistralai.workflows.plugins.mistralai import chat_parse_to_model
86
+
87
+ class Sentiment(BaseModel):
88
+ label: str
89
+ score: float
90
+
91
+ # inside the entrypoint, with `request` built as in the chat example above:
92
+ sentiment = await chat_parse_to_model(Sentiment, request)
93
+ ```
94
+
95
+ For the raw response instead of a parsed model, call `mistralai_chat_parse(request, response_format)` directly.
96
+
97
+ **Example — embeddings** (call from inside an entrypoint or activity):
98
+
99
+ ```python
100
+ from mistralai.workflows.plugins.mistralai import (
101
+ MistralEmbeddingsParams,
102
+ mistralai_embeddings,
103
+ )
104
+
105
+ response = await mistralai_embeddings(
106
+ MistralEmbeddingsParams(model="mistral-embed", inputs=["first text", "second text"]),
107
+ )
108
+ vectors = [item.embedding for item in response.data]
109
+ ```
110
+
111
+ **Example — OCR** extracts text from a document or image URL:
112
+
113
+ ```python
114
+ from mistralai.client.models import DocumentURLChunk
115
+ from mistralai.workflows.plugins.mistralai import OCRRequest, mistralai_ocr
116
+
117
+ result = await mistralai_ocr(
118
+ OCRRequest(
119
+ model="mistral-ocr-latest",
120
+ document=DocumentURLChunk(document_url="https://example.com/invoice.pdf"),
121
+ ),
122
+ )
123
+ pages_markdown = [page.markdown for page in result.pages]
124
+ ```
125
+
126
+ **Raw client (when a plugin activity isn't enough):** call the Mistral API directly from inside an activity. Import the client from `mistralai.client` — `mistralai` is a namespace package, so `from mistralai import Mistral` does **not** work — and keep that import inside the activity function so the workflow sandbox doesn't reject it:
127
+
128
+ ```python
129
+ import os
130
+ from mistralai.workflows import activity
131
+
132
+ @activity()
133
+ async def summarize(text: str) -> str:
134
+ # Import inside the activity so the workflow sandbox doesn't reject it.
135
+ from mistralai.client import Mistral # NOT `from mistralai import Mistral`
136
+
137
+ client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
138
+ resp = await client.chat.complete_async(
139
+ model="mistral-small-latest",
140
+ messages=[{"role": "user", "content": text}],
141
+ )
142
+ return resp.choices[0].message.content
143
+ ```
144
+
145
+ Model calls and other I/O must run inside an activity, never in the workflow body; see [Limitations](./limitations) for the determinism and import rules.
146
+
81
147
  For full documentation on `Agent`, `Runner`, sessions, MCP, and multi-agent handoffs, see the [Durable Agents guide](./durable-agents).
82
148
 
83
149
  ### Webhook Plugin
@@ -0,0 +1,217 @@
1
+ rules:
2
+ # Workflow code runs inside a determinism sandbox and is replayed on
3
+ # recovery. Non-deterministic operations break replay. These rules
4
+ # flag non-deterministic stdlib calls inside `@workflow.define` classes
5
+ # (the workflow classes). Activities and plain helper classes are exempt.
6
+
7
+ - id: no-datetime-now-in-workflow
8
+ patterns:
9
+ - pattern-either:
10
+ - pattern: datetime.now(...)
11
+ - pattern: datetime.datetime.now(...)
12
+ - pattern: datetime.utcnow(...)
13
+ - pattern: datetime.datetime.utcnow(...)
14
+ - pattern-either:
15
+ - pattern-inside: |
16
+ @workflow.define(...)
17
+ class $CLASS:
18
+ ...
19
+ - pattern-inside: |
20
+ @workflows.workflow.define(...)
21
+ class $CLASS:
22
+ ...
23
+ message: >-
24
+ Use `workflow.now()` instead of `datetime.now()` in workflow code.
25
+ Workflows must be deterministic — `datetime.now()` returns
26
+ different values on replay, breaking the execution history.
27
+ severity: ERROR
28
+ languages: [python]
29
+ metadata:
30
+ category: determinism
31
+ fix: Replace with `workflow.now()` from `mistralai.workflows`
32
+
33
+ - id: no-uuid4-in-workflow
34
+ patterns:
35
+ - pattern-either:
36
+ - pattern: uuid.uuid4(...)
37
+ - pattern: uuid4(...)
38
+ - pattern-either:
39
+ - pattern-inside: |
40
+ @workflow.define(...)
41
+ class $CLASS:
42
+ ...
43
+ - pattern-inside: |
44
+ @workflows.workflow.define(...)
45
+ class $CLASS:
46
+ ...
47
+ message: >-
48
+ Use `workflow.uuid4()` instead of `uuid.uuid4()` in workflow code.
49
+ Standard UUID generation is non-deterministic and breaks replay.
50
+ severity: ERROR
51
+ languages: [python]
52
+ metadata:
53
+ category: determinism
54
+ fix: Replace with `workflow.uuid4()` from `mistralai.workflows`
55
+
56
+ - id: no-random-in-workflow
57
+ patterns:
58
+ - pattern-either:
59
+ - pattern: random.random(...)
60
+ - pattern: random.randint(...)
61
+ - pattern: random.choice(...)
62
+ - pattern: random.shuffle(...)
63
+ - pattern: random.sample(...)
64
+ - pattern: random.uniform(...)
65
+ - pattern: random.randrange(...)
66
+ - pattern: random.gauss(...)
67
+ - pattern-either:
68
+ - pattern-inside: |
69
+ @workflow.define(...)
70
+ class $CLASS:
71
+ ...
72
+ - pattern-inside: |
73
+ @workflows.workflow.define(...)
74
+ class $CLASS:
75
+ ...
76
+ message: >-
77
+ Use `workflow.random()` instead of the `random` module in workflow
78
+ code. Standard random functions are non-deterministic and break
79
+ replay.
80
+ severity: ERROR
81
+ languages: [python]
82
+ metadata:
83
+ category: determinism
84
+ fix: Replace with `workflow.random()` from `mistralai.workflows`
85
+
86
+ - id: no-os-env-in-workflow
87
+ patterns:
88
+ - pattern-either:
89
+ - pattern: os.environ
90
+ - pattern: os.environ[...]
91
+ - pattern: os.environ.get(...)
92
+ - pattern: os.getenv(...)
93
+ - pattern: os.getcwd(...)
94
+ - pattern: os.listdir(...)
95
+ - pattern: os.path.exists(...)
96
+ - pattern-either:
97
+ - pattern-inside: |
98
+ @workflow.define(...)
99
+ class $CLASS:
100
+ ...
101
+ - pattern-inside: |
102
+ @workflows.workflow.define(...)
103
+ class $CLASS:
104
+ ...
105
+ message: >-
106
+ Do not access `os.environ`, `os.getenv()`, `os.getcwd()`, or
107
+ filesystem functions in workflow code. Environment variables and
108
+ filesystem state can differ between replays. Read config in an
109
+ activity and pass it as workflow input, or use dependency injection.
110
+ severity: ERROR
111
+ languages: [python]
112
+ metadata:
113
+ category: determinism
114
+ fix: Move to an activity or use dependency injection (Depends)
115
+
116
+ - id: no-time-in-workflow
117
+ patterns:
118
+ - pattern-either:
119
+ - pattern: time.time(...)
120
+ - pattern: time.monotonic(...)
121
+ - pattern: time.sleep(...)
122
+ - pattern-either:
123
+ - pattern-inside: |
124
+ @workflow.define(...)
125
+ class $CLASS:
126
+ ...
127
+ - pattern-inside: |
128
+ @workflows.workflow.define(...)
129
+ class $CLASS:
130
+ ...
131
+ message: >-
132
+ Do not use `time.time()`, `time.monotonic()`, or `time.sleep()`
133
+ in workflow code. Use `workflow.now()` for timestamps and
134
+ `asyncio.sleep()` for delays (which is durable and survives
135
+ replays).
136
+ severity: ERROR
137
+ languages: [python]
138
+ metadata:
139
+ category: determinism
140
+ fix: Use `workflow.now()` for time, `asyncio.sleep()` for delays
141
+
142
+ - id: no-hashlib-in-workflow
143
+ patterns:
144
+ - pattern-either:
145
+ - pattern: hashlib.sha256(...)
146
+ - pattern: hashlib.sha512(...)
147
+ - pattern: hashlib.md5(...)
148
+ - pattern: hashlib.sha1(...)
149
+ - pattern: hashlib.new(...)
150
+ - pattern: hashlib.pbkdf2_hmac(...)
151
+ - pattern-either:
152
+ - pattern-inside: |
153
+ @workflow.define(...)
154
+ class $CLASS:
155
+ ...
156
+ - pattern-inside: |
157
+ @workflows.workflow.define(...)
158
+ class $CLASS:
159
+ ...
160
+ message: >-
161
+ Cryptographic operations are CPU-intensive and can exceed the
162
+ 2-second limit between activities. Move hashing to an activity:
163
+ @activity()
164
+ async def hash_data(data: bytes) -> str:
165
+ return hashlib.sha256(data).hexdigest()
166
+ severity: WARNING
167
+ languages: [python]
168
+ metadata:
169
+ category: determinism
170
+ fix: Move cryptographic operations to an activity
171
+
172
+ - id: no-global-in-workflow
173
+ patterns:
174
+ - pattern: global $VAR
175
+ - pattern-either:
176
+ - pattern-inside: |
177
+ @workflow.define(...)
178
+ class $CLASS:
179
+ ...
180
+ - pattern-inside: |
181
+ @workflows.workflow.define(...)
182
+ class $CLASS:
183
+ ...
184
+ message: >-
185
+ Do not use `global` in workflow code. Modifying global variables
186
+ is non-deterministic — the global state may differ between
187
+ replays. Store state on `self` or pass it through activities.
188
+ severity: ERROR
189
+ languages: [python]
190
+ metadata:
191
+ category: determinism
192
+ fix: Use `self.field` for workflow state, or pass data via activities
193
+
194
+ - id: no-model-validate-in-workflow
195
+ patterns:
196
+ - pattern: $MODEL.model_validate(...)
197
+ - pattern-either:
198
+ - pattern-inside: |
199
+ @workflow.define(...)
200
+ class $CLASS:
201
+ ...
202
+ - pattern-inside: |
203
+ @workflows.workflow.define(...)
204
+ class $CLASS:
205
+ ...
206
+ message: >-
207
+ Pydantic `.model_validate()` can be CPU-intensive on large
208
+ payloads and may exceed the 2-second limit between activities.
209
+ Move heavy validation to an activity:
210
+ @activity()
211
+ async def validate(data: dict) -> MyModel:
212
+ return MyModel.model_validate(data)
213
+ severity: WARNING
214
+ languages: [python]
215
+ metadata:
216
+ category: determinism
217
+ fix: Move validation to an activity
@@ -0,0 +1,114 @@
1
+ rules:
2
+ - id: no-temporalio-import
3
+ pattern-either:
4
+ - pattern: import temporalio
5
+ - pattern: import temporalio.$MOD
6
+ - pattern: from temporalio import $X
7
+ - pattern: from temporalio.$MOD import $X
8
+ message: >-
9
+ Do not import `temporalio` directly. The workflows SDK re-exports
10
+ everything you need: `workflow.now()`, `workflow.uuid4()`,
11
+ `workflow.random()`, `workflow.wait_condition()`,
12
+ `workflow.continue_as_new()`, `WorkflowError`, `ActivityError`,
13
+ `ParentClosePolicy`, etc.
14
+ Use `from mistralai.workflows import ...` instead.
15
+ severity: ERROR
16
+ languages: [python]
17
+ metadata:
18
+ category: import
19
+ fix: Replace with the equivalent import from `mistralai.workflows`
20
+
21
+ - id: top-level-httpx-import
22
+ patterns:
23
+ - pattern: import httpx
24
+ - pattern-not-inside: |
25
+ def $F(...):
26
+ ...
27
+ - pattern-not-inside: |
28
+ async def $F(...):
29
+ ...
30
+ message: >-
31
+ Avoid top-level `import httpx`. The determinism sandbox re-imports
32
+ modules, and top-level imports with side effects can cause issues.
33
+ Import httpx inside your activity function instead:
34
+ @activity()
35
+ async def call_api(url: str) -> dict:
36
+ import httpx
37
+ async with httpx.AsyncClient() as client: ...
38
+ severity: WARNING
39
+ languages: [python]
40
+ metadata:
41
+ category: import
42
+ fix: Move `import httpx` inside the activity function body
43
+
44
+ - id: top-level-requests-import
45
+ patterns:
46
+ - pattern-either:
47
+ - pattern: import requests
48
+ - pattern: from requests import $X
49
+ - pattern-not-inside: |
50
+ def $F(...):
51
+ ...
52
+ - pattern-not-inside: |
53
+ async def $F(...):
54
+ ...
55
+ message: >-
56
+ Do not use the `requests` library. It is synchronous and blocks
57
+ the event loop. Use `httpx.AsyncClient` instead, imported inside
58
+ your activity function.
59
+ severity: WARNING
60
+ languages: [python]
61
+ metadata:
62
+ category: import
63
+ fix: Remove `requests` and use `httpx.AsyncClient` in activities
64
+
65
+ - id: top-level-aiohttp-import
66
+ patterns:
67
+ - pattern-either:
68
+ - pattern: import aiohttp
69
+ - pattern: from aiohttp import $X
70
+ - pattern-not-inside: |
71
+ def $F(...):
72
+ ...
73
+ - pattern-not-inside: |
74
+ async def $F(...):
75
+ ...
76
+ message: >-
77
+ Avoid top-level `import aiohttp`. Import it inside your activity
78
+ function to avoid sandbox re-import issues.
79
+ severity: WARNING
80
+ languages: [python]
81
+ metadata:
82
+ category: import
83
+ fix: Move the import inside the activity function body
84
+
85
+ - id: top-level-mistral-client-import
86
+ patterns:
87
+ - pattern-either:
88
+ - pattern: import mistralai.client
89
+ - pattern: import mistralai.client.$SUB
90
+ - pattern: from mistralai.client import $X
91
+ - pattern: from mistralai.client.$SUB import $X
92
+ - pattern-not-inside: |
93
+ def $F(...):
94
+ ...
95
+ - pattern-not-inside: |
96
+ async def $F(...):
97
+ ...
98
+ - pattern-not-inside: |
99
+ with workflows.workflow.unsafe.imports_passed_through():
100
+ ...
101
+ - pattern-not-inside: |
102
+ with workflow.unsafe.imports_passed_through():
103
+ ...
104
+ message: >-
105
+ Avoid a top-level import from `mistralai.client` (the raw SDK). It pulls in
106
+ `httpx`, which the determinism sandbox rejects when it re-imports the workflow
107
+ module — the worker then fails to validate the workflow at startup. Prefer the
108
+ Mistral AI plugin activities (`mistralai_chat_complete`, `mistralai_ocr`, ...);
109
+ if you genuinely need the raw client, import it inside the activity that uses it.
110
+ severity: ERROR
111
+ languages: [python]
112
+ metadata:
113
+ category: import
114
+ fix: Use a plugin activity, or import `mistralai.client` inside the activity body
@@ -0,0 +1,116 @@
1
+ rules:
2
+ # All I/O must be performed in activities. Workflow code may be
3
+ # replayed, and I/O operations would violate determinism or cause
4
+ # duplicate side effects.
5
+
6
+ - id: no-file-io-in-workflow
7
+ patterns:
8
+ - pattern-either:
9
+ - pattern: open(...)
10
+ - pattern: aiofiles.open(...)
11
+ - pattern-either:
12
+ - pattern-inside: |
13
+ @workflow.define(...)
14
+ class $CLASS:
15
+ ...
16
+ - pattern-inside: |
17
+ @workflows.workflow.define(...)
18
+ class $CLASS:
19
+ ...
20
+ message: >-
21
+ Do not perform file I/O in workflow code. Move file operations
22
+ to an activity:
23
+ @activity()
24
+ async def read_file(path: str) -> str:
25
+ async with aiofiles.open(path) as f:
26
+ return await f.read()
27
+ severity: ERROR
28
+ languages: [python]
29
+ metadata:
30
+ category: io
31
+ fix: Move file I/O to an activity function
32
+
33
+ - id: no-http-client-in-workflow
34
+ patterns:
35
+ - pattern-either:
36
+ - pattern: httpx.AsyncClient(...)
37
+ - pattern: httpx.Client(...)
38
+ - pattern: aiohttp.ClientSession(...)
39
+ - pattern-either:
40
+ - pattern-inside: |
41
+ @workflow.define(...)
42
+ class $CLASS:
43
+ ...
44
+ - pattern-inside: |
45
+ @workflows.workflow.define(...)
46
+ class $CLASS:
47
+ ...
48
+ message: >-
49
+ Do not make HTTP calls in workflow code. Move all HTTP/API calls
50
+ to an activity:
51
+ @activity()
52
+ async def call_api(url: str) -> dict:
53
+ async with httpx.AsyncClient() as client:
54
+ resp = await client.get(url)
55
+ return resp.json()
56
+ severity: ERROR
57
+ languages: [python]
58
+ metadata:
59
+ category: io
60
+ fix: Move HTTP calls to an activity function
61
+
62
+ - id: no-db-in-workflow
63
+ patterns:
64
+ - pattern-either:
65
+ - pattern: await $CONN.execute(...)
66
+ - pattern: await $CONN.fetch(...)
67
+ - pattern: await $CONN.fetchone(...)
68
+ - pattern: await $CONN.fetchall(...)
69
+ - pattern: await $CONN.fetchrow(...)
70
+ - pattern: await $CONN.query(...)
71
+ - pattern: await $CONN.commit(...)
72
+ - pattern: $CONN.commit(...)
73
+ - pattern-either:
74
+ - pattern-inside: |
75
+ @workflow.define(...)
76
+ class $CLASS:
77
+ ...
78
+ - pattern-inside: |
79
+ @workflows.workflow.define(...)
80
+ class $CLASS:
81
+ ...
82
+ message: >-
83
+ Do not perform database operations in workflow code. Move all
84
+ database queries to an activity. Use dependency injection
85
+ (Depends) to provide the connection:
86
+ @activity()
87
+ async def query_db(
88
+ q: str,
89
+ conn: Connection = Depends(get_connection),
90
+ ) -> list[dict]:
91
+ return await conn.fetch(q)
92
+ severity: ERROR
93
+ languages: [python]
94
+ metadata:
95
+ category: io
96
+ fix: Move database operations to an activity function
97
+
98
+ - id: no-sync-requests-library
99
+ pattern-either:
100
+ - pattern: requests.get(...)
101
+ - pattern: requests.post(...)
102
+ - pattern: requests.put(...)
103
+ - pattern: requests.delete(...)
104
+ - pattern: requests.patch(...)
105
+ - pattern: requests.head(...)
106
+ - pattern: requests.request(...)
107
+ message: >-
108
+ The `requests` library is synchronous and blocks the event loop.
109
+ Use `httpx.AsyncClient` instead:
110
+ async with httpx.AsyncClient() as client:
111
+ response = await client.get(url)
112
+ severity: ERROR
113
+ languages: [python]
114
+ metadata:
115
+ category: async
116
+ fix: Replace `requests` with `httpx.AsyncClient`