batchor 0.0.4__tar.gz → 0.0.5__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 (121) hide show
  1. {batchor-0.0.4 → batchor-0.0.5}/.agents/skills/batchor-dev/SKILL.md +2 -1
  2. {batchor-0.0.4 → batchor-0.0.5}/PKG-INFO +50 -6
  3. {batchor-0.0.4 → batchor-0.0.5}/README.md +46 -4
  4. batchor-0.0.5/docs/design_docs/ANTHROPIC_BATCHING.md +33 -0
  5. {batchor-0.0.4 → batchor-0.0.5}/docs/design_docs/ARCHITECTURE.md +15 -4
  6. {batchor-0.0.4 → batchor-0.0.5}/docs/design_docs/OPENAI_BATCHING.md +5 -2
  7. {batchor-0.0.4 → batchor-0.0.5}/docs/design_docs/ROADMAP.md +2 -6
  8. {batchor-0.0.4 → batchor-0.0.5}/docs/design_docs/STORAGE_AND_RUNS.md +14 -1
  9. {batchor-0.0.4 → batchor-0.0.5}/docs/doc-map.md +2 -0
  10. {batchor-0.0.4 → batchor-0.0.5}/docs/getting-started/cli.md +21 -0
  11. {batchor-0.0.4 → batchor-0.0.5}/docs/getting-started/installation.md +13 -1
  12. {batchor-0.0.4 → batchor-0.0.5}/docs/getting-started/python-api.md +26 -0
  13. {batchor-0.0.4 → batchor-0.0.5}/docs/index.md +1 -1
  14. {batchor-0.0.4 → batchor-0.0.5}/docs/policies/contributing.md +1 -1
  15. {batchor-0.0.4 → batchor-0.0.5}/docs/reference/api.md +10 -0
  16. {batchor-0.0.4 → batchor-0.0.5}/docs/smoke-test.md +17 -1
  17. {batchor-0.0.4 → batchor-0.0.5}/mkdocs.yml +1 -0
  18. {batchor-0.0.4 → batchor-0.0.5}/plugins/batchor/scripts/batchor_user_mcp.py +25 -12
  19. {batchor-0.0.4 → batchor-0.0.5}/plugins/batchor/skills/use-batchor/SKILL.md +3 -3
  20. {batchor-0.0.4 → batchor-0.0.5}/plugins/batchor/skills/use-batchor/references/cli-workflows.md +2 -0
  21. {batchor-0.0.4 → batchor-0.0.5}/plugins/batchor/skills/use-batchor/references/python-pipelines.md +2 -0
  22. {batchor-0.0.4 → batchor-0.0.5}/plugins/batchor-agent-tools/scripts/batchor_repo_mcp.py +14 -3
  23. {batchor-0.0.4 → batchor-0.0.5}/pyproject.toml +5 -2
  24. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/__init__.py +6 -0
  25. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/cli.py +21 -0
  26. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/core/enums.py +1 -0
  27. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/core/exceptions.py +11 -0
  28. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/core/models.py +67 -0
  29. batchor-0.0.5/src/batchor/providers/anthropic.py +177 -0
  30. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/providers/registry.py +16 -2
  31. batchor-0.0.5/src/batchor/runtime/execution.py +105 -0
  32. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/ingestion.py +13 -0
  33. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/polling.py +2 -0
  34. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/run_handle.py +5 -13
  35. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/runner.py +14 -10
  36. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/memory.py +2 -1
  37. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/sqlite_queries.py +14 -1
  38. batchor-0.0.5/tests/integration/test_batchor_live_anthropic.py +60 -0
  39. {batchor-0.0.4 → batchor-0.0.5}/tests/integration/test_batchor_runner.py +115 -0
  40. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_agent_tooling.py +43 -0
  41. batchor-0.0.5/tests/unit/test_batchor_anthropic_provider.py +117 -0
  42. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_architecture.py +26 -0
  43. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_cli.py +37 -1
  44. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_storage_contracts.py +24 -0
  45. {batchor-0.0.4 → batchor-0.0.5}/uv.lock +34 -2
  46. {batchor-0.0.4 → batchor-0.0.5}/.agents/plugins/marketplace.json +0 -0
  47. {batchor-0.0.4 → batchor-0.0.5}/.agents/skills/batchor-dev/agents/openai.yaml +0 -0
  48. {batchor-0.0.4 → batchor-0.0.5}/.github/workflows/ci.yml +0 -0
  49. {batchor-0.0.4 → batchor-0.0.5}/.github/workflows/docs.yml +0 -0
  50. {batchor-0.0.4 → batchor-0.0.5}/.github/workflows/publish.yml +0 -0
  51. {batchor-0.0.4 → batchor-0.0.5}/.gitignore +0 -0
  52. {batchor-0.0.4 → batchor-0.0.5}/.pre-commit-config.yaml +0 -0
  53. {batchor-0.0.4 → batchor-0.0.5}/AGENTS.md +0 -0
  54. {batchor-0.0.4 → batchor-0.0.5}/CONTRIBUTING.md +0 -0
  55. {batchor-0.0.4 → batchor-0.0.5}/LICENSE +0 -0
  56. {batchor-0.0.4 → batchor-0.0.5}/SUPPORT.md +0 -0
  57. {batchor-0.0.4 → batchor-0.0.5}/VERSIONING.md +0 -0
  58. {batchor-0.0.4 → batchor-0.0.5}/docs/assets/stylesheets/extra.css +0 -0
  59. {batchor-0.0.4 → batchor-0.0.5}/docs/design_docs/BOUNDARY_AND_PHILOSOPHY.md +0 -0
  60. {batchor-0.0.4 → batchor-0.0.5}/docs/design_docs/GEMINI_BATCHING.md +0 -0
  61. {batchor-0.0.4 → batchor-0.0.5}/docs/design_docs/STORAGE_MIGRATIONS.md +0 -0
  62. {batchor-0.0.4 → batchor-0.0.5}/docs/getting-started/use-cases.md +0 -0
  63. {batchor-0.0.4 → batchor-0.0.5}/docs/policies/support.md +0 -0
  64. {batchor-0.0.4 → batchor-0.0.5}/docs/policies/versioning.md +0 -0
  65. {batchor-0.0.4 → batchor-0.0.5}/plugins/batchor/.codex-plugin/plugin.json +0 -0
  66. {batchor-0.0.4 → batchor-0.0.5}/plugins/batchor/.mcp.json +0 -0
  67. {batchor-0.0.4 → batchor-0.0.5}/plugins/batchor/skills/use-batchor/agents/openai.yaml +0 -0
  68. {batchor-0.0.4 → batchor-0.0.5}/plugins/batchor-agent-tools/.codex-plugin/plugin.json +0 -0
  69. {batchor-0.0.4 → batchor-0.0.5}/plugins/batchor-agent-tools/.mcp.json +0 -0
  70. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/artifacts/__init__.py +0 -0
  71. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/artifacts/base.py +0 -0
  72. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/artifacts/local.py +0 -0
  73. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/core/__init__.py +0 -0
  74. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/core/responses.py +0 -0
  75. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/core/types.py +0 -0
  76. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/providers/__init__.py +0 -0
  77. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/providers/base.py +0 -0
  78. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/providers/gemini.py +0 -0
  79. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/providers/openai.py +0 -0
  80. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/py.typed +0 -0
  81. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/__init__.py +0 -0
  82. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/artifacts.py +0 -0
  83. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/context.py +0 -0
  84. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/results.py +0 -0
  85. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/retry.py +0 -0
  86. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/submission.py +0 -0
  87. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/tokens.py +0 -0
  88. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/runtime/validation.py +0 -0
  89. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/sources/__init__.py +0 -0
  90. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/sources/base.py +0 -0
  91. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/sources/composite.py +0 -0
  92. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/sources/files.py +0 -0
  93. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/__init__.py +0 -0
  94. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/postgres.py +0 -0
  95. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/postgres_store.py +0 -0
  96. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/registry.py +0 -0
  97. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/sqlite.py +0 -0
  98. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/sqlite_codec.py +0 -0
  99. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/sqlite_lifecycle.py +0 -0
  100. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/sqlite_protocol.py +0 -0
  101. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/sqlite_results.py +0 -0
  102. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/sqlite_schema.py +0 -0
  103. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/sqlite_store.py +0 -0
  104. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/state.py +0 -0
  105. {batchor-0.0.4 → batchor-0.0.5}/src/batchor/storage/state_models.py +0 -0
  106. {batchor-0.0.4 → batchor-0.0.5}/tests/integration/test_batchor_gemini_runner.py +0 -0
  107. {batchor-0.0.4 → batchor-0.0.5}/tests/integration/test_batchor_live_gemini.py +0 -0
  108. {batchor-0.0.4 → batchor-0.0.5}/tests/integration/test_batchor_live_openai.py +0 -0
  109. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_artifacts.py +0 -0
  110. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_gemini_provider.py +0 -0
  111. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_openai_provider.py +0 -0
  112. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_results.py +0 -0
  113. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_retry.py +0 -0
  114. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_runtime_ingestion.py +0 -0
  115. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_runtime_polling.py +0 -0
  116. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_runtime_submission.py +0 -0
  117. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_sources.py +0 -0
  118. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_sqlite_storage_flow.py +0 -0
  119. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_storage.py +0 -0
  120. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_tokens.py +0 -0
  121. {batchor-0.0.4 → batchor-0.0.5}/tests/unit/test_batchor_validation.py +0 -0
