mistralai-workflows-cli 1.2.2__tar.gz → 1.3.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 (106) hide show
  1. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/.gitignore +19 -0
  2. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/Makefile +6 -0
  3. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/PKG-INFO +2 -2
  4. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/pyproject.toml +1 -0
  5. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/SKILL.md +32 -16
  6. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/value-proposition.mdx +1 -1
  7. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/activities.mdx +4 -2
  8. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/concurrency.mdx +20 -0
  9. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/connectors.mdx +0 -1
  10. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/diagnostics.md +2 -2
  11. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/durable-agents.mdx +106 -0
  12. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/limitations.mdx +11 -0
  13. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/rate-limiting.mdx +13 -15
  14. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/testing.md +13 -3
  15. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/workflows-plugins.mdx +71 -0
  16. mistralai_workflows_cli-1.3.0/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/scripts/linting/rules/determinism.yaml +217 -0
  17. mistralai_workflows_cli-1.3.0/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/scripts/linting/rules/imports.yaml +114 -0
  18. mistralai_workflows_cli-1.3.0/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/scripts/linting/rules/io.yaml +116 -0
  19. mistralai_workflows_cli-1.3.0/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/scripts/linting/rules/structure.yaml +120 -0
  20. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/scripts/test_workflow.py +129 -78
  21. mistralai_workflows_cli-1.3.0/src/mistral_workflows_cli/_template/template/.dockerignore +17 -0
  22. mistralai_workflows_cli-1.3.0/src/mistral_workflows_cli/_template/template/.vibe/check_hooks.py +56 -0
  23. mistralai_workflows_cli-1.3.0/src/mistral_workflows_cli/_template/template/.vibe/hooks.toml +9 -0
  24. mistralai_workflows_cli-1.3.0/src/mistral_workflows_cli/_template/template/Dockerfile +26 -0
  25. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/Makefile +32 -1
  26. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/README.md.jinja +14 -0
  27. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/pyproject.toml.jinja +1 -0
  28. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/entrypoints/worker.py +16 -1
  29. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/workflows/hello.py +1 -1
  30. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/uv.lock +3 -3
  31. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/README.md +0 -0
  32. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/__init__.py +0 -0
  33. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/copier.yml +0 -0
  34. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/execution_ids.md +0 -0
  35. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/core-concepts.mdx +0 -0
  36. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/installation.mdx +0 -0
  37. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/introduction.mdx +0 -0
  38. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/python-sdk.mdx +0 -0
  39. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/getting-started/your-first-workflow.mdx +0 -0
  40. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/_deployment-patterns.mdx +0 -0
  41. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/assist-workflows.mdx +0 -0
  42. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/dependency-injection.mdx +0 -0
  43. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/error-codes.mdx +0 -0
  44. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/handling-large-data.mdx +0 -0
  45. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/local-execution.mdx +0 -0
  46. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/migration-v2-to-v3.mdx +0 -0
  47. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/observability.mdx +0 -0
  48. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/payload-encoding.mdx +0 -0
  49. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/scheduling.mdx +0 -0
  50. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/signals-queries-updates.mdx +0 -0
  51. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/streaming-consumption.mdx +0 -0
  52. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/streaming.mdx +0 -0
  53. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/workflows-exception.mdx +0 -0
  54. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/guides/workflows.mdx +0 -0
  55. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/pipeline_pattern.md +0 -0
  56. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.agents/skills/workflows/references/workflow_testing.md +0 -0
  57. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.env.jinja +0 -0
  58. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/.gitignore +0 -0
  59. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/entrypoints/__init__.py +0 -0
  60. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/entrypoints/dev.py +0 -0
  61. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/entrypoints/start.py +0 -0
  62. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/__init__.py +0 -0
  63. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/README.md +0 -0
  64. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/__init__.py +0 -0
  65. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/activities.py +0 -0
  66. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/models.py +0 -0
  67. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/sample_data/shipping_doc_anomaly.png +0 -0
  68. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/sample_data/shipping_doc_normal.png +0 -0
  69. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/cargo_release/workflow.py +0 -0
  70. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/README.md +0 -0
  71. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/__init__.py +0 -0
  72. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/activities.py +0 -0
  73. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/models.py +0 -0
  74. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/sample_data/legacy_repo/__init__.py +0 -0
  75. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/sample_data/legacy_repo/api_client.py +0 -0
  76. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/sample_data/legacy_repo/processor.py +0 -0
  77. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/sample_data/legacy_repo/utils.py +0 -0
  78. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/sub_workflow.py +0 -0
  79. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/code_modernization/workflow.py +0 -0
  80. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/README.md +0 -0
  81. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/__init__.py +0 -0
  82. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/activities.py +0 -0
  83. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/models.py +0 -0
  84. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/claim_high_severity.json +0 -0
  85. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/claim_low_severity.json +0 -0
  86. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/claim_medium_severity.json +0 -0
  87. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/photos/CREDITS.md +0 -0
  88. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/photos/claim_high_totaled_front.jpg +0 -0
  89. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/photos/claim_high_totaled_side.jpg +0 -0
  90. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/photos/claim_low_scratch_door.jpg +0 -0
  91. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/sample_data/photos/claim_medium_dent_rear.jpg +0 -0
  92. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/insurance_claims/workflow.py +0 -0
  93. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/linear_summarization/README.md +0 -0
  94. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/linear_summarization/__init__.py +0 -0
  95. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/linear_summarization/linear_activities.py +0 -0
  96. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/linear_summarization/summary_activity.py +0 -0
  97. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/linear_summarization/workflow.py +0 -0
  98. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/examples/worker.py +0 -0
  99. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/worker.py +0 -0
  100. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/src/workflows/__init__.py +0 -0
  101. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_template/template/worker.py +0 -0
  102. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/_version.py +0 -0
  103. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/main.py +0 -0
  104. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/src/mistral_workflows_cli/setup.py +0 -0
  105. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/tests/__init__.py +0 -0
  106. {mistralai_workflows_cli-1.2.2 → mistralai_workflows_cli-1.3.0}/tests/test_setup.py +0 -0
