Skip to content

[Bug]: FileWithBytes and FileWithUri use non-compliant field names (bytes/uri/mimeType instead of fileWithBytes/fileWithUri/mediaType) #269

@gijswalraven

Description

@gijswalraven

[Bug]: FileWithBytes and FileWithUri use non-compliant field names (bytes/uri/mimeType instead of fileWithBytes/fileWithUri/mediaType)

Description

The A2A NuGet package v0.1.0-preview.2 uses non-compliant field names for file handling that do not match the official A2A Protocol Specification. This breaks interoperability with spec-compliant agents.

Specification Reference

Official A2A Protocol Specification:

Exact Field Names from Specification (Section 4.1.7):

The specification defines FilePart with the following fields:

Field Name Type Description
fileWithUri string (optional) URL pointing to file content
fileWithBytes bytes (optional) Base64-encoded file content
mediaType string (optional) File's media type (e.g., "application/pdf")
name string (optional) Optional filename (e.g., "document.pdf")

Key Constraint from Specification:

"A FilePart MUST contain exactly one of the following: fileWithUri, fileWithBytes"

Expected JSON Structure per Specification:

Example 1 - File with bytes:

{
  "kind": "file",
  "file": {
    "fileWithBytes": "iVBORw0KGgoAAAANSUhEUgAAAAUA...",
    "mediaType": "image/png",
    "name": "input_image.png"
  }
}

Example 2 - File with URI:

{
  "kind": "file",
  "file": {
    "fileWithUri": "https://storage.example.com/file.pdf",
    "mediaType": "application/pdf",
    "name": "document.pdf"
  }
}

Current SDK Implementation (NON-COMPLIANT)

SDK Types (decompiled from A2A.dll v0.1.0-preview.2):

FileWithBytes class:

namespace A2A;

public sealed class FileWithBytes : FileContent
{
    [JsonPropertyName("name")]
    public string? Name { get; set; }

    [JsonPropertyName("mimeType")]      // ❌ WRONG - Should be "mediaType"
    public string? MimeType { get; set; }

    [JsonPropertyName("bytes")]         // ❌ WRONG - Should be "fileWithBytes"
    [JsonRequired]
    public string Bytes { get; set; } = string.Empty;

    [JsonPropertyName("uri")]           // ❌ WRONG - Should not exist
    public string? Uri { get; set; }
}

FileWithUri class:

namespace A2A;

public sealed class FileWithUri : FileContent
{
    [JsonPropertyName("name")]
    public string? Name { get; set; }

    [JsonPropertyName("mimeType")]      // ❌ WRONG - Should be "mediaType"
    public string? MimeType { get; set; }

    [JsonPropertyName("uri")]           // ❌ WRONG - Should be "fileWithUri"
    [JsonRequired]
    public string Uri { get; set; } = string.Empty;
}

Actual JSON Output from SDK:

Example 1 - FileWithBytes (NON-COMPLIANT):

{
  "kind": "file",
  "file": {
    "kind": "bytes",
    "name": "test.png",
    "mimeType": "image/png",
    "bytes": "iVBORw0KGgo...",
    "uri": null,
    "metadata": {}
  }
}

Example 2 - FileWithUri (NON-COMPLIANT):

{
  "kind": "file",
  "file": {
    "kind": "uri",
    "name": "document.pdf",
    "mimeType": "application/pdf",
    "uri": "https://example.com/document.pdf",
    "metadata": {}
  }
}

Field Name Violations Summary

SDK Field Name SDK Location Specification Field Name Compliance Status
file.bytes FileWithBytes.Bytes file.fileWithBytes ❌ Wrong name
file.uri (in FileWithBytes) FileWithBytes.Uri Should not exist ❌ Extra field
file.uri (in FileWithUri) FileWithUri.Uri file.fileWithUri ❌ Wrong name
file.mimeType FileWithBytes/FileWithUri.MimeType file.mediaType ❌ Wrong name
file.name FileWithBytes/FileWithUri.Name file.name ✅ Correct

Impact

🔴 Interoperability Broken

  • Spec-compliant agents expecting fileWithBytes will not recognize bytes
  • Spec-compliant agents expecting fileWithUri will not recognize uri
  • Spec-compliant agents expecting mediaType will not recognize mimeType
  • Messages with file attachments will fail to deserialize on receiving end