@@ -14,13 +14,14 @@ Use this skill for normal contributor work in this repository.
14
14
  3. Load only the design docs that match the task:
15
15
  - `docs/design_docs/ARCHITECTURE.md` for package layout and runtime boundaries
16
16
  - `docs/design_docs/OPENAI_BATCHING.md` for provider-specific batching behavior
17
+ - `docs/design_docs/ANTHROPIC_BATCHING.md` for Anthropic Message Batches behavior
17
18
  - `docs/design_docs/STORAGE_AND_RUNS.md` for durable state, run lifecycle, and retention
18
19
  - `docs/smoke-test.md` for the full validation matrix
19
20
 
20
21
  ## Repo map
21
22
 
22
23
  - `src/batchor/runtime/`: orchestration, run handles, validation, retry, token budgeting
23
- - `src/batchor/providers/`: provider interfaces and OpenAI Batch implementation
24
+ - `src/batchor/providers/`: provider interfaces and OpenAI, Anthropic, and Gemini implementations
24
25
  - `src/batchor/storage/`: SQLite, Postgres, and in-memory durability backends
25
26
  - `src/batchor/sources/`: file-backed checkpointable item sources
26
27
  - `src/batchor/artifacts/`: durable request/output artifact handling
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batchor
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: Structured-first provider Batch runner with typed Pydantic results.
5
5
  Project-URL: Documentation, https://github.com/AnsonDev42/batchor#readme
6
6
  Project-URL: Repository, https://github.com/AnsonDev42/batchor
@@ -79,7 +79,7 @@ License: # PolyForm Noncommercial License 1.0.0
79
79
 
80
80
  **Use** means anything you do with the software requiring one of your licenses.
81
81
  License-File: LICENSE
82
- Keywords: batch,cli,gemini,openai,pydantic,sqlite
82
+ Keywords: anthropic,batch,cli,gemini,openai,pydantic,sqlite
83
83
  Classifier: Development Status :: 3 - Alpha
84
84
  Classifier: Environment :: Console
85
85
  Classifier: Intended Audience :: Developers
@@ -99,6 +99,8 @@ Requires-Dist: python-dotenv<2,>=1.0.1
99
99
  Requires-Dist: sqlalchemy<3,>=2.0.43
100
100
  Requires-Dist: tiktoken>=0.12.0
101
101
  Requires-Dist: typer<1,>=0.16.0
102
+ Provides-Extra: anthropic
103
+ Requires-Dist: anthropic<1,>=0.71.0; extra == 'anthropic'
102
104
  Provides-Extra: gemini