@@ -79,6 +79,9 @@ target/
79
79
  # Ruff
80
80
  .ruff_cache/
81
81
 
82
+ # import-linter
83
+ .import_linter_cache/
84
+
82
85
  # Jupyter Notebook
83
86
  .ipynb_checkpoints
84
87
 
@@ -128,6 +131,7 @@ celerybeat.pid
128
131
  .env.local
129
132
  .envrc
130
133
  .venv
134
+ .run-vcw/
131
135
  env/
132
136
  venv/
133
137
  ENV/
@@ -222,6 +226,21 @@ jobs/run/checkpoints/test/consolidated/params.json
222
226
 
223
227
  # Agent plans (scratch planning docs)
224
228
  .agents/plans/
229
+
230
+ # Playwright MCP accessibility snapshots (local browser-debug artifacts)
231
+ .playwright-mcp/
232
+ .playwright-cli/
233
+
225
234
  tsconfig.tsbuildinfo
226
235
 
227
236
  .vscode-test/
237
+ infra/local/docker-compose.override.yaml
238
+
239
+ # Atlas overlap-scan generated fixtures
240
+ ts/packages/workflow-graph/tests/fixtures/overlap-views.json
241
+
242
+ # Go build output (go/Makefile "build" target); already in go/.dockerignore
243
+ go/bin/
244
+
245
+ # GHA→Buildkite migration tracker (local working ledger, not version-controlled)
246
+ tools/buildkite-pipeline/MIGRATION_STATUS.md
@@ -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
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: mistralai-workflows-cli
3
- Version: 1.2.2
3
+ Version: 1.3.0
4
4
  Summary: CLI to bootstrap Mistral Workflows projects
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: click>=8.0
@@ -15,6 +15,7 @@ mistralai-workflows-cli = "mistral_workflows_cli.main:cli"
15
15
 
