All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Middleware priority —
Middlewarebase class now acceptspriority: int(0-1000, default 0). Higher priority executes first; equal priority preserves registration order.BeforeMiddlewareandAfterMiddlewareadapters also acceptpriority. - Priority range validation —
ValueErrorraised for priority values outside 0-1000
- Middleware default priority changed from
0to100per PROTOCOL_SPEC §11.2. Middleware without explicit priority will now execute before priority-0 middleware.
- Rebrand: aipartnerup → aiperceivable
- Dict schema support — Modules can now define
input_schema/output_schemaas plain JSON Schema dicts instead of Pydantic model classes. A_DictSchemaAdaptertransparently wraps dict schemas at registration time so all internal code paths (executor, schema exporter,get_definition) work without changes.
get_definition()crash on dict schemas — Previously called.model_json_schema()on dict objects, causingAttributeError- Executor crash on dict schemas —
call(),call_async(), andstream()all called.model_validate()on dict objects
- File header docstrings — Enhanced docstrings for
errors.py,executor.py, andversion.py
0.13.0 - 2026-03-12
- Caching/pagination annotations —
ModuleAnnotationsgains 5 new fields:cacheable,cache_ttl,cache_key_fields,paginated,pagination_style(all optional with defaults, backward compatible) pagination_styleLiteral type — Typed asLiteral["cursor", "offset", "page"]instead of free-formstrsunset_date— New field onModuleDescriptorfor module deprecation lifecycle (ISO 8601 date)on_suspend()/on_resume()lifecycle hooks — Duck-typed optional hooks for state preservation during hot-reload; integrated intoReloadModuleModuleand registry watchdog- MCP
_metaexport — Schema exporter includescacheable,cacheTtl,cacheKeyFields,paginated,paginationStylein_metasub-dict - Suspend/resume tests —
tests/test_suspend_resume.pycovering state transfer, backward compatibility, error handling
- Rebranded — "module development framework" → "module standard" in pyproject.toml,
__init__.py, README, and internal docstrings ModuleProtocol —on_suspend/on_resumedeliberately kept OUT of Protocol (duck-typed viahasattr/callable)
0.12.0 - 2026-03-10
ExecutionCancelledErrornow extendsModuleError(was bareException) with error codeEXECUTION_CANCELLED, aligning with PROTOCOL_SPEC §8.7 error hierarchyErrorCodes— AddedEXECUTION_CANCELLEDconstant
0.11.0 - 2026-03-08
- Full lifecycle integration tests (
tests/integration/test_full_lifecycle.py) — 8 tests covering the complete 11-step pipeline with all gates (ACL + Approval + Middleware + Schema validation) enabled simultaneously, nested module calls, sharedcontext.data, error propagation, and ACL conditions.
Built-in system.* modules that allow AI agents to query, monitor
system.health.summary— Aggregate health status across all registered modules (healthy/degraded/unhealthy classification based on error rate thresholds).system.health.module— Per-module health detail including recent errors fromErrorHistory.system.manifest.module— Single module introspection (schema, annotations, tags, source path).system.manifest.full— Full registry manifest with filtering by tags/prefix.system.usage.summary— Usage statistics across all modules (call counts, error rates, avg latency).system.usage.module— Per-module usage detail with hourly trend data.system.control.update_config— Runtime config hot-patching with constraint validation.system.control.reload_module— Hot-reload a module from disk without restart.system.control.toggle_feature— Enable/disable modules at runtime with reason tracking.register_sys_modules()— Auto-registration wiring for all system modules.
ErrorHistory— Ring buffer tracking recent errors with deduplication and per-module querying.ErrorHistoryMiddleware— Middleware that recordsModuleErrordetails intoErrorHistory.UsageCollector— Per-module call counting, latency histograms, and hourly bucketed trend data.PlatformNotifyMiddleware— Threshold-based sensor that emits events on error rate spikes.
EventEmitter— Global event bus with async subscriber dispatch and thread-pool execution.EventSubscriberprotocol — Interface for event consumers.ApCoreEvent— Frozen dataclass for typed events (module lifecycle, errors, config changes).WebhookSubscriber— HTTP POST event delivery with retry.A2ASubscriber— Agent-to-Agent protocol event bridge.
APCore.on()/APCore.off()— Event subscription management via the unified client.APCore.disable()/APCore.enable()— Module toggle control via the unified client.APCore.discover()/APCore.list_modules()— Discovery and listing via the unified client.
ModuleDisabledError— Error class forMODULE_DISABLEDcode, raised when a disabled module is called.ReloadFailedError— Error class forRELOAD_FAILEDcode (retryable).SchemaStrategy— Enum for schema resolution strategy (yaml_first,native_first,yaml_only).ExportProfile— Enum for schema export profiles (mcp,openai,anthropic,generic).
- Module toggle — APCore client now supports
disable()/enable()for module toggling viasystem.control.toggle_feature, withModuleDisabledErrorenforcement and event emission. - Version negotiation —
negotiate_version()for SDK/module version compatibility checking.
WebhookSubscriber/A2ASubscribernow require optional dependencyaiohttp. Install withpip install apcore[events]. Core SDK no longer fails to import whenaiohttpis not installed.
aiohttphard import inevents/subscribers.pybroke core SDK import whenaiohttpwas not installed. Changed totry/except ImportErrorguard with clear error message at runtime.A2ASubscriber.on_eventImportErrorfor missingaiohttpwas silently swallowed by the broadexcept Exceptionblock. Moved guard before thetryblock to surface the error correctly.- README Access Control example now includes required
ExecutorandRegistryimports. pyproject.tomlrepository/issues/changelog URLs now point toapcore-python(was incorrectly pointing toapcore).- CHANGELOG
[0.7.1]compare link added (was missing from link references).
0.10.0 - 2026-03-07
APCore.stream()— Stream module output chunk by chunk via the unified client.APCore.validate()— Non-destructive preflight check via the unified client.APCore.describe()— Get module description info (for AI/LLM use).APCore.use_before()— Add before function middleware via the unified client.APCore.use_after()— Add after function middleware via the unified client.APCore.remove()— Remove middleware by identity via the unified client.
apcore.stream()— Global convenience for streaming module calls.apcore.validate()— Global convenience for preflight validation.apcore.register()— Global convenience for direct module registration.apcore.describe()— Global convenience for module description.apcore.use()— Global convenience for adding middleware.apcore.use_before()— Global convenience for adding before middleware.apcore.use_after()— Global convenience for adding after middleware.apcore.remove()— Global convenience for removing middleware.
FeatureNotImplementedError— New error class forGENERAL_NOT_IMPLEMENTEDcode (renamed fromNotImplementedErrorto avoid Python stdlib clash).DependencyNotFoundError— New error class forDEPENDENCY_NOT_FOUNDcode.
- APCore client and
apcore.*global functions now provide full feature parity withExecutor.
0.9.0 - 2026-03-06
PreflightCheckResult— New frozen dataclass representing a single preflight check result withcheck,passed, anderrorfields.PreflightResult— New dataclass returned byExecutor.validate(), containing per-check results andrequires_approvalflag. Duck-type compatible withValidationResultvia.validand.errorsproperties.- Full 6-check preflight —
validate()now runs Steps 1–6 of the pipeline (module_id format, module lookup, call chain safety, ACL, approval detection, schema validation) without executing module code or middleware.
- Step renumbering — Approval Gate renumbered from Step 4.5 to Step 5; all subsequent steps shifted +1 (now 11 clean steps).
validate()return type — Changed fromValidationResulttoPreflightResult. Backward compatible:.validand.errorsstill work identically for existing consumers (e.g., apcore-mcp router).validate()signature — Added optionalcontextparameter for call-chain checks;inputsnow defaults to{}.
- Exported
PreflightCheckResultandPreflightResultfromapcoretop-level package.
0.8.0 - 2026-03-05
- Dual-timeout model — Global deadline enforcement (
executor.global_timeout) alongside per-module timeout. The shorter of the two is applied, preventing nested call chains from exceeding the global budget. - Cooperative cancellation — On module timeout, the executor sends
CancelToken.cancel()and waits a 5-second grace period before raisingModuleTimeoutError. Modules that checkcancel_tokencan clean up gracefully. - Error propagation (Algorithm A11) — All execution paths (sync, async, stream) now wrap exceptions via
propagate_error(), ensuring middleware always receivesModuleErrorinstances with trace context. - Deep merge for streaming — Streaming chunk accumulation uses recursive deep merge (depth-capped at 32) instead of shallow merge, correctly handling nested response structures.
- ErrorCodeRegistry — Custom module error codes are validated against framework prefixes and other modules to prevent collisions. Raises
ErrorCodeCollisionErroron conflict. - VersionIncompatibleError — New error class for SDK/config version mismatches with
negotiate_version()utility. - MiddlewareChainError — Now explicitly
_default_retryable = Falseper PROTOCOL_SPEC §8.6.
guard_call_chain()— Standalone Algorithm A20 implementation for call chain safety checks (depth, circular, frequency). Executor delegates to this utility.propagate_error()— Standalone Algorithm A11 implementation for error wrapping and trace context attachment.normalize_to_canonical_id()— Cross-language module ID normalization (Python snake_case, Go PascalCase, etc.).calculate_specificity()— ACL pattern specificity scoring for deterministic rule ordering.parse_docstring()— Docstring parser for extracting parameter descriptions from function docstrings.
- Audit logging —
ACLconstructor accepts optionalaudit_loggercallback. All access decisions emitAuditEntrywith timestamp, caller/target IDs, matched rule, identity, and trace context. - Condition-based rules — ACL rules support
conditionsfor identity type, role, and call depth filtering.
- Full validation —
Config.validate()checks schema structure, value types, and range constraints. - Hot reload —
Config.reload()re-reads the YAML source and re-validates. - Environment overrides —
APCORE_*environment variables override config values (e.g.,APCORE_EXECUTOR_DEFAULT_TIMEOUT=5000). Config.from_defaults()— Factory method for default configuration.
- RetryMiddleware — Configurable retry with exponential/fixed backoff, jitter, and max delay. Only retries errors marked
retryable=True.
- ID conflict detection — Registry detects and prevents registration of conflicting module IDs.
- Safe unregister —
safe_unregister()with drain timeout for graceful module removal.
- Generic
servicestyping —Context[T]supports typed dependency injection via theservicesfield.
- Conformance test suite — JSON fixture-driven tests for error codes, call chain safety, ACL evaluation, pattern matching, specificity, ID normalization, and version negotiation.
- New unit tests — 17 new test files covering all added features.
_check_safety()now delegates to standaloneguard_call_chain()instead of inline logic.- Error handling wraps exceptions with
propagate_error()and re-raises withraise wrapped from exc. - Global deadline set on root call only, propagated to child contexts via
Context._global_deadline.
- Expanded
__all__inapcore.__init__with new exports:RetryMiddleware,RetryConfig,ErrorCodeRegistry,ErrorCodeCollisionError,VersionIncompatibleError,negotiate_version,guard_call_chain,propagate_error,normalize_to_canonical_id,calculate_specificity,AuditEntry,parse_docstring.
0.7.1 - 2026-03-04
- Module Protocol — Introduced
Moduleprotocol inapcore.modulefor standardized module typing. - Schema System — Exposed schema APIs (
SchemaLoader,SchemaValidator,SchemaExporter,RefResolver,to_strict_schema) to the top-levelapcoreexports. - Utilities — Exposed
match_patternutility to the top-levelapcoreexports.
0.7.0 - 2026-03-01
- ApprovalHandler Protocol - Async protocol for pluggable approval handlers with
request_approval()andcheck_approval()methods - ApprovalRequest / ApprovalResult - Frozen dataclasses carrying invocation context and handler decisions with
Literalstatus typing - Phase A (synchronous) - Handler blocks until approval decision; denied/timeout raise immediately
- Phase B (asynchronous) -
pendingstatus returns_approval_tokenfor async resume viacheck_approval() - Built-in handlers -
AlwaysDenyHandler(safe default),AutoApproveHandler(testing),CallbackApprovalHandler(custom logic) - Approval errors -
ApprovalError,ApprovalDeniedError,ApprovalTimeoutError,ApprovalPendingErrorwithresult,module_id, andreasonproperties - Audit events (Level 3) - Dual-channel emission:
logging.info()always + span events when tracing is active - Extension point -
approval_handlerregistered as a built-in extension point inExtensionManager - ErrorCodes - Added
APPROVAL_DENIED,APPROVAL_TIMEOUT,APPROVAL_PENDINGconstants
- Step 4.5 approval gate - Inserted between ACL (Step 4) and input validation (Step 5) in
call(),call_async(), andstream() - Executor.set_approval_handler() - Runtime handler configuration
- Executor.from_registry() - Added
approval_handlerparameter - Dict and dataclass annotations - Both
ModuleAnnotationsand dict-stylerequires_approvalsupported - Unknown status fail-closed - Unrecognized approval statuses treated as denied with warning log
- Approval errors re-exported from
apcore.approvalfor multi-language SDK consistency; canonical definitions remain inerrors.py ApprovalResult.statustyped asLiteral["approved", "rejected", "timeout", "pending"]per PROTOCOL_SPEC §7.3.2
0.6.0 - 2026-02-23
- ExtensionManager / ExtensionPoint - Added a unified extension-point framework for
discoverer,middleware,acl,span_exporter, andmodule_validator - Extension wiring - Added
apply()support to connect registered extensions intoRegistryandExecutor
- AsyncTaskManager - Added background task orchestration with status tracking, cancellation, concurrency limits, shutdown, and cleanup
- TaskStatus / TaskInfo - Added task lifecycle enum and metadata dataclass for async task management
- CancelToken / ExecutionCancelledError - Added cooperative cancellation primitives and integrated cancellation checks into executor flows
- TraceContext / TraceParent - Added W3C Trace Context utilities for
inject(),extract(), and strict parsing viafrom_traceparent() - Context.create(trace_parent=...) - Added distributed-tracing entry support by accepting inbound trace context
- OTLPExporter top-level export - Added OTLP exporter re-exports in observability and top-level public API
- Custom discoverer/validator hooks - Added
set_discoverer()andset_validator()integration paths - Module describe support - Added
Registry.describe()for human-readable module descriptions - Hot-reload APIs - Added
watch(),unwatch(), and file-change handling helpers for extension directories - Validation constants/protocols - Added
MAX_MODULE_ID_LENGTH,RESERVED_WORDS,Discoverer, andModuleValidatorexports
- Expanded top-level
apcoreexports to include cancellation, extensions, async task types, trace context types, additional registry protocols/constants, and new error classes
- Added
ModuleExecuteErrorandInternalErrorto the framework error hierarchy and exports - Extended
ErrorCodeswith additional constants used by newer execution/extension paths
- executor - Added recursive
_secret_key redaction for nested dictionaries - executor - Preserved explicit cancellation semantics by re-raising
ExecutionCancelledError
- Reduced import-coupling risk across middleware/observability/trace typing paths while preserving existing runtime behavior and public interfaces
0.5.0 - 2026-02-22
- decorator - Renamed
_generate_input_model/_generate_output_modeltogenerate_input_model/generate_output_modelas public API - context_logger - Renamed
formatparameter tooutput_formatto avoid shadowing Python builtin - registry - Renamed
_write_lockto_lockfor clearer intent
- decorator - Replaced bare
dictwithdict[str, Any]in_normalize_result,annotations,metadata,_async_execute,_sync_execute - bindings - Fixed
_build_model_from_json_schemaparameter type fromdicttodict[str, Any] - scanner - Fixed
rootsparameter type fromlist[dict]tolist[dict[str, Any]] - metrics - Fixed
snapshotreturn type fromdicttodict[str, Any] - executor - Removed redundant string-quoted forward references in
from_registry; fixedmiddlewaresparameter type tolist[Middleware] | None
- executor - Extracted
_convert_validation_errors()helper to eliminate 6 duplicated validation error conversion patterns - executor - Refactored
call_async()andstream()to use new async middleware manager methods - executor - Removed internal
_execute_on_error_asyncmethod (replaced byMiddlewareManager.execute_on_error_async) - loader - Use
self._resolver.clear_cache()instead of accessing private_file_cachedirectly - tracing - Replaced
print()withsys.stdout.write()inStdoutExporter - acl / loader - Changed hardcoded logger names to
logging.getLogger(__name__)
- ExtensionManager and ExtensionPoint for unified extension point management (discoverer, middleware, acl, span_exporter, module_validator) with
register(),get(),get_all(),unregister(),apply(),list_points()methods - AsyncTaskManager, TaskStatus, TaskInfo for async task execution with status tracking (PENDING, RUNNING, COMPLETED, FAILED, CANCELLED), cancellation, and concurrency limiting
- TraceContext and TraceParent for W3C Trace Context support with
inject(),extract(), andfrom_traceparent()methods Context.create()now accepts optionaltrace_parentparameter for distributed trace propagation
- MiddlewareManager - Added
execute_before_async(),execute_after_async(),execute_on_error_async()for proper async middleware dispatch withinspect.iscoroutinefunctiondetection - RefResolver - Added
clear_cache()public method for cache management - Executor - Added
clear_async_cache()public method
- SchemaExporter - Added
streaminghint toexport_mcp()annotations fromModuleAnnotations
- context - Changed
Identity.rolesfrom mutablelist[str]to immutabletuple[str, ...]in frozen dataclass
- context_logger / metrics - Handle cases where
before()was never called inObsLoggingMiddlewareandMetricsMiddleware
- acl - Added explicit
encoding="utf-8"to YAML file open
0.4.0 - 2026-02-20
- Executor.stream() - New async generator method for streaming module execution
- Implements same 6-step pipeline as
call_async()(context, safety, lookup, ACL, input validation, middleware before) - Falls back to
call_async()yielding single chunk for non-streaming modules - For streaming modules, iterates
module.stream()and yields each chunk - Accumulates chunks via shallow merge for output validation and after-middleware
- Full error handling with middleware recovery
- Implements same 6-step pipeline as
- ModuleAnnotations.streaming - New
streaming: bool = Falsefield to indicate if a module supports streaming execution - Test coverage - Added 5 comprehensive tests in
test_executor_stream.py:- Fallback behavior for non-streaming modules
- Multi-chunk streaming
- Module not found error handling
- Before/after middleware integration
- Disjoint key accumulation via shallow merge
0.3.0 - 2026-02-20
- ErrorCodes - New
ErrorCodesclass with all framework error code constants; replaces hardcoded error strings - ContextFactory Protocol - New
ContextFactoryprotocol for creating Context from framework-specific requests (e.g., Django, FastAPI) - Registry constants - Exported
REGISTRY_EVENTSdict andMODULE_ID_PATTERNregex for consistent module ID validation - Executor.from_registry() - Convenience factory method for creating an Executor from a Registry with optional middlewares, ACL, and config
- Comprehensive schema system - Full implementation with loading, validation, and export capabilities
- Schema loading from JSON/YAML files
- Runtime schema validation
- Schema export functionality
- ErrorCodes class - Prevent attribute deletion to ensure error code constants remain immutable
- Planning documentation - Updated progress bar style in overview.md
0.2.3 - 2026-02-20
- ContextFactory Protocol - New
ContextFactoryprotocol for creating Context from framework-specific requests (e.g., Django, FastAPI) - ErrorCodes - New
ErrorCodesclass with all framework error code constants; replaces hardcoded error strings - Registry constants - Exported
REGISTRY_EVENTSdict andMODULE_ID_PATTERNregex for consistent module ID validation - Executor.from_registry() - Convenience factory method for creating an Executor from a Registry with optional middlewares, ACL, and config
- Module ID validation - Strengthened to enforce lowercase letters, digits, underscores, and dots only; no hyphens allowed. Pattern:
^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$ - Registry events - Replaced hardcoded event strings with
REGISTRY_EVENTSconstant dict - Test fixtures - Updated registry test module IDs to comply with new module ID pattern
- .code-forge.json - Updated directory mappings:
basefromplanning/to./;inputfromfeatures/to../apcore/docs/features
- Better type hints and protocol definitions for framework integration
- Consistent error handling with standardized error codes
0.2.2 - 2026-02-16
- planning/features/ - Moved all feature specifications to
apcore/docs/features/for better organization with documentation - planning/implementation/ - Restructured implementation planning to consolidate with overall project architecture
- Implementation planning - Reorganized implementation plans to streamline project structure and improve maintainability
0.2.1 - 2026-02-14
- code-forge integration - Added
.code-forge.jsonconfiguration (v0.2.0 spec) with_toolmetadata, directory mappings, and execution settings - Feature specifications - 7 feature documents in
planning/features/covering all core modules: core-executor, schema-system, registry-system, middleware-system, acl-system, observability, decorator-bindings - Implementation plans - Complete implementation plans in
planning/implementation/for all 7 features, each containingoverview.md,plan.md,tasks/*.md, andstate.json - Project-level overview - Auto-generated
planning/implementation/overview.mdwith module dependency graph, progress tracking, and phased implementation order - Task breakdown - 42 task files with TDD-oriented steps, acceptance criteria, dependency tracking, and time estimates (~91 hours total estimated effort)
0.2.0 - 2026-02-14
- MiddlewareManager - Added internal locking and snapshot pattern;
add(),remove(),execute_before(),execute_after()are now thread-safe - Executor - Added lock to async module cache; use
snapshot()for middleware iteration incall_async()andmiddlewaresproperty - ACL - Internally synchronized;
check(),add_rule(),remove_rule(),reload()are now safe for concurrent use - Registry - Extended existing
RLockto cover all read paths (get,has,count,module_ids,list,iter,get_definition,on,_trigger_event,clear_cache)
- InMemoryExporter - Replaced unbounded
listwithcollections.deque(maxlen=10_000)and addedthreading.Lockfor thread-safe access
- TracingMiddleware - Added empty span stack guard in
after()andon_error()to log a warning instead of raisingIndexError - Executor - Set
daemon=Trueon timeout and async bridge threads to prevent blocking process exit
- apdev integration - Added
apdev[dev]as development dependency for code quality checks and project tooling - pip install support - Moved dev dependencies to
[project.optional-dependencies]sopip install -e ".[dev]"works alongsideuv sync --group dev - pre-commit hooks - Fixed
check-charsandcheck-importshooks to run as local hooks viaapdevinstead of incorrectly nesting underruff-pre-commitrepo
- Context.child() - Added docstring clarifying that
datais intentionally shared between parent and child for middleware state propagation
0.1.0 - 2026-02-13
- Schema-driven modules - Define modules with Pydantic input/output schemas and automatic validation
- @module decorator - Zero-boilerplate decorator to turn functions into schema-aware modules
- Executor - 10-step execution pipeline with comprehensive safety and security checks
- Registry - Module registration and discovery system with metadata support
- Access Control (ACL) - Pattern-based, first-match-wins rule system with wildcard support
- Call depth limits - Prevent infinite recursion and stack overflow
- Circular call detection - Detect and prevent circular module calls
- Frequency throttling - Rate limit module execution
- Timeout support - Configure execution timeouts per module
- Composable pipeline - Before/after hooks for request/response processing
- Error recovery - Graceful error handling and recovery in middleware chain
- LoggingMiddleware - Structured logging for all module calls
- TracingMiddleware - Distributed tracing with span support for observability
- YAML bindings - Register modules declaratively without modifying source code
- Configuration system - Centralized configuration management
- Environment support - Environment-based configuration override
- Tracing - Span-based distributed tracing integration
- Metrics - Built-in metrics collection for execution monitoring
- Context logging - Structured logging with execution context propagation
- Sync/Async modules - Seamless support for both synchronous and asynchronous execution
- Async executor - Non-blocking execution for async-first applications
- Type safety - Full type annotations across the framework (Python 3.11+)
- Comprehensive tests - 90%+ test coverage with unit and integration tests
- Documentation - Quick start guide, examples, and API documentation
- Examples - Sample modules demonstrating decorator-based and class-based patterns
- pydantic >= 2.0 - Schema validation and serialization
- pyyaml >= 6.0 - YAML binding support
- Python 3.11+