traia-iatp 0.1.1__py3-none-any.whl

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 traia-iatp might be problematic. Click here for more details.

Files changed (72) hide show
  1. traia_iatp/README.md +368 -0
  2. traia_iatp/__init__.py +30 -0
  3. traia_iatp/cli/__init__.py +5 -0
  4. traia_iatp/cli/main.py +483 -0
  5. traia_iatp/client/__init__.py +10 -0
  6. traia_iatp/client/a2a_client.py +274 -0
  7. traia_iatp/client/crewai_a2a_tools.py +335 -0
  8. traia_iatp/client/grpc_a2a_tools.py +349 -0
  9. traia_iatp/client/root_path_a2a_client.py +1 -0
  10. traia_iatp/core/__init__.py +43 -0
  11. traia_iatp/core/models.py +161 -0
  12. traia_iatp/mcp/__init__.py +15 -0
  13. traia_iatp/mcp/client.py +201 -0
  14. traia_iatp/mcp/mcp_agent_template.py +422 -0
  15. traia_iatp/mcp/templates/Dockerfile.j2 +56 -0
  16. traia_iatp/mcp/templates/README.md.j2 +212 -0
  17. traia_iatp/mcp/templates/cursor-rules.md.j2 +326 -0
  18. traia_iatp/mcp/templates/deployment_params.json.j2 +20 -0
  19. traia_iatp/mcp/templates/docker-compose.yml.j2 +23 -0
  20. traia_iatp/mcp/templates/dockerignore.j2 +47 -0
  21. traia_iatp/mcp/templates/gitignore.j2 +77 -0
  22. traia_iatp/mcp/templates/mcp_health_check.py.j2 +150 -0
  23. traia_iatp/mcp/templates/pyproject.toml.j2 +26 -0
  24. traia_iatp/mcp/templates/run_local_docker.sh.j2 +94 -0
  25. traia_iatp/mcp/templates/server.py.j2 +240 -0
  26. traia_iatp/mcp/traia_mcp_adapter.py +381 -0
  27. traia_iatp/preview_diagrams.html +181 -0
  28. traia_iatp/registry/__init__.py +26 -0
  29. traia_iatp/registry/atlas_search_indexes.json +280 -0
  30. traia_iatp/registry/embeddings.py +298 -0
  31. traia_iatp/registry/iatp_search_api.py +839 -0
  32. traia_iatp/registry/mongodb_registry.py +771 -0
  33. traia_iatp/registry/readmes/ATLAS_SEARCH_INDEXES.md +252 -0
  34. traia_iatp/registry/readmes/ATLAS_SEARCH_SETUP.md +134 -0
  35. traia_iatp/registry/readmes/AUTHENTICATION_UPDATE.md +124 -0
  36. traia_iatp/registry/readmes/EMBEDDINGS_SETUP.md +172 -0
  37. traia_iatp/registry/readmes/IATP_SEARCH_API_GUIDE.md +257 -0
  38. traia_iatp/registry/readmes/MONGODB_X509_AUTH.md +208 -0
  39. traia_iatp/registry/readmes/README.md +251 -0
  40. traia_iatp/registry/readmes/REFACTORING_SUMMARY.md +191 -0
  41. traia_iatp/server/__init__.py +15 -0
  42. traia_iatp/server/a2a_server.py +215 -0
  43. traia_iatp/server/example_template_usage.py +72 -0
  44. traia_iatp/server/iatp_server_agent_generator.py +237 -0
  45. traia_iatp/server/iatp_server_template_generator.py +235 -0
  46. traia_iatp/server/templates/Dockerfile.j2 +49 -0
  47. traia_iatp/server/templates/README.md +137 -0
  48. traia_iatp/server/templates/README.md.j2 +425 -0
  49. traia_iatp/server/templates/__init__.py +1 -0
  50. traia_iatp/server/templates/__main__.py.j2 +450 -0
  51. traia_iatp/server/templates/agent.py.j2 +80 -0
  52. traia_iatp/server/templates/agent_config.json.j2 +22 -0
  53. traia_iatp/server/templates/agent_executor.py.j2 +264 -0
  54. traia_iatp/server/templates/docker-compose.yml.j2 +23 -0
  55. traia_iatp/server/templates/env.example.j2 +67 -0
  56. traia_iatp/server/templates/gitignore.j2 +78 -0
  57. traia_iatp/server/templates/grpc_server.py.j2 +218 -0
  58. traia_iatp/server/templates/pyproject.toml.j2 +76 -0
  59. traia_iatp/server/templates/run_local_docker.sh.j2 +103 -0
  60. traia_iatp/server/templates/server.py.j2 +190 -0
  61. traia_iatp/special_agencies/__init__.py +4 -0
  62. traia_iatp/special_agencies/registry_search_agency.py +392 -0
  63. traia_iatp/utils/__init__.py +10 -0
  64. traia_iatp/utils/docker_utils.py +251 -0
  65. traia_iatp/utils/general.py +64 -0
  66. traia_iatp/utils/iatp_utils.py +126 -0
  67. traia_iatp-0.1.1.dist-info/METADATA +414 -0
  68. traia_iatp-0.1.1.dist-info/RECORD +72 -0
  69. traia_iatp-0.1.1.dist-info/WHEEL +5 -0
  70. traia_iatp-0.1.1.dist-info/entry_points.txt +2 -0
  71. traia_iatp-0.1.1.dist-info/licenses/LICENSE +21 -0
  72. traia_iatp-0.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,191 @@
