[Feat]: Add Resource Access Manifest (RAM) to AgentCard
- Dominant language
- Shell
- Stars
- 25.7k
- Forks
- 2.6k
- Avg merge
- 3d 6h
- Merged PRs (30d)
- 16
Description
### Is your feature request related to a problem? Please describe.
Currently, the A2A `AgentCard` provides metadata about an agent's capabilities, but it lacks a standardized way to declare the external resources an agent might access. This includes both user-owned (2P) resource accesses requiring user authorization and third party (3P) resource accesses requiring user acknowledgment. A resource could be a traditional REST resource, MCP Tool or A2A Agent.
This absence makes it difficult for consumers and orchestrators to:
1. Accurately assess the potential risk and "blast radius" of an agent.
2. Define fine-grained access control policies.
3. Dynamically select agents based on the principle of least privilege.
4. Clearly delineate responsibility for authorization failures.
### Describe the solution you'd like
We propose the introduction of a **Resource Access Manifest (RAM)** as a new standard field within the A2A `AgentCard`. The RAM formalizes an AI Agent's external footprint by cataloging 2P resource accesses requiring user authorization and 3P dependencies requiring user acknowledgment.
The RAM would:
* List external APIs, MCP Tools, or other A2A Agents the agent interacts with.
* Specify the operations performed on these resources.
* Detail the justification and necessity for each access.
* Indicate the identity used (End User or Agent).
* Flag if user confirmation (HITL) is required before execution.
Analogous to an Android app manifest, the RAM declares which external resources an Agent utilizes and why—though it catalogs the resource operations themselves and not the specific permissions associated with them (the permission sets are expected to be derived from the RAM via offline tooling).
**Detailed Proposal:**
The proposed structure for the `ResourceAccessManifest` is listed below. It will be added as a top level field to the `AgentCard` proto.
```protobuf
message AgentCard {
// Existing fields
...
// List of user-owned (2P) and third party (3P) resource that the
// Agent accesses for which it needs permissions and acknowledgement,
// respectively.
ResourceAccessManifest resource_access_manifest = 123; // proposed field addition
}
```
**Proto Definition:**
```protobuf
syntax = "proto3";
package a2a.v1;
// Represents the Agent's external resource footprint.
//
// IMPORTANT: This manifest catalogs resources that fall OUTSIDE the Agent
// developer's governance boundary. This includes:
// 1. Consumer-Owned (2P): Resources where the consumer must grant permission.
// 2. Third-Party (3P): External services where the consumer acknowledges data egress.
//
// This manifest acts as the source of truth for all downstream governance audits.
message ResourceAccessManifest {
// A registry of external entities (APIs, agents, tools) the Agent might access.
repeated Resource resources = 1;
// A registry of specific functional actions the Agent can perform on the
// resources above.
repeated Operation operations = 2;
// The binding layer that defines the specific context, justification, and
// necessity for each operational call.
repeated ResourceAccess resource_accesses = 3;
}
// Defines an external entity (Resource) that sits outside the Agent's governance boundary.
message Resource {
// Unique internal handle for referencing this resource within the RAM.
// Recommended Pattern: --.
// 2P API Example: "google-calendar-events-v3"
// 3P API Example: "openholidaysapi-publicholidays-v1"
// 2P MCP Example: "google-maps-lookup-weather" (MCP standard does not define versioning)
string id = 1;
// The technical protocol/interface used for the interaction.
InteractionProtocol interaction_protocol = 2;
// Specifies if the resource is consumer-owned (2P) or external (3P).
ResourceOwner owner = 3;
// User-facing display name for permission prompts and UIs.
// 2P API Example: "Google Calendar Events"
// 3P API Example: "OpenHolidaysAPI's PublicHolidays"
// 2P MCP Example: "Google Maps lookup_weather MCP Tool"
string display_name = 4;
// A static description of the entity itself, independent of the Agent's use.
// 2P API Example: "A calendar service managing user events and availability."
// 3P API Example: "An OSS project that collects public holiday and school holiday data
// and makes it available via an open REST API interface."
// 2P MCP Example: "Fetches weather data in a given location"
string description = 5;
// Link to the provider's human-readable documentation.
// 2P API Example: "https://developers.google.com/workspace/calendar/api/v3/reference/events"
// 3P API Example: "https://www.openholidaysapi.org/en/#tryit"
// 2P MCP Example: "https://developers.google.com/maps/ai/grounding-lite/reference/mcp/lookup_weather"
string developer_documentation_url = 6;
// Technical pointers for programmatic schema discovery.
ResourceSpec spec = 7;
}
// Specifies the technical communication standard for interacting with the resource.
enum InteractionProtocol {
INTERACTION_PROTOCOL_UNSPECIFIED = 0;
REST = 1; // Standard HTTP-based Web APIs
A2A = 2; // Agent-to-Agent protocol for Agents
MCP = 3; // Model Context Protocol for Tools
}
// Defines the ownership domain for GRC risk assessment.
enum ResourceOwner {
RESOURCE_OWNER_UNSPECIFIED = 0;
CONSUMER = 1; // 2P: User-owned. Requires permission grants.
THIRD_PARTY = 2; // 3P: External provider. Requires acknowledgment.
}
// Specifies metadata needed to programmatically fetch, parse and extract
// the schema of the resource.
message ResourceSpec {
// The URL to the machine-readable contract (OpenAPI JSON/YAML or Discovery Doc or MCP Server).
// 2P API Example: "https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"
// 3P API Example: "https://openholidaysapi.org/swagger/v1/swagger.json"
// 2P MCP Example: "https://mapstools.googleapis.com/mcp" (JSON-RPC call to 'tools/list' provides
// the schema information for each Tool hosted by the server).
string spec_url = 1;
// Path template within the spec for uniquely identifying the resource.
// 2P API Example: "/calendar/v3/calendars/{calendarId}/events"
// 3P API Example: "/PublicHolidays"
// 2P MCP Example: "lookup_weather" (the exact Tool name)
string resource_path = 2;
}
// Defines a specific action taken on a Resource.
message Operation {
// Unique internal handle for referencing this operation within the RAM.
// Recommended Pattern: -. For MCP Tools, operation is always 'call'.
// 2P API Example: "google-calendar-events-v3-insert"
// 3P API Example: "openholidaysapi-publicholidays-v1-get"
// 2P MCP Example: "google-maps-lookup-weather-call"
string id = 1;
// The id of a 'Resource' message defined in this RAM, to which this operation
// belongs to.
// 2P API Example: "google-calendar-events-v3"
// 3P API Example: "openholidaysapi-publicholidays-v1"
// 2P MCP Example: "google-maps-lookup-weather"
string resource = 2;
// A static description of the operation itself, independent of the Agent's use.
// 2P API Example: "Creates a new event on a calendar."
// 3P API Example: "Fetches public holidays of a country."
// 2P MCP Example: "Fetches weather in a particular location."
string description = 3;
// Link to the provider's human-readable documentation, including required permissions,
// OAuth scopes, etc.
// 2P API Example: "https://developers.google.com/workspace/calendar/api/v3/reference/events/insert"
// 3P API Example: "https://www.openholidaysapi.org/en/#tryit"
// 2P MCP Example: "https://developers.google.com/maps/ai/grounding-lite/reference/mcp/lookup_weather"
repeated string developer_documentation_url = 4;
// Technical pointers for programmatic schema and security requirements discovery.
// Not required for MCP Tools as the MCP standard uses the fixed "tools/call" method.
// Not required for A2A Agents as the interaction with A2A could be stateful and cannot
// be simplified to a single operation.
ApiOperationSpec api_operation_spec = 5;
}
// Specifies metadata needed to programmatically fetch, parse and extract
// the schema and security requirements of an API operation.
// This is only applicable for API Operations and not MCP/A2A calls.
message ApiOperationSpec {
// The URL to the specific spec containing this operation (if different from parent ResourceSpec).
// If not specified, the parent ResourceSpec.spec_url is used.
string spec_url = 1;
// Unique ID (e.g., OpenAPI operationId) for identifying the operation in the spec.
// If not specified, falls back to http_method.
// 2P API Example: "calendar.events.insert"
// 3P API Example: None (OpenHolidays API's spec doesn't use operation ids).
string operation_id = 2;
// The HTTP verb for the operation.
// Precedence: If operation_id is provided and found in the spec, it is used.
// Fallback: If operation_id is missing or unresolved, the operation is uniquely
// identified by resource_spec.resource_path plus this http_method.
// NOTE: operation_id is optional in OpenAPI spec but http_method is required.
// 2P API Example: "POST"
// 3P API Example: "GET"
string http_method = 3;
}
// Describes a specific context in which an operation is invoked by the Agent.
// Note: One Operation may have multiple ResourceAccess entries for different use cases, such
// separately writing an event to the user's personal calendar and corporate calendar.
message ResourceAccess {
// Unique internal handle for referencing this operation within the RAM.
// Recommended to include context for the access in the id value.
// 2P API Example (a): "create-personal-calendar-event-for-flight-reservation"
// 2P API Example (b): "create-corporate-calendar-event-for-flight-reservation"
// 3P API Example: "fetch-holidays-for-destination-country"
// 2P MCP Example: "lookup-weather-for-destination-country"
string id = 1;
// The 'id' of the Operation being invoked.
// 2P API Example:"google-calendar-events-v3-insert"
// 3P API Example:"openholidaysapi-publicholidays-v1-get"
// 2P MCP Example: "google-maps-lookup-weather-call"
string operation = 2;
// The principal identity under which the operation is executed.
IdentityType identity_used = 3;
// If true, the system must obtain explicit user confirmation (Human-in-the-Loop or HITL)
// before execution.
bool confirmation_required = 4;
// The business/functional reason for this access (the "Why").
// 2P API Example (a): "To create flight travel event on user's personal calendar."
// 2P API Example (b): "To create flight travel event on user's corporate calendar."
// 3P API Example: "To warn users of holiday closures in the destination country."
// 2P MCP Example: "To warn users of inclement weather in the destination country"
string access_justification = 5;
// The operational criticality of this access to the Agent's core mission.
AccessNecessity necessity = 6;
}
// Authentication/authorization context.
enum IdentityType {
IDENTITY_TYPE_UNSPECIFIED = 0;
END_USER = 1; // Acts as the user via delegated credentials.
AGENT = 2; // Acts as the agent's own service identity.
}
// Classifies the impact if this access is denied by the consumer.
enum AccessNecessity {
ACCESS_NECESSITY_UNSPECIFIED = 0;
// The Agent cannot fulfill its primary mission without this access. Most requests
// will fail without this access.
REQUIRED = 1;
// Significant feature degradation if denied, but core logic remains functional.
RECOMMENDED = 2;
// Enables auxiliary or "bonus" features only.
OPTIONAL = 3;
}
```
**JSON Representative Example:**
This example illustrates a Travel Reservation Agent's RAM, highlighting its integration with both 2P and 3P resources:
* **OpenHolidaysAPI (3P API):** Used to identify public holidays at the destination.
* **Google Calendar (2P API): **Utilized for automatically scheduling flight events, on both the personal and corporate calendars of the user.
* **Google Maps MCP Tool (2P Tool):** Accessed to provide destination weather forecasts and safety warnings.
```JSON
{
"resources": [
{
"id": "google-calendar-events-v3",
"interaction_protocol": "REST",
"owner": "CONSUMER",
"display_name": "Google Calendar Events",
"description": "A scheduling service managing user events and availability.",
"developer_documentation_url": "https://developers.google.com/workspace/calendar/api/v3/reference/events",
"spec": {
"spec_url": "https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest",
"resource_path": "/calendar/v3/calendars/{calendarId}/events"
}
},
{
"id": "openholidaysapi-publicholidays-v1",
"interaction_protocol": "REST",
"owner": "THIRD_PARTY",
"display_name": "OpenHolidaysAPI's PublicHolidays",
"description": "An OSS project that collects public holiday and school holiday data and makes it available via an open REST API interface.",
"developer_documentation_url": "https://www.openholidaysapi.org/en/#tryit",
"spec": {
"spec_url": "https://openholidaysapi.org/swagger/v1/swagger.json",
"resource_path": "/PublicHolidays"
}
},
{
"id": "google-maps-lookup-weather",
"interaction_protocol": "MCP",
"owner": "CONSUMER",
"display_name": "Google Maps lookup_weather MCP Tool",
"description": "Fetches weather data in a given location.",
"developer_documentation_url": "https://developers.google.com/maps/ai/grounding-lite/reference/mcp/lookup_weather",
"spec": {
"spec_url": "https://mapstools.googleapis.com/mcp",
"resource_path": "lookup_weather"
}
}
],
"operations": [
{
"id": "google-calendar-events-v3-insert",
"resource": "google-calendar-events-v3",
"description": "Creates a new event on a calendar.",
"developer_documentation_url": [
"https://developers.google.com/workspace/calendar/api/v3/reference/events/insert"
],
"api_operation_spec": {
"operation_id": "calendar.events.insert",
"http_method": "POST"
}
},
{
"id": "openholidaysapi-publicholidays-v1-get",
"resource": "openholidaysapi-publicholidays-v1",
"description": "Fetches public holidays of a country.",
"developer_documentation_url": [
"https://www.openholidaysapi.org/en/#tryit"
],
"api_operation_spec": {
"http_method": "GET"
}
},
{
"id": "google-maps-lookup-weather-call",
"resource": "google-maps-lookup-weather",
"description": "Fetches weather in a particular location.",
"developer_documentation_url": [
"https://developers.google.com/maps/ai/grounding-lite/reference/mcp/lookup_weather"
]
}
],
"resource_accesses": [
{
"id": "create-personal-calendar-event-for-flight-reservation",
"operation": "google-calendar-events-v3-insert",
"identity_used": "END_USER",
"confirmation_required": true,
"access_justification": "To create flight travel event on user's personal calendar.",
"necessity": "OPTIONAL"
},
{
"id": "create-corporate-calendar-event-for-flight-reservation",
"operation": "google-calendar-events-v3-insert",
"identity_used": "END_USER",
"confirmation_required": true,
"access_justification": "To create flight travel event on user's corporate calendar.",
"necessity": "OPTIONAL"
},
{
"id": "fetch-holidays-for-destination-country",
"operation": "openholidaysapi-publicholidays-v1-get",
"identity_used": "AGENT",
"confirmation_required": false,
"access_justification": "To warn users of holiday closures in the destination country.",
"necessity": "RECOMMENDED"
},
{
"id": "lookup-weather-for-destination-country",
"operation": "google-maps-lookup-weather-call",
"identity_used": "AGENT",
"confirmation_required": false,
"access_justification": "To warn users of inclement weather in the destination country.",
"necessity": "RECOMMENDED"
}
]
}
```
### Describe alternatives you've considered
The primary alternative is to rely on human-readable documentation to describe the 2P and 3P resources an Agent accesses. However, without a programmable manifest like the RAM, it's impossible to build deterministic schemes to programmatically analyze, inform, constrain, and audit the Agent's resource access, which directly impacts user data and systems.
Another possibility is attempting to extract the RAM from the Agent's implementation details. This is often not feasible, as Agents can be built using diverse frameworks, languages, and configurations, and their source code or internal structure may not be accessible.
Given that the A2A protocol treats Agents as opaque, black-box entities, the AgentCard is the only standardized and programmable mechanism to declare these crucial external dependencies and access requirements.
### Additional context
A key challenge with the current A2A specification is the unified `sendMessage()` API. While flexible, it aggregates the potential resource requirements for *all* of the agent's skills. This makes it difficult for consumers to discern the specific resources needed for a particular operation or skill they intend to use. Consequently, consumers or orchestrators cannot easily apply the principle of least privilege or compare agents based on their resource footprint for a given function.
To further enhance consumer-side governance and enable more precise permissioning, the RAM could be partitioned by skill or operation. This would allow a consumer to understand and authorize resource access based on the specific skills they intend to invoke via `sendMessage()`. The mechanics of partitioning the RAM may be taken up in a separate, future proposal.
### Code of Conduct
- [x] I agree to follow this project's Code of Conduct
Contributor guide
Assessment
This issue has not been assessed yet.