agentexec 0.1.2__tar.gz → 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentexec-0.1.3/.github/workflows/docker-publish.yml +65 -0
- agentexec-0.1.3/.github/workflows/npm-publish.yml +48 -0
- agentexec-0.1.3/CHANGELOG.md +171 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/PKG-INFO +47 -2
- {agentexec-0.1.2 → agentexec-0.1.3}/README.md +46 -1
- agentexec-0.1.3/docker/Dockerfile +77 -0
- agentexec-0.1.3/docker/README.md +149 -0
- agentexec-0.1.3/docker/entrypoint.py +78 -0
- agentexec-0.1.3/docs/api-reference/activity.md +455 -0
- agentexec-0.1.3/docs/api-reference/core.md +476 -0
- agentexec-0.1.3/docs/api-reference/pipeline.md +475 -0
- agentexec-0.1.3/docs/api-reference/runner.md +430 -0
- agentexec-0.1.3/docs/concepts/activity-tracking.md +520 -0
- agentexec-0.1.3/docs/concepts/architecture.md +344 -0
- agentexec-0.1.3/docs/concepts/task-lifecycle.md +435 -0
- agentexec-0.1.3/docs/concepts/worker-pool.md +499 -0
- agentexec-0.1.3/docs/contributing.md +341 -0
- agentexec-0.1.3/docs/deployment/docker.md +557 -0
- agentexec-0.1.3/docs/deployment/production.md +597 -0
- agentexec-0.1.3/docs/getting-started/configuration.md +295 -0
- agentexec-0.1.3/docs/getting-started/installation.md +34 -0
- agentexec-0.1.3/docs/getting-started/quickstart.md +262 -0
- agentexec-0.1.3/docs/guides/basic-usage.md +437 -0
- agentexec-0.1.3/docs/guides/custom-runners.md +595 -0
- agentexec-0.1.3/docs/guides/fastapi-integration.md +301 -0
- agentexec-0.1.3/docs/guides/openai-runner.md +468 -0
- agentexec-0.1.3/docs/guides/pipelines.md +553 -0
- agentexec-0.1.3/docs/index.md +129 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/README.md +45 -1
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/pipeline.py +1 -1
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/.gitignore +3 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/bun.lock +418 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/index.html +13 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/package.json +27 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/public/vite.svg +4 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/src/App.tsx +35 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/src/api/agents.ts +37 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/src/api/queries.ts +51 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/src/components/Layout.tsx +38 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/src/index.css +263 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/src/main.tsx +10 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/src/pages/AgentDetailPage.tsx +45 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/src/pages/AgentListPage.tsx +68 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/src/styles/github-dark.css +617 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/tsconfig.json +21 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/tsconfig.node.json +11 -0
- agentexec-0.1.3/examples/openai-agents-fastapi/ui/vite.config.ts +19 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/views.py +19 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/pyproject.toml +1 -1
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/__init__.py +2 -2
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/activity/__init__.py +2 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/activity/models.py +39 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/activity/tracker.py +12 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/config.py +12 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/core/queue.py +13 -16
- agentexec-0.1.3/src/agentexec/core/results.py +64 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/core/task.py +58 -22
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/pipeline.py +4 -8
- agentexec-0.1.3/src/agentexec/state/__init__.py +214 -0
- agentexec-0.1.3/src/agentexec/state/backend.py +210 -0
- agentexec-0.1.3/src/agentexec/state/redis_backend.py +352 -0
- agentexec-0.1.3/src/agentexec/worker/event.py +48 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/worker/logging.py +9 -10
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/worker/pool.py +25 -24
- agentexec-0.1.3/tests/test_activity_schemas.py +224 -0
- agentexec-0.1.3/tests/test_activity_tracking.py +354 -0
- agentexec-0.1.3/tests/test_config.py +204 -0
- agentexec-0.1.3/tests/test_db.py +134 -0
- agentexec-0.1.3/tests/test_pipeline.py +270 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/tests/test_public_api.py +0 -17
- agentexec-0.1.3/tests/test_queue.py +209 -0
- agentexec-0.1.3/tests/test_results.py +172 -0
- agentexec-0.1.3/tests/test_runners.py +573 -0
- agentexec-0.1.3/tests/test_self_describing_results.py +126 -0
- agentexec-0.1.3/tests/test_state.py +185 -0
- agentexec-0.1.3/tests/test_state_backend.py +272 -0
- agentexec-0.1.3/tests/test_task.py +319 -0
- agentexec-0.1.3/tests/test_worker_event.py +133 -0
- agentexec-0.1.3/tests/test_worker_logging.py +280 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/tests/test_worker_pool.py +122 -26
- agentexec-0.1.3/ui/.gitignore +3 -0
- agentexec-0.1.3/ui/README.md +148 -0
- agentexec-0.1.3/ui/bun.lock +397 -0
- agentexec-0.1.3/ui/package.json +52 -0
- agentexec-0.1.3/ui/src/components/ActiveAgentsBadge.tsx +20 -0
- agentexec-0.1.3/ui/src/components/ProgressBar.tsx +24 -0
- agentexec-0.1.3/ui/src/components/StatusBadge.tsx +42 -0
- agentexec-0.1.3/ui/src/components/TaskDetail.tsx +121 -0
- agentexec-0.1.3/ui/src/components/TaskList.tsx +119 -0
- agentexec-0.1.3/ui/src/components/index.ts +5 -0
- agentexec-0.1.3/ui/src/index.ts +23 -0
- agentexec-0.1.3/ui/src/types.ts +59 -0
- agentexec-0.1.3/ui/tsconfig.json +24 -0
- agentexec-0.1.3/ui/vite.config.ts +34 -0
- agentexec-0.1.2/CHANGELOG.md +0 -82
- agentexec-0.1.2/src/agentexec/core/redis_client.py +0 -71
- agentexec-0.1.2/src/agentexec/core/results.py +0 -62
- agentexec-0.1.2/src/agentexec/worker/event.py +0 -43
- agentexec-0.1.2/tests/test_activity_tracking.py +0 -89
- agentexec-0.1.2/tests/test_redis_client.py +0 -63
- agentexec-0.1.2/tests/test_task.py +0 -169
- {agentexec-0.1.2 → agentexec-0.1.3}/.github/workflows/publish.yml +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/.gitignore +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/alembic/README +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/alembic/env.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/alembic/script.py.mako +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/alembic.ini +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/compose.yml +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/context.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/db.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/main.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/models.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/pyproject.toml +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/tools.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/examples/openai-agents-fastapi/worker.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/activity/schemas.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/core/__init__.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/core/db.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/core/logging.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/runners/__init__.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/runners/base.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/runners/openai.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/src/agentexec/worker/__init__.py +0 -0
- {agentexec-0.1.2 → agentexec-0.1.3}/tests/test_activity_tracking.py.bak +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: Publish Docker Image
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
# Allow manual trigger for testing
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
tag:
|
|
10
|
+
description: 'Image tag (defaults to "dev")'
|
|
11
|
+
required: false
|
|
12
|
+
default: 'dev'
|
|
13
|
+
|
|
14
|
+
env:
|
|
15
|
+
REGISTRY: ghcr.io
|
|
16
|
+
IMAGE_NAME: agent-ci/agentexec-worker
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
packages: write
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
build-and-push:
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout repository
|
|
28
|
+
uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: Set up Docker Buildx
|
|
31
|
+
uses: docker/setup-buildx-action@v3
|
|
32
|
+
|
|
33
|
+
- name: Log in to Container Registry
|
|
34
|
+
uses: docker/login-action@v3
|
|
35
|
+
with:
|
|
36
|
+
registry: ${{ env.REGISTRY }}
|
|
37
|
+
username: ${{ github.actor }}
|
|
38
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
39
|
+
|
|
40
|
+
- name: Extract metadata for Docker
|
|
41
|
+
id: meta
|
|
42
|
+
uses: docker/metadata-action@v5
|
|
43
|
+
with:
|
|
44
|
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
45
|
+
tags: |
|
|
46
|
+
# Tag with version on release (e.g., v0.1.2 -> 0.1.2)
|
|
47
|
+
type=semver,pattern={{version}}
|
|
48
|
+
# Tag with major.minor on release (e.g., v0.1.2 -> 0.1)
|
|
49
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
50
|
+
# Tag as "latest" on release
|
|
51
|
+
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
|
52
|
+
# Tag with input value on manual dispatch
|
|
53
|
+
type=raw,value=${{ inputs.tag }},enable=${{ github.event_name == 'workflow_dispatch' }}
|
|
54
|
+
|
|
55
|
+
- name: Build and push Docker image
|
|
56
|
+
uses: docker/build-push-action@v5
|
|
57
|
+
with:
|
|
58
|
+
context: ./docker
|
|
59
|
+
file: ./docker/Dockerfile
|
|
60
|
+
push: true
|
|
61
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
62
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
63
|
+
cache-from: type=gha
|
|
64
|
+
cache-to: type=gha,mode=max
|
|
65
|
+
platforms: linux/amd64,linux/arm64
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Publish agentexec-ui to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
version:
|
|
9
|
+
description: 'Version to publish (leave empty to use package.json version)'
|
|
10
|
+
required: false
|
|
11
|
+
type: string
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
publish:
|
|
18
|
+
# Only run for releases tagged with ui-v* or manual triggers
|
|
19
|
+
if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/ui-v')
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
defaults:
|
|
23
|
+
run:
|
|
24
|
+
working-directory: ui
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
|
|
29
|
+
- name: Setup Node.js
|
|
30
|
+
uses: actions/setup-node@v4
|
|
31
|
+
with:
|
|
32
|
+
node-version: '20'
|
|
33
|
+
registry-url: 'https://registry.npmjs.org'
|
|
34
|
+
|
|
35
|
+
- name: Install dependencies
|
|
36
|
+
run: npm install
|
|
37
|
+
|
|
38
|
+
- name: Update version (if specified)
|
|
39
|
+
if: inputs.version != ''
|
|
40
|
+
run: npm version ${{ inputs.version }} --no-git-tag-version
|
|
41
|
+
|
|
42
|
+
- name: Build package
|
|
43
|
+
run: npm run build
|
|
44
|
+
|
|
45
|
+
- name: Publish to npm
|
|
46
|
+
run: npm publish --access public
|
|
47
|
+
env:
|
|
48
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
### Breaking Changes
|
|
6
|
+
|
|
7
|
+
**Self-describing JSON serialization replaces pickle**
|
|
8
|
+
- Task results now use JSON serialization with embedded type information (similar to pickle)
|
|
9
|
+
- Automatically stores fully qualified class name with data for type reconstruction
|
|
10
|
+
- No longer requires `TaskDefinition` registry for result deserialization
|
|
11
|
+
- `ax.gather()` now works with tasks created via `ax.enqueue()` without pool context
|
|
12
|
+
- **Migration**: Clear Redis or wait for TTL expiry on old pickled results
|
|
13
|
+
|
|
14
|
+
**TaskHandler Protocol enforces BaseModel returns**
|
|
15
|
+
- Task handlers must return a Pydantic `BaseModel` instance (not `None` or arbitrary objects)
|
|
16
|
+
- Return type is automatically inferred and validated at registration time
|
|
17
|
+
- Enables type-safe result retrieval and automatic serialization
|
|
18
|
+
|
|
19
|
+
### New Features
|
|
20
|
+
|
|
21
|
+
**State backend abstraction**
|
|
22
|
+
- Introduced `StateBackend` Protocol for pluggable state storage implementations
|
|
23
|
+
- Current Redis implementation moved to `agentexec.state.redis_backend`
|
|
24
|
+
- Backend modules verified against protocol at import time via `cast()`
|
|
25
|
+
- Prepares foundation for alternative backends (in-memory, DynamoDB, etc.)
|
|
26
|
+
|
|
27
|
+
**Improved async patterns**
|
|
28
|
+
- `brpop()` is now a proper async function (was sync returning coroutine)
|
|
29
|
+
- Consistent async/await usage across state operations
|
|
30
|
+
- Better type hints and IDE support
|
|
31
|
+
|
|
32
|
+
**Enhanced type safety**
|
|
33
|
+
- `TaskHandler` Protocol with support for both sync and async handlers
|
|
34
|
+
- Proper type annotations for all state backend operations
|
|
35
|
+
- `serialize()` and `deserialize()` type-enforced for `BaseModel` only
|
|
36
|
+
|
|
37
|
+
### Documentation
|
|
38
|
+
|
|
39
|
+
**Comprehensive documentation added**
|
|
40
|
+
- API reference for core modules (activity, pipeline, runner, task)
|
|
41
|
+
- Conceptual guides (architecture, task lifecycle, worker pool)
|
|
42
|
+
- Deployment guides (Docker, production best practices)
|
|
43
|
+
- Usage guides (basic usage, pipelines, FastAPI integration, OpenAI runner)
|
|
44
|
+
- Getting started (installation, quickstart, configuration)
|
|
45
|
+
- Contributing guide
|
|
46
|
+
|
|
47
|
+
### UI & Tooling
|
|
48
|
+
|
|
49
|
+
**React frontend and component library**
|
|
50
|
+
- Added `agentexec-ui` npm package with reusable React components
|
|
51
|
+
- Pre-built UI for agent monitoring and activity tracking
|
|
52
|
+
- TanStack Query integration for real-time updates
|
|
53
|
+
- React Router for navigation between agent list and detail views
|
|
54
|
+
|
|
55
|
+
**Docker deployment**
|
|
56
|
+
- Docker worker image for containerized deployments
|
|
57
|
+
- GitHub Actions for automated Docker image publishing to GitHub Container Registry
|
|
58
|
+
- GitHub Actions for automated npm publishing of UI components
|
|
59
|
+
|
|
60
|
+
### Testing
|
|
61
|
+
|
|
62
|
+
**Comprehensive test coverage**
|
|
63
|
+
- Achieved 89% code coverage
|
|
64
|
+
- Added unit tests for all core modules:
|
|
65
|
+
- State backend and serialization (`test_state.py`, `test_state_backend.py`)
|
|
66
|
+
- Self-describing results (`test_self_describing_results.py`)
|
|
67
|
+
- Activity tracking schemas (`test_activity_schemas.py`)
|
|
68
|
+
- Pipeline orchestration (`test_pipeline.py`)
|
|
69
|
+
- Task queue operations (`test_queue.py`)
|
|
70
|
+
- Worker events and logging (`test_worker_event.py`, `test_worker_logging.py`)
|
|
71
|
+
- Database operations (`test_db.py`)
|
|
72
|
+
- Configuration (`test_config.py`)
|
|
73
|
+
|
|
74
|
+
### Internal Improvements
|
|
75
|
+
|
|
76
|
+
**Redis client refactoring**
|
|
77
|
+
- Removed `core/redis_client.py` in favor of state backend abstraction
|
|
78
|
+
- Lazy connection initialization for both async and sync Redis clients
|
|
79
|
+
- Proper connection cleanup in `backend.close()`
|
|
80
|
+
|
|
81
|
+
**Key formatting consistency**
|
|
82
|
+
- All state keys use consistent `agentexec:` prefix via `backend.format_key()`
|
|
83
|
+
- Results: `agentexec:result:{agent_id}`
|
|
84
|
+
- Events: `agentexec:event:{name}:{id}`
|
|
85
|
+
- Logs channel: `agentexec:logs`
|
|
86
|
+
|
|
87
|
+
**Standardized function signatures**
|
|
88
|
+
- `get_result()` and `gather()` return `BaseModel` directly (not JSON strings)
|
|
89
|
+
- Consistent parameter ordering across state module functions
|
|
90
|
+
- Better docstrings with type information
|
|
91
|
+
|
|
92
|
+
## v0.1.2
|
|
93
|
+
|
|
94
|
+
### New Features
|
|
95
|
+
|
|
96
|
+
**Pipelines**
|
|
97
|
+
- Multi-step workflow orchestration with `ax.Pipeline`
|
|
98
|
+
- Define steps with `@pipeline.step(order)` decorator
|
|
99
|
+
- Parallel task execution with `ax.gather()`
|
|
100
|
+
- Result retrieval with `ax.get_result()`
|
|
101
|
+
|
|
102
|
+
**Worker logging via Redis pubsub**
|
|
103
|
+
- Workers publish logs to Redis, collected by main process
|
|
104
|
+
- Use `pool.run()` to see worker logs in real-time
|
|
105
|
+
|
|
106
|
+
### Internal Improvements
|
|
107
|
+
|
|
108
|
+
**Reorganized worker module**
|
|
109
|
+
- Worker code moved to `agentexec.worker` subpackage
|
|
110
|
+
- `RedisEvent` for cross-process shutdown coordination
|
|
111
|
+
- `get_worker_logger()` configures logging and returns logger in one call
|
|
112
|
+
|
|
113
|
+
**Refactored Redis client usage**
|
|
114
|
+
- Added `get_redis_sync()` for synchronous Redis operations
|
|
115
|
+
- Sync/async Redis clients for different contexts
|
|
116
|
+
|
|
117
|
+
## v0.1.1
|
|
118
|
+
|
|
119
|
+
### Breaking Changes
|
|
120
|
+
|
|
121
|
+
**Async `enqueue()` function**
|
|
122
|
+
- `ax.enqueue()` is now async and must be awaited:
|
|
123
|
+
```python
|
|
124
|
+
task = await ax.enqueue("task_name", MyContext(key="value"))
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Type-safe context with Pydantic BaseModel**
|
|
128
|
+
- Task context must be a Pydantic `BaseModel` instead of a raw `dict`
|
|
129
|
+
- Context class is automatically inferred from handler type hints:
|
|
130
|
+
```python
|
|
131
|
+
class ResearchContext(BaseModel):
|
|
132
|
+
company: str
|
|
133
|
+
|
|
134
|
+
@pool.task("research")
|
|
135
|
+
async def research(agent_id: UUID, context: ResearchContext):
|
|
136
|
+
company = context.company # Type-safe with IDE autocomplete
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Redis URL now required**
|
|
140
|
+
- `redis_url` defaults to `None` and must be explicitly configured via `REDIS_URL`
|
|
141
|
+
- Prevents accidental connections to wrong Redis instances
|
|
142
|
+
|
|
143
|
+
### New Features
|
|
144
|
+
|
|
145
|
+
**Configurable activity messages**
|
|
146
|
+
- Activity status messages are configurable via environment variables:
|
|
147
|
+
```bash
|
|
148
|
+
AGENTEXEC_ACTIVITY_MESSAGE_CREATE="Waiting to start."
|
|
149
|
+
AGENTEXEC_ACTIVITY_MESSAGE_STARTED="Task started."
|
|
150
|
+
AGENTEXEC_ACTIVITY_MESSAGE_COMPLETE="Task completed successfully."
|
|
151
|
+
AGENTEXEC_ACTIVITY_MESSAGE_ERROR="Task failed with error: {error}"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Improved Task architecture**
|
|
155
|
+
- `Task` is now the primary execution object with `execute()` method
|
|
156
|
+
- `TaskDefinition` handles registration metadata and context class inference
|
|
157
|
+
- Full lifecycle management (QUEUED → RUNNING → COMPLETE/ERROR) encapsulated in `Task.execute()`
|
|
158
|
+
|
|
159
|
+
**Better SQLAlchemy session management**
|
|
160
|
+
- New `scoped_session` pattern for worker processes
|
|
161
|
+
- Proper session cleanup on worker shutdown
|
|
162
|
+
|
|
163
|
+
### Internal Improvements
|
|
164
|
+
|
|
165
|
+
- Switched to async Redis client (`redis.asyncio`)
|
|
166
|
+
- Consolidated cleanup code in worker `_run()` method
|
|
167
|
+
- Removed unused `debug` config option
|
|
168
|
+
|
|
169
|
+
## v0.1.0
|
|
170
|
+
|
|
171
|
+
Initial release.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentexec
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Production-ready orchestration for OpenAI Agents with Redis-backed coordination, activity tracking, and workflow management
|
|
5
5
|
Project-URL: Homepage, https://github.com/Agent-CI/agentexec
|
|
6
6
|
Project-URL: Documentation, https://github.com/Agent-CI/agentexec#readme
|
|
@@ -25,6 +25,8 @@ Description-Content-Type: text/markdown
|
|
|
25
25
|
|
|
26
26
|
# `agentexec`
|
|
27
27
|
|
|
28
|
+
[](https://codecov.io/gh/Agent-CI/agentexec)
|
|
29
|
+
|
|
28
30
|
**Production-ready orchestration for OpenAI Agents SDK** with Redis-backed task queues, SQLAlchemy activity tracking, and multiprocessing worker pools.
|
|
29
31
|
|
|
30
32
|
Build reliable, scalable AI agent applications with automatic lifecycle management, progress tracking, and fault tolerance.
|
|
@@ -243,7 +245,7 @@ class MyPipeline(pipeline.Base):
|
|
|
243
245
|
async def analyze(self, brand_result, market_result):
|
|
244
246
|
"""Combine results from previous step."""
|
|
245
247
|
task = await ax.enqueue("analyze", AnalysisContext(...))
|
|
246
|
-
return await ax.get_result(task
|
|
248
|
+
return await ax.get_result(task)
|
|
247
249
|
|
|
248
250
|
|
|
249
251
|
# Run the pipeline
|
|
@@ -394,6 +396,49 @@ AgentExec creates two tables (prefix configurable):
|
|
|
394
396
|
|
|
395
397
|
---
|
|
396
398
|
|
|
399
|
+
## Docker Deployment
|
|
400
|
+
|
|
401
|
+
Deploy workers using the official Docker image:
|
|
402
|
+
|
|
403
|
+
### 1. Create your worker Dockerfile
|
|
404
|
+
|
|
405
|
+
```dockerfile
|
|
406
|
+
FROM ghcr.io/agent-ci/agentexec-worker:latest
|
|
407
|
+
|
|
408
|
+
COPY ./src /app/src
|
|
409
|
+
ENV AGENTEXEC_WORKER_MODULE=src.worker
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### 2. Create your worker module
|
|
413
|
+
|
|
414
|
+
```python
|
|
415
|
+
# src/worker.py
|
|
416
|
+
import os
|
|
417
|
+
import agentexec as ax
|
|
418
|
+
|
|
419
|
+
pool = ax.WorkerPool(database_url=os.environ["DATABASE_URL"])
|
|
420
|
+
|
|
421
|
+
@pool.task("my_task")
|
|
422
|
+
async def my_task(agent_id, context):
|
|
423
|
+
# Your task implementation
|
|
424
|
+
pass
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### 3. Run with Docker
|
|
428
|
+
|
|
429
|
+
```bash
|
|
430
|
+
docker build -t my-worker .
|
|
431
|
+
docker run \
|
|
432
|
+
-e DATABASE_URL=postgresql://... \
|
|
433
|
+
-e REDIS_URL=redis://... \
|
|
434
|
+
-e OPENAI_API_KEY=sk-... \
|
|
435
|
+
my-worker
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
See **[docker/README.md](docker/README.md)** for full documentation including Docker Compose examples.
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
397
442
|
## Development
|
|
398
443
|
|
|
399
444
|
```bash
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# `agentexec`
|
|
2
2
|
|
|
3
|
+
[](https://codecov.io/gh/Agent-CI/agentexec)
|
|
4
|
+
|
|
3
5
|
**Production-ready orchestration for OpenAI Agents SDK** with Redis-backed task queues, SQLAlchemy activity tracking, and multiprocessing worker pools.
|
|
4
6
|
|
|
5
7
|
Build reliable, scalable AI agent applications with automatic lifecycle management, progress tracking, and fault tolerance.
|
|
@@ -218,7 +220,7 @@ class MyPipeline(pipeline.Base):
|
|
|
218
220
|
async def analyze(self, brand_result, market_result):
|
|
219
221
|
"""Combine results from previous step."""
|
|
220
222
|
task = await ax.enqueue("analyze", AnalysisContext(...))
|
|
221
|
-
return await ax.get_result(task
|
|
223
|
+
return await ax.get_result(task)
|
|
222
224
|
|
|
223
225
|
|
|
224
226
|
# Run the pipeline
|
|
@@ -369,6 +371,49 @@ AgentExec creates two tables (prefix configurable):
|
|
|
369
371
|
|
|
370
372
|
---
|
|
371
373
|
|
|
374
|
+
## Docker Deployment
|
|
375
|
+
|
|
376
|
+
Deploy workers using the official Docker image:
|
|
377
|
+
|
|
378
|
+
### 1. Create your worker Dockerfile
|
|
379
|
+
|
|
380
|
+
```dockerfile
|
|
381
|
+
FROM ghcr.io/agent-ci/agentexec-worker:latest
|
|
382
|
+
|
|
383
|
+
COPY ./src /app/src
|
|
384
|
+
ENV AGENTEXEC_WORKER_MODULE=src.worker
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### 2. Create your worker module
|
|
388
|
+
|
|
389
|
+
```python
|
|
390
|
+
# src/worker.py
|
|
391
|
+
import os
|
|
392
|
+
import agentexec as ax
|
|
393
|
+
|
|
394
|
+
pool = ax.WorkerPool(database_url=os.environ["DATABASE_URL"])
|
|
395
|
+
|
|
396
|
+
@pool.task("my_task")
|
|
397
|
+
async def my_task(agent_id, context):
|
|
398
|
+
# Your task implementation
|
|
399
|
+
pass
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### 3. Run with Docker
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
docker build -t my-worker .
|
|
406
|
+
docker run \
|
|
407
|
+
-e DATABASE_URL=postgresql://... \
|
|
408
|
+
-e REDIS_URL=redis://... \
|
|
409
|
+
-e OPENAI_API_KEY=sk-... \
|
|
410
|
+
my-worker
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
See **[docker/README.md](docker/README.md)** for full documentation including Docker Compose examples.
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
372
417
|
## Development
|
|
373
418
|
|
|
374
419
|
```bash
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# agentexec-worker base image
|
|
2
|
+
#
|
|
3
|
+
# This image provides the agentexec framework for running background workers.
|
|
4
|
+
# Users extend this image with their own task definitions.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# FROM ghcr.io/agent-ci/agentexec-worker:latest
|
|
8
|
+
# COPY ./src /app/src
|
|
9
|
+
# ENV AGENTEXEC_WORKER_MODULE=src.worker
|
|
10
|
+
#
|
|
11
|
+
# Required environment variables at runtime:
|
|
12
|
+
# DATABASE_URL - Database connection URL (e.g., postgresql://...)
|
|
13
|
+
# REDIS_URL - Redis connection URL (e.g., redis://...)
|
|
14
|
+
# AGENTEXEC_WORKER_MODULE - Python module path with pool definition
|
|
15
|
+
#
|
|
16
|
+
# Optional environment variables:
|
|
17
|
+
# OPENAI_API_KEY - Required if using OpenAI agents
|
|
18
|
+
# AGENTEXEC_NUM_WORKERS - Number of worker processes (default: 4)
|
|
19
|
+
# AGENTEXEC_QUEUE_NAME - Redis queue name (default: agentexec_tasks)
|
|
20
|
+
|
|
21
|
+
FROM python:3.11-slim AS base
|
|
22
|
+
|
|
23
|
+
# Prevent Python from writing pyc files and buffering stdout/stderr
|
|
24
|
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
25
|
+
PYTHONUNBUFFERED=1 \
|
|
26
|
+
# Ensure Python can find modules in /app
|
|
27
|
+
PYTHONPATH=/app
|
|
28
|
+
|
|
29
|
+
WORKDIR /app
|
|
30
|
+
|
|
31
|
+
# Install system dependencies for database drivers
|
|
32
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
33
|
+
# PostgreSQL client library (for psycopg2)
|
|
34
|
+
libpq5 \
|
|
35
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
36
|
+
|
|
37
|
+
# Build stage for compiling dependencies
|
|
38
|
+
FROM base AS builder
|
|
39
|
+
|
|
40
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
41
|
+
# Build tools
|
|
42
|
+
gcc \
|
|
43
|
+
# PostgreSQL dev headers (for psycopg2)
|
|
44
|
+
libpq-dev \
|
|
45
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
46
|
+
|
|
47
|
+
# Install pip dependencies
|
|
48
|
+
RUN pip install --no-cache-dir --upgrade pip
|
|
49
|
+
|
|
50
|
+
# Install agentexec with common database drivers
|
|
51
|
+
# Users can extend with additional drivers as needed
|
|
52
|
+
RUN pip install --no-cache-dir \
|
|
53
|
+
agentexec \
|
|
54
|
+
psycopg2-binary \
|
|
55
|
+
# For async PostgreSQL (optional, commonly used)
|
|
56
|
+
asyncpg
|
|
57
|
+
|
|
58
|
+
# Final stage
|
|
59
|
+
FROM base AS runtime
|
|
60
|
+
|
|
61
|
+
# Copy installed packages from builder
|
|
62
|
+
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
|
|
63
|
+
COPY --from=builder /usr/local/bin /usr/local/bin
|
|
64
|
+
|
|
65
|
+
# Copy entrypoint script
|
|
66
|
+
COPY entrypoint.py /app/entrypoint.py
|
|
67
|
+
|
|
68
|
+
# Create non-root user for security
|
|
69
|
+
RUN useradd --create-home --shell /bin/bash worker
|
|
70
|
+
USER worker
|
|
71
|
+
|
|
72
|
+
# Health check - verify Python and agentexec are available
|
|
73
|
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
|
74
|
+
CMD python -c "import agentexec" || exit 1
|
|
75
|
+
|
|
76
|
+
# Default command runs the worker entrypoint
|
|
77
|
+
ENTRYPOINT ["python", "/app/entrypoint.py"]
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# agentexec-worker Docker Image
|
|
2
|
+
|
|
3
|
+
Base Docker image for deploying agentexec workers.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### 1. Create your worker module
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
# src/worker.py
|
|
11
|
+
import os
|
|
12
|
+
import agentexec as ax
|
|
13
|
+
|
|
14
|
+
pool = ax.WorkerPool(database_url=os.environ["DATABASE_URL"])
|
|
15
|
+
|
|
16
|
+
@pool.task("my_task")
|
|
17
|
+
async def my_task(agent_id, context):
|
|
18
|
+
# Your task implementation
|
|
19
|
+
pass
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 2. Create your Dockerfile
|
|
23
|
+
|
|
24
|
+
```dockerfile
|
|
25
|
+
FROM ghcr.io/agent-ci/agentexec-worker:latest
|
|
26
|
+
|
|
27
|
+
# Copy your application code
|
|
28
|
+
COPY ./src /app/src
|
|
29
|
+
|
|
30
|
+
# Point to your worker module
|
|
31
|
+
ENV AGENTEXEC_WORKER_MODULE=src.worker
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 3. Build and run
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Build your image
|
|
38
|
+
docker build -t my-worker .
|
|
39
|
+
|
|
40
|
+
# Run with required environment variables
|
|
41
|
+
docker run \
|
|
42
|
+
-e DATABASE_URL=postgresql://user:pass@host:5432/db \
|
|
43
|
+
-e REDIS_URL=redis://host:6379 \
|
|
44
|
+
-e OPENAI_API_KEY=sk-... \
|
|
45
|
+
my-worker
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Environment Variables
|
|
49
|
+
|
|
50
|
+
### Required
|
|
51
|
+
|
|
52
|
+
| Variable | Description |
|
|
53
|
+
|----------|-------------|
|
|
54
|
+
| `DATABASE_URL` | Database connection URL |
|
|
55
|
+
| `REDIS_URL` | Redis connection URL |
|
|
56
|
+
| `AGENTEXEC_WORKER_MODULE` | Python module path containing `pool` |
|
|
57
|
+
|
|
58
|
+
### Optional
|
|
59
|
+
|
|
60
|
+
| Variable | Default | Description |
|
|
61
|
+
|----------|---------|-------------|
|
|
62
|
+
| `OPENAI_API_KEY` | - | Required if using OpenAI agents |
|
|
63
|
+
| `AGENTEXEC_NUM_WORKERS` | 4 | Number of worker processes |
|
|
64
|
+
| `AGENTEXEC_QUEUE_NAME` | agentexec_tasks | Redis queue name |
|
|
65
|
+
| `AGENTEXEC_GRACEFUL_SHUTDOWN_TIMEOUT` | 300 | Shutdown timeout (seconds) |
|
|
66
|
+
| `AGENTEXEC_RESULT_TTL` | 3600 | Task result TTL (seconds) |
|
|
67
|
+
|
|
68
|
+
## Worker Module Requirements
|
|
69
|
+
|
|
70
|
+
Your worker module must expose either:
|
|
71
|
+
|
|
72
|
+
1. A `pool` variable (recommended):
|
|
73
|
+
```python
|
|
74
|
+
pool = ax.WorkerPool(database_url=os.environ["DATABASE_URL"])
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
2. Or a `create_pool()` function:
|
|
78
|
+
```python
|
|
79
|
+
def create_pool():
|
|
80
|
+
return ax.WorkerPool(database_url=os.environ["DATABASE_URL"])
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Docker Compose Example
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
version: '3.8'
|
|
87
|
+
|
|
88
|
+
services:
|
|
89
|
+
worker:
|
|
90
|
+
build: .
|
|
91
|
+
environment:
|
|
92
|
+
- DATABASE_URL=postgresql://postgres:postgres@db:5432/app
|
|
93
|
+
- REDIS_URL=redis://redis:6379
|
|
94
|
+
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
|
95
|
+
- AGENTEXEC_NUM_WORKERS=2
|
|
96
|
+
depends_on:
|
|
97
|
+
- db
|
|
98
|
+
- redis
|
|
99
|
+
|
|
100
|
+
db:
|
|
101
|
+
image: postgres:15
|
|
102
|
+
environment:
|
|
103
|
+
POSTGRES_PASSWORD: postgres
|
|
104
|
+
POSTGRES_DB: app
|
|
105
|
+
|
|
106
|
+
redis:
|
|
107
|
+
image: redis:7-alpine
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Extending the Image
|
|
111
|
+
|
|
112
|
+
### Adding Python dependencies
|
|
113
|
+
|
|
114
|
+
```dockerfile
|
|
115
|
+
FROM ghcr.io/agent-ci/agentexec-worker:latest
|
|
116
|
+
|
|
117
|
+
# Install additional packages
|
|
118
|
+
RUN pip install --no-cache-dir \
|
|
119
|
+
httpx \
|
|
120
|
+
beautifulsoup4
|
|
121
|
+
|
|
122
|
+
COPY ./src /app/src
|
|
123
|
+
ENV AGENTEXEC_WORKER_MODULE=src.worker
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Using a different database
|
|
127
|
+
|
|
128
|
+
The base image includes `psycopg2-binary` for PostgreSQL. For other databases:
|
|
129
|
+
|
|
130
|
+
```dockerfile
|
|
131
|
+
FROM ghcr.io/agent-ci/agentexec-worker:latest
|
|
132
|
+
|
|
133
|
+
# For MySQL
|
|
134
|
+
RUN pip install --no-cache-dir mysqlclient
|
|
135
|
+
|
|
136
|
+
# For SQLite (included in Python stdlib, but you may want async driver)
|
|
137
|
+
RUN pip install --no-cache-dir aiosqlite
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Building Locally
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
cd docker
|
|
144
|
+
docker build -t agentexec-worker .
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Multi-Architecture Support
|
|
148
|
+
|
|
149
|
+
The published image supports both `linux/amd64` and `linux/arm64` architectures.
|