Skip to content

Commit 7404d2f

Browse files
committed
Optimize the code format
1 parent 2029ee7 commit 7404d2f

File tree

1 file changed

+79
-27
lines changed

1 file changed

+79
-27
lines changed

veadk/a2a/remote_ve_agent.py

Lines changed: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,38 +36,52 @@ def _convert_agent_card_dict_to_obj(agent_card_dict: dict) -> AgentCard:
3636
class RemoteVeAgent(RemoteA2aAgent):
3737
"""Connect to a remote agent on the VeFaaS platform.
3838
39-
This class provides an interface to remotely connect with an agent deployed on the VeFaaS platform. It automatically fetches the agent card (metadata) and configures an HTTP client for secure communication. Authentication can be handled either via a bearer token in the HTTP header or via a query string parameter.
39+
This class provides an interface to remotely connect with an agent deployed on the
40+
VeFaaS platform. It automatically fetches the agent card (metadata) and configures
41+
an HTTP client for secure communication.
4042
41-
The class extends `RemoteA2aAgent` to provide compatibility with the A2A (Agent-to-Agent) communication layer.
43+
The class extends `RemoteA2aAgent` to provide compatibility with the A2A
44+
(Agent-to-Agent) communication layer.
4245
43-
This constructor connects to a remote VeFaaS agent endpoint, retrieves its metadata (`agent_card`), and sets up an asynchronous HTTP client (`httpx.AsyncClient`) for subsequent communication. Depending on the provided authentication parameters, it supports three connection modes:
44-
- **No authentication:** Directly fetches the agent card.
45-
- **Header authentication:** Sends a bearer token in the `Authorization` header.
46-
- **Query string authentication:** Appends the token to the URL query.
46+
This constructor handles agent discovery and HTTP client setup. It determines the
47+
agent's URL, fetches its metadata (`agent_card`), and prepares an
48+
`httpx.AsyncClient` for subsequent communication. You can either provide a URL
49+
directly, or pass a pre-configured `httpx.AsyncClient` with a `base_url`.
50+
51+
Authentication can be handled via a bearer token in the HTTP header or via a
52+
query string parameter. If a custom `httpx_client` is provided, authentication
53+
details will be added to it.
4754
4855
Attributes:
4956
name (str):
5057
A unique name identifying this remote agent instance.
51-
url (str):
52-
The base URL of the remote agent on the VeFaaS platform.
53-
auth_token (str | None):
54-
Optional authentication token used for secure access.
55-
If not provided, the agent will be accessed without authentication.
58+
url (Optional[str]):
59+
The base URL of the remote agent. This is optional if an `httpx_client`
60+
with a configured `base_url` is provided. If both are given, they must
61+
not conflict.
62+
auth_token (Optional[str]):
63+
Optional authentication token used for secure access. If not provided,
64+
the agent will be accessed without authentication.
5665
auth_method (Literal["header", "querystring"] | None):
5766
The method of attaching the authentication token.
5867
- `"header"`: Token is passed via HTTP `Authorization` header.
5968
- `"querystring"`: Token is passed as a query parameter.
60-
- `None`: No authentication used.
69+
httpx_client (Optional[httpx.AsyncClient]):
70+
An optional, pre-configured `httpx.AsyncClient` to use for communication.
71+
This allows for client sharing and advanced configurations (e.g., proxies).
72+
If its `base_url` is set, it will be used as the agent's location.
6173
6274
Raises:
6375
ValueError:
64-
If an unsupported `auth_method` is provided when `auth_token` is set.
76+
- If `url` and `httpx_client.base_url` are both provided and conflict.
77+
- If neither `url` nor an `httpx_client` with a `base_url` is provided.
78+
- If an unsupported `auth_method` is provided when `auth_token` is set.
6579
requests.RequestException:
6680
If fetching the agent card from the remote URL fails.
6781
6882
Examples:
6983
```python
70-
# Example 1: No authentication
84+
# Example 1: Connect using a URL
7185
agent = RemoteVeAgent(
7286
name="public_agent",
7387
url="https://vefaas.example.com/agents/public"
@@ -81,24 +95,45 @@ class RemoteVeAgent(RemoteA2aAgent):
8195
auth_method="header"
8296
)
8397
84-
# Example 3: Using token in query string
98+
# Example 3: Using a pre-configured httpx_client
99+
import httpx
100+
client = httpx.AsyncClient(
101+
base_url="https://vefaas.example.com/agents/query",
102+
timeout=600
103+
)
85104
agent = RemoteVeAgent(
86105
name="query_agent",
87-
url="https://vefaas.example.com/agents/query",
88106
auth_token="my_secret_token",
89-
auth_method="querystring"
107+
auth_method="querystring",
108+
httpx_client=client
90109
)
91110
```
92111
"""
93112