16
16
  [tool.uv]
17
17
  exclude-newer = "2 days"
18
+ index-strategy = "first-index"
18
19
 
19
20
  [build-system]
20
21
  requires = ["hatchling", "uv-dynamic-versioning"]
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: workflows
3
- description: Framework for building durable workflows with orchestrated activities, used for background jobs, multi-step pipelines, scheduled tasks, LLM agents, or any process requiring fault tolerance, retries, and long-running execution. This skill provides comprehensive documentation and guidance for working with the Mistral Workflows framework.
3
+ description: Use when writing, editing, or debugging Mistral Workflows code (`mistralai.workflows`): workflows and activities, background jobs, multi-step pipelines, scheduled tasks, durable LLM agents, and any process needing fault tolerance, retries, or long-running execution. Covers the determinism and import rules, the Mistral AI plugin API, activity timeouts and retries, signals and HITL, and a pre-flight check to run before finishing.
4
4
  license: Complete terms in LICENSE.txt
5
5
  ---
6
6
 
@@ -44,6 +44,8 @@ Focused snippets may use `from mistralai.workflows import workflow, activity, ..
44
44
 
45
45
  Call activities directly (`await my_activity(args)`); timeouts and retries live on the `@activity(...)` decorator, not at the call site.
46
46
 
47
+ **Calling Mistral plugins:** prefer the plugin activities (`mistralai_chat_complete`, `mistralai_ocr`, `mistralai_embeddings`, `chat_parse_to_model`, …; see [Workflows Plugins](references/guides/workflows-plugins.mdx)) — they are sandbox-safe. Use the raw `mistralai.client.Mistral` only when no plugin fits, and import it inside the activity that uses it: a module-level import pulls in `httpx`, which the sandbox rejects at worker startup (see [Limitations](references/guides/limitations.mdx)). Hoist it to module scope only under `workflow.unsafe.imports_passed_through()`.
48
+
47
49
  ## Documentation Structure
48
50
 
49
51
  The documentation is organized into several categories:
@@ -76,22 +78,43 @@ The documentation is organized into several categories:
76
78
  - **[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
79
  - **[Conversational Workflows](references/guides/assist-workflows.mdx)**: InteractiveWorkflow, HITL, ChatInput/FormInput, Canvas editing, Rich UI components, Tool UI states
78
80
  - **[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
81
+ - **[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
82
+ - **[Workflows Plugins](references/guides/workflows-plugins.mdx)**: Mistral AI plugin (calling chat / structured-output / embeddings / OCR models), Webhook plugin, Nuage plugin, custom plugins
81
83
  - **[Deployment Patterns](references/guides/_deployment-patterns.mdx)**: Best practices for deploying workflows
82
84
  - **[Migration v2 to v3](references/guides/migration-v2-to-v3.mdx)**: Breaking changes and upgrade steps from SDK v2 through v3.4.0
83
85
 
84
- ### Testing
86
+ ### Testing & Diagnostics
85
87
 
86
88
  - **[Testing Workflows](references/guides/testing.md)**: Integration testing with `create_test_worker`, hang prevention, sandbox pitfalls
87
89
  - **[Diagnostics](references/guides/diagnostics.md)**: Run `wf-diagnose` locally or on Kubernetes to collect a diagnostic report for support triage
88
90
 
89
- **Quick-test script** — run any workflow in a local test environment with zero setup:
91
+ ### Internal References
92
+
93
+ These are additional patterns and utilities not covered in the official docs:
94
+
95
+ - **[Execution IDs](references/execution_ids.md)**: Generate deterministic execution IDs for child workflows
96
+ - **[Pipeline Pattern](references/pipeline_pattern.md)**: Build multi-step workflows with declarative StepSpec definitions
97
+ - **[Workflow Testing](references/workflow_testing.md)**: Ensure workflow classes are properly registered in workers
98
+
99
+ ## Testing
100
+
101
+ Run the project's static checks before reporting a workflow as done. Three static checks are available:
102
+
103
+ - `make lint` — Ruff: style, imports, and common errors (`make format` auto-fixes most)
104
+ - `make typecheck` — mypy static type checking
105
+ - `make lint-workflows` — Semgrep workflow rules: determinism violations, I/O outside activities, missing return-type annotations, unsafe imports (advisory — reports but does not block)
106
+
107
+ And `make check` runs all three.
108
+
109
+ To start the workflow and do a test run with sample inputs, use the `test_workflow.py` script:
110
+
90
111
  ```bash
