♻️ Feat: support a2a custom authorization - #3512
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR extends Nexent’s A2A external-agent integration to support authenticated Agent Card discovery/refresh (via saved custom headers) and configurable per-agent call credentials derived from Agent Card security metadata.
Changes:
- Add support for saving custom headers used only when fetching/refreshing an Agent Card.
- Persist Agent Card security metadata and introduce an API + UI flow to store credential values and apply them to agent calls (header/query/cookie).
- Add HTTP client support for params/cookies and raise a dedicated exception on non-2xx responses; update tests, docs, and i18n strings accordingly.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| test/backend/utils/test_a2a_http_client.py | Adds coverage for non-2xx GET behavior via A2AHttpStatusError. |
| test/backend/services/test_a2a_client_service.py | Updates URL-building tests; adds coverage for header forwarding, refresh behavior, and credential handling. |
| test/backend/database/test_a2a_agent_db.py | Extends DB unit tests for new agent-card header and security metadata fields, plus secret-hiding behavior. |
| test/backend/consts/test_a2a_models.py | Adds request-model tests for custom_headers acceptance and default behavior. |
| frontend/services/api.ts | Adds client endpoint for updating agent security credentials. |
| frontend/services/a2aService.ts | Adds types for security metadata and an API call to persist security credentials. |
| frontend/public/locales/zh/common.json | Adds Chinese i18n strings for custom headers + authentication UI. |
| frontend/public/locales/en/common.json | Adds English i18n strings for custom headers + authentication UI. |
| frontend/app/[locale]/agents/components/a2a/A2AAgentDiscoveryModal.tsx | Adds custom headers input for discovery and an “Agent Authentication” popover for security schemes. |
| doc/docs/zh/user-guide/agent-development.md | Documents custom discovery headers and the authentication configuration workflow (ZH). |
| doc/docs/en/user-guide/agent-development.md | Documents custom discovery headers and the authentication configuration workflow (EN). |
| deploy/sql/migrations/v2.4.0_0727_add_a2a_agent_card_headers_and_security_fields.sql | Adds JSONB columns for saved Agent Card headers and security metadata/credentials. |
| backend/utils/a2a_http_client.py | Adds A2AHttpStatusError, non-2xx handling, and params/cookies support for POST requests. |
| backend/services/a2a_client_service.py | Implements header persistence/usage for Agent Card fetch/refresh and credential application for agent calls. |
| backend/database/db_models.py | Adds new JSON columns to A2AExternalAgent ORM model. |
| backend/database/a2a_agent_db.py | Persists new fields, hides secrets by default, and adds an update method for credentials. |
| backend/consts/a2a_models.py | Extends discovery request model with custom_headers. |
| backend/apps/a2a_client_app.py | Plumbs custom_headers through discovery and adds a PUT endpoint to save security credentials. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
69
to
74
| custom_headers = custom_headers or {} | ||
| async with A2AHttpClient() as client: | ||
| headers = build_a2a_headers() | ||
| if custom_headers: | ||
| headers.update(custom_headers) | ||
| card = await client.get_json(url, headers=headers) |
Comment on lines
589
to
+592
| assert result == mock_result | ||
| mock_db.create_external_agent_from_url.assert_called_once() | ||
| assert mock_db.create_external_agent_from_url.call_args.kwargs["agent_card_headers"] == {} | ||
|
|
Contributor
Author
There was a problem hiding this comment.
已修改为assert mock_db.create_external_agent_from_url.call_args.kwargs["agent_card_headers"] is None
Comment on lines
+693
to
+697
| credential = credentials.get(scheme_id) | ||
| scheme = schemes.get(scheme_id, {}) | ||
| api_key_scheme = scheme.get("apiKeySecurityScheme", {}) if isinstance(scheme, dict) else {} | ||
| location = api_key_scheme.get("location") | ||
| parameter_name = api_key_scheme.get("name") |
Comment on lines
+77
to
+80
| const entries = Object.entries(schemes).flatMap(([schemeId, scheme]) => { | ||
| const apiKeyScheme = (scheme as Record<string, any>).apiKeySecurityScheme; | ||
| return apiKeyScheme ? [{ schemeId, ...apiKeyScheme }] : []; | ||
| }); |
| "a2a.discovery.customHeadersLabel": "Custom Request Headers (Optional)", | ||
| "a2a.discovery.customHeadersTooltip": "Saved and used only to retrieve and refresh this Agent Card, never for agent calls.", | ||
| "a2a.discovery.customHeadersPlaceholder": "{\"Authorization\": \"Bearer <token>\"}", | ||
| "a2a.discovery.customHeadersInvalid": "Custom request headers must be a JSON object with string keys and values", |
| "a2a.discovery.customHeadersLabel": "自定义请求头(可选)", | ||
| "a2a.discovery.customHeadersTooltip": "会保存并仅用于获取和刷新 Agent Card,不会用于后续调用", | ||
| "a2a.discovery.customHeadersPlaceholder": "{\"Authorization\": \"Bearer <token>\"}", | ||
| "a2a.discovery.customHeadersInvalid": "自定义请求头必须是键和值均为字符串的 JSON 对象", |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
…ass authentication
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.