1
+ # Registry and Search API Refactoring Summary
2
+
3
+ ## Overview
4
+
5
+ This refactoring separates the concerns between registry management (write operations) and search/query operations (read operations) to eliminate duplication and improve maintainability.
6
+
7
+ ## Changes Made
8
+
9
+ ### 1. `mongodb_registry.py` - Write Operations Only
10
+
11
+ **Removed Methods:**
12
+ - `query_agents()` - Moved to search API
13
+ - `atlas_search()` - Moved to search API
14
+ - `vector_search()` - Moved to search API
15
+ - `vector_search_text()` - Moved to search API
16
+ - `query_mcp_servers()` - Moved to search API
17
+ - `atlas_search()` (MCP) - Moved to search API
18
+ - `vector_search()` (MCP) - Moved to search API
19
+ - `vector_search_text()` (MCP) - Moved to search API
20
+
21
+ **Kept Methods:**
22
+ - `add_utility_agent()` - Registry management
23
+ - `update_health_status()` - Registry management
24
+ - `update_agent_base_url()` - Registry management
25
+ - `add_tags()` - Registry management
26
+ - `remove_agent()` - Registry management
27
+ - `update_utility_agent()` - Registry management
28
+ - `get_statistics()` - Registry statistics (read but specific to registry)
29
+ - `add_mcp_server()` - Registry management
30
+ - `get_mcp_server()` - Simple lookup (kept for backward compatibility)
31
+
32
+ **Updated Documentation:**
33
+ - Updated module docstring to clarify write-only purpose
34
+ - Updated class docstrings to indicate write operations only
35
+ - Added references to `iatp_search_api.py` for search operations
36
+
37
+ ### 2. `iatp_search_api.py` - Search and Query Operations
38
+
39
+ **Existing Methods (Unchanged):**
40
+ - `find_utility_agent()` - Search by name, capability, tag, or query
41
+ - `list_utility_agents()` - List agents with filters
42
+ - `search_utility_agents()` - Vector search for agents
43
+ - `find_mcp_server()` - Search MCP servers
44
+ - `list_mcp_servers()` - List MCP servers
45
+ - `search_mcp_servers()` - Vector search for MCP servers
46
+ - `get_mcp_server()` - Get MCP server by name
47
+
48
+ **Features:**
49
+ - Atlas Search integration
50
+ - Vector search with embeddings
51
+ - Fallback to Atlas Search when vector search fails
52
+ - Read-only operations (no MongoDB write access needed)
53
+ - Cached connections for better performance
54
+
55
+ ### 3. Updated Test Files
56
+
57
+ **`test_discovery_and_usage.py`:**
58
+ - Updated imports to use `iatp_search_api` instead of `mongodb_registry`
59
+ - Modified `discover_hyperliquid_agent()` to use `search_utility_agents()`
60
+ - Updated `create_tools_from_discovered_agent()` to work with `UtilityAgentInfo` structure
61
+ - Removed registry connection management
62
+
63
+ **`test_refactoring.py`:**
64
+ - New test script to verify refactoring works correctly
65
+ - Tests registry write operations
66
+ - Tests search API operations
67
+ - Tests discovery test imports
68
+
69
+ ## Benefits
70
+
71
+ ### 1. Clear Separation of Concerns
72
+ - **Registry**: Handles data persistence and lifecycle management
73
+ - **Search API**: Handles discovery and querying
74
+
75
+ ### 2. Reduced Duplication
76
+ - Eliminated duplicate search methods between files
77
+ - Single source of truth for search logic
78
+
79
+ ### 3. Better Performance
80
+ - Search API uses read-only connections
81
+ - Cached connections for repeated queries
82
+ - Optimized for search operations
83
+
84
+ ### 4. Improved Maintainability
85
+ - Easier to modify search logic in one place
86
+ - Clearer responsibilities for each module
87
+ - Better testability
88
+
89
+ ### 5. Enhanced Security
90
+ - Search API can use read-only credentials
91
+ - Registry operations require write permissions
92
+ - Reduced attack surface
93
+
94
+ ## Usage Examples
95
+
96
+ ### Registry Operations (Write)
97
+ ```python
98
+ from iatp.registry.mongodb_registry import UtilityAgentRegistry
99
+
100
+ # Add new agent
101
+ registry = UtilityAgentRegistry()
102
+ await registry.add_utility_agent(agent, tags=["trading", "hyperliquid"])
103
+
104
+ # Update agent
105
+ await registry.update_health_status(agent_id, is_healthy=True)
106
+ await registry.update_agent_base_url(agent_id, new_url)
107
+ ```
108
+
109
+ ### Search Operations (Read)
110
+ ```python
111
+ from iatp.registry.iatp_search_api import search_utility_agents, find_utility_agent
112
+
113
+ # Search for agents
114
+ agents = await search_utility_agents("hyperliquid trading", limit=5)
115
+
116
+ # Find specific agent
117
+ agent = find_utility_agent(capability="market_data")
118
+ ```
119
+
120
+ ### Discovery Test
121
+ ```python
122
+ # The discovery test now uses the search API
123
+ from iatp.registry.iatp_search_api import search_utility_agents
124
+
125
+ # Search for Hyperliquid agent
126
+ search_results = await search_utility_agents(
127
+ query="hyperliquid trading",
128
+ limit=5,
129
+ active_only=True
130
+ )
131
+ ```
132
+
133
+ ## Migration Guide
134
+
135
+ ### For Existing Code
136
+
137
+ 1. **If using registry for search/query:**
138
+ ```python
139
+ # OLD
140
+ from iatp.registry.mongodb_registry import UtilityAgentRegistry
141
+ registry = UtilityAgentRegistry()
142
+ agents = await registry.query_agents(query="trading")
143
+
144
+ # NEW
145
+ from iatp.registry.iatp_search_api import search_utility_agents
146
+ agents = await search_utility_agents("trading")
147
+ ```
148
+
149
+ 2. **If using registry for write operations:**
150
+ ```python
151
+ # No changes needed - these methods are still available
152
+ from iatp.registry.mongodb_registry import UtilityAgentRegistry
153
+ registry = UtilityAgentRegistry()
154
+ await registry.add_utility_agent(agent)
155
+ ```
156
+
157
+ ### Environment Variables
158
+
159
+ No changes to environment variables are required. Both modules use the same authentication methods:
160
+ - `MONGODB_CONNECTION_STRING`
161
+ - `MONGODB_USER` + `MONGODB_PASSWORD`
162
+ - `MONGODB_X509_CERT_FILE`
163
+
164
+ ## Testing
165
+
166
+ Run the refactoring test to verify everything works:
167
+
168
+ ```bash
169
+ cd traia-centralized-backend
170
+ python test_refactoring.py
171
+ ```
172
+
173
+ This will test:
174
+ - Registry write operations
175
+ - Search API operations
176
+ - Discovery test imports
177
+
178
+ ## Future Improvements
179
+
180
+ 1. **Connection Pooling**: Implement connection pooling for better performance
181
+ 2. **Caching**: Add Redis caching for frequently accessed data
182
+ 3. **Rate Limiting**: Add rate limiting for search operations
183
+ 4. **Metrics**: Add metrics collection for search performance
184
+ 5. **API Versioning**: Consider API versioning for future changes
185
+
186
+ ## Backward Compatibility
187
+
188
+ - All existing registry write operations remain unchanged
189
+ - Search operations now use the dedicated search API
190
+ - No breaking changes to existing functionality
191
+ - Clear migration path provided
@@ -0,0 +1,15 @@
1
+ """IATP server module for creating A2A servers from utility agents."""
2
+
3
+ from .a2a_server import (
4
+ UtilityAgencyExecutor,
5
+ create_a2a_server,
6
+ create_and_start_a2a_server
7
+ )
8
+ from .iatp_server_agent_generator import IATPServerAgentGenerator
9
+
10
+ __all__ = [
11
+ "UtilityAgencyExecutor",
12
+ "IATPServerAgentGenerator",
13
+ "create_a2a_server",
14
+ "create_and_start_a2a_server",
15
+ ]
@@ -0,0 +1,215 @@
1
+ """A2A server implementation for utility agencies using the official a2a-sdk."""
2
+
3
+ import asyncio
4
+ import logging
5
+ from typing import Dict, Any, Optional, List
6
+ from a2a.server.apps import A2AStarletteApplication
7
+ from a2a.server.agent_execution import AgentExecutor, RequestContext
8
+ from a2a.server.events.event_queue import EventQueue
9
+ from a2a.server.tasks import InMemoryTaskStore
10
+ from a2a.server.request_handlers import DefaultRequestHandler
11
+ from a2a.types import AgentCard, AgentSkill, AgentCapabilities
12
+ from a2a.utils import new_agent_text_message, new_text_artifact
13
+ from dataclasses import dataclass
14
+ import uvicorn
15
+
16
+ from ..core.models import UtilityAgent
17
+ from .iatp_server_agent_generator import IATPServerAgentGenerator
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class UtilityAgencyExecutor(AgentExecutor):
23
+ """Agent executor that wraps a utility agency and executes tasks via CrewAI."""
24
+
25
+ def __init__(self, agency: UtilityAgent, agency_generator: IATPServerAgentGenerator):
26
+ self.agency = agency
27
+ self.agency_generator = agency_generator
28
+ self._crew = None
29
+
30
+ async def _get_crew(self):
31
+ """Lazily build the crew from agency config."""
32
+ if self._crew is None:
33
+ self._crew = await self.agency_generator.build_crew_from_agency(self.agency)
34
+ return self._crew
35
+
36
+ async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
37
+ """Execute a task using the utility agency crew."""
38
+ try:
39
+ # Get the user's request from context
40
+ user_message = context.get_last_user_message()
41
+ if not user_message:
42
+ event_queue.enqueue_event(
43
+ new_agent_text_message("No user message provided")
44
+ )
45
+ return
46
+
47
+ # Extract text from message parts
48
+ user_text = ""
49
+ for part in user_message.parts:
50
+ if hasattr(part, 'text'):
51
+ user_text += part.text
52
+
53
+ if not user_text:
54
+ event_queue.enqueue_event(
55
+ new_agent_text_message("No text content in user message")
56
+ )
57
+ return
58
+
59
+ # Build crew and execute
60
+ crew = await self._get_crew()
61
+
62
+ # Run the crew with the request
63
+ result = crew.kickoff(inputs={"request": user_text})
64
+
65
+ # Send the result as agent message
66
+ event_queue.enqueue_event(
67
+ new_agent_text_message(str(result))
68
+ )
69
+
70
+ except Exception as e:
71
+ logger.error(f"Error executing task: {e}")
72
+ event_queue.enqueue_event(
73
+ new_agent_text_message(f"Error processing request: {str(e)}")
74
+ )
75
+
76
+
77
+ class MCPToolExecutor(AgentExecutor):
78
+ """Agent executor for individual MCP tool execution."""
79
+
80
+ def __init__(self, agency: UtilityAgent, tool_name: str):
81
+ self.agency = agency
82
+ self.tool_name = tool_name
83
+
84
+ async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
85
+ """Execute a specific MCP tool."""
86
+ try:
87
+ from ..mcp.client import MCPClient
88
+
89
+ # Get tool arguments from context
90
+ user_message = context.get_last_user_message()
91
+ if not user_message:
92
+ event_queue.enqueue_event(
93
+ new_agent_text_message("No arguments provided")
94
+ )
95
+ return
96
+
97
+ # Extract arguments (assuming they're passed as JSON in text)
98
+ import json
99
+ arguments = {}
100
+ for part in user_message.parts:
101
+ if hasattr(part, 'text'):
102
+ try:
103
+ arguments = json.loads(part.text)
104
+ except:
105
+ arguments = {"query": part.text} # Fallback to simple text
106
+
107
+ # Connect to MCP server and execute tool
108
+ mcp_client = MCPClient(self.agency.mcp_server)
109
+ await mcp_client.connect()
110
+
111
+ try:
112
+ result = await mcp_client.call_tool(self.tool_name, arguments)
113
+ event_queue.enqueue_event(
114
+ new_agent_text_message(str(result))
115
+ )
116
+ finally:
117
+ await mcp_client.disconnect()
118
+
119
+ except Exception as e:
120
+ logger.error(f"Error executing MCP tool {self.tool_name}: {e}")
121
+ event_queue.enqueue_event(
122
+ new_agent_text_message(f"Error executing tool: {str(e)}")
123
+ )
124
+
125
+
126
+ def create_a2a_server(
127
+ agency: UtilityAgent,
128
+ agency_generator: IATPServerAgentGenerator,
129
+ host: str = "0.0.0.0",
130
+ port: int = 8000
131
+ ) -> A2AStarletteApplication:
132
+ """Create an A2A server for a utility agency."""
133
+
134
+ # Create skills from agency capabilities
135
+ skills = []
136
+
137
+ # Add main processing skill
138
+ main_skill = AgentSkill(
139
+ id="process_request",
140
+ name=f"Process request using {agency.name}",
141
+ description=f"Process a request using {agency.name} capabilities. {agency.description}",
142
+ examples=[
143
+ f"Help me with {cap}" for cap in agency.mcp_server.capabilities[:2]
144
+ ] if agency.mcp_server.capabilities else ["Process this request for me"]
145
+ )
146
+ skills.append(main_skill)
147
+
148
+ # Add individual MCP tool skills
149
+ for capability in agency.mcp_server.capabilities:
150
+ skill = AgentSkill(
151
+ id=f"mcp_{capability}",
152
+ name=f"Execute {capability}",
153
+ description=f"Execute {capability} tool on MCP server",
154
+ examples=[f"Run {capability} with these parameters"]
155
+ )
156
+ skills.append(skill)
157
+
158
+ # Create capabilities
159
+ capabilities = AgentCapabilities(
160
+ streaming=False, # Not implementing streaming for now
161
+ pushNotifications=False, # Not implementing push notifications
162
+ stateTransitionHistory=False
163
+ )
164
+
165
+ # Create agent card
166
+ agent_card = AgentCard(
167
+ name=agency.name.replace(" ", "_").lower(),
168
+ description=agency.description,
169
+ url=f"http://{host}:{port}",
170
+ version="1.0.0",
171
+ capabilities=capabilities,
172
+ skills=skills,
173
+ # TODO: Add authentication when AgentAuthentication is available
174
+ # authentication=AgentAuthentication(schemes=["Bearer"]) if agency.auth_type else None
175
+ )
176
+
177
+ # Create executor mapping
178
+ executors = {
179
+ "process_request": UtilityAgencyExecutor(agency, agency_generator)
180
+ }
181
+
182
+ # Add MCP tool executors
183
+ for capability in agency.mcp_server.capabilities:
184
+ executors[f"mcp_{capability}"] = MCPToolExecutor(agency, capability)
185
+
186
+ # Create task store and request handler
187
+ task_store = InMemoryTaskStore()
188
+ request_handler = DefaultRequestHandler(
189
+ agent_card=agent_card,
190
+ executors=executors,
191
+ task_store=task_store
192
+ )
193
+
194
+ # Create the A2A application
195
+ app = A2AStarletteApplication(
196
+ agent_card=agent_card,
197
+ request_handler=request_handler
198
+ )
199
+
200
+ return app
201
+
202
+
203
+ async def create_and_start_a2a_server(
204
+ agency: UtilityAgent,
205
+ agency_generator: IATPServerAgentGenerator,
206
+ host: str = "0.0.0.0",
207
+ port: int = 8000
208
+ ):
209
+ """Create and start an A2A server for a utility agency."""
210
+ app = create_a2a_server(agency, agency_generator, host, port)
211
+
212
+ logger.info(f"Starting A2A server for {agency.name} on {host}:{port}")
213
+ config = uvicorn.Config(app, host=host, port=port, log_level="info")
214
+ server = uvicorn.Server(config)
215
+ await server.serve()
@@ -0,0 +1,72 @@
1
+ """Example usage of the utility agent template generator.
2
+
3
+ This script demonstrates how to generate a utility agent from an MCP server.
4
+ """
5
+
6
+ from pathlib import Path
7
+ from ..core.models import MCPServer, MCPServerType
8
+ from .iatp_server_agent_generator import IATPServerAgentGenerator
9
+
10
+
11
+ def main():
12
+ """Example of generating a utility agent."""
13
+
14
+ # Create an MCP server specification
15
+ mcp_server = MCPServer(
16
+ id="hyperliquid-mcp-001",
17
+ name="hyperliquid-mcp",
18
+ url="http://localhost:3000/mcp",
19
+ server_type=MCPServerType.STREAMABLE_HTTP,
20
+ description="Implements comprehensive trading tools for Hyperliquid L1",
21
+ capabilities=[
22
+ "market_data",
23
+ "place_order",
24
+ "cancel_order",
25
+ "get_positions",
26
+ "get_account_info"
27
+ ],
28
+ metadata={
29
+ "version": "1.0.0",
30
+ "author": "Traia"
31
+ }
32
+ )
33
+
34
+ # Create the generator
35
+ generator = IATPServerAgentGenerator(
36
+ output_base_dir=Path("generated_agents")
37
+ )
38
+
39
+ # Generate the utility agent
40
+ agent = generator.generate_agent(
41
+ mcp_server=mcp_server,
42
+ agent_name="Hyperliquid Trading",
43
+ agent_id="hyperliquid-mcp-traia-utility-agent",
44
+ agent_description="A utility agent that exposes Hyperliquid trading capabilities via A2A protocol",
45
+ expose_individual_tools=False, # Just expose one main skill
46
+ auth_required=False,
47
+ use_simple_server=True, # Use the simplified server template
48
+ skill_examples=[
49
+ "Get current market data for ETH-USD",
50
+ "Place a limit order to buy 1 ETH at $3000",
51
+ "Show my current positions",
52
+ "Cancel order with ID 12345",
53
+ "Get my account balance and margin"
54
+ ]
55
+ )
56
+
57
+ print(f"Generated utility agent: {agent.name}")
58
+ print(f"ID: {agent.id}")
59
+ print(f"Status: {agent.status}")
60
+ print(f"Code path: {agent.code_path}")
61
+ print(f"Capabilities: {agent.capabilities}")
62
+
63
+ # The generated agent can now be:
64
+ # 1. Pushed to GitHub using push_agency_to_repo
65
+ # 2. Deployed to Cloud Run using cloudrun_deployer
66
+ # 3. Registered in MongoDB for discovery
67
+
68
+ return agent
69
+
70
+
71
+ if __name__ == "__main__":
72
+ main()