traia-iatp 0.1.29__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 (107) hide show
  1. traia_iatp/README.md +368 -0
  2. traia_iatp/__init__.py +54 -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/d402_a2a_client.py +293 -0
  9. traia_iatp/client/grpc_a2a_tools.py +349 -0
  10. traia_iatp/client/root_path_a2a_client.py +1 -0
  11. traia_iatp/contracts/__init__.py +12 -0
  12. traia_iatp/contracts/iatp_contracts_config.py +263 -0
  13. traia_iatp/contracts/wallet_creator.py +255 -0
  14. traia_iatp/core/__init__.py +43 -0
  15. traia_iatp/core/models.py +172 -0
  16. traia_iatp/d402/__init__.py +55 -0
  17. traia_iatp/d402/chains.py +102 -0
  18. traia_iatp/d402/client.py +150 -0
  19. traia_iatp/d402/clients/__init__.py +7 -0
  20. traia_iatp/d402/clients/base.py +218 -0
  21. traia_iatp/d402/clients/httpx.py +219 -0
  22. traia_iatp/d402/common.py +114 -0
  23. traia_iatp/d402/encoding.py +28 -0
  24. traia_iatp/d402/examples/client_example.py +197 -0
  25. traia_iatp/d402/examples/server_example.py +171 -0
  26. traia_iatp/d402/facilitator.py +453 -0
  27. traia_iatp/d402/fastapi_middleware/__init__.py +6 -0
  28. traia_iatp/d402/fastapi_middleware/middleware.py +225 -0
  29. traia_iatp/d402/fastmcp_middleware.py +147 -0
  30. traia_iatp/d402/mcp_middleware.py +434 -0
  31. traia_iatp/d402/middleware.py +193 -0
  32. traia_iatp/d402/models.py +116 -0
  33. traia_iatp/d402/networks.py +98 -0
  34. traia_iatp/d402/path.py +43 -0
  35. traia_iatp/d402/payment_introspection.py +104 -0
  36. traia_iatp/d402/payment_signing.py +178 -0
  37. traia_iatp/d402/paywall.py +119 -0
  38. traia_iatp/d402/starlette_middleware.py +326 -0
  39. traia_iatp/d402/template.py +1 -0
  40. traia_iatp/d402/types.py +300 -0
  41. traia_iatp/mcp/__init__.py +18 -0
  42. traia_iatp/mcp/client.py +201 -0
  43. traia_iatp/mcp/d402_mcp_tool_adapter.py +361 -0
  44. traia_iatp/mcp/mcp_agent_template.py +481 -0
  45. traia_iatp/mcp/templates/Dockerfile.j2 +80 -0
  46. traia_iatp/mcp/templates/README.md.j2 +310 -0
  47. traia_iatp/mcp/templates/cursor-rules.md.j2 +520 -0
  48. traia_iatp/mcp/templates/deployment_params.json.j2 +20 -0
  49. traia_iatp/mcp/templates/docker-compose.yml.j2 +32 -0
  50. traia_iatp/mcp/templates/dockerignore.j2 +47 -0
  51. traia_iatp/mcp/templates/env.example.j2 +57 -0
  52. traia_iatp/mcp/templates/gitignore.j2 +77 -0
  53. traia_iatp/mcp/templates/mcp_health_check.py.j2 +150 -0
  54. traia_iatp/mcp/templates/pyproject.toml.j2 +32 -0
  55. traia_iatp/mcp/templates/pyrightconfig.json.j2 +22 -0
  56. traia_iatp/mcp/templates/run_local_docker.sh.j2 +390 -0
  57. traia_iatp/mcp/templates/server.py.j2 +175 -0
  58. traia_iatp/mcp/traia_mcp_adapter.py +543 -0
  59. traia_iatp/preview_diagrams.html +181 -0
  60. traia_iatp/registry/__init__.py +26 -0
  61. traia_iatp/registry/atlas_search_indexes.json +280 -0
  62. traia_iatp/registry/embeddings.py +298 -0
  63. traia_iatp/registry/iatp_search_api.py +846 -0
  64. traia_iatp/registry/mongodb_registry.py +771 -0
  65. traia_iatp/registry/readmes/ATLAS_SEARCH_INDEXES.md +252 -0
  66. traia_iatp/registry/readmes/ATLAS_SEARCH_SETUP.md +134 -0
  67. traia_iatp/registry/readmes/AUTHENTICATION_UPDATE.md +124 -0
  68. traia_iatp/registry/readmes/EMBEDDINGS_SETUP.md +172 -0
  69. traia_iatp/registry/readmes/IATP_SEARCH_API_GUIDE.md +257 -0
  70. traia_iatp/registry/readmes/MONGODB_X509_AUTH.md +208 -0
  71. traia_iatp/registry/readmes/README.md +251 -0
  72. traia_iatp/registry/readmes/REFACTORING_SUMMARY.md +191 -0
  73. traia_iatp/scripts/__init__.py +2 -0
  74. traia_iatp/scripts/create_wallet.py +244 -0
  75. traia_iatp/server/__init__.py +15 -0
  76. traia_iatp/server/a2a_server.py +219 -0
  77. traia_iatp/server/example_template_usage.py +72 -0
  78. traia_iatp/server/iatp_server_agent_generator.py +237 -0
  79. traia_iatp/server/iatp_server_template_generator.py +235 -0
  80. traia_iatp/server/templates/.dockerignore.j2 +48 -0
  81. traia_iatp/server/templates/Dockerfile.j2 +49 -0
  82. traia_iatp/server/templates/README.md +137 -0
  83. traia_iatp/server/templates/README.md.j2 +425 -0
  84. traia_iatp/server/templates/__init__.py +1 -0
  85. traia_iatp/server/templates/__main__.py.j2 +565 -0
  86. traia_iatp/server/templates/agent.py.j2 +94 -0
  87. traia_iatp/server/templates/agent_config.json.j2 +22 -0
  88. traia_iatp/server/templates/agent_executor.py.j2 +279 -0
  89. traia_iatp/server/templates/docker-compose.yml.j2 +23 -0
  90. traia_iatp/server/templates/env.example.j2 +84 -0
  91. traia_iatp/server/templates/gitignore.j2 +78 -0
  92. traia_iatp/server/templates/grpc_server.py.j2 +218 -0
  93. traia_iatp/server/templates/pyproject.toml.j2 +78 -0
  94. traia_iatp/server/templates/run_local_docker.sh.j2 +103 -0
  95. traia_iatp/server/templates/server.py.j2 +243 -0
  96. traia_iatp/special_agencies/__init__.py +4 -0
  97. traia_iatp/special_agencies/registry_search_agency.py +392 -0
  98. traia_iatp/utils/__init__.py +10 -0
  99. traia_iatp/utils/docker_utils.py +251 -0
  100. traia_iatp/utils/general.py +64 -0
  101. traia_iatp/utils/iatp_utils.py +126 -0
  102. traia_iatp-0.1.29.dist-info/METADATA +423 -0
  103. traia_iatp-0.1.29.dist-info/RECORD +107 -0
  104. traia_iatp-0.1.29.dist-info/WHEEL +5 -0
  105. traia_iatp-0.1.29.dist-info/entry_points.txt +2 -0
  106. traia_iatp-0.1.29.dist-info/licenses/LICENSE +21 -0
  107. traia_iatp-0.1.29.dist-info/top_level.txt +1 -0
