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.
- traia_iatp/README.md +368 -0
- traia_iatp/__init__.py +54 -0
- traia_iatp/cli/__init__.py +5 -0
- traia_iatp/cli/main.py +483 -0
- traia_iatp/client/__init__.py +10 -0
- traia_iatp/client/a2a_client.py +274 -0
- traia_iatp/client/crewai_a2a_tools.py +335 -0
- traia_iatp/client/d402_a2a_client.py +293 -0
- traia_iatp/client/grpc_a2a_tools.py +349 -0
- traia_iatp/client/root_path_a2a_client.py +1 -0
- traia_iatp/contracts/__init__.py +12 -0
- traia_iatp/contracts/iatp_contracts_config.py +263 -0
- traia_iatp/contracts/wallet_creator.py +255 -0
- traia_iatp/core/__init__.py +43 -0
- traia_iatp/core/models.py +172 -0
- traia_iatp/d402/__init__.py +55 -0
- traia_iatp/d402/chains.py +102 -0
- traia_iatp/d402/client.py +150 -0
- traia_iatp/d402/clients/__init__.py +7 -0
- traia_iatp/d402/clients/base.py +218 -0
- traia_iatp/d402/clients/httpx.py +219 -0
- traia_iatp/d402/common.py +114 -0
- traia_iatp/d402/encoding.py +28 -0
- traia_iatp/d402/examples/client_example.py +197 -0
- traia_iatp/d402/examples/server_example.py +171 -0
- traia_iatp/d402/facilitator.py +453 -0
- traia_iatp/d402/fastapi_middleware/__init__.py +6 -0
- traia_iatp/d402/fastapi_middleware/middleware.py +225 -0
- traia_iatp/d402/fastmcp_middleware.py +147 -0
- traia_iatp/d402/mcp_middleware.py +434 -0
- traia_iatp/d402/middleware.py +193 -0
- traia_iatp/d402/models.py +116 -0
- traia_iatp/d402/networks.py +98 -0
- traia_iatp/d402/path.py +43 -0
- traia_iatp/d402/payment_introspection.py +104 -0
- traia_iatp/d402/payment_signing.py +178 -0
- traia_iatp/d402/paywall.py +119 -0
- traia_iatp/d402/starlette_middleware.py +326 -0
- traia_iatp/d402/template.py +1 -0
- traia_iatp/d402/types.py +300 -0
- traia_iatp/mcp/__init__.py +18 -0
- traia_iatp/mcp/client.py +201 -0
- traia_iatp/mcp/d402_mcp_tool_adapter.py +361 -0
- traia_iatp/mcp/mcp_agent_template.py +481 -0
- traia_iatp/mcp/templates/Dockerfile.j2 +80 -0
- traia_iatp/mcp/templates/README.md.j2 +310 -0
- traia_iatp/mcp/templates/cursor-rules.md.j2 +520 -0
- traia_iatp/mcp/templates/deployment_params.json.j2 +20 -0
- traia_iatp/mcp/templates/docker-compose.yml.j2 +32 -0
- traia_iatp/mcp/templates/dockerignore.j2 +47 -0
- traia_iatp/mcp/templates/env.example.j2 +57 -0
- traia_iatp/mcp/templates/gitignore.j2 +77 -0
- traia_iatp/mcp/templates/mcp_health_check.py.j2 +150 -0
- traia_iatp/mcp/templates/pyproject.toml.j2 +32 -0
- traia_iatp/mcp/templates/pyrightconfig.json.j2 +22 -0
- traia_iatp/mcp/templates/run_local_docker.sh.j2 +390 -0
- traia_iatp/mcp/templates/server.py.j2 +175 -0
- traia_iatp/mcp/traia_mcp_adapter.py +543 -0
- traia_iatp/preview_diagrams.html +181 -0
- traia_iatp/registry/__init__.py +26 -0
- traia_iatp/registry/atlas_search_indexes.json +280 -0
- traia_iatp/registry/embeddings.py +298 -0
- traia_iatp/registry/iatp_search_api.py +846 -0
- traia_iatp/registry/mongodb_registry.py +771 -0
- traia_iatp/registry/readmes/ATLAS_SEARCH_INDEXES.md +252 -0
- traia_iatp/registry/readmes/ATLAS_SEARCH_SETUP.md +134 -0
- traia_iatp/registry/readmes/AUTHENTICATION_UPDATE.md +124 -0
- traia_iatp/registry/readmes/EMBEDDINGS_SETUP.md +172 -0
- traia_iatp/registry/readmes/IATP_SEARCH_API_GUIDE.md +257 -0
- traia_iatp/registry/readmes/MONGODB_X509_AUTH.md +208 -0
- traia_iatp/registry/readmes/README.md +251 -0
- traia_iatp/registry/readmes/REFACTORING_SUMMARY.md +191 -0
- traia_iatp/scripts/__init__.py +2 -0
- traia_iatp/scripts/create_wallet.py +244 -0
- traia_iatp/server/__init__.py +15 -0
- traia_iatp/server/a2a_server.py +219 -0
- traia_iatp/server/example_template_usage.py +72 -0
- traia_iatp/server/iatp_server_agent_generator.py +237 -0
- traia_iatp/server/iatp_server_template_generator.py +235 -0
- traia_iatp/server/templates/.dockerignore.j2 +48 -0
- traia_iatp/server/templates/Dockerfile.j2 +49 -0
- traia_iatp/server/templates/README.md +137 -0
- traia_iatp/server/templates/README.md.j2 +425 -0
- traia_iatp/server/templates/__init__.py +1 -0
- traia_iatp/server/templates/__main__.py.j2 +565 -0
- traia_iatp/server/templates/agent.py.j2 +94 -0
- traia_iatp/server/templates/agent_config.json.j2 +22 -0
- traia_iatp/server/templates/agent_executor.py.j2 +279 -0
- traia_iatp/server/templates/docker-compose.yml.j2 +23 -0
- traia_iatp/server/templates/env.example.j2 +84 -0
- traia_iatp/server/templates/gitignore.j2 +78 -0
- traia_iatp/server/templates/grpc_server.py.j2 +218 -0
- traia_iatp/server/templates/pyproject.toml.j2 +78 -0
- traia_iatp/server/templates/run_local_docker.sh.j2 +103 -0
- traia_iatp/server/templates/server.py.j2 +243 -0
- traia_iatp/special_agencies/__init__.py +4 -0
- traia_iatp/special_agencies/registry_search_agency.py +392 -0
- traia_iatp/utils/__init__.py +10 -0
- traia_iatp/utils/docker_utils.py +251 -0
- traia_iatp/utils/general.py +64 -0
- traia_iatp/utils/iatp_utils.py +126 -0
- traia_iatp-0.1.29.dist-info/METADATA +423 -0
- traia_iatp-0.1.29.dist-info/RECORD +107 -0
- traia_iatp-0.1.29.dist-info/WHEEL +5 -0
- traia_iatp-0.1.29.dist-info/entry_points.txt +2 -0
- traia_iatp-0.1.29.dist-info/licenses/LICENSE +21 -0
- traia_iatp-0.1.29.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# A2A Utility Agency Templates
|
|
2
|
+
|
|
3
|
+
This directory contains Jinja2 templates for generating utility agencies that wrap MCP servers and expose them via the A2A (Agent-to-Agent) protocol.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
These templates follow the pattern established by the [A2A CrewAI examples](https://github.com/google-a2a/a2a-samples/tree/main/samples/python/agents/crewai) to create standardized A2A servers that:
|
|
8
|
+
|
|
9
|
+
1. **Wrap MCP Servers**: Connect to any MCP (Model Context Protocol) server
|
|
10
|
+
2. **Use CrewAI**: Leverage CrewAI agents to process requests intelligently
|
|
11
|
+
3. **Expose A2A Interface**: Provide a standard A2A protocol interface for agent-to-agent communication
|
|
12
|
+
|
|
13
|
+
## Templates
|
|
14
|
+
|
|
15
|
+
### Core Templates
|
|
16
|
+
|
|
17
|
+
- **`agent.py.j2`** - CrewAI agent implementation that wraps the MCP server
|
|
18
|
+
- **`agent_executor.py.j2`** - A2A executor that interfaces the CrewAI agent with A2A protocol
|
|
19
|
+
- **`__main__.py.j2`** - Main entry point that initializes and starts the A2A server
|
|
20
|
+
|
|
21
|
+
### Simple Server Template
|
|
22
|
+
|
|
23
|
+
- **`server.py.j2`** - All-in-one simplified implementation combining agent, executor, and server
|
|
24
|
+
|
|
25
|
+
### Configuration Templates
|
|
26
|
+
|
|
27
|
+
- **`agency_config.json.j2`** - Agency configuration file
|
|
28
|
+
- **`pyproject.toml.j2`** - Python project dependencies
|
|
29
|
+
- **`Dockerfile.j2`** - Docker container configuration
|
|
30
|
+
- **`README.md.j2`** - Documentation for the generated agency
|
|
31
|
+
|
|
32
|
+
## Template Variables
|
|
33
|
+
|
|
34
|
+
The templates expect the following variables:
|
|
35
|
+
|
|
36
|
+
### Required Variables
|
|
37
|
+
- `agency_name` - Human-readable name of the agency
|
|
38
|
+
- `agency_id` - Unique identifier for the agency
|
|
39
|
+
- `mcp_server_name` - Name of the MCP server
|
|
40
|
+
- `mcp_server_url` - URL or path to the MCP server
|
|
41
|
+
- `mcp_server_description` - Description of the MCP server
|
|
42
|
+
- `mcp_server_capabilities` - List of capabilities provided
|
|
43
|
+
|
|
44
|
+
### Optional Variables
|
|
45
|
+
- `agency_description` - Description of the agency (auto-generated if not provided)
|
|
46
|
+
- `agency_version` - Version of the agency (default: "0.1.0")
|
|
47
|
+
- `mcp_server_type` - Type of MCP server: "stdio", "http", etc. (default: "stdio")
|
|
48
|
+
- `expose_individual_tools` - Whether to expose each MCP tool as a separate A2A skill
|
|
49
|
+
- `auth_required` - Whether authentication is required
|
|
50
|
+
- `auth_schemes` - List of auth schemes if auth is required
|
|
51
|
+
- `skill_examples` - Example prompts for the main skill
|
|
52
|
+
- `additional_dependencies` - Extra Python dependencies
|
|
53
|
+
- `use_simple_server` - Whether to use the simplified server.py template
|
|
54
|
+
|
|
55
|
+
### Auto-generated Variables
|
|
56
|
+
- `class_name` - PascalCase class name derived from agency_name
|
|
57
|
+
- `package_name` - Python package name (snake_case)
|
|
58
|
+
- `module_name` - Python module name
|
|
59
|
+
- `docker_image` - Docker image name
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
Use the `UtilityAgencyTemplateGenerator` class to generate agencies:
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from traia_iatp.server.template_generator import UtilityAgencyTemplateGenerator
|
|
67
|
+
|
|
68
|
+
generator = UtilityAgencyTemplateGenerator()
|
|
69
|
+
output_path = generator.generate_agency(
|
|
70
|
+
output_dir="path/to/output",
|
|
71
|
+
agency_name="My MCP Agency",
|
|
72
|
+
agency_id="my-mcp-agency",
|
|
73
|
+
mcp_server_name="my-mcp-server",
|
|
74
|
+
mcp_server_url="http://localhost:3000",
|
|
75
|
+
mcp_server_description="Description of the MCP server",
|
|
76
|
+
mcp_server_capabilities=["capability1", "capability2"],
|
|
77
|
+
use_simple_server=True # For simpler deployments
|
|
78
|
+
)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Generated Structure
|
|
82
|
+
|
|
83
|
+
### Simple Server (use_simple_server=True)
|
|
84
|
+
```
|
|
85
|
+
output_dir/
|
|
86
|
+
├── server.py # All-in-one A2A server
|
|
87
|
+
├── agency_config.json # Configuration
|
|
88
|
+
├── pyproject.toml # Dependencies
|
|
89
|
+
├── Dockerfile # Container config
|
|
90
|
+
├── README.md # Documentation
|
|
91
|
+
├── docker-compose.yml # Local development
|
|
92
|
+
├── .gitignore # Git ignore rules
|
|
93
|
+
└── .env.example # Environment variables example
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Modular Structure (use_simple_server=False)
|
|
97
|
+
```
|
|
98
|
+
output_dir/
|
|
99
|
+
├── package_name/
|
|
100
|
+
│ ├── __init__.py
|
|
101
|
+
│ ├── agent.py # CrewAI agent
|
|
102
|
+
│ ├── agent_executor.py # A2A executor
|
|
103
|
+
│ └── __main__.py # Entry point
|
|
104
|
+
├── agency_config.json
|
|
105
|
+
├── pyproject.toml
|
|
106
|
+
├── Dockerfile
|
|
107
|
+
├── README.md
|
|
108
|
+
├── docker-compose.yml
|
|
109
|
+
├── .gitignore
|
|
110
|
+
└── .env.example
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## A2A Protocol Compliance
|
|
114
|
+
|
|
115
|
+
The generated agencies follow the A2A protocol by:
|
|
116
|
+
|
|
117
|
+
1. **Agent Card**: Exposing agent capabilities at `/.well-known/agent.json`
|
|
118
|
+
2. **Task Processing**: Handling tasks via POST to `/tasks/send`
|
|
119
|
+
3. **Text I/O**: Supporting text input and output by default
|
|
120
|
+
4. **Request Context**: Processing request context and metadata
|
|
121
|
+
5. **Error Handling**: Proper error responses in A2A format
|
|
122
|
+
|
|
123
|
+
## Next Steps
|
|
124
|
+
|
|
125
|
+
After generating an agency:
|
|
126
|
+
|
|
127
|
+
1. **Test Locally**: Run with `uv run python -m package_name` or `python server.py`
|
|
128
|
+
2. **Build Docker**: `docker build -t agency-name .`
|
|
129
|
+
3. **Push to GitHub**: Use the push_agency_to_repo functionality
|
|
130
|
+
4. **Deploy to Cloud**: Use cloudrun_deployer for Google Cloud Run
|
|
131
|
+
5. **Register**: Add to MongoDB registry for discovery
|
|
132
|
+
|
|
133
|
+
## References
|
|
134
|
+
|
|
135
|
+
- [A2A Protocol Documentation](https://github.com/google-a2a/A2A)
|
|
136
|
+
- [A2A CrewAI Examples](https://github.com/google-a2a/a2a-samples/tree/main/samples/python/agents/crewai)
|
|
137
|
+
- [MCP Protocol](https://github.com/anthropics/model-context-protocol)
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
# {{ agent_name }}
|
|
2
|
+
|
|
3
|
+
{{ agent_description }}
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This utility agent provides access to {{ mcp_server_name }} capabilities through the A2A (Agent-to-Agent) protocol. It acts as a bridge between AI agents and the {{ mcp_server_name }} MCP server.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **A2A Protocol Support**: Full implementation of the A2A protocol for agent communication
|
|
12
|
+
- **{{ mcp_server_name }} Integration**: Direct access to {{ mcp_server_name }} tools and capabilities
|
|
13
|
+
- **HTTP/2 Multiplexing**: High-performance concurrent request handling
|
|
14
|
+
- **SSE Streaming**: Real-time streaming responses for compatible operations
|
|
15
|
+
- **Async Operations**: Built with modern async Python for optimal performance
|
|
16
|
+
- **Docker Support**: Easy deployment with Docker and docker-compose
|
|
17
|
+
- **Health Monitoring**: Built-in health check endpoints
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### Using Docker (Recommended)
|
|
22
|
+
|
|
23
|
+
1. Copy the environment configuration:
|
|
24
|
+
```bash
|
|
25
|
+
cp .env.example .env
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
2. Configure your environment variables in `.env` (especially API keys if needed)
|
|
29
|
+
|
|
30
|
+
3. Run with Docker:
|
|
31
|
+
```bash
|
|
32
|
+
chmod +x run_local_docker.sh
|
|
33
|
+
./run_local_docker.sh
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or with docker-compose:
|
|
37
|
+
```bash
|
|
38
|
+
docker-compose up
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Manual Setup
|
|
42
|
+
|
|
43
|
+
1. Install dependencies:
|
|
44
|
+
```bash
|
|
45
|
+
uv sync
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
2. Copy and configure environment:
|
|
49
|
+
```bash
|
|
50
|
+
cp .env.example .env
|
|
51
|
+
# Edit .env with your configuration
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
3. Run the server:
|
|
55
|
+
```bash
|
|
56
|
+
uv run python -m {{ agent_id }}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Configuration
|
|
60
|
+
|
|
61
|
+
All configuration is managed through environment variables. See `.env.example` for available options:
|
|
62
|
+
|
|
63
|
+
- `PORT`: Server port (default: 8000)
|
|
64
|
+
- `HOST`: Server host (default: 0.0.0.0)
|
|
65
|
+
- `LLM_MODEL`: Language model to use (default: openai/gpt-4.1)
|
|
66
|
+
- `DEBUG_PROTOCOL`: Enable protocol-level debugging (default: false)
|
|
67
|
+
- `USE_TLS`: Enable TLS/HTTPS (default: false)
|
|
68
|
+
- API keys and other service-specific configuration
|
|
69
|
+
|
|
70
|
+
## API Endpoints
|
|
71
|
+
|
|
72
|
+
### A2A Protocol Endpoints
|
|
73
|
+
|
|
74
|
+
The A2A (Agent-to-Agent) protocol defines a minimal set of endpoints for agent communication:
|
|
75
|
+
|
|
76
|
+
#### 1. **`POST /` (Root Path)** - Main JSON-RPC Endpoint
|
|
77
|
+
This is the primary endpoint for all A2A communication. Despite what you might expect, the A2A library creates the JSON-RPC endpoint at the root path (`/`), not at `/a2a`.
|
|
78
|
+
|
|
79
|
+
**Supported Methods:**
|
|
80
|
+
- `message/send` - Send a message to the agent
|
|
81
|
+
- `tasks/get` - Get task status
|
|
82
|
+
- `tasks/list` - List tasks
|
|
83
|
+
|
|
84
|
+
**Example Request:**
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"jsonrpc": "2.0",
|
|
88
|
+
"method": "message/send",
|
|
89
|
+
"id": "msg-123",
|
|
90
|
+
"params": {
|
|
91
|
+
"message": {
|
|
92
|
+
"messageId": "msg-456",
|
|
93
|
+
"role": "user",
|
|
94
|
+
"parts": [{"text": "Get BTC price"}]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### 2. **`GET /.well-known/agent.json`** - Agent Card
|
|
101
|
+
Returns the agent's capabilities, skills, and metadata following the A2A standard.
|
|
102
|
+
|
|
103
|
+
**Example Response:**
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"name": "{{ agent_id }}",
|
|
107
|
+
"description": "{{ agent_description }}",
|
|
108
|
+
"version": "{{ agent_version }}",
|
|
109
|
+
"capabilities": {
|
|
110
|
+
"streaming": true,
|
|
111
|
+
"pushNotifications": false,
|
|
112
|
+
"stateTransitionHistory": true
|
|
113
|
+
},
|
|
114
|
+
"skills": [...]
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### 3. **`POST /a2a/tasks/subscribe`** - SSE Task Subscription
|
|
119
|
+
Subscribe to real-time updates for a specific task using Server-Sent Events (SSE).
|
|
120
|
+
|
|
121
|
+
**Request Body:**
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"jsonrpc": "2.0",
|
|
125
|
+
"method": "tasks/sendSubscribe",
|
|
126
|
+
"params": {
|
|
127
|
+
"id": "task-id",
|
|
128
|
+
"historyLength": 0
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### 4. **`POST /a2a/tasks/resubscribe`** - SSE Task Resubscription
|
|
134
|
+
Resume a subscription to task events, useful for handling connection drops.
|
|
135
|
+
|
|
136
|
+
### How Streaming Works
|
|
137
|
+
|
|
138
|
+
**Important:** Streaming uses the SAME root endpoint (`/`) as regular requests. The difference is in the request parameters:
|
|
139
|
+
|
|
140
|
+
**Regular Request:**
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"params": {
|
|
144
|
+
"message": {...},
|
|
145
|
+
"configuration": null // or omitted
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Streaming Request:**
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"params": {
|
|
154
|
+
"message": {...},
|
|
155
|
+
"configuration": {
|
|
156
|
+
"output_mode": "text/event-stream" // This enables streaming!
|
|
157
|
+
},
|
|
158
|
+
"metadata": {"streaming": true}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
When the server receives `output_mode: "text/event-stream"`, it:
|
|
164
|
+
1. Returns a task ID immediately
|
|
165
|
+
2. Processes the request asynchronously
|
|
166
|
+
3. Streams results via SSE if the client subscribes to `/a2a/tasks/subscribe`
|
|
167
|
+
|
|
168
|
+
### What About `/health` and `/info`?
|
|
169
|
+
|
|
170
|
+
These endpoints are **NOT** part of the A2A protocol standard. The A2A protocol is intentionally minimal, focusing only on agent communication. Health monitoring should be implemented at the infrastructure level (e.g., container orchestration health checks).
|
|
171
|
+
|
|
172
|
+
## A2A Operation Modes
|
|
173
|
+
|
|
174
|
+
This utility agent supports two primary operation modes through the A2A protocol:
|
|
175
|
+
|
|
176
|
+
### 1. Synchronous Mode (JSON-RPC)
|
|
177
|
+
|
|
178
|
+
For simple request-response patterns:
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
import httpx
|
|
182
|
+
|
|
183
|
+
# Direct JSON-RPC request to root endpoint
|
|
184
|
+
request = {
|
|
185
|
+
"jsonrpc": "2.0",
|
|
186
|
+
"method": "message/send",
|
|
187
|
+
"id": "req-123",
|
|
188
|
+
"params": {
|
|
189
|
+
"message": {
|
|
190
|
+
"messageId": "msg-456",
|
|
191
|
+
"role": "user",
|
|
192
|
+
"parts": [{"text": "Get BTC price"}]
|
|
193
|
+
}
|
|
194
|
+
# Note: no configuration or configuration: null for sync mode
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
response = httpx.post("http://localhost:8000/", json=request)
|
|
199
|
+
result = response.json()
|
|
200
|
+
print(result["result"]["parts"][0]["text"])
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**How it works:**
|
|
204
|
+
- Client sends a `message/send` request to `/` (root path)
|
|
205
|
+
- No `configuration` parameter or `configuration: null`
|
|
206
|
+
- Server processes the request synchronously
|
|
207
|
+
- Server returns a complete response immediately
|
|
208
|
+
- No task ID, no streaming, no status updates
|
|
209
|
+
|
|
210
|
+
### 2. Asynchronous Streaming Mode (SSE)
|
|
211
|
+
|
|
212
|
+
For real-time updates and streaming responses:
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
import httpx
|
|
216
|
+
import json
|
|
217
|
+
|
|
218
|
+
# Step 1: Send streaming request to root endpoint
|
|
219
|
+
request = {
|
|
220
|
+
"jsonrpc": "2.0",
|
|
221
|
+
"method": "message/send",
|
|
222
|
+
"id": "req-123",
|
|
223
|
+
"params": {
|
|
224
|
+
"message": {
|
|
225
|
+
"messageId": "msg-456",
|
|
226
|
+
"role": "user",
|
|
227
|
+
"parts": [{"text": "Stream market data for BTC"}]
|
|
228
|
+
},
|
|
229
|
+
"configuration": {
|
|
230
|
+
"output_mode": "text/event-stream" # This enables streaming!
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
response = httpx.post("http://localhost:8000/", json=request)
|
|
236
|
+
result = response.json()
|
|
237
|
+
task_id = result["result"]["id"] # Get task ID
|
|
238
|
+
|
|
239
|
+
# Step 2: Subscribe to SSE events
|
|
240
|
+
subscribe_request = {
|
|
241
|
+
"jsonrpc": "2.0",
|
|
242
|
+
"method": "tasks/sendSubscribe",
|
|
243
|
+
"params": {
|
|
244
|
+
"id": task_id,
|
|
245
|
+
"historyLength": 0
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
# Use SSE client to receive streaming events
|
|
250
|
+
with httpx.stream("POST", "http://localhost:8000/a2a/tasks/subscribe",
|
|
251
|
+
json=subscribe_request) as sse_response:
|
|
252
|
+
for line in sse_response.iter_lines():
|
|
253
|
+
if line.startswith("data: "):
|
|
254
|
+
event_data = json.loads(line[6:])
|
|
255
|
+
print(f"Event: {event_data}")
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**How it works:**
|
|
259
|
+
- Client sends a `message/send` request to `/` with `output_mode: "text/event-stream"`
|
|
260
|
+
- Server returns a `Task` object with an ID immediately
|
|
261
|
+
- Client subscribes to `/a2a/tasks/subscribe` endpoint for SSE events
|
|
262
|
+
- Server streams events: connection, message chunks, status updates, completion
|
|
263
|
+
|
|
264
|
+
## MCP Server Details
|
|
265
|
+
|
|
266
|
+
**Server**: {{ mcp_server_name }}
|
|
267
|
+
**URL**: {{ mcp_server_url }}
|
|
268
|
+
**Type**: {{ mcp_server_type }}
|
|
269
|
+
|
|
270
|
+
### Available Capabilities
|
|
271
|
+
|
|
272
|
+
{% for capability in mcp_server_capabilities %}
|
|
273
|
+
- {{ capability }}
|
|
274
|
+
{% endfor %}
|
|
275
|
+
|
|
276
|
+
## Performance Features
|
|
277
|
+
|
|
278
|
+
### HTTP/2 Multiplexing
|
|
279
|
+
|
|
280
|
+
The server supports HTTP/2 for improved performance:
|
|
281
|
+
- Multiple concurrent requests over a single TCP connection
|
|
282
|
+
- Reduced latency and overhead
|
|
283
|
+
- Up to 100 concurrent streams per connection
|
|
284
|
+
|
|
285
|
+
### Thread Pool Execution
|
|
286
|
+
|
|
287
|
+
CrewAI operations run in a dedicated thread pool:
|
|
288
|
+
- Prevents blocking the async event loop
|
|
289
|
+
- Enables true concurrent request processing
|
|
290
|
+
- 10 worker threads by default
|
|
291
|
+
|
|
292
|
+
## Debugging
|
|
293
|
+
|
|
294
|
+
Enable protocol-level debugging for troubleshooting:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
DEBUG_PROTOCOL=true ./run_local_docker.sh
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
This will log:
|
|
301
|
+
- HTTP version and protocol details
|
|
302
|
+
- Request/response timing
|
|
303
|
+
- Connection multiplexing information
|
|
304
|
+
- A2A message flow
|
|
305
|
+
|
|
306
|
+
## Usage Examples
|
|
307
|
+
|
|
308
|
+
### Basic Request
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
import httpx
|
|
312
|
+
|
|
313
|
+
# Get agent info
|
|
314
|
+
response = httpx.get("http://localhost:8000/.well-known/agent.json")
|
|
315
|
+
info = response.json()
|
|
316
|
+
|
|
317
|
+
# Send a message via A2A (note: endpoint is at root "/", not "/a2a")
|
|
318
|
+
request = {
|
|
319
|
+
"jsonrpc": "2.0",
|
|
320
|
+
"method": "message/send",
|
|
321
|
+
"params": {
|
|
322
|
+
"message": {
|
|
323
|
+
"messageId": "msg-123",
|
|
324
|
+
"role": "user",
|
|
325
|
+
"parts": [{"text": "Get current BTC price"}]
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
"id": 1
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
response = httpx.post("http://localhost:8000/", json=request) # Root path!
|
|
332
|
+
result = response.json()
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Using A2A Client Library
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
from a2a.client import A2AClient, A2ACardResolver
|
|
339
|
+
import httpx
|
|
340
|
+
|
|
341
|
+
# Create HTTP/2 enabled client
|
|
342
|
+
httpx_client = httpx.AsyncClient(
|
|
343
|
+
timeout=httpx.Timeout(30.0),
|
|
344
|
+
transport=httpx.AsyncHTTPTransport(http2=True)
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# Discover agent card
|
|
348
|
+
card_resolver = A2ACardResolver(
|
|
349
|
+
httpx_client=httpx_client,
|
|
350
|
+
base_url="http://localhost:8000"
|
|
351
|
+
)
|
|
352
|
+
agent_card = await card_resolver.get_agent_card()
|
|
353
|
+
|
|
354
|
+
# Create A2A client (note: uses base URL, not /a2a)
|
|
355
|
+
client = A2AClient(
|
|
356
|
+
httpx_client=httpx_client,
|
|
357
|
+
agent_card=agent_card,
|
|
358
|
+
url="http://localhost:8000" # Root URL, not /a2a!
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
# Simple request
|
|
362
|
+
response = await client.send_message("What's the BTC/USDT price?")
|
|
363
|
+
print(response.result)
|
|
364
|
+
|
|
365
|
+
# Streaming request
|
|
366
|
+
streaming_request = {
|
|
367
|
+
"message": {"role": "user", "parts": [{"text": "Stream market data"}]},
|
|
368
|
+
"configuration": {"output_mode": "text/event-stream"}
|
|
369
|
+
}
|
|
370
|
+
async for chunk in client.send_message_streaming(streaming_request):
|
|
371
|
+
print(chunk)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Development
|
|
375
|
+
|
|
376
|
+
### Running Tests
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
uv run pytest
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Building Docker Image
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
docker build -t {{ agent_id }} .
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## Deployment
|
|
389
|
+
|
|
390
|
+
This utility agent can be deployed to:
|
|
391
|
+
- Google Cloud Run (recommended for serverless)
|
|
392
|
+
- AWS ECS/Fargate
|
|
393
|
+
- Kubernetes
|
|
394
|
+
- Any container hosting platform
|
|
395
|
+
|
|
396
|
+
For production deployments, consider:
|
|
397
|
+
- Setting up proper TLS certificates
|
|
398
|
+
- Configuring appropriate resource limits
|
|
399
|
+
- Implementing rate limiting
|
|
400
|
+
- Setting up monitoring and logging
|
|
401
|
+
|
|
402
|
+
## Troubleshooting
|
|
403
|
+
|
|
404
|
+
### 503 Service Unavailable
|
|
405
|
+
- Check server logs: `docker logs -f {{ agent_id }}-local`
|
|
406
|
+
- Ensure MCP server is accessible
|
|
407
|
+
- Verify environment variables are set correctly
|
|
408
|
+
|
|
409
|
+
### Connection Timeouts
|
|
410
|
+
- Default timeout is 60 seconds
|
|
411
|
+
- For long-running operations, use streaming mode
|
|
412
|
+
- Check if CrewAI operations are completing
|
|
413
|
+
|
|
414
|
+
### HTTP/2 Not Working
|
|
415
|
+
- HTTP/2 requires TLS in most client libraries
|
|
416
|
+
- Use `USE_TLS=true` for HTTPS support
|
|
417
|
+
- Check client HTTP/2 configuration
|
|
418
|
+
|
|
419
|
+
## License
|
|
420
|
+
|
|
421
|
+
[Your License Here]
|
|
422
|
+
|
|
423
|
+
## Support
|
|
424
|
+
|
|
425
|
+
For issues and questions, please contact [your-support-email]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Template files for generating A2A utility agencies
|