91
- python .agents/skills/workflows/scripts/test_workflow.py <workflow_file> --input '{"key": "value"}' [--timeout 30]
112
+ uv run python .agents/skills/workflows/scripts/test_workflow.py <workflow_file> --input '{"key": "value"}' [--timeout 30]
92
113
  ```
93
114
 
94
- **Timeout policy for testing:** Use aggressive (short) timeouts to keep the feedback loop tight. A hanging test wastes more time than a false timeout. Defaults:
115
+ `ruff`, `mypy`, and `semgrep` are the project's dev dependencies; `make check` invokes them through `uv run`.
116
+
117
+ Use timeouts to keep the feedback loop tight. A hanging test wastes more time than a false timeout. Defaults:
95
118
 
96
119
  | Context | Recommended timeout | When to increase |
97
120
  |---|---|---|
@@ -99,15 +122,9 @@ python .agents/skills/workflows/scripts/test_workflow.py <workflow_file> --input
99
122
  | `execution_timeout` (pytest) | `timedelta(seconds=10)` | Known long-running workflow |
100
123
  | `asyncio.wait_for` (pytest) | `15` seconds | Should always be slightly above `execution_timeout` |
101
124
 
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.
125
+ If a workflow is known to be long-running (e.g. multi-step agent, large data processing), increase timeouts proportionally. Start short and only raise them when you see legitimate timeout failures, not preemptively.
103
126
 
104
- ### Internal References
105
-
106
- These are additional patterns and utilities not covered in the official docs:
107
-
108
- - **[Execution IDs](references/execution_ids.md)**: Generate deterministic execution IDs for child workflows
109
- - **[Pipeline Pattern](references/pipeline_pattern.md)**: Build multi-step workflows with declarative StepSpec definitions
110
- - **[Workflow Testing](references/workflow_testing.md)**: Ensure workflow classes are properly registered in workers
127
+ > **You must run the static checks and a test run before reporting a workflow as done.** This ensures that the workflow is deterministic, free of I/O outside activities, and passes basic integration tests. Failure to do so will result in failing workflows and wasted time for the developer. Never forget this.
111
128
 
112
129
  ## When to Use This Skill
113
130
 
@@ -139,4 +156,3 @@ Use this skill when you need to:
139
156
  - **Durable agents**: AI agents with MCP support, multi-agent handoffs, and persistent state
140
157
  - **Connectors**: Call external services with platform-managed credentials avoiding secrets in the workflow code
141
158
  - **Scalability**: Designed to handle complex, distributed applications
142
-
@@ -59,7 +59,7 @@ result = await my_activity(name) # Just call it
59
59
 
60
60
  ### 2. Configuration on Decorators
61
61
 
62
- - Activities: `@activity(start_to_close_timeout=..., retry_policy_max_attempts=..., rate_limit=..., name=...)`
62
+ - Activities: `@activity(start_to_close_timeout=timedelta(seconds=30), retry_policy_max_attempts=3, name="fetch_data")`, where `start_to_close_timeout` takes a `datetime.timedelta`
63
63
  - Workflows: `@workflow.define(name=..., workflow_display_name=..., workflow_description=...)`
64
64
  - Configure once on the decorator instead of at every call site
65
65
 
@@ -72,13 +72,15 @@ Customize activity identification with:
72
72
  Configure execution time limits to prevent runaway activities:
73
73
 
74
74
  ```python
