python-base-agent 2026.2.13__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.
- python_base_agent-2026.2.13/PKG-INFO +536 -0
- python_base_agent-2026.2.13/README.md +470 -0
- python_base_agent-2026.2.13/pyproject.toml +210 -0
- python_base_agent-2026.2.13/setup.cfg +4 -0
- python_base_agent-2026.2.13/src/base_agent/__init__.py +49 -0
- python_base_agent-2026.2.13/src/base_agent/agent.py +1060 -0
- python_base_agent-2026.2.13/src/base_agent/config.py +220 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/__init__.py +209 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/access_control_summary_part.py +42 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/agent_loop_part.py +87 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/agent_tool_part.py +15 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/append_entity_class_part.py +15 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/broadcast_message.py +30 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/broadcast_message_type.py +13 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/cache_stability_metadata.py +27 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/code_generation.py +18 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/context_management_notification.py +20 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/context_management_pipeline.py +21 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/cross_vector_similarity_search_request.py +14 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/data_classification_tag.py +12 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/data_lineage_part.py +46 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/data_part.py +15 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/data_pointer_part.py +20 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/embedding_request.py +15 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/embedding_response.py +21 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/entity_matching_form_data.py +79 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/entity_vector_text_search_match.py +12 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/entity_vector_text_search_request.py +14 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/entity_vector_text_search_result.py +24 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/entity_vectorization_job_info.py +24 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/entity_vectorization_jobs_result.py +30 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/entity_vectorization_progress.py +14 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/entity_vectorization_request.py +15 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/entity_vectorization_result.py +17 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/envelope.py +20 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/error_part.py +24 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/error_part_type.py +14 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/file_part.py +17 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/file_pointer_part.py +17 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/file_revectorization_request_event.py +19 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/file_vectorization_request_event.py +22 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/for_each_part.py +30 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/fuzzy_matching_params.py +21 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/group_plan.py +16 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/header.py +69 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/human_input_request.py +16 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/inspector_pipeline_item.py +19 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/list_entity_vectorization_jobs_request.py +12 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/llm_accounting_part.py +33 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/llm_error_notification.py +13 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/llm_judge_job.py +84 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/llm_judge_params.py +15 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/llm_judge_progress.py +20 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/llm_model_part.py +72 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/llm_reasoning_summary.py +23 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/llm_response.py +25 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/llm_response_part.py +54 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/match_entities_job.py +43 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/match_result.py +52 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/notification_error_type.py +12 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/notification_severity.py +14 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/on_trigger_fired.py +17 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/parallel_execution_plan.py +25 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/part.py +30 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/resume_entity_vectorization_request.py +11 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/room_dataset_catalog.py +44 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/room_dataset_catalog_entry.py +38 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/room_dataset_column.py +12 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/room_dataset_schema.py +24 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/scratch_pad_content.py +14 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/search_request.py +27 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/search_response.py +39 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/search_result.py +21 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/search_type_result.py +13 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/semantic_search_progress.py +18 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/semantic_search_result.py +25 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/stream_content_message.py +35 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/stream_event_type.py +12 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/stream_message.py +14 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/stream_metadata.py +28 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/task_artifact_update.py +20 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/task_error_response.py +22 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/task_ref.py +19 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/task_request.py +21 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/task_response.py +21 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/task_status_update.py +31 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/text_part.py +15 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/tool_authorization_request.py +21 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/tool_call_index.py +42 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/tool_call_index_entry.py +32 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/tool_call_initiation.py +27 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/tool_learning_request.py +34 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/tool_response_completion.py +19 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/tool_response_part.py +31 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/usage_metadata.py +11 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/user_data_notification.py +13 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/user_notification.py +21 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/vector_similarity_search_request.py +13 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/vector_similarity_search_result.py +25 -0
- python_base_agent-2026.2.13/src/base_agent/contracts/workflow_part.py +17 -0
- python_base_agent-2026.2.13/src/base_agent/exceptions.py +39 -0
- python_base_agent-2026.2.13/src/base_agent/health/__init__.py +5 -0
- python_base_agent-2026.2.13/src/base_agent/health/server.py +191 -0
- python_base_agent-2026.2.13/src/base_agent/messaging/__init__.py +5 -0
- python_base_agent-2026.2.13/src/base_agent/messaging/kafka_client.py +572 -0
- python_base_agent-2026.2.13/src/base_agent/ordering/__init__.py +5 -0
- python_base_agent-2026.2.13/src/base_agent/ordering/vector_clock.py +176 -0
- python_base_agent-2026.2.13/src/base_agent/prompts/__init__.py +10 -0
- python_base_agent-2026.2.13/src/base_agent/prompts/prompt_manager.py +213 -0
- python_base_agent-2026.2.13/src/base_agent/registration/__init__.py +5 -0
- python_base_agent-2026.2.13/src/base_agent/registration/registration_client.py +364 -0
- python_base_agent-2026.2.13/src/base_agent/schemas/__init__.py +14 -0
- python_base_agent-2026.2.13/src/base_agent/schemas/models.py +30 -0
- python_base_agent-2026.2.13/src/base_agent/schemas/schema_registry_client.py +493 -0
- python_base_agent-2026.2.13/src/base_agent/schemas/source_type.py +24 -0
- python_base_agent-2026.2.13/src/base_agent/schemas/technical_name_validator.py +147 -0
- python_base_agent-2026.2.13/src/base_agent/state/__init__.py +13 -0
- python_base_agent-2026.2.13/src/base_agent/state/logical_clock_tracker.py +50 -0
- python_base_agent-2026.2.13/src/base_agent/state/session_tracker.py +91 -0
- python_base_agent-2026.2.13/src/base_agent/state/store.py +333 -0
- python_base_agent-2026.2.13/src/base_agent/storage/__init__.py +27 -0
- python_base_agent-2026.2.13/src/base_agent/storage/azure_store.py +615 -0
- python_base_agent-2026.2.13/src/base_agent/storage/exceptions.py +26 -0
- python_base_agent-2026.2.13/src/base_agent/storage/models.py +73 -0
- python_base_agent-2026.2.13/src/base_agent/storage/object_store.py +248 -0
- python_base_agent-2026.2.13/src/base_agent/storage/object_store_factory.py +136 -0
- python_base_agent-2026.2.13/src/base_agent/storage/s3_store.py +411 -0
- python_base_agent-2026.2.13/src/base_agent/telemetry/__init__.py +1 -0
- python_base_agent-2026.2.13/src/base_agent/tools/__init__.py +12 -0
- python_base_agent-2026.2.13/src/base_agent/tools/models.py +66 -0
- python_base_agent-2026.2.13/src/base_agent/tools/tool_registry_client.py +607 -0
- python_base_agent-2026.2.13/src/base_agent/utils/__init__.py +5 -0
- python_base_agent-2026.2.13/src/base_agent/utils/logger.py +146 -0
- python_base_agent-2026.2.13/src/base_agent/utils/version_utils.py +92 -0
- python_base_agent-2026.2.13/src/python_base_agent.egg-info/PKG-INFO +536 -0
- python_base_agent-2026.2.13/src/python_base_agent.egg-info/SOURCES.txt +137 -0
- python_base_agent-2026.2.13/src/python_base_agent.egg-info/dependency_links.txt +1 -0
- python_base_agent-2026.2.13/src/python_base_agent.egg-info/requires.txt +57 -0
- python_base_agent-2026.2.13/src/python_base_agent.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-base-agent
|
|
3
|
+
Version: 2026.2.13
|
|
4
|
+
Summary: Python implementation of BaseAgent for distributed message processing
|
|
5
|
+
Author-email: AI One Platform Team <platform@ai.one>
|
|
6
|
+
Classifier: Development Status :: 3 - Alpha
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
10
|
+
Requires-Python: >=3.12
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: confluent-kafka>=2.3.0
|
|
13
|
+
Requires-Dist: pydantic>=2.11.0
|
|
14
|
+
Requires-Dist: pydantic-settings>=2.8.0
|
|
15
|
+
Requires-Dist: python-dotenv>=1.1.0
|
|
16
|
+
Requires-Dist: redis>=6.4.0
|
|
17
|
+
Requires-Dist: asyncpg>=0.30.0
|
|
18
|
+
Requires-Dist: boto3>=1.35.0
|
|
19
|
+
Requires-Dist: aioboto3>=13.0.0
|
|
20
|
+
Requires-Dist: azure-storage-blob>=12.23.0
|
|
21
|
+
Requires-Dist: azure-identity>=1.18.0
|
|
22
|
+
Requires-Dist: aiohttp>=3.13.3
|
|
23
|
+
Requires-Dist: fastapi>=0.116.0
|
|
24
|
+
Requires-Dist: starlette>=0.49.1
|
|
25
|
+
Requires-Dist: uvicorn>=0.35.0
|
|
26
|
+
Requires-Dist: opentelemetry-api>=1.36.0
|
|
27
|
+
Requires-Dist: opentelemetry-sdk>=1.36.0
|
|
28
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.36.0
|
|
29
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.55b1
|
|
30
|
+
Requires-Dist: opentelemetry-instrumentation-redis>=0.55b1
|
|
31
|
+
Requires-Dist: opentelemetry-propagator-b3>=1.36.0
|
|
32
|
+
Requires-Dist: prometheus-client>=0.21.0
|
|
33
|
+
Requires-Dist: httpx>=0.28.0
|
|
34
|
+
Requires-Dist: structlog>=25.1.0
|
|
35
|
+
Requires-Dist: croniter>=6.0.0
|
|
36
|
+
Requires-Dist: psutil>=6.0.0
|
|
37
|
+
Requires-Dist: datamodel-code-generator>=0.33.0
|
|
38
|
+
Requires-Dist: urllib3>=2.6.3
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: pytest>=8.4.0; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-asyncio>=1.1.0; extra == "dev"
|
|
42
|
+
Requires-Dist: pytest-cov>=6.0.0; extra == "dev"
|
|
43
|
+
Requires-Dist: pytest-mock>=3.14.0; extra == "dev"
|
|
44
|
+
Requires-Dist: pytest-timeout>=2.3.0; extra == "dev"
|
|
45
|
+
Requires-Dist: pytest-xdist>=3.6.0; extra == "dev"
|
|
46
|
+
Requires-Dist: testcontainers>=4.12.0; extra == "dev"
|
|
47
|
+
Requires-Dist: testcontainers[kafka]>=4.12.0; extra == "dev"
|
|
48
|
+
Requires-Dist: testcontainers[redis]>=4.12.0; extra == "dev"
|
|
49
|
+
Requires-Dist: testcontainers[minio]>=4.12.0; extra == "dev"
|
|
50
|
+
Requires-Dist: testcontainers[azurite]>=4.12.0; extra == "dev"
|
|
51
|
+
Requires-Dist: black>=25.1.0; extra == "dev"
|
|
52
|
+
Requires-Dist: isort>=5.13.0; extra == "dev"
|
|
53
|
+
Requires-Dist: mypy>=1.13.0; extra == "dev"
|
|
54
|
+
Requires-Dist: ruff>=0.9.0; extra == "dev"
|
|
55
|
+
Requires-Dist: pre-commit>=4.0.0; extra == "dev"
|
|
56
|
+
Requires-Dist: types-redis>=4.6.0; extra == "dev"
|
|
57
|
+
Requires-Dist: boto3-stubs[s3]>=1.40.0; extra == "dev"
|
|
58
|
+
Requires-Dist: datamodel-code-generator>=0.33.0; extra == "dev"
|
|
59
|
+
Provides-Extra: publish
|
|
60
|
+
Requires-Dist: build>=1.0.0; extra == "publish"
|
|
61
|
+
Requires-Dist: twine>=6.0.0; extra == "publish"
|
|
62
|
+
Provides-Extra: docs
|
|
63
|
+
Requires-Dist: sphinx>=8.2.0; extra == "docs"
|
|
64
|
+
Requires-Dist: sphinx-rtd-theme>=3.0.0; extra == "docs"
|
|
65
|
+
Requires-Dist: sphinx-autodoc-typehints>=2.5.0; extra == "docs"
|
|
66
|
+
|
|
67
|
+
# Python BaseAgent
|
|
68
|
+
|
|
69
|
+
Python implementation of the BaseAgent framework for building distributed message processing agents with exactly-once semantics.
|
|
70
|
+
|
|
71
|
+
## Overview
|
|
72
|
+
|
|
73
|
+
BaseAgent provides a robust foundation for building agents that:
|
|
74
|
+
- Process messages from Kafka with exactly-once semantics
|
|
75
|
+
- Manage state with pluggable storage backends (Redis/Memory)
|
|
76
|
+
- Store large payloads in object storage (S3/MinIO)
|
|
77
|
+
- Provide health checks for Kubernetes deployments
|
|
78
|
+
- Include distributed tracing with OpenTelemetry
|
|
79
|
+
- Handle deduplication with vector clocks
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
The platform uses `mise` for task management and `uv` for Python dependency management:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Using mise tasks (recommended - platform convention)
|
|
87
|
+
mise run base-agent-install
|
|
88
|
+
|
|
89
|
+
# Or manually with uv
|
|
90
|
+
uv pip install -e ".[dev]"
|
|
91
|
+
|
|
92
|
+
# Or with pip
|
|
93
|
+
pip install -e ".[dev]"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Quick Start
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from base_agent import BaseAgent, AgentConfig, Envelope
|
|
100
|
+
|
|
101
|
+
class WordCountAgent(BaseAgent):
|
|
102
|
+
"""Example agent that counts words in messages"""
|
|
103
|
+
|
|
104
|
+
async def process_message(self, envelope: Envelope):
|
|
105
|
+
"""Process a single message"""
|
|
106
|
+
text = envelope.payload.get("text", "")
|
|
107
|
+
word_count = len(text.split())
|
|
108
|
+
|
|
109
|
+
# Store result in object storage
|
|
110
|
+
await self.store_result(f"count-{envelope.header.message_id}", {
|
|
111
|
+
"message_id": envelope.header.message_id,
|
|
112
|
+
"word_count": word_count,
|
|
113
|
+
"timestamp": envelope.header.send_timestamp
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
# Send notification
|
|
117
|
+
await self.send_notification(
|
|
118
|
+
envelope.header,
|
|
119
|
+
f"Processed {word_count} words"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Configure and run
|
|
123
|
+
config = AgentConfig(
|
|
124
|
+
kafka_brokers="localhost:9092",
|
|
125
|
+
consumer_group="word-count-group",
|
|
126
|
+
topics=["input-topic"],
|
|
127
|
+
object_store_endpoint="http://localhost:9000",
|
|
128
|
+
object_store_access_key="admin",
|
|
129
|
+
object_store_secret_key="password",
|
|
130
|
+
redis_url="redis://localhost:6379"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
async def main():
|
|
134
|
+
async with WordCountAgent("word-count", config) as agent:
|
|
135
|
+
await agent.run() # Runs until interrupted
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Architecture
|
|
139
|
+
|
|
140
|
+
BaseAgent follows the same architecture as the Java BaseAgent:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
┌─────────────────────────────────────────────────┐
|
|
144
|
+
│ BaseAgent │
|
|
145
|
+
├─────────────────────────────────────────────────┤
|
|
146
|
+
│ Kafka Consumer │ Message Processing │ Producer │
|
|
147
|
+
├─────────────────────────────────────────────────┤
|
|
148
|
+
│ State Store │ Object Store │ Health API │
|
|
149
|
+
├─────────────────────────────────────────────────┤
|
|
150
|
+
│ Vector Clock │ Telemetry │ Metrics │
|
|
151
|
+
└─────────────────────────────────────────────────┘
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Core Components
|
|
155
|
+
|
|
156
|
+
### 1. Message Processing
|
|
157
|
+
- Kafka consumer with manual offset management
|
|
158
|
+
- Transactional producer for exactly-once semantics
|
|
159
|
+
- Automatic deduplication using vector clocks
|
|
160
|
+
- Session tracking to prevent reprocessing
|
|
161
|
+
|
|
162
|
+
### 2. State Management
|
|
163
|
+
- Pluggable state stores (Redis, In-Memory)
|
|
164
|
+
- Offset tracking for fault tolerance
|
|
165
|
+
- Session high-watermark tracking
|
|
166
|
+
- Atomic operations for consistency
|
|
167
|
+
|
|
168
|
+
### 3. Object Storage
|
|
169
|
+
- S3-compatible object storage (S3, MinIO) and Azure Blob Storage
|
|
170
|
+
- Large payload handling with streaming support
|
|
171
|
+
- Automatic bucket creation and validation
|
|
172
|
+
- Full CRUD operations (put, get, delete, list, copy)
|
|
173
|
+
- Presigned URL generation for temporary access
|
|
174
|
+
- Object metadata management
|
|
175
|
+
- Pagination support for listing large buckets
|
|
176
|
+
- Path-style access for MinIO compatibility
|
|
177
|
+
|
|
178
|
+
### 4. Health Monitoring
|
|
179
|
+
- Kubernetes-compatible health endpoints
|
|
180
|
+
- Liveness: `/health/liveness`
|
|
181
|
+
- Readiness: `/health/readiness`
|
|
182
|
+
- Configurable port (set to 0 to disable)
|
|
183
|
+
|
|
184
|
+
### 5. Observability
|
|
185
|
+
- OpenTelemetry tracing
|
|
186
|
+
- Prometheus metrics
|
|
187
|
+
- Structured logging with context
|
|
188
|
+
- Distributed trace propagation
|
|
189
|
+
|
|
190
|
+
## Configuration
|
|
191
|
+
|
|
192
|
+
Configuration can be provided via:
|
|
193
|
+
1. Environment variables
|
|
194
|
+
2. `.env` file
|
|
195
|
+
3. Direct configuration object
|
|
196
|
+
|
|
197
|
+
### Required Configuration
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
config = AgentConfig(
|
|
201
|
+
# Kafka (required)
|
|
202
|
+
kafka_brokers="localhost:9092",
|
|
203
|
+
consumer_group="my-group",
|
|
204
|
+
topics=["input-topic"],
|
|
205
|
+
|
|
206
|
+
# Object Storage (required) - see provider-specific config below
|
|
207
|
+
object_store_bucket="agent-data",
|
|
208
|
+
)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Object Store Configuration
|
|
212
|
+
|
|
213
|
+
The BaseAgent supports multiple object store providers: S3, MinIO, and Azure Blob Storage.
|
|
214
|
+
|
|
215
|
+
#### Common Configuration
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# Provider type: s3, minio, or azure (default: s3)
|
|
219
|
+
OBJECT_STORE_TYPE=s3
|
|
220
|
+
|
|
221
|
+
# Bucket/Container name (used by all providers)
|
|
222
|
+
OBJECT_STORE_BUCKET=agent-data
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
#### S3/MinIO Configuration
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
OBJECT_STORE_TYPE=s3 # or minio
|
|
229
|
+
OBJECT_STORE_BUCKET=agent-data
|
|
230
|
+
|
|
231
|
+
# Object Store Endpoint (for S3-compatible stores like MinIO)
|
|
232
|
+
OBJECT_STORE_ENDPOINT=http://localhost:9000
|
|
233
|
+
|
|
234
|
+
# Object Store Credentials
|
|
235
|
+
OBJECT_STORE_ACCESS_KEY=admin
|
|
236
|
+
OBJECT_STORE_SECRET_KEY=password
|
|
237
|
+
OBJECT_STORE_REGION=us-east-1
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Development (MinIO):**
|
|
241
|
+
```bash
|
|
242
|
+
OBJECT_STORE_TYPE=minio
|
|
243
|
+
OBJECT_STORE_ENDPOINT=http://localhost:9000
|
|
244
|
+
OBJECT_STORE_ACCESS_KEY=admin
|
|
245
|
+
OBJECT_STORE_SECRET_KEY=password
|
|
246
|
+
OBJECT_STORE_BUCKET=agent-data
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Production (AWS S3):**
|
|
250
|
+
```bash
|
|
251
|
+
OBJECT_STORE_TYPE=s3
|
|
252
|
+
# Leave OBJECT_STORE_ENDPOINT unset to use AWS S3 default
|
|
253
|
+
OBJECT_STORE_ACCESS_KEY=your-aws-access-key
|
|
254
|
+
OBJECT_STORE_SECRET_KEY=your-aws-secret-key
|
|
255
|
+
OBJECT_STORE_BUCKET=your-production-bucket
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### Azure Blob Storage Configuration
|
|
259
|
+
|
|
260
|
+
Azure Blob Storage can be configured using one of three authentication methods:
|
|
261
|
+
|
|
262
|
+
**Option 1: Azure AD (DefaultAzureCredential) - Recommended for production:**
|
|
263
|
+
```bash
|
|
264
|
+
OBJECT_STORE_TYPE=azure
|
|
265
|
+
OBJECT_STORE_BUCKET=agent-data
|
|
266
|
+
AZURE_STORAGE_ACCOUNT=yourstorageaccount
|
|
267
|
+
# Optional: AZURE_STORAGE_ENDPOINT=https://youracct.blob.core.windows.net
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
This uses Azure's DefaultAzureCredential chain (environment variables, managed identity, workload identity, etc.).
|
|
271
|
+
|
|
272
|
+
**Option 2: Connection String:**
|
|
273
|
+
```bash
|
|
274
|
+
OBJECT_STORE_TYPE=azure
|
|
275
|
+
OBJECT_STORE_BUCKET=agent-data
|
|
276
|
+
AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Option 3: Account Key:**
|
|
280
|
+
```bash
|
|
281
|
+
OBJECT_STORE_TYPE=azure
|
|
282
|
+
OBJECT_STORE_BUCKET=agent-data
|
|
283
|
+
AZURE_STORAGE_ACCOUNT=yourstorageaccount
|
|
284
|
+
AZURE_STORAGE_KEY=your-storage-account-key
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Development (Azurite):**
|
|
288
|
+
```bash
|
|
289
|
+
OBJECT_STORE_TYPE=azure
|
|
290
|
+
OBJECT_STORE_BUCKET=agent-data
|
|
291
|
+
AZURE_STORAGE_CONNECTION_STRING=UseDevelopmentStorage=true;
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### Presigned URLs (SAS) Behavior
|
|
295
|
+
|
|
296
|
+
For Azure Blob Storage, presigned URLs are implemented using Shared Access Signatures (SAS):
|
|
297
|
+
|
|
298
|
+
- **Account Key auth**: SAS tokens are signed directly with the account key
|
|
299
|
+
- **Azure AD auth**: User Delegation SAS tokens are generated using a delegation key obtained from Azure AD
|
|
300
|
+
- Requires the service principal to have the `Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action` permission (included in the Storage Blob Data Contributor role)
|
|
301
|
+
- **Connection String auth**: SAS tokens are signed with the account key extracted from the connection string
|
|
302
|
+
|
|
303
|
+
If SAS generation is not possible (e.g., missing permissions), `generate_presigned_url` returns `None`.
|
|
304
|
+
|
|
305
|
+
### Optional Configuration
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
config = AgentConfig(
|
|
309
|
+
# ... required fields ...
|
|
310
|
+
|
|
311
|
+
# State Storage (defaults to in-memory)
|
|
312
|
+
state_store_type="redis", # or "memory"
|
|
313
|
+
redis_url="redis://localhost:6379",
|
|
314
|
+
|
|
315
|
+
# Health Check
|
|
316
|
+
health_check_port=8080, # Set to 0 to disable
|
|
317
|
+
|
|
318
|
+
# Admin Gateway Registration
|
|
319
|
+
admin_gateway_url="http://localhost:8888",
|
|
320
|
+
|
|
321
|
+
# Telemetry
|
|
322
|
+
otel_endpoint="http://localhost:4317",
|
|
323
|
+
|
|
324
|
+
# Performance
|
|
325
|
+
kafka_max_poll_records=100,
|
|
326
|
+
kafka_poll_timeout_ms=100,
|
|
327
|
+
)
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Testing
|
|
331
|
+
|
|
332
|
+
The project follows Test-Driven Development (TDD) principles.
|
|
333
|
+
|
|
334
|
+
### Running Tests with Mise (Platform Convention)
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
# Using mise tasks (recommended)
|
|
338
|
+
mise run base-agent-test # Run all tests
|
|
339
|
+
mise run base-agent-test-unit # Run unit tests only
|
|
340
|
+
mise run base-agent-test-int # Run integration tests
|
|
341
|
+
|
|
342
|
+
# Format and lint
|
|
343
|
+
mise run base-agent-fmt # Format code
|
|
344
|
+
mise run base-agent-lint # Lint code
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Running Tests Manually
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
# Run all tests
|
|
351
|
+
pytest
|
|
352
|
+
|
|
353
|
+
# Run unit tests only
|
|
354
|
+
pytest tests/unit -m unit
|
|
355
|
+
|
|
356
|
+
# Run integration tests (requires Docker)
|
|
357
|
+
pytest tests/integration -m integration
|
|
358
|
+
|
|
359
|
+
# Run with coverage
|
|
360
|
+
pytest --cov=base_agent --cov-report=html
|
|
361
|
+
|
|
362
|
+
# Run specific test file
|
|
363
|
+
pytest tests/unit/test_agent.py
|
|
364
|
+
|
|
365
|
+
# Run tests in parallel
|
|
366
|
+
pytest -n auto
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Test Structure
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
tests/
|
|
373
|
+
├── unit/ # Fast, isolated unit tests
|
|
374
|
+
│ ├── test_agent.py
|
|
375
|
+
│ ├── test_state_store.py
|
|
376
|
+
│ ├── test_kafka_client.py
|
|
377
|
+
│ ├── test_object_store.py # ✅ IMPLEMENTED
|
|
378
|
+
│ └── test_vector_clock.py
|
|
379
|
+
├── integration/ # Tests with real services
|
|
380
|
+
│ ├── test_end_to_end.py
|
|
381
|
+
│ ├── test_exactly_once.py
|
|
382
|
+
│ └── test_recovery.py
|
|
383
|
+
└── conftest.py # Shared fixtures
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Integration Testing with TestContainers
|
|
387
|
+
|
|
388
|
+
Integration tests use testcontainers to spin up real services:
|
|
389
|
+
|
|
390
|
+
```python
|
|
391
|
+
# tests/conftest.py
|
|
392
|
+
@pytest.fixture(scope="session")
|
|
393
|
+
async def kafka():
|
|
394
|
+
with KafkaContainer() as kafka:
|
|
395
|
+
yield kafka.get_bootstrap_server()
|
|
396
|
+
|
|
397
|
+
@pytest.fixture(scope="session")
|
|
398
|
+
async def redis():
|
|
399
|
+
with RedisContainer() as redis:
|
|
400
|
+
yield redis.get_connection_url()
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Development
|
|
404
|
+
|
|
405
|
+
### Setup Development Environment
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
# Clone the repository
|
|
409
|
+
git clone <repo>
|
|
410
|
+
cd python-base-agent
|
|
411
|
+
|
|
412
|
+
# Install dependencies using mise (platform standard)
|
|
413
|
+
mise run base-agent-install
|
|
414
|
+
|
|
415
|
+
# Start development services
|
|
416
|
+
mise run base-agent-docker-up
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Code Quality
|
|
420
|
+
|
|
421
|
+
All code quality tasks are managed through mise (no Makefile/custom scripts):
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
# Format code
|
|
425
|
+
mise run base-agent-fmt
|
|
426
|
+
|
|
427
|
+
# Lint code
|
|
428
|
+
mise run base-agent-lint
|
|
429
|
+
|
|
430
|
+
# Type checking
|
|
431
|
+
mise run base-agent-type-check
|
|
432
|
+
|
|
433
|
+
# All quality checks
|
|
434
|
+
mise run base-agent-quality
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Building Documentation
|
|
438
|
+
|
|
439
|
+
```bash
|
|
440
|
+
# Install docs dependencies
|
|
441
|
+
pip install -e ".[docs]"
|
|
442
|
+
|
|
443
|
+
# Build HTML docs
|
|
444
|
+
cd docs
|
|
445
|
+
make html
|
|
446
|
+
|
|
447
|
+
# View docs
|
|
448
|
+
open _build/html/index.html
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
## Performance
|
|
452
|
+
|
|
453
|
+
The Python BaseAgent is designed to match the performance characteristics of the Java version:
|
|
454
|
+
|
|
455
|
+
- **Throughput**: 10,000+ messages/second per agent
|
|
456
|
+
- **Latency**: < 10ms p99 message processing
|
|
457
|
+
- **Memory**: < 200MB baseline memory usage
|
|
458
|
+
- **Startup**: < 5 seconds to ready state
|
|
459
|
+
|
|
460
|
+
Performance can be tuned via configuration:
|
|
461
|
+
- Batch size for Kafka polling
|
|
462
|
+
- Transaction commit interval
|
|
463
|
+
- State store flush frequency
|
|
464
|
+
- Connection pool sizes
|
|
465
|
+
|
|
466
|
+
## Migration from Java BaseAgent
|
|
467
|
+
|
|
468
|
+
If migrating from Java BaseAgent:
|
|
469
|
+
|
|
470
|
+
1. **Configuration**: Most configuration maps directly
|
|
471
|
+
2. **Message Format**: Same Envelope/Header structure
|
|
472
|
+
3. **State Storage**: Compatible state store keys
|
|
473
|
+
4. **Kafka Topics**: No changes needed
|
|
474
|
+
5. **Object Storage**: Same S3 paths and formats
|
|
475
|
+
|
|
476
|
+
Key differences:
|
|
477
|
+
- Async/await instead of threads
|
|
478
|
+
- Context managers for lifecycle
|
|
479
|
+
- Type hints instead of static typing
|
|
480
|
+
- Protocol classes instead of interfaces
|
|
481
|
+
|
|
482
|
+
## Troubleshooting
|
|
483
|
+
|
|
484
|
+
### Common Issues
|
|
485
|
+
|
|
486
|
+
1. **Kafka Connection Failed**
|
|
487
|
+
- Check `kafka_brokers` configuration
|
|
488
|
+
- Verify Kafka is running
|
|
489
|
+
- Check network connectivity
|
|
490
|
+
|
|
491
|
+
2. **State Store Connection Failed**
|
|
492
|
+
- For Redis: verify `redis_url`
|
|
493
|
+
- Falls back to in-memory if Redis unavailable
|
|
494
|
+
|
|
495
|
+
3. **Health Check Not Responding**
|
|
496
|
+
- Check `health_check_port` configuration
|
|
497
|
+
- Verify port is not in use
|
|
498
|
+
- Set to 0 to disable
|
|
499
|
+
|
|
500
|
+
4. **Message Processing Slow**
|
|
501
|
+
- Check `kafka_max_poll_records`
|
|
502
|
+
- Monitor transaction commit frequency
|
|
503
|
+
- Review async operation bottlenecks
|
|
504
|
+
|
|
505
|
+
### Debug Logging
|
|
506
|
+
|
|
507
|
+
Enable debug logging:
|
|
508
|
+
|
|
509
|
+
```python
|
|
510
|
+
import logging
|
|
511
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
512
|
+
|
|
513
|
+
# Or set environment variable
|
|
514
|
+
export LOG_LEVEL=DEBUG
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## Contributing
|
|
518
|
+
|
|
519
|
+
Follow the TDD process documented in `python-base-agent-implementation-plan.md`:
|
|
520
|
+
|
|
521
|
+
1. Create Linear ticket
|
|
522
|
+
2. Create feature branch
|
|
523
|
+
3. Write tests FIRST
|
|
524
|
+
4. Implement to pass tests
|
|
525
|
+
5. Update documentation
|
|
526
|
+
6. Submit PR
|
|
527
|
+
|
|
528
|
+
## License
|
|
529
|
+
|
|
530
|
+
Proprietary - AI First Technologies LLC
|
|
531
|
+
|
|
532
|
+
## References
|
|
533
|
+
|
|
534
|
+
- [Java BaseAgent Topology](../base-agent-topology.md)
|
|
535
|
+
- [Implementation Plan](../python-base-agent-implementation-plan.md)
|
|
536
|
+
- [LLM Implementation Guide](../pythonAgent.md)
|