Skip to content

Releases: Agent-CI/agentexec

v0.2.0rc1

31 Mar 20:16

Choose a tag to compare

v0.2.0rc1 Pre-release
Pre-release

0.2.0rc1 — Architecture overhaul

First release candidate for 0.2.0. Major refactor of the backend, queue, activity, and worker systems.

Breaking changes

  • agentexec.state.redis_backendagentexec.state.redis (update AGENTEXEC_STATE_BACKEND if set explicitly)
  • AGENTEXEC_QUEUE_NAMEAGENTEXEC_QUEUE_PREFIX (old name still accepted as alias)
  • Activity functions are now async (await ax.activity.create(...), await ax.activity.update(...), etc.)
  • Task.context is now Mapping[str, Any] (raw dict), not a typed BaseModel — hydration happens at execution time
  • Task.create() is now async
  • Removed: set_global_session/get_global_session/remove_global_session — use configure_engine/get_session
  • Removed: state.backend.publish/subscribe (pubsub), index_add/index_range/index_remove, clear, configure

New features

  • Partitioned Redis queues — tasks with lock_key route to dedicated partition queues with per-partition locking and SCAN-based fair dequeue
  • Activity handler pattern — pluggable persistence via PostgresHandler (default) and IPCHandler (worker processes)
  • Task retry with backoff — failed tasks requeue as high priority with AGENTEXEC_MAX_TASK_RETRIES (default 3)
  • Kafka backend (experimental)pip install agentexec[kafka] for queue and schedule via Kafka (state ops raise NotImplementedError)
  • Typed worker IPCTaskFailed, LogEntry, ActivityUpdated messages over multiprocessing.Queue
  • Schedule composite keys{task_name}:{cron}:{context_hash} for unique schedule identity

Improvements

  • Class-based backend architecture with ABCs
  • Task is pure data, TaskDefinition owns behavior
  • Session management via configure_engine/get_session (Pool owns the engine)
  • Status enum extracted to activity/status.py (no SQLAlchemy dependency)
  • 277 tests passing across partitions, retries, execute lifecycle, schedules

v0.1.7

24 Mar 03:35

Choose a tag to compare

New Features

Scheduled tasks with cron expressions

  • @pool.schedule("task_name", "*/5 * * * *") decorator registers and schedules a task in one step
  • pool.add_schedule() for imperative scheduling of already-registered tasks
  • Cron expressions evaluated in configurable timezone (AGENTEXEC_SCHEDULER_TIMEZONE, default UTC)
  • Repeat budget: -1 for forever, 0 for one-shot, N for N more executions
  • Scheduler runs automatically inside pool.run()
  • Idempotent registration: keyed by task name, restarts and multiple pool instances overwrite instead of duplicating
  • Clock-drift resilient, skips missed intervals after downtime

Improvements

  • Added zadd(), zrangebyscore(), zrem() to state backend protocol and Redis implementation

See CHANGELOG.md for full details.

v0.1.6

22 Mar 04:00

Choose a tag to compare

New Features

Task-level distributed locking

  • New lock_key parameter on @pool.task() and pool.add_task() for sequential execution of tasks sharing state
  • String template evaluated against context fields (e.g., lock_key="user:{user_id}")
  • Workers acquire a Redis lock before execution; tasks requeue automatically on contention
  • Configurable TTL via AGENTEXEC_LOCK_TTL (default 1800s)

Activity metadata for multi-tenancy

  • Attach arbitrary metadata when creating activities for tenant isolation
  • Filter activities by metadata in activity.list() and activity.detail()
  • Metadata excluded from API serialization by default

Improvements

  • Redis cleanup on shutdown via state.clear_keys()
  • acquire_lock() / release_lock() added to state backend protocol

See CHANGELOG.md for full details.

v0.1.5

16 Jan 00:19
3d90c3b

Choose a tag to compare

What's Changed

  • Improve readme by @tcdent in #8
  • Make pool.add_task public, less restrictive types on payloads, add typechecking to test harness. by @accordion-tcdent in #10
  • Bump version to v0.1.5 by @Copilot in #11

New Contributors

Full Changelog: v0.1.4...v0.1.5

v0.1.4

06 Dec 02:04

Choose a tag to compare

v0.1.4

Breaking Changes

Renamed WorkerPool to Pool

  • ax.WorkerPool is now ax.Pool for cleaner API
  • Update imports: from agentexec import Pool

Activity percentage field renamed

  • completion_% renamed to percentage for cleaner field naming

New Features

Pipelines run on workers

  • Pipelines can now be executed on worker processes
  • Register pipelines with the pool and enqueue them like tasks

Tracker for stateful counters

  • New Tracker class for managing stateful counters across workers
  • Useful for tracking progress, metrics, and distributed state

Strict Pipeline type flow validation

  • All step parameters and return types must be BaseModel subclasses
  • Type flow between consecutive steps is validated at runtime
  • Tuple returns are unpacked and matched to next step's parameters
  • Final step must return a single BaseModel (not a tuple)
  • Empty pipelines raise RuntimeError at class definition time

Internal Improvements

Type checking with ty

  • Added ty type checker to development workflow
  • Better Protocol definitions for step handlers
  • Improved type hints throughout pipeline module

Better Pipeline flow tests

  • Comprehensive test coverage for valid and invalid type flows
  • Tests for tuple unpacking, subclass compatibility, count mismatches
  • Tests for primitive type rejection and edge cases

v0.1.3

02 Dec 22:48

Choose a tag to compare

Breaking Changes