75
- from datetime import datetime
75
+ from datetime import timedelta
76
76
 
77
77
  @workflows.activity(
78
- start_to_close_timeout=datetime.timedelta(minutes=10)
78
+ start_to_close_timeout=timedelta(minutes=10),
79
79
  )
80
80
  ```
81
81
 
82
+ `start_to_close_timeout` and the other `*_timeout` params must be a `datetime.timedelta`. Passing an int or a string raises at activity-definition time.
83
+
82
84
  [Learn more about timeouts](#)
83
85
 
84
86
  ### 3. Retry Policies
@@ -26,6 +26,26 @@ All patterns are built on the platform's workflow continuation primitives, provi
26
26
  - **Fault Tolerance**: Built-in error handling and retry mechanisms
27
27
  - **Progress Tracking**: Monitor execution progress through built-in observability features
28
28
 
29
+ ## Small Batches: `asyncio.gather`
30
+
31
+ The patterns described in the other sections add continue-as-new, per-item progress, retry, and scale past a few thousand items. For fewer items, `asyncio.gather` is enough. Activities are awaitables, so gathering them runs concurrently with no bookkeeping, and you stay under the 51,200-event history limit that continue-as-new exists to manage.
32
+
33
+ ```python
34
+ import asyncio
35
+
36
+ # Named, heterogeneous calls:
37
+ a, b, c = await asyncio.gather(
38
+ fetch(user_a),
39
+ fetch(user_b),
40
+ fetch(user_c),
41
+ )
42
+
43
+ # A collection you hold in full:
44
+ results = await asyncio.gather(*[process_item(item) for item in params.items])
45
+ ```
46
+
47
+ Use `execute_activities_in_parallel` past a few thousand items, or when you need continue-as-new, progress tracking, or per-item retry.
48
+
29
49
  ## List Executor Pattern
30
50
 
31
51
  ### Use Case
@@ -121,7 +121,6 @@ class GitHubIssueCreatorWorkflow:
121
121
  Fall back to worker credentials (omit `on_behalf_of`) when there's no triggering user or you deliberately want one shared identity. Caveats (platform-enforced):
122
122
 
123
123
  - **Needs a triggering user.** Starting an `on_behalf_of=True` workflow without a user session is rejected (`403 "On-behalf-of workflows require user identity"`). For the same reason it **can't be combined with `schedules`** — the SDK raises at definition time, since a scheduled run has no triggering user.
124
- - **Restricted to Mistral-internal orgs.** Registering an `on_behalf_of=True` workflow returns `403 "on_behalf workflows are currently restricted to Mistral-internal organizations"` unless the org is internal or the `ON_BEHALF_WORKFLOWS_ENABLED` feature flag is enabled.
125
124
 
126
125
  ## Connectors in durable agents
127
126
 
@@ -11,13 +11,13 @@ sidebar_position: 21
11
11
  ## Running Locally
12
12
 
13
13
  ```bash
14
- wf-diagnose
14
+ uv run wf-diagnose
15
15
  ```
16
16
 
17
17
  Or via module:
18
18
 
19
19
  ```bash
20
- python -m mistralai.workflows.scripts.diagnose
20
+ uv run python -m mistralai.workflows.scripts.diagnose
21
21
  ```
22
22
 
23
23
  ## Running on a Kubernetes Cluster
@@ -225,6 +225,31 @@ agent = Agent(
225
225
  )
226
226
  ```
227
227
 
