From 0ab21b9c58733f9176c01e029b8085b29436e73d Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 29 Jul 2025 19:57:33 +0100 Subject: [PATCH 1/3] Update types --- src/a2a/types.py | 65 ++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/src/a2a/types.py b/src/a2a/types.py index d90715b67..052b32b8f 100644 --- a/src/a2a/types.py +++ b/src/a2a/types.py @@ -1,12 +1,13 @@ # generated by datamodel-codegen: -# filename: https://raw.githubusercontent.com/a2aproject/A2A/refs/heads/main/specification/json/a2a.json +# filename: https://raw.githubusercontent.com/a2aproject/A2A/refs/heads/jsdoc-strings/specification/json/a2a.json from __future__ import annotations +from datetime import datetime from enum import Enum from typing import Any, Literal -from pydantic import Field, RootModel +from pydantic import AnyUrl, Field, RootModel from a2a._base import A2ABaseModel @@ -87,7 +88,7 @@ class AgentExtension(A2ABaseModel): If true, the client must understand and comply with the extension's requirements to interact with the agent. """ - uri: str + uri: AnyUrl """ The unique URI identifying the extension. """ @@ -103,7 +104,7 @@ class AgentInterface(A2ABaseModel): """ The transport protocol supported at this URL. """ - url: str = Field( + url: AnyUrl = Field( ..., examples=[ 'https://api.example.com/a2a/v1', @@ -125,7 +126,7 @@ class AgentProvider(A2ABaseModel): """ The name of the agent provider's organization. """ - url: str + url: AnyUrl """ A URL for the agent provider's website or relevant documentation. """ @@ -165,7 +166,7 @@ class AgentSkill(A2ABaseModel): The set of supported output MIME types for this skill, overriding the agent's defaults. """ tags: list[str] = Field( - ..., examples=[['cooking', 'customer support', 'billing']] + ..., examples=[['cooking', 'customer support', 'billing']], min_length=1 ) """ A set of keywords describing the skill's capabilities. @@ -177,12 +178,12 @@ class AuthorizationCodeOAuthFlow(A2ABaseModel): Defines configuration details for the OAuth 2.0 Authorization Code flow. """ - authorization_url: str + authorization_url: AnyUrl """ The authorization URL to be used for this flow. This MUST be a URL and use TLS. """ - refresh_url: str | None = None + refresh_url: AnyUrl | None = None """ The URL to be used for obtaining refresh tokens. This MUST be a URL and use TLS. @@ -192,7 +193,7 @@ class AuthorizationCodeOAuthFlow(A2ABaseModel): The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. """ - token_url: str + token_url: AnyUrl """ The token URL to be used for this flow. This MUST be a URL and use TLS. @@ -204,7 +205,7 @@ class ClientCredentialsOAuthFlow(A2ABaseModel): Defines configuration details for the OAuth 2.0 Client Credentials flow. """ - refresh_url: str | None = None + refresh_url: AnyUrl | None = None """ The URL to be used for obtaining refresh tokens. This MUST be a URL. """ @@ -213,7 +214,7 @@ class ClientCredentialsOAuthFlow(A2ABaseModel): The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. """ - token_url: str + token_url: AnyUrl """ The token URL to be used for this flow. This MUST be a URL. """ @@ -369,7 +370,7 @@ class FileWithUri(A2ABaseModel): """ An optional name for the file (e.g., "document.pdf"). """ - uri: str + uri: AnyUrl """ A URL pointing to the file's content. """ @@ -425,11 +426,11 @@ class ImplicitOAuthFlow(A2ABaseModel): Defines configuration details for the OAuth 2.0 Implicit flow. """ - authorization_url: str + authorization_url: AnyUrl """ The authorization URL to be used for this flow. This MUST be a URL. """ - refresh_url: str | None = None + refresh_url: AnyUrl | None = None """ The URL to be used for obtaining refresh tokens. This MUST be a URL. """ @@ -698,7 +699,7 @@ class OpenIdConnectSecurityScheme(A2ABaseModel): """ An optional description for the security scheme. """ - open_id_connect_url: str + open_id_connect_url: AnyUrl """ The OpenID Connect Discovery URL for the OIDC provider's metadata. """ @@ -724,7 +725,7 @@ class PasswordOAuthFlow(A2ABaseModel): Defines configuration details for the OAuth 2.0 Resource Owner Password flow. """ - refresh_url: str | None = None + refresh_url: AnyUrl | None = None """ The URL to be used for obtaining refresh tokens. This MUST be a URL. """ @@ -733,7 +734,7 @@ class PasswordOAuthFlow(A2ABaseModel): The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. """ - token_url: str + token_url: AnyUrl """ The token URL to be used for this flow. This MUST be a URL. """ @@ -748,7 +749,7 @@ class PushNotificationAuthenticationInfo(A2ABaseModel): """ Optional credentials required by the push notification endpoint. """ - schemes: list[str] + schemes: list[str] = Field(..., min_length=1) """ A list of supported authentication schemes (e.g., 'Basic', 'Bearer'). """ @@ -772,7 +773,7 @@ class PushNotificationConfig(A2ABaseModel): """ A unique token for this task or session to validate incoming push notifications. """ - url: str + url: AnyUrl """ The callback URL where the agent should send push notifications. """ @@ -1326,7 +1327,7 @@ class Artifact(A2ABaseModel): """ An optional, human-readable name for the artifact. """ - parts: list[Part] + parts: list[Part] = Field(..., min_length=1) """ An array of content parts that make up the artifact. """ @@ -1390,7 +1391,7 @@ class Message(A2ABaseModel): """ Optional metadata for extensions. The key is an extension-specific identifier. """ - parts: list[Part] + parts: list[Part] = Field(..., min_length=1) """ An array of content parts that form the message body. A message can be composed of multiple parts of different types (e.g., text and files). @@ -1574,7 +1575,7 @@ class TaskStatus(A2ABaseModel): """ The current state of the task's lifecycle. """ - timestamp: str | None = Field( + timestamp: datetime | None = Field( default=None, examples=['2023-10-27T10:00:00Z'] ) """ @@ -1668,12 +1669,12 @@ class AgentCard(A2ABaseModel): """ A declaration of optional capabilities supported by the agent. """ - default_input_modes: list[str] + default_input_modes: list[str] = Field(..., min_length=1) """ Default set of supported input MIME types for all skills, which can be overridden on a per-skill basis. """ - default_output_modes: list[str] + default_output_modes: list[str] = Field(..., min_length=1) """ Default set of supported output MIME types for all skills, which can be overridden on a per-skill basis. @@ -1685,11 +1686,11 @@ class AgentCard(A2ABaseModel): A human-readable description of the agent, assisting users and other agents in understanding its purpose. """ - documentation_url: str | None = None + documentation_url: AnyUrl | None = None """ An optional URL to the agent's documentation. """ - icon_url: str | None = None + icon_url: AnyUrl | None = None """ An optional URL to an icon for the agent. """ @@ -1730,7 +1731,7 @@ class AgentCard(A2ABaseModel): """ JSON Web Signatures computed for this AgentCard. """ - skills: list[AgentSkill] + skills: list[AgentSkill] = Field(..., min_length=1) """ The set of skills, or distinct capabilities, that the agent can perform. """ @@ -1739,14 +1740,18 @@ class AgentCard(A2ABaseModel): If true, the agent can provide an extended agent card with additional details to authenticated users. Defaults to false. """ - url: str = Field(..., examples=['https://api.example.com/a2a/v1']) + url: AnyUrl = Field(..., examples=['https://api.example.com/a2a/v1']) """ The preferred endpoint URL for interacting with the agent. This URL MUST support the transport specified by 'preferredTransport'. """ - version: str = Field(..., examples=['1.0.0']) + version: str = Field( + ..., + examples=['1.0.0'], + pattern='^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$', + ) """ - The agent's own version number. The format is defined by the provider. + The agent's own version number. Semantic Versioning MUST be used. """ From 877484116b9e35d0937d538c154bc21adfb1722d Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 29 Jul 2025 20:05:01 +0100 Subject: [PATCH 2/3] Update types --- src/a2a/types.py | 136 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 105 insertions(+), 31 deletions(-) diff --git a/src/a2a/types.py b/src/a2a/types.py index 052b32b8f..cce562af1 100644 --- a/src/a2a/types.py +++ b/src/a2a/types.py @@ -88,7 +88,7 @@ class AgentExtension(A2ABaseModel): If true, the client must understand and comply with the extension's requirements to interact with the agent. """ - uri: AnyUrl + uri: str """ The unique URI identifying the extension. """ @@ -104,7 +104,7 @@ class AgentInterface(A2ABaseModel): """ The transport protocol supported at this URL. """ - url: AnyUrl = Field( + url: str = Field( ..., examples=[ 'https://api.example.com/a2a/v1', @@ -166,24 +166,44 @@ class AgentSkill(A2ABaseModel): The set of supported output MIME types for this skill, overriding the agent's defaults. """ tags: list[str] = Field( - ..., examples=[['cooking', 'customer support', 'billing']], min_length=1 + ..., examples=[['cooking', 'customer support', 'billing']] ) """ A set of keywords describing the skill's capabilities. """ +class AuthenticatedExtendedCardNotConfiguredError(A2ABaseModel): + """ + An A2A-specific error indicating that the agent does not have an Authenticated Extended Card configured + """ + + code: Literal[-32007] = -32007 + """ + The error code for when an authenticated extended card is not configured. + """ + data: Any | None = None + """ + A primitive or structured value containing additional information about the error. + This may be omitted. + """ + message: str | None = 'Authenticated Extended Card is not configured' + """ + The error message. + """ + + class AuthorizationCodeOAuthFlow(A2ABaseModel): """ Defines configuration details for the OAuth 2.0 Authorization Code flow. """ - authorization_url: AnyUrl + authorization_url: str """ The authorization URL to be used for this flow. This MUST be a URL and use TLS. """ - refresh_url: AnyUrl | None = None + refresh_url: str | None = None """ The URL to be used for obtaining refresh tokens. This MUST be a URL and use TLS. @@ -193,7 +213,7 @@ class AuthorizationCodeOAuthFlow(A2ABaseModel): The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. """ - token_url: AnyUrl + token_url: str """ The token URL to be used for this flow. This MUST be a URL and use TLS. @@ -205,7 +225,7 @@ class ClientCredentialsOAuthFlow(A2ABaseModel): Defines configuration details for the OAuth 2.0 Client Credentials flow. """ - refresh_url: AnyUrl | None = None + refresh_url: str | None = None """ The URL to be used for obtaining refresh tokens. This MUST be a URL. """ @@ -214,7 +234,7 @@ class ClientCredentialsOAuthFlow(A2ABaseModel): The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. """ - token_url: AnyUrl + token_url: str """ The token URL to be used for this flow. This MUST be a URL. """ @@ -370,12 +390,33 @@ class FileWithUri(A2ABaseModel): """ An optional name for the file (e.g., "document.pdf"). """ - uri: AnyUrl + uri: str """ A URL pointing to the file's content. """ +class GetAuthenticatedExtendedCardRequest(A2ABaseModel): + """ + Represents a JSON-RPC request for the `agent/getAuthenticatedExtendedCard` method. + """ + + id: str | int + """ + The identifier for this request. + """ + jsonrpc: Literal['2.0'] = '2.0' + """ + The version of the JSON-RPC protocol. MUST be exactly "2.0". + """ + method: Literal['agent/getAuthenticatedExtendedCard'] = ( + 'agent/getAuthenticatedExtendedCard' + ) + """ + The method name. Must be 'agent/getAuthenticatedExtendedCard'. + """ + + class GetTaskPushNotificationConfigParams(A2ABaseModel): """ Defines parameters for fetching a specific push notification configuration for a task. @@ -426,11 +467,11 @@ class ImplicitOAuthFlow(A2ABaseModel): Defines configuration details for the OAuth 2.0 Implicit flow. """ - authorization_url: AnyUrl + authorization_url: str """ The authorization URL to be used for this flow. This MUST be a URL. """ - refresh_url: AnyUrl | None = None + refresh_url: str | None = None """ The URL to be used for obtaining refresh tokens. This MUST be a URL. """ @@ -699,7 +740,7 @@ class OpenIdConnectSecurityScheme(A2ABaseModel): """ An optional description for the security scheme. """ - open_id_connect_url: AnyUrl + open_id_connect_url: str """ The OpenID Connect Discovery URL for the OIDC provider's metadata. """ @@ -725,7 +766,7 @@ class PasswordOAuthFlow(A2ABaseModel): Defines configuration details for the OAuth 2.0 Resource Owner Password flow. """ - refresh_url: AnyUrl | None = None + refresh_url: str | None = None """ The URL to be used for obtaining refresh tokens. This MUST be a URL. """ @@ -734,7 +775,7 @@ class PasswordOAuthFlow(A2ABaseModel): The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. """ - token_url: AnyUrl + token_url: str """ The token URL to be used for this flow. This MUST be a URL. """ @@ -749,7 +790,7 @@ class PushNotificationAuthenticationInfo(A2ABaseModel): """ Optional credentials required by the push notification endpoint. """ - schemes: list[str] = Field(..., min_length=1) + schemes: list[str] """ A list of supported authentication schemes (e.g., 'Basic', 'Bearer'). """ @@ -773,7 +814,7 @@ class PushNotificationConfig(A2ABaseModel): """ A unique token for this task or session to validate incoming push notifications. """ - url: AnyUrl + url: str """ The callback URL where the agent should send push notifications. """ @@ -1000,6 +1041,7 @@ class A2AError( | UnsupportedOperationError | ContentTypeNotSupportedError | InvalidAgentResponseError + | AuthenticatedExtendedCardNotConfiguredError ] ): root: ( @@ -1014,6 +1056,7 @@ class A2AError( | UnsupportedOperationError | ContentTypeNotSupportedError | InvalidAgentResponseError + | AuthenticatedExtendedCardNotConfiguredError ) """ A discriminated union of all standard JSON-RPC and A2A-specific error types. @@ -1171,6 +1214,7 @@ class JSONRPCErrorResponse(A2ABaseModel): | UnsupportedOperationError | ContentTypeNotSupportedError | InvalidAgentResponseError + | AuthenticatedExtendedCardNotConfiguredError ) """ An object describing the error that occurred. @@ -1327,7 +1371,7 @@ class Artifact(A2ABaseModel): """ An optional, human-readable name for the artifact. """ - parts: list[Part] = Field(..., min_length=1) + parts: list[Part] """ An array of content parts that make up the artifact. """ @@ -1391,7 +1435,7 @@ class Message(A2ABaseModel): """ Optional metadata for extensions. The key is an extension-specific identifier. """ - parts: list[Part] = Field(..., min_length=1) + parts: list[Part] """ An array of content parts that form the message body. A message can be composed of multiple parts of different types (e.g., text and files). @@ -1626,6 +1670,7 @@ class A2ARequest( | TaskResubscriptionRequest | ListTaskPushNotificationConfigRequest | DeleteTaskPushNotificationConfigRequest + | GetAuthenticatedExtendedCardRequest ] ): root: ( @@ -1638,6 +1683,7 @@ class A2ARequest( | TaskResubscriptionRequest | ListTaskPushNotificationConfigRequest | DeleteTaskPushNotificationConfigRequest + | GetAuthenticatedExtendedCardRequest ) """ A discriminated union representing all possible JSON-RPC 2.0 requests supported by the A2A specification. @@ -1669,12 +1715,12 @@ class AgentCard(A2ABaseModel): """ A declaration of optional capabilities supported by the agent. """ - default_input_modes: list[str] = Field(..., min_length=1) + default_input_modes: list[str] """ Default set of supported input MIME types for all skills, which can be overridden on a per-skill basis. """ - default_output_modes: list[str] = Field(..., min_length=1) + default_output_modes: list[str] """ Default set of supported output MIME types for all skills, which can be overridden on a per-skill basis. @@ -1686,11 +1732,11 @@ class AgentCard(A2ABaseModel): A human-readable description of the agent, assisting users and other agents in understanding its purpose. """ - documentation_url: AnyUrl | None = None + documentation_url: str | None = None """ An optional URL to the agent's documentation. """ - icon_url: AnyUrl | None = None + icon_url: str | None = None """ An optional URL to an icon for the agent. """ @@ -1731,7 +1777,7 @@ class AgentCard(A2ABaseModel): """ JSON Web Signatures computed for this AgentCard. """ - skills: list[AgentSkill] = Field(..., min_length=1) + skills: list[AgentSkill] """ The set of skills, or distinct capabilities, that the agent can perform. """ @@ -1740,18 +1786,33 @@ class AgentCard(A2ABaseModel): If true, the agent can provide an extended agent card with additional details to authenticated users. Defaults to false. """ - url: AnyUrl = Field(..., examples=['https://api.example.com/a2a/v1']) + url: str = Field(..., examples=['https://api.example.com/a2a/v1']) """ The preferred endpoint URL for interacting with the agent. This URL MUST support the transport specified by 'preferredTransport'. """ - version: str = Field( - ..., - examples=['1.0.0'], - pattern='^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$', - ) + version: str = Field(..., examples=['1.0.0']) + """ + The agent's own version number. The format is defined by the provider. + """ + + +class GetAuthenticatedExtendedCardSuccessResponse(A2ABaseModel): + """ + Represents a successful JSON-RPC response for the `agent/getAuthenticatedExtendedCard` method. + """ + + id: str | int | None = None """ - The agent's own version number. Semantic Versioning MUST be used. + The identifier established by the client. + """ + jsonrpc: Literal['2.0'] = '2.0' + """ + The version of the JSON-RPC protocol. MUST be exactly "2.0". + """ + result: AgentCard + """ + The result is an Agent Card object. """ @@ -1774,7 +1835,7 @@ class Task(A2ABaseModel): """ id: str """ - A unique identifier for the task, generated by the client for a new task or provided by the agent. + A unique identifier for the task, generated by the server for a new task. """ kind: Literal['task'] = 'task' """ @@ -1809,6 +1870,17 @@ class CancelTaskSuccessResponse(A2ABaseModel): """ +class GetAuthenticatedExtendedCardResponse( + RootModel[ + JSONRPCErrorResponse | GetAuthenticatedExtendedCardSuccessResponse + ] +): + root: JSONRPCErrorResponse | GetAuthenticatedExtendedCardSuccessResponse + """ + Represents a JSON-RPC response for the `agent/getAuthenticatedExtendedCard` method. + """ + + class GetTaskSuccessResponse(A2ABaseModel): """ Represents a successful JSON-RPC response for the `tasks/get` method. @@ -1894,6 +1966,7 @@ class JSONRPCResponse( | GetTaskPushNotificationConfigSuccessResponse | ListTaskPushNotificationConfigSuccessResponse | DeleteTaskPushNotificationConfigSuccessResponse + | GetAuthenticatedExtendedCardSuccessResponse ] ): root: ( @@ -1906,6 +1979,7 @@ class JSONRPCResponse( | GetTaskPushNotificationConfigSuccessResponse | ListTaskPushNotificationConfigSuccessResponse | DeleteTaskPushNotificationConfigSuccessResponse + | GetAuthenticatedExtendedCardSuccessResponse ) """ A discriminated union representing all possible JSON-RPC 2.0 responses From f95d10d9555b5719eb206de8995fc68dec026580 Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 29 Jul 2025 20:18:36 +0100 Subject: [PATCH 3/3] Update to use regex --- src/a2a/types.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/a2a/types.py b/src/a2a/types.py index cce562af1..c3e511e4a 100644 --- a/src/a2a/types.py +++ b/src/a2a/types.py @@ -3,7 +3,6 @@ from __future__ import annotations -from datetime import datetime from enum import Enum from typing import Any, Literal @@ -1619,8 +1618,10 @@ class TaskStatus(A2ABaseModel): """ The current state of the task's lifecycle. """ - timestamp: datetime | None = Field( - default=None, examples=['2023-10-27T10:00:00Z'] + timestamp: str | None = Field( + default=None, + examples=['2023-10-27T10:00:00Z'], + pattern='^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T([01]\\d|2[0-3]):([0-5]\\d):([0-5]\\d)(\\.\\d+)?(Z|[+-](?:[01]\\d|2[0-3])(?::?[0-5]\\d)?)?$', ) """ An ISO 8601 datetime string indicating when this status was recorded.