Patterns overview¶
ExecutionKit provides six async call patterns. Each takes a provider and
returns PatternResult.
| Pattern | Choose it when | Model-call shape |
|---|---|---|
| Consensus | Several independent calls can return a short answer from a constrained set, and exact-answer agreement is useful. | num_samples calls, concurrent up to max_concurrency. |
| Iterative refinement | You can score an answer and want bounded revisions. | One generation and one score per round with the default evaluator. |
| ReAct tool loop | The model needs registered tools before it can answer. | One model call per round; tool calls within a round run concurrently. |
| Structured output | You need a JSON object or array with an application validator. | One initial call plus up to max_retries repair calls. |
| Pipe | Each step can use the previous result as its next prompt. | Sum of the step costs. |
| Map-reduce | Independent inputs need the same operation before one combined result. | One call per input, then one reduce call. |
Retries can increase every model-call count in the table.
Decision guide¶
flowchart TD
A["What must the model do?"] --> B{"Call tools?"}
B -- "yes" --> C["react_loop"]
B -- "no" --> D{"Return validated JSON?"}
D -- "yes" --> E["structured"]
D -- "no" --> F{"Process many independent inputs?"}
F -- "yes" --> G["map_reduce"]
F -- "no" --> H{"Revise against a score?"}
H -- "yes" --> I["refine_loop"]
H -- "no" --> J{"Compare several constrained answers?"}
J -- "yes" --> K["consensus"]
J -- "no" --> L["Provider.complete"]
C --> M{"Feed result into another pattern?"}
E --> M
G --> M
I --> M
K --> M
M -- "yes, without branching" --> N["pipe"]
Use ordinary async Python when you need branching or when later work needs
several earlier outputs. pipe() intentionally passes only the string form of
the previous value.
Return contract¶
valueis the pattern output.scoreisNoneunless the pattern defines a score.costisTokenUsage(input_tokens, output_tokens, llm_calls).metadatais a read-only mapping with keys listed on the pattern page.
llm_calls counts dispatched attempts, including retries. Token counts come
from successful provider responses.
Shared controls¶
Most call patterns accept:
| Parameter | Meaning |
|---|---|
temperature |
Sampling temperature sent to the provider. The default differs by pattern. |
max_tokens |
Per-response output-token request limit. |
max_cost |
Token and call budget checked before dispatch. |
retry |
RetryConfig for retryable provider errors. |
trace |
Sync or async callback receiving TraceEvent. |
Some patterns also accept on_checkpoint callbacks. These callbacks expose
progress state but do not persist it; storage belongs to the caller.
Read Execution controls before relying on budgets. Call-count limits are strict within one asyncio event loop, while a completed response can take a recorded token total beyond its pre-dispatch limit.
Synchronous wrappers¶
Each pattern has a package-root wrapper:
from executionkit import (
consensus_sync,
map_reduce_sync,
pipe_sync,
react_loop_sync,
refine_loop_sync,
structured_sync,
)
The wrappers call asyncio.run(). Use the async functions inside notebooks,
async web handlers, or any other active event loop.
Exceptions¶
Provider failures derive from LLMError. Pattern failures derive from
PatternError. Both derive from ExecutionKitError and carry partial cost
and metadata.
See Execution helper API.