228
+ #### Forwarding credentials to a stdio server
229
+
230
+ Some stdio MCP servers need credentials (e.g. a bot token) to authenticate. Use
231
+ `env_mapping` to inject them from the worker's environment into the subprocess.
232
+ The mapping goes from **subprocess variable name** to **worker variable name**:
233
+
234
+ ```python
235
+ mcp_config = MCPStdioConfig(
236
+ command="npx",
237
+ args=["-y", "@notionhq/notion-mcp-server"],
238
+ name="notion_bot_a",
239
+ env_mapping={"NOTION_TOKEN": "NOTION_TOKEN_BOT_A"},
240
+ )
241
+ ```
242
+
243
+ Why pass a mapping instead of the raw values? Activity inputs are persisted to
244
+ the Temporal event history, so loading secrets from the worker's environment and
245
+ passing them directly would expose them there. With `env_mapping`, only the
246
+ mapping names are serialized into activity params and event history; the secret
247
+ values are read from the worker's environment inside the activity and never leave
248
+ it. This also lets you run several instances of the same server with different
249
+ credentials (e.g. `NOTION_TOKEN_BOT_A` and `NOTION_TOKEN_BOT_B`) on one worker.
250
+ If a declared worker variable is missing from the environment, the activity
251
+ fails fast.
252
+
228
253
  ### SSE MCP Server
229
254
 
230
255
  For remote MCP servers over Server-Sent Events:
@@ -247,6 +272,87 @@ agent = workflows_mistralai.Agent(
247
272
  )
248
273
  ```
249
274
 
275
+ ### Streamable HTTP MCP Server
276
+
277
+ For remote MCP servers that speak the Streamable HTTP transport (`--transport http`),
278
+ such as a self-hosted server behind an HTTP endpoint:
279
+
280
+ > **Requires `mistralai>=2.8.0`.** The Streamable HTTP client ships in the `mistralai`
281
+ > client from 2.8.0 (client-python#592). This plugin keeps a permissive floor
282
+ > (`mistralai>=2.0.0`), so if you use `MCPStreamableHTTPConfig`, pin
283
+ > `mistralai>=2.8.0` in your own project's dependencies.
284
+
285
+ ```python
286
+ from mistralai.workflows.plugins.mistralai import MCPStreamableHTTPConfig
287
+
288
+ mcp_config = MCPStreamableHTTPConfig(
289
+ url="https://your-mcp-server.com/mcp",
290
+ name="remote-tools",
291
+ )
292
+
293
+ agent = Agent(
294
+ model="mistral-medium-latest",
295
+ name="streamable-http-mcp-agent",
296
+ description="Agent with access to a Streamable HTTP MCP server",
297
+ mcp_clients=[mcp_config],
298
+ )
299
+ ```
300
+
301
+ #### Forwarding credentials to a Streamable HTTP server
302
+
303
+ A Streamable HTTP server usually needs credentials on every request: a bearer token
304
+ gating the endpoint and/or a per-request integration token. Set them from the
305
+ worker's environment so no secret is ever serialized into the Temporal event history
306
+ (the same reasoning as `env_mapping` above).
307
+
308
+ Use `auth_token_env` for the endpoint bearer. The SDK reads the raw token from that
309
+ worker variable inside the activity and sends it as `Authorization: Bearer <value>`,
310
+ so store the raw token in your secret manager and let the SDK add the scheme:
311
+
312
+ ```python
313
+ mcp_config = MCPStreamableHTTPConfig(
314
+ url="https://your-mcp-server.com/mcp",
315
+ name="remote-tools",
316
+ auth_token_env="MCP_ENDPOINT_TOKEN",
317
+ )
318
+ ```
319
+
320
+ Use `header_mapping` for any other per-request secret header. Like `env_mapping`,
321
+ each entry maps an **HTTP header name** to a **worker variable name**, and only the
322
+ names are serialized; the values are read from the worker's environment inside the
323
+ activity:
324
+
325
+ ```python
326
+ mcp_config = MCPStreamableHTTPConfig(
327
+ url="https://your-mcp-server.com/mcp",
328
+ name="notion",
329
+ auth_token_env="MCP_ENDPOINT_TOKEN", # -> Authorization: Bearer <value>
330
+ header_mapping={"Notion-Token": "NOTION_TOKEN_BOT_A"}, # header <- whole env value
331
+ )
332
+ ```
333
+
334
+ Only put non-secret values in the static `headers` field, since those are serialized
335
+ into activity params. As with `env_mapping`, a declared worker variable that is
336
+ missing from the environment makes the activity fail fast. A fresh client is opened
337
+ per call, so different callers or tokens never share a session.
338
+
339
+ **Redirects**
340
+
341
+ By default the client does **not** follow HTTP redirects (`follow_redirects=False`).
342
+ On a redirect, `httpx` only strips the `Authorization` header on cross-origin hops,
343
+ so the per-request secret headers above (e.g. `Notion-Token`) would be resent to the
344
+ redirect target, letting a compromised or open-redirecting MCP exfiltrate them. If
345
+ your MCP server relies on redirects (for example `/mcp` -> `/mcp/`) and you trust
346
+ every host it can redirect to, opt in:
347
+
348
+ ```python
349
+ mcp_config = MCPStreamableHTTPConfig(
350
+ url="https://your-mcp-server.com/mcp",
351
+ name="remote-tools",
352
+ follow_redirects=True,
353
+ )
354
+ ```
355
+
250
356
  ## Built-in Tools
251
357
 
252
358
  Use Mistral's built-in tools alongside activities:
@@ -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,32 +28,30 @@ 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
32
31
  from mistralai.workflows import Depends
33
32
  from pydantic import BaseModel
34
33
 
35
- def get_mistral_client() -> Mistral:
36
- """Creates a shared chat completion client with rate limiting"""
37
- client = Mistral(
38
- api_key="your_api_key",
39
- )
40
- return client
34
+
35
+ def get_mistral_client():
36
+ """Shared Mistral client wired with workflows tracking + OBO interceptors."""
37
+ from mistralai.workflows.plugins.mistralai import get_mistral_client as _get_client
38
+
39
+ return _get_client()
40
+
41
41
 
42
42
  class CompletionParams(BaseModel):
43
43
  model: str
44
- messages: Messages
44
+ messages: list[dict]
45
+
45
46
 
46
47
  @workflows.activity(rate_limit=workflows.RateLimit(time_window_in_sec=1, max_calls=100))
47
- async def generate_chat_response(
48
- params: CompletionParams,
49
- client: Mistral = Depends(get_mistral_client)
50
- ):
51
- """Generates a chat response using a shared client"""
52
- # This activity can be called from multiple workflows
53
- # but will share the same rate limit across all of them
48
+ async def generate_chat_response(params: CompletionParams, client=Depends(get_mistral_client)):
49
+ """Generate a chat response using the shared client."""
54
50
  return await client.chat.complete_async(model=params.model, messages=params.messages)
55
51
  ```