🔴 Mutual Exclusivity Violation

  • Both FileWithBytes and FileWithUri classes have both Bytes and Uri properties
  • Specification requires: "A FilePart MUST contain exactly one"
  • SDK violates this by having both fields (set to null when unused)

🔴 Protocol Version Compliance

  • A2A Protocol v1.0 (DRAFT) specifies these field names in Section 4.1.7
  • SDK claims to implement A2A protocol but deviates from specification
  • Creates fragmentation in A2A ecosystem

Reproduction / Test Evidence

Created integration tests that verify the JSON output from the SDK:

Test Code:

[Fact]
public void CreateUserMessage_WithFileUpload_ProducesCorrectJsonStructure()
{
    var filePart = new FilePart
    {
        File = new FileWithBytes
        {
            Bytes = "SGVsbG8=",
            MimeType = "text/plain"
        }
    };

    var json = JsonSerializer.Serialize(filePart, JsonOptions);
    var jsonDoc = JsonDocument.Parse(json);
    var fileObj = jsonDoc.RootElement.GetProperty("file");

    var hasFileWithBytes = fileObj.TryGetProperty("fileWithBytes", out _);
    var hasBytes = fileObj.TryGetProperty("bytes", out _);

    Assert.True(hasFileWithBytes,
        "Field should be 'fileWithBytes' per A2A spec Section 4.1.7");
}

Test Results:

❌ FAILED: CreateUserMessage_WithFileUpload_ProducesCorrectJsonStructure
   Expected field: "fileWithBytes"
   Actual field: "bytes"

   COMPLIANCE FAILURE: Field should be 'fileWithBytes' per A2A v2 spec
   (Section 4.1.7), but field not found. The A2A SDK may be using
   non-compliant field names.

❌ FAILED: CreateUserMessage_WithFileUrl_ProducesCorrectJsonStructure
   Expected field: "fileWithUri"
   Actual field: "uri"

   COMPLIANCE FAILURE: Field should be 'fileWithUri' per A2A v2 spec
   (Section 4.1.7), but field not found.

Suggested Fix

Option 1: Update JsonPropertyName Attributes ⭐ (Recommended)

FileWithBytes.cs:

public sealed class FileWithBytes : FileContent
{
    [JsonPropertyName("name")]
    public string? Name { get; set; }

    [JsonPropertyName("mediaType")]     // ✅ Fixed
    public string? MediaType { get; set; }

    [JsonPropertyName("fileWithBytes")] // ✅ Fixed
    [JsonRequired]
    public string FileWithBytes { get; set; } = string.Empty;

    // Remove Uri property entirely - ✅ Fixed
}

FileWithUri.cs:

public sealed class FileWithUri : FileContent
{
    [JsonPropertyName("name")]
    public string? Name { get; set; }

    [JsonPropertyName("mediaType")]     // ✅ Fixed
    public string? MediaType { get; set; }

    [JsonPropertyName("fileWithUri")]   // ✅ Fixed
    [JsonRequired]
    public string FileWithUri { get; set; } = string.Empty;

    // Remove Bytes property entirely - ✅ Fixed
}

Option 2: Custom JsonConverter (Non-Breaking)

Create JsonConverter<FileContent> that maps SDK properties to spec field names during serialization.

Option 3: New Major Version

Release v1.0.0 with breaking changes to align with specification.


Environment

  • Package: A2A v0.1.0-preview.2 (NuGet)
  • Target Framework: .NET 9.0
  • Serializer: System.Text.Json
  • OS: Windows 11

Related Issues


Additional Context

This issue was discovered while implementing file attachment support in a Blazor WebAssembly A2A client application. The SDK successfully creates FilePart objects, but integration tests revealed the JSON output does not match the specification.

The field name mismatches prevent interoperability with:

  • ✗ Spec-compliant A2A agents written in other languages (Python, Java, JS)
  • ✗ Tools that validate A2A protocol compliance
  • ✗ Future versions of the A2A ecosystem

Request: Please prioritize fixing this to ensure the .NET SDK produces specification-compliant output and maintains interoperability within the A2A ecosystem.


Specification References

  1. A2A Protocol Specification v1.0 (DRAFT)

  2. GitHub Specification

  3. Other Official SDKs for Reference

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions