aixtools 0.7.8__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.

Potentially problematic release.


This version of aixtools might be problematic. Click here for more details.

Files changed (137) hide show
  1. aixtools-0.7.8/PKG-INFO +1121 -0
  2. aixtools-0.7.8/README.md +1080 -0
  3. aixtools-0.7.8/aixtools/.chainlit/config.toml +113 -0
  4. aixtools-0.7.8/aixtools/.chainlit/translations/bn.json +214 -0
  5. aixtools-0.7.8/aixtools/.chainlit/translations/en-US.json +214 -0
  6. aixtools-0.7.8/aixtools/.chainlit/translations/gu.json +214 -0
  7. aixtools-0.7.8/aixtools/.chainlit/translations/he-IL.json +214 -0
  8. aixtools-0.7.8/aixtools/.chainlit/translations/hi.json +214 -0
  9. aixtools-0.7.8/aixtools/.chainlit/translations/ja.json +214 -0
  10. aixtools-0.7.8/aixtools/.chainlit/translations/kn.json +214 -0
  11. aixtools-0.7.8/aixtools/.chainlit/translations/ml.json +214 -0
  12. aixtools-0.7.8/aixtools/.chainlit/translations/mr.json +214 -0
  13. aixtools-0.7.8/aixtools/.chainlit/translations/nl.json +214 -0
  14. aixtools-0.7.8/aixtools/.chainlit/translations/ta.json +214 -0
  15. aixtools-0.7.8/aixtools/.chainlit/translations/te.json +214 -0
  16. aixtools-0.7.8/aixtools/.chainlit/translations/zh-CN.json +214 -0
  17. aixtools-0.7.8/aixtools/__init__.py +11 -0
  18. aixtools-0.7.8/aixtools/_version.py +34 -0
  19. aixtools-0.7.8/aixtools/a2a/app.py +243 -0
  20. aixtools-0.7.8/aixtools/a2a/auth_middleware.py +46 -0
  21. aixtools-0.7.8/aixtools/a2a/auth_push_notification_sender.py +65 -0
  22. aixtools-0.7.8/aixtools/a2a/context_middleware.py +47 -0
  23. aixtools-0.7.8/aixtools/a2a/google_sdk/__init__.py +0 -0
  24. aixtools-0.7.8/aixtools/a2a/google_sdk/pydantic_ai_adapter/agent_executor.py +269 -0
  25. aixtools-0.7.8/aixtools/a2a/google_sdk/pydantic_ai_adapter/storage.py +26 -0
  26. aixtools-0.7.8/aixtools/a2a/google_sdk/remote_agent_connection.py +104 -0
  27. aixtools-0.7.8/aixtools/a2a/google_sdk/store/__init__.py +0 -0
  28. aixtools-0.7.8/aixtools/a2a/google_sdk/store/alembic.ini +148 -0
  29. aixtools-0.7.8/aixtools/a2a/google_sdk/store/config.py +3 -0
  30. aixtools-0.7.8/aixtools/a2a/google_sdk/store/ensure_database.py +176 -0
  31. aixtools-0.7.8/aixtools/a2a/google_sdk/store/migrations/env.py +97 -0
  32. aixtools-0.7.8/aixtools/a2a/google_sdk/store/migrations/script.py.mako +28 -0
  33. aixtools-0.7.8/aixtools/a2a/google_sdk/store/migrations/versions/68c6975ed20b_added_a2a_sdk_task_table.py +44 -0
  34. aixtools-0.7.8/aixtools/a2a/google_sdk/utils.py +116 -0
  35. aixtools-0.7.8/aixtools/a2a/utils.py +116 -0
  36. aixtools-0.7.8/aixtools/agents/__init__.py +12 -0
  37. aixtools-0.7.8/aixtools/agents/agent.py +264 -0
  38. aixtools-0.7.8/aixtools/agents/agent_batch.py +71 -0
  39. aixtools-0.7.8/aixtools/agents/context/data_models.py +56 -0
  40. aixtools-0.7.8/aixtools/agents/context/processors/audio.py +214 -0
  41. aixtools-0.7.8/aixtools/agents/context/processors/code.py +83 -0
  42. aixtools-0.7.8/aixtools/agents/context/processors/common.py +134 -0
  43. aixtools-0.7.8/aixtools/agents/context/processors/document.py +147 -0
  44. aixtools-0.7.8/aixtools/agents/context/processors/image.py +109 -0
  45. aixtools-0.7.8/aixtools/agents/context/processors/json.py +182 -0
  46. aixtools-0.7.8/aixtools/agents/context/processors/spreadsheet.py +443 -0
  47. aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/char_grid_detector_col.py +82 -0
  48. aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/char_grid_detector_flood.py +92 -0
  49. aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/char_grid_detector_row.py +74 -0
  50. aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/table_detector_sheet_char.py +282 -0
  51. aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/table_header_detector_char.py +177 -0
  52. aixtools-0.7.8/aixtools/agents/context/processors/table_detector/char_grid/table_merger.py +53 -0
  53. aixtools-0.7.8/aixtools/agents/context/processors/table_detector/table_detector_base.py +94 -0
  54. aixtools-0.7.8/aixtools/agents/context/processors/table_detector/table_detector_char.py +30 -0
  55. aixtools-0.7.8/aixtools/agents/context/processors/table_detector/table_region.py +173 -0
  56. aixtools-0.7.8/aixtools/agents/context/processors/table_detector/worksheet_as_char.py +310 -0
  57. aixtools-0.7.8/aixtools/agents/context/processors/tabular.py +306 -0
  58. aixtools-0.7.8/aixtools/agents/context/processors/text.py +183 -0
  59. aixtools-0.7.8/aixtools/agents/context/processors/xml.py +124 -0
  60. aixtools-0.7.8/aixtools/agents/context/processors/yaml.py +87 -0
  61. aixtools-0.7.8/aixtools/agents/context/reader.py +281 -0
  62. aixtools-0.7.8/aixtools/agents/nodes_to_md.py +201 -0
  63. aixtools-0.7.8/aixtools/agents/nodes_to_message.py +30 -0
  64. aixtools-0.7.8/aixtools/agents/nodes_to_str.py +109 -0
  65. aixtools-0.7.8/aixtools/agents/print_nodes.py +54 -0
  66. aixtools-0.7.8/aixtools/agents/prompt.py +270 -0
  67. aixtools-0.7.8/aixtools/app.py +143 -0
  68. aixtools-0.7.8/aixtools/auth/__init__.py +0 -0
  69. aixtools-0.7.8/aixtools/auth/auth.py +293 -0
  70. aixtools-0.7.8/aixtools/chainlit.md +14 -0
  71. aixtools-0.7.8/aixtools/compliance/__init__.py +9 -0
  72. aixtools-0.7.8/aixtools/compliance/private_data.py +137 -0
  73. aixtools-0.7.8/aixtools/compliance/utils.py +44 -0
  74. aixtools-0.7.8/aixtools/context.py +23 -0
  75. aixtools-0.7.8/aixtools/db/__init__.py +17 -0
  76. aixtools-0.7.8/aixtools/db/database.py +110 -0
  77. aixtools-0.7.8/aixtools/db/vector_db.py +115 -0
  78. aixtools-0.7.8/aixtools/evals/__init__.py +0 -0
  79. aixtools-0.7.8/aixtools/evals/__main__.py +74 -0
  80. aixtools-0.7.8/aixtools/evals/dataset.py +87 -0
  81. aixtools-0.7.8/aixtools/evals/discovery.py +186 -0
  82. aixtools-0.7.8/aixtools/evals/run_evals.py +98 -0
  83. aixtools-0.7.8/aixtools/google/client.py +25 -0
  84. aixtools-0.7.8/aixtools/log_view/__init__.py +17 -0
  85. aixtools-0.7.8/aixtools/log_view/app.py +195 -0
  86. aixtools-0.7.8/aixtools/log_view/display.py +285 -0
  87. aixtools-0.7.8/aixtools/log_view/export.py +51 -0
  88. aixtools-0.7.8/aixtools/log_view/filters.py +41 -0
  89. aixtools-0.7.8/aixtools/log_view/log_utils.py +26 -0
  90. aixtools-0.7.8/aixtools/log_view/node_summary.py +229 -0
  91. aixtools-0.7.8/aixtools/logfilters/__init__.py +7 -0
  92. aixtools-0.7.8/aixtools/logfilters/context_filter.py +72 -0
  93. aixtools-0.7.8/aixtools/logging/__init__.py +30 -0
  94. aixtools-0.7.8/aixtools/logging/log_objects.py +240 -0
  95. aixtools-0.7.8/aixtools/logging/logging_config.py +161 -0
  96. aixtools-0.7.8/aixtools/logging/mcp_log_models.py +102 -0
  97. aixtools-0.7.8/aixtools/logging/mcp_logger.py +172 -0
  98. aixtools-0.7.8/aixtools/logging/model_patch_logging.py +87 -0
  99. aixtools-0.7.8/aixtools/logging/open_telemetry.py +36 -0
  100. aixtools-0.7.8/aixtools/mcp/__init__.py +15 -0
  101. aixtools-0.7.8/aixtools/mcp/client.py +306 -0
  102. aixtools-0.7.8/aixtools/mcp/example_client.py +30 -0
  103. aixtools-0.7.8/aixtools/mcp/example_server.py +22 -0
  104. aixtools-0.7.8/aixtools/mcp/exceptions.py +5 -0
  105. aixtools-0.7.8/aixtools/mcp/fast_mcp_log.py +31 -0
  106. aixtools-0.7.8/aixtools/mcp/faulty_mcp.py +319 -0
  107. aixtools-0.7.8/aixtools/mcp/middleware.py +54 -0
  108. aixtools-0.7.8/aixtools/mcp/server.py +76 -0
  109. aixtools-0.7.8/aixtools/model_patch/model_patch.py +63 -0
  110. aixtools-0.7.8/aixtools/server/__init__.py +23 -0
  111. aixtools-0.7.8/aixtools/server/app_mounter.py +90 -0
  112. aixtools-0.7.8/aixtools/server/path.py +153 -0
  113. aixtools-0.7.8/aixtools/server/utils.py +120 -0
  114. aixtools-0.7.8/aixtools/testing/__init__.py +9 -0
  115. aixtools-0.7.8/aixtools/testing/agent_mock.py +143 -0
  116. aixtools-0.7.8/aixtools/testing/aix_test_model.py +186 -0
  117. aixtools-0.7.8/aixtools/testing/mock_tool.py +66 -0
  118. aixtools-0.7.8/aixtools/testing/model_patch_cache.py +279 -0
  119. aixtools-0.7.8/aixtools/tools/doctor/__init__.py +3 -0
  120. aixtools-0.7.8/aixtools/tools/doctor/mcp_tool_doctor.py +79 -0
  121. aixtools-0.7.8/aixtools/tools/doctor/tool_doctor.py +65 -0
  122. aixtools-0.7.8/aixtools/tools/doctor/tool_recommendation.py +49 -0
  123. aixtools-0.7.8/aixtools/utils/__init__.py +35 -0
  124. aixtools-0.7.8/aixtools/utils/chainlit/cl_agent_show.py +82 -0
  125. aixtools-0.7.8/aixtools/utils/chainlit/cl_utils.py +168 -0
  126. aixtools-0.7.8/aixtools/utils/config.py +274 -0
  127. aixtools-0.7.8/aixtools/utils/config_util.py +95 -0
  128. aixtools-0.7.8/aixtools/utils/crypto.py +42 -0
  129. aixtools-0.7.8/aixtools/utils/enum_with_description.py +37 -0
  130. aixtools-0.7.8/aixtools/utils/files.py +17 -0
  131. aixtools-0.7.8/aixtools/utils/persisted_dict.py +99 -0
  132. aixtools-0.7.8/aixtools/utils/utils.py +199 -0
  133. aixtools-0.7.8/aixtools/vault/__init__.py +7 -0
  134. aixtools-0.7.8/aixtools/vault/vault.py +159 -0
  135. aixtools-0.7.8/aixtools.egg-info/SOURCES.txt +134 -0
  136. aixtools-0.7.8/pyproject.toml +92 -0
  137. aixtools-0.7.8/setup.cfg +4 -0
@@ -0,0 +1,1121 @@
1
+ Metadata-Version: 2.4
2
+ Name: aixtools
3
+ Version: 0.7.8
4
+ Summary: Tools for AI exploration and debugging
5
+ Requires-Python: >=3.11.2
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: a2a-sdk>=0.3.1
8
+ Requires-Dist: alembic>=1.17.1
9
+ Requires-Dist: cachebox>=5.0.1
10
+ Requires-Dist: chainlit>=2.5.5
11
+ Requires-Dist: colorlog>=6.9.0
12
+ Requires-Dist: fasta2a>=0.5.0
13
+ Requires-Dist: fastmcp>=2.13.0
14
+ Requires-Dist: hvac>=2.3.0
15
+ Requires-Dist: ipykernel>=6.29.5
16
+ Requires-Dist: langchain-chroma>=0.2.3
17
+ Requires-Dist: langchain-ollama>=0.3.2
18
+ Requires-Dist: langchain-openai>=0.3.14
19
+ Requires-Dist: markitdown[docx,pdf,pptx,xls,xlsx]>=0.1.3
20
+ Requires-Dist: mcp>=1.20.0
21
+ Requires-Dist: mypy>=1.18.2
22
+ Requires-Dist: pandas>=2.2.3
23
+ Requires-Dist: psycopg2-binary>=2.9.11
24
+ Requires-Dist: pydantic-evals>=0.4.10
25
+ Requires-Dist: pydantic-ai>=1.11.1
26
+ Requires-Dist: pyjwt>=2.10.1
27
+ Requires-Dist: pylint>=3.3.7
28
+ Requires-Dist: rich>=14.0.0
29
+ Requires-Dist: ruff>=0.11.6
30
+ Requires-Dist: sqlalchemy>=2.0.44
31
+ Requires-Dist: streamlit>=1.44.1
32
+ Requires-Dist: tiktoken>=0.9.0
33
+ Requires-Dist: openpyxl>=3.1.5
34
+ Requires-Dist: xlrd>=2.0.2
35
+ Requires-Dist: odfpy>=1.4.1
36
+ Requires-Dist: watchdog>=6.0.0
37
+ Provides-Extra: test
38
+ Requires-Dist: pyyaml; extra == "test"
39
+ Provides-Extra: feature
40
+ Requires-Dist: logfire; extra == "feature"
41
+
42
+ # AIXtools
43
+
44
+ AIXtools is a comprehensive Python library for AI agent development, debugging, and deployment. It provides a complete toolkit for building, testing, and monitoring AI agents with support for multiple model providers, advanced logging, and agent-to-agent communication.
45
+
46
+ ## Capabilities
47
+
48
+ - **[Installation](#installation)**
49
+ - **[Environment Configuration](#environment-configuration)**
50
+ - **[Agents](#agents)** - Core agent functionality
51
+ - Basic Agent Usage
52
+ - Agent Development & Management
53
+ - Agent Batch Processing
54
+ - Node Debugging and Visualization
55
+ - **[Context Engineering](#context-engineering)** - Transform files into agent-readable content
56
+ - File Type Processors
57
+ - Configuration
58
+ - Processing Examples
59
+ - **[Agent-to-Agent Communication](#a2a-agent-to-agent-communication)** - Inter-agent communication framework
60
+ - Core Features
61
+ - Google SDK Integration
62
+ - Remote Agent Connections
63
+ - **[Testing & Tools](#testing--tools)** - Comprehensive testing utilities
64
+ - Running Tests
65
+ - Testing Utilities
66
+ - Mock Tool System
67
+ - Model Patch Caching
68
+ - Agent Mock
69
+ - FaultyMCP Testing Server
70
+ - MCP Tool Doctor
71
+ - Tool Doctor
72
+ - Evaluations
73
+ - **[Logging & Debugging](#logging--debugging)** - Advanced logging and debugging
74
+ - Basic Logging
75
+ - Log Viewing Application
76
+ - Object Logging
77
+ - MCP Logging
78
+ - **[Databases](#databases)** - Traditional and vector database support
79
+ - **[Chainlit & HTTP Server](#chainlit--http-server)** - Web interfaces and server framework
80
+ - Chainlit Integration
81
+ - HTTP Server Framework
82
+ - **[Programming Utilities](#programming-utilities)** - Essential utilities
83
+ - Persisted Dictionary
84
+ - Enum with Description
85
+ - Context Management
86
+ - Configuration Management
87
+ - File Utilities
88
+ - Chainlit Utilities
89
+
90
+ ## Installation
91
+
92
+ ```bash
93
+ uv add aixtools
94
+ ```
95
+
96
+ **Updating**
97
+
98
+ ```bash
99
+ uv add --upgrade aixtools
100
+ ```
101
+
102
+ ## Environment Configuration
103
+
104
+ AIXtools requires environment variables for model providers.
105
+
106
+ **IMPORTANT:** Create a `.env` file based on `.env_template`:
107
+
108
+ Here is an example configuration:
109
+
110
+ ```bash
111
+ # Model family (azure, openai, or ollama)
112
+ MODEL_FAMILY=azure
113
+ MODEL_TIMEOUT=120
114
+
115
+ # Azure OpenAI
116
+ AZURE_OPENAI_ENDPOINT=https://your_endpoint.openai.azure.com
117
+ AZURE_OPENAI_API_VERSION=2024-06-01
118
+ AZURE_OPENAI_API_KEY=your_secret_key
119
+ AZURE_MODEL_NAME=gpt-4o
120
+
121
+ # OpenAI
122
+ OPENAI_MODEL_NAME=gpt-4.5-preview
123
+ OPENAI_API_KEY=openai_api_key
124
+
125
+ # Ollama
126
+ OLLAMA_MODEL_NAME=llama3.2:3b-instruct-fp16
127
+ OLLAMA_LOCAL_URL=http://localhost:11434/v1
128
+ ```
129
+
130
+ ## Agents
131
+
132
+ ### Basic Agent Usage
133
+
134
+ ```python
135
+ from aixtools.agents.agent import get_agent, run_agent
136
+
137
+ async def main():
138
+ agent = get_agent(system_prompt="You are a helpful assistant.")
139
+ result, nodes = await run_agent(agent, "Explain quantum computing")
140
+ print(result)
141
+ ```
142
+
143
+ ### Agent Development & Management
144
+
145
+ The agent system provides a unified interface for creating and managing AI agents across different model providers.
146
+
147
+ ```python
148
+ from aixtools.agents.agent import get_agent, run_agent
149
+
150
+ # Create an agent with default model
151
+ agent = get_agent(system_prompt="You are a helpful assistant.")
152
+
153
+ # Run the agent
154
+ result, nodes = await run_agent(agent, "Tell me about AI")
155
+ ```
156
+
157
+ ### Node Debugging and Visualization
158
+
159
+ The `print_nodes` module provides a clean, indented output for easy reading of the node from agent execution.
160
+
161
+ ```python
162
+ from aixtools.agents.print_nodes import print_nodes, print_node
163
+ from aixtools.agents.agent import get_agent, run_agent
164
+
165
+ agent = get_agent(system_prompt="You are a helpful assistant.")
166
+ result, nodes = await run_agent(agent, "Explain quantum computing")
167
+ # Print all execution nodes for debugging
168
+ print_nodes(nodes)
169
+ ```
170
+
171
+ **Features:**
172
+ - Node Type Detection: Automatically handles different node types (`UserPromptNode`, `CallToolsNode`, `ModelRequestNode`, `End`)
173
+ - Formatted Output: Provides clean, indented output for easy reading
174
+ - Tool Call Visualization: Shows tool names and arguments for tool calls
175
+ - Text Content Display: Formats text parts with proper indentation
176
+ - Model Request Summary: Shows character count for model requests to avoid verbose output
177
+
178
+ **Node Types Supported:**
179
+ - `UserPromptNode` - Displays user prompts with indentation
180
+ - `CallToolsNode` - Shows tool calls with names and arguments
181
+ - `ModelRequestNode` - Summarizes model requests with character count
182
+ - `End` - Marks the end of execution (output suppressed by default)
183
+
184
+ ### Agent Batch Processing
185
+
186
+ Process multiple agent queries simultaneously with built-in concurrency control and result aggregation.
187
+
188
+ ```python
189
+ from aixtools.agents.agent_batch import agent_batch, AgentQueryParams
190
+
191
+ # Create query parameters
192
+ query_parameters = [
193
+ AgentQueryParams(prompt="What is the meaning of life"),
194
+ AgentQueryParams(prompt="Who is the prime minister of Canada")
195
+ ]
196
+
197
+ # Run queries in batches
198
+ async for result in agent_batch(query_parameters):
199
+ print(result)
200
+ ```
201
+
202
+ ## Context Engineering
203
+
204
+ Transform file formats into agent-readable content with enforced size limits to prevent context overflow. The main entry point is the `read_file()` function in `aixtools/agents/context/reader.py`, which provides automatic file type detection and delegates to specialized processors for each file type.
205
+
206
+ ### Basic Usage
207
+
208
+ The `read_file()` function in `reader.py` is the main interface for processing files. It automatically detects file types and applies appropriate truncation strategies.
209
+
210
+ ```python
211
+ from aixtools.agents.context.reader import read_file
212
+ from pathlib import Path
213
+
214
+ # Read a file with automatic type detection and truncation
215
+ result = read_file(Path("data.csv"))
216
+
217
+ if result.success:
218
+ print(f"File type: {result.file_type}")
219
+ print(f"Content length: {len(result.content)}")
220
+ print(f"Truncation info: {result.truncation_info}")
221
+ print(result.content)
222
+
223
+ # Optionally specify custom tokenizer and limits
224
+ result = read_file(
225
+ Path("large_file.json"),
226
+ max_tokens_per_file=10000,
227
+ max_total_output=100000
228
+ )
229
+ ```
230
+
231
+ ### Architecture
232
+
233
+ The context engineering system is organized with `reader.py` as the main interface:
234
+ - `reader.py` - Main `read_file()` function with file type detection and processing coordination
235
+ - `config.py` - Configurable size limits and thresholds
236
+ - `processors/` - Specialized processors for each file type (text, code, JSON, CSV, PDF, etc.)
237
+ - `data_models.py` - Data classes for results and metadata
238
+
239
+ ### Supported File Types
240
+
241
+ - Text files (`.txt`, `.log`, `.md`)
242
+ - Code files (Python, JavaScript, etc.)
243
+ - Structured data (`JSON`, `YAML`, `XML`)
244
+ - Tabular data (`CSV`, `TSV`)
245
+ - Documents (`PDF`, `DOCX`)
246
+ - Spreadsheets (`.xlsx`, `.xls`, `.ods`)
247
+ - Images (`PNG`, `JPEG`, `GIF`, `WEBP`)
248
+ - Audio files
249
+
250
+ ### Key Features
251
+
252
+ - Automatic file type detection based on MIME types and extensions
253
+ - Token-based truncation with configurable limits per file
254
+ - Intelligent content sampling (head + tail rows for tabular data)
255
+ - Structure-aware truncation for `JSON`, `YAML`, and `XML`
256
+ - Markdown conversion for documents using `markitdown`
257
+ - Binary content support for images with metadata extraction
258
+ - Comprehensive error handling with partial results when possible
259
+
260
+ ### Configuration
261
+
262
+ All limits are configurable via environment variables:
263
+
264
+ ```bash
265
+ # Output limits
266
+ MAX_TOKENS_PER_FILE=5000
267
+ MAX_TOTAL_OUTPUT=50000
268
+
269
+ # Text truncation
270
+ MAX_LINES=200
271
+ MAX_LINE_LENGTH=1000
272
+
273
+ # Tabular truncation
274
+ MAX_COLUMNS=50
275
+ DEFAULT_ROWS_HEAD=20
276
+ DEFAULT_ROWS_MIDDLE=10
277
+ DEFAULT_ROWS_TAIL=10
278
+ MAX_CELL_LENGTH=500
279
+
280
+ # Images
281
+ MAX_IMAGE_ATTACHMENT_SIZE=2097152 # 2MB
282
+ ```
283
+
284
+ ### Processing Examples
285
+
286
+ The recommended approach is to use the `read_file()` function which automatically handles file type detection and processing. However, you can also use individual processors directly for specific file types.
287
+
288
+ #### Using read_file() (Recommended)
289
+
290
+ ```python
291
+ from aixtools.agents.context.reader import read_file
292
+ from pathlib import Path
293
+
294
+ # Process any file type automatically
295
+ result = read_file(Path("data.csv"))
296
+ if result.success:
297
+ print(result.content)
298
+
299
+ # Works with all supported types
300
+ pdf_result = read_file(Path("report.pdf"))
301
+ excel_result = read_file(Path("workbook.xlsx"))
302
+ json_result = read_file(Path("config.json"))
303
+ ```
304
+
305
+ #### Processing Tabular Data Directly
306
+
307
+ ```python
308
+ from aixtools.agents.context.processors.tabular import process_tabular
309
+ from pathlib import Path
310
+
311
+ # Process specific row range from large CSV
312
+ result = process_tabular(
313
+ file_path=Path("large_data.csv"),
314
+ start_row=100,
315
+ end_row=200,
316
+ max_columns=20,
317
+ max_cell_length=500
318
+ )
319
+
320
+ print(f"Rows shown: {result.truncation_info.rows_shown}")
321
+ print(f"Columns shown: {result.truncation_info.columns_shown}")
322
+ ```
323
+
324
+ #### Processing Spreadsheets Directly
325
+
326
+ ```python
327
+ from aixtools.agents.context.processors.spreadsheet import process_spreadsheet
328
+ from pathlib import Path
329
+
330
+ # Process Excel file with multiple sheets
331
+ result = process_spreadsheet(
332
+ file_path=Path("workbook.xlsx"),
333
+ max_sheets=3,
334
+ max_rows_per_sheet_head=20,
335
+ max_rows_per_sheet_tail=10
336
+ )
337
+
338
+ # Content includes all processed sheets with truncation info
339
+ print(result.content)
340
+ ```
341
+
342
+ #### Processing Documents Directly
343
+
344
+ ```python
345
+ from aixtools.agents.context.processors.document import process_document
346
+ from pathlib import Path
347
+
348
+ # Convert PDF to markdown and truncate
349
+ result = process_document(
350
+ file_path=Path("report.pdf"),
351
+ max_lines=200,
352
+ max_line_length=1000
353
+ )
354
+
355
+ if result.was_extracted:
356
+ print("Document successfully converted to markdown")
357
+ print(result.content)
358
+ ```
359
+
360
+ ### Output Format
361
+
362
+ All processors return consistent output with metadata:
363
+
364
+ ```
365
+ File: data.csv
366
+ Columns: 8 (of 20000 total)
367
+ Rows: 20 (of 1000000 total)
368
+
369
+ col1,col2,...,col8
370
+ value1,value2,...
371
+ ...
372
+
373
+ Truncated: columns: 8 of 20000, rows: 20 of 1000000, 45 cells
374
+ ```
375
+
376
+ The context engineering system ensures agents receive properly formatted, size-limited content that fits within token budgets while preserving the most relevant information from each file type.
377
+
378
+ ## A2A (Agent-to-Agent Communication)
379
+
380
+ The `A2A` module provides a comprehensive framework for enabling sophisticated communication between AI agents across different environments and platforms. It includes Google SDK integration, `PydanticAI` adapters, and `FastA2A` application conversion capabilities.
381
+
382
+ ### Core Features
383
+
384
+ **Agent Application Conversion**
385
+ - Convert `PydanticAI` agents into `FastA2A` applications (deprecated)
386
+ - Support for session metadata extraction and context management
387
+ - Custom worker classes with enhanced data part support
388
+ - Automatic handling of user and session identification
389
+
390
+ **Remote Agent Connections**
391
+ - Establish connections between agents across different environments
392
+ - Asynchronous message sending with task polling capabilities
393
+ - Terminal state detection and error handling
394
+ - Support for various message types including text, files, and data
395
+
396
+ **Google SDK Integration**
397
+ - Native integration with Google's A2A SDK
398
+ - Card-based agent representation and discovery
399
+ - `PydanticAI` adapter for seamless Google SDK compatibility
400
+ - Storage and execution management for agent interactions
401
+
402
+ ### Basic Usage
403
+
404
+ Enable sophisticated agent interactions with Google SDK integration and `PydanticAI` adapters.
405
+
406
+ ```python
407
+ from aixtools.a2a.google_sdk.remote_agent_connection import RemoteAgentConnection
408
+ from aixtools.a2a.app import agent_to_a2a
409
+
410
+ # Convert a PydanticAI agent to FastA2A application
411
+ a2a_app = agent_to_a2a(
412
+ agent=my_agent,
413
+ name="MyAgent",
414
+ description="A helpful AI assistant",
415
+ skills=[{"name": "chat", "description": "General conversation"}]
416
+ )
417
+
418
+ # Connect agents across different environments
419
+ connection = RemoteAgentConnection(card=agent_card, client=a2a_client)
420
+ response = await connection.send_message_with_polling(message)
421
+ ```
422
+
423
+ ### Postgres DB Store for A2A agent
424
+
425
+ See implementation: `aixtools/a2a/google_sdk/store`
426
+
427
+ #### Alembic
428
+
429
+ In order to take full control of the database schema management Alembic is used for handling database migrations.
430
+ Thus make sure, that google-sdk Store objects are being created with parameter create_table=False
431
+ ```python
432
+ from a2a.server.tasks import DatabaseTaskStore
433
+
434
+ ...
435
+
436
+ task_store=DatabaseTaskStore(engine=db_engine, create_table=False)
437
+ ```
438
+
439
+ #### Setup of database and applying migrations (manual if needed):
440
+
441
+ configure POSTGRES_URL env variable
442
+ ```.dotenv
443
+ POSTGRES_URL=postgresql+asyncpg://user:password@localhost:5432/a2a_magic_db
444
+ ```
445
+
446
+
447
+ ```shell
448
+ # from scope of your a2a service
449
+
450
+ #activate your virtual environment
451
+ kzwk877@degfqx35d621DD a2a_magic_service % source .venv/bin/activate
452
+ # set the PATH_TO_ALEMBIC_CONFIG environment variable to point to the alembic configuration directory
453
+ (a2a_magic_service) kzwk877@degfqx35d621DD a2a_magic_service % export PATH_TO_ALEMBIC_CONFIG="$(pwd)/.venv/lib/python3.12/site-packages/aixtools/a2a/google_sdk/store"
454
+ # Make sure that database is existed
455
+ (a2a_magic_service) kzwk877@degfqx35d621DD a2a_magic_service % uv run "${PATH_TO_ALEMBIC_CONFIG}/ensure_database.py"
456
+ 2025-11-11 10:08:51.501 WARNING [root] Looking for '.env' file in default directory
457
+ 2025-11-11 10:08:52.750 INFO [root] Using .env file at '/PATH_TO_A2A_SERVICE/a2a_magic_service/.env'
458
+ 2025-11-11 10:08:52.751 INFO [root] Using MAIN_PROJECT_DIR='/PATH_TO_A2A_SERVICE/a2a_magic_service'
459
+ 2025-11-11 10:08:52.752 WARNING [root] Using DATA_DIR='/app/data'
460
+ 2025-11-11 10:08:52.757 INFO [__main__] Starting database creation script...
461
+ ...
462
+ 2025-11-11 10:08:52.821 INFO [__main__] Creating database 'a2a_magic_db'...
463
+ 2025-11-11 10:08:52.904 INFO [__main__] Database 'a2a_magic_db' created successfully
464
+ ...
465
+ 2025-11-11 10:08:52.921 INFO [__main__] Database creation script completed successfully!
466
+ # Apply alembic migrations
467
+ (a2a_magic_service) kzwk877@degfqx35d621DD a2a_magic_service % alembic --config "${PATH_TO_ALEMBIC_CONFIG}/alembic.ini" upgrade head
468
+ 2025-11-11 10:11:34.185 WARNING [root] Looking for '.env' file in default directory
469
+ 2025-11-11 10:11:35.046 WARNING [root] Looking for '.env' file at '/PATH_TO_A2A_SERVICE/a2a_magic_service'
470
+ 2025-11-11 10:11:35.047 INFO [root] Using .env file at '/PATH_TO_A2A_SERVICE/a2a_magic_service/.env'
471
+ 2025-11-11 10:11:35.048 INFO [root] Using MAIN_PROJECT_DIR='/PATH_TO_A2A_SERVICE/a2a_magic_service'
472
+ 2025-11-11 10:11:35.049 WARNING [root] Using DATA_DIR='/app/data'
473
+ 2025-11-11 10:11:35.054 INFO [env_py] Using database URL for migrations: postgresql://user:password@localhost:5432/a2a_magic_db
474
+ INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
475
+ INFO [alembic.runtime.migration] Will assume transactional DDL.
476
+ INFO [alembic.runtime.migration] Running upgrade -> 68c6975ed20b, Added a2a-sdk Task table
477
+ ```
478
+
479
+ #### Schema modifications
480
+
481
+ if new schema modifications has been introduced with new versions of a2a sdk suggested way
482
+ to create new alembic migrations would be:
483
+
484
+ - launch a2a service with passed parameter to `DatabaseStore` `create_table=True`
485
+ - make sure that all new tables/columns are created in
486
+ the database (possibly an new request to a2a server needs to be made)
487
+ - create new alembic migration script
488
+ ```shell
489
+ (a2a_magic_service) kzwk877@degfqx35d621DD % alembic --config "${PATH_TO_ALEMBIC_CONFIG}/alembic.ini" revision --autogenerate -m "New table introduced"
490
+ ```
491
+ - review the generated migration script
492
+ - apply and test
493
+
494
+ ## Databases
495
+
496
+ ### Database Integration
497
+
498
+ Support for both traditional and vector databases with seamless integration.
499
+
500
+ ```python
501
+ from aixtools.db.database import Database
502
+ from aixtools.db.vector_db import VectorDB
503
+
504
+ # Traditional database
505
+ db = Database("sqlite:///app.db")
506
+
507
+ # Vector database for embeddings
508
+ vector_db = VectorDB()
509
+ vector_db.add_documents(documents)
510
+ ```
511
+
512
+ ## Logging & Debugging
513
+
514
+ AixTools provides functionality for logging and debugging.
515
+
516
+ ### Basic Logging and Debugging
517
+
518
+ ```python
519
+ from aixtools.agents.agent import get_agent, run_agent
520
+
521
+ async def main():
522
+ # Create an agent
523
+ agent = get_agent(system_prompt="You are a helpful assistant.")
524
+
525
+ # Run agent - logging is automatic via ObjectLogger
526
+ result, nodes = await run_agent(
527
+ agent,
528
+ "Explain quantum computing",
529
+ debug=True, # Enable debug logging
530
+ log_model_requests=True # Log model requests/responses
531
+ )
532
+
533
+ print(f"Result: {result}")
534
+ print(f"Logged {len(nodes)} nodes")
535
+ ```
536
+
537
+ ### Log Viewing Application
538
+
539
+ Interactive `Streamlit` application for analyzing logged objects and debugging agent behavior.
540
+
541
+ **Features:**
542
+ - Log file selection and filtering
543
+ - Node visualization with expand/collapse
544
+ - Export capabilities to `JSON`
545
+ - Regex pattern matching
546
+ - Real-time log monitoring
547
+
548
+ ```bash
549
+ # Run the log viewer
550
+ log_view
551
+
552
+ # Or specify custom log directory
553
+ log_view /path/to/logs
554
+ ```
555
+
556
+ ### Object Logging & Debugging
557
+
558
+ Advanced logging system with object serialization and visual debugging tools.
559
+
560
+ ```python
561
+ from aixtools.logging.log_objects import ObjectLogger
562
+
563
+ # Log any pickleable object
564
+ with ObjectLogger() as logger:
565
+ logger.log({"message": "Hello, world!"})
566
+ logger.log(agent_response)
567
+ ```
568
+
569
+ ### MCP Logging
570
+
571
+ AIXtools provides MCP support for both client and server implementations with easier logging for debugging purposes.
572
+
573
+ **Example:**
574
+
575
+ Let's assume we have an MCP server that runs an agent tool.
576
+
577
+ Note that the `ctx: Context` parameter is passed to `run_agent()`, this will enable logging to the MCP client.
578
+
579
+ ```python
580
+ @mcp.tool
581
+ async def my_tool_with_agent(query: str, ctx: Context) -> str:
582
+ """ A tool that uses an gents to process the query """
583
+ agent = get_agent()
584
+ async with get_qb_agent() as agent:
585
+ ret, nodes = await run_agent(agent=agent, prompt=query, ctx=ctx) # Enable MCP logging
586
+ return str(ret)
587
+ ```
588
+
589
+ On the client side, you can create an agent connected to the MCP server, the nodes from the MCP server will show on the `STDOUT` so you can see what's going on the MCP server's agent loop.
590
+
591
+ ```python
592
+ mcp = get_mcp_client("http://localhost:8000") # Get an MCP client with a default log handler that prints to STDOUT
593
+ agent = get_agent(toolsets=[mcp])
594
+ async with agent:
595
+ # The messages from the MCP server will be printed to the STDOUT
596
+ ret, nodes = await run_agent(agent, prompt="...")
597
+ ```
598
+
599
+ #### MCP Server Logging
600
+
601
+ Create MCP servers with built-in logging capabilities.
602
+
603
+ ```python
604
+ from aixtools.mcp.fast_mcp_log import FastMcpLog
605
+
606
+ # Use FastMCP server with logging
607
+ mcp = FastMcpLog("Demo")
608
+ ```
609
+
610
+ ## Testing & Tools
611
+
612
+ AIXtools provides comprehensive testing utilities and diagnostic tools for AI agent development and debugging.
613
+
614
+ ### Running Tests
615
+
616
+ Execute the test suite using the provided scripts:
617
+
618
+ ```bash
619
+ # Run all tests
620
+ ./scripts/test.sh
621
+
622
+ # Run unit tests only
623
+ ./scripts/test_unit.sh
624
+
625
+ # Run integration tests only
626
+ ./scripts/test_integration.sh
627
+ ```
628
+
629
+ ### Testing Utilities
630
+
631
+ The testing module provides mock tools, model patching, and test utilities for comprehensive agent testing.
632
+
633
+ ```python
634
+ from aixtools.testing.mock_tool import MockTool
635
+ from aixtools.testing.model_patch_cache import ModelPatchCache
636
+ from aixtools.testing.aix_test_model import AixTestModel
637
+
638
+ # Create mock tools for testing
639
+ mock_tool = MockTool(name="test_tool", response="mock response")
640
+
641
+ # Use model patch caching for consistent test results
642
+ cache = ModelPatchCache()
643
+ cached_response = cache.get_cached_response("test_prompt")
644
+
645
+ # Test model for controlled testing scenarios
646
+ test_model = AixTestModel()
647
+ ```
648
+
649
+ ### Mock Tool System
650
+
651
+ Create and manage mock tools for testing agent behavior without external dependencies.
652
+
653
+ ```python
654
+ from aixtools.testing.mock_tool import MockTool
655
+
656
+ # Create a mock tool with predefined responses
657
+ mock_calculator = MockTool(
658
+ name="calculator",
659
+ description="Performs mathematical calculations",
660
+ response_map={
661
+ "2+2": "4",
662
+ "10*5": "50"
663
+ }
664
+ )
665
+
666
+ # Use in agent testing
667
+ agent = get_agent(tools=[mock_calculator])
668
+ result = await run_agent(agent, "What is 2+2?")
669
+ ```
670
+
671
+ ### Model Patch Caching
672
+
673
+ Cache model responses for consistent testing and development workflows.
674
+
675
+ ```python
676
+ from aixtools.testing.model_patch_cache import ModelPatchCache
677
+
678
+ # Initialize cache
679
+ cache = ModelPatchCache(cache_dir="./test_cache")
680
+
681
+ # Cache responses for specific prompts
682
+ cache.cache_response("test prompt", "cached response")
683
+
684
+ # Retrieve cached responses
685
+ response = cache.get_cached_response("test prompt")
686
+ ```
687
+
688
+ ### Model Patching System
689
+
690
+ Dynamic model behavior modification for testing and debugging.
691
+
692
+ ```python
693
+ from aixtools.model_patch.model_patch import ModelPatch
694
+
695
+ # Apply patches to models for testing
696
+ with ModelPatch() as patch:
697
+ patch.apply_response_override("test response")
698
+ result = await agent.run("test prompt")
699
+ ```
700
+
701
+ ### Agent Mock
702
+
703
+ Replay previously recorded agent runs without executing the actual agent. Useful for testing, debugging, and creating reproducible test cases.
704
+
705
+ ```python
706
+ from aixtools.testing.agent_mock import AgentMock
707
+ from aixtools.agents.agent import get_agent, run_agent
708
+
709
+ # Run an agent and capture its execution
710
+ agent = get_agent(system_prompt="You are a helpful assistant.")
711
+ result, nodes = await run_agent(agent, "Explain quantum computing")
712
+
713
+ # Create a mock agent from the recorded nodes
714
+ agent_mock = AgentMock(nodes=nodes, result_output=result)
715
+
716
+ # Save the mock for later use
717
+ agent_mock.save(Path("test_data/quantum_mock.pkl"))
718
+
719
+ # Load and replay the mock agent
720
+ loaded_mock = AgentMock.load(Path("test_data/quantum_mock.pkl"))
721
+ result, nodes = await run_agent(loaded_mock, "any prompt") # Returns recorded nodes
722
+ ```
723
+
724
+ ### FaultyMCP Testing Server
725
+
726
+ A specialized MCP server designed for testing error handling and resilience in MCP client implementations. `FaultyMCP` simulates various failure scenarios including network errors, server crashes, and random exceptions.
727
+
728
+ **Features:**
729
+ - Configurable error probabilities for different request types
730
+ - HTTP 404 error injection for `POST`/`DELETE` requests
731
+ - Server crash simulation on `GET` requests
732
+ - Random exception throwing in tool operations
733
+ - MCP-specific error simulation (`ValidationError`, `ResourceError`, etc.)
734
+ - Safe mode for controlled testing
735
+
736
+ ```python
737
+ from aixtools.mcp.faulty_mcp import run_server_on_port, config
738
+
739
+ # Configure error probabilities
740
+ config.prob_on_post_404 = 0.3 # 30% chance of 404 on POST
741
+ config.prob_on_get_crash = 0.1 # 10% chance of crash on GET
742
+ config.prob_in_list_tools_throw = 0.2 # 20% chance of exception in tools/list
743
+
744
+ # Run the faulty server
745
+ run_server_on_port()
746
+ ```
747
+
748
+ **Command Line Usage:**
749
+
750
+ ```bash
751
+ # Run with default error probabilities
752
+ python -m aixtools.mcp.faulty_mcp
753
+
754
+ # Run in safe mode (no errors by default)
755
+ python -m aixtools.mcp.faulty_mcp --safe-mode
756
+
757
+ # Custom configuration
758
+ python -m aixtools.mcp.faulty_mcp \
759
+ --port 8888 \
760
+ --prob-on-post-404 0.2 \
761
+ --prob-on-get-crash 0.1 \
762
+ --prob-in-list-tools-throw 0.3
763
+ ```
764
+
765
+ **Available Test Tools:**
766
+ - `add(a, b)` - Reliable addition operation
767
+ - `multiply(a, b)` - Reliable multiplication operation
768
+ - `always_error()` - Always throws an exception
769
+ - `random_throw_exception(a, b, prob)` - Randomly throws exceptions
770
+ - `freeze_server(seconds)` - Simulates server freeze
771
+ - `throw_404_exception()` - Throws HTTP 404 error
772
+
773
+ ### MCP Tool Doctor
774
+
775
+ Analyze tools from MCP (Model Context Protocol) servers and receive AI-powered recommendations for improvement.
776
+
777
+ ```python
778
+ from aixtools.tools.doctor.mcp_tool_doctor import tool_doctor_mcp
779
+ from pydantic_ai.mcp import MCPServerStreamableHTTP, MCPServerStdio
780
+
781
+ # Analyze HTTP MCP server
782
+ recommendations = await tool_doctor_mcp(mcp_url='http://127.0.0.1:8000/mcp')
783
+ for rec in recommendations:
784
+ print(rec)
785
+
786
+ # Analyze STDIO MCP server
787
+ server = MCPServerStdio(command='fastmcp', args=['run', 'my_server.py'])
788
+ recommendations = await tool_doctor_mcp(mcp_server=server, verbose=True)
789
+ ```
790
+
791
+ **Command Line Usage:**
792
+
793
+ ```bash
794
+ # Analyze HTTP MCP server (default)
795
+ tool_doctor_mcp
796
+
797
+ # Analyze specific HTTP MCP server
798
+ tool_doctor_mcp --mcp-url http://localhost:9000/mcp --verbose
799
+
800
+ # Analyze STDIO MCP server
801
+ tool_doctor_mcp --stdio-command fastmcp --stdio-args run my_server.py --debug
802
+ ```
803
+
804
+ **Available options:**
805
+ - `--mcp-url URL` - URL of HTTP MCP server (default: `http://127.0.0.1:8000/mcp`)
806
+ - `--stdio-command CMD` - Command to run STDIO MCP server
807
+ - `--stdio-args ARGS` - Arguments for STDIO MCP server command
808
+ - `--verbose` - Enable verbose output
809
+ - `--debug` - Enable debug output
810
+
811
+ ### Tool Doctor
812
+
813
+ Analyze tool usage patterns from agent logs and get optimization recommendations.
814
+
815
+ ```python
816
+ from aixtools.tools.doctor.tool_doctor import ToolDoctor
817
+ from aixtools.tools.doctor.tool_recommendation import ToolRecommendation
818
+
819
+ # Analyze tool usage patterns
820
+ doctor = ToolDoctor()
821
+ analysis = doctor.analyze_tools(agent_logs)
822
+
823
+ # Get tool recommendations
824
+ recommendation = ToolRecommendation()
825
+ suggestions = recommendation.recommend_tools(agent_context)
826
+ ```
827
+
828
+ ### Evaluations
829
+
830
+ Run comprehensive Agent/LLM evaluations using the built-in evaluation discovery based on `Pydantic-AI` framework with AIXtools enhancements.
831
+
832
+ ```bash
833
+ # Run all evaluations
834
+ python -m aixtools.evals
835
+
836
+ # Run evaluations with filtering
837
+ python -m aixtools.evals --filter "specific_test"
838
+
839
+ # Run with verbose output and detailed reporting
840
+ python -m aixtools.evals --verbose --include-input --include-output --include-reasons
841
+
842
+ # Specify custom evaluations directory
843
+ python -m aixtools.evals --evals-dir /path/to/evals
844
+
845
+ # Set minimum assertions threshold
846
+ python -m aixtools.evals --min-assertions 0.8
847
+ ```
848
+
849
+ **Command Line Options:**
850
+ - `--evals-dir` - Directory containing `eval_*.py` files (default: `evals`)
851
+ - `--filter` - Filter to run only matching evaluations
852
+ - `--include-input` - Include input in report output (default: `True`)
853
+ - `--include-output` - Include output in report output (default: `True`)
854
+ - `--include-evaluator-failures` - Include evaluator failures in report
855
+ - `--include-reasons` - Include reasons in report output
856
+ - `--min-assertions` - Minimum assertions average required for success (default: `1.0`)
857
+ - `--verbose` - Print detailed information about discovery and processing
858
+
859
+ The evaluation system discovers and runs all `Dataset` objects from `eval_*.py` files in the specified directory, similar to test runners but specifically designed for LLM evaluations using `pydantic_evals`.
860
+
861
+ **Discovery Mechanism**
862
+
863
+ The evaluation framework uses an automatic discovery system:
864
+
865
+ 1. **File Discovery**: Scans the specified directory for files matching the pattern `eval_*.py`
866
+ 2. **Dataset Discovery**: Within each file, looks for variables named `dataset_*` that are instances of `pydantic_evals.Dataset`
867
+ 3. **Target Function Discovery**: Within the same file looks for function or async function named `target_*`. There must be 1 target function per file.
868
+ 4. **Function Discovery**: Looks for functions with specific prefixes:
869
+ - Functions prefixed with `scorer_*`, `evaluator_*` for custom scorer and evaluator functions that will be used for each dataset in that file
870
+ 5. **Filtering**: Supports filtering by module name, file name, dataset name, or fully qualified name
871
+
872
+ **Example Evaluation File Structure:**
873
+
874
+ ```python
875
+ # eval_math_operations.py
876
+ from pydantic_evals import Dataset, Case
877
+
878
+ # This dataset will be discovered automatically
879
+ dataset_addition = Dataset(
880
+ name="Addition Tests",
881
+ cases=[
882
+ Case(input="What is 2 + 2?", expected="4"),
883
+ Case(input="What is 10 + 5?", expected="15"),
884
+ ],
885
+ evaluators=[...]
886
+ )
887
+
888
+ # This function will be used as the evaluation target
889
+ async def target_math_agent(input_text: str) -> str:
890
+ # Your agent run logic here
891
+ agent = get_agent(system_prompt="You are a math assistant.")
892
+ result, _ = await run_agent(agent, input_text)
893
+ return result
894
+
895
+ # This function will be used as evaluator for all datasets (optional)
896
+ def evaluator_check_output(ctx: EvaluatorContext) -> bool:
897
+ # Your result evaluation logic here
898
+ return ctx.output == ctx.expected_output
899
+ ```
900
+
901
+ The discovery system will:
902
+ - Find `eval_math_operations.py` in the `evals` directory
903
+ - Discover `dataset_addition` as an evaluation dataset
904
+ - Use `evaluate_math_agent` as the target function for evaluation
905
+ - Run each case through the target function and evaluate results
906
+
907
+ #### Name-Based Discovery
908
+
909
+ The evaluation system uses name-based discovery for all components:
910
+
911
+ **Target Functions** (exactly one required per eval file):
912
+ - Purpose: The main function being evaluated - processes inputs and returns outputs
913
+ - Naming: Functions named `target_*` (e.g., `target_my_function`)
914
+ - Signature: `def target_name(inputs: InputType) -> OutputType` or `async def target_name(inputs: InputType) -> OutputType`
915
+ - Example: `async def target_math_agent(input_text: str) -> str`
916
+
917
+ **Scoring Functions** (optional):
918
+ - Purpose: Determine if evaluation results meet success criteria
919
+ - Naming: Functions named `scorer_*` (e.g., `scorer_custom`)
920
+ - Signature: `def scorer_name(report: EvaluationReport, dataset: AixDataset, min_score: float = 1.0, verbose: bool = False) -> bool`
921
+ - Example: `def scorer_accuracy_threshold(report, dataset, min_score=0.8, verbose=False) -> bool`
922
+
923
+ **Evaluator Functions** (optional):
924
+ - Purpose: Custom evaluation logic for comparing outputs with expected results
925
+ - Naming: Functions named `evaluator_*` (e.g., `evaluator_check_output`)
926
+ - Signature: `def evaluator_name(ctx: EvaluatorContext) -> EvaluatorOutput` or `async def evaluator_name(ctx: EvaluatorContext) -> EvaluatorOutput`
927
+ - Example: `def evaluator_exact_match(ctx) -> EvaluatorOutput`
928
+
929
+ This name-based approach works seamlessly with both synchronous and asynchronous functions.
930
+
931
+ #### Scoring System
932
+
933
+ The framework includes a custom scoring system with `average_assertions` as the default scorer. This scorer checks if the average assertion score meets a minimum threshold and provides detailed pass/fail reporting.
934
+
935
+ ## Chainlit & HTTP Server
936
+
937
+ ### Chainlit Integration
938
+
939
+ Ready-to-use `Chainlit` application for interactive agent interfaces.
940
+
941
+ ```python
942
+ # Run the Chainlit app
943
+ # Configuration in aixtools/chainlit.md
944
+ # Main app in aixtools/app.py
945
+ ```
946
+
947
+ ### HTTP Server Framework
948
+
949
+ AIXtools provides an HTTP server framework for deploying agents and tools as web services.
950
+
951
+ ```python
952
+ from aixtools.server.app_mounter import mount_app
953
+ from aixtools.server import create_server
954
+
955
+ # Create and configure server
956
+ server = create_server()
957
+
958
+ # Mount applications and endpoints
959
+ mount_app(server, "/agent", agent_app)
960
+ mount_app(server, "/tools", tools_app)
961
+
962
+ # Run server
963
+ server.run(host="0.0.0.0", port=8000)
964
+ ```
965
+
966
+ **Features:**
967
+ - Application mounting system for modular service composition
968
+ - Integration with `Chainlit` for agent interfaces
969
+ - RESTful API support
970
+ - Middleware support for authentication and logging
971
+
972
+ ## Programming Utilities
973
+
974
+ AIXtools provides essential programming utilities for configuration management, data persistence, file operations, and context handling.
975
+
976
+ ### Persisted Dictionary
977
+
978
+ Persistent key-value storage with automatic serialization and file-based persistence.
979
+
980
+ ```python
981
+ from aixtools.utils.persisted_dict import PersistedDict
982
+
983
+ # Create a persistent dictionary
984
+ cache = PersistedDict("cache.json")
985
+
986
+ # Store and retrieve data
987
+ cache["user_preferences"] = {"theme": "dark", "language": "en"}
988
+ cache["session_data"] = {"last_login": "2024-01-01"}
989
+
990
+ # Data is automatically saved to file
991
+ print(cache["user_preferences"]) # Persists across program restarts
992
+ ```
993
+
994
+ ### Enum with Description
995
+
996
+ Enhanced `Enum` classes with built-in descriptions for better documentation and user interfaces.
997
+
998
+ ```python
999
+ from aixtools.utils.enum_with_description import EnumWithDescription
1000
+
1001
+ class ModelType(EnumWithDescription):
1002
+ GPT4 = ("gpt-4", "OpenAI GPT-4 model")
1003
+ CLAUDE = ("claude-3", "Anthropic Claude-3 model")
1004
+ LLAMA = ("llama-2", "Meta LLaMA-2 model")
1005
+
1006
+ # Access enum values and descriptions
1007
+ print(ModelType.GPT4.value) # "gpt-4"
1008
+ print(ModelType.GPT4.description) # "OpenAI GPT-4 model"
1009
+
1010
+ # Get all descriptions
1011
+ for model in ModelType:
1012
+ print(f"{model.value}: {model.description}")
1013
+ ```
1014
+
1015
+ ### Context Management
1016
+
1017
+ Centralized context management for sharing state across components.
1018
+
1019
+ ```python
1020
+ from aixtools.context import Context
1021
+
1022
+ # Create and use context
1023
+ context = Context()
1024
+ context.set("user_id", "12345")
1025
+ context.set("session_data", {"preferences": {"theme": "dark"}})
1026
+
1027
+ # Retrieve context data
1028
+ user_id = context.get("user_id")
1029
+ session_data = context.get("session_data")
1030
+
1031
+ # Context can be passed between components
1032
+ def process_request(ctx: Context):
1033
+ user_id = ctx.get("user_id")
1034
+ # Process with user context
1035
+ ```
1036
+
1037
+ ### Configuration Management
1038
+
1039
+ Robust configuration handling with environment variable support and validation.
1040
+
1041
+ ```python
1042
+ from aixtools.utils.config import Config
1043
+ from aixtools.utils.config_util import load_config
1044
+
1045
+ # Load configuration from environment and files
1046
+ config = load_config()
1047
+
1048
+ # Access configuration values
1049
+ model_name = config.get("MODEL_NAME", "gpt-4")
1050
+ api_key = config.get("API_KEY")
1051
+ timeout = config.get("TIMEOUT", 30, int)
1052
+
1053
+ # Configuration with validation
1054
+ class AppConfig(Config):
1055
+ model_name: str = "gpt-4"
1056
+ max_tokens: int = 1000
1057
+ temperature: float = 0.7
1058
+
1059
+ app_config = AppConfig()
1060
+ ```
1061
+
1062
+ ### File Utilities
1063
+
1064
+ Enhanced file operations with `Path` support and utility functions.
1065
+
1066
+ ```python
1067
+ from aixtools.utils.files import read_file, write_file, ensure_directory
1068
+ from pathlib import Path
1069
+
1070
+ # Read and write files with automatic encoding handling
1071
+ content = read_file("data.txt")
1072
+ write_file("output.txt", "Hello, world!")
1073
+
1074
+ # Ensure directories exist
1075
+ data_dir = Path("data/logs")
1076
+ ensure_directory(data_dir)
1077
+
1078
+ # Work with file paths
1079
+ config_path = Path("config") / "settings.json"
1080
+ if config_path.exists():
1081
+ config_data = read_file(config_path)
1082
+ ```
1083
+
1084
+ ### Chainlit Utilities
1085
+
1086
+ Specialized utilities for `Chainlit` integration and agent display.
1087
+
1088
+ ```python
1089
+ from aixtools.utils.chainlit.cl_agent_show import show_agent_response
1090
+ from aixtools.utils.chainlit.cl_utils import format_message
1091
+
1092
+ # Display agent responses in Chainlit
1093
+ await show_agent_response(
1094
+ response="Hello, how can I help you?",
1095
+ metadata={"model": "gpt-4", "tokens": 150}
1096
+ )
1097
+
1098
+ # Format messages for Chainlit display
1099
+ formatted_msg = format_message(
1100
+ content="Processing your request...",
1101
+ message_type="info"
1102
+ )
1103
+ ```
1104
+
1105
+ ### General Utilities
1106
+
1107
+ Common utility functions for everyday programming tasks.
1108
+
1109
+ ```python
1110
+ from aixtools.utils.utils import safe_json_loads, timestamp_now, hash_string
1111
+
1112
+ # Safe JSON parsing
1113
+ data = safe_json_loads('{"key": "value"}', default={})
1114
+
1115
+ # Get current timestamp
1116
+ now = timestamp_now()
1117
+
1118
+ # Generate hash for strings
1119
+ file_hash = hash_string("content to hash")
1120
+ ```
1121
+