56
52
 
53
+ The `mistralai.workflows.plugins.mistralai` import lives inside `get_mistral_client`, not at module scope. Imported at the top of a workflow file, it pulls in `httpx`, which the determinism sandbox rejects at startup.
54
+
57
55
  **Behavior**: All workflows calling `generate_chat_response` share the same 100 calls/sec limit. If Workflow A makes 60 calls and Workflow B makes 50 calls in the same second, they compete for the same pool.
58
56
 
59
57
  **With a key**: Add `key="mistral_api"` to share this limit across multiple activities (e.g., `generate_chat_response`, `generate_embeddings`, `moderate_content`).
@@ -11,7 +11,7 @@ sidebar_position: 20
11
11
  The fastest way to verify a workflow works end-to-end. No test files, no conftest, no pytest:
12
12
 
13
13
  ```bash
14
- python .agents/skills/workflows/scripts/test_workflow.py src/workflows/my_workflow.py \
14
+ uv run python .agents/skills/workflows/scripts/test_workflow.py src/workflows/my_workflow.py \
15
15
  --input '{"key": "value"}' \
16
16
  --timeout 30
17
17
  ```
@@ -19,7 +19,7 @@ python .agents/skills/workflows/scripts/test_workflow.py src/workflows/my_workfl
19
19
  For interactive workflows that use `wait_for_input()`, provide `--interactions`:
20
20
 
