agentexec 0.1.0__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.
Files changed (38) hide show
  1. agentexec-0.1.0/.github/workflows/publish.yml +31 -0
  2. agentexec-0.1.0/.gitignore +63 -0
  3. agentexec-0.1.0/PKG-INFO +370 -0
  4. agentexec-0.1.0/README.md +345 -0
  5. agentexec-0.1.0/examples/fastapi-app/worker.py +84 -0
  6. agentexec-0.1.0/examples/openai-agents-fastapi/README.md +103 -0
  7. agentexec-0.1.0/examples/openai-agents-fastapi/alembic/README +1 -0
  8. agentexec-0.1.0/examples/openai-agents-fastapi/alembic/env.py +82 -0
  9. agentexec-0.1.0/examples/openai-agents-fastapi/alembic/script.py.mako +28 -0
  10. agentexec-0.1.0/examples/openai-agents-fastapi/alembic.ini +148 -0
  11. agentexec-0.1.0/examples/openai-agents-fastapi/main.py +77 -0
  12. agentexec-0.1.0/examples/openai-agents-fastapi/models.py +9 -0
  13. agentexec-0.1.0/examples/openai-agents-fastapi/pyproject.toml +30 -0
  14. agentexec-0.1.0/examples/openai-agents-fastapi/tools.py +46 -0
  15. agentexec-0.1.0/examples/openai-agents-fastapi/views.py +83 -0
  16. agentexec-0.1.0/examples/openai-agents-fastapi/worker.py +84 -0
  17. agentexec-0.1.0/pyproject.toml +70 -0
  18. agentexec-0.1.0/src/agentexec/__init__.py +73 -0
  19. agentexec-0.1.0/src/agentexec/activity/__init__.py +50 -0
  20. agentexec-0.1.0/src/agentexec/activity/models.py +294 -0
  21. agentexec-0.1.0/src/agentexec/activity/schemas.py +70 -0
  22. agentexec-0.1.0/src/agentexec/activity/tracker.py +267 -0
  23. agentexec-0.1.0/src/agentexec/config.py +72 -0
  24. agentexec-0.1.0/src/agentexec/core/__init__.py +0 -0
  25. agentexec-0.1.0/src/agentexec/core/models.py +23 -0
  26. agentexec-0.1.0/src/agentexec/core/queue.py +109 -0
  27. agentexec-0.1.0/src/agentexec/core/redis_client.py +40 -0
  28. agentexec-0.1.0/src/agentexec/core/task.py +132 -0
  29. agentexec-0.1.0/src/agentexec/core/worker.py +304 -0
  30. agentexec-0.1.0/src/agentexec/runners/__init__.py +13 -0
  31. agentexec-0.1.0/src/agentexec/runners/base.py +135 -0
  32. agentexec-0.1.0/src/agentexec/runners/openai.py +237 -0
  33. agentexec-0.1.0/tests/test_activity_tracking.py +89 -0
  34. agentexec-0.1.0/tests/test_activity_tracking.py.bak +427 -0
  35. agentexec-0.1.0/tests/test_public_api.py +99 -0
  36. agentexec-0.1.0/tests/test_redis_client.py +58 -0
  37. agentexec-0.1.0/tests/test_task.py +111 -0
  38. agentexec-0.1.0/tests/test_worker_pool.py +102 -0
