Core API Reference
ParallelBatchProcessor
async_batch_llm.ParallelBatchProcessor
ParallelBatchProcessor(max_workers: int | None = None, post_processor: PostProcessorFunc[TOutput, TContext] | None = None, timeout_per_item: float | None = None, rate_limit_cooldown: float | None = None, config: ProcessorConfig | None = None, error_classifier: ErrorClassifier | None = None, rate_limit_strategy: RateLimitStrategy | None = None, middlewares: list[Middleware[TInput, TOutput, TContext]] | None = None, observers: list[ProcessorObserver] | None = None, progress_callback: ProgressCallbackFunc | None = None, artifact_store: ArtifactStore | None = None, resume: ResumePolicy = ResumePolicy.NONE)
Bases: BatchProcessor[TInput, TOutput, TContext], Generic[TInput, TOutput, TContext]
Batch processor that executes items in parallel as individual agent calls.
This refactored version uses: - Pluggable error classification (provider-agnostic) - Pluggable rate limit strategies - Middleware pipeline for extensibility - Observer pattern for monitoring - Configuration objects for easier setup
Initialize the parallel batch processor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_workers
|
int | None
|
Maximum concurrent workers (deprecated, use config) |
None
|
post_processor
|
PostProcessorFunc[TOutput, TContext] | None
|
Optional async function called after each successful item |
None
|
timeout_per_item
|
float | None
|
Timeout per item in seconds (deprecated, use config) |
None
|
rate_limit_cooldown
|
float | None
|
Cooldown duration (deprecated, use config) |
None
|
config
|
ProcessorConfig | None
|
Processor configuration object (recommended) |
None
|
error_classifier
|
ErrorClassifier | None
|
Optional global classifier override. When omitted, each strategy's recommendation is resolved independently. |
None
|
rate_limit_strategy
|
RateLimitStrategy | None
|
Strategy for handling rate limits |
None
|
middlewares
|
list[Middleware[TInput, TOutput, TContext]] | None
|
List of middleware to apply |
None
|
observers
|
list[ProcessorObserver] | None
|
List of observers for events |
None
|
progress_callback
|
ProgressCallbackFunc | None
|
Optional callback(completed, total, current_item_id) for progress updates |
None
|
Source code in src/async_batch_llm/parallel.py
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | |
__aexit__
async
__aexit__(exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None) -> bool
Context manager exit - ensures cleanup of strategies and resources.
Calls cleanup() on all prepared strategies, then delegates to parent cleanup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exc_type
|
type[BaseException] | None
|
Exception type (if any exception occurred) |
required |
exc_val
|
BaseException | None
|
Exception value (if any exception occurred) |
required |
exc_tb
|
TracebackType | None
|
Exception traceback (if any exception occurred) |
required |
Returns:
| Type | Description |
|---|---|
bool
|
False to indicate exceptions should not be suppressed |
Source code in src/async_batch_llm/parallel.py
add_work
async
Queue a work item and register its identity-scoped admission state.
Source code in src/async_batch_llm/parallel.py
cleanup
async
Cancel workers, timers, and every quota-scoped admission resource.
Source code in src/async_batch_llm/parallel.py
get_stats
async
Get processor statistics (thread-safe).
Returns:
| Type | Description |
|---|---|
dict
|
Dictionary containing processing statistics including: |
dict
|
|
dict
|
|
dict
|
|
dict
|
|
dict
|
|
dict
|
|
dict
|
|
Source code in src/async_batch_llm/parallel.py
shutdown
async
Clean up resources: flush observers and cancel pending tasks.
Source code in src/async_batch_llm/parallel.py
start
wait_for_abort
async
Wait until a configured batch deadline or fail-fast abort trips.
LLMWorkItem
async_batch_llm.LLMWorkItem
dataclass
LLMWorkItem(item_id: str, strategy: LLMCallStrategy[TOutput], prompt: str = '', context: TContext | None = None, submission_index: int | None = None, _artifact_key: Any = None)
Bases: Generic[TInput, TOutput, TContext]
Represents a single work item to be processed by an LLM strategy.
Attributes:
| Name | Type | Description |
|---|---|---|
item_id |
str
|
Unique identifier for this work item |
strategy |
LLMCallStrategy[TOutput]
|
LLM call strategy that encapsulates how to make the LLM call |
prompt |
str
|
The prompt/input to pass to the LLM |
context |
TContext | None
|
Optional context data passed through to results/post-processor |
__post_init__
Validate work item fields.
Source code in src/async_batch_llm/base.py
WorkItemResult
async_batch_llm.WorkItemResult
dataclass
WorkItemResult(item_id: str, success: bool, output: TOutput | None = None, error: str | None = None, context: TContext | None = None, token_usage: TokenUsage = (lambda: {'input_tokens': 0, 'output_tokens': 0, 'total_tokens': 0})(), metadata: dict[str, Any] | None = None, gemini_safety_ratings: dict[str, str] | None = None, exception: Exception | None = None, admission_wait_seconds: float = 0.0, timing: WorkItemTiming = WorkItemTiming(), submission_index: int | None = None, error_category: str | None = None, replayed_from_artifact: bool = False)
Bases: ProviderOutputViews, Generic[TOutput, TContext]
Result of processing a single work item.
Attributes:
| Name | Type | Description |
|---|---|---|
item_id |
str
|
ID of the work item |
success |
bool
|
Whether processing succeeded |
output |
TOutput | None
|
Agent output if successful, None if failed |
error |
str | None
|
Error message if failed, None if successful |
context |
TContext | None
|
Context data from the work item |
token_usage |
TokenUsage
|
Token usage stats (input_tokens, output_tokens, total_tokens) |
metadata |
dict[str, Any] | None
|
Provider-specific metadata returned alongside the response —
e.g. |
gemini_safety_ratings |
dict[str, str] | None
|
Deprecated. Use |
exception |
Exception | None
|
The originating exception for a failed result, when one was
raised (all retries exhausted, or a permanent non-retryable error).
|
admission_wait_seconds |
float
|
Total time this item spent waiting for provider capacity across all attempts. This wait occurs before the per-attempt execution timeout starts. |
timing |
WorkItemTiming
|
Structured end-to-end and per-attempt timing details. |
quota_wait_seconds
property
Combined RPM/TPM wait, separate from provider-capacity admission.
__post_init__
Backfill gemini_safety_ratings from metadata['safety_ratings']
for backward compatibility. Once gemini_safety_ratings is removed,
this method goes away. (Reads/writes go through __dict__ directly
so the framework itself never triggers the deprecation warning.)
Source code in src/async_batch_llm/base.py
from_dict
classmethod
from_dict(data: Mapping[str, Any], *, output_decoder: ValueDecoder | None = None, context_decoder: ValueDecoder | None = None) -> WorkItemResult[Any, Any]
Restore a result from :meth:to_dict output.
Without decoders, custom values (including Pydantic models and dataclasses) are restored as JSON-native mappings/lists.
Source code in src/async_batch_llm/base.py
to_dict
Return a versioned, JSON-safe representation of this result.
encoder may convert application-specific output/context values to
supported JSON-safe values. Unsupported values raise
:class:~async_batch_llm.ResultSerializationError.
Source code in src/async_batch_llm/base.py
AttemptTiming
async_batch_llm.AttemptTiming
dataclass
AttemptTiming(attempt: int, try_number: int, total_seconds: float = 0.0, admission_wait_seconds: float = 0.0, startup_ramp_wait_seconds: float = 0.0, execution_seconds: float = 0.0, provider_seconds: float | None = None, cooldown_wait_seconds: float = 0.0, retry_backoff_seconds: float = 0.0, success: bool = False, error_type: str | None = None, error_category: str | None = None, timeout_category: str | None = None, quota_wait_seconds: float = 0.0, estimated_input_tokens: int | None = None, estimated_output_tokens: int | None = None, reserved_tokens: int = 0, reported_tokens: int | None = None, reconciliation_delta_tokens: int | None = None, quota_scope_id: int | None = None)
Timing and outcome details for one physical strategy execution try.
WorkItemTiming
async_batch_llm.WorkItemTiming
dataclass
ProcessorConfig
async_batch_llm.ProcessorConfig
dataclass
ProcessorConfig(max_workers: int | None = None, timeout_per_item: float | None = None, post_processor_timeout: float = 90.0, concurrent_post_processing: bool = False, retry: RetryConfig = RetryConfig(), rate_limit: RateLimitConfig = RateLimitConfig(), max_requests_per_minute: float | None = None, progress_interval: int = 10, progress_callback_timeout: float | None = 5.0, enable_detailed_logging: bool = False, max_queue_size: int = 0, dry_run: bool = False, max_provider_concurrency: int | None = None, startup_ramp: StartupRampConfig | None = None, guardrails: GuardrailConfig = GuardrailConfig(), attempt_timeout: float | None = None, concurrency: int | None = None, max_result_queue_size: int = 0, progress_refresh_interval_seconds: float = 0.1, max_tokens_per_minute: int | None = None, token_estimator: TokenEstimator | None = None)
Complete configuration for batch processor.
__post_init__
Resolve the deprecated timeout alias, then validate.
Source code in src/async_batch_llm/core/config.py
validate
Validate complete configuration.
Source code in src/async_batch_llm/core/config.py
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 | |
GuardrailConfig
async_batch_llm.GuardrailConfig
dataclass
GuardrailConfig(total_timeout_per_item: float | None = None, batch_timeout: float | None = None, abort_on_error_categories: frozenset[str] = frozenset(), abort_mode: AbortMode = AbortMode.DRAIN_ACTIVE)
Optional end-to-end deadlines and terminal-category fail-fast policy.
AbortMode
async_batch_llm.AbortMode
Bases: str, Enum
How a controlled batch abort treats provider calls already running.
StartupRampConfig
async_batch_llm.StartupRampConfig
dataclass
StartupRampConfig(initial_concurrency: int = 1, concurrency_step: int = 1, ramp_interval_seconds: float = 1.0, max_concurrency: int | None = None, jitter_seconds: float = 0.0)
Optional concurrency ramp applied when an execution host starts.
BatchResult
async_batch_llm.BatchResult
dataclass
BatchResult(results: list[WorkItemResult[TOutput, TContext]], termination: BatchTermination = BatchTermination(), wall_time_seconds: float | None = None)
Bases: Generic[TOutput, TContext]
Result of processing a batch of work items.
Attributes:
| Name | Type | Description |
|---|---|---|
results |
list[WorkItemResult[TOutput, TContext]]
|
Individual work item results, in completion order — the
order items finished, which (with parallel workers, retries, and
rate-limit cooldowns) is generally NOT the order they were added.
Use :meth: |
total_items |
int
|
Total number of items in the batch |
succeeded |
int
|
Number of successful items |
failed |
int
|
Number of failed items |
total_input_tokens |
int
|
Sum of input tokens across all items |
total_output_tokens |
int
|
Sum of output tokens across all items |
total_cached_tokens |
int
|
Sum of cached input tokens across all items (v0.2.0) |
cache_hit_rate
property
Percentage (0.0–100.0) of input tokens served from cache.
A property since v0.20.0 (issue #93), consistent with the sibling
zero-arg scalars (total_cached_tokens, succeeded, ...).
The v0.18 method spelling batch.cache_hit_rate() still works
via a transitional callable-float return value and emits a
DeprecationWarning; drop the parentheses.
failures
property
The failed results only, in completion order.
successes
property
The successful results only, in completion order.
__post_init__
Calculate summary statistics from results.
Source code in src/async_batch_llm/base.py
by_id
Map item_id -> result for direct lookup.
Results are ordered by completion, so use this when you need to align
outputs back to specific inputs. If two results somehow share an
item_id, the later-completed one wins.
Source code in src/async_batch_llm/base.py
effective_input_tokens
Estimate billable input tokens after the cache discount.
cached_token_rate is the fraction of the normal input-token price
you pay for tokens served from cache. For example, Gemini charges
10% of the normal price (rate = 0.10), so 1000 cached tokens cost
the same as 100 uncached tokens.
Use the named constants on :class:CachedTokenRates to avoid
hardcoding magic numbers:
.. code-block:: python
result.effective_input_tokens(CachedTokenRates.OPENAI)
result.effective_input_tokens(CachedTokenRates.GEMINI)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cached_token_rate
|
float | None
|
Fraction (0.0–1.0) of the normal input price
paid for cached tokens. When omitted ( |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Effective input tokens billed. The discount is computed by |
int
|
truncating |
int
|
|
int
|
rounded up when the discount would have a fractional |
int
|
part — a deliberately conservative choice for cost reporting |
int
|
(your real bill is at most this number, never more). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/async_batch_llm/base.py
estimated_cost
estimated_cost(input_per_mtok: float, output_per_mtok: float, cached_token_rate: float | None = None) -> float
Estimate total spend from per-million-token prices.
Applies the cache discount to input tokens via
:meth:effective_input_tokens, so cached tokens are billed at their
reduced rate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_per_mtok
|
float
|
Price per 1,000,000 input tokens (in your currency). |
required |
output_per_mtok
|
float
|
Price per 1,000,000 output tokens. |
required |
cached_token_rate
|
float | None
|
Fraction of the normal input price paid for
cached tokens (see :class: |
None
|
Returns:
| Type | Description |
|---|---|
float
|
Estimated total cost: ``effective_input / 1e6 * input_per_mtok + |
float
|
output / 1e6 * output_per_mtok``. |
Source code in src/async_batch_llm/base.py
from_dict
classmethod
from_dict(data: Mapping[str, Any], *, output_decoder: ValueDecoder | None = None, context_decoder: ValueDecoder | None = None) -> BatchResult[Any, Any]
Restore a batch from :meth:to_dict output.
Source code in src/async_batch_llm/base.py
from_json
classmethod
from_json(value: str | bytes, *, output_decoder: ValueDecoder | None = None, context_decoder: ValueDecoder | None = None) -> BatchResult[Any, Any]
Restore a batch from a JSON string or UTF-8 bytes.
Source code in src/async_batch_llm/base.py
from_jsonl
classmethod
from_jsonl(path: str | Path, *, output_decoder: ValueDecoder | None = None, context_decoder: ValueDecoder | None = None) -> BatchResult[Any, Any]
Restore a batch from :meth:to_jsonl output.
Source code in src/async_batch_llm/base.py
in_input_order
Return a new batch whose results are sorted by submission order.
The current batch and its result list are not mutated. Ordering is
never inferred from item_id because IDs may be duplicated.
Source code in src/async_batch_llm/base.py
outputs
Iterate over the outputs of successful results, in result order.
The happy-path accessor — no if item.success loop needed:
.. code-block:: python
for output in batch.outputs():
print(output)
for item_id, output in batch.outputs(with_ids=True):
print(item_id, output)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
with_ids
|
bool
|
When True, yield |
False
|
Added in v0.20.0. Failed results are skipped; iterate .failures
(or check batch.failed) to handle them.
Source code in src/async_batch_llm/base.py
summary
Return a printable plain-text report of the whole run.
print(batch.summary()) is a complete post-run report: item
counts, termination, retry totals, token totals (with replayed work
accounted separately, consistent with v0.18 replay accounting),
admission/execution percentiles, wall time, and failures grouped by
error category. Works identically on collected batches and on
batches restored via from_dict/from_json/from_jsonl.
Added in v0.20.0.
Source code in src/async_batch_llm/base.py
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 | |
to_dict
Return a versioned, JSON-safe representation of the batch.
Source code in src/async_batch_llm/base.py
to_json
Serialize this batch to a JSON string.
Source code in src/async_batch_llm/base.py
to_jsonl
Write one versioned result record per UTF-8 JSONL line.
Source code in src/async_batch_llm/base.py
BatchTermination
async_batch_llm.BatchTermination
dataclass
BatchTermination(kind: Literal['completed', 'batch_timeout', 'fail_fast', 'artifact_error'] = 'completed', reason: str | None = None, error_category: str | None = None, triggering_item_id: str | None = None)
Serializable reason a batch stopped accepting or executing work.
Grounding
async_batch_llm.Grounding
dataclass
Grounding(sources: list[GroundingSource] = list(), queries: list[str] = list(), supports: list[dict[str, Any]] = list())
Web-grounding data from a grounded call (e.g. Gemini google_search).
Attributes:
| Name | Type | Description |
|---|---|---|
sources |
list[GroundingSource]
|
The web sources the answer was grounded in. |
queries |
list[str]
|
Search queries the model issued ( |
supports |
list[dict[str, Any]]
|
Answer-span → source-index links, as plain dicts
( |
from_metadata
classmethod
Parse a metadata['grounding'] dict; lenient, never raises.
Source code in src/async_batch_llm/provider_output.py
GroundingSource
async_batch_llm.GroundingSource
dataclass
One web source backing a grounded response.
Attributes:
| Name | Type | Description |
|---|---|---|
uri |
str
|
Source URL (always present; entries without one are dropped). |
title |
str | None
|
Human-readable page title, when the provider supplied one. |
snippet |
str | None
|
Excerpt from the source, when the provider supplied one. |
from_metadata
classmethod
Parse one metadata['grounding']['sources'] entry; lenient, never raises.
Source code in src/async_batch_llm/provider_output.py
ToolCall
async_batch_llm.ToolCall
dataclass
One tool/function call the model requested. Visibility only — the framework never executes tools; feed these to your own dispatch loop.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str | None
|
Provider call id, when supplied. |
name |
str
|
Tool/function name (always present; entries without one are dropped). |
arguments |
str
|
The raw JSON-string arguments, deliberately unparsed —
parse with |
from_metadata
classmethod
Parse one metadata['tool_calls'] entry; lenient, never raises.