Self-describing JSON serialization replaces pickle

  • Task results now use JSON serialization with embedded type information (similar to pickle)
  • Automatically stores fully qualified class name with data for type reconstruction
  • No longer requires TaskDefinition registry for result deserialization
  • ax.gather() now works with tasks created via ax.enqueue() without pool context
  • Migration: Clear Redis or wait for TTL expiry on old pickled results

TaskHandler Protocol enforces BaseModel returns

  • Task handlers must return a Pydantic BaseModel instance (not None or arbitrary objects)
  • Return type is automatically inferred and validated at registration time
  • Enables type-safe result retrieval and automatic serialization

New Features

State backend abstraction

  • Introduced StateBackend Protocol for pluggable state storage implementations
  • Current Redis implementation moved to agentexec.state.redis_backend
  • Backend modules verified against protocol at import time via cast()
  • Prepares foundation for alternative backends (in-memory, DynamoDB, etc.)

Improved async patterns

  • brpop() is now a proper async function (was sync returning coroutine)
  • Consistent async/await usage across state operations
  • Better type hints and IDE support

Enhanced type safety

  • TaskHandler Protocol with support for both sync and async handlers
  • Proper type annotations for all state backend operations
  • serialize() and deserialize() type-enforced for BaseModel only

Documentation

Comprehensive documentation added

  • API reference for core modules (activity, pipeline, runner, task)
  • Conceptual guides (architecture, task lifecycle, worker pool)
  • Deployment guides (Docker, production best practices)
  • Usage guides (basic usage, pipelines, FastAPI integration, OpenAI runner)
  • Getting started (installation, quickstart, configuration)
  • Contributing guide

UI & Tooling

React frontend and component library

  • Added agentexec-ui npm package with reusable React components
  • Pre-built UI for agent monitoring and activity tracking
  • TanStack Query integration for real-time updates
  • React Router for navigation between agent list and detail views

Docker deployment

  • Docker worker image for containerized deployments
  • GitHub Actions for automated Docker image publishing to GitHub Container Registry
  • GitHub Actions for automated npm publishing of UI components

Testing

Comprehensive test coverage

  • Achieved 89% code coverage
  • Added unit tests for all core modules:
    • State backend and serialization (test_state.py, test_state_backend.py)
    • Self-describing results (test_self_describing_results.py)
    • Activity tracking schemas (test_activity_schemas.py)
    • Pipeline orchestration (test_pipeline.py)
    • Task queue operations (test_queue.py)
    • Worker events and logging (test_worker_event.py, test_worker_logging.py)
    • Database operations (test_db.py)
    • Configuration (test_config.py)

Internal Improvements

Redis client refactoring

  • Removed core/redis_client.py in favor of state backend abstraction
  • Lazy connection initialization for both async and sync Redis clients
  • Proper connection cleanup in backend.close()

Key formatting consistency

  • All state keys use consistent agentexec: prefix via backend.format_key()
  • Results: agentexec:result:{agent_id}
  • Events: agentexec:event:{name}:{id}
  • Logs channel: agentexec:logs

Standardized function signatures

  • get_result() and gather() return BaseModel directly (not JSON strings)
  • Consistent parameter ordering across state module functions
  • Better docstrings with type information

v0.1.2

01 Dec 04:07

Choose a tag to compare

v0.1.2

New Features

Pipelines

  • Multi-step workflow orchestration with ax.Pipeline
  • Define steps with @pipeline.step(order) decorator
  • Parallel task execution with ax.gather()
  • Result retrieval with ax.get_result()

Worker logging via Redis pubsub

  • Workers publish logs to Redis, collected by main process
  • Use pool.run() to see worker logs in real-time

Internal Improvements

Reorganized worker module

  • Worker code moved to agentexec.worker subpackage
  • RedisEvent for cross-process shutdown coordination
  • get_worker_logger() configures logging and returns logger in one call

Refactored Redis client usage

  • Added get_redis_sync() for synchronous Redis operations
  • Sync/async Redis clients for different contexts

v0.1.1

28 Nov 22:45

Choose a tag to compare

v0.1.1

Breaking Changes

Async enqueue() function

  • ax.enqueue() is now async and must be awaited:
    task = await ax.enqueue("task_name", MyContext(key="value"))

Type-safe context with Pydantic BaseModel

  • Task context must be a Pydantic BaseModel instead of a raw dict
  • Context class is automatically inferred from handler type hints:
    class ResearchContext(BaseModel):
        company: str
    
    @pool.task("research")
    async def research(agent_id: UUID, context: ResearchContext):
        company = context.company  # Type-safe with IDE autocomplete

Redis URL now required

  • redis_url defaults to None and must be explicitly configured via REDIS_URL
  • Prevents accidental connections to wrong Redis instances

New Features

Configurable activity messages

  • Activity status messages are configurable via environment variables:
    AGENTEXEC_ACTIVITY_MESSAGE_CREATE="Waiting to start."
    AGENTEXEC_ACTIVITY_MESSAGE_STARTED="Task started."
    AGENTEXEC_ACTIVITY_MESSAGE_COMPLETE="Task completed successfully."
    AGENTEXEC_ACTIVITY_MESSAGE_ERROR="Task failed with error: {error}"

Improved Task architecture

  • Task is now the primary execution object with execute() method
  • TaskDefinition handles registration metadata and context class inference
  • Full lifecycle management (QUEUED → RUNNING → COMPLETE/ERROR) encapsulated in Task.execute()

Better SQLAlchemy session management

  • New scoped_session pattern for worker processes
  • Proper session cleanup on worker shutdown

Internal Improvements

  • Switched to async Redis client (redis.asyncio)
  • Consolidated cleanup code in worker _run() method
  • Removed unused debug config option

v0.1.0

22 Nov 06:24

Choose a tag to compare

v0.1.0 Pre-release
Pre-release

Initial release.