traia_iatp/cli/main.py ADDED
@@ -0,0 +1,483 @@
1
+ """IATP CLI interface."""
2
+
3
+ import asyncio
4
+ import json
5
+ from pathlib import Path
6
+ from typing import Optional, List
7
+ import typer
8
+ from rich.console import Console
9
+ from rich.table import Table
10
+ from rich.progress import Progress, SpinnerColumn, TextColumn
11
+ from pydantic import HttpUrl
12
+
13
+ from ..core.models import MCPServer, MCPServerType, UtilityAgent
14
+ from ..server.iatp_server_agent_generator import IATPServerAgentGenerator
15
+ from ..registry.mongodb_registry import UtilityAgentRegistry, MCPServerRegistry
16
+ from ..utils.docker_utils import use_run_local_docker_script, LocalDockerRunner
17
+ from ..client.a2a_client import create_utility_agency_tools
18
+ from ..mcp.mcp_agent_template import MCPServerConfig
19
+
20
+ app = typer.Typer(
21
+ name="iatp",
22
+ help="Inter Agent Transfer Protocol - Enable AI Agents to utilize other AI Agents as tools"
23
+ )
24
+ console = Console()
25
+
26
+
27
+ @app.command()
28
+ def create_agency(
29
+ name: str = typer.Option(..., "--name", "-n", help="Name of the utility agency"),
30
+ description: str = typer.Option(..., "--description", "-d", help="Description of the agency"),
31
+ mcp_name: str = typer.Option(..., "--mcp-name", help="Name of existing MCP server in registry"),
32
+ output_dir: str = typer.Option("utility_agencies", "--output-dir", "-o", help="Output directory"),
33
+ deploy: bool = typer.Option(False, "--deploy", help="Deploy immediately after creation"),
34
+ port: Optional[int] = typer.Option(None, "--port", "-p", help="Port to deploy on"),
35
+ mongodb_uri: Optional[str] = typer.Option(None, "--mongodb-uri", help="MongoDB URI for registry")
36
+ ):
37
+ """Create a new utility agency from an existing MCP server in the registry."""
38
+ async def _create():
39
+ with Progress(
40
+ SpinnerColumn(),
41
+ TextColumn("[progress.description]{task.description}"),
42
+ console=console
43
+ ) as progress:
44
+ task = progress.add_task("Creating utility agency...", total=None)
45
+
46
+ try:
47
+ # Look up MCP server in registry
48
+ mcp_registry = MCPServerRegistry(mongodb_uri)
49
+ try:
50
+ mcp_data = await mcp_registry.get_mcp_server(mcp_name)
51
+
52
+ if not mcp_data:
53
+ console.print(f"āŒ MCP server '{mcp_name}' not found in registry", style="red")
54
+ return None, None
55
+
56
+ # Create MCPServer object from registry data
57
+ mcp_server = MCPServer(
58
+ id=str(mcp_data.get("_id", "")),
59
+ name=mcp_data["name"],
60
+ url=mcp_data["url"],
61
+ description=mcp_data["description"],
62
+ server_type=mcp_data.get("server_type", MCPServerType.STREAMABLE_HTTP),
63
+ capabilities=mcp_data.get("capabilities", []),
64
+ metadata=mcp_data.get("metadata", {})
65
+ )
66
+ finally:
67
+ mcp_registry.close()
68
+
69
+ # Create agency generator
70
+ generator = IATPServerAgentGenerator(output_base_dir=Path(output_dir))
71
+
72
+ # Generate the agency
73
+ agency = generator.generate_agent(
74
+ mcp_server=mcp_server,
75
+ agency_name=name,
76
+ agency_description=description,
77
+ use_simple_server=False # Use modular server for CLI
78
+ )
79
+
80
+ folder_path = agency.code_path
81
+
82
+ progress.update(task, description="Agency created successfully!")
83
+
84
+ console.print(f"\nāœ… Created utility agency: {agency.name}")
85
+ console.print(f" ID: {agency.id}")
86
+ console.print(f" Status: {agency.status}")
87
+ console.print(f" Folder: {folder_path}")
88
+ console.print(f" MCP Server: {mcp_server.name}")
89
+ console.print(f" Capabilities: {', '.join(agency.capabilities)}")
90
+
91
+ if deploy:
92
+ progress.update(task, description="Deploying agency to Docker...")
93
+
94
+ # Use the docker utilities to run the generated agency
95
+ runner = LocalDockerRunner()
96
+ deployment_info = await runner.run_agent_docker(
97
+ agent_path=Path(folder_path),
98
+ port=port or 8000,
99
+ detached=True
100
+ )
101
+
102
+ if deployment_info["success"]:
103
+ console.print(f"\nšŸš€ Deployed agency:")
104
+ console.print(f" Base URL: {deployment_info['base_url']}")
105
+ console.print(f" IATP Endpoint: {deployment_info['iatp_endpoint']}")
106
+ console.print(f" Container: {deployment_info['container_name']}")
107
+ console.print(f" Port: {deployment_info['port']}")
108
+ console.print(f"\nšŸ“ Useful commands:")
109
+ console.print(f" View logs: {deployment_info['logs_command']}")
110
+ console.print(f" Stop: {deployment_info['stop_command']}")
111
+
112
+ # Register the deployed agency if MongoDB is configured
113
+ if mongodb_uri:
114
+ registry = UtilityAgentRegistry(mongodb_uri)
115
+ try:
116
+ await registry.add_utility_agency(
117
+ agency=agency,
118
+ endpoint=deployment_info['iatp_endpoint'],
119
+ tags=["docker", "cli-deployed"]
120
+ )
121
+ console.print(f" āœ… Registered in MongoDB")
122
+ finally:
123
+ registry.close()
124
+ else:
125
+ console.print(f"āŒ Deployment failed", style="red")
126
+
127
+ return agency, folder_path
128
+
129
+ except Exception as e:
130
+ console.print(f"āŒ Error creating agency: {e}", style="red")
131
+ raise
132
+
133
+ asyncio.run(_create())
134
+
135
+
136
+ @app.command()
137
+ def register_mcp(
138
+ name: str = typer.Option(..., "--name", "-n", help="Name of the MCP server"),
139
+ url: str = typer.Option(..., "--url", "-u", help="URL of the MCP server"),
140
+ description: str = typer.Option(..., "--description", "-d", help="Description of the MCP server"),
141
+ server_type: str = typer.Option("streamable-http", "--type", "-t", help="Server type (streamable-http only)"),
142
+ capabilities: Optional[List[str]] = typer.Option(None, "--capability", "-c", help="Server capabilities"),
143
+ mongodb_uri: Optional[str] = typer.Option(None, "--mongodb-uri", help="MongoDB URI for registry")
144
+ ):
145
+ """Register an MCP server in the registry."""
146
+ async def _register():
147
+ registry = MCPServerRegistry(mongodb_uri)
148
+
149
+ try:
150
+ # Convert string to enum if necessary
151
+ if server_type == "streamable-http":
152
+ server_type_enum = MCPServerType.STREAMABLE_HTTP
153
+ else:
154
+ server_type_enum = server_type
155
+
156
+ server_id = await registry.add_mcp_server(
157
+ name=name,
158
+ url=url,
159
+ description=description,
160
+ server_type=server_type_enum,
161
+ capabilities=capabilities or []
162
+ )
163
+
164
+ console.print(f"āœ… Registered MCP server '{name}' with ID: {server_id}")
165
+
166
+ finally:
167
+ registry.close()
168
+
169
+ asyncio.run(_register())
170
+
171
+
172
+ @app.command()
173
+ def list_agencies(
174
+ mongodb_uri: Optional[str] = typer.Option(None, "--mongodb-uri", help="MongoDB URI for registry"),
175
+ active_only: bool = typer.Option(True, "--active-only", help="Show only active agencies")
176
+ ):
177
+ """List all registered utility agencies."""
178
+ async def _list():
179
+ registry = UtilityAgentRegistry(mongodb_uri)
180
+
181
+ try:
182
+ agencies = await registry.query_agencies(active_only=active_only, limit=100)
183
+
184
+ if not agencies:
185
+ console.print("No agencies found.", style="yellow")
186
+ return
187
+
188
+ table = Table(title="Registered Utility Agencies")
189
+ table.add_column("Name", style="cyan")
190
+ table.add_column("ID", style="magenta")
191
+ table.add_column("Endpoint", style="green")
192
+ table.add_column("Capabilities", style="yellow")
193
+ table.add_column("Active", style="blue")
194
+
195
+ for agency in agencies:
196
+ table.add_row(
197
+ agency.name,
198
+ agency.agency_id[:8] + "...",
199
+ str(agency.endpoint),
200
+ ", ".join(agency.capabilities[:3]) + ("..." if len(agency.capabilities) > 3 else ""),
201
+ "āœ…" if agency.is_active else "āŒ"
202
+ )
203
+
204
+ console.print(table)
205
+
206
+ finally:
207
+ registry.close()
208
+
209
+ asyncio.run(_list())
210
+
211
+
212
+ @app.command()
213
+ def list_mcp_servers(
214
+ mongodb_uri: Optional[str] = typer.Option(None, "--mongodb-uri", help="MongoDB URI for registry"),
215
+ server_type: Optional[str] = typer.Option(None, "--type", "-t", help="Filter by server type")
216
+ ):
217
+ """List all registered MCP servers."""
218
+ async def _list():
219
+ registry = MCPServerRegistry(mongodb_uri)
220
+
221
+ try:
222
+ servers = await registry.query_mcp_servers(server_type=server_type)
223
+
224
+ if not servers:
225
+ console.print("No MCP servers found.", style="yellow")
226
+ return
227
+
228
+ table = Table(title="Registered MCP Servers")
229
+ table.add_column("Name", style="cyan")
230
+ table.add_column("URL", style="green")
231
+ table.add_column("Type", style="yellow")
232
+ table.add_column("Description", style="white")
233
+ table.add_column("Capabilities", style="magenta")
234
+
235
+ for server in servers:
236
+ table.add_row(
237
+ server["name"],
238
+ server["url"],
239
+ server.get("server_type", "streamable-http"),
240
+ server["description"][:40] + "..." if len(server["description"]) > 40 else server["description"],
241
+ ", ".join(server.get("capabilities", [])[:3]) + ("..." if len(server.get("capabilities", [])) > 3 else "")
242
+ )
243
+
244
+ console.print(table)
245
+
246
+ finally:
247
+ registry.close()
248
+
249
+ asyncio.run(_list())
250
+
251
+
252
+ @app.command()
253
+ def search_agencies(
254
+ query: Optional[str] = typer.Argument(None, help="Search query"),
255
+ tags: Optional[List[str]] = typer.Option(None, "--tag", "-t", help="Filter by tags"),
256
+ capabilities: Optional[List[str]] = typer.Option(None, "--capability", "-c", help="Filter by capabilities"),
257
+ mongodb_uri: Optional[str] = typer.Option(None, "--mongodb-uri", help="MongoDB URI for registry"),
258
+ limit: int = typer.Option(10, "--limit", "-l", help="Maximum number of results")
259
+ ):
260
+ """Search for utility agencies."""
261
+ async def _search():
262
+ registry = UtilityAgentRegistry(mongodb_uri)
263
+
264
+ try:
265
+ agencies = await registry.query_agencies(
266
+ query=query,
267
+ tags=tags,
268
+ capabilities=capabilities,
269
+ active_only=True,
270
+ limit=limit
271
+ )
272
+
273
+ if not agencies:
274
+ console.print("No agencies found matching criteria.", style="yellow")
275
+ return
276
+
277
+ table = Table(title=f"Search Results ({len(agencies)} found)")
278
+ table.add_column("Name", style="cyan")
279
+ table.add_column("Description", style="white")
280
+ table.add_column("Capabilities", style="yellow")
281
+ table.add_column("Tags", style="green")
282
+
283
+ for agency in agencies:
284
+ table.add_row(
285
+ agency.name,
286
+ agency.description[:50] + "..." if len(agency.description) > 50 else agency.description,
287
+ ", ".join(agency.capabilities[:3]) + ("..." if len(agency.capabilities) > 3 else ""),
288
+ ", ".join(agency.tags[:3]) + ("..." if len(agency.tags) > 3 else "")
289
+ )
290
+
291
+ console.print(table)
292
+
293
+ finally:
294
+ registry.close()
295
+
296
+ asyncio.run(_search())
297
+
298
+
299
+ @app.command()
300
+ def deploy(
301
+ agency_path: Path = typer.Argument(..., help="Path to generated agency directory"),
302
+ port: Optional[int] = typer.Option(None, "--port", "-p", help="Port to deploy on"),
303
+ mongodb_uri: Optional[str] = typer.Option(None, "--mongodb-uri", help="MongoDB URI for registry"),
304
+ use_script: bool = typer.Option(False, "--use-script", help="Use the run_local_docker.sh script")
305
+ ):
306
+ """Deploy a utility agency from a generated directory."""
307
+ async def _deploy():
308
+ if not agency_path.exists():
309
+ console.print(f"āŒ Directory not found: {agency_path}", style="red")
310
+ return
311
+
312
+ # Check if it's a valid agency directory
313
+ required_files = ["Dockerfile", "pyproject.toml"]
314
+ missing_files = [f for f in required_files if not (agency_path / f).exists()]
315
+ if missing_files:
316
+ console.print(f"āŒ Invalid agency directory. Missing files: {', '.join(missing_files)}", style="red")
317
+ return
318
+
319
+ with Progress(
320
+ SpinnerColumn(),
321
+ TextColumn("[progress.description]{task.description}"),
322
+ console=console
323
+ ) as progress:
324
+ task = progress.add_task("Deploying agency...", total=None)
325
+
326
+ try:
327
+ if use_script:
328
+ # Use the generated run_local_docker.sh script
329
+ script_path = agency_path / "run_local_docker.sh"
330
+ if not script_path.exists():
331
+ console.print(f"āŒ run_local_docker.sh not found in {agency_path}", style="red")
332
+ return
333
+
334
+ progress.update(task, description="Running deployment script...")
335
+ use_run_local_docker_script(str(agency_path))
336
+
337
+ console.print(f"\nšŸš€ Agency deployed using run_local_docker.sh")
338
+ console.print(f" Check the script output for connection details")
339
+ else:
340
+ # Use LocalDockerRunner
341
+ runner = LocalDockerRunner()
342
+ deployment_info = await runner.run_agent_docker(
343
+ agent_path=agency_path,
344
+ port=port or 8000,
345
+ detached=True
346
+ )
347
+
348
+ if deployment_info["success"]:
349
+ console.print(f"\nšŸš€ Deployed agency from: {agency_path}")
350
+ console.print(f" Base URL: {deployment_info['base_url']}")
351
+ console.print(f" IATP Endpoint: {deployment_info['iatp_endpoint']}")
352
+ console.print(f" Container: {deployment_info['container_name']}")
353
+ console.print(f" Port: {deployment_info['port']}")
354
+ console.print(f"\nšŸ“ Useful commands:")
355
+ console.print(f" View logs: {deployment_info['logs_command']}")
356
+ console.print(f" Stop: {deployment_info['stop_command']}")
357
+
358
+ # If MongoDB URI is provided and agent_config.json exists, register it
359
+ if mongodb_uri and (agency_path / "agent_config.json").exists():
360
+ with open(agency_path / "agent_config.json", 'r') as f:
361
+ agency_data = json.load(f)
362
+
363
+ agency = UtilityAgent(**agency_data)
364
+
365
+ registry = UtilityAgentRegistry(mongodb_uri)
366
+ try:
367
+ await registry.add_utility_agency(
368
+ agency=agency,
369
+ endpoint=deployment_info['iatp_endpoint'],
370
+ tags=["docker", "cli-deployed"]
371
+ )
372
+ console.print(f" āœ… Registered in MongoDB")
373
+ finally:
374
+ registry.close()
375
+ else:
376
+ console.print(f"āŒ Deployment failed", style="red")
377
+
378
+ except Exception as e:
379
+ console.print(f"āŒ Deployment failed: {e}", style="red")
380
+ raise
381
+
382
+ asyncio.run(_deploy())
383
+
384
+
385
+ @app.command()
386
+ def find_tools(
387
+ query: Optional[str] = typer.Argument(None, help="Search query for tools"),
388
+ tags: Optional[List[str]] = typer.Option(None, "--tag", "-t", help="Filter by tags"),
389
+ capabilities: Optional[List[str]] = typer.Option(None, "--capability", "-c", help="Filter by capabilities"),
390
+ mongodb_uri: Optional[str] = typer.Option(None, "--mongodb-uri", help="MongoDB URI for registry"),
391
+ output_file: Optional[Path] = typer.Option(None, "--output", "-o", help="Save tools configuration to file")
392
+ ):
393
+ """Find utility agency tools for use in CrewAI."""
394
+ tools = create_utility_agency_tools(
395
+ mongodb_uri=mongodb_uri,
396
+ query=query,
397
+ tags=tags,
398
+ capabilities=capabilities
399
+ )
400
+
401
+ if not tools:
402
+ console.print("No tools found matching criteria.", style="yellow")
403
+ return
404
+
405
+ table = Table(title=f"Available Tools ({len(tools)} found)")
406
+ table.add_column("Tool Name", style="cyan")
407
+ table.add_column("Description", style="white")
408
+ table.add_column("Endpoint", style="green")
409
+
410
+ tools_config = []
411
+ for tool in tools:
412
+ table.add_row(
413
+ tool.name,
414
+ tool.description[:60] + "..." if len(tool.description) > 60 else tool.description,
415
+ tool.endpoint
416
+ )
417
+
418
+ tools_config.append({
419
+ "name": tool.name,
420
+ "description": tool.description,
421
+ "endpoint": tool.endpoint,
422
+ "agency_id": tool.agency_id,
423
+ "capabilities": tool.capabilities
424
+ })
425
+
426
+ console.print(table)
427
+
428
+ if output_file:
429
+ with open(output_file, 'w') as f:
430
+ json.dump(tools_config, f, indent=2)
431
+ console.print(f"\nšŸ’¾ Tools configuration saved to: {output_file}", style="green")
432
+
433
+
434
+ @app.command()
435
+ def example_crew():
436
+ """Show an example of how to use utility agencies in a CrewAI crew."""
437
+ example_code = '''
438
+ # Example: Using utility agencies in a CrewAI crew
439
+
440
+ from crewai import Agent, Crew, Task
441
+ from traia_iatp import create_utility_agency_tools
442
+
443
+ # Find and create tools from utility agencies
444
+ tools = create_utility_agency_tools(
445
+ query="weather data analysis", # Search for relevant agencies
446
+ tags=["weather", "api"], # Filter by tags
447
+ capabilities=["forecast"] # Filter by capabilities
448
+ )
449
+
450
+ # Create an agent with utility agency tools
451
+ analyst = Agent(
452
+ role="Data Analyst",
453
+ goal="Analyze weather patterns and provide insights",
454
+ backstory="You are an expert at analyzing weather data and trends.",
455
+ tools=tools, # Use the utility agency tools
456
+ allow_delegation=False,
457
+ verbose=True
458
+ )
459
+
460
+ # Create a task
461
+ analysis_task = Task(
462
+ description="Analyze the weather forecast for New York City for the next week",
463
+ expected_output="A detailed analysis of weather patterns and recommendations",
464
+ agent=analyst
465
+ )
466
+
467
+ # Create and run the crew
468
+ crew = Crew(
469
+ agents=[analyst],
470
+ tasks=[analysis_task],
471
+ verbose=True
472
+ )
473
+
474
+ result = crew.kickoff()
475
+ print(result)
476
+ '''
477
+
478
+ console.print("šŸ“š Example: Using Utility Agencies in CrewAI\n", style="bold cyan")
479
+ console.print(example_code, style="cyan")
480
+
481
+
482
+ if __name__ == "__main__":
483
+ app()
@@ -0,0 +1,10 @@
1
+ """IATP client module for A2A integration."""
2
+
3
+ from .a2a_client import UtilityAgencyTool, create_utility_agency_tools
4
+ from .crewai_a2a_tools import A2AToolSchema
5
+
6
+ __all__ = [
7
+ "UtilityAgencyTool",
8
+ "create_utility_agency_tools",
9
+ "A2AToolSchema",
10
+ ]