103
105
  Requires-Dist: google-cloud-storage<4,>=3.4.0; extra == 'gemini'
104
106
  Requires-Dist: google-genai<2,>=1.55.0; extra == 'gemini'
@@ -118,7 +120,7 @@ Description-Content-Type: text/markdown
118
120
  - library-first run controls
119
121
  - a small operator CLI for CSV and JSONL jobs
120
122
 
121
- It is intentionally narrow today: OpenAI is the CLI default, Gemini is opt-in through `batchor[gemini]`, SQLite is the CLI durability backend, and the Python API exposes the broadest configuration surface.
123
+ It is intentionally narrow today: OpenAI is the CLI default, Anthropic and Gemini are opt-in through provider extras, SQLite is the CLI durability backend, and the Python API exposes the broadest configuration surface.
122
124
 
123
125
  ## What problem it solves
124
126
 
@@ -143,6 +145,7 @@ Most OpenAI Batch examples stop at "upload a JSONL file and poll until it finish
143
145
  Built-in implementations:
144
146
 
145
147
  - `OpenAIProviderConfig` + `OpenAIBatchProvider`
148
+ - `AnthropicProviderConfig` + `AnthropicBatchProvider` for Claude Message Batches
146
149
  - `GeminiProviderConfig` + `GeminiBatchProvider` for text-only Gemini Batch jobs
147
150
  - `SQLiteStorage`
148
151
  - `PostgresStorage` as an opt-in durable control-plane backend
@@ -159,7 +162,7 @@ Important constraints:
159
162
  - the CLI supports file-backed inputs only
160
163
  - users still own selecting and ordering input files or partitions
161
164
  - the built-in CLI uses SQLite durability only
162
- - the CLI supports OpenAI plus Gemini Developer API and Vertex AI text jobs
165
+ - the CLI supports OpenAI, Anthropic, Gemini Developer API, and Vertex AI text jobs
163
166
  - Gemini support is text-only for now and does not build multimodal requests
164
167
  - structured-output rehydration requires an importable module-level Pydantic model
165
168
  - raw output artifacts are retained by default and must be exported before raw pruning
@@ -185,6 +188,14 @@ Durability is split on purpose:
185
188
 
186
189
  That split is what allows retries and fresh-process resume without keeping every request inline in the control-plane store.
187
190
  On resume, existing active provider batches are polled before `batchor` materializes or submits new local work, so completed batches and retry backoff are reconciled first. Deterministic sources also use stored checkpoint completion metadata to avoid opening a fully materialized Parquet or composite source just to discover there are no rows left.
191
+ Incomplete checkpointed ingestion keeps the run non-terminal. In the process that
192
+ started the job, `Run.resume()` can continue from the attached source. After a
193
+ fresh-process rehydration, call `start(job, run_id=...)`; `refresh()` otherwise
194
+ raises `RunIngestionSourceRequiredError` instead of silently completing only the
195
+ already-materialized rows.
196
+ Cancelling an incompletely ingested checkpointed source abandons its
197
+ unmaterialized tail and finalizes the checkpoint after active batches drain, so
198
+ the cancelled run can still reach a terminal lifecycle state.
188
199
 
189
200
  ## Architecture
190
201
 
@@ -195,10 +206,12 @@ graph LR
195
206
  subgraph runtime["runtime/"]
196
207
  BatchRunner
197
208
  Run["Run handle"]
209
+ Executor["RunExecutor"]
198
210
  end
199
211
 
200
212
  subgraph providers["providers/"]
201
213
  OpenAI["OpenAIBatchProvider"]
214
+ Anthropic["AnthropicBatchProvider"]
202
215
  Gemini["GeminiBatchProvider"]
203
216
  end
204
217
 
@@ -218,7 +231,9 @@ graph LR
218
231
 
219
232
  User -->|"start() / run_and_wait()"| BatchRunner
220
233
  BatchRunner --> Run
234
+ BatchRunner --> Executor
221
235
  BatchRunner --> OpenAI
236
+ BatchRunner --> Anthropic
222
237
  BatchRunner --> Gemini
223
238
  BatchRunner --> SQLite
224
239
  BatchRunner --> LocalFS
@@ -261,6 +276,12 @@ For Gemini Batch support, install the optional extra:
261
276
  pip install "batchor[gemini]"
262
277
  ```
263
278
 
279
+ For Anthropic Message Batches support:
280
+
281
+ ```bash
282
+ pip install "batchor[anthropic]"
283
+ ```
284
+
264
285
  ## Agent setup
265
286
 
266
287
  Batchor keeps contributor tooling separate from the tools intended for researchers and downstream projects:
@@ -291,8 +312,8 @@ Supported Python versions:
291
312
 
292
313
  For Python API usage, auth resolution is:
293
314
 
294
- 1. explicit provider config credentials such as `OpenAIProviderConfig(api_key=...)` or `GeminiProviderConfig(api_key=...)`
295
- 2. ambient provider environment variables, currently `OPENAI_API_KEY` or `GEMINI_API_KEY`
315
+ 1. explicit provider config credentials such as `OpenAIProviderConfig(api_key=...)`, `AnthropicProviderConfig(api_key=...)`, or `GeminiProviderConfig(api_key=...)`
316
+ 2. ambient provider environment variables: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY`
296
317
  3. Vertex AI Application Default Credentials when `GeminiProviderConfig(vertexai=True, ...)` or `GOOGLE_GENAI_USE_VERTEXAI=true` is used
297
318
 
298
319
  The Python library does not auto-load `.env`.
