Changelog¶
All notable changes to ExecutionKit are documented here. Format follows Keep a Changelog. Versioning follows Semantic Versioning.
[Unreleased]¶
[0.3.0] - 2026-07-08¶
Added¶
- Add multi-turn conversation primitives.
react_loopnow acceptsmessages=(a prior conversation to continue, mutually exclusive withprompt) and returns the full updated transcript asmetadata["messages"], so callers can thread state across turns - Add
Kit.turn(user_text, tools=...)plus aKit.messagestranscript (and an optionalmessages=seed onKit), giving a stateful conversational API on top ofreact_loop - Add message-construction helpers
system_message,tool_message, andassistant_tool_calls_messagetoexecutionkit.engine.messages - Add
examples/conversational_assistant.pydemonstrating multi-turn tool use with context carryover - Add a multi-turn eval harness —
ConversationScript,Turn, andrun_conversation_script(script, kit)— that drives a scripted conversation through a singleKit(state carries across turns) and returns anEvalReport, one result per turn - Add optional rate limiting to
Kitvia arate_limiter: TokenBucket | Noneparameter; a token is acquired before every pattern dispatch - Add an optional
summarizer=hook toreact_loopthat compresses history dropped bymax_history_messagestrimming into a system note for the active window (the stored transcript is unchanged); asummarizedcount is reported in metadata react_loopcheckpoint state now includes the runningmessagestranscript, enabling conversation-level resume- Add a "Building a conversational assistant" recipe (
docs/recipes/assistant.md) covering stateful turns,structured()intent/slot NLU, the streaming limitation, andConversationScriptevals - Add the
map_reduce()pattern — parallel fan-out over a collection of inputs, each processed independently, then reduced to a single answer (ADR-011) - Add a stdlib-only MCP server —
python -m executionkit.mcpspeaks newline-delimited JSON-RPC 2.0 over stdio and exposesconsensusand a demo-toolset-restrictedreact_loopas MCP tools (ADR-012) - Add Anthropic Message Batches fan-out —
consensus_batch()andmap_batch()submit samples as a single batch job over a stdliburllibclient and score with the sametally_votesas the liveconsensus()pattern (ADR-014)
Changed¶
react_loop()no longer silently swallows unknown keyword arguments (the**_sink was removed); an unsupported kwarg now raisesTypeError.promptis now optional (defaults toNone) andtoolsdefaults to()(behavior change)
[0.2.0] - 2026-06-08¶
Added¶
- Add lightweight orchestration primitives:
Router/RouteRulefor provider selection before a pattern call,Workflow/Stepfor dependency-ordered async fan-out, andPlan/PlanStepfor ordered plan-then-act execution - Add approval gates —
ApprovalGate,ApprovalRequest,ApprovalDecision, andApprovalDeniedError— that require human or policy approval before tool execution, workflow steps, or plan steps; wired intoreact_loop(a denial becomes a tool observation) and intoWorkflow/Plan(a denial aborts) - Add observability hooks —
TraceEvent,TraceCallback, andemit_trace— emitting structured sync-or-async events for LLM call start/end/error, tool calls, workflow steps, plan steps, and approvals; add atrace=parameter toconsensus,refine_loop,react_loop, andstructured - Add an eval harness —
EvalCase,EvalResult,EvalReport, andrun_eval_suite()for deterministic golden checks, pluslive_provider_from_env()for opt-in live evals gated onEXECUTIONKIT_LIVE_EVAL;EvalReportreportsaccuracyandsummary() - Add an output-correctness eval suite: deterministic per-pattern golden datasets and a curated model-failure corpus that run offline in CI under a dedicated "Eval suite" gate, plus opt-in judge-calibration and per-pattern live-provider regression tiers and a scheduled/manual
Live Evalworkflow that runs them against a local Ollama model - Add an
approval_gate=parameter toreact_loop,Workflow.run, andPlan.execute
Changed¶
- Budget accounting now counts every dispatched wire attempt — including failed retries — toward
llm_calls, and the deadrelease_call()slot-release path was removed; amax_costllm_callsceiling now caps total attempts, not just successes (behavior change) Router.run(pattern, prompt, *, context=..., **kwargs)takes routing inputs through an explicitcontextmapping disjoint from the pattern's keyword arguments, so a routing key (e.g.tier) can no longer leak into the pattern call and raiseTypeError- Broaden credential redaction to match common keyless token shapes (
ghp_/gho_,AIza,xox[bpoa]-,gsk_, andkey=/token:/bearer …variants) and apply it to transport-failure messages and malformed tool-argument echoes as well as HTTP error bodies
Security¶
- Harden the
refine_loopdefault judge: embedded</response_to_rate>envelope tags are stripped from candidate text so adversarial content cannot break out of the scoring sandbox - Bounds-check provider-reported token usage (
_usage_int): reject booleans, negatives, and absurdly large counts asProviderErrorso a hostile or buggy endpoint cannot under-count and bypassmax_cost - Add
ApprovalGateas an opt-in control for human/policy review before tool, workflow, or plan side effects
Fixed¶
- Map urllib read-phase
TimeoutErrorto a retryableProviderErroron the default (no-httpx) transport path, matching thehttpxbackend Kit.usagenow records the partial cost carried by a raisedExecutionKitError(e.g.BudgetExhaustedError,MaxIterationsError) instead of dropping it when a pattern aborts- Harden
Router.runagainst apromptkey in the routing context colliding with the positionalpromptargument toselect() - Strengthen ReAct history-trimming tests (remove
asyncio.coroutine, unavailable since Python 3.11) and assert onrounds/tool_calls_made/truncated_observations/messages_trimmedmetadata
[0.1.0] - 2026-05-22¶
Security¶
- Fix prompt injection in
refine_loopdefault evaluator via XML delimiter sandboxing and input truncation to 32 768 chars - Mask API key in
Provider.__repr__— previously leakedsk-...values in logs and tracebacks - Redact credential-pattern substrings from HTTP error messages using
_redact_sensitiveregex - Return only exception type name (not message) from tool error handler in
react_loopto prevent leaking internal details to the LLM - Add Bandit SAST job to CI and Dependabot weekly auto-update configuration for pip and GitHub Actions
Added¶
- Add the
structured()pattern andstructured_sync()wrapper for JSON extraction, optional validation, and repair retries - Add optional
httpxbackend for HTTP connection pooling — install withpip install executionkit[httpx]; falls back tourllibwhenhttpxis absent - Add
max_history_messages: int | Noneparameter toreact_loopfor capping message history size; always preserves the original user prompt - Add
_validate_tool_argshelper inreact_loopthat validates tool call arguments against JSON Schema (required fields,additionalProperties, and type checks) before execution — uses stdlib only, nojsonschemadependency - Add
aclose()and async context manager support (__aenter__/__aexit__) toProviderfor explicit HTTP client lifecycle management - Add
messages_trimmedcounter toreact_loopmetadata - Add MkDocs Material documentation site with public guides for installation, provider setup, patterns, recipes, API reference, contributing, license, and changelog
- Add architecture decision records for structural protocols, flat package layout, and single OpenAI-compatible provider design
- Add GitHub Pages documentation deployment workflow and CodeQL analysis workflow
- Add supply-chain hardening with
requirements.lockand SBOM artifact generation in the publish workflow
Fixed¶
- Fix
consensusvoting incorrectly splitting semantically identical responses that differ only in trailing newlines or internal whitespace — votes now use normalized text while the original winning response is preserved - Fix
_parse_scoresilently accepting scores outside the 0–10 range; now raisesValueErrorfor out-of-range values - Remove phantom
pydantic>=2.0fromproject.dependencies; pydantic was never imported in the library source - Fix strict MkDocs builds by excluding internal documents with stale cross-references from the public site
Changed¶
- Change
PatternResult.metadatatype fromdict[str, Any]toMappingProxyType[str, Any]to enforce true immutability on a frozen dataclass - Update GitHub Actions workflow dependencies to current major versions
- Replace the old Astro documentation site with the MkDocs Material site