94113
def __init__(
95114
self,
96115
name: str,
97-
url: str,
98-
auth_token: str | None = None,
116+
url: Optional[str] = None,
117+
auth_token: Optional[str] = None,
99118
auth_method: Literal["header", "querystring"] | None = None,
100119
httpx_client: Optional[httpx.AsyncClient] = None,
101120
):
121+
# Determine the effective URL for the agent and handle conflicts.
122+
effective_url = url
123+
if httpx_client and httpx_client.base_url:
124+
client_url_str = str(httpx_client.base_url).rstrip("/")
125+
if url and url.rstrip("/") != client_url_str:
126+
raise ValueError(
127+
f"The `url` parameter ('{url}') conflicts with the `base_url` of the provided "
128+
f"httpx_client ('{client_url_str}'). Please provide only one or ensure they match."
129+
)
130+
effective_url = client_url_str
131+
132+
if not effective_url:
133+
raise ValueError(
134+
"Could not determine agent URL. Please provide the `url` parameter or an `httpx_client` with a configured `base_url`."
135+
)
136+
102137
req_headers = {}
103138
req_params = {}
104139

@@ -107,40 +142,57 @@ def __init__(
107142
req_headers = {"Authorization": f"Bearer {auth_token}"}
108143
elif auth_method == "querystring":
109144
req_params = {"token": auth_token}
110-
else:
145+
elif auth_method:
111146
raise ValueError(
112147
f"Unsupported auth method {auth_method}, use `header` or `querystring` instead."
113148
)
114149

115150
agent_card_dict = requests.get(
116-
url + AGENT_CARD_WELL_KNOWN_PATH, headers=req_headers, params=req_params
151+
effective_url + AGENT_CARD_WELL_KNOWN_PATH,
152+
headers=req_headers,
153+
params=req_params,
117154
).json()
118155
# replace agent_card_url with actual host
119-
agent_card_dict["url"] = url
156+
agent_card_dict["url"] = effective_url
120157

121158
agent_card_object = _convert_agent_card_dict_to_obj(agent_card_dict)
122159

123160
logger.debug(f"Agent card of {name}: {agent_card_object}")
124161

162+
client_was_provided = httpx_client is not None
125163
client_to_use = httpx_client
126-
if auth_token:
127-
if client_to_use:
164+
165+
if client_was_provided:
166+
# If a client was provided, update it with auth info
167+
if auth_token:
128168
if auth_method == "header":
129169
client_to_use.headers.update(req_headers)
130170
elif auth_method == "querystring":
131171
new_params = dict(client_to_use.params)
132172
new_params.update(req_params)
133173
client_to_use.params = new_params
134-
else:
174+
else:
175+
# If no client was provided, create a new one with auth info
176+
if auth_token:
135177
if auth_method == "header":
136178
client_to_use = httpx.AsyncClient(
137-
base_url=url, headers=req_headers, timeout=600
179+
base_url=effective_url, headers=req_headers, timeout=600
138180
)
139181
elif auth_method == "querystring":
140182
client_to_use = httpx.AsyncClient(
141-
base_url=url, params=req_params, timeout=600
183+
base_url=effective_url, params=req_params, timeout=600
142184
)
185+
else: # No auth, no client provided
186+
client_to_use = httpx.AsyncClient(base_url=effective_url, timeout=600)
143187

144188
super().__init__(
145189
name=name, agent_card=agent_card_object, httpx_client=client_to_use
146190
)
191+
192+
# The parent class sets _httpx_client_needs_cleanup based on whether
193+
# the httpx_client it received was None. Since we always pass a
194+
# client (either the user's or one we create), it will always set
195+
# it to False. We must override this to ensure clients we create
196+
# are properly cleaned up.
197+
if not client_was_provided:
198+
self._httpx_client_needs_cleanup = True

0 commit comments

Comments
 (0)