@@ -322,6 +343,29 @@ run = runner.run_and_wait(
322
343
  print(run.results()[0].output_text)
323
344
  ```
324
345
 
346
+ ### Anthropic text job
347
+
348
+ ```python
349
+ from batchor import AnthropicProviderConfig, BatchItem, BatchJob, BatchRunner, PromptParts
350
+
351
+
352
+ runner = BatchRunner(storage="memory")
353
+ run = runner.run_and_wait(
354
+ BatchJob(
355
+ items=[BatchItem(item_id="row1", payload="Summarize this text")],
356
+ build_prompt=lambda item: PromptParts(prompt=item.payload),
357
+ provider_config=AnthropicProviderConfig(
358
+ model="claude-sonnet-4-5",
359
+ max_tokens=1024,
360
+ ),
361
+ )
362
+ )
363
+
364
+ print(run.results()[0].output_text)
365
+ ```
366
+
367
+ Anthropic support maps Batchor attempt identifiers deterministically to Claude-safe `custom_id` values and supports system prompts, `message_params`, and structured outputs through `output_config.format`.
368
+
325
369
  ### Gemini text job
326
370
 
327
371
  ```python
@@ -12,7 +12,7 @@
12
12
  - library-first run controls
13
13
  - a small operator CLI for CSV and JSONL jobs
14
14
 
15
- It is intentionally narrow today: OpenAI is the CLI default, Gemini is opt-in through `batchor[gemini]`, SQLite is the CLI durability backend, and the Python API exposes the broadest configuration surface.
15
+ It is intentionally narrow today: OpenAI is the CLI default, Anthropic and Gemini are opt-in through provider extras, SQLite is the CLI durability backend, and the Python API exposes the broadest configuration surface.
16
16
 
17
17
  ## What problem it solves
18
18
 
@@ -37,6 +37,7 @@ Most OpenAI Batch examples stop at "upload a JSONL file and poll until it finish
37
37
  Built-in implementations:
38
38
 
39
39
  - `OpenAIProviderConfig` + `OpenAIBatchProvider`
40
+ - `AnthropicProviderConfig` + `AnthropicBatchProvider` for Claude Message Batches
40
41
  - `GeminiProviderConfig` + `GeminiBatchProvider` for text-only Gemini Batch jobs
41
42
  - `SQLiteStorage`
42
43
  - `PostgresStorage` as an opt-in durable control-plane backend
@@ -53,7 +54,7 @@ Important constraints:
53
54
  - the CLI supports file-backed inputs only
54
55
  - users still own selecting and ordering input files or partitions
55
56
  - the built-in CLI uses SQLite durability only
56
- - the CLI supports OpenAI plus Gemini Developer API and Vertex AI text jobs
57
+ - the CLI supports OpenAI, Anthropic, Gemini Developer API, and Vertex AI text jobs
57
58
  - Gemini support is text-only for now and does not build multimodal requests
58
59
  - structured-output rehydration requires an importable module-level Pydantic model
59
60
  - raw output artifacts are retained by default and must be exported before raw pruning
@@ -79,6 +80,14 @@ Durability is split on purpose:
79
80
 
80
81
  That split is what allows retries and fresh-process resume without keeping every request inline in the control-plane store.
81
82
  On resume, existing active provider batches are polled before `batchor` materializes or submits new local work, so completed batches and retry backoff are reconciled first. Deterministic sources also use stored checkpoint completion metadata to avoid opening a fully materialized Parquet or composite source just to discover there are no rows left.
83
+ Incomplete checkpointed ingestion keeps the run non-terminal. In the process that
84
+ started the job, `Run.resume()` can continue from the attached source. After a
85
+ fresh-process rehydration, call `start(job, run_id=...)`; `refresh()` otherwise
86
+ raises `RunIngestionSourceRequiredError` instead of silently completing only the
87
+ already-materialized rows.
88
+ Cancelling an incompletely ingested checkpointed source abandons its
89
+ unmaterialized tail and finalizes the checkpoint after active batches drain, so
90
+ the cancelled run can still reach a terminal lifecycle state.
82
91
 
83
92
  ## Architecture
84
93
 
@@ -89,10 +98,12 @@ graph LR
89
98
  subgraph runtime["runtime/"]
90
99
  BatchRunner
91
100
  Run["Run handle"]
101
+ Executor["RunExecutor"]
92
102
  end
93
103
 
94
104
  subgraph providers["providers/"]
95
105
  OpenAI["OpenAIBatchProvider"]
106
+ Anthropic["AnthropicBatchProvider"]
96
107
  Gemini["GeminiBatchProvider"]
97
108
  end
98
109
 
@@ -112,7 +123,9 @@ graph LR
112
123
 
113
124
  User -->|"start() / run_and_wait()"| BatchRunner
114
125
  BatchRunner --> Run
126
+ BatchRunner --> Executor
115
127
  BatchRunner --> OpenAI
128
+ BatchRunner --> Anthropic
116
129
  BatchRunner --> Gemini
117
130
  BatchRunner --> SQLite
118
131
  BatchRunner --> LocalFS
@@ -155,6 +168,12 @@ For Gemini Batch support, install the optional extra:
155
168
  pip install "batchor[gemini]"
156
169
  ```
157
170
 
171
+ For Anthropic Message Batches support:
172
+
173
+ ```bash
174
+ pip install "batchor[anthropic]"
175
+ ```
176
+
158
177
  ## Agent setup
159
178
 
160
179
  Batchor keeps contributor tooling separate from the tools intended for researchers and downstream projects:
@@ -185,8 +204,8 @@ Supported Python versions:
185
204
 
186
205
  For Python API usage, auth resolution is:
187
206
 
188
- 1. explicit provider config credentials such as `OpenAIProviderConfig(api_key=...)` or `GeminiProviderConfig(api_key=...)`
189
- 2. ambient provider environment variables, currently `OPENAI_API_KEY` or `GEMINI_API_KEY`
207
+ 1. explicit provider config credentials such as `OpenAIProviderConfig(api_key=...)`, `AnthropicProviderConfig(api_key=...)`, or `GeminiProviderConfig(api_key=...)`
208
+ 2. ambient provider environment variables: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY`
190
209
  3. Vertex AI Application Default Credentials when `GeminiProviderConfig(vertexai=True, ...)` or `GOOGLE_GENAI_USE_VERTEXAI=true` is used
191
210
 
192
211
  The Python library does not auto-load `.env`.
@@ -216,6 +235,29 @@ run = runner.run_and_wait(
216
235
  print(run.results()[0].output_text)
217
236
  ```
218
237
 
238
+ ### Anthropic text job
239
+
240
+ ```python
241
+ from batchor import AnthropicProviderConfig, BatchItem, BatchJob, BatchRunner, PromptParts
242
+
243
+
244
+ runner = BatchRunner(storage="memory")
245
+ run = runner.run_and_wait(
246
+ BatchJob(
247
+ items=[BatchItem(item_id="row1", payload="Summarize this text")],
248
+ build_prompt=lambda item: PromptParts(prompt=item.payload),
249
+ provider_config=AnthropicProviderConfig(
250
+ model="claude-sonnet-4-5",
251
+ max_tokens=1024,
252
+ ),
253
+ )
254
+ )
255
+
256
+ print(run.results()[0].output_text)
257
+ ```
258
+
259
+ Anthropic support maps Batchor attempt identifiers deterministically to Claude-safe `custom_id` values and supports system prompts, `message_params`, and structured outputs through `output_config.format`.
260
+
219
261
  ### Gemini text job
220
262
 
221
263
  ```python
@@ -0,0 +1,33 @@
1
+ # Anthropic Batching
2
+
3
+ The built-in Anthropic provider targets the Claude Message Batches API.
4
+
5
+ ## Request mapping
6
+
7
+ Each Batchor item attempt becomes one Anthropic batch request:
8
+
9
+ - Batchor's durable correlation identifier is deterministically hashed into Anthropic's 64-character-safe `custom_id` alphabet
10
+ - `PromptParts.prompt` becomes one user message
11
+ - `PromptParts.system_prompt` becomes the top-level `system` parameter
12
+ - `model` and `max_tokens` come from `AnthropicProviderConfig`
13
+ - `message_params` supplies optional Messages API parameters
14
+ - structured output schemas use `output_config.format`
15
+
16
+ Batchor rejects provider-owned fields in `message_params` so replayed requests cannot silently change model, token limit, messages, system prompt, or streaming behavior.
17
+
18
+ ## Submission and lifecycle
19
+
20
+ Anthropic accepts request objects directly rather than an uploaded JSONL file. The provider therefore stages Batchor's durable request artifact in memory only for the upload/create boundary, then calls `messages.batches.create(requests=...)`.
21
+
22
+ Anthropic `in_progress` maps to Batchor's active status and `ended` maps to `completed`. Once ended, the provider streams `messages.batches.results(...)` into Batchor's raw output artifact. Result order is not assumed; correlation always uses `custom_id`.
23
+
24
+ The four Anthropic result types map as follows:
25
+
26
+ - `succeeded`: Batchor success
27
+ - `errored`, `canceled`, and `expired`: Batchor item error, subject to the configured retry policy
28
+
29
+ ## Limits and retention
30
+
31
+ Anthropic currently limits a Message Batch to 100,000 requests or 256 MB. Batchor's default chunk limits are lower than both limits. Claude batch results remain available from Anthropic for 29 days; Batchor downloads and retains them according to its artifact policy, so durable runs do not depend on that remote retention window after ingestion.
32
+
33
+ Message Batches are not eligible for Anthropic Zero Data Retention. Users should account for Anthropic's batch retention policy when selecting workloads.
@@ -61,6 +61,7 @@ graph TB
61
61
  subgraph providers["providers/"]
62
62
  BatchProvider["BatchProvider (ABC)"]
63
63
  OpenAIProvider["OpenAIBatchProvider"]
64
+ AnthropicProvider["AnthropicBatchProvider"]
64
65
  GeminiProvider["GeminiBatchProvider"]
65
66
  ProviderRegistry
66
67
  end
@@ -95,6 +96,7 @@ graph TB
95
96
  MemoryStateStore -.->|implements| StateStore
96
97
  BatchRunner -->|submits/polls| BatchProvider
97
98
  OpenAIProvider -.->|implements| BatchProvider
99
+ AnthropicProvider -.->|implements| BatchProvider
98
100
  GeminiProvider -.->|implements| BatchProvider
99
101
  BatchRunner -->|stores artifacts| ArtifactStore
100
102
  LocalArtifactStore -.->|implements| ArtifactStore
@@ -126,7 +128,7 @@ one logical source, while callers remain responsible for selecting and ordering
126
128
  the child sources up front.
127
129
 
128
130
  Provider adaptation is intentionally concentrated behind `BatchProvider`.
129
- The runtime stores one durable internal custom identifier per item attempt, while each provider maps that identifier to its own request shape. OpenAI uses `custom_id`; the Gemini Developer API uses `key`; Vertex AI uses a request label that is returned with the original request in GCS output.
131
+ The runtime stores one durable internal custom identifier per item attempt, while each provider maps that identifier to its own request shape. OpenAI and Anthropic use `custom_id`; the Gemini Developer API uses `key`; Vertex AI uses a request label that is returned with the original request in GCS output.
130
132
  Provider hooks also own response-text extraction so structured-output parsing can stay generic across provider payload shapes.
131
133
 
132
134
  ## Main user-facing flow
@@ -311,6 +313,7 @@ Owns provider-facing abstractions and implementations:
311
313
  - base provider contract
312
314
  - provider registry
313
315
  - OpenAI Batch implementation
316
+ - Anthropic Message Batches implementation
314
317
 
315
318
  The provider layer is responsible for:
316
319
 
@@ -350,8 +353,12 @@ Owns execution behavior:
350
353
 
351
354
  This is where the durable lifecycle lives. It bridges the domain models, providers, storage, and artifact store.
352
355
 
353
- The public facade is still `BatchRunner` plus `Run`, but the current internal layering under `runtime/` is intentionally split so execution concerns do not collapse back into one file:
356
+ The public facade is still `BatchRunner` plus `Run`. A deep internal
357
+ `RunExecutor` module owns execution attachment and the ordered advance cycle,
358
+ returning a structured outcome that reports durable progress.
359
+ The supporting implementation under `runtime/` remains split by concern:
354
360
 
361
+ - `execution.py`: claim recovery on execution attachment, source-availability checks, and ordered ingest/poll/cancel/submit advancement
355
362
  - `context.py`: persisted config building, resume config comparison, output-model resolution, and provider-backed `RunContext` creation
356
363
  - `ingestion.py`: checkpoint-aware item materialization, ingest checkpoint updates, and resume-aware ingestion flow
357
364
  - `submission.py`: pending-item claiming, request replay/build, token-budget gating, request artifact persistence, and batch submission
@@ -432,7 +439,7 @@ That split gives `batchor`:
432
439
  ## Current invariants
433
440
 
434
441
  1. Public execution is run-oriented: `start()`, `get_run()`, `run_and_wait()`.
435
- 2. OpenAI Batch and text-only Gemini Batch are built-in Python and CLI providers; OpenAI remains the CLI default.
442
+ 2. OpenAI Batch, Anthropic Message Batches, and text-only Gemini Batch are built-in Python and CLI providers; OpenAI remains the CLI default.
436
443
  3. SQLite is the default durable backend.
437
444
  4. Postgres is an opt-in durable backend for shared control-plane state.
438
445
  5. Structured outputs require a module-level Pydantic v2 model for rehydration.
@@ -450,7 +457,11 @@ That split gives `batchor`:
450
457
  17. Run lifecycle status and run control state are separate; pause/cancel do not redefine terminal lifecycle semantics.
451
458
  18. Incremental terminal-result reads are sequence-based and only return items that have already reached a terminal item state.
452
459
  19. Built-in deterministic-source resume currently covers CSV, JSONL, and Parquet; arbitrary iterables still do not become durable by magic.
453
- 20. `BatchItem.metadata["batchor_lineage"]` is reserved for lightweight source/join metadata when provided by built-in adapters or callers.
460
+ 20. An incomplete ingest checkpoint prevents terminal lifecycle status. A fresh
461
+ process must reattach the source with `start(job, run_id=...)` before execution
462
+ can advance, unless cancellation intentionally abandons the unmaterialized
463
+ source tail and finalizes the checkpoint.
464
+ 21. `BatchItem.metadata["batchor_lineage"]` is reserved for lightweight source/join metadata when provided by built-in adapters or callers.
454
465
 
455
466
  ## Extension seams
456
467
 
@@ -2,11 +2,11 @@
2
2
 
3
3
  This document describes the OpenAI-specific behavior inside `batchor`.
4
4
 
5
- OpenAI remains the default and most feature-complete provider path. Gemini has its own design note in [`GEMINI_BATCHING.md`](GEMINI_BATCHING.md), while this page focuses only on OpenAI Batch semantics.
5
+ OpenAI remains the default and most feature-complete provider path. Anthropic and Gemini have their own design notes in [`ANTHROPIC_BATCHING.md`](ANTHROPIC_BATCHING.md) and [`GEMINI_BATCHING.md`](GEMINI_BATCHING.md), while this page focuses only on OpenAI Batch semantics.
6
6
 
7
7
  ## Current behavior
8
8
 
9
- The Python API and CLI both support OpenAI. The CLI is OpenAI-only today.
9
+ The Python API and CLI both support OpenAI, which remains the CLI default.
10
10
 
11
11
  ## Request construction
12
12
 
@@ -58,6 +58,9 @@ That currently includes CSV, JSONL, Parquet, and `CompositeItemSource` for order
58
58
  When `CompositeItemSource` is used, child-source row IDs are auto-namespaced into run-unique `item_id` values, while the original row ID is preserved in lineage metadata.
59
59
  Custom non-file sources must implement a durable checkpoint contract explicitly; arbitrary iterables and live DB cursors are still `TBD`.
60
60
  Before resumed ingestion continues, active OpenAI batches are polled once. If that poll consumes terminal batches or records enqueue/backoff failures, those state changes are applied before any new prompt rendering, request replay, or submission happens.
61
+ The execution cycle reports durable progress explicitly to `Run.wait()`, so the
62
+ wait loop immediately drains productive poll/submission cycles and sleeps only
63
+ when a cycle makes no durable progress, respecting any persisted retry backoff.
61
64
 
62
65
  ## Raw output retention
63
66
 
@@ -4,17 +4,13 @@ This file tracks important work that should be explicit in the extracted reposit
4
4
 
5
5
  ## Next Practical Steps
6
6
 
7
- - add Postgres storage backend
8
- - extend resumable ingestion beyond the built-in CSV/JSONL sources
9
7
  - add automated retention windows on top of the explicit export/prune lifecycle
10
- - add more input adapters beyond CSV and JSONL
11
- - expose non-OpenAI providers through CLI workflows once provider-specific auth and flags are stable
12
8
  - add CLI structured-output workflows if the importability story can stay durable and predictable
13
9
 
14
10
  ## Longer-Term Ideas
15
11
 
16
- - additional provider coverage beyond OpenAI and text-only Gemini
17
- - artifact store abstraction
12
+ - additional provider coverage beyond OpenAI, Anthropic, and text-only Gemini
13
+ - remote/shared artifact store implementations beyond the local filesystem abstraction
18
14
  - partial-result streaming APIs
19
15
  - richer CLI or operator workflow beyond the current file-backed text-job surface
20
16
 
@@ -37,7 +37,7 @@ Important semantics:
37
37
 
38
38
  - `status` is cached from the last summary read or refresh
39
39
  - `refresh()` performs one poll-and-submit pass
40
- - `wait()` repeatedly refreshes until the run is terminal, and skips the poll-interval sleep after refreshes that complete items, fail items, or submit additional batches
40
+ - `wait()` repeatedly advances through the internal executor until the run is terminal, and skips the poll-interval sleep when the structured cycle outcome reports durable progress
41
41
  - `results()` and artifact lifecycle operations are terminal-only
42
42
  - terminal currently means either `completed` or `completed_with_failures`
43
43
  - `read_terminal_results()` and `export_terminal_results()` are incremental APIs for already-terminal items and are safe to call before the whole run finishes
@@ -177,11 +177,18 @@ Successful rehydration depends on:
177
177
  - credentials being available when a refresh needs to talk to the provider
178
178
 
179
179
  Fresh-process resume also requeues any `queued_local` items back to `pending` before submission resumes.
180
+ This recovery happens when an execution owner advances the run, not when a
181
+ caller merely reads a handle with `get_run()` or changes control state.
180
182
  When `start(job, run_id=...)` resumes a run with active provider batches, it first performs a poll-only reconciliation pass. Terminal provider batches are consumed, failed batches update retry backoff, and any active backoff prevents new source materialization or submission until the backoff expires.
181
183
 
182
184
  Resume compatibility intentionally ignores non-persisted secret fields such as provider API keys. Rehydrated OpenAI runs need `OPENAI_API_KEY` when no explicit in-memory config is supplied. Gemini Developer API runs need `GEMINI_API_KEY`; Vertex runs need Application Default Credentials plus the persisted or ambient project, location, and GCS prefix configuration.
183
185
 
184
186
  For deterministic-source resume, the caller must also reuse the same `run_id` and provide the same source identity/fingerprint.
187
+ An incomplete ingest checkpoint is part of terminal-state calculation. In the
188
+ same process, `Run.resume()` continues ingestion when the original job remains
189
+ attached. A rehydrated run without that source stays non-terminal and raises
190
+ `RunIngestionSourceRequiredError` from `refresh()`/`wait()`, directing the caller
191
+ to `start(job, run_id=...)`.
185
192
  For composite sources, that includes the same ordered child identities; changing the child order or swapping one file changes the logical source identity.
186
193
 
187
194
  Built-in deterministic sources currently include:
@@ -240,6 +247,12 @@ Semantics:
240
247
  - `resume` restarts those local activities from persisted state
241
248
  - `cancel` stops new ingestion/submission, keeps polling active provider batches, and then permanently fails remaining local non-terminal items with `error_class="run_cancelled"`
242
249
 
250
+ If checkpointed ingestion is incomplete when cancellation is requested, the
251
+ unmaterialized source tail is intentionally abandoned. After active batches
252
+ drain and remaining materialized items are cancelled, the stored ingest
253
+ checkpoint is finalized so the run can become terminal without reopening the
254
+ source.
255
+
243
256
  Manual pauses record `control_reason="manual"`. OpenAI upload/create/polling and batch-level insufficient-quota pauses record `control_reason="openai_insufficient_quota"`, clear batch-control-plane backoff, and preserve affected items for later retry without consuming attempts.
244
257
 
245
258
  Row-level insufficient-quota records inside completed batch outputs do not pause the run. Those items are stored as `failed_retryable` with `error_class="openai_insufficient_quota"`, do not consume attempts, and rely on retry backoff before they are submitted again.
@@ -19,6 +19,7 @@ This page explains what each document is for so readers do not have to guess whi
19
19
  | `design_docs/BOUNDARY_AND_PHILOSOPHY.md` | Ownership boundary between `batchor`, storage/artifacts, and user pipelines. |
20
20
  | `design_docs/ARCHITECTURE.md` | Canonical runtime diagrams, package structure, main flows, and extension seams. |
21
21
  | `design_docs/OPENAI_BATCHING.md` | OpenAI request construction, token budgeting, splitting, and batch polling behavior. |
22
+ | `design_docs/ANTHROPIC_BATCHING.md` | Anthropic Message Batches request construction, polling, result parsing, limits, and retention. |
22
23
  | `design_docs/GEMINI_BATCHING.md` | Gemini text-only request construction, batch polling, response parsing, and current limits. |
23
24
  | `design_docs/STORAGE_AND_RUNS.md` | Durable `Run` lifecycle, rehydration, checkpoints, control state, artifact retention, and operator semantics. |
24
25
  | `design_docs/STORAGE_MIGRATIONS.md` | SQLite schema-versioning and migration guidance. |
@@ -40,3 +41,4 @@ This page explains what each document is for so readers do not have to guess whi
40
41
  - Incremental terminal-result reads/exports are documented in the Python API and storage docs.
41
42
  - Raw output/error artifact retention is now configurable per run through `ArtifactPolicy`.
42
43
  - Gemini text-only Batch support is available through the Python API and default provider registry.
44
+ - Anthropic Message Batches support is available through the Python API, CLI, and default provider registry.
@@ -40,6 +40,13 @@ pip install "batchor[gemini]"
40
40
  echo "GEMINI_API_KEY=..." > .env
41
41
  ```
42
42
 
43
+ For Anthropic:
44
+
45
+ ```bash
46
+ pip install "batchor[anthropic]"
47
+ echo "ANTHROPIC_API_KEY=..." > .env
48
+ ```
49
+
43
50
  ## Start a run from JSONL
44
51
 
45
52
  ```bash
@@ -66,6 +73,20 @@ Use `--prompt-template` when the prompt should be derived from several fields.
66
73
 
67
74
  Exactly one of `--prompt-field` or `--prompt-template` is required.
68
75
 
76
+ ## Start an Anthropic run
77
+
78
+ ```bash
79
+ batchor start \
80
+ --input input/items.jsonl \
81
+ --id-field id \
82
+ --prompt-field text \
83
+ --provider anthropic \
84
+ --model claude-sonnet-4-5 \
85
+ --anthropic-max-tokens 1024
86
+ ```
87
+
88
+ Use `--anthropic-message-params` for an additional JSON object such as `'{"temperature":0.2}'`.
89
+
69
90
  ## Start a Gemini Developer API run
70
91
 
71
92
  ```bash
@@ -22,6 +22,12 @@ pip install "batchor[gemini]"
22
22
 
23
23
  Gemini support is text-only and is available through both the Python API and CLI.
24
24
 
25
+ Anthropic support uses the optional Anthropic SDK dependency:
26
+
27
+ ```bash
28
+ pip install "batchor[anthropic]"
29
+ ```
30
+
25
31
  ## What gets installed
26
32
 
27
33
  The package includes:
@@ -29,6 +35,7 @@ The package includes:
29
35
  - the Python library
30
36
  - the `batchor` CLI
31
37
  - the built-in OpenAI provider integration
38
+ - the built-in Anthropic provider integration when `batchor[anthropic]` is installed
32
39
  - the built-in Gemini provider integration when `batchor[gemini]` is installed
33
40
  - SQLite and Postgres storage implementations
34
41
 
@@ -63,11 +70,16 @@ For Gemini Developer API usage, authentication resolution is:
63
70
  1. `GeminiProviderConfig(api_key=...)`
64
71
  2. `GEMINI_API_KEY`
65
72
 
73
+ For Anthropic usage, authentication resolution is:
74
+
75
+ 1. `AnthropicProviderConfig(api_key=...)`
76
+ 2. `ANTHROPIC_API_KEY`
77
+
66
78
  Vertex AI uses Application Default Credentials and resolves project/location from explicit `GeminiProviderConfig` fields or `GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`. Vertex batches also require a writable `gs://` staging prefix.
67
79
 
68
80
  The Python library does not auto-load `.env`.
69
81
 
70
- The CLI loads a local `.env` as a convenience for operator usage. It resolves `OPENAI_API_KEY` for OpenAI, `GEMINI_API_KEY` for the Gemini Developer API, and the documented Google Cloud environment variables for Vertex AI. Rehydrated `status`, `wait`, and result operations load the same `.env` before reconstructing a provider.
82
+ The CLI loads a local `.env` as a convenience for operator usage. It resolves `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, and the documented Google Cloud environment variables for Vertex AI. Rehydrated `status`, `wait`, and result operations load the same `.env` before reconstructing a provider.
71
83
 
72
84
  ## Storage defaults
73
85
 
@@ -39,6 +39,31 @@ print(run.results()[0].output_text)
39
39
 
40
40
  Use `storage="memory"` only for tests or short-lived local experiments. For durable runs, use the default SQLite storage or an explicit backend.
41
41
 
42
+ ## Anthropic text job
43
+
44
+ Install `batchor[anthropic]`, then use the same runner lifecycle with an Anthropic provider config:
45
+
46
+ ```python
47
+ from batchor import AnthropicProviderConfig, BatchItem, BatchJob, BatchRunner, PromptParts
48
+
49
+
50
+ runner = BatchRunner(storage="memory")
51
+ run = runner.run_and_wait(
52
+ BatchJob(
53
+ items=[BatchItem(item_id="row1", payload="Summarize this text")],
54
+ build_prompt=lambda item: PromptParts(prompt=item.payload),
55
+ provider_config=AnthropicProviderConfig(
56
+ model="claude-sonnet-4-5",
57
+ max_tokens=1024,
58
+ ),
59
+ )
60
+ )
61
+
62
+ print(run.results()[0].output_text)
63
+ ```
64
+
65
+ If `api_key` is omitted, the provider resolves `ANTHROPIC_API_KEY`. Extra Messages API parameters such as `temperature` can be supplied through `message_params`; Batchor reserves the fields it constructs itself.
66
+
42
67
  ## Gemini text job
43
68
 
44
69
  Gemini Batch support is available through the Python API after installing `batchor[gemini]`.
@@ -131,6 +156,7 @@ Notes:
131
156
  - `output` is the parsed Pydantic object
132
157
  - `output_text` preserves the raw text that was parsed
133
158
  - with `GeminiProviderConfig`, the same `structured_output=` argument is sent through Gemini `generation_config.response_json_schema`
159
+ - with `AnthropicProviderConfig`, it is sent through Anthropic `output_config.format`
134
160
 
135
161
  ## Durable run lifecycle
136
162
 
@@ -56,7 +56,7 @@ If that is the mental model you were missing from the generated docs, start with
56
56
 
57
57
  ## Current surface
58
58
 
59
- - Built-in providers: OpenAI Batch, plus text-only Gemini Batch for Python API usage
59
+ - Built-in providers: OpenAI Batch, Anthropic Message Batches, and text-only Gemini Batch through Python and CLI workflows
60
60
  - Durable storage: SQLite by default, Postgres as an opt-in control-plane backend
61
61
  - Ephemeral storage: in-memory state store
62
62
  - Artifact backend: local filesystem via `LocalArtifactStore`
@@ -13,7 +13,7 @@ Before submitting changes:
13
13
  Please keep changes aligned with the documented package boundary:
14
14
 
15
15
  - durable batch execution
16
- - OpenAI Batch provider support
16
+ - OpenAI, Anthropic, and Gemini Batch provider support
17
17
  - SQLite-backed local durability by default
18
18
 
19
19
  Out-of-scope proposals are still useful, but should usually start as an issue discussing fit before implementation.
@@ -20,6 +20,7 @@ Most users only need a small subset of the package:
20
20
  - `BatchRunner`: start, resume, and run orchestration
21
21
  - `Run`: refresh, wait, inspect, export, and prune
22
22
  - `OpenAIProviderConfig`: built-in provider config
23
+ - `AnthropicProviderConfig`: built-in Anthropic Message Batches config
23
24
  - `GeminiProviderConfig`: built-in Gemini provider config for text batch jobs; the common fields are also exposed by the CLI
24
25
  - `SQLiteStorage` and `PostgresStorage`: durable control-plane backends
25
26
  - `CompositeItemSource`, `CsvItemSource`, `JsonlItemSource`, and `ParquetItemSource`: deterministic item streaming
@@ -73,6 +74,15 @@ This is the built-in Gemini Batch implementation. Most consumers only need `Gemi
73
74
  show_root_heading: true
74
75
  heading_level: 2
75
76
 
77
+ ## Anthropic provider
78
+
79
+ Install `batchor[anthropic]` for the SDK dependency. Most consumers only need `AnthropicProviderConfig`.
80
+
81
+ ::: batchor.providers.anthropic
82
+ options:
83
+ show_root_heading: true
84
+ heading_level: 2
85
+
76
86
  ## Sources
77
87
 
78
88
  These sources support durable resume through source fingerprints and checkpoints.