/ docs / docs / documentation / components / proxies.md
proxies.md
  1  ---
  2  title: Proxies
  3  sidebar_position: 250
  4  ---
  5  
  6  # Proxies
  7  
  8  Proxies act as protocol bridges that connect Agent Mesh to external A2A agents. By translating between A2A over Solace event mesh and A2A over HTTPS protocols, proxies enable agents within the mesh to delegate tasks to external agents and include them in collaborative workflows.
  9  
 10  A single proxy instance can manage multiple external agents, each with its own URL, authentication configuration, and timeout settings.
 11  
 12  :::tip[In one sentence]
 13  Proxies are protocol bridges that connect multiple external A2A-over-HTTPS agents to the Solace event mesh, enabling hybrid agent architectures.
 14  :::
 15  
 16  :::info[Agent Mesh Enterprise]
 17  If you are using Agent Mesh Enterprise, you can connect external agents through a guided wizard interface instead of writing YAML configuration files. For more information, see [Connect External Agents](../enterprise/connect-external-agents.md).
 18  :::
 19  
 20  ## Key Functions
 21  
 22  1. **Protocol Translation**: Proxies translate between A2A over HTTPS and A2A over Solace event mesh, enabling external agents to communicate with agents on the mesh without modification.
 23  
 24  2. **Authentication Management**: Proxies handle authentication to downstream agents, supporting multiple authentication schemes including static bearer tokens, API keys, and OAuth 2.0 client credentials flow with automatic token refresh.
 25  
 26  3. **Agent Discovery**: Proxies fetch agent cards from external agents and publish them to the mesh discovery topic, making external agents discoverable to other agents in the system.
 27  
 28  4. **Artifact Handling**: Proxies manage artifact flow between the mesh and external agents, resolving artifact URIs to byte content before forwarding requests and saving returned artifacts to the mesh's artifact service.
 29  
 30  5. **Task Lifecycle Management**: Proxies track active tasks, handle cancellation requests, and ensure proper cleanup when tasks complete or fail.
 31  
 32  6. **Automatic Retry Logic**: For OAuth 2.0 authenticated agents, proxies automatically detect authentication failures (401 responses), refresh tokens, and retry requests without manual intervention.
 33  
 34  ## When to Use a Proxy
 35  
 36  Proxies are the right choice when you need:
 37  
 38  - **Integration with Third-Party Agents**: Connect to external A2A agents provided by vendors or partners that run on their own infrastructure.
 39  
 40  - **Hybrid Cloud Architectures**: Bridge agents running in different cloud environments or on-premises systems with your Solace mesh.
 41  
 42  - **Legacy System Integration**: Connect existing A2A agents that cannot be modified to use Solace messaging directly.
 43  
 44  - **Gradual Migration**: Incrementally migrate agents to the Solace mesh while maintaining compatibility with external systems.
 45  
 46  - **Service Isolation**: Keep certain agents isolated on separate infrastructure while still enabling them to participate in collaborative workflows.
 47  
 48  ### Proxy vs. Native Agent
 49  
 50  | Aspect | Proxy | Native Agent |
 51  |--------|-------|--------------|
 52  | **Communication** | A2A over HTTPS to external agent | A2A over Solace event mesh directly |
 53  | **Deployment** | External agent runs separately | Runs within Agent Mesh |
 54  | **Authentication** | Proxy handles auth to external agent | Mesh-level authentication |
 55  | **Latency** | Additional HTTP hop | Direct mesh communication |
 56  | **Task Initiation** | Can only receive tasks from mesh agents | Can initiate tasks to any agent |
 57  | **Use Case** | External/third-party agents | Agents you control |
 58  
 59  ## Architecture Overview
 60  
 61  The proxy sits between the Solace event mesh and external A2A agents, performing bidirectional protocol translation:
 62  
 63  ```mermaid
 64  graph LR
 65      A[Agent Mesh<br/>A2A over Solace Event Mesh] <-->|Solace Topics| B[Proxy Component]
 66      B <-->|HTTPS| C[External Agent 1<br/>A2A over HTTPS]
 67      B <-->|HTTPS| D[External Agent 2<br/>A2A over HTTPS]
 68      B <-->|HTTPS| E[External Agent N<br/>A2A over HTTPS]
 69      
 70      style B fill:none,stroke:#00C895,stroke-width:2px
 71      style A fill:none,stroke:#333,stroke-width:2px
 72      style C fill:none,stroke:#333,stroke-width:2px
 73      style D fill:none,stroke:#333,stroke-width:2px
 74      style E fill:none,stroke:#333,stroke-width:2px
 75  ```
 76  
 77  The proxy performs these operations:
 78  
 79  1. **Request Flow**: Receives A2A requests from Agent Mesh, resolves artifact URIs to byte content, forwards HTTPS requests to external agents, and streams responses back to Agent Mesh.
 80  
 81  2. **Response Flow**: Receives responses from external agents, saves artifacts to Agent Mesh's artifact service, replaces byte content with artifact URIs, and publishes responses to Agent Mesh topics.
 82  
 83  3. **Discovery Flow**: Periodically fetches agent cards from external agents, updates the local registry, and publishes cards to the Agent Mesh discovery topic.
 84  
 85  ## Configuration
 86  
 87  Proxies are configured through YAML files that specify the namespace, downstream agents, authentication, and service settings.
 88  
 89  ### Basic Configuration
 90  
 91  A single proxy can manage multiple external agents. Each agent in the `proxied_agents` list can have its own URL, authentication, and timeout configuration:
 92  
 93  ```yaml
 94  app:
 95    class_name: solace_agent_mesh.agent.proxies.a2a.app.A2AProxyApp
 96    name: my-a2a-proxy
 97    app_config:
 98      namespace: "myorg/production"
 99      proxied_agents:
100        - name: "external-data-agent"
101          url: "https://api.example.com/agent"
102          request_timeout_seconds: 120
103          # Optional: Apply auth to agent card fetching
104          # use_auth_for_agent_card: true
105          # Optional: Use configured URL instead of agent card URL for tasks
106          # use_agent_card_url: false
107          # Optional: Custom headers for agent card fetching
108          # agent_card_headers:
109          #   - name: "X-API-Version"
110          #     value: "v2"
111          # Optional: Custom headers for task invocations
112          # task_headers:
113          #   - name: "X-Tenant-ID"
114          #     value: "${TENANT_ID}"
115        - name: "external-analytics-agent"
116          url: "https://analytics.example.com/agent"
117          request_timeout_seconds: 180
118        - name: "external-reporting-agent"
119          url: "https://reports.example.com/agent"
120      artifact_service:
121        type: "filesystem"
122        base_path: "/tmp/proxy-artifacts"
123      discovery_interval_seconds: 60
124      default_request_timeout_seconds: 300
125  
126  broker:
127    # Broker configuration inherited from environment or specified here
128  ```
129  
130  ### Configuration Parameters
131  
132  - `namespace`: The topic prefix for A2A communication (for example, "myorg/production").
133  - `proxied_agents`: A list of external agents to proxy. Each agent can have its own URL, authentication, and timeout settings (see Authentication Types below).
134    - `use_auth_for_agent_card`: If true, applies the configured authentication when fetching agent cards. If false (default), agent card requests are made without authentication.
135    - `use_agent_card_url`: If true (default), uses the URL from the agent card for task invocations. If false, uses the configured URL directly for all task invocations. Note: The configured URL is always used to fetch the agent card itself.
136    - `agent_card_headers`: Custom HTTP headers to include when fetching the agent card. These headers are added alongside authentication headers.
137    - `task_headers`: Custom HTTP headers to include when invoking A2A tasks. These headers are added alongside authentication headers.
138    - `convert_progress_updates`: If true (default), converts TextParts in status updates to AgentProgressUpdateData DataParts for consistent UI behavior. If false, preserves original text parts.
139    - `agent_card_data`: Static agent card data embedded directly in configuration. If provided, the proxy uses this data instead of fetching from the agent card endpoint. This allows proxying agents that do not have agent card endpoints.
140  - `artifact_service`: Configuration for storing artifacts. This is shared across all proxied agents. This is configured in the same manner as agents and gateways
141  - `discovery_interval_seconds`: How often to refresh agent cards from all external agents (default: 60).
142  - `default_request_timeout_seconds`: Default timeout for requests to external agents. Individual agents can override this (default: 300).
143  
144  ## Authentication Types
145  
146  The proxy supports three authentication schemes for connecting to downstream agents. Each agent in the `proxied_agents` list can use a different authentication type, allowing you to integrate agents with varying security requirements in a single proxy instance.
147  
148  By default, authentication is only applied to A2A task invocations, not to agent card fetching. You can enable authentication for agent card fetching by setting `use_auth_for_agent_card: true` in the agent configuration.
149  
150  ### Static Bearer Token
151  
152  Use static bearer tokens for agents that require a fixed authentication token.
153  
154  ```yaml
155  proxied_agents:
156    - name: "secure-agent"
157      url: "https://api.example.com/agent"
158      authentication:
159        type: "static_bearer"
160        token: "${AGENT_BEARER_TOKEN}"  # Use environment variable
161      # use_auth_for_agent_card: true  # Optional: Apply auth to agent card fetching
162  ```
163  
164  ### Static API Key
165  
166  Use static API keys for agents that require API key authentication.
167  
168  ```yaml
169  proxied_agents:
170    - name: "api-key-agent"
171      url: "https://api.example.com/agent"
172      authentication:
173        type: "static_apikey"
174        token: "${AGENT_API_KEY}"
175      # use_auth_for_agent_card: true  # Optional: Apply auth to agent card fetching
176  ```
177  
178  ### OAuth 2.0 Client Credentials
179  
180  Use OAuth 2.0 client credentials flow for agents that require dynamic token acquisition. The proxy automatically handles token refresh and retry logic.
181  
182  ```yaml
183  proxied_agents:
184    - name: "oauth-agent"
185      url: "https://api.example.com/agent"
186      authentication:
187        type: "oauth2_client_credentials"
188        token_url: "https://auth.example.com/oauth/token"
189        client_id: "${OAUTH_CLIENT_ID}"
190        client_secret: "${OAUTH_CLIENT_SECRET}"
191        scope: "agent.read agent.write"  # Optional
192        token_cache_duration_seconds: 3300  # Optional, default: 3300 (55 minutes)
193      # use_auth_for_agent_card: true  # Optional: Apply auth to agent card fetching
194  ```
195  
196  The proxy caches OAuth tokens and automatically refreshes them when they expire. If a request receives a 401 Unauthorized response, the proxy invalidates the cached token and retries the request once with a fresh token.
197  
198  :::note[Security Best Practice]
199  Always use environment variables for sensitive credentials. Never commit tokens or secrets directly in configuration files.
200  :::
201  
202  ## SSL Certificate Verification
203  
204  By default, the proxy verifies SSL certificates when connecting to downstream agents over HTTPS. You can disable certificate verification for specific agents using the `ssl_verify` configuration option.
205  
206  ### When to Disable SSL Verification
207  
208  Disable SSL verification (`ssl_verify: false`) only in these scenarios:
209  
210  - **Development/Testing**: Connecting to agents with self-signed certificates in non-production environments
211  - **Internal Infrastructure**: Agents running on internal networks with private CA certificates not trusted by the system
212  
213  :::warning[Security Warning]
214  Disabling SSL verification removes protection against man-in-the-middle attacks. Never disable SSL verification in production environments unless you fully understand the security implications.
215  :::
216  
217  ### Configuration
218  
219  ```yaml
220  proxied_agents:
221    - name: "production-agent"
222      url: "https://api.example.com/agent"
223      ssl_verify: true  # Default - verify against system CAs
224  
225    - name: "dev-agent-self-signed"
226      url: "https://dev.internal.example.com/agent"
227      ssl_verify: false  # Disable verification for self-signed certs
228  ```
229  
230  The `ssl_verify` setting applies to both agent card fetching and task invocations for the configured agent.
231  
232  ## Custom HTTP Headers
233  
234  The proxy supports custom HTTP headers for both agent card fetching and A2A task invocations. This is useful for scenarios like API versioning, tenant identification, custom authentication schemes, or any other header-based requirements.
235  
236  ### Header Configuration
237  
238  Custom headers are defined as name-value pairs and can be configured separately for agent card fetching (`agent_card_headers`) and task invocations (`task_headers`):
239  
240  ```yaml
241  proxied_agents:
242    - name: "custom-header-agent"
243      url: "https://api.example.com/agent"
244      authentication:
245        type: "static_bearer"
246        token: "${AGENT_TOKEN}"
247      agent_card_headers:
248        - name: "X-API-Version"
249          value: "v2"
250        - name: "X-Tenant-ID"
251          value: "${TENANT_ID}"
252      task_headers:
253        - name: "X-API-Version"
254          value: "v2"
255        - name: "X-Request-Priority"
256          value: "high"
257  ```
258  
259  ### Header Precedence Rules
260  
261  When both authentication and custom headers are configured:
262  
263  1. **Authentication headers take precedence**: The proxy applies authentication headers (like `Authorization` or `X-API-Key`) based on the authentication type configured. These are applied by the A2A SDK's authentication layer after custom headers are set.
264  
265  2. **Custom headers are for metadata, not authentication**: Custom headers should be used for non-authentication purposes such as API versioning, tenant identification, or request metadata. They cannot override authentication headers.
266  
267  3. **For custom authentication**: If you need custom authentication logic, omit the `authentication` configuration block and use `task_headers` to set your custom authentication header directly.
268  
269  ### Use Cases
270  
271  **API Versioning**: Specify the API version your integration requires:
272  
273  ```yaml
274  agent_card_headers:
275    - name: "X-API-Version"
276      value: "v2"
277  task_headers:
278    - name: "X-API-Version"
279      value: "v2"
280  ```
281  
282  **Tenant Identification**: Pass tenant or organization identifiers:
283  
284  ```yaml
285  task_headers:
286    - name: "X-Tenant-ID"
287      value: "${TENANT_ID}"
288    - name: "X-Organization"
289      value: "acme-corp"
290  ```
291  
292  **Custom Authentication**: If you need custom authentication, omit the `authentication` block and use headers directly:
293  
294  ```yaml
295  # Note: Do NOT configure the 'authentication' block if using custom auth headers
296  task_headers:
297    - name: "Authorization"
298      value: "Bearer ${CUSTOM_AUTH_TOKEN}"
299    # Or use a custom auth scheme:
300    - name: "X-Custom-Auth"
301      value: "${CUSTOM_AUTH_TOKEN}"
302  ```
303  
304  **Request Metadata**: Add metadata for tracking or routing:
305  
306  ```yaml
307  task_headers:
308    - name: "X-Request-Source"
309      value: "agent-mesh"
310    - name: "X-Request-Priority"
311      value: "high"
312  ```
313  
314  ## Artifact Handling
315  
316  The proxy manages artifact flow in both directions to ensure seamless integration between Agent Mesh and external agents.
317  
318  ### Request Flow: Agent Mesh to External Agent
319  
320  When it forwards requests to external agents, the proxy resolves artifact URIs to byte content using the following sequence of operations:
321  
322  1. The proxy receives an A2A request containing artifact references (for example, `artifact://app/user/session/data.csv?version=1`).
323  2. The proxy loads the artifact content from Agent Mesh's artifact service.
324  3. The proxy replaces the URI with the actual byte content in the request.
325  4. The proxy forwards the modified request to the external agent.
326  
327  This process ensures that external agents receive complete artifact data without needing access to Agent Mesh's artifact service.
328  
329  ### Response Flow: External Agent to Agent Mesh
330  
331  When it receives responses from external agents, the proxy saves artifacts to Agent Mesh as follows:
332  
333  1. The external agent returns artifacts with byte content in the response.
334  2. The proxy saves each artifact to Agent Mesh's artifact service.
335  3. The proxy replaces the byte content with an artifact URI.
336  4. The proxy publishes the modified response to Agent Mesh.
337  
338  This process ensures that artifacts are stored centrally and can be accessed by other agents in Agent Mesh.
339  
340  ### Artifact Metadata
341  
342  The proxy automatically generates metadata for saved artifacts, including:
343  
344  - `proxied_from_artifact_id`: The original artifact ID from the external agent
345  - `description`: Extracted from the artifact or generated from context
346  - `produced_artifacts`: A manifest of all artifacts created during task execution
347  
348  ## Status Update Conversion
349  
350  The proxy can automatically convert text-based status updates from external A2A agents to match the native SAM agent format, ensuring consistent UI behavior across all agents in your mesh.
351  
352  ### Conversion Scope
353  
354  The `convert_progress_updates` setting only affects intermediate status updates:
355  
356  - **Applies to**: `TaskStatusUpdateEvent` messages (streaming progress updates)
357  - **Does not apply to**: Final `Task` responses, artifact content, or other message types
358  
359  This means that final responses from external agents remain as text parts, preserving the agent's intended final output format.
360  
361  ### When to Disable
362  
363  Set `convert_progress_updates: false` if:
364  
365  - The external agent sends structured status updates that should be preserved exactly as-is
366  - You have custom UI handling for text-based status updates
367  - You need to preserve original TextParts for debugging or custom processing
368  - The external agent already sends progress updates as DataParts
369  
370  Example configuration with conversion disabled:
371  
372  ```yaml
373  proxied_agents:
374    - name: "legacy-agent"
375      url: "https://legacy.example.com/agent"
376      convert_progress_updates: false  # Preserve original text parts
377  ```
378  
379  When disabled, all status update content passes through unchanged, allowing you to implement custom handling in your gateway or UI layer.
380  
381  ## Discovery and Health
382  
383  The proxy maintains agent discovery and health monitoring through periodic agent card fetching.
384  
385  ### Initial Discovery
386  
387  When the proxy starts, it performs synchronous discovery of all configured agents by:
388  
389  1. Fetching agent cards from each external agent's `/.well-known/agent-card.json` endpoint.
390  2. Updating the local agent registry with agent capabilities.
391  3. Publishing agent cards to the Agent Mesh discovery topic.
392  
393  This process ensures that external agents are immediately discoverable when the proxy starts.
394  
395  ### Periodic Refresh
396  
397  The proxy periodically refreshes agent cards based on the configured `discovery_interval_seconds`. When the configured interval elapses, the proxy fetches updated agent cards from external agents, updates the local registry with any changes, and then publishes the updated cards to Agent Mesh. This process ensures that Agent Mesh has current information about external agent capabilities and availability.
398  
399  ### Agent Card Transformation
400  
401  The proxy transforms agent cards to make external agents appear as native Agent Mesh agents:
402  
403  - The `name` field is set to the configured alias (the name you specify in `proxied_agents`).
404  - The `url` field is rewritten to use the Solace topic format (for example, `solace:myorg/production/agent/external-data-agent`).
405  
406  These agent cards allow other agents to interact with external agents using the standard A2A protocol over Solace event mesh, without knowing they are proxied.
407  
408  ### URL Behavior
409  
410  The proxy handles URLs in two contexts:
411  
412  1. **Agent Card Fetching**: Always uses the configured URL in the `proxied_agents` list to fetch the agent card from the external agent's `/.well-known/agent-card.json` endpoint.
413  
414  2. **Task Invocations**: By default, uses the URL specified in the agent card returned by the external agent. This allows external agents to advertise their preferred endpoint (which may differ from the agent card endpoint). You can override this behavior by setting `use_agent_card_url: false` to always use the configured URL for both agent card fetching and task invocations.
415  
416  ## Task Lifecycle Management
417  
418  The proxy tracks active tasks and manages their lifecycle from initiation to completion.
419  
420  ### Task Initiation
421  
422  When a request arrives from Agent Mesh, the proxy:
423  
424  1. Creates a task context to track the task's state.
425  2. Resolves inbound artifacts.
426  3. Forwards the request to the external agent.
427  4. Begins streaming responses back to Agent Mesh.
428  
429  ### Task Cancellation
430  
431  When a cancellation request arrives, the proxy:
432  
433  1. Looks up the active task context.
434  2. Forwards the cancellation request to the external agent.
435  3. Publishes the cancellation response to Agent Mesh.
436  
437  ### Task Completion
438  
439  When a task completes, the proxy:
440  
441  1. Processes any final artifacts.
442  2. Publishes the final task response to Agent Mesh.
443  3. Removes the task context from active tracking.
444  
445  ## Error Handling and Retry Logic
446  
447  The proxy implements robust error handling and automatic retry logic for authentication failures.
448  
449  ### OAuth 2.0 Automatic Retry
450  
451  When using OAuth 2.0 authentication, the proxy automatically handles token expiration using the following sequence:
452  
453  1. A request receives a 401 Unauthorized response from the external agent.
454  2. The proxy invalidates the cached token.
455  3. The proxy removes all cached clients for the agent/session.
456  4. The proxy fetches a fresh token from the OAuth provider.
457  5. The proxy retries the request once with the new token.
458  
459  This sequence ensures seamless operation even when tokens expire during long-running tasks.
460  
461  ### Connection Errors
462  
463  The proxy provides clear error messages for connection failures:
464  
465  - Connection refused or agent unreachable
466  - Timeout errors with configurable timeout values
467  - JSON-RPC protocol errors from external agents
468  
469  ### Error Responses
470  
471  When errors occur, the proxy publishes standard A2A error responses to Agent Mesh, including:
472  
473  - `InternalError`: For unexpected proxy errors
474  - `InvalidRequestError`: For malformed requests
475  - `TaskNotFoundError`: For cancellation requests on unknown tasks
476  
477  ## Creating a Proxy
478  
479  Proxies are configured using standard YAML configuration files, similar to agents and gateways.
480  
481  ### Creating the Configuration File
482  
483  Create a new YAML file in your `configs` directory (for example, `configs/my-proxy.yaml`):
484  
485  ```yaml
486  log:
487    stdout_log_level: INFO
488    log_file_level: DEBUG
489    log_file: my-proxy.log
490  
491  # Include shared configuration (broker connection, etc.)
492  !include shared_config.yaml
493  
494  apps:
495    - name: my_a2a_proxy
496      app_module: solace_agent_mesh.agent.proxies.a2a.app
497      broker:
498        <<: *broker_connection
499  
500      app_config:
501        namespace: "${NAMESPACE}"
502        
503        artifact_service:
504          type: "filesystem"
505          base_path: "/tmp/proxy-artifacts"
506          artifact_scope: "namespace"
507        
508        discovery_interval_seconds: 60
509        default_request_timeout_seconds: 300
510        
511        proxied_agents:
512          - name: "external-agent-1"
513            url: "https://api.example.com/agent"
514            request_timeout_seconds: 120
515            authentication:
516              type: "static_bearer"
517              token: "${AGENT_TOKEN}"
518  ```
519  
520  You can use the example file at `examples/a2a_proxy.yaml` as a template.
521  
522  ### Running the Proxy
523  
524  Run the proxy along with your other Agent Mesh components:
525  
526  ```bash
527  sam run
528  ```
529  
530  The proxy automatically subscribes to the appropriate Solace topics and begins proxying requests to external agents.
531  
532  ### Multiple Proxy Configurations
533  
534  While a single proxy can manage multiple external agents, you may want to create separate proxy configurations to:
535  
536  - Organize agents by domain or team
537  - Isolate agents with different security requirements
538  - Distribute load across multiple proxy instances
539  
540  ```bash
541  configs/
542  ├── data-agents-proxy.yaml      # Proxies 3 data-related agents
543  ├── analytics-agents-proxy.yaml # Proxies 2 analytics agents
544  └── third-party-agents-proxy.yaml # Proxies external vendor agents
545  ```
546  
547  Run all proxies together:
548  
549  ```bash
550  sam run
551  ```
552  
553  Or run specific proxy configurations:
554  
555  ```bash
556  sam run configs/data-agents-proxy.yaml
557  ```
558  
559  ## Advanced Configuration
560  
561  ### Per-Agent Timeout Override
562  
563  You can override the default timeout for specific agents:
564  
565  ```yaml
566  proxied_agents:
567    - name: "slow-agent"
568      url: "https://slow.example.com/agent"
569      request_timeout_seconds: 600  # 10 minutes
570  ```
571  
572  ### Custom Headers with Authentication
573  
574  Combine authentication with custom headers for complex integration requirements:
575  
576  ```yaml
577  proxied_agents:
578    - name: "enterprise-agent"
579      url: "https://enterprise.example.com/agent"
580      authentication:
581        type: "oauth2_client_credentials"
582        token_url: "https://auth.example.com/oauth/token"
583        client_id: "${OAUTH_CLIENT_ID}"
584        client_secret: "${OAUTH_CLIENT_SECRET}"
585      use_auth_for_agent_card: true  # Apply OAuth to agent card fetching
586      agent_card_headers:
587        - name: "X-API-Version"
588          value: "v2"
589        - name: "X-Client-Type"
590          value: "agent-mesh"
591      task_headers:
592        - name: "X-API-Version"
593          value: "v2"
594        - name: "X-Tenant-ID"
595          value: "${TENANT_ID}"
596        - name: "X-Request-Priority"
597          value: "high"
598  ```
599  
600  ### URL Override for Task Invocations
601  
602  By default, the proxy uses the URL from the agent card for task invocations. This allows external agents to specify their preferred endpoint. However, you can override this behavior by setting `use_agent_card_url: false`:
603  
604  ```yaml
605  proxied_agents:
606    - name: "fixed-url-agent"
607      url: "https://api.example.com/agent"
608      use_agent_card_url: false  # Always use the configured URL
609      authentication:
610        type: "static_bearer"
611        token: "${AGENT_TOKEN}"
612  ```
613  
614  **Important notes:**
615  
616  - The configured URL is always used to fetch the agent card, regardless of this setting
617  - When `use_agent_card_url: false`, all task invocations use the configured URL
618  - When `use_agent_card_url: true` (default), the agent card's URL is used for tasks
619  
620  ### Agents Without Agent Card Endpoints
621  
622  For external agents that do not expose an agent card endpoint, you can embed the agent card data directly in the configuration using `agent_card_data`:
623  
624  ```yaml
625  proxied_agents:
626    - name: "no-card-agent"
627      url: "https://api.example.com/agent"
628      agent_card_data:
629        name: "MyExternalAgent"
630        description: "An external agent without an agent card endpoint"
631        version: "1.0.0"
632        skills:
633          - id: "process_data"
634            name: "process_data"
635            description: "Processes incoming data"
636        defaultInputModes:
637          - "text"
638        defaultOutputModes:
639          - "text"
640      authentication:
641        type: "static_bearer"
642        token: "${AGENT_TOKEN}"
643  ```
644  
645  When `agent_card_data` is provided, the proxy skips fetching from the agent card endpoint and uses the embedded data instead.
646  
647  ### Custom Artifact Service Scope
648  
649  Configure artifact storage scope for the proxy:
650  
651  ```yaml
652  artifact_service:
653    type: "filesystem"
654    base_path: "/data/proxy-artifacts"
655    artifact_scope: "namespace"  # Options: namespace, app, custom
656  ```
657  
658  ### Multiple Proxies
659  
660  You can run multiple proxy instances to distribute load or isolate different sets of external agents. Each proxy instance can manage multiple agents:
661  
662  ```yaml
663  # data-agents-proxy.yaml
664  app:
665    name: data-agents-proxy
666    app_config:
667      proxied_agents:
668        - name: "data-agent-1"
669          url: "https://data1.example.com/agent"
670        - name: "data-agent-2"
671          url: "https://data2.example.com/agent"
672        - name: "data-agent-3"
673          url: "https://data3.example.com/agent"
674  
675  # analytics-agents-proxy.yaml
676  app:
677    name: analytics-agents-proxy
678    app_config:
679      proxied_agents:
680        - name: "analytics-agent-1"
681          url: "https://analytics1.example.com/agent"
682        - name: "analytics-agent-2"
683          url: "https://analytics2.example.com/agent"
684  ```
685  
686  ## Troubleshooting
687  
688  ### Agent Not Discoverable
689  
690  If an external agent does not appear in Agent Mesh:
691  
692  1. Check that the agent's URL is accessible from the proxy.
693  2. Verify that the agent exposes `/.well-known/agent-card.json`.
694  3. Check the proxy logs for discovery errors.
695  4. Ensure that `discovery_interval_seconds` is set appropriately and is more frequent than the `health_check_ttl_seconds` that is set on the calling agents and gateways.
696  
697  ### Authentication Failures
698  
699  If requests fail with 401 errors:
700  
701  1. Verify that the credentials are correctly set in environment variables.
702  2. For OAuth 2.0, check that `token_url`, `client_id`, and `client_secret` are correct.
703  3. Ensure that the OAuth token URL uses HTTPS (required for security).
704  4. Check the proxy logs for token acquisition errors.
705  
706  ### Timeout Errors
707  
708  If requests timeout:
709  
710  1. Increase `request_timeout_seconds` for slow agents.
711  2. Check the network connectivity between the proxy and the external agent.
712  3. Verify that the external agent is responding within the timeout period.
713  
714  ### Artifact Issues
715  
716  If artifacts are not flowing correctly:
717  
718  1. Verify that the artifact service is properly configured.
719  2. Check that the proxy has write permissions to the artifact storage location.
720  3. Ensure that the artifact URIs are correctly formatted.
721  4. Check the proxy logs for artifact save/load errors.
722  
723  ### Strands SDK Streaming Issues
724  
725  If streaming responses from Strands SDK agents appear as status updates instead of chat content, the agent may be using legacy streaming mode. Strands agents require the `enable_a2a_compliant_streaming` option to be enabled on their `A2AServer` instance to properly send streaming content. See the [Strands A2AServer documentation](https://strandsagents.com/latest/documentation/docs/api-reference/python/multiagent/a2a/server/?h=enable_a2a_compliant_streaming#strands.multiagent.a2a.server.A2AServer.__init__) for details.
726  
727  ### Issues Running A2A Samples with `Containerfile`
728  
729  If you encounter a `ValueError: Invalid context_id: ... is not a valid UUID.` when running A2A samples using a `Containerfile`, it may be due to outdated dependencies in the `uv.lock` file. This can happen if the sample is pinned to an older version of the `a2a-sdk` package. For more details, see [this GitHub issue](https://github.com/a2aproject/a2a-samples/issues/399).
730  
731  To resolve this, navigate to the sample's directory and upgrade the dependencies:
732  
733  ```bash
734  uv lock --upgrade
735  ```
736  
737  This will update the `uv.lock` file to use the latest version of `a2a-sdk`, which includes the necessary bug fixes.