@@ -0,0 +1,31 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ publish:
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v5
19
+ with:
20
+ enable-cache: true
21
+
22
+ - name: Set up Python
23
+ run: uv python install
24
+
25
+ - name: Build package
26
+ run: uv build
27
+
28
+ - name: Publish to PyPI
29
+ env:
30
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
31
+ run: uv publish
@@ -0,0 +1,63 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+
8
+ # Virtual environments
9
+ .venv/
10
+ venv/
11
+ ENV/
12
+ env/
13
+
14
+ # uv
15
+ .uv/
16
+ uv.lock
17
+
18
+ # pytest
19
+ .pytest_cache/
20
+ .coverage
21
+ htmlcov/
22
+ .tox/
23
+
24
+ # mypy
25
+ .mypy_cache/
26
+ .dmypy.json
27
+ dmypy.json
28
+
29
+ # ruff
30
+ .ruff_cache/
31
+
32
+ # IDEs
33
+ .vscode/
34
+ .idea/
35
+ *.swp
36
+ *.swo
37
+ *~
38
+
39
+ # OS
40
+ .DS_Store
41
+ Thumbs.db
42
+
43
+ # Database files
44
+ *.db
45
+ *.sqlite
46
+ *.sqlite3
47
+
48
+ # Build artifacts
49
+ build/
50
+ dist/
51
+ *.egg-info/
52
+ *.egg
53
+
54
+ # Environment variables
55
+ .env
56
+ .env.local
57
+
58
+ # Logs
59
+ *.log
60
+
61
+ # Project specific
62
+ agents.db
63
+ examples/fastapi-app/.env
@@ -0,0 +1,370 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentexec
3
+ Version: 0.1.0
4
+ Summary: Production-ready orchestration for OpenAI Agents with Redis-backed coordination, activity tracking, and workflow management
5
+ Project-URL: Homepage, https://github.com/Agent-CI/agentexec
6
+ Project-URL: Documentation, https://github.com/Agent-CI/agentexec#readme
7
+ Project-URL: Repository, https://github.com/Agent-CI/agentexec
8
+ Project-URL: Issues, https://github.com/Agent-CI/agentexec/issues
9
+ Author-email: Agent CI <hello@agentci.com>, Travis Dent <root@a10k.co>
10
+ License: MIT
11
+ Keywords: agents,async,background-workers,openai,orchestration,redis
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Requires-Python: >=3.11
19
+ Requires-Dist: openai-agents>=0.1.0
20
+ Requires-Dist: pydantic-settings>=2.5.0
21
+ Requires-Dist: pydantic>=2.12.0
22
+ Requires-Dist: redis>=7.0.1
23
+ Requires-Dist: sqlalchemy>=2.0.44
24
+ Description-Content-Type: text/markdown
25
+
26
+ # `agentexec`
27
+
28
+ **Production-ready orchestration for OpenAI Agents SDK** with Redis-backed task queues, SQLAlchemy activity tracking, and multiprocessing worker pools.
29
+
30
+ Build reliable, scalable AI agent applications with automatic lifecycle management, progress tracking, and fault tolerance.
31
+
32
+ Running AI agents in production requires more than just the SDK. You need:
33
+
34
+ - **Background execution** - Agents can take minutes to complete; users shouldn't wait
35
+ - **Progress tracking** - Know what your agents are doing and when they finish
36
+ - **Fault tolerance** - Handle failures gracefully with automatic error tracking
37
+ - **Scalability** - Process multiple agent tasks concurrently across worker processes
38
+ - **Observability** - Full audit trail of agent activities and status updates
39
+
40
+ `agentexec` provides all of this out of the box, with a simple API that integrates seamlessly with the OpenAI Agents SDK (and the extensibility to continue adding support for other frameworks).
41
+
42
+ ---
43
+
44
+ ## Features
45
+
46
+ - **Multi-process worker pool** - True parallelism for concurrent agent execution
47
+ - **Redis task queue** - Reliable job distribution with priority support
48
+ - **Automatic activity tracking** - Full lifecycle management (QUEUED → RUNNING → COMPLETE/ERROR)
49
+ - **OpenAI Agents integration** - Drop-in runner with max turns recovery
50
+ - **Agent self-reporting** - Built-in tools for agents to report progress
51
+ - **SQLAlchemy-based storage** - Flexible database support (PostgreSQL, MySQL, SQLite)
52
+ - **Type-safe** - Full type annotations with Pydantic schemas
53
+ - **Production-ready** - Graceful shutdown, error handling, configurable timeouts
54
+
55
+ ---
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ uv add agentexec
61
+ ```
62
+
63
+ **Requirements:**
64
+ - Python 3.11+
65
+ - Redis (for task queue)
66
+ - SQLAlchemy-compatible database (for activity tracking)
67
+ - Agents that you want to parallelize!
68
+
69
+ ---
70
+
71
+ ## Quick Start
72
+
73
+ ### 1. Set Up Your Worker
74
+
75
+ ```python
76
+ import agentexec as ax
77
+ from agents import Agent
78
+ from sqlalchemy import Session, create_engine
79
+
80
+ # database for activity tracking (share with your app)
81
+ engine = create_engine("sqlite:///agents.db")
82
+
83
+ # create worker pool
84
+ pool = ax.WorkerPool(engine=engine)
85
+
86
+ @pool.task("research_company")
87
+ async def research_company(agent_id: UUID, payload: dict) -> None:
88
+ """Background task that runs an AI agent."""
89
+ runner = ax.OpenAIRunner(
90
+ agent_id=agent_id,
91
+ max_turns_recovery=True,
92
+ )
93
+
94
+ agent = Agent(
95
+ name="Research Agent",
96
+ instructions=(
97
+ f"Research {payload['company']}.\n"
98
+ "\n"
99
+ f"{runner.prompts.report_status}"
100
+ ),
101
+ tools=[
102
+ runner.tools.report_status,
103
+ ],
104
+ model="gpt-5.1",
105
+ )
106
+
107
+ result = await runner.run(
108
+ agent,
109
+ input="Start research",
110
+ max_turns=15,
111
+ )
112
+ print(f"Done! {result.final_output}")
113
+
114
+ if __name__ == "__main__":
115
+ pool.start() # start workers
116
+ ```
117
+
118
+ ### 2. Queue Tasks from Your Application
119
+
120
+ ```python
121
+ import agentexec as ax
122
+
123
+ # enqueue a task (from your API, web app, etc.)
124
+ task = ax.enqueue(
125
+ "research_company",
126
+ {"company": "Anthropic"},
127
+ )
128
+
129
+ print(f"Task queued: {task.agent_id}")
130
+ ```
131
+
132
+ ### 3. Track Progress
133
+
134
+ ```python
135
+ with Session(engine) as db:
136
+ # list recent activities
137
+ activities = ax.activity.list(db, page=1, page_size=10)
138
+ for activity in activities:
139
+ print(f"Agent {activity.agent_id} - Status: {activity.status}")
140
+
141
+ # get activity with full log history
142
+ activity = ax.activity.detail(db, agent_id=task.agent_id)
143
+ print(f"Activity for {activity.agent_id}:")
144
+ for log in activity.logs:
145
+ print(f" - {log.created_at}: {log.message} ({log.status})")
146
+ ```
147
+
148
+ ---
149
+
150
+ ## What You Get
151
+
152
+ ### Automatic Activity Tracking
153
+
154
+ Every task gets full lifecycle tracking without manual updates:
155
+
156
+ ```python
157
+ runner = ax.OpenAIRunner(agent_id=agent_id)
158
+ result = await runner.run(agent, input="...")
159
+
160
+ # Activity automatically transitions:
161
+ # QUEUED → RUNNING → COMPLETE (or ERROR on failure)
162
+ ```
163
+
164
+ ### Agent Self-Reporting
165
+
166
+ Agents can report their own progress using a built-in tool:
167
+
168
+ ```python
169
+ agent = Agent(
170
+ instructions=f"Do research. {runner.prompts.report_status}",
171
+ tools=[runner.tools.report_status], # Agent can call this
172
+ )
173
+
174
+ # Agent will report: "Gathering data" (40%), "Analyzing results" (80%), etc.
175
+ ```
176
+
177
+ ### Max Turns Recovery
178
+
179
+ Automatically handle conversation limits with graceful wrap-up:
180
+
181
+ ```python
182
+ runner = ax.OpenAIRunner(
183
+ agent_id=agent_id,
184
+ max_turns_recovery=True,
185
+ wrap_up_prompt="Please summarize your findings.",
186
+ )
187
+
188
+ # If agent hits max turns, runner automatically:
189
+ # 1. Catches MaxTurnsExceeded
190
+ # 2. Continues with wrap-up prompt
191
+ # 3. Returns final result
192
+ ```
193
+
194
+ ### Priority Queue
195
+
196
+ Control task execution order:
197
+
198
+ ```python
199
+ # High priority - processed first
200
+ ax.enqueue("urgent_task", payload, priority=ax.Priority.HIGH)
201
+
202
+ # Low priority - processed later
203
+ ax.enqueue("batch_job", payload, priority=ax.Priority.LOW)
204
+ ```
205
+
206
+ ---
207
+
208
+ ## Full Example: FastAPI Integration
209
+
210
+ See **[examples/openai-agents-fastapi/](examples/openai-agents-fastapi/)** for a complete production application showing:
211
+
212
+ - Background worker pool with task handlers
213
+ - FastAPI routes for queueing tasks and checking status
214
+ - Database session management with SQLAlchemy
215
+ - Custom agents with function tools
216
+ - Real-time progress monitoring
217
+ - Graceful shutdown with cleanup
218
+
219
+ ---
220
+
221
+ ## Configuration
222
+
223
+ Configure via environment variables or `.env` file:
224
+
225
+ ```bash
226
+ # Worker settings
227
+ AGENTEXEC_NUM_WORKERS=4
228
+
229
+ # Redis settings
230
+ AGENTEXEC_REDIS_URL=redis://localhost:6379/0
231
+ AGENTEXEC_QUEUE_NAME=agentexec:tasks
232
+
233
+ # Database table prefix
234
+ AGENTEXEC_TABLE_PREFIX=agentexec_
235
+ ```
236
+ ---
237
+
238
+ ## Public API
239
+
240
+ ### Task Queue
241
+
242
+ ```python
243
+ # Enqueue task
244
+ task = ax.enqueue(task_name, payload, priority=ax.Priority.LOW)
245
+ ```
246
+
247
+ ### Activity Tracking
248
+
249
+ ```python
250
+ # Query activities
251
+ activities = ax.activity.list(session, page=1, page_size=50)
252
+ activity = ax.activity.detail(session, agent_id)
253
+
254
+ ```
255
+
256
+ ### Worker Pool
257
+
258
+ ```python
259
+ pool = ax.WorkerPool(engine=engine)
260
+
261
+ @pool.task("task_name")
262
+ async def handler(agent_id: UUID, payload: dict) -> None:
263
+ # Task implementation
264
+ pass
265
+
266
+ pool.start() # Start worker processes
267
+ ```
268
+
269
+ ### OpenAI Runner
270
+
271
+ ```python
272
+ runner = ax.OpenAIRunner(
273
+ agent_id=agent_id,
274
+ max_turns_recovery=True,
275
+ wrap_up_prompt="Summarize...",
276
+ )
277
+
278
+ # Run agent
279
+ result = await runner.run(agent, input="...", max_turns=15)
280
+
281
+ # Streaming
282
+ result = await runner.run_streamed(agent, input="...", max_turns=15)
283
+ ```
284
+
285
+ ---
286
+
287
+ ## Architecture
288
+
289
+ ```
290
+ ┌─────────────┐ ┌──────────┐ ┌─────────────┐
291
+ │ Your │────────>│ Redis │<────────│ Worker │
292
+ │ Application │ enqueue │ Queue │ dequeue │ Pool │
293
+ └─────────────┘ └──────────┘ └─────────────┘
294
+ │ │
295
+ │ Runner │
296
+ │ (+ Activity Tracking) │
297
+ v v
298
+ ┌─────────────────────────────────────────────────────────-┐
299
+ │ SQLAlchemy Database │
300
+ │ (Activities, Logs, Progress) │
301
+ └─────────────────────────────────────────────────────────-┘
302
+ ```
303
+
304
+ **Flow:**
305
+ 1. Application enqueues task → Activity created (QUEUED)
306
+ 2. Worker dequeues task → Executes with OpenAIRunner
307
+ 3. Runner updates activity → RUNNING
308
+ 4. Agent reports progress → Log entries created
309
+ 5. Task completes → Activity marked COMPLETE/ERROR
310
+
311
+ ---
312
+
313
+ ## Database Models
314
+
315
+ AgentExec creates two tables (prefix configurable):
316
+
317
+ **`agentexec_activity`** - Main activity records
318
+ - `id` - Primary key (UUID)
319
+ - `agent_id` - Unique agent identifier (UUID)
320
+ - `agent_type` - Task name/type
321
+ - `created_at` - When activity was created
322
+ - `updated_at` - Last update timestamp
323
+
324
+ **`agentexec_activity_log`** - Status and progress logs
325
+ - `id` - Primary key (UUID)
326
+ - `activity_id` - Foreign key to activity
327
+ - `message` - Log message
328
+ - `status` - QUEUED, RUNNING, COMPLETE, ERROR, CANCELED
329
+ - `completion_percentage` - Progress (0-100)
330
+ - `created_at` - When log was created
331
+
332
+ ---
333
+
334
+ ## Development
335
+
336
+ ```bash
337
+ # Clone repository
338
+ git clone https://github.com/Agent-CI/agentexec
339
+ cd agentexec
340
+
341
+ # Install dependencies
342
+ uv sync
343
+
344
+ # Run tests
345
+ uv run pytest
346
+
347
+ # Type checking
348
+ uv run mypy src/agentexec
349
+
350
+ # Linting
351
+ uv run ruff check src/
352
+
353
+ # Formatting
354
+ uv run ruff format src/
355
+ ```
356
+
357
+
358
+
359
+ ## License
360
+
361
+ MIT License - see [LICENSE](LICENSE) for details
362
+
363
+ ---
364
+
365
+ ## Links
366
+
367
+ - **Documentation**: See example application in `examples/openai-agents-fastapi/`
368
+ - **Issues**: [GitHub Issues](https://github.com/Agent-CI/agentexec/issues)
369
+ - **PyPI**: [agentexec](https://pypi.org/project/agentexec/)
370
+