21
21
  ```bash
22
- python .agents/skills/workflows/scripts/test_workflow.py src/workflows/my_workflow.py \
22
+ uv run python .agents/skills/workflows/scripts/test_workflow.py src/workflows/my_workflow.py \
23
23
  --input '{}' \
24
24
  --interactions '[{"choice": "WFL"}]' \
25
25
  --timeout 60
@@ -40,6 +40,7 @@ Options:
40
40
  - `--timeout` (default 30): max seconds before the workflow is killed
41
41
  - `--workflow-name`: select a specific workflow if the file contains multiple
42
42
  - `--interactions`: JSON array of responses for interactive workflows
43
+ - `DEPLOYMENT_NAME` (env): deployment the worker registers under; defaults to `"default"`
43
44
 
44
45
  Because the script uses a real worker, you get full worker logs (activity errors, retries, HTTP failures) in real time on stderr. No time-skipping — activities execute with real network calls.
45
46
 
@@ -115,7 +116,7 @@ Always use both.
115
116
  ### `start_to_close_timeout` must be a `timedelta`
116
117
 
117
118
  ```python
118
- # WRONG — causes infinite retry loop
119
+ # WRONG — raises AttributeError: 'int' object has no attribute 'total_seconds'
119
120
  @activity(start_to_close_timeout=60)
120
121
 
121
122
  # RIGHT
@@ -148,3 +149,12 @@ The test client returns raw dicts. Access fields directly: `result["message"]`,
148
149
  ### Don't add `_emit_*` activities manually
149
150
 
150
151
  `create_test_worker` already registers all workflow-lifecycle event activities. Adding them again causes duplicate-activity registration errors.
152
+
153
+ ### `AMBIGUOUS_WORKFLOW` error
154
+
155
+ Happens when multiple deployments register the same workflow name and the API can't tell which worker should run it. Set `DEPLOYMENT_NAME` to match the deployment your worker should register under:
156
+
157
+ ```bash
158
+ DEPLOYMENT_NAME=my-deployment python .agents/skills/workflows/scripts/test_workflow.py \
159
+ src/workflows/my_workflow.py --input '{}'
160
+ ```
@@ -78,6 +78,77 @@ 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.workflows import activity
115
+ from mistralai.workflows.plugins.mistralai import OCRRequest, mistralai_ocr
116
+
117
+
118
+ @activity()
119
+ async def extract_text(document_url: str) -> list[str]:
120
+ from mistralai.client.models import DocumentURLChunk
121
+
122
+ result = await mistralai_ocr(
123
+ OCRRequest(
124
+ model="mistral-ocr-latest",
125
+ document=DocumentURLChunk(document_url=document_url),
126
+ ),
127
+ )
128
+ return [page.markdown for page in result.pages]
129
+ ```
130
+
131
+ **Raw client (when a plugin activity isn't enough):** call the Mistral API directly from inside an activity, and keep the `from mistralai.client import Mistral` import inside the activity function. A module-level import of the raw client pulls in `httpx`, which the determinism sandbox rejects while validating the workflow at startup (see [Limitations](./limitations)). `mistralai` is a namespace package, so the path is `mistralai.client`; `from mistralai import Mistral` does not work:
132
+
133
+ ```python
134
+ import os
135
+ from mistralai.workflows import activity
136
+
137
+ @activity()
138
+ async def summarize(text: str) -> str:
139
+ # Import inside the activity so the workflow sandbox doesn't reject it.
140
+ from mistralai.client import Mistral # NOT `from mistralai import Mistral`
141
+
142
+ client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
143
+ resp = await client.chat.complete_async(
144
+ model="mistral-small-latest",
145
+ messages=[{"role": "user", "content": text}],
146
+ )
147
+ return resp.choices[0].message.content
148
+ ```
149
+
150
+ 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.
151
+
81
152
  For full documentation on `Agent`, `Runner`, sessions, MCP, and multi-agent handoffs, see the [Durable Agents guide](./durable-agents).
82
153
 
83
154
  ### Webhook Plugin